# 问题陈述 设计并拆分 `course` 模块,使其从“仅有 SQL 结构”升级为可支撑教师建课、班级投放、学生学习与小程序差异化可见性的课程域。 ## 当前状态(已确认) * 架构与 API 已定义 `course` 为独立业务域,含课程、章节、知识点、掌握度等接口与数据职责。参考 `docs/architecture/logical-view.md (12-18)`、`docs/architecture/api-design.md (34-41)`。 * 当前 `backend` Maven 模块尚未包含 `course` 服务实现,仅有 `init/pg/course` SQL。参考 `backend/pom.xml (11-20)`、`init/pg/course/10_create_course_tables.sql (1-521)`。 * `course` 表结构已覆盖课程主链路:课程/章节/节点/资源/知识点/学习会话/进度/事件,并内置节点类型 `IN_CLASS_ACTIVITY`、`AFTER_CLASS_TASK`、`MATERIAL`。参考 `init/pg/course/10_create_course_tables.sql (63-78)`、`init/pg/course/10_create_course_tables.sql (323-349)`。 * 小程序端当前仍是骨架页,未接课程业务。参考 `app/src/app.json (1-13)`、`app/src/pages/home/index.js (1-6)`。 ## 模块拆分与设计细节 ### 1) 子模块边界 * `course-core`:课程、章节、节点、发布状态(单版本模型,不引入发布快照版本化)。 * `course-resource`:节点资源与文件引用。 * `course-knowledge`:知识点、章节/节点关联、掌握度回写。 * `course-learning`:学习会话、学习进度、学习事件。 * `course-delivery`:课程对班级投放与可见规则(与 `upms-class` 联动)。 ### 2) 课程可见性与小程序约束 * 教师端可管理全部节点类型(含 `MATERIAL/LESSON` 课件类节点)。 * 小程序端仅 `STUDENT` 角色可访问课程能力,且 `LESSON` 节点在小程序全部隐藏。 * 端侧可见性采用“字段内嵌”方案(不使用独立策略表): * 节点级字段:`visible_for_web_teacher`、`visible_for_mini_student` * 资源级字段:`resource_visible_scope` * 课程查询接口按 `clientType + roleCodes + classMembership` 组合过滤。 ### 3) 与班级和作业联动 * 章节节点点击查询固定两步: 1) 查询课件(`course.cl_node_resource`,小程序端不执行该步)。 2) 查询课堂练习(`course.cl_node_homework_rel` + `question.hw_assignment`,`relation_type=IN_CLASS`)。 * 课后作业由作业入口独立查询,不并入章节节点点击查询结果。 * 课程投放以 `upms.tb_school_class_course_rel` 为准,课程域不重复维护班级主数据。 * `course.cl_node_homework_rel` 与 `question.hw_assignment` 建立稳定联查规范,统一“课堂练习/课后作业”来源。 * 学习进度、知识点掌握度更新时强制校验学生是否属于课程投放班级。 ### 4) 租户隔离策略 * 全量查询与写入以 `tenant_id` 强约束,并在需要层级权限时附加 `tenant_path/dept_path`。 * 对跨租户课程引用(节点关联作业、资源文件)做一致性校验。 ## 问题点与风险 * 目前没有 `course` 运行服务与 API,实现成本集中在“从 0 到 1”。 * 节点与资源的端侧可见性字段尚未实际落表,首期需补齐增量 SQL 与索引。 * 种子数据为空,联调期将缺少可复现演示样本。参考 `init/pg/course/20_init_course_seed.sql (1-2)`。 * 课程与班级关系存在跨模块依赖,若不先固定 authoritative source,容易出现双写冲突。 ## 已确定的实现决策 * 端侧可见性采用“字段内嵌”方案。 * 章节节点点击查询采用两步:查询课件(小程序不查)+ 查询课堂练习。 * `LESSON` 节点在小程序全部隐藏。 * 课程发布模型不做版本化,采用单版本状态流转(DRAFT/PUBLISHED/ARCHIVED)。