667 lines
19 KiB
Markdown
667 lines
19 KiB
Markdown
|
|
# 学习记录功能完善 - 问题分析与解决方案
|
|||
|
|
|
|||
|
|
## 📊 现状分析
|
|||
|
|
|
|||
|
|
### 1. 现有功能
|
|||
|
|
- ✅ **成长记录功能**(已完成)
|
|||
|
|
- 位置:`/user-package/pages/growth/list.vue`
|
|||
|
|
- 功能:陪伴员填写的每日/周/月反馈
|
|||
|
|
- 数据来源:`growth_record` 表
|
|||
|
|
- 接口:`/api/growth-record/*`
|
|||
|
|
|
|||
|
|
- ⚠️ **学习记录功能**(数据来源不明确)
|
|||
|
|
- 位置:`/user-package/pages/user/learning-record.vue`
|
|||
|
|
- 功能:学习记录列表和详情
|
|||
|
|
- 数据来源:**未明确**
|
|||
|
|
- 接口:`/api/record/*`(**接口不存在**)
|
|||
|
|
|
|||
|
|
### 2. 核心问题
|
|||
|
|
|
|||
|
|
#### 问题1:功能重复
|
|||
|
|
- **成长记录** 和 **学习记录** 本质上是同一个功能
|
|||
|
|
- 两个页面展示相同的数据(陪伴员填写的服务记录)
|
|||
|
|
- 造成用户困惑和维护成本增加
|
|||
|
|
|
|||
|
|
#### 问题2:API不存在
|
|||
|
|
```javascript
|
|||
|
|
// learning-record.vue 调用的API
|
|||
|
|
recordApi.getRecordList() // ❌ /api/record/list 不存在
|
|||
|
|
recordApi.getRecordDetail() // ❌ /api/record/detail/:id 不存在
|
|||
|
|
recordApi.getStats() // ❌ /api/record/stats 不存在
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 问题3:数据关联不清晰
|
|||
|
|
- 学习记录应该来自成长记录
|
|||
|
|
- 但代码中没有明确的关联关系
|
|||
|
|
- 导致数据显示不一致
|
|||
|
|
|
|||
|
|
## 🎯 解决方案
|
|||
|
|
|
|||
|
|
### 方案A:统一为成长记录(推荐)✅
|
|||
|
|
|
|||
|
|
**核心思路**:将"学习记录"功能合并到"成长记录",统一入口和数据源
|
|||
|
|
|
|||
|
|
#### 优点
|
|||
|
|
- ✅ 功能统一,用户体验更好
|
|||
|
|
- ✅ 减少维护成本
|
|||
|
|
- ✅ 数据来源明确
|
|||
|
|
- ✅ 已有完整的后端支持
|
|||
|
|
|
|||
|
|
#### 实施步骤
|
|||
|
|
|
|||
|
|
**1. 更新用户中心入口**
|
|||
|
|
```vue
|
|||
|
|
<!-- 将"学习记录"改为"成长记录" -->
|
|||
|
|
<view class="menu-item" @click="goPage('/user-package/pages/growth/list')">
|
|||
|
|
<text class="menu-icon">📚</text>
|
|||
|
|
<text>成长记录</text>
|
|||
|
|
<text class="arrow">></text>
|
|||
|
|
</view>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**2. 删除冗余页面**
|
|||
|
|
- 删除 `learning-record.vue`
|
|||
|
|
- 删除 `learning-record-detail.vue`
|
|||
|
|
- 删除 `recordApi` 相关代码
|
|||
|
|
|
|||
|
|
**3. 完善成长记录功能**
|
|||
|
|
- 添加统计数据展示
|
|||
|
|
- 优化列表和详情页面
|
|||
|
|
- 确保包含所有必要信息
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 方案B:保留两个功能,明确区分
|
|||
|
|
|
|||
|
|
**核心思路**:明确区分两个功能的用途
|
|||
|
|
|
|||
|
|
#### 功能定位
|
|||
|
|
- **成长记录**:陪伴员填写的专业反馈(每日/周/月)
|
|||
|
|
- **学习记录**:家长视角的服务记录汇总
|
|||
|
|
|
|||
|
|
#### 实施步骤
|
|||
|
|
|
|||
|
|
**1. 创建学习记录后端接口**
|
|||
|
|
```java
|
|||
|
|
@RestController
|
|||
|
|
@RequestMapping("/api/record")
|
|||
|
|
public class LearningRecordController {
|
|||
|
|
|
|||
|
|
// 获取学习记录列表(基于成长记录)
|
|||
|
|
@GetMapping("/list")
|
|||
|
|
public Result<Page<LearningRecordVO>> getList(
|
|||
|
|
@RequestParam Long studentId,
|
|||
|
|
@RequestParam(required = false) String period,
|
|||
|
|
@RequestParam(defaultValue = "1") Integer page,
|
|||
|
|
@RequestParam(defaultValue = "10") Integer size
|
|||
|
|
) {
|
|||
|
|
// 从 growth_record 表查询数据
|
|||
|
|
// 转换为学习记录格式
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取学习统计
|
|||
|
|
@GetMapping("/stats")
|
|||
|
|
public Result<LearningStatsVO> getStats(@RequestParam Long studentId) {
|
|||
|
|
// 统计总学习时长、次数、平均评分等
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**2. 数据转换逻辑**
|
|||
|
|
```java
|
|||
|
|
// 将成长记录转换为学习记录
|
|||
|
|
LearningRecordVO vo = new LearningRecordVO();
|
|||
|
|
vo.setId(growthRecord.getId());
|
|||
|
|
vo.setServiceDate(growthRecord.getRecordDate());
|
|||
|
|
vo.setContent(growthRecord.getContent());
|
|||
|
|
vo.setTeacherName(teacher.getName());
|
|||
|
|
vo.setStudentName(student.getName());
|
|||
|
|
|
|||
|
|
// 从签到记录获取服务时长
|
|||
|
|
CheckInRecord checkIn = getCheckInByOrderId(growthRecord.getOrderId());
|
|||
|
|
vo.setDuration(calculateDuration(checkIn));
|
|||
|
|
|
|||
|
|
// 从评价获取评分
|
|||
|
|
Review review = getReviewByOrderId(growthRecord.getOrderId());
|
|||
|
|
vo.setRating(review != null ? review.getRating() : null);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 📋 推荐方案详细实施
|
|||
|
|
|
|||
|
|
### 采用方案A:统一为成长记录
|
|||
|
|
|
|||
|
|
#### 第一步:更新前端路由和入口
|
|||
|
|
|
|||
|
|
**1. 修改用户中心入口**
|
|||
|
|
|
|||
|
|
文件位置:`peidu/uniapp/src/pages/user/index.vue`
|
|||
|
|
|
|||
|
|
```vue
|
|||
|
|
<!-- 修改前 -->
|
|||
|
|
<view class="menu-item" @click="goPage('/user-package/pages/user/learning-record')">
|
|||
|
|
<text class="menu-icon">📚</text>
|
|||
|
|
<text>学习记录</text>
|
|||
|
|
<text class="arrow">></text>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 修改后 -->
|
|||
|
|
<view class="menu-item" @click="goPage('/user-package/pages/growth/list')">
|
|||
|
|
<text class="menu-icon">📚</text>
|
|||
|
|
<text>成长记录</text>
|
|||
|
|
<text class="arrow">></text>
|
|||
|
|
</view>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**2. 更新pages.json配置**
|
|||
|
|
|
|||
|
|
删除学习记录相关页面配置:
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"path": "pages/user/learning-record",
|
|||
|
|
"style": {
|
|||
|
|
"navigationBarTitleText": "学习记录"
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"path": "pages/user/learning-record-detail",
|
|||
|
|
"style": {
|
|||
|
|
"navigationBarTitleText": "记录详情"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 第二步:完善成长记录功能
|
|||
|
|
|
|||
|
|
**1. 添加统计数据展示**
|
|||
|
|
|
|||
|
|
修改 `peidu/uniapp/src/user-package/pages/growth/list.vue`:
|
|||
|
|
|
|||
|
|
```vue
|
|||
|
|
<template>
|
|||
|
|
<view class="growth-page">
|
|||
|
|
<!-- 新增:统计卡片 -->
|
|||
|
|
<view class="stats-card">
|
|||
|
|
<view class="stat-item">
|
|||
|
|
<text class="stat-value">{{ stats.totalHours }}</text>
|
|||
|
|
<text class="stat-label">累计学习(小时)</text>
|
|||
|
|
</view>
|
|||
|
|
<view class="stat-divider"></view>
|
|||
|
|
<view class="stat-item">
|
|||
|
|
<text class="stat-value">{{ stats.totalSessions }}</text>
|
|||
|
|
<text class="stat-label">服务次数</text>
|
|||
|
|
</view>
|
|||
|
|
<view class="stat-divider"></view>
|
|||
|
|
<view class="stat-item">
|
|||
|
|
<text class="stat-value">{{ stats.avgScore }}</text>
|
|||
|
|
<text class="stat-label">平均评分</text>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 原有内容保持不变 -->
|
|||
|
|
...
|
|||
|
|
</view>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
export default {
|
|||
|
|
data() {
|
|||
|
|
return {
|
|||
|
|
// 新增统计数据
|
|||
|
|
stats: {
|
|||
|
|
totalHours: '0',
|
|||
|
|
totalSessions: 0,
|
|||
|
|
avgScore: '0'
|
|||
|
|
},
|
|||
|
|
// ... 其他数据
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
onLoad(options) {
|
|||
|
|
this.studentId = options.studentId || this.getDefaultStudentId()
|
|||
|
|
this.loadStats() // 新增:加载统计数据
|
|||
|
|
this.loadRecordList()
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
methods: {
|
|||
|
|
// 新增:加载统计数据
|
|||
|
|
async loadStats() {
|
|||
|
|
try {
|
|||
|
|
const res = await request.get('/api/growth-record/parent/stats', {
|
|||
|
|
studentId: this.studentId
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
if (res.code === 200 && res.data) {
|
|||
|
|
this.stats = {
|
|||
|
|
totalHours: res.data.totalHours || '0',
|
|||
|
|
totalSessions: res.data.totalSessions || 0,
|
|||
|
|
avgScore: res.data.avgScore || '0'
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
} catch (e) {
|
|||
|
|
console.error('加载统计数据失败:', e)
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// ... 其他方法
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style lang="scss" scoped>
|
|||
|
|
// 新增:统计卡片样式
|
|||
|
|
.stats-card {
|
|||
|
|
background: linear-gradient(135deg, #2d9687 0%, #3da896 100%);
|
|||
|
|
padding: 40rpx 30rpx;
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: space-around;
|
|||
|
|
align-items: center;
|
|||
|
|
|
|||
|
|
.stat-item {
|
|||
|
|
flex: 1;
|
|||
|
|
text-align: center;
|
|||
|
|
|
|||
|
|
.stat-value {
|
|||
|
|
display: block;
|
|||
|
|
font-size: 48rpx;
|
|||
|
|
font-weight: bold;
|
|||
|
|
color: #fff;
|
|||
|
|
margin-bottom: 12rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.stat-label {
|
|||
|
|
display: block;
|
|||
|
|
font-size: 24rpx;
|
|||
|
|
color: rgba(255, 255, 255, 0.9);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.stat-divider {
|
|||
|
|
width: 2rpx;
|
|||
|
|
height: 60rpx;
|
|||
|
|
background: rgba(255, 255, 255, 0.3);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ... 其他样式
|
|||
|
|
</style>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**2. 完善详情页面信息**
|
|||
|
|
|
|||
|
|
修改 `peidu/uniapp/src/user-package/pages/growth/detail.vue`,确保包含:
|
|||
|
|
- ✅ 服务时间、时长
|
|||
|
|
- ✅ 学习内容
|
|||
|
|
- ✅ 陪伴员评价
|
|||
|
|
- ✅ 照片记录
|
|||
|
|
- ✅ 学生表现
|
|||
|
|
- ✅ 视频记录(如果有)
|
|||
|
|
|
|||
|
|
#### 第三步:创建后端统计接口
|
|||
|
|
|
|||
|
|
**文件位置**:`peidu/backend/src/main/java/com/peidu/controller/GrowthRecordController.java`
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
/**
|
|||
|
|
* 获取家长端统计数据
|
|||
|
|
*/
|
|||
|
|
@ApiOperation("获取家长端统计数据")
|
|||
|
|
@GetMapping("/parent/stats")
|
|||
|
|
public Result<Map<String, Object>> getParentStats(
|
|||
|
|
@RequestParam Long studentId,
|
|||
|
|
HttpServletRequest request) {
|
|||
|
|
try {
|
|||
|
|
log.info("获取家长端统计数据: studentId={}", studentId);
|
|||
|
|
|
|||
|
|
// 查询该学生的所有成长记录
|
|||
|
|
QueryWrapper<GrowthRecord> wrapper = new QueryWrapper<>();
|
|||
|
|
wrapper.eq("student_id", studentId)
|
|||
|
|
.eq("record_type", "daily")
|
|||
|
|
.orderByDesc("record_date");
|
|||
|
|
|
|||
|
|
List<GrowthRecord> records = growthRecordService.list(wrapper);
|
|||
|
|
|
|||
|
|
// 统计数据
|
|||
|
|
int totalMinutes = 0;
|
|||
|
|
int totalSessions = records.size();
|
|||
|
|
double totalRating = 0;
|
|||
|
|
int ratingCount = 0;
|
|||
|
|
|
|||
|
|
for (GrowthRecord record : records) {
|
|||
|
|
// 计算服务时长
|
|||
|
|
if (record.getOrderId() != null) {
|
|||
|
|
Order order = orderService.getById(record.getOrderId());
|
|||
|
|
if (order != null) {
|
|||
|
|
// 从签到记录获取实际服务时长
|
|||
|
|
QueryWrapper<CheckInRecord> checkInWrapper = new QueryWrapper<>();
|
|||
|
|
checkInWrapper.eq("order_id", record.getOrderId())
|
|||
|
|
.orderByAsc("check_time");
|
|||
|
|
List<CheckInRecord> checkInRecords = checkInRecordMapper.selectList(checkInWrapper);
|
|||
|
|
|
|||
|
|
LocalDateTime checkInTime = null;
|
|||
|
|
LocalDateTime checkOutTime = null;
|
|||
|
|
|
|||
|
|
for (CheckInRecord checkRecord : checkInRecords) {
|
|||
|
|
if ("checkin".equals(checkRecord.getCheckType()) && checkInTime == null) {
|
|||
|
|
checkInTime = checkRecord.getCheckTime();
|
|||
|
|
} else if ("checkout".equals(checkRecord.getCheckType())) {
|
|||
|
|
checkOutTime = checkRecord.getCheckTime();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (checkInTime != null && checkOutTime != null) {
|
|||
|
|
Duration duration = Duration.between(checkInTime, checkOutTime);
|
|||
|
|
totalMinutes += (int) duration.toMinutes();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取评分
|
|||
|
|
QueryWrapper<Review> reviewWrapper = new QueryWrapper<>();
|
|||
|
|
reviewWrapper.eq("order_id", record.getOrderId());
|
|||
|
|
Review review = reviewMapper.selectOne(reviewWrapper);
|
|||
|
|
if (review != null && review.getRating() != null) {
|
|||
|
|
totalRating += review.getRating();
|
|||
|
|
ratingCount++;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 构建返回数据
|
|||
|
|
Map<String, Object> stats = new HashMap<>();
|
|||
|
|
stats.put("totalHours", String.format("%.1f", totalMinutes / 60.0));
|
|||
|
|
stats.put("totalSessions", totalSessions);
|
|||
|
|
stats.put("avgScore", ratingCount > 0 ?
|
|||
|
|
String.format("%.1f", totalRating / ratingCount) : "0");
|
|||
|
|
|
|||
|
|
log.info("统计结果: {}", stats);
|
|||
|
|
return Result.success(stats);
|
|||
|
|
} catch (Exception e) {
|
|||
|
|
log.error("获取统计数据失败", e);
|
|||
|
|
return Result.error(e.getMessage());
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取家长端成长记录列表
|
|||
|
|
*/
|
|||
|
|
@ApiOperation("获取家长端成长记录列表")
|
|||
|
|
@GetMapping("/parent/list")
|
|||
|
|
public Result<Page<GrowthRecordVO>> getParentList(
|
|||
|
|
@RequestParam Long studentId,
|
|||
|
|
@RequestParam(required = false) String recordType,
|
|||
|
|
@RequestParam(defaultValue = "1") Integer page,
|
|||
|
|
@RequestParam(defaultValue = "10") Integer size) {
|
|||
|
|
try {
|
|||
|
|
log.info("获取家长端成长记录列表: studentId={}, recordType={}, page={}, size={}",
|
|||
|
|
studentId, recordType, page, size);
|
|||
|
|
|
|||
|
|
Page<GrowthRecord> pageParam = new Page<>(page, size);
|
|||
|
|
QueryWrapper<GrowthRecord> wrapper = new QueryWrapper<>();
|
|||
|
|
wrapper.eq("student_id", studentId);
|
|||
|
|
|
|||
|
|
if (recordType != null && !"all".equals(recordType)) {
|
|||
|
|
wrapper.eq("record_type", recordType);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
wrapper.orderByDesc("record_date");
|
|||
|
|
|
|||
|
|
Page<GrowthRecord> recordPage = growthRecordService.page(pageParam, wrapper);
|
|||
|
|
|
|||
|
|
// 转换为VO
|
|||
|
|
Page<GrowthRecordVO> voPage = new Page<>();
|
|||
|
|
voPage.setCurrent(recordPage.getCurrent());
|
|||
|
|
voPage.setSize(recordPage.getSize());
|
|||
|
|
voPage.setTotal(recordPage.getTotal());
|
|||
|
|
|
|||
|
|
List<GrowthRecordVO> voList = new ArrayList<>();
|
|||
|
|
for (GrowthRecord record : recordPage.getRecords()) {
|
|||
|
|
GrowthRecordVO vo = convertToVO(record);
|
|||
|
|
voList.add(vo);
|
|||
|
|
}
|
|||
|
|
voPage.setRecords(voList);
|
|||
|
|
|
|||
|
|
log.info("查询成功,共{}条记录", voPage.getTotal());
|
|||
|
|
return Result.success(voPage);
|
|||
|
|
} catch (Exception e) {
|
|||
|
|
log.error("获取家长端成长记录列表失败", e);
|
|||
|
|
return Result.error(e.getMessage());
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 转换为VO对象
|
|||
|
|
*/
|
|||
|
|
private GrowthRecordVO convertToVO(GrowthRecord record) {
|
|||
|
|
GrowthRecordVO vo = new GrowthRecordVO();
|
|||
|
|
vo.setId(record.getId());
|
|||
|
|
vo.setRecordDate(record.getRecordDate());
|
|||
|
|
vo.setRecordType(record.getRecordType());
|
|||
|
|
vo.setContent(record.getContent());
|
|||
|
|
vo.setImageList(record.getImageList());
|
|||
|
|
vo.setVideoList(record.getVideoList());
|
|||
|
|
|
|||
|
|
// 设置类型名称
|
|||
|
|
String typeName = "每日反馈";
|
|||
|
|
if ("weekly".equals(record.getRecordType())) {
|
|||
|
|
typeName = "周反馈";
|
|||
|
|
} else if ("monthly".equals(record.getRecordType())) {
|
|||
|
|
typeName = "月反馈";
|
|||
|
|
}
|
|||
|
|
vo.setRecordTypeName(typeName);
|
|||
|
|
|
|||
|
|
// 获取学生信息
|
|||
|
|
if (record.getStudentId() != null) {
|
|||
|
|
Student student = studentMapper.selectById(record.getStudentId());
|
|||
|
|
if (student != null) {
|
|||
|
|
vo.setStudentName(student.getName());
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取教师信息
|
|||
|
|
if (record.getTeacherId() != null) {
|
|||
|
|
Teacher teacher = teacherMapper.selectById(record.getTeacherId());
|
|||
|
|
if (teacher != null) {
|
|||
|
|
vo.setTeacherName(teacher.getName());
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取服务时长
|
|||
|
|
if (record.getOrderId() != null) {
|
|||
|
|
QueryWrapper<CheckInRecord> checkInWrapper = new QueryWrapper<>();
|
|||
|
|
checkInWrapper.eq("order_id", record.getOrderId())
|
|||
|
|
.orderByAsc("check_time");
|
|||
|
|
List<CheckInRecord> checkInRecords = checkInRecordMapper.selectList(checkInWrapper);
|
|||
|
|
|
|||
|
|
LocalDateTime checkInTime = null;
|
|||
|
|
LocalDateTime checkOutTime = null;
|
|||
|
|
|
|||
|
|
for (CheckInRecord checkRecord : checkInRecords) {
|
|||
|
|
if ("checkin".equals(checkRecord.getCheckType()) && checkInTime == null) {
|
|||
|
|
checkInTime = checkRecord.getCheckTime();
|
|||
|
|
} else if ("checkout".equals(checkRecord.getCheckType())) {
|
|||
|
|
checkOutTime = checkRecord.getCheckTime();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (checkInTime != null && checkOutTime != null) {
|
|||
|
|
Duration duration = Duration.between(checkInTime, checkOutTime);
|
|||
|
|
int minutes = (int) duration.toMinutes();
|
|||
|
|
int hours = minutes / 60;
|
|||
|
|
int mins = minutes % 60;
|
|||
|
|
vo.setDurationText(hours > 0 ?
|
|||
|
|
String.format("%d小时%d分钟", hours, mins) :
|
|||
|
|
String.format("%d分钟", mins));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return vo;
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**需要添加的依赖注入**:
|
|||
|
|
```java
|
|||
|
|
@Autowired
|
|||
|
|
private StudentMapper studentMapper;
|
|||
|
|
|
|||
|
|
@Autowired
|
|||
|
|
private TeacherMapper teacherMapper;
|
|||
|
|
|
|||
|
|
@Autowired
|
|||
|
|
private ReviewMapper reviewMapper;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 第四步:更新VO类
|
|||
|
|
|
|||
|
|
**文件位置**:`peidu/backend/src/main/java/com/peidu/vo/GrowthRecordVO.java`
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
/**
|
|||
|
|
* 成长记录VO
|
|||
|
|
*/
|
|||
|
|
@Data
|
|||
|
|
public class GrowthRecordVO {
|
|||
|
|
private Long id;
|
|||
|
|
private Long orderId;
|
|||
|
|
private Long studentId;
|
|||
|
|
private String studentName; // 新增
|
|||
|
|
private Long teacherId;
|
|||
|
|
private String teacherName; // 新增
|
|||
|
|
private LocalDate recordDate;
|
|||
|
|
private String recordType;
|
|||
|
|
private String recordTypeName; // 新增:类型名称
|
|||
|
|
private String content;
|
|||
|
|
private String imageList;
|
|||
|
|
private String videoList;
|
|||
|
|
private String durationText; // 新增:服务时长文本
|
|||
|
|
private LocalDateTime createTime;
|
|||
|
|
private LocalDateTime updateTime;
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 第五步:清理冗余代码
|
|||
|
|
|
|||
|
|
**1. 删除文件**
|
|||
|
|
```bash
|
|||
|
|
# 删除学习记录页面
|
|||
|
|
peidu/uniapp/src/user-package/pages/user/learning-record.vue
|
|||
|
|
peidu/uniapp/src/user-package/pages/user/learning-record-detail.vue
|
|||
|
|
|
|||
|
|
# 如果存在旧版本,也一并删除
|
|||
|
|
peidu/uniapp/user-package/pages/user/learning-record.vue
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**2. 清理API定义**
|
|||
|
|
|
|||
|
|
修改 `peidu/uniapp/src/api/index.js`,删除recordApi:
|
|||
|
|
```javascript
|
|||
|
|
// 删除这部分代码
|
|||
|
|
export const recordApi = {
|
|||
|
|
getRecordList(params) {
|
|||
|
|
return request.get('/api/record/list', { params })
|
|||
|
|
},
|
|||
|
|
getRecordDetail(id) {
|
|||
|
|
return request.get(`/api/record/detail/${id}`)
|
|||
|
|
},
|
|||
|
|
getStats() {
|
|||
|
|
return request.get('/api/record/stats')
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 📝 数据关联说明
|
|||
|
|
|
|||
|
|
### 成长记录包含的完整信息
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
成长记录 (growth_record)
|
|||
|
|
├── 基础信息
|
|||
|
|
│ ├── 服务日期 (record_date)
|
|||
|
|
│ ├── 记录类型 (record_type: daily/weekly/monthly)
|
|||
|
|
│ └── 创建时间 (create_time)
|
|||
|
|
│
|
|||
|
|
├── 关联信息
|
|||
|
|
│ ├── 订单ID (order_id) → 关联订单表
|
|||
|
|
│ ├── 学生ID (student_id) → 关联学生表
|
|||
|
|
│ └── 教师ID (teacher_id) → 关联教师表
|
|||
|
|
│
|
|||
|
|
├── 内容信息
|
|||
|
|
│ ├── 学习内容 (content)
|
|||
|
|
│ ├── 照片列表 (image_list)
|
|||
|
|
│ ├── 视频列表 (video_list)
|
|||
|
|
│ └── 周/月总结 (summary)
|
|||
|
|
│
|
|||
|
|
└── 扩展信息(通过关联获取)
|
|||
|
|
├── 服务时长 → 从 check_in_record 表计算
|
|||
|
|
├── 学生姓名 → 从 student 表获取
|
|||
|
|
├── 教师姓名 → 从 teacher 表获取
|
|||
|
|
└── 评价评分 → 从 review 表获取
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 数据流转图
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
陪伴员填写成长记录
|
|||
|
|
↓
|
|||
|
|
保存到 growth_record 表
|
|||
|
|
↓
|
|||
|
|
家长端查看成长记录
|
|||
|
|
↓
|
|||
|
|
展示完整信息:
|
|||
|
|
- 基础信息(日期、内容、照片)
|
|||
|
|
- 服务时长(从签到记录计算)
|
|||
|
|
- 评价评分(从评价表获取)
|
|||
|
|
- 学生/教师信息(从关联表获取)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## ✅ 实施检查清单
|
|||
|
|
|
|||
|
|
### 前端修改
|
|||
|
|
- [ ] 修改用户中心入口(user/index.vue)
|
|||
|
|
- [ ] 完善成长记录列表页(growth/list.vue)
|
|||
|
|
- [ ] 添加统计卡片
|
|||
|
|
- [ ] 调用统计接口
|
|||
|
|
- [ ] 确认详情页信息完整(growth/detail.vue)
|
|||
|
|
- [ ] 删除学习记录页面文件
|
|||
|
|
- [ ] 清理recordApi定义
|
|||
|
|
- [ ] 更新pages.json配置
|
|||
|
|
|
|||
|
|
### 后端修改
|
|||
|
|
- [ ] 添加家长端统计接口
|
|||
|
|
- [ ] 添加家长端列表接口
|
|||
|
|
- [ ] 完善GrowthRecordVO类
|
|||
|
|
- [ ] 添加必要的Mapper注入
|
|||
|
|
- [ ] 测试接口返回数据
|
|||
|
|
|
|||
|
|
### 测试验证
|
|||
|
|
- [ ] 用户中心入口跳转正确
|
|||
|
|
- [ ] 统计数据显示正确
|
|||
|
|
- [ ] 列表数据加载正常
|
|||
|
|
- [ ] 详情页信息完整
|
|||
|
|
- [ ] 服务时长计算准确
|
|||
|
|
- [ ] 评分显示正确
|
|||
|
|
|
|||
|
|
## 🎉 预期效果
|
|||
|
|
|
|||
|
|
完成后,家长端将拥有统一的"成长记录"功能:
|
|||
|
|
|
|||
|
|
1. **统计概览**
|
|||
|
|
- 累计学习时长
|
|||
|
|
- 服务次数
|
|||
|
|
- 平均评分
|
|||
|
|
|
|||
|
|
2. **记录列表**
|
|||
|
|
- 每日反馈
|
|||
|
|
- 周反馈
|
|||
|
|
- 月反馈
|
|||
|
|
|
|||
|
|
3. **详细信息**
|
|||
|
|
- 服务时间、时长
|
|||
|
|
- 学习内容
|
|||
|
|
- 陪伴员评价
|
|||
|
|
- 照片/视频记录
|
|||
|
|
- 学生表现
|
|||
|
|
|
|||
|
|
4. **数据来源清晰**
|
|||
|
|
- 所有数据来自 `growth_record` 表
|
|||
|
|
- 通过关联表获取完整信息
|
|||
|
|
- 数据一致性有保障
|