feat: 添加课程包课程列表查询API
- 新增 GET /api/v1/school/packages/{packageId}/courses 接口
- 返回课程包详情,包含课程列表和排课计划参考数据
- 更新开发日志和变更日志
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
2e3143affb
commit
d3cf4fd43b
@ -6,6 +6,30 @@
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### 排课计划参考功能 ✅ (2026-03-17 下午)
|
||||||
|
|
||||||
|
**添加了课程包排课计划参考数据的返回和显示功能:**
|
||||||
|
|
||||||
|
**问题背景**:
|
||||||
|
- 学校老师需要排课计划参考作为指引
|
||||||
|
- 课程包下有导入课、集体课、五大领域课,需要告诉老师如何安排才能发挥最大价值
|
||||||
|
|
||||||
|
**后端实现**:
|
||||||
|
- `CoursePackageResponse.CoursePackageCourseItem` 添加 `scheduleRefData` 和 `lessonType` 字段
|
||||||
|
- `CoursePackageService.toResponse()` 填充 `scheduleRefData` 和 `lessonType`
|
||||||
|
- `CourseCollectionService.toPackageResponse()` 重写以包含课程列表和排课计划参考
|
||||||
|
- 添加必要的 mapper 依赖注入
|
||||||
|
|
||||||
|
**前端实现**:
|
||||||
|
- `school.ts` `CoursePackage` 接口添加 `scheduleRefData` 字段
|
||||||
|
- `CreateScheduleModal.vue` 优化 `selectPackage()` 方法,直接从响应数据中提取排课计划参考
|
||||||
|
|
||||||
|
**API验证**:`GET /api/v1/school/packages/5/packages` 返回包含 `courses` 数组的完整响应
|
||||||
|
|
||||||
|
**Git提交**: `commit 9f89ce7`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### 排课功能两层结构重构完成 ✅ (2026-03-17)
|
### 排课功能两层结构重构完成 ✅ (2026-03-17)
|
||||||
|
|
||||||
**实现了课程套餐→课程包→课程的两层结构架构:**
|
**实现了课程套餐→课程包→课程的两层结构架构:**
|
||||||
|
|||||||
@ -224,3 +224,162 @@ mvn clean compile -DskipTests
|
|||||||
| AdminPackageController | ✅ 已规范 |
|
| AdminPackageController | ✅ 已规范 |
|
||||||
| AdminThemeController | ✅ 已规范 |
|
| AdminThemeController | ✅ 已规范 |
|
||||||
| AdminSettingsController | 🟡 可选(设置类接口允许使用 Map) |
|
| AdminSettingsController | 🟡 可选(设置类接口允许使用 Map) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 排课计划参考功能实现
|
||||||
|
|
||||||
|
### 背景
|
||||||
|
|
||||||
|
学校端排课功能需要显示排课计划参考数据,帮助老师了解课程包下的课程安排建议。用户说明:"因为我们一个套餐是一个课程体系,在这个课程体系下,有多个课程包,每个课程包下,有导入课、集体课、五大领域课,我们提供的排课计划参考是为了给学校老师指引,告诉他们课程包下的这三类课如何上,才能发挥最大的价值。"
|
||||||
|
|
||||||
|
### 新建排课流程
|
||||||
|
|
||||||
|
1. 选择课程套餐 → 选择课程包 → 显示排课计划参考
|
||||||
|
2. 单选课程类型(导入课/集体课/五大领域课)
|
||||||
|
3. 选择班级 → 指定授课教师
|
||||||
|
4. 设置授课时间
|
||||||
|
|
||||||
|
### 后端修改
|
||||||
|
|
||||||
|
#### 1. CoursePackageResponse.java
|
||||||
|
|
||||||
|
**文件路径**: `reading-platform-java/src/main/java/com/reading/platform/dto/response/CoursePackageResponse.java`
|
||||||
|
|
||||||
|
**修改内容**: 在 `CoursePackageCourseItem` 内部类中添加 `scheduleRefData` 和 `lessonType` 字段
|
||||||
|
|
||||||
|
```java
|
||||||
|
@Schema(description = "排课计划参考数据(JSON)")
|
||||||
|
private String scheduleRefData;
|
||||||
|
|
||||||
|
@Schema(description = "课程类型")
|
||||||
|
private String lessonType;
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. CoursePackageService.java
|
||||||
|
|
||||||
|
**文件路径**: `reading-platform-java/src/main/java/com/reading/platform/service/CoursePackageService.java`
|
||||||
|
|
||||||
|
**修改内容**: 修改 `toResponse()` 方法,填充 `scheduleRefData` 和 `lessonType`
|
||||||
|
|
||||||
|
```java
|
||||||
|
if (course != null) {
|
||||||
|
item.setId(course.getId());
|
||||||
|
item.setName(course.getName());
|
||||||
|
item.setScheduleRefData(course.getScheduleRefData());
|
||||||
|
item.setLessonType(course.getLessonType());
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. CourseCollectionService.java
|
||||||
|
|
||||||
|
**文件路径**: `reading-platform-java/src/main/java/com/reading/platform/service/CourseCollectionService.java`
|
||||||
|
|
||||||
|
**修改内容**:
|
||||||
|
- 添加依赖注入:`CoursePackageCourseMapper`, `CourseMapper`
|
||||||
|
- 添加导入:`Course`, `CoursePackageCourse`
|
||||||
|
- 完全重写 `toPackageResponse()` 方法,包含课程列表查询逻辑
|
||||||
|
|
||||||
|
```java
|
||||||
|
private CoursePackageResponse toPackageResponse(CoursePackage pkg) {
|
||||||
|
// 查询课程包关联的课程
|
||||||
|
List<CoursePackageCourse> packageCourses = packageCourseMapper.selectList(
|
||||||
|
new LambdaQueryWrapper<CoursePackageCourse>()
|
||||||
|
.eq(CoursePackageCourse::getPackageId, pkg.getId())
|
||||||
|
.orderByAsc(CoursePackageCourse::getSortOrder)
|
||||||
|
);
|
||||||
|
|
||||||
|
List<CoursePackageResponse.CoursePackageCourseItem> courseItems = ...;
|
||||||
|
// 构建 courseItems 列表,包含 scheduleRefData
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 前端修改
|
||||||
|
|
||||||
|
#### 1. school.ts
|
||||||
|
|
||||||
|
**文件路径**: `reading-platform-frontend/src/api/school.ts`
|
||||||
|
|
||||||
|
**修改内容**: 在 `CoursePackage` 接口的 `courses` 数组项中添加 `scheduleRefData` 字段
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
courses?: Array<{
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
gradeLevel: string;
|
||||||
|
sortOrder: number;
|
||||||
|
scheduleRefData?: string; // 新增字段
|
||||||
|
}>;
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. CreateScheduleModal.vue
|
||||||
|
|
||||||
|
**文件路径**: `reading-platform-frontend/src/views/school/schedule/components/CreateScheduleModal.vue`
|
||||||
|
|
||||||
|
**修改内容**: 优化 `selectPackage()` 方法,直接从响应数据中提取排课计划参考
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const selectPackage = async (packageId: number) => {
|
||||||
|
formData.packageId = packageId;
|
||||||
|
formData.courseId = undefined;
|
||||||
|
|
||||||
|
// 加载排课计划参考(从选中的课程包中获取)
|
||||||
|
if (selectedCollection.value?.packages) {
|
||||||
|
const selectedPkg = selectedCollection.value.packages.find((p: any) => p.id === packageId);
|
||||||
|
if (selectedPkg?.courses && selectedPkg.courses.length > 0) {
|
||||||
|
const firstCourse = selectedPkg.courses[0];
|
||||||
|
if (firstCourse.scheduleRefData) {
|
||||||
|
try {
|
||||||
|
const parsedData = JSON.parse(firstCourse.scheduleRefData);
|
||||||
|
scheduleRefData.value = Array.isArray(parsedData) ? parsedData : [];
|
||||||
|
} catch (e) {
|
||||||
|
scheduleRefData.value = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await loadLessonTypes(packageId);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### API 验证
|
||||||
|
|
||||||
|
**请求**:
|
||||||
|
```
|
||||||
|
GET /api/v1/school/packages/5/packages
|
||||||
|
Authorization: Bearer {token}
|
||||||
|
```
|
||||||
|
|
||||||
|
**响应**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"data": [{
|
||||||
|
"id": "5",
|
||||||
|
"name": "完整阅读能力培养套餐",
|
||||||
|
"courses": [
|
||||||
|
{
|
||||||
|
"id": "6",
|
||||||
|
"name": "小猪佩奇绘本阅读",
|
||||||
|
"gradeLevel": "小班",
|
||||||
|
"sortOrder": 1,
|
||||||
|
"scheduleRefData": null,
|
||||||
|
"lessonType": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 下一步工作
|
||||||
|
|
||||||
|
1. 在数据库中添加示例排课计划参考数据(`course.schedule_ref_data` 字段)
|
||||||
|
2. 考虑添加 `collectionId` 存储(需要数据库迁移和 DTO 更新)
|
||||||
|
|
||||||
|
### Git 提交
|
||||||
|
|
||||||
|
```
|
||||||
|
commit 9f89ce7
|
||||||
|
feat: 添加课程包排课计划参考数据返回
|
||||||
|
```
|
||||||
|
|||||||
@ -48,6 +48,13 @@ public class SchoolPackageController {
|
|||||||
return Result.success(collectionService.getPackagesByCollection(collectionId));
|
return Result.success(collectionService.getPackagesByCollection(collectionId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/packages/{packageId}/courses")
|
||||||
|
@Operation(summary = "获取课程包下的课程列表(包含排课计划参考)")
|
||||||
|
@RequireRole(UserRole.SCHOOL)
|
||||||
|
public Result<CoursePackageResponse> getPackageCourses(@PathVariable Long packageId) {
|
||||||
|
return Result.success(packageService.findOnePackage(packageId));
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/legacy")
|
@GetMapping("/legacy")
|
||||||
@Operation(summary = "查询租户套餐(旧版API,已废弃)")
|
@Operation(summary = "查询租户套餐(旧版API,已废弃)")
|
||||||
@Deprecated
|
@Deprecated
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user