# 课程中心重构设计(教师端 & 学校端) > 创建时间:2026-03-21 > 状态:✅ 已实现 --- ## 一、背景与目标 ### 1.1 重构背景 原有学校端"课程管理"模块功能单一: - 仅展示课程包列表和基本信息 - 课程详情页展示数据不完整 - 缺少课程介绍、排课参考、环创建设等内容 - 与教师端课程中心存在功能重复,维护成本高 ### 1.2 重构目标 1. **统一体验**:学校端课程中心与教师端保持一致的浏览体验 2. **完整展示**:课程详情页展示完整信息(课程配置、排课参考、环创建设等) 3. **代码复用**:两端共享组件和 API 层,降低维护成本 4. **角色适配**:学校端移除备课/授课功能,仅保留查看能力 --- ## 二、功能对比 ### 2.1 功能差异矩阵 | 功能点 | 教师端 | 学校端 | 说明 | |-------|:------:|:------:|------| | 套餐列表浏览 | ✅ | ✅ | 左侧套餐列表 | | 课程包列表 | ✅ | ✅ | 右侧网格展示 | | 年级/主题筛选 | ✅ | ✅ | 标签+下拉筛选 | | 课程包搜索 | ✅ | ✅ | 关键词搜索 | | 课程包详情查看 | ✅ | ✅ | 完整详情页 | | 备课模式 | ✅ | ❌ | 学校端无 | | 授课模式 | ✅ | ❌ | 学校端无 | | 预约上课 | ✅ | ❌ | 学校端无 | | 收藏课程 | ✅ | ❌ | 学校端暂无 | | 创建校本版本 | ✅ | ❌ | 学校端暂无 | ### 2.2 数据展示对比 | 数据项 | 教师端详情 | 学校端详情(重构前) | 学校端详情(重构后) | |-------|:----------:|:------------------:|:------------------:| | 基本信息 | ✅ | ✅ | ✅ | | 使用统计 | ✅ | ✅ | ✅ | | 版本记录 | ✅ | ✅ | ✅ | | 课程介绍(8项) | ✅ | ❌ | ✅ | | 排课计划参考 | ✅ | ❌ | ✅ | | 环创建设 | ✅ | ❌ | ✅ | | 课程配置(lessons) | ✅ | ❌ | ✅ | | 数字资源 | ✅ | ❌ | ✅ | --- ## 三、架构设计 ### 3.1 前端组件结构 ``` reading-platform-frontend/src/views/ ├── school/ │ └── courses-new/ # 学校端课程中心(新增) │ ├── CourseCenterView.vue # 课程中心主页面 │ └── components/ │ └── CoursePackageCard.vue # 课程包卡片组件 │ ├── teacher/ │ └── courses-new/ # 教师端课程中心(新增) │ ├── CourseCenterView.vue # 课程中心主页面 │ └── components/ │ └── CoursePackageCard.vue # 课程包卡片组件 │ └── [共享] courses/CourseDetailView.vue # 课程详情页(两端共用) ``` ### 3.2 API 层设计 ``` reading-platform-frontend/src/api/ ├── course-center.ts # 课程中心通用 API(新增) │ ├── getCollections() # 获取套餐列表 │ ├── getPackages() # 获取课程包列表 │ └── getFilterMeta() # 获取筛选元数据 │ ├── school.ts # 学校端专用 API │ └── getSchoolCourse(id) # 获取课程详情 │ └── teacher.ts # 教师端专用 API └── getTeacherCourse(id) # 获取课程详情 ``` ### 3.3 后端 API 设计 ``` # 学校端 GET /api/v1/school/packages # 获取已授权套餐列表 GET /api/v1/school/packages/{collectionId}/packages # 获取套餐下的课程包 GET /api/v1/school/packages/{packageId}/filter-meta # 获取筛选元数据 GET /api/v1/school/courses/{id} # 获取课程详情 → 返回 CourseResponse # 教师端 GET /api/v1/teacher/packages # 获取已授权套餐列表 GET /api/v1/teacher/packages/{collectionId}/packages # 获取套餐下的课程包 GET /api/v1/teacher/packages/{packageId}/filter-meta # 获取筛选元数据 GET /api/v1/teacher/courses/{id} # 获取课程详情 → 返回 CourseResponse ``` --- ## 四、页面布局设计 ### 4.1 课程中心主页面 ``` ┌──────────────────────────────────────────────────────────────────────┐ │ 课程中心 │ ├──────────────────────────────────────────────────────────────────────┤ │ │ │ ┌────────────┬───────────────────────────────────────────────────┐ │ │ │ │ │ │ │ │ 套餐列表 │ 课程包网格 │ │ │ │ │ │ │ │ │ ┌────────┐ │ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │ │ │ │ │小班套餐 │ │ │课程包1│ │课程包2│ │课程包3│ │课程包4│ │ │ │ │ │12个课程 │ │ │ │ │ │ │ │ │ │ │ │ │ │ └────────┘ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └──────┘ └──────┘ └──────┘ └──────┘ │ │ │ │ ┌────────┐ │ │ │ │ │ │中班套餐 │ │ 筛选条件: │ │ │ │ │15个课程 │ │ 年级:[全部] [小班] [中班] [大班] │ │ │ │ └────────┘ │ 主题:[下拉选择] │ │ │ │ │ 搜索:[关键词搜索______] │ │ │ │ ┌────────┐ │ │ │ │ │ │大班套餐 │ │ │ │ │ │ │18个课程 │ │ │ │ │ │ └────────┘ │ │ │ │ │ │ │ │ │ └────────────┴───────────────────────────────────────────────────┘ │ │ │ └──────────────────────────────────────────────────────────────────────┘ ``` ### 4.2 课程包详情页(完整版) ``` ┌──────────────────────────────────────────────────────────────────────┐ │ ◀ 返回课程中心 │ │ │ │ 课程包名称 - 课程详情 │ ├──────────────────────────────────────────────────────────────────────┤ │ │ │ ┌────────────┬───────────────────────────────────────────────────┐ │ │ │ [封面图] │ 基本信息:主题、适用年级、时长等 │ │ │ │ │ 使用统计:使用次数、使用教师、平均评分 │ │ │ └────────────┴───────────────────────────────────────────────────┘ │ │ │ │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │ │ │ │ 【课程介绍】(Tab 形式) │ │ ┌────────┬────────┬────────┬────────┬────────┐ │ │ │课程简介│课程亮点│课程目标│内容安排│重难点│教学方法│评价方式│注意事项│ │ │ └────────┴────────┴────────┴────────┴────────┘ │ │ │ │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │ │ │ │ 【排课计划参考】 │ │ ┌──────────────────────────────────────────────────────────────┐ │ │ │ 时间 │ 课程类型 │ 课程名称 │ 区域活动 │ 备注 │ │ │ │ 周一 │ 导入课 │ ... │ ... │ ... │ │ │ │ 周二 │ 集体课 │ ... │ ... │ ... │ │ │ │ 周三 │ 语言领域 │ ... │ ... │ ... │ │ │ │ ... │ ... │ ... │ ... │ ... │ │ │ └──────────────────────────────────────────────────────────────┘ │ │ │ │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │ │ │ │ 【环创建设】 │ │ ┌──────────────────────────────────────────────────────────────┐ │ │ │ 环创建设内容... │ │ │ └──────────────────────────────────────────────────────────────┘ │ │ │ │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │ │ │ │ 【课程配置】(7节课程) │ │ ┌──────────────────────────────────────────────────────────────┐ │ │ │ 1. 导入课 - 10分钟 │ │ │ │ 教学目标、教学准备、核心资源、教学环节(步骤列表) │ │ │ ├──────────────────────────────────────────────────────────────┤ │ │ │ 2. 集体课 - 25分钟 │ │ │ │ ... │ │ │ ├──────────────────────────────────────────────────────────────┤ │ │ │ 3-7. 五大领域课程(语言/科学/健康/社会/艺术) │ │ │ │ ... │ │ │ └──────────────────────────────────────────────────────────────┘ │ │ │ │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │ │ │ │ 【数字资源】 │ │ ┌──────────────────────────────────────────────────────────────┐ │ │ │ 视频资源 | 音频资源 | 文档资源 | 图片资源 │ │ │ └──────────────────────────────────────────────────────────────┘ │ │ │ └──────────────────────────────────────────────────────────────────────┘ ``` --- ## 五、关键技术实现 ### 5.1 后端:统一返回 CourseResponse **修改前(学校端):** ```java @GetMapping("/{id}") public Result getSchoolCourse(@PathVariable Long id) { // 返回简化的 SchoolCourseResponse return Result.success(SchoolCourseResponse.toSchoolCourseResponse(course)); } ``` **修改后(学校端):** ```java @GetMapping("/{id}") public Result getSchoolCourse(@PathVariable Long id) { Long tenantId = SecurityUtils.getCurrentTenantId(); // 验证权限 courseService.getCourseByIdWithTenantCheck(id, tenantId); // 返回完整详情(与教师端一致) return Result.success(courseService.getCourseByIdWithLessons(id)); } ``` ### 5.2 CourseResponse 完整字段 ```java public class CourseResponse { // 基本信息 private Long id; private String name; private String description; private String coverImagePath; private Integer durationMinutes; private String[] gradeTags; private String[] domainTags; // 课程介绍(8项) private String introSummary; // 课程简介 private String introHighlights; // 课程亮点 private String introGoals; // 课程总目标 private String introSchedule; // 内容安排 private String introKeyPoints; // 重难点 private String introMethods; // 教学方法 private String introEvaluation; // 评价方式 private String introNotes; // 注意事项 // 排课参考 private String scheduleRefData; // JSON 格式的排课计划 // 环创建设 private String environmentConstruction; // 课程配置(核心) private List courseLessons; // 课程列表,包含步骤 // 统计数据 private Integer usageCount; private Integer teacherCount; private Double avgRating; // 版本信息 private String version; private LocalDateTime publishedAt; } ``` ### 5.3 前端:筛选元数据响应 ```typescript // PackageFilterMetaResponse interface FilterMetaResponse { grades: Array<{ label: string; // 年级名称 count: number; // 该年级下课程包数量 }>; themes: Array<{ id: number; // 主题ID name: string; // 主题名称 count: number; // 该主题下课程包数量 }>; } ``` --- ## 六、文件变更清单 ### 6.1 前端新增文件 | 文件路径 | 说明 | |---------|------| | `src/api/course-center.ts` | 课程中心通用 API | | `src/views/school/courses-new/CourseCenterView.vue` | 学校端课程中心页面 | | `src/views/school/courses-new/components/CoursePackageCard.vue` | 课程包卡片组件 | | `src/views/teacher/courses-new/CourseCenterView.vue` | 教师端课程中心页面 | | `src/views/teacher/courses-new/components/CoursePackageCard.vue` | 课程包卡片组件 | ### 6.2 前端修改文件 | 文件路径 | 修改内容 | |---------|---------| | `src/router/index.ts` | 课程中心路由指向新组件 | | `src/views/school/LayoutView.vue` | 菜单文案:课程管理 → 课程中心 | | `src/api/school.ts` | 新增 getSchoolCourse 返回 any 类型 | ### 6.3 后端修改文件 | 文件路径 | 修改内容 | |---------|---------| | `SchoolCourseController.java` | getSchoolCourse 返回 CourseResponse | | `SchoolPackageController.java` | 新增筛选元数据接口 | | `CoursePackageResponse.java` | 新增 filterMeta 字段 | | `PackageFilterMetaResponse.java` | 新增筛选元数据响应类 | | `CourseCollectionService.java` | 新增 getFilterMeta 方法 | | `CourseCollectionServiceImpl.java` | 实现筛选元数据查询 | --- ## 七、测试验证 ### 7.1 API 验证 ```bash # 获取课程详情 curl -H "Authorization: Bearer $TOKEN" \ http://localhost:8480/api/v1/school/courses/17 | jq '{ has_courseLessons: (.data.courseLessons | length), has_scheduleRefData: (.data.scheduleRefData != null), has_introSummary: (.data.introSummary != null) }' # 预期结果 { "has_courseLessons": 7, // ✅ 包含课程配置 "has_scheduleRefData": true, // ✅ 包含排课参考 "has_introSummary": true // ✅ 包含课程介绍 } ``` ### 7.2 前端验证清单 - [x] 学校端课程中心页面正常加载 - [x] 左侧套餐列表正常显示 - [x] 右侧课程包网格正常显示 - [x] 年级/主题筛选正常工作 - [x] 关键词搜索正常工作 - [x] 点击课程包跳转详情页 - [x] 课程详情页展示完整数据: - [x] 基本信息 - [x] 使用统计 - [x] 课程介绍(8项) - [x] 排课计划参考 - [x] 环创建设 - [x] 课程配置(lessons with steps) - [x] 数字资源 --- ## 八、后续优化方向 1. **组件复用**:考虑将 CourseCenterView 抽象为通用组件,通过 props 区分角色 2. **缓存优化**:套餐列表和筛选元数据可考虑前端缓存 3. **学校端增强**: - 添加收藏功能 - 添加数据统计导出 4. **教师端增强**: - 备课入口优化 - 授课入口优化 --- *本文档创建于 2026-03-21* *实现版本:retirado 分支 commit 3183d1d*