问题: - 今日课程功能只查询了 lesson 表,没有 JOIN 关联表 - TeacherLessonVO 的 courseName 和 className 字段为 null - 前端无法显示课程名称和班级名称 修复: - LessonMapper 新增 selectTodayLessonsWithDetails() 方法 - 通过 LEFT JOIN course_package 和 clazz 表获取名称 - TeacherStatsServiceImpl 重写 getTodayLessons() 方法 - 添加类型转换辅助方法 (getLong/getString/getLocalDate/getLocalTime/getLocalDateTime) 影响范围: - 教师端首页 - 今日课程模块 - API: GET /api/v1/teacher/today-lessons - API: GET /api/v1/teacher/dashboard Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
304 lines
9.2 KiB
Markdown
304 lines
9.2 KiB
Markdown
# 学校端数据导出功能测试记录
|
||
|
||
**测试日期**: 2026-03-21
|
||
**测试人员**: Claude
|
||
**功能模块**: 学校端数据概览 - 数据导出
|
||
|
||
---
|
||
|
||
## 实现内容
|
||
|
||
### 后端实现
|
||
|
||
#### 1. 添加依赖
|
||
- 添加 `EasyExcel 3.3.4` 依赖到 `pom.xml`
|
||
|
||
#### 2. 新建文件
|
||
- `dto/response/LessonExportVO.java` - 授课记录导出 VO
|
||
- `dto/response/TeacherPerformanceExportVO.java` - 教师绩效导出 VO
|
||
- `dto/response/StudentStatExportVO.java` - 学生统计导出 VO
|
||
- `service/SchoolExportService.java` - 导出服务接口
|
||
- `service/impl/SchoolExportServiceImpl.java` - 导出服务实现
|
||
|
||
#### 3. 修改文件
|
||
- `mapper/LessonMapper.java` - 添加三个导出查询方法
|
||
- `controller/school/SchoolExportController.java` - 实现导出接口
|
||
|
||
### 前端实现
|
||
|
||
#### 修改文件
|
||
- `src/api/school.ts` - 增强导出函数,处理空数据时返回的 JSON 响应
|
||
|
||
---
|
||
|
||
## 测试步骤
|
||
|
||
### 后端测试
|
||
|
||
#### 1. 启动后端服务(端口 8481)
|
||
|
||
```bash
|
||
export JAVA_HOME="/f/Java/jdk-17"
|
||
export SERVER_PORT=8481
|
||
cd reading-platform-java
|
||
mvn spring-boot:run
|
||
```
|
||
|
||
#### 2. 使用 Swagger 测试接口
|
||
|
||
访问:http://localhost:8481/doc.html
|
||
|
||
测试以下接口:
|
||
- `GET /api/v1/school/export/lessons` - 授课记录导出
|
||
- `GET /api/v1/school/export/teacher-stats` - 教师绩效导出
|
||
- `GET /api/v1/school/export/student-stats` - 学生统计导出
|
||
|
||
#### 3. 验证空数据响应
|
||
|
||
当没有数据时,应返回 JSON:
|
||
```json
|
||
{
|
||
"code": 404,
|
||
"message": "指定时间范围内暂无授课记录",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 测试用例
|
||
|
||
### 用例 1:导出授课记录
|
||
|
||
**请求参数**:
|
||
- startDate: 2026-03-01
|
||
- endDate: 2026-03-21
|
||
|
||
**预期结果**:
|
||
- 成功:下载 Excel 文件,包含授课日期、授课时间、班级名称、教师姓名、课程名称、课程类型、学生人数、平均参与度、评价反馈
|
||
- 无数据:返回 JSON 响应 `{code: 404, message: "指定时间范围内暂无授课记录"}`
|
||
|
||
### 用例 2:导出教师绩效统计
|
||
|
||
**请求参数**:
|
||
- startDate: 2026-03-01
|
||
- endDate: 2026-03-21
|
||
|
||
**预期结果**:
|
||
- 成功:下载 Excel 文件,包含教师姓名、所属班级、授课次数、课程数量、活跃等级、最后活跃时间、平均参与度
|
||
- 无数据:返回 JSON 响应 `{code: 404, message: "指定时间范围内暂无教师绩效数据"}`
|
||
|
||
### 用例 3:导出学生统计
|
||
|
||
**请求参数**:
|
||
- classId: 可选
|
||
|
||
**预期结果**:
|
||
- 成功:下载 Excel 文件,包含学生姓名、性别、班级、授课次数、平均参与度、平均专注度
|
||
- 无数据:返回 JSON 响应 `{code: 404, message: "暂无学生统计数据"}`
|
||
|
||
---
|
||
|
||
## 前端测试
|
||
|
||
### 1. 启动前端服务(端口 5174)
|
||
|
||
```bash
|
||
export VITE_APP_PORT=5174
|
||
cd reading-platform-frontend
|
||
npm run dev
|
||
```
|
||
|
||
### 2. 访问学校端数据概览页面
|
||
|
||
访问:http://localhost:5174/school/dashboard
|
||
|
||
### 3. 测试导出功能
|
||
|
||
1. 点击"授课记录"导出按钮
|
||
2. 点击"教师绩效"导出按钮
|
||
3. 点击"学生统计"导出按钮
|
||
|
||
**预期结果**:
|
||
- 有数据时:自动下载 Excel 文件,提示"导出成功"
|
||
- 无数据时:提示"暂无数据"或相应错误消息
|
||
|
||
---
|
||
|
||
## 导出字段设计
|
||
|
||
### 授课记录导出 (LessonExportVO)
|
||
|
||
| Excel 列名 | 字段 | 类型 | 数据来源 |
|
||
|-----------|------|------|----------|
|
||
| 授课日期 | lessonDate | LocalDate | lesson.lesson_date |
|
||
| 授课时间 | timeRange | String | lesson.start_time ~ end_time |
|
||
| 班级名称 | className | String | clazz.name |
|
||
| 教师姓名 | teacherName | String | teacher.name |
|
||
| 课程名称 | courseName | String | course_package.name |
|
||
| 课程类型 | lessonType | String | lesson.lesson_type |
|
||
| 学生人数 | studentCount | Integer | student_record count |
|
||
| 平均参与度 | avgParticipation | Double | avg(student_record.participation) |
|
||
| 评价反馈 | feedbackContent | String | lesson_feedback.content |
|
||
|
||
### 教师绩效导出 (TeacherPerformanceExportVO)
|
||
|
||
| Excel 列名 | 字段 | 类型 | 数据来源 |
|
||
|-----------|------|------|----------|
|
||
| 教师姓名 | teacherName | String | teacher.name |
|
||
| 所属班级 | classNames | String | GROUP_CONCAT(clazz.name) |
|
||
| 授课次数 | lessonCount | Integer | COUNT(lesson.id) |
|
||
| 课程数量 | courseCount | Integer | COUNT(DISTINCT course_id) |
|
||
| 活跃等级 | activityLevel | String | CASE WHEN |
|
||
| 最后活跃时间 | lastActiveAt | LocalDateTime | MAX(end_datetime) |
|
||
| 平均参与度 | avgParticipation | Double | AVG(participation) |
|
||
|
||
### 学生统计导出 (StudentStatExportVO)
|
||
|
||
| Excel 列名 | 字段 | 类型 | 数据来源 |
|
||
|-----------|------|------|----------|
|
||
| 学生姓名 | studentName | String | student.name |
|
||
| 性别 | gender | String | student.gender |
|
||
| 班级 | className | String | clazz.name |
|
||
| 授课次数 | lessonCount | Integer | COUNT(lesson.id) |
|
||
| 平均参与度 | avgParticipation | Double | AVG(participation) |
|
||
| 平均专注度 | avgFocus | Double | AVG(focus) |
|
||
|
||
---
|
||
|
||
## 注意事项
|
||
|
||
1. **日期范围处理**:前端传入日期字符串,后端解析为 LocalDate
|
||
2. **文件名编码**:中文文件名使用 URLEncoder 编码
|
||
3. **空数据处理**:没有数据时返回 JSON 响应,不生成 Excel 文件
|
||
4. **Content-Type 判断**:前端需要判断响应头,区分 Excel 和 JSON 响应
|
||
5. **权限验证**:通过 `@RequireRole(UserRole.SCHOOL)` 确保只导出当前租户数据
|
||
|
||
---
|
||
|
||
## 待办事项
|
||
|
||
- [ ] 后端服务启动验证
|
||
- [ ] Swagger 接口测试
|
||
- [ ] 前端页面功能测试
|
||
- [ ] 空数据场景测试
|
||
- [ ] 大数据量导出性能测试
|
||
|
||
---
|
||
|
||
## 测试结果
|
||
|
||
| 测试项 | 状态 | 备注 |
|
||
|--------|------|------|
|
||
| 编译通过 | ✅ | 后端编译成功 |
|
||
| 授课记录导出 | ✅ | HTTP 200,生成 Excel 文件 (5.6KB, 39 条记录) |
|
||
| 教师绩效导出 | ✅ | HTTP 200,生成 Excel 文件 (4.1KB, 10 条记录) |
|
||
| 学生统计导出 | ✅ | HTTP 200,生成 Excel 文件 |
|
||
| 空数据处理 | ✅ | 返回 JSON `{code: 404, message: "指定时间范围内暂无授课记录"}` |
|
||
| 前端服务 | ✅ | 端口 5174 正常运行 |
|
||
|
||
---
|
||
|
||
## 问题修复
|
||
|
||
### 修复 1: 授课记录日期时间为空
|
||
|
||
**问题**: 授课日期和授课时间字段在 Excel 中显示为空
|
||
|
||
**原因**:
|
||
1. SQL 返回的 Map 使用下划线命名 (`lesson_date`),但 Java 代码获取驼峰命名 (`lessonDate`)
|
||
2. SQL 返回的是 `java.sql.Date` 和 `java.sql.Time` 类型,不能直接转换为 `LocalDate` 和 `LocalTime`
|
||
|
||
**解决**:
|
||
```java
|
||
// 日期转换
|
||
Object dateObj = row.get("lesson_date");
|
||
if (dateObj instanceof java.sql.Date) {
|
||
vo.setLessonDate(((java.sql.Date) dateObj).toLocalDate());
|
||
}
|
||
|
||
// 时间转换
|
||
Object startTimeObj = row.get("start_time");
|
||
if (startTimeObj instanceof java.sql.Time) {
|
||
vo.setTimeRange(((java.sql.Time) startTimeObj).toLocalTime().format(TIME_FORMATTER) + ...);
|
||
}
|
||
```
|
||
|
||
### 修复 2: 教师绩效活跃等级未翻译
|
||
|
||
**问题**: Excel 中活跃等级显示为 `HIGH`/`MEDIUM`/`LOW`/`INACTIVE` 英文代码
|
||
|
||
**解决**: 添加翻译方法 `translateActivityLevel()`:
|
||
```java
|
||
private String translateActivityLevel(String code) {
|
||
switch (code) {
|
||
case "HIGH": return "高";
|
||
case "MEDIUM": return "中";
|
||
case "LOW": return "低";
|
||
case "INACTIVE": return "未活跃";
|
||
default: return code;
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 测试详情
|
||
|
||
### 后端接口测试结果
|
||
|
||
**测试时间**: 2026-03-21
|
||
|
||
#### 1. 授课记录导出
|
||
- **接口**: `GET /api/v1/school/export/lessons?startDate=2026-03-01&endDate=2026-03-21`
|
||
- **状态**: ✅ 通过
|
||
- **响应**: HTTP 200,Microsoft Excel 2007+ 文件格式
|
||
- **包含字段**: 授课日期、授课时间、班级名称、教师姓名、课程名称、状态、学生人数、平均参与度、备注
|
||
|
||
#### 2. 教师绩效导出
|
||
- **接口**: `GET /api/v1/school/export/teacher-stats?startDate=2026-03-01&endDate=2026-03-21`
|
||
- **状态**: ✅ 通过
|
||
- **响应**: HTTP 200,Microsoft Excel 2007+ 文件格式
|
||
- **包含字段**: 教师姓名、所属班级、授课次数、课程数量、活跃等级、最后活跃时间、平均参与度
|
||
|
||
#### 3. 学生统计导出
|
||
- **接口**: `GET /api/v1/school/export/student-stats`
|
||
- **状态**: ✅ 通过
|
||
- **响应**: HTTP 200,Microsoft Excel 2007+ 文件格式
|
||
- **包含字段**: 学生姓名、性别、年级、授课次数、平均参与度、平均专注度
|
||
|
||
#### 4. 空数据处理测试
|
||
- **接口**: `GET /api/v1/school/export/lessons?startDate=2020-01-01&endDate=2020-01-07`
|
||
- **状态**: ✅ 通过
|
||
- **响应**: `{"code":404,"message":"指定时间范围内暂无授课记录"}`
|
||
|
||
---
|
||
|
||
## 修复记录
|
||
|
||
1. **修复 lesson_type 字段不存在问题**
|
||
- 问题:`lesson` 表没有 `lesson_type` 字段
|
||
- 解决:移除 SQL 中的 `l.lesson_type`,改用 `l.status` 和 `l.notes`
|
||
|
||
2. **修复 student 表 class_id 字段不存在问题**
|
||
- 问题:`student` 表没有 `class_id` 字段
|
||
- 解决:改用 `s.grade` 作为 `className` 显示
|
||
|
||
---
|
||
|
||
## 前端测试
|
||
|
||
### 访问地址
|
||
- 前端:http://localhost:5174
|
||
- 后端:http://localhost:8481
|
||
- 登录账号:school1 / 123456
|
||
|
||
### 测试步骤
|
||
1. 访问 http://localhost:5174/login 登录学校账号
|
||
2. 进入"数据概览"页面
|
||
3. 点击"授课记录"、"教师绩效"、"学生统计"导出按钮
|
||
|
||
### 预期结果
|
||
- 有数据时:自动下载 Excel 文件,message 提示"导出成功"
|
||
- 无数据时:message 提示"暂无数据"
|