# 服务商提现功能优化 **日期:** 2026-01-31 **功能:** 服务商提现申请后,可提取金额立即减少 --- ## 问题描述 用户反馈:提交提现申请后,可提取金额没有变化。 ### 原因分析 **修改前的逻辑:** ``` 可提取金额 = 总收益(所有已完成订单的金额) ``` 问题: - 提现申请只创建了记录,没有扣减可提现余额 - 无论提现多少次,可提取金额始终等于总收益 --- ## 解决方案 ### 修改后的逻辑 ``` 可提取金额 = 总收益 - 已提现金额 - 提现中金额 ``` 其中: - **总收益**: 所有已完成订单(status=4)的金额总和 - **已提现金额**: 状态为 `approved` 或 `completed` 的提现记录金额总和 - **提现中金额**: 状态为 `pending` 的提现记录金额总和 ### 状态流转 ``` pending (待审核) → approved (已通过) → completed (已完成) ↘ rejected (已拒绝) ``` - **pending**: 用户提交提现申请,金额从"可提取"转为"提现中" - **approved**: 管理员审核通过,金额仍在"已提现" - **rejected**: 管理员拒绝,金额回到"可提取" - **completed**: 提现完成,金额在"已提现" --- ## 修改内容 ### 文件: `ProviderServiceImpl.java` **方法:** `getEarningsStats(Long providerId)` **修改点:** 1. **计算已提现金额** ```java // 查询状态为 approved 或 completed 的提现记录 LambdaQueryWrapper withdrawnWrapper = new LambdaQueryWrapper<>(); withdrawnWrapper.eq(Withdraw::getTeacherId, providerId) .in(Withdraw::getStatus, "approved", "completed"); List withdrawnRecords = withdrawMapper.selectList(withdrawnWrapper); BigDecimal withdrawnAmount = withdrawnRecords.stream() .map(Withdraw::getAmount) .filter(amount -> amount != null) .reduce(BigDecimal.ZERO, BigDecimal::add); ``` 2. **计算提现中金额** ```java // 查询状态为 pending 的提现记录 LambdaQueryWrapper withdrawingWrapper = new LambdaQueryWrapper<>(); withdrawingWrapper.eq(Withdraw::getTeacherId, providerId) .eq(Withdraw::getStatus, "pending"); List withdrawingRecords = withdrawMapper.selectList(withdrawingWrapper); BigDecimal withdrawingAmount = withdrawingRecords.stream() .map(Withdraw::getAmount) .filter(amount -> amount != null) .reduce(BigDecimal.ZERO, BigDecimal::add); ``` 3. **计算可提现余额** ```java // 可提现余额 = 总收益 - 已提现金额 - 提现中金额 BigDecimal availableBalance = totalEarnings .subtract(withdrawnAmount) .subtract(withdrawingAmount); // 确保可提现余额不为负数 if (availableBalance.compareTo(BigDecimal.ZERO) < 0) { availableBalance = BigDecimal.ZERO; } ``` --- ## 测试步骤 ### 1. 查看当前收益状态 ```sql -- 查看服务商的订单收益 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`