220 lines
6.5 KiB
Markdown
220 lines
6.5 KiB
Markdown
# 收益明细功能实现 - 2026-01-31
|
||
|
||
## 问题描述
|
||
|
||
收益查看页面显示有收益(222元),但"收益明细"列表显示"暂无收益记录"。
|
||
|
||
## 问题原因
|
||
|
||
后端接口 `/api/provider/earnings/detail` 只是返回空列表,没有实现真正的查询逻辑。
|
||
|
||
```java
|
||
// 原代码
|
||
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. **数据转换**
|
||
- 将订单数据转换为前端需要的格式
|
||
- 包含:课程名称、学生姓名、日期、金额、状态等
|
||
|
||
### 修改后的代码
|
||
|
||
```java
|
||
@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);
|
||
}
|
||
```
|
||
|
||
## 返回数据格式
|
||
|
||
```json
|
||
{
|
||
"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. 查看数据库
|
||
```sql
|
||
-- 查看服务商的已完成订单
|
||
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. 测试接口
|
||
```bash
|
||
# 查询本月收益明细
|
||
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*
|