378 lines
9.7 KiB
Markdown
378 lines
9.7 KiB
Markdown
# 后台提现审核数据对接
|
||
|
||
## 需求
|
||
|
||
在后台管理的"交易中心-提现审核"页面,完善数据显示,让管理员能够:
|
||
1. 查看用户的累计佣金信息
|
||
2. 查看用户的已提现金额
|
||
3. 查看用户的待审核提现金额
|
||
4. 预判审核通过后用户的剩余余额
|
||
5. 识别超额提现风险
|
||
|
||
## 实现内容
|
||
|
||
### 1. 后端API增强
|
||
|
||
**文件**:`app/api/admin/withdrawals/route.ts`
|
||
|
||
#### 数据库查询优化
|
||
|
||
添加了用户佣金相关信息的查询:
|
||
|
||
```typescript
|
||
SELECT
|
||
w.*,
|
||
u.nickname as user_nickname,
|
||
u.phone as user_phone,
|
||
u.avatar as user_avatar,
|
||
u.referral_code,
|
||
u.withdrawn_earnings,
|
||
u.earnings,
|
||
u.pending_earnings,
|
||
-- 计算累计佣金(从 orders 表)
|
||
(SELECT COALESCE(SUM(o.amount), 0)
|
||
FROM orders o
|
||
WHERE o.referrer_id = w.user_id AND o.status = 'paid') as total_order_amount,
|
||
-- 计算待审核提现金额(不包括当前这条)
|
||
(SELECT COALESCE(SUM(w2.amount), 0)
|
||
FROM withdrawals w2
|
||
WHERE w2.user_id = w.user_id AND w2.status = 'pending' AND w2.id != w.id) as other_pending_amount
|
||
FROM withdrawals w
|
||
LEFT JOIN users u ON w.user_id = u.id
|
||
```
|
||
|
||
#### 返回数据结构
|
||
|
||
新增 `userCommissionInfo` 字段:
|
||
|
||
```typescript
|
||
{
|
||
id: string,
|
||
userId: string,
|
||
userNickname: string,
|
||
amount: number,
|
||
status: string,
|
||
// ... 其他字段
|
||
|
||
// ✅ 新增:用户佣金信息
|
||
userCommissionInfo: {
|
||
totalCommission: number, // 累计佣金(订单金额 × 90%)
|
||
withdrawnEarnings: number, // 已提现金额
|
||
pendingWithdrawals: number, // 待审核金额(包括当前这笔)
|
||
availableAfterThis: number // 审核通过后的剩余余额
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 计算逻辑
|
||
|
||
```typescript
|
||
// 计算累计佣金(90%分成)
|
||
const totalCommission = parseFloat(w.total_order_amount) * 0.9
|
||
|
||
// 已提现金额
|
||
const withdrawnEarnings = parseFloat(w.withdrawn_earnings) || 0
|
||
|
||
// 其他待审核金额(不包括当前这笔)
|
||
const otherPendingAmount = parseFloat(w.other_pending_amount) || 0
|
||
|
||
// 当前提现金额
|
||
const currentWithdrawAmount = parseFloat(w.amount)
|
||
|
||
// ✅ 审核后余额 = 累计佣金 - 已提现 - 其他待审核 - 当前提现
|
||
const availableAfterThis = totalCommission - withdrawnEarnings - otherPendingAmount - currentWithdrawAmount
|
||
```
|
||
|
||
### 2. 前端页面增强
|
||
|
||
**文件**:`app/admin/withdrawals/page.tsx`
|
||
|
||
#### 新增列:用户佣金信息
|
||
|
||
在表格中添加了一列显示用户的完整佣金情况:
|
||
|
||
| 字段 | 说明 | 颜色 |
|
||
|------|------|------|
|
||
| 累计佣金 | 用户的历史总佣金 | 青色(#38bdac) |
|
||
| 已提现 | 已到账的金额 | 灰色 |
|
||
| 待审核 | 所有待审核的提现申请总和 | 橙色 |
|
||
| 审核后余额 | 如果通过当前申请,用户剩余的可提现金额 | 绿色(≥0)/ 红色(<0) |
|
||
|
||
#### 界面效果
|
||
|
||
```
|
||
┌─────────────────────────────────────────┐
|
||
│ 用户佣金信息 │
|
||
├─────────────────────────────────────────┤
|
||
│ 累计佣金: ¥100.00 [青色] │
|
||
│ 已提现: ¥30.00 [灰色] │
|
||
│ 待审核: ¥50.00 [橙色] │
|
||
│ ───────────────────────────── │
|
||
│ 审核后余额: ¥20.00 [绿色] │
|
||
└─────────────────────────────────────────┘
|
||
```
|
||
|
||
#### 风险警告
|
||
|
||
当 `审核后余额 < 0` 时:
|
||
- 显示为红色
|
||
- 批准时弹出警告提示
|
||
|
||
```typescript
|
||
if (withdrawal.userCommissionInfo.availableAfterThis < 0) {
|
||
confirm(`⚠️ 风险警告:该用户审核后余额为负数(¥${availableAfterThis}),可能存在超额提现。\n\n确认已核实用户账户并完成打款?`)
|
||
}
|
||
```
|
||
|
||
## 数据示例
|
||
|
||
### 示例1:正常提现
|
||
|
||
```
|
||
用户A:
|
||
- 累计佣金: ¥100
|
||
- 已提现: ¥30
|
||
- 其他待审核: ¥20
|
||
- 当前申请: ¥40
|
||
|
||
审核后余额 = 100 - 30 - 20 - 40 = ¥10 ✅ 正常
|
||
```
|
||
|
||
### 示例2:超额提现(风险)
|
||
|
||
```
|
||
用户B:
|
||
- 累计佣金: ¥100
|
||
- 已提现: ¥30
|
||
- 其他待审核: ¥20
|
||
- 当前申请: ¥60
|
||
|
||
审核后余额 = 100 - 30 - 20 - 60 = -¥10 ❌ 超额!
|
||
```
|
||
|
||
**警告**:用户B可能存在以下问题:
|
||
1. 重复提现(并发提交)
|
||
2. 恶意超额提现
|
||
3. 数据异常
|
||
|
||
### 示例3:多笔待审核
|
||
|
||
```
|
||
用户C:
|
||
- 累计佣金: ¥200
|
||
- 已提现: ¥50
|
||
- 其他待审核: ¥80(两笔:¥50 + ¥30)
|
||
- 当前申请: ¥50
|
||
|
||
审核后余额 = 200 - 50 - 80 - 50 = ¥20 ✅ 正常
|
||
但注意:如果三笔都通过,还能再提 ¥20
|
||
```
|
||
|
||
## 审核流程
|
||
|
||
### 管理员视角
|
||
|
||
```
|
||
1. 打开提现审核页面
|
||
↓
|
||
2. 查看待审核列表
|
||
↓
|
||
3. 查看用户佣金信息
|
||
- 累计佣金: 判断用户赚了多少
|
||
- 已提现: 判断之前提现过多少
|
||
- 待审核: 判断还有多少在审核中
|
||
- 审核后余额: 判断是否超额
|
||
↓
|
||
4. 点击"批准"或"拒绝"
|
||
↓
|
||
5. 如果审核后余额 < 0:
|
||
- ⚠️ 弹出风险警告
|
||
- 需要二次确认
|
||
↓
|
||
6. 确认后执行操作
|
||
```
|
||
|
||
### 决策依据
|
||
|
||
**批准条件**:
|
||
- ✅ 审核后余额 ≥ 0
|
||
- ✅ 用户信息真实
|
||
- ✅ 已完成线下打款(或准备自动转账)
|
||
|
||
**拒绝条件**:
|
||
- ❌ 审核后余额 < 0(超额提现)
|
||
- ❌ 用户信息异常
|
||
- ❌ 疑似恶意提现
|
||
- ❌ 未完成打款且不打算打款
|
||
|
||
## 统计信息
|
||
|
||
### 顶部统计卡片
|
||
|
||
显示全局提现统计:
|
||
|
||
| 统计项 | 说明 |
|
||
|--------|------|
|
||
| 总申请 | 所有提现申请的数量 |
|
||
| 待处理 | 状态为 pending 的数量和金额 |
|
||
| 已完成 | 状态为 success 的数量和金额 |
|
||
| 已拒绝 | 状态为 failed 的数量 |
|
||
|
||
### 筛选功能
|
||
|
||
可以按状态筛选:
|
||
- 全部
|
||
- 待处理(pending)
|
||
- 已完成(success)
|
||
- 已拒绝(failed)
|
||
|
||
## 状态说明
|
||
|
||
| 状态 | 英文 | 说明 | 可操作 |
|
||
|------|------|------|--------|
|
||
| 待处理 | pending | 用户刚提交,等待审核 | 批准/拒绝 |
|
||
| 处理中 | processing | 已发起微信转账,等待到账 | - |
|
||
| 已完成 | success | 已到账,提现完成 | - |
|
||
| 已拒绝 | failed | 管理员拒绝,余额已返还 | - |
|
||
|
||
## 测试步骤
|
||
|
||
### 1. 准备测试数据
|
||
|
||
```sql
|
||
-- 插入测试用户
|
||
INSERT INTO users (id, nickname, phone, withdrawn_earnings, referral_code)
|
||
VALUES ('test_user_1', '测试用户A', '13800138000', 0, 'SOULA001');
|
||
|
||
-- 插入测试订单(产生佣金)
|
||
INSERT INTO orders (id, user_id, amount, referrer_id, status, pay_time)
|
||
VALUES ('order_1', 'buyer_1', 100, 'test_user_1', 'paid', NOW());
|
||
|
||
-- 插入测试提现申请
|
||
INSERT INTO withdrawals (id, user_id, amount, status, created_at)
|
||
VALUES ('W001', 'test_user_1', 50, 'pending', NOW());
|
||
```
|
||
|
||
### 2. 访问页面
|
||
|
||
```
|
||
http://localhost:3006/admin/withdrawals
|
||
```
|
||
|
||
### 3. 验证数据
|
||
|
||
**查看提现记录**:
|
||
- 用户昵称:测试用户A
|
||
- 电话:138****8000
|
||
- 提现金额:¥50.00
|
||
|
||
**查看佣金信息**:
|
||
- 累计佣金:¥90.00(100 × 90%)
|
||
- 已提现:¥0.00
|
||
- 待审核:¥50.00
|
||
- 审核后余额:¥40.00 ✅
|
||
|
||
### 4. 测试超额提现
|
||
|
||
```sql
|
||
-- 再插入一笔超额提现
|
||
INSERT INTO withdrawals (id, user_id, amount, status, created_at)
|
||
VALUES ('W002', 'test_user_1', 60, 'pending', NOW());
|
||
```
|
||
|
||
**刷新页面**,查看 W002:
|
||
- 累计佣金:¥90.00
|
||
- 已提现:¥0.00
|
||
- 待审核:¥110.00(50 + 60)
|
||
- 审核后余额:**-¥20.00** ❌ 红色显示
|
||
|
||
**点击批准**:
|
||
- 应该弹出风险警告
|
||
- 需要二次确认
|
||
|
||
## 安全检查
|
||
|
||
### 防止超额提现
|
||
|
||
1. **前端校验**:小程序端计算可提现金额
|
||
2. **后端校验**:提现接口验证金额
|
||
3. **管理端提示**:显示审核后余额,红色警告
|
||
|
||
### 并发提现防护
|
||
|
||
如果用户快速提交多笔提现:
|
||
- 后端查询会累加所有待审核金额
|
||
- 管理员能看到"待审核"总额
|
||
- "审核后余额"会提前减去所有待审核的金额
|
||
|
||
### 数据一致性
|
||
|
||
- 累计佣金:实时从 orders 表计算
|
||
- 已提现:从 users.withdrawn_earnings 读取
|
||
- 待审核:实时从 withdrawals 表查询
|
||
|
||
## 常见问题
|
||
|
||
### Q1: 为什么审核后余额是负数?
|
||
|
||
**A**: 可能原因:
|
||
1. 用户并发提交多笔提现
|
||
2. 前端校验被绕过
|
||
3. 数据库数据异常
|
||
|
||
**处理**:
|
||
- 拒绝超额提现申请
|
||
- 核查用户账户
|
||
- 只批准合理范围内的提现
|
||
|
||
### Q2: 如果有多笔待审核,应该如何处理?
|
||
|
||
**A**:
|
||
- 查看"待审核"总额
|
||
- 确保所有待审核的总和 ≤ 可提现金额
|
||
- 按时间顺序逐笔审核
|
||
- 或者拒绝超额的申请
|
||
|
||
### Q3: 审核后余额为0,还能再提现吗?
|
||
|
||
**A**:
|
||
- 如果有新订单产生佣金,可以
|
||
- 审核后余额0表示当前所有佣金都将被提走
|
||
- 新订单会增加累计佣金,从而增加可提现金额
|
||
|
||
### Q4: 如何处理已拒绝的提现?
|
||
|
||
**A**:
|
||
- 拒绝时余额自动返还
|
||
- 用户可以在小程序重新申请
|
||
- "审核后余额"会恢复
|
||
|
||
## 相关文件
|
||
|
||
- `app/admin/withdrawals/page.tsx` - 前端页面 ✅
|
||
- `app/api/admin/withdrawals/route.ts` - 后端API ✅
|
||
- `app/api/withdraw/route.ts` - 用户提现接口
|
||
- `miniprogram/pages/referral/referral.js` - 小程序提现页面
|
||
|
||
## 总结
|
||
|
||
这次数据对接实现了:
|
||
|
||
### 功能增强
|
||
- ✅ 显示用户的完整佣金信息
|
||
- ✅ 计算审核后余额
|
||
- ✅ 风险警告(超额提现)
|
||
- ✅ 数据实时计算,确保准确
|
||
|
||
### 管理便利
|
||
- ✅ 一眼看清用户的资金状况
|
||
- ✅ 提前识别超额提现风险
|
||
- ✅ 批准/拒绝决策有据可依
|
||
|
||
### 安全保障
|
||
- ✅ 三层校验(前端、后端、管理端)
|
||
- ✅ 并发提现检测
|
||
- ✅ 超额提现警告
|
||
|
||
**核心价值**:让管理员能够**看到完整的资金流水**,做出**明智的审核决策**,防止**超额提现风险**。
|