383 lines
9.4 KiB
Markdown
383 lines
9.4 KiB
Markdown
# 家长端服务记录功能检查补充报告
|
||
|
||
**检查时间**: 2026-01-23
|
||
**检查人**: AI助手
|
||
**针对问题**: 家长端日历中是否已实现查看服务记录(打卡照片、服务时长)
|
||
|
||
---
|
||
|
||
## 一、检查结论
|
||
|
||
❌ **家长端日历页面未实现查看服务记录(打卡照片、服务时长)功能**
|
||
|
||
---
|
||
|
||
## 二、家长端日历页面现状
|
||
|
||
### 2.1 页面位置
|
||
- 路径: `user-package/pages/calendar/index.vue`
|
||
- 配置: 已在 `pages.json` 中配置(但未找到对应路由)
|
||
|
||
### 2.2 已实现的功能 ✅
|
||
|
||
1. **日历展示**
|
||
- 显示月度日历视图
|
||
- 标记有服务安排的日期
|
||
- 支持月份切换
|
||
|
||
2. **统计信息**
|
||
- 总课时数
|
||
- 已完成课时
|
||
- 待服务课时
|
||
|
||
3. **日程查看**
|
||
- 点击日期查看当天服务安排
|
||
- 显示服务时间、服务名称、状态
|
||
- 点击日程跳转到订单详情
|
||
|
||
4. **数据来源**
|
||
- 调用 `calendarApi.getAppointments()` 获取预约数据
|
||
- 调用 `calendarApi.getMonthlyStats()` 获取统计数据
|
||
- 调用 `calendarApi.getDailyServices()` 获取当天服务
|
||
|
||
### 2.3 未实现的功能 ❌
|
||
|
||
1. **打卡记录显示**
|
||
- ❌ 未显示签到时间和照片
|
||
- ❌ 未显示签退时间和照片
|
||
- ❌ 未显示服务时长
|
||
|
||
2. **服务过程记录**
|
||
- ❌ 未显示服务进度
|
||
- ❌ 未显示陪伴员位置
|
||
- ❌ 未显示服务照片
|
||
|
||
3. **服务反馈**
|
||
- ❌ 未显示陪伴员提交的服务反馈
|
||
- ❌ 未显示学生表现记录
|
||
|
||
---
|
||
|
||
## 三、订单详情页面现状
|
||
|
||
### 3.1 页面位置
|
||
- 路径: `order-package/pages/order/detail.vue`
|
||
|
||
### 3.2 已实现的功能 ✅
|
||
|
||
1. **订单基本信息**
|
||
- 订单状态
|
||
- 服务信息(服务名称、时间、时长)
|
||
- 陪伴员信息(姓名、电话)
|
||
- 学生信息(姓名、年级、联系电话)
|
||
- 订单信息(订单号、核销码、下单时间等)
|
||
- 费用明细
|
||
|
||
2. **操作功能**
|
||
- 取消订单(待支付状态)
|
||
- 立即支付(待支付状态)
|
||
- 联系客服
|
||
- 联系陪伴员
|
||
|
||
### 3.3 未实现的功能 ❌
|
||
|
||
1. **服务记录区域**
|
||
- ❌ 未显示打卡记录
|
||
- ❌ 未显示签到/签退照片
|
||
- ❌ 未显示服务时长
|
||
- ❌ 未显示服务地点
|
||
|
||
2. **服务反馈区域**
|
||
- ❌ 未显示陪伴员提交的服务反馈
|
||
- ❌ 未显示每日反馈内容
|
||
- ❌ 未显示反馈照片
|
||
|
||
3. **评价功能**
|
||
- ❌ 未显示"评价"按钮(订单完成后)
|
||
- ❌ 未实现评价表单
|
||
|
||
---
|
||
|
||
## 四、数据流向分析
|
||
|
||
### 4.1 日历页面数据流
|
||
|
||
```
|
||
家长打开日历页面
|
||
↓
|
||
调用 calendarApi.getAppointments(startDate, endDate)
|
||
↓
|
||
返回预约数据(订单基本信息)
|
||
↓
|
||
显示在日历上(日期标记)
|
||
↓
|
||
点击日期 → 显示当天服务列表
|
||
↓
|
||
点击服务 → 跳转到订单详情页面
|
||
```
|
||
|
||
**问题**:
|
||
- 日历API只返回订单基本信息,不包含打卡记录
|
||
- 订单详情页面也未显示打卡记录
|
||
|
||
### 4.2 订单详情页面数据流
|
||
|
||
```
|
||
家长打开订单详情
|
||
↓
|
||
调用 orderApi.getOrderDetail(orderId) 或 orderApi.getOrderDetailFull(orderId)
|
||
↓
|
||
返回订单详细信息
|
||
↓
|
||
显示订单基本信息、陪伴员信息、学生信息、费用明细
|
||
```
|
||
|
||
**问题**:
|
||
- 订单详情API可能未返回打卡记录
|
||
- 前端未实现打卡记录显示区域
|
||
|
||
---
|
||
|
||
## 五、需要实现的功能
|
||
|
||
### 5.1 后端接口增强
|
||
|
||
#### 1. 订单详情接口返回打卡记录
|
||
|
||
**接口**: `GET /api/order/detail-full/{id}`
|
||
|
||
**需要添加的数据**:
|
||
```java
|
||
// OrderController.getOrderDetailFull() 中添加
|
||
List<CheckInRecord> checkInRecords = checkInService.getByOrderId(orderId);
|
||
Map<String, Object> checkInData = new HashMap<>();
|
||
|
||
// 查找签到记录
|
||
CheckInRecord checkIn = checkInRecords.stream()
|
||
.filter(r -> "in".equals(r.getCheckType()) || "checkin".equals(r.getCheckType()))
|
||
.findFirst()
|
||
.orElse(null);
|
||
|
||
// 查找签退记录
|
||
CheckInRecord checkOut = checkInRecords.stream()
|
||
.filter(r -> "out".equals(r.getCheckType()) || "checkout".equals(r.getCheckType()))
|
||
.findFirst()
|
||
.orElse(null);
|
||
|
||
checkInData.put("checkIn", checkIn);
|
||
checkInData.put("checkOut", checkOut);
|
||
|
||
// 计算服务时长
|
||
if (checkIn != null && checkOut != null) {
|
||
long minutes = Duration.between(
|
||
checkIn.getCheckTime(),
|
||
checkOut.getCheckTime()
|
||
).toMinutes();
|
||
checkInData.put("duration", minutes);
|
||
checkInData.put("durationText", formatDuration(minutes));
|
||
}
|
||
|
||
orderDetail.put("checkInRecords", checkInData);
|
||
```
|
||
|
||
#### 2. 确保 check_in_record 表有 order_id 字段
|
||
|
||
```sql
|
||
-- 检查字段是否存在
|
||
SELECT COLUMN_NAME
|
||
FROM INFORMATION_SCHEMA.COLUMNS
|
||
WHERE TABLE_NAME = 'check_in_record'
|
||
AND COLUMN_NAME = 'order_id';
|
||
|
||
-- 如果不存在,添加字段
|
||
ALTER TABLE check_in_record
|
||
ADD COLUMN order_id BIGINT NULL COMMENT '订单ID' AFTER work_order_no,
|
||
ADD INDEX idx_order_id (order_id);
|
||
```
|
||
|
||
---
|
||
|
||
### 5.2 前端实现
|
||
|
||
#### 1. 订单详情页面添加服务记录区域
|
||
|
||
**位置**: `order-package/pages/order/detail.vue`
|
||
|
||
**添加内容**:
|
||
```vue
|
||
<!-- 服务记录 -->
|
||
<view class="service-record-section" v-if="checkInRecords">
|
||
<view class="section-title">服务记录</view>
|
||
|
||
<!-- 签到记录 -->
|
||
<view class="record-item" v-if="checkInRecords.checkIn">
|
||
<view class="record-header">
|
||
<text class="record-icon">✓</text>
|
||
<text class="record-title">签到</text>
|
||
<text class="record-time">{{ formatTime(checkInRecords.checkIn.checkTime) }}</text>
|
||
</view>
|
||
<view class="record-body">
|
||
<view class="record-info">
|
||
<text class="info-label">签到地点</text>
|
||
<text class="info-value">{{ checkInRecords.checkIn.address }}</text>
|
||
</view>
|
||
<view class="record-photo" v-if="checkInRecords.checkIn.photoUrl">
|
||
<image
|
||
:src="checkInRecords.checkIn.photoUrl"
|
||
mode="aspectFill"
|
||
@click="previewPhoto(checkInRecords.checkIn.photoUrl)"
|
||
/>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 签退记录 -->
|
||
<view class="record-item" v-if="checkInRecords.checkOut">
|
||
<view class="record-header">
|
||
<text class="record-icon">✓</text>
|
||
<text class="record-title">签退</text>
|
||
<text class="record-time">{{ formatTime(checkInRecords.checkOut.checkTime) }}</text>
|
||
</view>
|
||
<view class="record-body">
|
||
<view class="record-info">
|
||
<text class="info-label">签退地点</text>
|
||
<text class="info-value">{{ checkInRecords.checkOut.address }}</text>
|
||
</view>
|
||
<view class="record-photo" v-if="checkInRecords.checkOut.photoUrl">
|
||
<image
|
||
:src="checkInRecords.checkOut.photoUrl"
|
||
mode="aspectFill"
|
||
@click="previewPhoto(checkInRecords.checkOut.photoUrl)"
|
||
/>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 服务时长 -->
|
||
<view class="duration-info" v-if="checkInRecords.durationText">
|
||
<text class="duration-label">服务时长</text>
|
||
<text class="duration-value">{{ checkInRecords.durationText }}</text>
|
||
</view>
|
||
</view>
|
||
```
|
||
|
||
**添加方法**:
|
||
```javascript
|
||
methods: {
|
||
// 预览照片
|
||
previewPhoto(url) {
|
||
uni.previewImage({
|
||
urls: [url],
|
||
current: url
|
||
})
|
||
},
|
||
|
||
// 格式化时间
|
||
formatTime(time) {
|
||
if (!time) return ''
|
||
return time.substring(0, 16).replace('T', ' ')
|
||
}
|
||
}
|
||
```
|
||
|
||
**添加数据**:
|
||
```javascript
|
||
data() {
|
||
return {
|
||
order: {},
|
||
checkInRecords: null // 新增
|
||
}
|
||
},
|
||
|
||
async loadOrderDetail() {
|
||
const res = await api.orderApi.getOrderDetailFull(this.orderId)
|
||
if (res.code === 200) {
|
||
this.order = res.data
|
||
this.checkInRecords = res.data.checkInRecords // 新增
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### 2. 日历页面增强(可选)
|
||
|
||
**位置**: `user-package/pages/calendar/index.vue`
|
||
|
||
**可以添加**:
|
||
- 在日程详情中显示服务状态(已签到、已签退)
|
||
- 显示服务时长
|
||
- 添加"查看详情"按钮跳转到订单详情
|
||
|
||
---
|
||
|
||
## 六、实施步骤
|
||
|
||
### 第一步:数据库检查和修复
|
||
|
||
1. 检查 `check_in_record` 表是否有 `order_id` 字段
|
||
2. 如果没有,执行 SQL 添加字段
|
||
3. 检查现有打卡记录是否有 `order_id` 数据
|
||
|
||
### 第二步:后端接口增强
|
||
|
||
1. 修改 `OrderController.getOrderDetailFull()` 方法
|
||
2. 添加查询打卡记录的逻辑
|
||
3. 计算服务时长
|
||
4. 返回打卡记录数据
|
||
|
||
### 第三步:前端实现
|
||
|
||
1. 修改订单详情页面 `order-package/pages/order/detail.vue`
|
||
2. 添加服务记录显示区域
|
||
3. 实现照片预览功能
|
||
4. 测试功能
|
||
|
||
### 第四步:测试验证
|
||
|
||
1. 创建测试订单
|
||
2. 陪伴员签到签退
|
||
3. 家长查看订单详情
|
||
4. 验证打卡记录显示
|
||
5. 验证照片预览功能
|
||
|
||
---
|
||
|
||
## 七、总结
|
||
|
||
### 现状
|
||
|
||
✅ **家长端日历页面已实现**:
|
||
- 日历展示
|
||
- 统计信息
|
||
- 日程查看
|
||
- 跳转到订单详情
|
||
|
||
❌ **家长端日历页面未实现**:
|
||
- 打卡记录显示
|
||
- 服务时长显示
|
||
- 打卡照片显示
|
||
|
||
❌ **订单详情页面未实现**:
|
||
- 服务记录区域
|
||
- 打卡记录显示
|
||
- 打卡照片显示
|
||
- 服务时长显示
|
||
|
||
### 结论
|
||
|
||
**家长端日历页面本身不需要显示打卡记录**,它的作用是:
|
||
1. 展示服务日程安排
|
||
2. 提供统计信息
|
||
3. 作为入口跳转到订单详情
|
||
|
||
**真正需要显示打卡记录的是订单详情页面**,这才是家长查看服务记录的主要入口。
|
||
|
||
因此,原报告的结论是正确的:**家长端订单详情页面未实现查看服务记录(打卡照片、服务时长)功能**。
|
||
|
||
---
|
||
|
||
**报告完成时间**: 2026-01-23
|
||
**检查人**: AI助手
|
||
**下一步行动**: 按照实施步骤完成功能开发
|