peixue-dev/Archive/[一次性]收益明细功能实现-2026-01-31.md

6.5 KiB
Raw Permalink Blame History

收益明细功能实现 - 2026-01-31

问题描述

收益查看页面显示有收益222元但"收益明细"列表显示"暂无收益记录"。

问题原因

后端接口 /api/provider/earnings/detail 只是返回空列表,没有实现真正的查询逻辑。

// 原代码
Map<String, Object> response = new HashMap<>();
response.put("records", new ArrayList<>());  // 直接返回空列表
response.put("total", 0);
return Result.success(response);

修复方案

实现收益明细查询功能,从订单表中查询已完成的订单作为收益记录。

实现逻辑

  1. 时间范围筛选

    • 本月当前月份第1天到当前时间
    • 本季度当前季度第一个月的第1天到当前时间
    • 本年当前年份1月1日到当前时间
  2. 订单筛选条件

    • teacher_id = providerId服务商ID
    • status = 4(只查询已完成订单)
    • create_time 在时间范围内
  3. 分页查询

    • 支持分页参数page页码、size每页数量
    • 按创建时间倒序排列
  4. 数据转换

    • 将订单数据转换为前端需要的格式
    • 包含:课程名称、学生姓名、日期、金额、状态等

修改后的代码

@GetMapping("/earnings/detail")
public Result<Object> getEarningsDetail(
        @RequestHeader("Authorization") String token,
        @RequestParam(required = false) String type,
        @RequestParam(defaultValue = "1") Integer page,
        @RequestParam(defaultValue = "10") Integer size) {
    
    // 1. 获取服务商ID
    Long userId = jwtUtil.getUserIdFromToken(token.substring(7));
    Long providerId = providerService.getProviderIdByUserId(userId);
    
    // 2. 确定时间范围
    LocalDateTime now = LocalDateTime.now();
    LocalDateTime start;
    if ("year".equals(type)) {
        start = now.withDayOfYear(1).withHour(0).withMinute(0).withSecond(0);
    } else if ("quarter".equals(type)) {
        int month = now.getMonthValue();
        int quarterStartMonth = ((month - 1) / 3) * 3 + 1;
        start = now.withMonth(quarterStartMonth).withDayOfMonth(1)
                   .withHour(0).withMinute(0).withSecond(0);
    } else {
        start = now.withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0);
    }
    LocalDateTime end = now.withHour(23).withMinute(59).withSecond(59);
    
    // 3. 查询已完成订单
    LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
    wrapper.eq(Order::getTeacherId, providerId)
           .eq(Order::getStatus, 4)  // 只查询已完成订单
           .between(Order::getCreateTime, start, end)
           .orderByDesc(Order::getCreateTime);
    
    // 4. 分页查询
    Page<Order> pageParam = new Page<>(page, size);
    Page<Order> orderPage = orderMapper.selectPage(pageParam, wrapper);
    
    // 5. 转换数据格式
    List<Map<String, Object>> records = orderPage.getRecords().stream()
            .map(order -> {
                Map<String, Object> record = new HashMap<>();
                record.put("id", order.getId());
                record.put("courseName", order.getServiceName() != null ? 
                          order.getServiceName() : "课程服务");
                record.put("studentName", order.getStudentName() != null ? 
                          order.getStudentName() : "学生");
                record.put("date", order.getCreateTime() != null ? 
                          order.getCreateTime().format(
                              DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")) : "");
                record.put("type", "income");
                record.put("amount", order.getPayAmount() != null ? 
                          order.getPayAmount() : BigDecimal.ZERO);
                record.put("status", "completed");
                record.put("statusText", "已结算");
                return record;
            })
            .collect(Collectors.toList());
    
    // 6. 返回结果
    Map<String, Object> response = new HashMap<>();
    response.put("records", records);
    response.put("total", orderPage.getTotal());
    response.put("pages", orderPage.getPages());
    response.put("current", orderPage.getCurrent());
    
    return Result.success(response);
}

返回数据格式

{
  "code": 200,
  "message": "success",
  "data": {
    "records": [
      {
        "id": 1,
        "courseName": "数学一对一",
        "studentName": "张小明",
        "date": "2026-01-20 14:30",
        "type": "income",
        "amount": 100,
        "status": "completed",
        "statusText": "已结算"
      },
      {
        "id": 2,
        "courseName": "英语口语",
        "studentName": "李小红",
        "date": "2026-01-18 10:00",
        "type": "income",
        "amount": 122,
        "status": "completed",
        "statusText": "已结算"
      }
    ],
    "total": 2,
    "pages": 1,
    "current": 1
  }
}

前端展示

收益明细列表会显示:

  • 课程名称
  • 学生姓名
  • 服务日期和时间
  • 收益金额(绿色显示,带+号)
  • 状态标签(已结算)

验证方法

1. 查看数据库

-- 查看服务商的已完成订单
SELECT 
    id,
    service_name,
    student_name,
    pay_amount,
    create_time,
    status
FROM `order`
WHERE teacher_id = ? AND status = 4
ORDER BY create_time DESC;

2. 测试接口

# 查询本月收益明细
GET /api/provider/earnings/detail?type=month&page=1&size=10

# 查询本季度收益明细
GET /api/provider/earnings/detail?type=quarter&page=1&size=10

# 查询本年收益明细
GET /api/provider/earnings/detail?type=year&page=1&size=10

3. 前端验证

  1. 打开收益查看页面
  2. 切换"本月"、"本季度"、"本年"标签
  3. 查看"收益明细"列表是否显示订单记录
  4. 验证金额、日期、学生信息是否正确

注意事项

  1. 只显示已完成订单

    • status = 4 的订单才会显示在收益明细中
    • 待服务、服务中的订单不会显示
  2. 时间范围

    • 根据选择的标签(本月/本季度/本年)显示对应时间范围的记录
    • 使用订单的 create_time 字段判断
  3. 分页支持

    • 默认每页显示10条记录
    • 支持翻页查看更多记录
  4. 数据一致性

    • 收益明细的总金额应该等于收益统计中显示的金额
    • 如果不一致,需要检查订单状态和时间范围

相关文件

  • peidu/backend/src/main/java/com/peidu/controller/ProviderController.java
  • peidu/uniapp/src/provider-package/pages/provider/earnings.vue

实现时间2026-01-31