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

11 KiB
Raw Blame History

提现卡片数据优化说明

一、修改需求

用户需求

  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)

添加待审核金额查询

// 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)
}

修改返回数据

// === 收益数据 ===
// 累计佣金总额(所有获得的佣金)
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)

data: {
  // === 收益数据 ===
  totalCommission: 0,   // 累计佣金总额(所有获得的佣金)
  availableEarnings: 0, // 可提现金额(未申请提现的佣金)
  pendingWithdrawAmount: 0, // 待审核金额(已申请提现但未审核)
  withdrawnEarnings: 0, // 已提现金额
  earnings: 0,          // 已结算收益(保留兼容)
  pendingEarnings: 0,   // 待结算收益(保留兼容)
  shareRate: 90,        // 分成比例90%
  minWithdrawAmount: 10, // 最低提现金额(从后端获取)
}

数据更新逻辑

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,
})

提现逻辑修改

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)

<!-- 收益卡片 - 对齐 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. 数据库检查

-- 查看用户收益数据
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 测试

# 测试接口
curl -X GET "http://localhost:3000/api/referral/data" \
  -H "Cookie: auth_token=xxx"

期望返回数据

{
  "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. 向后兼容

为了保证系统稳定,保留了原有的 earningspendingEarnings 字段,仅在小程序中使用新字段。

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. 待审核金额:让用户清楚知道有多少提现申请正在处理中

优化后的界面更加清晰、易懂,用户体验更佳!