peixue-dev/Archive/[一次性]服务商提现功能优化-2026-01-31.md

4.5 KiB

服务商提现功能优化

日期: 2026-01-31
功能: 服务商提现申请后,可提取金额立即减少


问题描述

用户反馈:提交提现申请后,可提取金额没有变化。

原因分析

修改前的逻辑:

可提取金额 = 总收益(所有已完成订单的金额)

问题:

  • 提现申请只创建了记录,没有扣减可提现余额
  • 无论提现多少次,可提取金额始终等于总收益

解决方案

修改后的逻辑

可提取金额 = 总收益 - 已提现金额 - 提现中金额

其中:

  • 总收益: 所有已完成订单(status=4)的金额总和
  • 已提现金额: 状态为 approvedcompleted 的提现记录金额总和
  • 提现中金额: 状态为 pending 的提现记录金额总和

状态流转

pending (待审核) → approved (已通过) → completed (已完成)
                 ↘ rejected (已拒绝)
  • pending: 用户提交提现申请,金额从"可提取"转为"提现中"
  • approved: 管理员审核通过,金额仍在"已提现"
  • rejected: 管理员拒绝,金额回到"可提取"
  • completed: 提现完成,金额在"已提现"

修改内容

文件: ProviderServiceImpl.java

方法: getEarningsStats(Long providerId)

修改点:

  1. 计算已提现金额
// 查询状态为 approved 或 completed 的提现记录
LambdaQueryWrapper<Withdraw> withdrawnWrapper = new LambdaQueryWrapper<>();
withdrawnWrapper.eq(Withdraw::getTeacherId, providerId)
        .in(Withdraw::getStatus, "approved", "completed");
List<Withdraw> withdrawnRecords = withdrawMapper.selectList(withdrawnWrapper);
BigDecimal withdrawnAmount = withdrawnRecords.stream()
        .map(Withdraw::getAmount)
        .filter(amount -> amount != null)
        .reduce(BigDecimal.ZERO, BigDecimal::add);
  1. 计算提现中金额
// 查询状态为 pending 的提现记录
LambdaQueryWrapper<Withdraw> withdrawingWrapper = new LambdaQueryWrapper<>();
withdrawingWrapper.eq(Withdraw::getTeacherId, providerId)
        .eq(Withdraw::getStatus, "pending");
List<Withdraw> withdrawingRecords = withdrawMapper.selectList(withdrawingWrapper);
BigDecimal withdrawingAmount = withdrawingRecords.stream()
        .map(Withdraw::getAmount)
        .filter(amount -> amount != null)
        .reduce(BigDecimal.ZERO, BigDecimal::add);
  1. 计算可提现余额
// 可提现余额 = 总收益 - 已提现金额 - 提现中金额
BigDecimal availableBalance = totalEarnings
        .subtract(withdrawnAmount)
        .subtract(withdrawingAmount);

// 确保可提现余额不为负数
if (availableBalance.compareTo(BigDecimal.ZERO) < 0) {
    availableBalance = BigDecimal.ZERO;
}

测试步骤

1. 查看当前收益状态

-- 查看服务商的订单收益
SELECT SUM(pay_amount) as total_earnings
FROM `order`
WHERE teacher_id = ? AND status = 4;

-- 查看提现记录
SELECT status, SUM(amount) as total
FROM withdraw
WHERE teacher_id = ?
GROUP BY status;

2. 提交提现申请

  • 前端: 进入"收益查看"页面 → 点击"提取收益"
  • 输入提现金额 → 提交

3. 验证可提取金额变化

  • 提交后,刷新页面
  • 可提取金额应该减少(扣除提现申请的金额)
  • 提现中金额应该增加

4. 测试审核流程

  • 管理员审核通过: 金额从"提现中"转为"已提现"
  • 管理员拒绝: 金额回到"可提取"

预期效果

场景1: 提交提现申请

操作前:

  • 总收益: ¥1000
  • 可提取: ¥1000
  • 提现中: ¥0
  • 已提现: ¥0

提交¥300提现申请后:

  • 总收益: ¥1000
  • 可提取: ¥700
  • 提现中: ¥300
  • 已提现: ¥0

场景2: 审核通过

审核通过后:

  • 总收益: ¥1000
  • 可提取: ¥700
  • 提现中: ¥0
  • 已提现: ¥300

场景3: 审核拒绝

审核拒绝后:

  • 总收益: ¥1000
  • 可提取: ¥1000 (金额回到可提取)
  • 提现中: ¥0
  • 已提现: ¥0

注意事项

  1. 数据一致性: 确保提现记录的状态正确更新
  2. 并发控制: 多次提现申请时,需要确保余额计算正确
  3. 负数保护: 可提现余额不能为负数
  4. 日志记录: 关键操作都有日志输出,便于排查问题

相关文件

  • peidu/backend/src/main/java/com/peidu/service/impl/ProviderServiceImpl.java
  • peidu/backend/src/main/java/com/peidu/entity/Withdraw.java
  • peidu/uniapp/src/provider-package/pages/provider/earnings.vue
  • peidu/uniapp/src/provider-package/pages/provider/withdraw.vue