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` - 小程序提现页面
|
|||
|
|
|
|||
|
|
## 总结
|
|||
|
|
|
|||
|
|
这次数据对接实现了:
|
|||
|
|
|
|||
|
|
### 功能增强
|
|||
|
|
- ✅ 显示用户的完整佣金信息
|
|||
|
|
- ✅ 计算审核后余额
|
|||
|
|
- ✅ 风险警告(超额提现)
|
|||
|
|
- ✅ 数据实时计算,确保准确
|
|||
|
|
|
|||
|
|
### 管理便利
|
|||
|
|
- ✅ 一眼看清用户的资金状况
|
|||
|
|
- ✅ 提前识别超额提现风险
|
|||
|
|
- ✅ 批准/拒绝决策有据可依
|
|||
|
|
|
|||
|
|
### 安全保障
|
|||
|
|
- ✅ 三层校验(前端、后端、管理端)
|
|||
|
|
- ✅ 并发提现检测
|
|||
|
|
- ✅ 超额提现警告
|
|||
|
|
|
|||
|
|
**核心价值**:让管理员能够**看到完整的资金流水**,做出**明智的审核决策**,防止**超额提现风险**。
|