2026-05-12

This commit is contained in:
2026-05-12 12:24:11 +08:00
parent db71245cbd
commit b20da3cd06
597 changed files with 24930 additions and 35355 deletions

View File

@@ -0,0 +1,196 @@
# 培训计划模块training
> 证据来源:[SRC-FEAT-01] [SRC-FEAT-02] [SRC-SQL-01] [SRC-API-01] [SRC-CODE-01module/training/]
---
## 1. 模块定位
- **模块目标**:将知识内容和考试任务组合成有时间范围的培训计划,分配给指定学员,并跟踪每位学员的完成进度。
- **解决问题**:组织端无法跟踪员工是否真正完成学习目标;培训计划模块实现"分配→执行→进度可视"的闭环管理。
---
## 2. 功能清单
[SRC-FEAT-01模块六] [SRC-FEAT-023.4 我的培训] [SRC-API-014.5]
| 功能名称 | 功能描述 | 输入 | 输出 | 依赖模块 |
|---------|---------|------|------|---------|
| 创建培训计划 | 设置计划基本信息(名称/描述/时间范围/所属部门) | TrainingPlanQueryDTOtitle, start_date, end_date | TrainingPlanVO | system |
| 关联知识内容 | 在培训计划中添加多个知识,设置必修/选修和排序 | plan_id, [{knowledge_id, required, sort_order}] | - | knowledge |
| 关联考试任务 | 在培训计划中添加多个考试,设置必考/选考和排序V1.0.1+| plan_id, [{exam_id, required, sort_order}] | - | exam |
| 分配培训对象 | 指定培训计划的参与者(部门/小组/个人) | plan_id, [{target_type, target_id}] | - | system |
| 培训计划列表(讲师端) | 查询本部门的培训计划,含状态和统计信息 | 分页参数 | PageResult<TrainingPlanVO> | - |
| 培训计划详情(讲师端) | 查看计划详情,含关联知识/考试/对象/进度汇总 | planId | TrainingPlanDetailVO | - |
| 更新/删除培训计划 | 修改计划信息(未开始时可修改,进行中时受限)| planId, TrainingPlanQueryDTO | - | - |
| 学员-我的培训列表 | 查询分配给当前学员的培训计划(进行中优先) | - | PageResult<TrainingPlanVO + 进度> | auth |
| 学员-培训详情 | 查看某培训计划详情:课程列表+学习状态+考试列表+通过状态 | planId | TrainingDetailVO | knowledge, exam |
| 进度计算 | 按必修知识完成数 + 必考通过数 / 总必修项 计算进度% | planId, userId | Integer0~100 | knowledge, exam |
| 知识进度同步 | 学员学习某知识时,若 source=TRAINING 则同步更新 tr_plan_progress | planId, userId, knowledgeId | - | knowledge |
---
## 3. 核心逻辑
### 3.1 业务规则
[SRC-FEAT-01模块六] [SRC-API-015.4]
**培训计划状态自动流转**
- `tr_plan.status` 根据 `start_date` / `end_date` 与当前日期比较自动判定:
- `NOW() < start_date` → NOT_STARTED
- `start_date ≤ NOW() ≤ end_date` → IN_PROGRESS
- `NOW() > end_date` → ENDED
- [ASSUMPTION] 状态字段在查询时实时计算或由定时任务定期刷新PRD 未明确)
**培训进度计算公式**V1.0.1[SRC-API-015.4]
```
progress% = (必修知识完成数 + 必考考试通过数) / (必修知识总数 + 必考考试总数) × 100
```
- 必修知识完成:`km_knowledge_progress.status = COMPLETED``plan_id = 当前计划`
- 必考通过:在 `tr_plan_exam``required=1` 的考试,学员在 `ex_exam_record` 中存在 `passed=1` 的记录
- 选修知识/选考考试不计入进度(但在详情页展示)
- 总必修项为 0 时,进度 = 100%(无内容的计划视为自动完成)
**知识完成与培训进度联动**
- 学员调用 `knowledge.updateProgress()` 时,若 `source=TRAINING``planId != null`
1. 更新 `km_knowledge_progress`
2. 若 status 变为 COMPLETED则更新 `tr_plan_progress`plan_id, user_id, knowledge_id 唯一记录)
**考试通过与培训进度联动**
- 学员考试提交后,`TrainingProgressService` 查询该 exam_id 被哪些计划引用(`tr_plan_exam`),若有关联且 `passed=1`,则重新计算相关计划的进度(或标记为需要刷新)
**多对象分配逻辑**
- 分配对象类型支持 DEPARTMENT(0) / GROUP(1) / USER(2) 混合
- 当指定 DEPARTMENT 时,该部门下所有 STUDENT 账号都被纳入
- 当指定 GROUP 时,该小组所有成员纳入
- 已被纳入的学员在查询时去重(多路径覆盖同一人不重复统计)
### 3.2 校验逻辑
| 校验项 | 规则 | 失败响应 |
|-------|------|---------|
| 培训时间范围 | start_date < end_date | 400培训结束日期必须晚于开始日期 |
| 关联知识状态 | 关联到计划的知识必须是 PUBLISHED 状态 | 400请先发布知识再关联到培训计划 |
| 关联考试状态 | 关联到计划的考试必须是 IN_PROGRESS NOT_STARTED | 400已结束的考试不可关联 |
| 进行中计划修改 | [ASSUMPTION] IN_PROGRESS 状态下不允许修改培训对象和时间范围 | 400培训进行中不可修改 |
| 知识引用保护 | 已关联计划的知识被下架时触发警告 | knowledge 模块负责见知识库模块 6 |
| 学员查看非自己的计划 | Service 层校验该学员是否在 tr_plan_target 覆盖范围内 | 403无权访问该培训计划 |
### 3.3 状态流转
```mermaid
stateDiagram-v2
[*] --> NOT_STARTED : 创建培训计划start_date 未到)
NOT_STARTED --> IN_PROGRESS : start_date 到达(自动/定时)
IN_PROGRESS --> ENDED : end_date 到达(自动/定时)
NOT_STARTED --> [*] : 逻辑删除(未开始可删除)
ENDED --> [*] : 归档
note right of IN_PROGRESS : 学员可学习和考试
note right of ENDED : 仅供历史查阅
```
**学员培训进度状态(非独立表字段,实时计算)**
- 0%尚未开始学习
- 1%~99%学习中
- 100%全部必修项完成培训通过
---
## 4. 数据结构
[SRC-SQL-01培训模块]
### 4.1 涉及数据表
**tr_plan**
| 字段 | 类型 | 说明 |
|------|------|------|
| id | BIGINT | 主键 |
| title | VARCHAR(200) NOT NULL | 计划标题 |
| description | TEXT | 计划描述 |
| start_date | DATE NOT NULL | 开始日期 |
| end_date | DATE NOT NULL | 结束日期 |
| department_id | BIGINT NOT NULL | 所属部门数据隔离键 |
| status | TINYINT | 0-未开始 / 1-进行中 / 2-已结束 |
| creator_id | BIGINT NOT NULL | 创建人 |
**tr_plan_knowledge**培训计划-知识关联
| 字段 | 类型 | 说明 |
|------|------|------|
| plan_id | BIGINT NOT NULL | 培训计划 ID |
| knowledge_id | BIGINT NOT NULL | 知识 ID |
| required | TINYINT DEFAULT 1 | 1-必修 / 0-选修 |
| sort_order | INT | 排序 |
**tr_plan_exam**培训计划-考试关联V1.0.1
| 字段 | 类型 | 说明 |
|------|------|------|
| plan_id | BIGINT NOT NULL | 培训计划 ID |
| exam_id | BIGINT NOT NULL | 考试 ID |
| required | TINYINT DEFAULT 1 | 1-必考 / 0-选考 |
| sort_order | INT | 排序 |
| 唯一约束 | uk_plan_exam | (plan_id, exam_id) |
**tr_plan_target**培训计划-分配对象
| 字段 | 类型 | 说明 |
|------|------|------|
| plan_id | BIGINT NOT NULL | 培训计划 ID |
| target_type | TINYINT NOT NULL | 0-部门 / 1-小组 / 2-个人 |
| target_id | BIGINT NOT NULL | 对应实体 ID |
**tr_plan_progress**知识级别进度供快速查询
| 字段 | 类型 | 说明 |
|------|------|------|
| plan_id | BIGINT NOT NULL | 培训计划 ID |
| user_id | BIGINT NOT NULL | 学员 ID |
| knowledge_id | BIGINT NOT NULL | 知识 ID |
| completed | TINYINT DEFAULT 0 | 0-未完成 / 1-已完成 |
| complete_time | DATETIME | 完成时间 |
### 4.2 数据关联
- `tr_plan_knowledge.plan_id` `tr_plan.id`
- `tr_plan_knowledge.knowledge_id` `km_knowledge.id`
- `tr_plan_exam.plan_id` `tr_plan.id`
- `tr_plan_exam.exam_id` `ex_exam.id`
- `tr_plan_target` 多态关联type=0→`sys_department.id`type=1→`sys_group.id`type=2→`sys_user.id`
- 进度计算同时读取 `km_knowledge_progress`source=TRAINING, plan_id `ex_exam_record`passed=1
---
## 5. 对外接口
[SRC-API-014.5] [SRC-CODE-01module/training/controller/]
| API 名称 | 方法 | 路径 | 权限 |
|---------|------|------|------|
| 培训计划列表讲师 | GET | /api/training | LECTURER/ADMIN |
| 创建培训计划 | POST | /api/training | LECTURER/ADMIN |
| 修改培训计划 | PUT | /api/training/{id} | LECTURER/ADMIN |
| 删除培训计划 | DELETE | /api/training/{id} | LECTURER/ADMIN |
| 关联知识 | POST | /api/training/{id}/knowledge | LECTURER/ADMIN |
| 关联考试 | POST | /api/training/{id}/exam | LECTURER/ADMIN |
| 分配对象 | POST | /api/training/{id}/target | LECTURER/ADMIN |
| 学员-培训列表 | GET | /api/student/training | STUDENT |
| 学员-培训详情 | GET | /api/student/training/{id} | STUDENT |
---
## 6. 异常与边界处理
| 场景 | 处理方式 |
|------|---------|
| 培训计划结束后学员查看 | 状态=ENDED页面展示历史进度和成绩不可继续学习/考试 |
| 学员尚未被分配到某计划就访问 | 403无权访问该培训计划 |
| 相关考试时间窗口已过但培训计划仍进行中 | 考试显示"已结束"无法参加该考试通过状态默认为"未通过"评估影响进度 |
| 同一学员多次被添加部门+个人双重覆盖 | tr_plan_target 可能有重复记录进度计算时去重 user_id 聚合 |
| 培训计划关联的知识被删除 | tr_plan_knowledge 记录仍在显示时标注"知识已下架" [ASSUMPTION] |
| 总必修项为 0 的计划 | 进度直接返回 100%calculateProgress 中已处理totalRequired=0 return 100[SRC-API-015.4] |