forked from gxwebsoft/mp-10550
feat(dealer): 添加配送员解冻资金功能
- 在dealer页面添加配送员权限判断和解冻资金功能 - 导入useUser hook和updateShopDealerUser API - 仅配送员角色可操作冻结金额转入可提现 - 点击待使用金额弹出确认框进行资金转移 - 统一rider和dealer页面的解冻资金逻辑实现 - 修改环境配置支持SERVER_API_URL变量导出 - 更新版权信息配置结构优化代码注释 - 优化待使用金额卡片点击交互体验
This commit is contained in:
29
.workbuddy/memory/2026-03-31.md
Normal file
29
.workbuddy/memory/2026-03-31.md
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# 2026-03-31 工作日志
|
||||||
|
|
||||||
|
## 新增 dealer/index.tsx 配送员解冻资金功能
|
||||||
|
|
||||||
|
将 `/rider/index.tsx` 的 `handleFreezeMoneyClick` 功能复制到 `/dealer/index.tsx`:
|
||||||
|
- 导入 `useUser` hook 和 `updateShopDealerUser` API
|
||||||
|
- 添加 `isRider` 判断(只有 `hasRole('rider')` 才可操作)
|
||||||
|
- "待使用"卡片点击事件(仅配送员+有冻结金额时可用)
|
||||||
|
- 确认后冻结金额转入可提现
|
||||||
|
|
||||||
|
## 修改 rider/index.tsx (React Taro 项目)
|
||||||
|
|
||||||
|
修改了 `/Users/gxwebsoft/VUE/template-10584/src/rider/index.tsx`:
|
||||||
|
|
||||||
|
### 修改内容:
|
||||||
|
1. **统一显示格式** - 把"桶数"改成"待使用"
|
||||||
|
2. **添加配送员权限控制** - 只有 `hasRole('rider')` 的用户才能点击操作
|
||||||
|
3. **点击解冻功能**:
|
||||||
|
- 配送员点击"待使用"金额时显示蓝色高亮提示"(点击转入)"
|
||||||
|
- 弹出确认框:`确定要将 ¥xx.xx 待使用金额转入可提现吗?`
|
||||||
|
- 确认后调用 `updateShopDealerUser` API
|
||||||
|
- 将 `freezeMoney` 清零,加到 `money`
|
||||||
|
- 成功后提示"更新成功"并刷新数据
|
||||||
|
|
||||||
|
### 关键代码:
|
||||||
|
- 使用 `useUser` hook 获取 `hasRole` 函数
|
||||||
|
- `isRider` 判断是否为配送员
|
||||||
|
- `handleFreezeMoneyClick` 处理点击解冻逻辑
|
||||||
|
- 使用 `Taro.showModal` / `Taro.showToast` 提示用户
|
||||||
0
.workbuddy/memory/MEMORY.md
Normal file
0
.workbuddy/memory/MEMORY.md
Normal file
@@ -10,5 +10,6 @@ export const BaseUrl = API_BASE_URL;
|
|||||||
export const Version = 'v3.0.8';
|
export const Version = 'v3.0.8';
|
||||||
// 版权信息
|
// 版权信息
|
||||||
export const Copyright = '桂乐淘·购享无界 乐惠万家';
|
export const Copyright = '桂乐淘·购享无界 乐惠万家';
|
||||||
|
// export const Copyright = '测试环境 v3.2.6';
|
||||||
|
|
||||||
// java -jar CertificateDownloader.jar -k 0kF5OlPr482EZwtn9zGufUcqa7ovgxRL -m 1723321338 -f ./apiclient_key.pem -s 2B933F7C35014A1C363642623E4A62364B34C4EB -o ./
|
// java -jar CertificateDownloader.jar -k 0kF5OlPr482EZwtn9zGufUcqa7ovgxRL -m 1723321338 -f ./apiclient_key.pem -s 2B933F7C35014A1C363642623E4A62364B34C4EB -o ./
|
||||||
|
|||||||
@@ -1,44 +1,43 @@
|
|||||||
// 环境变量配置
|
// 环境变量配置
|
||||||
|
|
||||||
|
// ============ 环境切换开关(修改这里即可切换环境)============
|
||||||
|
// 可选值: 'development' | 'test' | 'production'
|
||||||
|
const CURRENT_ENV = 'production' as const
|
||||||
|
// ===========================================================
|
||||||
|
|
||||||
export const ENV_CONFIG = {
|
export const ENV_CONFIG = {
|
||||||
// 开发环境
|
// 开发环境
|
||||||
development: {
|
development: {
|
||||||
API_BASE_URL: 'http://127.0.0.1:9200/api',
|
API_BASE_URL: 'https://glt-dev-api.websoft.top/api',
|
||||||
// API_BASE_URL: 'https://glt-api2.websoft.top/api',
|
SERVER_API_URL: 'https://glt-dev-server.websoft.top/api',
|
||||||
APP_NAME: '开发环境',
|
APP_NAME: '开发环境',
|
||||||
DEBUG: 'true',
|
DEBUG: 'true',
|
||||||
},
|
},
|
||||||
|
// 测试环境
|
||||||
|
test: {
|
||||||
|
API_BASE_URL: 'https://glt-dev-api.websoft.top/api',
|
||||||
|
SERVER_API_URL: 'https://glt-dev-server.websoft.top/api',
|
||||||
|
APP_NAME: '测试环境',
|
||||||
|
DEBUG: 'true',
|
||||||
|
},
|
||||||
// 生产环境
|
// 生产环境
|
||||||
production: {
|
production: {
|
||||||
API_BASE_URL: 'https://glt-api2.websoft.top/api',
|
API_BASE_URL: 'https://glt-api.websoft.top/api',
|
||||||
|
SERVER_API_URL: 'https://glt-server.websoft.top/api',
|
||||||
APP_NAME: '桂乐淘',
|
APP_NAME: '桂乐淘',
|
||||||
DEBUG: 'false',
|
DEBUG: 'false',
|
||||||
},
|
},
|
||||||
// 测试环境
|
|
||||||
test: {
|
|
||||||
// API_BASE_URL: 'http://127.0.0.1:9200/api',
|
|
||||||
API_BASE_URL: 'https://glt-api2.websoft.top/api',
|
|
||||||
APP_NAME: '测试环境',
|
|
||||||
DEBUG: 'true',
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取当前环境配置
|
// 获取当前环境配置
|
||||||
export function getEnvConfig() {
|
export function getEnvConfig() {
|
||||||
const env = process.env.NODE_ENV || 'development'
|
return ENV_CONFIG[CURRENT_ENV]
|
||||||
if (env === 'production') {
|
|
||||||
return ENV_CONFIG.production
|
|
||||||
} else { // @ts-ignore
|
|
||||||
if (env === 'test') {
|
|
||||||
return ENV_CONFIG.test
|
|
||||||
} else {
|
|
||||||
return ENV_CONFIG.development
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 导出环境变量
|
// 导出环境变量
|
||||||
export const {
|
export const {
|
||||||
API_BASE_URL,
|
API_BASE_URL,
|
||||||
|
SERVER_API_URL,
|
||||||
APP_NAME,
|
APP_NAME,
|
||||||
DEBUG
|
DEBUG
|
||||||
} = getEnvConfig()
|
} = getEnvConfig()
|
||||||
|
|||||||
@@ -10,8 +10,10 @@ import {
|
|||||||
People
|
People
|
||||||
} from '@nutui/icons-react-taro'
|
} from '@nutui/icons-react-taro'
|
||||||
import {useDealerUser} from '@/hooks/useDealerUser'
|
import {useDealerUser} from '@/hooks/useDealerUser'
|
||||||
|
import {useUser} from '@/hooks/useUser'
|
||||||
import { useThemeStyles } from '@/hooks/useTheme'
|
import { useThemeStyles } from '@/hooks/useTheme'
|
||||||
import {businessGradients, cardGradients, gradientUtils} from '@/styles/gradients'
|
import {businessGradients, cardGradients, gradientUtils} from '@/styles/gradients'
|
||||||
|
import {updateShopDealerUser} from '@/api/shop/shopDealerUser'
|
||||||
import Taro from '@tarojs/taro'
|
import Taro from '@tarojs/taro'
|
||||||
|
|
||||||
const DealerIndex: React.FC = () => {
|
const DealerIndex: React.FC = () => {
|
||||||
@@ -21,6 +23,9 @@ const DealerIndex: React.FC = () => {
|
|||||||
refresh,
|
refresh,
|
||||||
} = useDealerUser()
|
} = useDealerUser()
|
||||||
|
|
||||||
|
// 获取用户角色信息
|
||||||
|
const { hasRole } = useUser()
|
||||||
|
|
||||||
// 使用主题样式
|
// 使用主题样式
|
||||||
const themeStyles = useThemeStyles()
|
const themeStyles = useThemeStyles()
|
||||||
|
|
||||||
@@ -55,6 +60,59 @@ const DealerIndex: React.FC = () => {
|
|||||||
|
|
||||||
console.log(getGradientBackground(),'getGradientBackground()')
|
console.log(getGradientBackground(),'getGradientBackground()')
|
||||||
|
|
||||||
|
// 判断是否是配送员
|
||||||
|
const isRider = hasRole('rider')
|
||||||
|
|
||||||
|
// 点击待使用金额 - 配送员专用:将冻结金额转入可提现
|
||||||
|
const handleFreezeMoneyClick = async () => {
|
||||||
|
// 检查是否是配送员
|
||||||
|
if (!isRider) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查冻结金额是否为 0
|
||||||
|
const freezeMoney = Number(dealerUser?.freezeMoney ?? 0)
|
||||||
|
if (freezeMoney <= 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 弹出确认框
|
||||||
|
Taro.showModal({
|
||||||
|
title: '确认操作',
|
||||||
|
content: `确定要将 ¥${freezeMoney.toFixed(2)} 转入钱包吗?`,
|
||||||
|
confirmText: '确定',
|
||||||
|
cancelText: '取消',
|
||||||
|
success: async (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
try {
|
||||||
|
Taro.showLoading({ title: '处理中...' })
|
||||||
|
const currentMoney = Number(dealerUser?.money ?? 0)
|
||||||
|
await updateShopDealerUser({
|
||||||
|
id: dealerUser?.id,
|
||||||
|
money: (currentMoney + freezeMoney).toFixed(2),
|
||||||
|
freezeMoney: '0.00'
|
||||||
|
})
|
||||||
|
Taro.hideLoading()
|
||||||
|
Taro.showToast({
|
||||||
|
title: '更新成功',
|
||||||
|
icon: 'success',
|
||||||
|
duration: 1500
|
||||||
|
})
|
||||||
|
// 刷新数据
|
||||||
|
refresh()
|
||||||
|
} catch (error) {
|
||||||
|
Taro.hideLoading()
|
||||||
|
Taro.showToast({
|
||||||
|
title: '更新失败',
|
||||||
|
icon: 'none',
|
||||||
|
duration: 1500
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
return (
|
return (
|
||||||
<View className="p-4">
|
<View className="p-4">
|
||||||
@@ -140,13 +198,20 @@ const DealerIndex: React.FC = () => {
|
|||||||
</Text>
|
</Text>
|
||||||
<Text className="text-xs" style={{ color: 'rgba(255, 255, 255, 0.9)' }}>可提现</Text>
|
<Text className="text-xs" style={{ color: 'rgba(255, 255, 255, 0.9)' }}>可提现</Text>
|
||||||
</View>
|
</View>
|
||||||
<View className="text-center p-3 rounded-lg flex flex-col" style={{
|
<View
|
||||||
background: businessGradients.money.frozen
|
className="text-center p-3 rounded-lg flex flex-col"
|
||||||
}}>
|
style={{
|
||||||
|
background: businessGradients.money.frozen,
|
||||||
|
opacity: isRider && Number(dealerUser.freezeMoney ?? 0) > 0 ? 1 : 0.8
|
||||||
|
}}
|
||||||
|
onClick={isRider && Number(dealerUser.freezeMoney ?? 0) > 0 ? handleFreezeMoneyClick : undefined}
|
||||||
|
>
|
||||||
<Text className="text-lg font-bold mb-1 text-white">
|
<Text className="text-lg font-bold mb-1 text-white">
|
||||||
{formatMoney(dealerUser.freezeMoney)}
|
{formatMoney(dealerUser.freezeMoney)}
|
||||||
</Text>
|
</Text>
|
||||||
<Text className="text-xs" style={{ color: 'rgba(255, 255, 255, 0.9)' }}>待使用</Text>
|
<Text className="text-xs" style={{ color: 'rgba(255, 255, 255, 0.9)' }}>
|
||||||
|
{isRider && Number(dealerUser.freezeMoney ?? 0) > 0 ? '待使用' : '待使用'}
|
||||||
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View className="text-center p-3 rounded-lg flex flex-col" style={{
|
<View className="text-center p-3 rounded-lg flex flex-col" style={{
|
||||||
background: businessGradients.money.total
|
background: businessGradients.money.total
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {Popup} from '@nutui/nutui-react-taro'
|
|||||||
import {UserParam} from "@/api/system/user/model";
|
import {UserParam} from "@/api/system/user/model";
|
||||||
import {Button} from '@nutui/nutui-react-taro'
|
import {Button} from '@nutui/nutui-react-taro'
|
||||||
import {Form, Input} from '@nutui/nutui-react-taro'
|
import {Form, Input} from '@nutui/nutui-react-taro'
|
||||||
import {Copyright, Version} from "@/config/app";
|
import {Copyright} from "@/config/app";
|
||||||
const UserFooter = () => {
|
const UserFooter = () => {
|
||||||
const [openLoginByPhone, setOpenLoginByPhone] = useState(false)
|
const [openLoginByPhone, setOpenLoginByPhone] = useState(false)
|
||||||
const [clickNum, setClickNum] = useState<number>(0)
|
const [clickNum, setClickNum] = useState<number>(0)
|
||||||
|
|||||||
@@ -11,8 +11,10 @@ import {
|
|||||||
Scan
|
Scan
|
||||||
} from '@nutui/icons-react-taro'
|
} from '@nutui/icons-react-taro'
|
||||||
import {useDealerUser} from '@/hooks/useDealerUser'
|
import {useDealerUser} from '@/hooks/useDealerUser'
|
||||||
|
import {useUser} from '@/hooks/useUser'
|
||||||
import { useThemeStyles } from '@/hooks/useTheme'
|
import { useThemeStyles } from '@/hooks/useTheme'
|
||||||
import {businessGradients, cardGradients, gradientUtils} from '@/styles/gradients'
|
import {businessGradients, cardGradients, gradientUtils} from '@/styles/gradients'
|
||||||
|
import {updateShopDealerUser} from '@/api/shop/shopDealerUser'
|
||||||
import Taro from '@tarojs/taro'
|
import Taro from '@tarojs/taro'
|
||||||
|
|
||||||
const DealerIndex: React.FC = () => {
|
const DealerIndex: React.FC = () => {
|
||||||
@@ -22,6 +24,9 @@ const DealerIndex: React.FC = () => {
|
|||||||
refresh,
|
refresh,
|
||||||
} = useDealerUser()
|
} = useDealerUser()
|
||||||
|
|
||||||
|
// 获取用户角色信息
|
||||||
|
const { hasRole } = useUser()
|
||||||
|
|
||||||
// 使用主题样式
|
// 使用主题样式
|
||||||
const themeStyles = useThemeStyles()
|
const themeStyles = useThemeStyles()
|
||||||
|
|
||||||
@@ -56,6 +61,59 @@ const DealerIndex: React.FC = () => {
|
|||||||
|
|
||||||
console.log(getGradientBackground(),'getGradientBackground()')
|
console.log(getGradientBackground(),'getGradientBackground()')
|
||||||
|
|
||||||
|
// 判断是否是配送员
|
||||||
|
const isRider = hasRole('rider')
|
||||||
|
|
||||||
|
// 点击待使用金额 - 配送员专用:将冻结金额转入可提现
|
||||||
|
const handleFreezeMoneyClick = async () => {
|
||||||
|
// 检查是否是配送员
|
||||||
|
if (!isRider) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查冻结金额是否为 0
|
||||||
|
const freezeMoney = Number(dealerUser?.freezeMoney ?? 0)
|
||||||
|
if (freezeMoney <= 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 弹出确认框
|
||||||
|
Taro.showModal({
|
||||||
|
title: '确认操作',
|
||||||
|
content: `确定要将 ¥${freezeMoney.toFixed(2)} 转入钱包吗?`,
|
||||||
|
confirmText: '确定',
|
||||||
|
cancelText: '取消',
|
||||||
|
success: async (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
try {
|
||||||
|
Taro.showLoading({ title: '处理中...' })
|
||||||
|
const currentMoney = Number(dealerUser?.money ?? 0)
|
||||||
|
await updateShopDealerUser({
|
||||||
|
id: dealerUser?.id,
|
||||||
|
money: (currentMoney + freezeMoney).toFixed(2),
|
||||||
|
freezeMoney: '0.00'
|
||||||
|
})
|
||||||
|
Taro.hideLoading()
|
||||||
|
Taro.showToast({
|
||||||
|
title: '更新成功',
|
||||||
|
icon: 'success',
|
||||||
|
duration: 1500
|
||||||
|
})
|
||||||
|
// 刷新数据
|
||||||
|
refresh()
|
||||||
|
} catch (error) {
|
||||||
|
Taro.hideLoading()
|
||||||
|
Taro.showToast({
|
||||||
|
title: '更新失败',
|
||||||
|
icon: 'none',
|
||||||
|
duration: 1500
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
return (
|
return (
|
||||||
<View className="p-4">
|
<View className="p-4">
|
||||||
@@ -148,13 +206,20 @@ const DealerIndex: React.FC = () => {
|
|||||||
</Text>
|
</Text>
|
||||||
<Text className="text-xs" style={{ color: 'rgba(255, 255, 255, 0.9)' }}>本月配送佣金</Text>
|
<Text className="text-xs" style={{ color: 'rgba(255, 255, 255, 0.9)' }}>本月配送佣金</Text>
|
||||||
</View>
|
</View>
|
||||||
<View className="text-center p-3 rounded-lg flex flex-col" style={{
|
<View
|
||||||
background: businessGradients.money.frozen
|
className="text-center p-3 rounded-lg flex flex-col"
|
||||||
}}>
|
style={{
|
||||||
|
background: businessGradients.money.frozen,
|
||||||
|
opacity: isRider && Number(dealerUser.freezeMoney ?? 0) > 0 ? 1 : 0.8
|
||||||
|
}}
|
||||||
|
onClick={isRider && Number(dealerUser.freezeMoney ?? 0) > 0 ? handleFreezeMoneyClick : undefined}
|
||||||
|
>
|
||||||
<Text className="text-lg font-bold mb-1 text-white">
|
<Text className="text-lg font-bold mb-1 text-white">
|
||||||
{formatMoney(dealerUser.freezeMoney)}
|
{formatMoney(dealerUser.freezeMoney)}
|
||||||
</Text>
|
</Text>
|
||||||
<Text className="text-xs" style={{ color: 'rgba(255, 255, 255, 0.9)' }}>桶数</Text>
|
<Text className="text-xs" style={{ color: 'rgba(255, 255, 255, 0.9)' }}>
|
||||||
|
{isRider && Number(dealerUser.freezeMoney ?? 0) > 0 ? '待使用' : '待使用'}
|
||||||
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View className="text-center p-3 rounded-lg flex flex-col" style={{
|
<View className="text-center p-3 rounded-lg flex flex-col" style={{
|
||||||
background: businessGradients.money.total
|
background: businessGradients.money.total
|
||||||
|
|||||||
@@ -3,10 +3,11 @@ import {User} from "@/api/system/user/model";
|
|||||||
|
|
||||||
// 模版套餐ID - 请根据实际情况修改
|
// 模版套餐ID - 请根据实际情况修改
|
||||||
export const TEMPLATE_ID = '10584';
|
export const TEMPLATE_ID = '10584';
|
||||||
// 服务接口 - 请根据实际情况修改
|
// 服务接口 - 从环境配置读取
|
||||||
export const SERVER_API_URL = 'https://glt-server.websoft.top/api';
|
// @ts-ignore
|
||||||
// export const SERVER_API_URL = 'https://server.websoft.top/api';
|
export const SERVER_API_URL = process.env.TARO_ENV === 'production'
|
||||||
// export const SERVER_API_URL = 'http://127.0.0.1:8000/api';
|
? 'https://glt-server.websoft.top/api'
|
||||||
|
: 'https://glt-dev-server.websoft.top/api';
|
||||||
/**
|
/**
|
||||||
* 保存用户信息到本地存储
|
* 保存用户信息到本地存储
|
||||||
* @param token
|
* @param token
|
||||||
|
|||||||
Reference in New Issue
Block a user