Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
c85a3fd195
@ -6,6 +6,65 @@
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### 排课计划参考示例数据添加 ✅ (2026-03-18)
|
||||||
|
|
||||||
|
**添加了课程排课计划参考示例数据:**
|
||||||
|
|
||||||
|
**数据库迁移**:
|
||||||
|
- Flyway 迁移脚本:`V29__add_schedule_ref_data.sql`
|
||||||
|
- 为小猪佩奇绘本阅读、好饿的毛毛虫、三只小猪等课程添加排课计划参考
|
||||||
|
|
||||||
|
**数据内容**:
|
||||||
|
- 导入课:课程导入,激发兴趣(每周1次,连续2周)
|
||||||
|
- 集体课:集体教学活动(每周2次,连续4周)
|
||||||
|
- 五大领域课:语言、社会、科学、艺术、健康领域活动
|
||||||
|
|
||||||
|
**数据结构**:
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"lessonType": "INTRODUCTION",
|
||||||
|
"title": "导入课",
|
||||||
|
"suggestedOrder": 1,
|
||||||
|
"durationMinutes": 15,
|
||||||
|
"frequency": "每周1次,连续2周",
|
||||||
|
"keyPoints": ["展示绘本封面,引导观察"],
|
||||||
|
"tips": "建议配合实物教具或多媒体资源"
|
||||||
|
},
|
||||||
|
...
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
**后端 API**:
|
||||||
|
- 新增 `GET /api/v1/school/packages/{packageId}/courses` 获取课程包课程列表
|
||||||
|
- Git 提交:`commit 4072b21`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 排课计划参考功能 ✅ (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: 添加课程包排课计划参考数据返回
|
||||||
|
```
|
||||||
|
|||||||
82
docs/dev-logs/2026-03-18.md
Normal file
82
docs/dev-logs/2026-03-18.md
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
# 开发日志 - 2026-03-18
|
||||||
|
|
||||||
|
## 完成事项
|
||||||
|
|
||||||
|
### 1. 提交昨天的变更代码
|
||||||
|
|
||||||
|
**提交内容**:
|
||||||
|
- `SchoolPackageController.java` - 新增 `GET /api/v1/school/packages/{packageId}/courses` 接口
|
||||||
|
- 文档更新(CHANGELOG.md, dev-logs/2026-03-17.md)
|
||||||
|
|
||||||
|
**Git 提交**:
|
||||||
|
```
|
||||||
|
commit 4072b21
|
||||||
|
feat: 添加课程包课程列表查询API
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 添加排课计划参考示例数据
|
||||||
|
|
||||||
|
**Flyway 迁移脚本**:`V29__add_schedule_ref_data.sql`
|
||||||
|
|
||||||
|
**为以下课程添加了排课计划参考数据**:
|
||||||
|
|
||||||
|
#### 小猪佩奇绘本阅读
|
||||||
|
- 导入课:通过图片、视频等形式导入课程主题
|
||||||
|
- 集体课:全班集体参与的教学活动
|
||||||
|
- 五大领域课:语言、社会、科学、艺术、健康
|
||||||
|
|
||||||
|
#### 好饿的毛毛虫
|
||||||
|
- 导入课:通过毛毛虫玩偶导入课程,激发好奇心
|
||||||
|
- 集体课:绘本共读,了解毛毛虫的成长过程
|
||||||
|
- 五大领域课:各领域活动安排
|
||||||
|
|
||||||
|
#### 三只小猪
|
||||||
|
- 导入课:通过小猪玩偶和房子图片导入课程主题
|
||||||
|
- 集体课:绘本共读,理解故事情节和寓意
|
||||||
|
- 五大领域课:各领域活动安排
|
||||||
|
|
||||||
|
**排课计划参考数据结构**:
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"lessonType": "INTRODUCTION",
|
||||||
|
"title": "导入课",
|
||||||
|
"description": "...",
|
||||||
|
"suggestedOrder": 1,
|
||||||
|
"durationMinutes": 15,
|
||||||
|
"frequency": "每周1次,连续2周",
|
||||||
|
"keyPoints": ["..."],
|
||||||
|
"tips": "..."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"lessonType": "COLLECTIVE",
|
||||||
|
"title": "集体课",
|
||||||
|
"description": "...",
|
||||||
|
"suggestedOrder": 2,
|
||||||
|
"durationMinutes": 25,
|
||||||
|
"frequency": "每周2次,连续4周",
|
||||||
|
"keyPoints": ["..."],
|
||||||
|
"tips": "..."
|
||||||
|
},
|
||||||
|
// ... 五大领域课
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 排课计划参考功能说明
|
||||||
|
|
||||||
|
**功能目的**:
|
||||||
|
帮助学校老师了解课程包下的三类课程(导入课、集体课、五大领域课)如何安排才能发挥最大价值。
|
||||||
|
|
||||||
|
**数据位置**:
|
||||||
|
- 数据库:`course.schedule_ref_data` 字段(JSON 格式)
|
||||||
|
- 实体类:`Course.scheduleRefData`
|
||||||
|
- 响应 DTO:`CoursePackageResponse.CoursePackageCourseItem.scheduleRefData`
|
||||||
|
|
||||||
|
**前端显示**:
|
||||||
|
学校端排课功能中,选择课程包后会自动显示该课程包的排课计划参考,帮助老师了解课程安排建议。
|
||||||
|
|
||||||
|
### 后续工作
|
||||||
|
|
||||||
|
- [ ] 考虑添加 `collectionId` 存储(需要数据库迁移和 DTO 更新)
|
||||||
|
|
||||||
|
---
|
||||||
@ -301,6 +301,7 @@ export interface CoursePackage {
|
|||||||
name: string;
|
name: string;
|
||||||
gradeLevel: string;
|
gradeLevel: string;
|
||||||
sortOrder: number;
|
sortOrder: number;
|
||||||
|
scheduleRefData?: string;
|
||||||
}>;
|
}>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -405,7 +405,29 @@ const handleCollectionChange = async (collectionId: number) => {
|
|||||||
const selectPackage = async (packageId: number) => {
|
const selectPackage = async (packageId: number) => {
|
||||||
formData.packageId = packageId;
|
formData.packageId = packageId;
|
||||||
formData.courseId = undefined;
|
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 : [];
|
||||||
|
console.log('✅ 排课计划参考数据:', scheduleRefData.value);
|
||||||
|
} catch (e) {
|
||||||
|
console.error('解析排课数据失败:', e);
|
||||||
scheduleRefData.value = [];
|
scheduleRefData.value = [];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
scheduleRefData.value = [];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
scheduleRefData.value = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 加载课程类型列表
|
// 加载课程类型列表
|
||||||
await loadLessonTypes(packageId);
|
await loadLessonTypes(packageId);
|
||||||
@ -414,31 +436,6 @@ const selectPackage = async (packageId: number) => {
|
|||||||
// 选择课程
|
// 选择课程
|
||||||
const selectCourse = (courseId: number) => {
|
const selectCourse = (courseId: number) => {
|
||||||
formData.courseId = courseId;
|
formData.courseId = courseId;
|
||||||
// 加载该课程的排课计划参考
|
|
||||||
loadScheduleRefData(courseId);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 加载排课计划参考数据
|
|
||||||
const loadScheduleRefData = async (courseId: number) => {
|
|
||||||
try {
|
|
||||||
// TODO: 调用获取课程详情的API
|
|
||||||
// const course = await getCourseDetail(courseId);
|
|
||||||
// if (course?.scheduleRefData) {
|
|
||||||
// try {
|
|
||||||
// const parsedData = JSON.parse(course.scheduleRefData);
|
|
||||||
// scheduleRefData.value = Array.isArray(parsedData) ? parsedData : [];
|
|
||||||
// } catch (e) {
|
|
||||||
// console.error('Failed to parse scheduleRefData:', e);
|
|
||||||
// scheduleRefData.value = [];
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// scheduleRefData.value = [];
|
|
||||||
// }
|
|
||||||
scheduleRefData.value = [];
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Failed to load course detail:', error);
|
|
||||||
scheduleRefData.value = [];
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 加载课程类型列表
|
// 加载课程类型列表
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -98,5 +98,11 @@ public class CoursePackageResponse {
|
|||||||
|
|
||||||
@Schema(description = "排序号")
|
@Schema(description = "排序号")
|
||||||
private Integer sortOrder;
|
private Integer sortOrder;
|
||||||
|
|
||||||
|
@Schema(description = "排课计划参考数据(JSON)")
|
||||||
|
private String scheduleRefData;
|
||||||
|
|
||||||
|
@Schema(description = "课程类型")
|
||||||
|
private String lessonType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,12 +8,16 @@ import com.reading.platform.common.enums.TenantPackageStatus;
|
|||||||
import com.reading.platform.common.response.PageResult;
|
import com.reading.platform.common.response.PageResult;
|
||||||
import com.reading.platform.dto.response.CourseCollectionResponse;
|
import com.reading.platform.dto.response.CourseCollectionResponse;
|
||||||
import com.reading.platform.dto.response.CoursePackageResponse;
|
import com.reading.platform.dto.response.CoursePackageResponse;
|
||||||
|
import com.reading.platform.entity.Course;
|
||||||
import com.reading.platform.entity.CourseCollection;
|
import com.reading.platform.entity.CourseCollection;
|
||||||
import com.reading.platform.entity.CourseCollectionPackage;
|
import com.reading.platform.entity.CourseCollectionPackage;
|
||||||
import com.reading.platform.entity.CoursePackage;
|
import com.reading.platform.entity.CoursePackage;
|
||||||
|
import com.reading.platform.entity.CoursePackageCourse;
|
||||||
import com.reading.platform.entity.TenantPackage;
|
import com.reading.platform.entity.TenantPackage;
|
||||||
import com.reading.platform.mapper.CourseCollectionMapper;
|
import com.reading.platform.mapper.CourseCollectionMapper;
|
||||||
import com.reading.platform.mapper.CourseCollectionPackageMapper;
|
import com.reading.platform.mapper.CourseCollectionPackageMapper;
|
||||||
|
import com.reading.platform.mapper.CourseMapper;
|
||||||
|
import com.reading.platform.mapper.CoursePackageCourseMapper;
|
||||||
import com.reading.platform.mapper.CoursePackageMapper;
|
import com.reading.platform.mapper.CoursePackageMapper;
|
||||||
import com.reading.platform.mapper.TenantPackageMapper;
|
import com.reading.platform.mapper.TenantPackageMapper;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@ -39,6 +43,8 @@ public class CourseCollectionService extends ServiceImpl<CourseCollectionMapper,
|
|||||||
private final CourseCollectionPackageMapper collectionPackageMapper;
|
private final CourseCollectionPackageMapper collectionPackageMapper;
|
||||||
private final CoursePackageMapper packageMapper;
|
private final CoursePackageMapper packageMapper;
|
||||||
private final TenantPackageMapper tenantPackageMapper;
|
private final TenantPackageMapper tenantPackageMapper;
|
||||||
|
private final CoursePackageCourseMapper packageCourseMapper;
|
||||||
|
private final CourseMapper courseMapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询租户的课程套餐列表
|
* 查询租户的课程套餐列表
|
||||||
@ -323,9 +329,46 @@ public class CourseCollectionService extends ServiceImpl<CourseCollectionMapper,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 转换为课程包响应对象(简化版)
|
* 转换为课程包响应对象(包含课程列表和排课计划参考)
|
||||||
*/
|
*/
|
||||||
private CoursePackageResponse toPackageResponse(CoursePackage pkg) {
|
private CoursePackageResponse toPackageResponse(CoursePackage pkg) {
|
||||||
|
// 解析 gradeLevels
|
||||||
|
String[] gradeLevelsArray = new String[0];
|
||||||
|
if (pkg.getGradeLevels() != null && !pkg.getGradeLevels().isEmpty()) {
|
||||||
|
try {
|
||||||
|
gradeLevelsArray = pkg.getGradeLevels().split(",");
|
||||||
|
} catch (Exception e) {
|
||||||
|
gradeLevelsArray = new String[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<CoursePackageResponse.CoursePackageCourseItem> courseItems = new ArrayList<>();
|
||||||
|
|
||||||
|
// 查询课程包关联的课程
|
||||||
|
List<CoursePackageCourse> packageCourses = packageCourseMapper.selectList(
|
||||||
|
new LambdaQueryWrapper<CoursePackageCourse>()
|
||||||
|
.eq(CoursePackageCourse::getPackageId, pkg.getId())
|
||||||
|
.orderByAsc(CoursePackageCourse::getSortOrder)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!packageCourses.isEmpty()) {
|
||||||
|
courseItems = packageCourses.stream()
|
||||||
|
.map(pkc -> {
|
||||||
|
CoursePackageResponse.CoursePackageCourseItem item = new CoursePackageResponse.CoursePackageCourseItem();
|
||||||
|
// 从 CoursePackageCourse 获取课程信息
|
||||||
|
Course course = courseMapper.selectById(pkc.getCourseId());
|
||||||
|
if (course != null) {
|
||||||
|
item.setId(course.getId());
|
||||||
|
item.setName(course.getName());
|
||||||
|
item.setScheduleRefData(course.getScheduleRefData());
|
||||||
|
}
|
||||||
|
item.setGradeLevel(pkc.getGradeLevel());
|
||||||
|
item.setSortOrder(pkc.getSortOrder());
|
||||||
|
return item;
|
||||||
|
})
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
return CoursePackageResponse.builder()
|
return CoursePackageResponse.builder()
|
||||||
.id(pkg.getId())
|
.id(pkg.getId())
|
||||||
.name(pkg.getName())
|
.name(pkg.getName())
|
||||||
@ -333,7 +376,7 @@ public class CourseCollectionService extends ServiceImpl<CourseCollectionMapper,
|
|||||||
.price(pkg.getPrice())
|
.price(pkg.getPrice())
|
||||||
.discountPrice(pkg.getDiscountPrice())
|
.discountPrice(pkg.getDiscountPrice())
|
||||||
.discountType(pkg.getDiscountType())
|
.discountType(pkg.getDiscountType())
|
||||||
.gradeLevels(pkg.getGradeLevels() != null ? pkg.getGradeLevels().split(",") : new String[0])
|
.gradeLevels(gradeLevelsArray)
|
||||||
.courseCount(pkg.getCourseCount())
|
.courseCount(pkg.getCourseCount())
|
||||||
.status(pkg.getStatus())
|
.status(pkg.getStatus())
|
||||||
.submittedAt(pkg.getSubmittedAt())
|
.submittedAt(pkg.getSubmittedAt())
|
||||||
@ -344,6 +387,7 @@ public class CourseCollectionService extends ServiceImpl<CourseCollectionMapper,
|
|||||||
.publishedAt(pkg.getPublishedAt())
|
.publishedAt(pkg.getPublishedAt())
|
||||||
.createdAt(pkg.getCreatedAt())
|
.createdAt(pkg.getCreatedAt())
|
||||||
.updatedAt(pkg.getUpdatedAt())
|
.updatedAt(pkg.getUpdatedAt())
|
||||||
|
.courses(courseItems)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -153,6 +153,7 @@ public class CoursePackageService extends ServiceImpl<CoursePackageMapper, Cours
|
|||||||
item.setName(course.getName());
|
item.setName(course.getName());
|
||||||
item.setGradeLevel(pkc.getGradeLevel());
|
item.setGradeLevel(pkc.getGradeLevel());
|
||||||
item.setSortOrder(pkc.getSortOrder());
|
item.setSortOrder(pkc.getSortOrder());
|
||||||
|
item.setScheduleRefData(course.getScheduleRefData());
|
||||||
return item;
|
return item;
|
||||||
})
|
})
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
|
|||||||
@ -0,0 +1,341 @@
|
|||||||
|
-- =====================================================
|
||||||
|
-- 添加排课计划参考示例数据
|
||||||
|
-- 版本: V29
|
||||||
|
-- 创建时间: 2026-03-18
|
||||||
|
-- 描述: 为课程添加排课计划参考数据,帮助学校老师了解课程包下的
|
||||||
|
-- 导入课、集体课、五大领域课的排课安排建议
|
||||||
|
-- =====================================================
|
||||||
|
|
||||||
|
-- 排课计划参考数据说明:
|
||||||
|
-- 根据用户需求,课程体系下有多个课程包,每个课程包包含:
|
||||||
|
-- 1. 导入课 (INTRODUCTION) - 课程导入,激发兴趣
|
||||||
|
-- 2. 集体课 (COLLECTIVE) - 集体教学活动
|
||||||
|
-- 3. 五大领域课 - LANGUAGE(语言)、SOCIETY(社会)、SCIENCE(科学)、ART(艺术)、HEALTH(健康)
|
||||||
|
|
||||||
|
-- 为小猪佩奇绘本阅读课程添加排课计划参考
|
||||||
|
UPDATE `course` SET `schedule_ref_data` = '[
|
||||||
|
{
|
||||||
|
"lessonType": "INTRODUCTION",
|
||||||
|
"title": "导入课",
|
||||||
|
"description": "通过图片、视频等形式导入课程主题,激发幼儿学习兴趣",
|
||||||
|
"suggestedOrder": 1,
|
||||||
|
"durationMinutes": 15,
|
||||||
|
"frequency": "每周1次,连续2周",
|
||||||
|
"keyPoints": [
|
||||||
|
"展示绘本封面,引导观察",
|
||||||
|
"提出开放性问题激发兴趣",
|
||||||
|
"介绍课程主题和学习目标"
|
||||||
|
],
|
||||||
|
"tips": "建议配合实物教具或多媒体资源,增强视觉效果"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"lessonType": "COLLECTIVE",
|
||||||
|
"title": "集体课",
|
||||||
|
"description": "全班集体参与的教学活动,培养集体意识和协作能力",
|
||||||
|
"suggestedOrder": 2,
|
||||||
|
"durationMinutes": 25,
|
||||||
|
"frequency": "每周2次,连续4周",
|
||||||
|
"keyPoints": [
|
||||||
|
"绘本共读,教师引导讲解",
|
||||||
|
"互动问答,鼓励幼儿表达",
|
||||||
|
"角色扮演或情景模拟",
|
||||||
|
"总结分享,巩固学习成果"
|
||||||
|
],
|
||||||
|
"tips": "注重全体参与,关注个别差异,给予每个幼儿表达机会"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"lessonType": "LANGUAGE",
|
||||||
|
"title": "语言领域活动",
|
||||||
|
"description": "语言表达能力训练,丰富词汇量",
|
||||||
|
"suggestedOrder": 3,
|
||||||
|
"durationMinutes": 20,
|
||||||
|
"frequency": "每周2次",
|
||||||
|
"keyPoints": [
|
||||||
|
"词汇学习与巩固",
|
||||||
|
"句型练习与对话",
|
||||||
|
"故事复述与创编",
|
||||||
|
"语言游戏活动"
|
||||||
|
],
|
||||||
|
"tips": "创设语言环境,鼓励大胆表达,及时给予正面反馈"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"lessonType": "SOCIETY",
|
||||||
|
"title": "社会领域活动",
|
||||||
|
"description": "培养社会交往能力和情感认知",
|
||||||
|
"suggestedOrder": 4,
|
||||||
|
"durationMinutes": 20,
|
||||||
|
"frequency": "每周1次",
|
||||||
|
"keyPoints": [
|
||||||
|
"情感认知与表达",
|
||||||
|
"社交技能培养",
|
||||||
|
"规则意识建立",
|
||||||
|
"团队合作活动"
|
||||||
|
],
|
||||||
|
"tips": "结合生活实际,引导幼儿体验和反思"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"lessonType": "SCIENCE",
|
||||||
|
"title": "科学领域活动",
|
||||||
|
"description": "科学探究与认知能力培养",
|
||||||
|
"suggestedOrder": 5,
|
||||||
|
"durationMinutes": 20,
|
||||||
|
"frequency": "每周1次",
|
||||||
|
"keyPoints": [
|
||||||
|
"观察与发现",
|
||||||
|
"探究与实验",
|
||||||
|
"分类与比较",
|
||||||
|
"记录与分享"
|
||||||
|
],
|
||||||
|
"tips": "提供丰富材料,鼓励动手操作,培养科学思维"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"lessonType": "ART",
|
||||||
|
"title": "艺术领域活动",
|
||||||
|
"description": "艺术表现与审美能力培养",
|
||||||
|
"suggestedOrder": 6,
|
||||||
|
"durationMinutes": 25,
|
||||||
|
"frequency": "每周1次",
|
||||||
|
"keyPoints": [
|
||||||
|
"欣赏与感受",
|
||||||
|
"创作与表现",
|
||||||
|
"分享与评价",
|
||||||
|
"作品展示活动"
|
||||||
|
],
|
||||||
|
"tips": "尊重幼儿创意,提供多样化材料,鼓励自由表达"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"lessonType": "HEALTH",
|
||||||
|
"title": "健康领域活动",
|
||||||
|
"description": "身体运动与健康生活习惯培养",
|
||||||
|
"suggestedOrder": 7,
|
||||||
|
"durationMinutes": 20,
|
||||||
|
"frequency": "每周1次",
|
||||||
|
"keyPoints": [
|
||||||
|
"身体协调训练",
|
||||||
|
"生活习惯养成",
|
||||||
|
"安全意识教育",
|
||||||
|
"情绪管理学习"
|
||||||
|
],
|
||||||
|
"tips": "结合游戏活动,注重趣味性和参与度"
|
||||||
|
}
|
||||||
|
]' WHERE `name` = '小猪佩奇绘本阅读';
|
||||||
|
|
||||||
|
-- 为好饿的毛毛虫课程添加排课计划参考
|
||||||
|
UPDATE `course` SET `schedule_ref_data` = '[
|
||||||
|
{
|
||||||
|
"lessonType": "INTRODUCTION",
|
||||||
|
"title": "导入课",
|
||||||
|
"description": "通过毛毛虫玩偶导入课程,激发幼儿对生命成长的好奇",
|
||||||
|
"suggestedOrder": 1,
|
||||||
|
"durationMinutes": 15,
|
||||||
|
"frequency": "每周1次,连续2周",
|
||||||
|
"keyPoints": [
|
||||||
|
"出示毛毛虫玩偶,激发兴趣",
|
||||||
|
"提问关于毛毛虫的问题",
|
||||||
|
"介绍成长的概念"
|
||||||
|
],
|
||||||
|
"tips": "准备真实的毛毛虫或蝴蝶标本,增强直观感受"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"lessonType": "COLLECTIVE",
|
||||||
|
"title": "集体课",
|
||||||
|
"description": "绘本共读,了解毛毛虫的成长过程",
|
||||||
|
"suggestedOrder": 2,
|
||||||
|
"durationMinutes": 25,
|
||||||
|
"frequency": "每周2次,连续4周",
|
||||||
|
"keyPoints": [
|
||||||
|
"完整讲述绘本故事",
|
||||||
|
"讨论每天吃的东西",
|
||||||
|
"数数练习(1-5)",
|
||||||
|
"认识星期概念"
|
||||||
|
],
|
||||||
|
"tips": "使用日历教具,帮助幼儿理解时间概念"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"lessonType": "LANGUAGE",
|
||||||
|
"title": "语言领域活动",
|
||||||
|
"description": "词汇扩展与句型练习",
|
||||||
|
"suggestedOrder": 3,
|
||||||
|
"durationMinutes": 20,
|
||||||
|
"frequency": "每周2次",
|
||||||
|
"keyPoints": [
|
||||||
|
"食物词汇学习",
|
||||||
|
"星期词汇学习",
|
||||||
|
"简单句型练习",
|
||||||
|
"故事复述"
|
||||||
|
],
|
||||||
|
"tips": "使用闪卡和实物,增加词汇学习的趣味性"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"lessonType": "SOCIETY",
|
||||||
|
"title": "社会领域活动",
|
||||||
|
"description": "生命教育与情感认知",
|
||||||
|
"suggestedOrder": 4,
|
||||||
|
"durationMinutes": 20,
|
||||||
|
"frequency": "每周1次",
|
||||||
|
"keyPoints": [
|
||||||
|
"认识生命成长过程",
|
||||||
|
"分享自己的成长经历",
|
||||||
|
"关爱生命教育",
|
||||||
|
"分享与合作"
|
||||||
|
],
|
||||||
|
"tips": "邀请家长分享幼儿成长照片,增强情感连接"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"lessonType": "SCIENCE",
|
||||||
|
"title": "科学领域活动",
|
||||||
|
"description": "昆虫观察与自然科学探索",
|
||||||
|
"suggestedOrder": 5,
|
||||||
|
"durationMinutes": 20,
|
||||||
|
"frequency": "每周1次",
|
||||||
|
"keyPoints": [
|
||||||
|
"观察昆虫特征",
|
||||||
|
"了解变态发育",
|
||||||
|
"种植观察活动",
|
||||||
|
"自然探索"
|
||||||
|
],
|
||||||
|
"tips": "准备放大镜、观察盒等科学工具"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"lessonType": "ART",
|
||||||
|
"title": "艺术领域活动",
|
||||||
|
"description": "创意手工与美术表达",
|
||||||
|
"suggestedOrder": 6,
|
||||||
|
"durationMinutes": 25,
|
||||||
|
"frequency": "每周1次",
|
||||||
|
"keyPoints": [
|
||||||
|
"毛毛虫手工制作",
|
||||||
|
"蝴蝶绘画创作",
|
||||||
|
"拼贴画活动",
|
||||||
|
"作品展示"
|
||||||
|
],
|
||||||
|
"tips": "提供多样化材料,鼓励自由创作"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"lessonType": "HEALTH",
|
||||||
|
"title": "健康领域活动",
|
||||||
|
"description": "健康饮食习惯培养",
|
||||||
|
"suggestedOrder": 7,
|
||||||
|
"durationMinutes": 20,
|
||||||
|
"frequency": "每周1次",
|
||||||
|
"keyPoints": [
|
||||||
|
"认识健康食物",
|
||||||
|
"了解均衡饮食",
|
||||||
|
"良好饮食习惯",
|
||||||
|
"身体运动游戏"
|
||||||
|
],
|
||||||
|
"tips": "结合健康餐盘游戏,学习食物分类"
|
||||||
|
}
|
||||||
|
]' WHERE `name` = '好饿的毛毛虫';
|
||||||
|
|
||||||
|
-- 为三只小猪课程添加排课计划参考
|
||||||
|
UPDATE `course` SET `schedule_ref_data` = '[
|
||||||
|
{
|
||||||
|
"lessonType": "INTRODUCTION",
|
||||||
|
"title": "导入课",
|
||||||
|
"description": "通过小猪玩偶和房子图片导入课程主题",
|
||||||
|
"suggestedOrder": 1,
|
||||||
|
"durationMinutes": 15,
|
||||||
|
"frequency": "每周1次,连续2周",
|
||||||
|
"keyPoints": [
|
||||||
|
"出示三只小猪图片",
|
||||||
|
"提问关于房子的问题",
|
||||||
|
"引入建房主题"
|
||||||
|
],
|
||||||
|
"tips": "准备不同材质的建筑材料样品"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"lessonType": "COLLECTIVE",
|
||||||
|
"title": "集体课",
|
||||||
|
"description": "绘本共读,理解故事情节和寓意",
|
||||||
|
"suggestedOrder": 2,
|
||||||
|
"durationMinutes": 25,
|
||||||
|
"frequency": "每周2次,连续4周",
|
||||||
|
"keyPoints": [
|
||||||
|
"完整讲述故事",
|
||||||
|
"讨论三只房子区别",
|
||||||
|
"理解勤劳与智慧",
|
||||||
|
"角色扮演活动"
|
||||||
|
],
|
||||||
|
"tips": "准备动物头饰,增强角色扮演趣味性"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"lessonType": "LANGUAGE",
|
||||||
|
"title": "语言领域活动",
|
||||||
|
"description": "词汇扩展与语言表达",
|
||||||
|
"suggestedOrder": 3,
|
||||||
|
"durationMinutes": 20,
|
||||||
|
"frequency": "每周2次",
|
||||||
|
"keyPoints": [
|
||||||
|
"建筑材料词汇",
|
||||||
|
"形容词学习(结实、轻便等)",
|
||||||
|
"对话练习",
|
||||||
|
"故事创编"
|
||||||
|
],
|
||||||
|
"tips": "使用实物材料,增强词汇学习的直观性"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"lessonType": "SOCIETY",
|
||||||
|
"title": "社会领域活动",
|
||||||
|
"description": "劳动教育与团队协作",
|
||||||
|
"suggestedOrder": 4,
|
||||||
|
"durationMinutes": 20,
|
||||||
|
"frequency": "每周1次",
|
||||||
|
"keyPoints": [
|
||||||
|
"认识劳动价值",
|
||||||
|
"培养勤劳品质",
|
||||||
|
"团队协作游戏",
|
||||||
|
"分享劳动成果"
|
||||||
|
],
|
||||||
|
"tips": "组织简单的劳动活动,体验劳动乐趣"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"lessonType": "SCIENCE",
|
||||||
|
"title": "科学领域活动",
|
||||||
|
"description": "建筑材料与结构探索",
|
||||||
|
"suggestedOrder": 5,
|
||||||
|
"durationMinutes": 20,
|
||||||
|
"frequency": "每周1次",
|
||||||
|
"keyPoints": [
|
||||||
|
"认识不同建筑材料",
|
||||||
|
"探索材料特性",
|
||||||
|
"简单搭建活动",
|
||||||
|
"结构稳定性实验"
|
||||||
|
],
|
||||||
|
"tips": "准备积木、纸板等材料,开展搭建游戏"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"lessonType": "ART",
|
||||||
|
"title": "艺术领域活动",
|
||||||
|
"description": "美术创作与手工活动",
|
||||||
|
"suggestedOrder": 6,
|
||||||
|
"durationMinutes": 25,
|
||||||
|
"frequency": "每周1次",
|
||||||
|
"keyPoints": [
|
||||||
|
"房子绘画创作",
|
||||||
|
"小猪手工制作",
|
||||||
|
"拼贴画活动",
|
||||||
|
"作品展示分享"
|
||||||
|
],
|
||||||
|
"tips": "鼓励幼儿设计自己的理想房子"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"lessonType": "HEALTH",
|
||||||
|
"title": "健康领域活动",
|
||||||
|
"description": "身体运动与安全意识",
|
||||||
|
"suggestedOrder": 7,
|
||||||
|
"durationMinutes": 20,
|
||||||
|
"frequency": "每周1次",
|
||||||
|
"keyPoints": [
|
||||||
|
"跑跳运动游戏",
|
||||||
|
"安全意识教育",
|
||||||
|
"躲避游戏",
|
||||||
|
"身体协调训练"
|
||||||
|
],
|
||||||
|
"tips": "设计安全的追逐游戏,锻炼反应能力"
|
||||||
|
}
|
||||||
|
]' WHERE `name` = '三只小猪';
|
||||||
|
|
||||||
|
-- 注意:lesson_type 字段位于 course_lesson 表,不在 course 表中
|
||||||
|
-- 课程类型(INTRODUCTION, COLLECTIVE, LANGUAGE, SOCIETY, SCIENCE, ART, HEALTH)
|
||||||
|
-- 在 course_esson 表中定义,此处不需要更新
|
||||||
Loading…
Reference in New Issue
Block a user