Files
soul-yongping/开发文档/8、部署/后台提现审核功能完善说明.md
2026-02-09 15:09:29 +08:00

17 KiB
Raw Blame History

后台提现审核功能完善说明

概述

完善后台管理的"提现审核"页面,增加用户佣金信息展示,帮助管理员做出准确的审核决策。

功能增强

1. 新增用户佣金信息展示

在提现记录表格中,新增"用户佣金信息"列,显示:

字段 说明 计算方式 颜色
累计佣金 用户的历史总佣金 SUM(orders.amount) × 90% 青色
已提现 已到账的金额 users.withdrawn_earnings 灰色
待审核 所有待审核的提现申请 SUM(withdrawals.amount WHERE status='pending') 橙色
审核后余额 如果通过该申请,用户剩余的可提现金额 累计 - 已提现 - 待审核 绿色(≥0) / 红色(<0)

2. 超额提现风险警告

当"审核后余额"为负数时:

  • 以红色显示
  • 批准时弹出二次确认警告
⚠️ 风险警告:该用户审核后余额为负数(¥-20.00),可能存在超额提现。

确认已核实用户账户并完成打款?

3. 用户头像显示

优化用户信息展示:

  • 如果有头像,显示真实头像
  • 如果无头像,显示昵称首字母
  • 显示推荐码(如果有)

技术实现

后端API (app/api/admin/withdrawals/route.ts)

查询优化

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

返回数据结构

{
  id: string,
  userId: string,
  userNickname: string,
  userPhone: string,
  userAvatar: string,
  referralCode: string,
  amount: number,
  status: string,
  createdAt: string,
  processedAt: string,
  
  // ✅ 新增:用户佣金信息
  userCommissionInfo: {
    totalCommission: number,        // 累计佣金
    withdrawnEarnings: number,      // 已提现
    pendingWithdrawals: number,     // 待审核(包括当前)
    availableAfterThis: number      // 审核后余额
  }
}

计算逻辑

// 累计佣金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

前端页面 (app/admin/withdrawals/page.tsx)

界面布局

<td className="p-4">
  {w.userCommissionInfo ? (
    <div className="text-xs space-y-1">
      {/* 累计佣金 */}
      <div className="flex justify-between gap-4">
        <span className="text-gray-500">累计佣金:</span>
        <span className="text-[#38bdac] font-medium">
          ¥{w.userCommissionInfo.totalCommission.toFixed(2)}
        </span>
      </div>
      
      {/* 已提现 */}
      <div className="flex justify-between gap-4">
        <span className="text-gray-500">已提现:</span>
        <span className="text-gray-400">
          ¥{w.userCommissionInfo.withdrawnEarnings.toFixed(2)}
        </span>
      </div>
      
      {/* 待审核 */}
      <div className="flex justify-between gap-4">
        <span className="text-gray-500">待审核:</span>
        <span className="text-orange-400">
          ¥{w.userCommissionInfo.pendingWithdrawals.toFixed(2)}
        </span>
      </div>
      
      {/* 审核后余额(带边框分隔) */}
      <div className="flex justify-between gap-4 pt-1 border-t border-gray-700/30">
        <span className="text-gray-500">审核后余额:</span>
        <span className={
          w.userCommissionInfo.availableAfterThis >= 0 
            ? "text-green-400 font-medium" 
            : "text-red-400 font-medium"
        }>
          ¥{w.userCommissionInfo.availableAfterThis.toFixed(2)}
        </span>
      </div>
    </div>
  ) : (
    <span className="text-gray-500 text-xs">暂无数据</span>
  )}
</td>

风险警告

const handleApprove = async (id: string) => {
  const withdrawal = withdrawals.find(w => w.id === id)
  
  // 检查超额提现风险
  if (withdrawal?.userCommissionInfo?.availableAfterThis < 0) {
    if (!confirm(`⚠️ 风险警告:该用户审核后余额为负数...`)) {
      return
    }
  } else {
    if (!confirm("确认已完成打款?批准后将更新用户提现记录。")) {
      return
    }
  }
  
  // 执行批准操作
  // ...
}

使用场景

场景1正常提现

用户A的提现申请

  • 累计佣金: ¥100.00
  • 已提现: ¥30.00
  • 待审核: ¥40.00(包括当前 ¥40
  • 审核后余额: ¥30.00 绿色

管理员判断

  • 数据正常
  • 审核通过后还有 ¥30 余额
  • 可以批准

场景2超额提现风险

用户B的提现申请

  • 累计佣金: ¥100.00
  • 已提现: ¥30.00
  • 待审核: ¥80.00(当前 ¥60 + 其他 ¥20
  • 审核后余额: -¥10.00 红色

管理员判断

  • ⚠️ 超额提现风险!
  • ⚠️ 待审核总额 ¥80 > 可提现 ¥70
  • ⚠️ 可能是并发提现或恶意提现
  • 🛑 建议拒绝,或核实后只批准部分

场景3多笔待审核

用户C的多笔提现

第一笔申请 ¥40

  • 累计佣金: ¥100.00
  • 已提现: ¥0.00
  • 待审核: ¥40.00
  • 审核后余额: ¥60.00

第二笔申请 ¥30

  • 累计佣金: ¥100.00
  • 已提现: ¥0.00
  • 待审核: ¥70.00¥40 + ¥30
  • 审核后余额: ¥30.00

第三笔申请 ¥40

  • 累计佣金: ¥100.00
  • 已提现: ¥0.00
  • 待审核: ¥110.00¥40 + ¥30 + ¥40
  • 审核后余额: -¥10.00 红色

管理员策略

  • 批准第一笔¥40
  • 批准第二笔¥30
  • 拒绝第三笔¥40- 余额不足

测试验证

1. 准备测试数据

-- 用户A正常用户
INSERT INTO users (id, nickname, phone, withdrawn_earnings, referral_code) 
VALUES ('user_a', '测试用户A', '13800138000', 0, 'SOULA001');

INSERT INTO orders (id, user_id, amount, referrer_id, status, pay_time) 
VALUES ('order_a1', 'buyer_1', 100, 'user_a', 'paid', NOW());

INSERT INTO withdrawals (id, user_id, amount, status) 
VALUES ('W_A1', 'user_a', 50, 'pending');

-- 用户B超额提现用户
INSERT INTO users (id, nickname, phone, withdrawn_earnings, referral_code) 
VALUES ('user_b', '测试用户B', '13900139000', 30, 'SOULB001');

INSERT INTO orders (id, user_id, amount, referrer_id, status, pay_time) 
VALUES ('order_b1', 'buyer_2', 100, 'user_b', 'paid', NOW());

INSERT INTO withdrawals (id, user_id, amount, status) 
VALUES 
  ('W_B1', 'user_b', 20, 'pending'),
  ('W_B2', 'user_b', 60, 'pending');

2. 访问页面

http://localhost:3006/admin/withdrawals

3. 验证显示

用户A的记录

  • 累计佣金: ¥90.00100 × 90%
  • 已提现: ¥0.00
  • 待审核: ¥50.00
  • 审核后余额: ¥40.00 绿色

用户B的记录W_B1

  • 累计佣金: ¥90.00
  • 已提现: ¥30.00
  • 待审核: ¥80.0020 + 60
  • 审核后余额: -¥20.00 红色

用户B的记录W_B2

  • 累计佣金: ¥90.00
  • 已提现: ¥30.00
  • 待审核: ¥80.0020 + 60
  • 审核后余额: -¥20.00 红色

4. 测试批准操作

批准用户A的提现

  • 正常弹出确认框
  • 批准成功

批准用户B的提现

  • ⚠️ 弹出风险警告
  • 显示负数余额
  • 需要二次确认

管理员决策指南

何时批准?

  • 审核后余额 ≥ 0
  • 用户信息真实完整
  • 累计佣金合理(有订单支持)
  • 已完成线下打款(或准备自动转账)

何时拒绝?

  • 审核后余额 < 0
  • 累计佣金异常(没有订单但有佣金)
  • 同一用户有多笔待审核且总额超额
  • 用户信息不全或异常

如何处理并发提现?

发现场景:同一用户有多笔待审核,总额超出可提现金额

处理策略

  1. 按时间顺序查看
  2. 计算每笔的"审核后余额"
  3. 批准最早的几笔(余额充足的)
  4. 拒绝超额的后续申请
  5. 联系用户说明情况

数据完整性说明

数据来源

数据 来源 可靠性
累计佣金 orders 表实时计算 最准确
已提现 users.withdrawn_earnings 需要提现接口正确维护
待审核 withdrawals 表实时查询 实时准确

计算公式

累计佣金 = Σ(已付款订单金额) × 分成比例(90%)
已提现金额 = users.withdrawn_earnings
待审核金额 = Σ(status='pending'的提现申请)
审核后余额 = 累计佣金 - 已提现金额 - 待审核金额

界面效果

提现记录表格

┌──────────────┬───────────┬──────────┬─────────────────────┬────────┬──────────┬────────┐
│ 申请时间     │   用户    │ 提现金额 │   用户佣金信息      │ 状态   │ 处理时间 │ 操作   │
├──────────────┼───────────┼──────────┼─────────────────────┼────────┼──────────┼────────┤
│ 2026-02-04   │  [头像]   │ ¥50.00  │ 累计佣金: ¥100.00   │ 待处理 │    -     │ 批准   │
│ 15:30        │  张三     │          │ 已提现:   ¥30.00   │        │          │ 拒绝   │
│              │  138***00 │          │ 待审核:   ¥50.00   │        │          │        │
│              │           │          │ ─────────────────   │        │          │        │
│              │           │          │ 审核后余额: ¥20.00  │        │          │        │
└──────────────┴───────────┴──────────┴─────────────────────┴────────┴──────────┴────────┘

风险提示(审核后余额<0

┌──────────────┬───────────┬──────────┬─────────────────────┬────────┬──────────┬────────┐
│ 申请时间     │   用户    │ 提现金额 │   用户佣金信息      │ 状态   │ 处理时间 │ 操作   │
├──────────────┼───────────┼──────────┼─────────────────────┼────────┼──────────┼────────┤
│ 2026-02-04   │  [头像]   │ ¥80.00  │ 累计佣金: ¥100.00   │ 待处理 │    -     │ 批准   │
│ 15:35        │  李四     │          │ 已提现:   ¥30.00   │        │          │ 拒绝   │
│              │  139***00 │          │ 待审核:   ¥80.00   │        │          │        │
│              │           │          │ ─────────────────   │        │          │        │
│              │           │          │ 审核后余额: -¥10.00 │        │          │        │
│              │           │          │           ↑ [红色] │        │          │        │
└──────────────┴───────────┴──────────┴─────────────────────┴────────┴──────────┴────────┘

点击批准时

┌─────────────────────────────────────────┐
│             ⚠️ 风险警告                 │
├─────────────────────────────────────────┤
│ 该用户审核后余额为负数(¥-10.00   │
│ 可能存在超额提现。                      │
│                                         │
│ 确认已核实用户账户并完成打款?          │
├─────────────────────────────────────────┤
│         [取消]          [确定]          │
└─────────────────────────────────────────┘

审核流程示例

正常流程

  1. 管理员查看

    • 用户:张三
    • 提现金额¥50
    • 累计佣金¥100已提现¥30待审核¥50
    • 审核后余额¥20
  2. 判断:数据正常,余额充足

  3. 操作:点击"批准"

  4. 结果

    • 提现记录状态改为 success
    • 用户的 withdrawn_earnings += 50
    • 用户收到微信零钱(自动转账)

风险流程

  1. 管理员查看

    • 用户:李四
    • 提现金额¥80
    • 累计佣金¥100已提现¥30待审核¥80
    • 审核后余额:-¥10
  2. 判断:超额提现,存在风险

  3. 操作

    • 方案A直接拒绝备注"余额不足"
    • 方案B核实数据后只批准部分金额
  4. 结果

    • 拒绝:用户的待审核金额归零,可重新申请
    • 部分批准:需要先拒绝原申请,等用户重新申请合理金额

相关文件

后端文件

  • app/api/admin/withdrawals/route.ts - 提现审核API
  • app/api/withdraw/route.ts - 用户提现接口
  • app/api/referral/data/route.ts - 分销数据接口

前端文件

  • app/admin/withdrawals/page.tsx - 提现审核页面
  • miniprogram/pages/referral/referral.js - 小程序提现页面

脚本文件

  • scripts/verify-withdrawal-data.sql - 数据验证SQL脚本

部署步骤

1. 重启后端服务

python devlop.py restart mycontent

2. 访问管理后台

http://localhost:3006/admin/withdrawals

3. 验证数据显示

  • 用户信息完整(昵称、头像、电话)
  • 提现金额正确
  • 佣金信息完整(累计、已提现、待审核、审核后余额)
  • 审核后余额颜色正确(绿色/红色)
  • 批准/拒绝按钮可用

4. 测试审核操作

  • 批准正常提现审核后余额≥0
  • 批准风险提现(会弹出警告)
  • 拒绝提现(余额返还)

5. 验证数据更新

批准后:

-- 检查提现记录状态
SELECT status FROM withdrawals WHERE id = 'W_XXX';
-- 应该是 'success'

-- 检查用户已提现金额
SELECT withdrawn_earnings FROM users WHERE id = 'user_xxx';
-- 应该增加了提现金额

后续优化建议

1. 批量审核

选中多条记录,一键批准所有:

<Button onClick={handleBatchApprove}>
  批量批准已勾选项
</Button>

2. 自动审核

小额提现(如 ≤ ¥50自动审核通过

if (amount <= 50 && availableAmount >= amount) {
  // 自动批准
}

3. 审核备注

添加备注字段,记录审核原因:

ALTER TABLE withdrawals ADD COLUMN admin_note VARCHAR(500);

4. 审核历史

记录审核人和审核时间:

ALTER TABLE withdrawals 
ADD COLUMN approved_by VARCHAR(64),
ADD COLUMN approved_at TIMESTAMP;

总结

这次数据对接实现了:

信息完整性

  • 显示用户的累计佣金
  • 显示用户的已提现金额
  • 显示用户的待审核金额
  • 计算审核后余额

风险防控

  • 超额提现自动标红
  • 批准时弹出风险警告
  • 帮助管理员做出正确决策

用户体验

  • 界面清晰,数据一目了然
  • 颜色区分(绿色安全,红色风险)
  • 详细的计算明细

核心价值:让管理员能够快速准确地审核提现申请,同时有效防范超额提现风险