11 KiB
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. 功能目标与范围
本功能将课程维护改造为两步式向导,并补齐课程与教学资源之间的真实关联能力:
- 第一步维护课程编码、名称、类型、学时、教学目标、课程内容、状态与备注;
- 第二步查看已关联资源、关联资源库中的既有资源、上传新资源并自动关联、解除资源关联;
- 课程与资源使用规范化多对多关联表
train_course_resource,禁止在train_course中保存逗号分隔资源 ID; - 复用既有课程、教学资源与通用文件上传能力,不引入新的文件存储协议;
- 不修改培训计划课程配置、排课及其他计划流程模块。
1.1 明确边界
- 解除关联只删除
train_course_resource关系,不删除train_resource资源记录及实际文件; - 被课程引用的资源禁止直接删除,必须先解除课程关联;
- 本功能不提供资源文件物理删除、资源版本管理、断点续传及大文件分片上传;
- 本功能未执行真实生产数据库迁移或写入。
2. 用户操作流程
2.1 新增课程
- 用户点击“新增”;
- 在“课程基本信息”步骤填写并保存课程;
- 后端返回已生成
cId,前端进入“教学资源”步骤; - 用户可关联既有资源,或通过通用上传组件上传文件、创建资源并自动绑定;
- 用户点击“完成”关闭向导并刷新课程列表。
2.2 修改课程
- 用户从列表进入“修改”;
- 页面加载课程详情及其真实资源列表;
- 用户可修改课程基本信息,也可进入第二步新增或解除资源关联;
- 解除关联不会删除资源库中的资源。
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 的环境:
- 检测
train_course.resource_id是否存在; - 将逗号分隔的资源 ID 拆分后迁移到
train_course_resource; - 忽略不存在或已逻辑删除的资源;
- 使用唯一约束避免重复迁移;
- 完成迁移后删除
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
实现内容:
- 使用
el-steps提供“课程基本信息 → 教学资源”两步流程; - 新增课程时先保存课程并取得后端生成的
cId; - 展示真实关联资源及其文件/链接;
- 支持搜索并关联资源库中尚未绑定的资源;
- 非外部链接资源复用
file-upload组件; - 外部链接校验必须以
http://或https://开头; - 上传资源后调用既有资源新增接口,再调用课程资源绑定接口;
- 支持解除关联,并明确提示资源本身不会被删除。
前端 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. 上线与验证顺序
- 在备份后的集成数据库执行正向迁移 011;
- 核对
train_course_resource表、唯一约束、外键、字典和菜单; - 构建并部署后端、前端;
- 使用具备课程及资源权限的账号进行浏览器验收;
- 验证新增课程、修改课程、上传资源、关联既有资源、解除关联和资源删除保护;
- 核对操作日志与数据库关联记录;
- 验收通过后再合并到目标集成分支。
11. Git 与交付状态
- 当前代码与本文档均位于本地分支
feat/20261009-course-wizard; - 当前改动尚未执行
git commit、git push或创建合并请求; - 远端页面显示的
Status: Failed对应基线提交55143af4的既有 CI Pipeline,不代表本地尚未提交的课程向导代码已经执行或失败; - 推荐先完成本地变更审查并按中文提交规范提交,再推送该功能分支触发新的 CI;
- 新 Pipeline 全部通过后,再向
integration/20261010-pilot创建合并请求。
建议提交信息:
新增培训:实现课程两步式向导与教学资源关联
12. 已知事项
- 本地完整管理端构建依赖授权的 Kingbase JDBC 驱动;CI Runner 必须先通过
scripts/bootstrap/check-kingbase-jdbc.sh; - 当前远端失败 Pipeline 的具体失败 Job 和日志需在 GitLab Pipeline 页面查看,单凭分支页红色状态无法判断根因;
- 推送不会自动部署生产环境:当前
.gitlab-ci.yml仅允许feat/cicd-pipeline执行deploy_production,本功能分支只会运行后端、前端构建测试。