Files
railwaysystem/docs/development/feat-20261009-course-wizard.md
T

11 KiB
Raw Blame History

FEAT-20261009 课程两步式向导与教学资源关联 开发与验收文档

功能编号: FEAT-20261009-COURSE-WIZARD
关联模块: ISSUE-01-03 课程库基础资料管理
开发分支: feat/20261009-course-wizard
开发基线: 55143af4a518222007d9b82dfbe0677a04f06150
API Contract: docs/api-v2/02_module_a_base_resource_api.md
数据库: KingbaseES / Database V2
实施日期: 2026-10-09
当前状态: 代码开发完成,静态构建与自动化测试通过;待提交、推送、CI 与运行时验收


1. 功能目标与范围

本功能将课程维护改造为两步式向导,并补齐课程与教学资源之间的真实关联能力:

  1. 第一步维护课程编码、名称、类型、学时、教学目标、课程内容、状态与备注;
  2. 第二步查看已关联资源、关联资源库中的既有资源、上传新资源并自动关联、解除资源关联;
  3. 课程与资源使用规范化多对多关联表 train_course_resource,禁止在 train_course 中保存逗号分隔资源 ID;
  4. 复用既有课程、教学资源与通用文件上传能力,不引入新的文件存储协议;
  5. 不修改培训计划课程配置、排课及其他计划流程模块。

1.1 明确边界

  • 解除关联只删除 train_course_resource 关系,不删除 train_resource 资源记录及实际文件;
  • 被课程引用的资源禁止直接删除,必须先解除课程关联;
  • 本功能不提供资源文件物理删除、资源版本管理、断点续传及大文件分片上传;
  • 本功能未执行真实生产数据库迁移或写入。

2. 用户操作流程

2.1 新增课程

  1. 用户点击“新增”;
  2. 在“课程基本信息”步骤填写并保存课程;
  3. 后端返回已生成 cId,前端进入“教学资源”步骤;
  4. 用户可关联既有资源,或通过通用上传组件上传文件、创建资源并自动绑定;
  5. 用户点击“完成”关闭向导并刷新课程列表。

2.2 修改课程

  1. 用户从列表进入“修改”;
  2. 页面加载课程详情及其真实资源列表;
  3. 用户可修改课程基本信息,也可进入第二步新增或解除资源关联;
  4. 解除关联不会删除资源库中的资源。

3. 数据模型与设计决策

3.1 规范化关联模型

课程与资源采用标准 N:M 模型:

train_course (1) ──< train_course_resource >── (1) train_resource

train_course_resource 核心字段:

字段 类型 说明
id BIGINT IDENTITY 关联记录主键
c_id VARCHAR(32) 课程 ID,外键指向 train_course.c_id
resource_id VARCHAR(32) 资源 ID,外键指向 train_resource.resource_id
sort_no INTEGER 课程内资源排序号
create_by VARCHAR(64) 创建人
create_time TIMESTAMP 创建时间

唯一约束为 (c_id, resource_id),防止同一资源被重复绑定到同一课程。

3.2 旧字段兼容迁移

迁移脚本兼容曾执行旧版 011 的环境:

  1. 检测 train_course.resource_id 是否存在;
  2. 将逗号分隔的资源 ID 拆分后迁移到 train_course_resource;
  3. 忽略不存在或已逻辑删除的资源;
  4. 使用唯一约束避免重复迁移;
  5. 完成迁移后删除 train_course.resource_id 非规范字段。

4. API 与权限

4.1 本次新增或调整的课程接口

HTTP Method Path 权限 说明
GET /train/course/{cId} train:course:query 返回 CourseDetailVO,其中 resources 为真实关联资源列表
POST /train/course train:course:add 新增课程并在 data 中返回包含生成后 cId 的课程对象
POST /train/course/{cId}/resources train:course:edit 绑定资源;请求体为 resourceId、sortNo
DELETE /train/course/{cId}/resources/{resourceId} train:course:edit 解除课程资源关联,不删除资源本身

4.2 复用的资源接口

HTTP Method Path 权限 用途
GET /train/resource/list train:resource:list 获取可关联资源
POST /train/resource train:resource:edit 创建教学资源并返回生成后的资源对象
POST /common/upload 登录用户 复用通用上传组件上传资源文件

4.3 请求模型

CourseResourceBindDTO:

字段 校验 说明
resourceId @NotBlank 必填资源 ID
sortNo @Min(0) 可选排序号,默认 0

5. 后端实现

层级 文件 实现内容
Controller TrainCourseController 返回新增课程对象;增加资源绑定、解绑端点
Controller TrainResourceController 新增资源后返回包含 resourceId 的资源对象
DTO CourseResourceBindDTO 绑定请求参数与校验
VO CourseDetailVO resources 调整为 List<TrainResource>
Service TrainCourseResourceServiceImpl 校验课程和资源、幂等绑定、更新排序、解除关联
Service TrainCourseServiceImpl 查询课程详情时聚合真实资源列表
Service TrainResourceServiceImpl 删除前检查课程引用并给出友好提示
Mapper TrainCourseResourceMapper 关联查询、新增、更新、删除与引用计数
Mapper XML TrainCourseResourceMapper.xml 实现规范化关联 SQL,并过滤已逻辑删除资源
Entity/Mapper TrainCourse、TrainCourseMapper.xml 移除旧 resourceId/resource_id 逗号串字段

绑定操作的业务语义为幂等:若关联已存在,则更新 sort_no,不重复插入关联记录。


6. 前端实现

主要页面:build_ui/src/views/train/course/index.vue

实现内容:

  1. 使用 el-steps 提供“课程基本信息 → 教学资源”两步流程;
  2. 新增课程时先保存课程并取得后端生成的 cId;
  3. 展示真实关联资源及其文件/链接;
  4. 支持搜索并关联资源库中尚未绑定的资源;
  5. 非外部链接资源复用 file-upload 组件;
  6. 外部链接校验必须以 http:// 或 https:// 开头;
  7. 上传资源后调用既有资源新增接口,再调用课程资源绑定接口;
  8. 支持解除关联,并明确提示资源本身不会被删除。

前端 API 文件 build_ui/src/api/train/course.js 新增:

  • bindCourseResource(cId, data);
  • unbindCourseResource(cId, resourceId)。

7. 数据库迁移与回滚

7.1 正向迁移

脚本:RuoYi-Vue/sql/train/v2/011_pilot_20261010_master_data_and_resource.sql

  • 幂等创建 train_resource 与 train_course_resource;
  • 创建课程资源唯一索引、课程索引与资源索引;
  • 创建课程、资源外键;
  • 迁移旧逗号 ID 后删除 train_course.resource_id;
  • 补齐资源类型字典、菜单与角色授权。

7.2 回滚

脚本:RuoYi-Vue/sql/train/v2/rollback/011_pilot_20261010_master_data_and_resource_rollback.sql

回滚脚本会删除资源菜单、字典、课程资源关联表与资源表,并回滚 011 中的主数据扩展列。该操作具有破坏性,只允许在确认无正式数据的回滚窗口执行。


8. 自动化验证结果

验证项 结果 说明
ruoyi-train 全量测试 PASS 393 tests,0 failures,0 errors,0 skipped
课程资源关联定向测试 PASS 3 tests,覆盖新增绑定、重复绑定幂等更新、资源不存在拦截
后端业务模块编译 PASS ruoyi-train 编译成功
前端 ESLint PASS 课程页面与课程 API 文件 0 errors
前端生产构建 PASS npm run build:prod 成功
完整 ruoyi-admin 本地聚合构建 环境阻断 本机缺少非公开依赖 com.kingbase:kingbase8:8.6.0,不是本次代码编译错误
数据库迁移实跑 PENDING 未连接目标 Kingbase 环境执行 011
浏览器端到端验收 PENDING 需在迁移后的集成环境验证上传、绑定、解绑完整流程

前端构建存在一条仓库既有警告:src/views/graph/antv/index2.vue 使用的 @antv/x6 未导出 Addon。该警告与课程模块无关,未阻断构建。


9. Acceptance Criteria

AC 验收内容 当前状态
AC-01 新增课程保存后可进入资源步骤,且获得有效 cId STATIC/AUTOMATED PASS
AC-02 课程详情返回真实关联资源列表 STATIC/AUTOMATED PASS
AC-03 可关联既有资源,同一资源不会重复绑定 AUTOMATED PASS
AC-04 可上传新资源并自动关联课程 BUILD PASS / RUNTIME PENDING
AC-05 解除关联不删除资源本身 STATIC PASS / RUNTIME PENDING
AC-06 被课程引用的资源禁止删除 STATIC PASS / RUNTIME PENDING
AC-07 数据库不再使用逗号分隔资源 ID MIGRATION STATIC PASS / RUNTIME PENDING
AC-08 不影响培训计划课程及排课流程 REGRESSION PASS

10. 上线与验证顺序

  1. 在备份后的集成数据库执行正向迁移 011;
  2. 核对 train_course_resource 表、唯一约束、外键、字典和菜单;
  3. 构建并部署后端、前端;
  4. 使用具备课程及资源权限的账号进行浏览器验收;
  5. 验证新增课程、修改课程、上传资源、关联既有资源、解除关联和资源删除保护;
  6. 核对操作日志与数据库关联记录;
  7. 验收通过后再合并到目标集成分支。

11. Git 与交付状态

  • 当前代码与本文档均位于本地分支 feat/20261009-course-wizard;
  • 当前改动尚未执行 git commit、git push 或创建合并请求;
  • 远端页面显示的 Status: Failed 对应基线提交 55143af4 的既有 CI Pipeline,不代表本地尚未提交的课程向导代码已经执行或失败;
  • 推荐先完成本地变更审查并按中文提交规范提交,再推送该功能分支触发新的 CI;
  • 新 Pipeline 全部通过后,再向 integration/20261010-pilot 创建合并请求。

建议提交信息:

新增培训:实现课程两步式向导与教学资源关联

12. 已知事项

  1. 本地完整管理端构建依赖授权的 Kingbase JDBC 驱动;CI Runner 必须先通过 scripts/bootstrap/check-kingbase-jdbc.sh;
  2. 当前远端失败 Pipeline 的具体失败 Job 和日志需在 GitLab Pipeline 页面查看,单凭分支页红色状态无法判断根因;
  3. 推送不会自动部署生产环境:当前 .gitlab-ci.yml 仅允许 feat/cicd-pipeline 执行 deploy_production,本功能分支只会运行后端、前端构建测试。