Files
soul-yongping/开发文档/8、部署/提现卡片数据优化说明.md

368 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 提现卡片数据优化说明
## 一、修改需求
**用户需求**
1. **累计佣金**:显示用户获得的所有佣金总额(包括可提现、待审核、已提现的所有佣金)
2. **待审核金额**:显示当前已发起提现申请但还未审核的金额累计总和(`withdrawals` 表中 `status = 'pending'` 的金额)
3. **可提现金额**:显示可以发起提现的金额(即 `users.pending_earnings`
## 二、数据定义
### 1. 原数据结构
| 字段 | 原定义 | 问题 |
|------|--------|------|
| `users.earnings` | 已结算收益 | 不够直观 |
| `users.pending_earnings` | 待结算收益 | 命名容易误解,实际是可提现金额 |
| `users.withdrawn_earnings` | 已提现金额 | ✅ 正确 |
### 2. 新数据结构
| 字段 | 新定义 | 说明 |
|------|--------|------|
| **累计佣金** (`totalCommission`) | `earnings` + `pending_earnings` + `withdrawn_earnings` | 所有获得的佣金总额 |
| **可提现金额** (`availableEarnings`) | `pending_earnings` | 未申请提现的佣金,可以发起提现 |
| **待审核金额** (`pendingWithdrawAmount`) | `SUM(withdrawals.amount) WHERE status='pending'` | 已发起提现但未审核的金额 |
| **已提现金额** (`withdrawnEarnings`) | `withdrawn_earnings` | 已成功提现的金额 |
### 3. 业务流程
```
用户获得佣金
累计佣金 +X
可提现金额 +X (pending_earnings)
用户发起提现申请
可提现金额 -X (pending_earnings)
待审核金额 +X (withdrawals.status='pending')
管理员审核通过
待审核金额 -X (withdrawals.status='success')
已提现金额 +X (withdrawn_earnings)
累计佣金不变
```
## 三、代码修改
### 1. 后端 API 修改 (`app/api/referral/data/route.ts`)
#### 添加待审核金额查询
```typescript
// 7. 获取待审核提现金额
let pendingWithdrawAmount = 0
try {
const pendingResult = await query(`
SELECT COALESCE(SUM(amount), 0) as pending_amount
FROM withdrawals
WHERE user_id = ? AND status = 'pending'
`, [userId]) as any[]
pendingWithdrawAmount = parseFloat(pendingResult[0]?.pending_amount || 0)
} catch (e) {
console.log('[ReferralData] 获取待审核提现金额失败:', e)
}
```
#### 修改返回数据
```typescript
// === 收益数据 ===
// 累计佣金总额(所有获得的佣金)
totalCommission: Math.round((
(parseFloat(user.earnings) || 0) +
(parseFloat(user.pending_earnings) || 0) +
(parseFloat(user.withdrawn_earnings) || 0)
) * 100) / 100,
// 可提现金额pending_earnings
availableEarnings: parseFloat(user.pending_earnings) || 0,
// 待审核金额(提现申请中的金额)
pendingWithdrawAmount: Math.round(pendingWithdrawAmount * 100) / 100,
// 已提现金额
withdrawnEarnings: parseFloat(user.withdrawn_earnings) || 0,
// 已结算收益(保留兼容)
earnings: parseFloat(user.earnings) || 0,
// 待结算收益(保留兼容)
pendingEarnings: parseFloat(user.pending_earnings) || 0,
```
### 2. 小程序前端修改
#### 数据字段 (`miniprogram/pages/referral/referral.js`)
```javascript
data: {
// === 收益数据 ===
totalCommission: 0, // 累计佣金总额(所有获得的佣金)
availableEarnings: 0, // 可提现金额(未申请提现的佣金)
pendingWithdrawAmount: 0, // 待审核金额(已申请提现但未审核)
withdrawnEarnings: 0, // 已提现金额
earnings: 0, // 已结算收益(保留兼容)
pendingEarnings: 0, // 待结算收益(保留兼容)
shareRate: 90, // 分成比例90%
minWithdrawAmount: 10, // 最低提现金额(从后端获取)
}
```
#### 数据更新逻辑
```javascript
this.setData({
// 收益数据 - 格式化为两位小数
totalCommission: formatMoney(realData?.totalCommission || 0),
availableEarnings: formatMoney(realData?.availableEarnings || 0),
pendingWithdrawAmount: formatMoney(realData?.pendingWithdrawAmount || 0),
withdrawnEarnings: formatMoney(realData?.withdrawnEarnings || 0),
earnings: formatMoney(realData?.earnings || 0),
pendingEarnings: formatMoney(realData?.pendingEarnings || 0),
shareRate: realData?.shareRate || 90,
minWithdrawAmount: realData?.minWithdrawAmount || 10,
})
```
#### 提现逻辑修改
```javascript
async handleWithdraw() {
const availableEarnings = parseFloat(this.data.availableEarnings) || 0
const minWithdrawAmount = this.data.minWithdrawAmount || 10
if (availableEarnings <= 0) {
wx.showToast({ title: '暂无可提现收益', icon: 'none' })
return
}
// 检查是否达到最低提现金额
if (availableEarnings < minWithdrawAmount) {
wx.showToast({
title: `满${minWithdrawAmount}元可提现`,
icon: 'none'
})
return
}
// 确认提现
wx.showModal({
title: '确认提现',
content: `将提现 ¥${availableEarnings.toFixed(2)} 到您的微信零钱`,
confirmText: '立即提现',
success: async (res) => {
if (res.confirm) {
await this.doWithdraw(availableEarnings)
}
}
})
}
```
### 3. UI 界面修改 (`miniprogram/pages/referral/referral.wxml`)
```xml
<!-- 收益卡片 - 对齐 Next.js -->
<view class="earnings-card">
<view class="earnings-bg"></view>
<view class="earnings-main">
<view class="earnings-header">
<view class="earnings-left">
<view class="wallet-icon">
<image class="icon-wallet" src="/assets/icons/wallet.svg" mode="aspectFit"></image>
</view>
<view class="earnings-info">
<text class="earnings-label">累计佣金</text>
<text class="commission-rate">{{shareRate}}% 返利</text>
</view>
</view>
<view class="earnings-right">
<text class="earnings-value">¥{{totalCommission}}</text>
<text class="pending-text">待审核: ¥{{pendingWithdrawAmount}}</text>
</view>
</view>
<view class="withdraw-btn {{availableEarnings < minWithdrawAmount ? 'btn-disabled' : ''}}" bindtap="handleWithdraw">
{{availableEarnings < minWithdrawAmount ? '满' + minWithdrawAmount + '元可提现' : '申请提现 ¥' + availableEarnings}}
</view>
</view>
</view>
```
### 4. 界面变化对比
| 位置 | 原显示 | 新显示 | 说明 |
|------|--------|--------|------|
| 卡片标题 | 累计收益 | 累计佣金 | 更准确的描述 |
| 主金额 | `earnings` | `totalCommission` | 显示所有佣金总和 |
| 副金额标签 | "待结算" | "待审核" | 更明确的状态描述 |
| 副金额 | `pendingEarnings` | `pendingWithdrawAmount` | 显示提现申请中的金额 |
| 按钮文案 | "申请提现" | "申请提现 ¥XX" | 显示可提现金额 |
| 按钮禁用 | `pendingEarnings < minWithdrawAmount` | `availableEarnings < minWithdrawAmount` | 使用可提现金额判断 |
## 四、验证方法
### 1. 数据库检查
```sql
-- 查看用户收益数据
SELECT
id,
nickname,
earnings,
pending_earnings,
withdrawn_earnings,
(earnings + pending_earnings + withdrawn_earnings) as total_commission
FROM users
WHERE id = 'user_xxx';
-- 查看待审核提现金额
SELECT
user_id,
SUM(amount) as pending_amount
FROM withdrawals
WHERE status = 'pending'
GROUP BY user_id;
```
### 2. API 测试
```bash
# 测试接口
curl -X GET "http://localhost:3000/api/referral/data" \
-H "Cookie: auth_token=xxx"
```
**期望返回数据**
```json
{
"success": true,
"data": {
"totalCommission": 100.00, // 累计佣金 = 30 + 50 + 20
"availableEarnings": 50.00, // 可提现 = pending_earnings
"pendingWithdrawAmount": 20.00, // 待审核 = SUM(withdrawals WHERE status='pending')
"withdrawnEarnings": 30.00, // 已提现
"earnings": 30.00, // 已结算(保留兼容)
"pendingEarnings": 50.00, // 待结算(保留兼容)
"shareRate": 90,
"minWithdrawAmount": 10
}
}
```
### 3. 小程序测试
1. **查看提现卡片**
- ✅ 累计佣金显示正确(所有佣金总和)
- ✅ 待审核金额显示正确(提现申请中的金额)
- ✅ 提现按钮显示可提现金额
2. **发起提现**
- ✅ 提现按钮使用 `availableEarnings` 判断是否可用
- ✅ 提现金额为 `availableEarnings`
- ✅ 提现后,`availableEarnings` 减少,`pendingWithdrawAmount` 增加
3. **管理员审核后**
-`pendingWithdrawAmount` 减少
-`withdrawnEarnings` 增加
-`totalCommission` 保持不变
## 五、注意事项
### 1. 向后兼容
为了保证系统稳定,保留了原有的 `earnings``pendingEarnings` 字段,仅在小程序中使用新字段。
### 2. 提现流程
用户发起提现时,系统会:
1. 扣减 `users.pending_earnings`
2. 创建 `withdrawals` 记录(`status = 'pending'`
3. 管理员审核通过后,`withdrawals.status` 改为 `'success'`
4. 同时增加 `users.withdrawn_earnings`
### 3. 数据一致性
确保以下等式始终成立:
```
totalCommission = availableEarnings + pendingWithdrawAmount + withdrawnEarnings
```
### 4. 前端显示
所有金额都使用 `formatMoney()` 函数格式化为两位小数。
## 六、影响范围
### 修改文件
1. **后端**
- `app/api/referral/data/route.ts` - 添加 `pendingWithdrawAmount` 查询和返回字段
2. **小程序**
- `miniprogram/pages/referral/referral.js` - 数据字段和提现逻辑
- `miniprogram/pages/referral/referral.wxml` - UI 显示
### 不影响
- ❌ 提现流程逻辑(`/api/withdraw`
- ❌ 管理后台(仍使用原字段)
- ❌ 佣金计算逻辑(`/api/payment/*/notify`
- ❌ 数据库表结构(无需修改)
## 七、测试场景
### 场景 1新用户获得佣金
```
初始状态:
- totalCommission = 0
- availableEarnings = 0
- pendingWithdrawAmount = 0
- withdrawnEarnings = 0
用户 A 购买了 100 元的书籍,推荐人 B 获得 90 元佣金:
- totalCommission = 90
- availableEarnings = 90
- pendingWithdrawAmount = 0
- withdrawnEarnings = 0
```
### 场景 2用户发起提现
```
用户 B 发起提现 90 元:
- totalCommission = 90不变
- availableEarnings = 0减少 90
- pendingWithdrawAmount = 90增加 90
- withdrawnEarnings = 0
```
### 场景 3管理员审核通过
```
管理员审核通过,打款成功:
- totalCommission = 90不变
- availableEarnings = 0
- pendingWithdrawAmount = 0减少 90
- withdrawnEarnings = 90增加 90
```
### 场景 4管理员拒绝提现
```
管理员拒绝提现:
- totalCommission = 90不变
- availableEarnings = 90恢复 90
- pendingWithdrawAmount = 0减少 90
- withdrawnEarnings = 0
```
## 八、总结
此次优化主要解决了提现卡片数据定义不清晰的问题:
1. **累计佣金**:直观展示用户获得的所有佣金
2. **可提现金额**:明确告知用户可以发起提现的金额
3. **待审核金额**:让用户清楚知道有多少提现申请正在处理中
优化后的界面更加清晰、易懂,用户体验更佳!