Files
training-system/training/context/03-功能模块/03-知识库模块.md
2026-05-12 12:24:11 +08:00

206 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 知识库模块knowledge
> 证据来源:[SRC-FEAT-01] [SRC-FEAT-02] [SRC-SQL-01] [SRC-SQL-02] [SRC-API-01] [SRC-CODE-01module/knowledge/]
---
## 1. 模块定位
- **模块目标**:管理企业的结构化知识资产,支持文档和视频两种内容类型的上传、分类管理、状态发布,并记录学员的个人学习进度。
- **解决问题**:解决救援知识依赖口口相传的问题;同时为培训计划提供可引用的学习内容,并跟踪学员是否真实完成学习(防刷机制)。
---
## 2. 功能清单
[SRC-FEAT-01模块二] [SRC-FEAT-023.2 知识学习]
| 功能名称 | 功能描述 | 输入 | 输出 | 依赖模块 |
|---------|---------|------|------|---------|
| 知识分类管理 | 创建/修改/删除多级分类树,按部门隔离 | CategoryDTOname, parent_id, department_id | CategoryVO | system部门 |
| 知识分类树查询 | 返回树形结构的分类目录 | department_id | List<CategoryVO>(树) | - |
| 知识内容 CRUD | 创建/修改/删除知识(文档/视频),状态为草稿时可修改 | KnowledgeDTOtitle, type, file_url, category_id… | KnowledgeVO | system |
| 文件上传 | 上传 PDF/Word/Excel/PPT/视频文件,返回文件 URL | MultipartFile | FileDTOurl, fileName, size, type | 文件存储服务 |
| 知识发布/下架 | 变更知识状态(草稿→发布/发布→下架/下架→再发布)| knowledgeId, action | - | - |
| 知识列表查询(讲师端) | 管理端分页查询,可查所有状态,含草稿 | KnowledgeQueryDTOcategory_id, status, keyword | PageResult<KnowledgeVO> | - |
| 知识列表查询(学员端) | 只查 PUBLISHED 状态,携带个人学习状态 | department_id, KnowledgeQueryDTO | PageResult<KnowledgeVO + 学习状态> | auth |
| 知识在线预览 | 文档在线预览PDF/Word等、视频在线播放 | knowledgeId | 文件 URL / 预览链接 | 文件存储/文档预览服务 |
| 开始学习 | 创建或获取学习进度记录,记录首次学习时间 | knowledgeId, [source, planId] | - | auth |
| 更新学习进度 | 定时上报学习进度每60秒累加时长判断完成 | ProgressUpdateDTOduration, progress, videoPosition, source, planId | - | training若来源=TRAINING |
| 完成学习 | 前端显式标记完成(文档)| knowledgeId | - | - |
| 查询学习进度 | 查询学员对某知识/某批知识的学习状态 | userId/knowledgeIds | List<KnowledgeProgressVO> | - |
| 引用保护检查 | 检查知识是否被培训计划引用,下架前警告 | knowledgeId | Boolean + 引用计划数 | training |
---
## 3. 核心逻辑
### 3.1 业务规则
[SRC-FEAT-014.5 引用保护规则] [SRC-API-015.1 学习进度更新流程]
**内容状态规则**
- 草稿DRAFT=0只有讲师和管理员可见可自由修改
- 已发布PUBLISHED=1全部门学员可见处于此状态时不可修改内容需先下架
- 已下架OFFLINE=2学员不可见可重新上架或继续修改后再发布
**学习进度完成判定规则**
- **视频类**:播放进度 ≥ 90% 时status 自动变更为 COMPLETED
- **文档类**:累计学习时长 ≥ 预估阅读时间(按文件大小估算,具体算法在 `calculateEstimatedTime()`status 变更为 COMPLETED
- 两种类型均支持多次学习,完成后不会重置;时长可继续累加
**防刷机制(活跃检测)**
- 前端 ActivityDetector 监听 mousemove/click/scroll/keypress 事件
- 60秒无活动判定为非活跃停止本地计时器不上报进度
- 恢复活跃后重新计时
**多标签页防重**
- BroadcastChannel API 实现:同一知识在多个 Tab 打开时,检测到重复后关闭后来的 Tab [SRC-API-016.2]
**部门数据隔离**
- 所有知识查询一律追加 `WHERE department_id = [当前用户部门]`
- 分类也按 department_id 隔离
**引用保护**
- 知识下架前,需检查 `tr_plan_knowledge` 中是否有关联;若有,提示警告,用户确认后方可下架
### 3.2 校验逻辑
| 校验项 | 规则 | 失败响应 |
|-------|------|---------|
| 文件类型 | 文档PDF/Word/Excel/PPT视频MP4等常见格式 | 400不支持的文件格式 |
| 文件大小 | [ASSUMPTION] PRD 提及限制大文件,具体上限需配置,建议文档 ≤100MB视频 ≤2GB | 400文件超出大小限制 |
| 知识状态变更 | PUBLISHED 状态下不允许修改内容字段(标题/文件),只允许下架操作 | 400已发布知识不可修改请先下架 |
| 学习进度上报频率 | 前端每60秒上报一次后端不做频率限制允许补报 | - |
| 视频播放进度合理性 | `video_position ≤ 视频总时长`[ASSUMPTION] 后端当前未做服务端校验PRD 明确属于风险项) | 暂无服务端拦截 |
| 分类隶属 | 知识的 category_id 必须属于同一 department_id 的分类 | 400分类不存在或无权限 |
### 3.3 状态流转
```mermaid
stateDiagram-v2
[*] --> DRAFT : 创建知识(可新增/修改/删除)
DRAFT --> PUBLISHED : 讲师发布
PUBLISHED --> OFFLINE : 讲师下架(引用警告确认)
OFFLINE --> PUBLISHED : 讲师重新上架
OFFLINE --> DRAFT : 重新编辑后回到草稿 [ASSUMPTION]
DRAFT --> [*] : 逻辑删除
note right of PUBLISHED : 学员可见\n不可修改内容
note right of DRAFT : 仅讲师/管理员可见
note right of OFFLINE : 学员不可见\n可编辑
```
**学习进度状态流转**
```mermaid
stateDiagram-v2
[*] --> NOT_STARTED : 知识发布,学员尚未打开
NOT_STARTED --> IN_PROGRESS : 调用"开始学习"接口
IN_PROGRESS --> IN_PROGRESS : 每次上报进度(时长累加)
IN_PROGRESS --> COMPLETED : 视频≥90% 或 文档时长达标
COMPLETED --> IN_PROGRESS : 再次学习(时长继续累加,状态不回退)
```
---
## 4. 数据结构
[SRC-SQL-01二、知识库模块] [SRC-SQL-02]
### 4.1 涉及数据表
**km_category**
| 字段 | 类型 | 说明 |
|------|------|------|
| id | BIGINT | 主键 |
| name | VARCHAR(100) NOT NULL | 分类名称 |
| parent_id | BIGINT DEFAULT 0 | 父分类0=顶级) |
| department_id | BIGINT NOT NULL | 所属部门(部门隔离键) |
| sort_order | INT | 排序 |
| deleted | TINYINT | 逻辑删除 |
**km_knowledge**
| 字段 | 类型 | 说明 |
|------|------|------|
| id | BIGINT | 主键 |
| title | VARCHAR(200) NOT NULL | 标题 |
| description | TEXT | 描述/摘要 |
| category_id | BIGINT | 所属分类(可空) |
| type | TINYINT NOT NULL | 0-文档 / 1-视频 |
| file_name | VARCHAR(255) | 文件名 |
| file_url | VARCHAR(500) | 文件 URL |
| file_size | BIGINT | 文件大小(字节) |
| file_type | VARCHAR(20) | 文件后缀pdf/mp4… |
| department_id | BIGINT NOT NULL | 所属部门(隔离键,有 idx |
| status | TINYINT DEFAULT 0 | 0-草稿 / 1-已发布 / 2-已下架 |
| creator_id | BIGINT NOT NULL | 创建人 |
| publish_time | DATETIME | 发布时间 |
| view_count | INT | 浏览次数 |
| deleted | TINYINT | 逻辑删除 |
**km_knowledge_progress**(学员学习进度)[SRC-SQL-02]
| 字段 | 类型 | 说明 |
|------|------|------|
| id | BIGINT | 主键 |
| user_id | BIGINT NOT NULL | 学员ID |
| knowledge_id | BIGINT NOT NULL | 知识ID |
| department_id | BIGINT NOT NULL | 部门(冗余,用于分区查询) |
| status | VARCHAR(20) | NOT_STARTED / IN_PROGRESS / COMPLETED |
| progress | INT | 进度百分比0~100 |
| duration | BIGINT | 累计学习时长(秒) |
| video_position | BIGINT | 视频播放位置(秒,仅视频) |
| source | VARCHAR(20) | FREE / TRAINING |
| plan_id | BIGINT | 关联培训计划source=TRAINING 时有值) |
| start_time | DATETIME | 首次学习时间 |
| complete_time | DATETIME | 完成时间 |
| 唯一约束 | uk_user_knowledge | (user_id, knowledge_id) 唯一 |
### 4.2 数据关联
- `km_knowledge.category_id``km_category.id`
- `km_knowledge.department_id` = `km_category.department_id`(同部门隔离)
- `km_knowledge_progress.user_id``sys_user.id`
- `km_knowledge_progress.plan_id``tr_plan.id`(可空)
---
## 5. 对外接口
[SRC-API-014.3 知识学习接口] [SRC-CODE-01module/knowledge/controller/]
| API 名称 | 方法 | 路径 | 权限 |
|---------|------|------|------|
| 查询知识分类树 | GET | /api/knowledge/category/tree | LECTURER/ADMIN |
| 创建分类 | POST | /api/knowledge/category | LECTURER/ADMIN |
| 修改分类 | PUT | /api/knowledge/category/{id} | LECTURER/ADMIN |
| 删除分类 | DELETE | /api/knowledge/category/{id} | LECTURER/ADMIN |
| 查询知识列表(管理端) | GET | /api/knowledge | LECTURER/ADMIN |
| 创建知识 | POST | /api/knowledge | LECTURER/ADMIN |
| 修改知识 | PUT | /api/knowledge/{id} | LECTURER/ADMIN |
| 发布/下架知识 | PUT | /api/knowledge/{id}/status | LECTURER/ADMIN |
| 删除知识 | DELETE | /api/knowledge/{id} | LECTURER/ADMIN |
| 文件上传 | POST | /api/knowledge/upload | LECTURER/ADMIN |
| 学员-知识列表 | GET | /api/student/knowledge | STUDENT |
| 学员-知识详情 | GET | /api/student/knowledge/{id} | STUDENT |
| 学员-开始学习 | POST | /api/student/knowledge/{id}/start | STUDENT |
| 学员-更新进度 | POST | /api/student/knowledge/{id}/progress | STUDENT |
| 学员-标记完成 | POST | /api/student/knowledge/{id}/complete | STUDENT |
---
## 6. 异常与边界处理
| 场景 | 处理方式 |
|------|---------|
| 已发布知识被下架,同时培训计划正引用 | 弹出确认警告,显示引用该知识的培训计划数量,用户确认后方可下架 |
| 文件上传失败(存储服务不可用) | 返回 503前端提示"文件上传失败,请稍后重试" |
| 学员学习已下架的知识(在培训计划中) | [ASSUMPTION] PRD 未明确,建议:关联进培训计划的知识下架后,学员仍可查看历史进度但不可重新打开 |
| km_knowledge_progress 并发 UPSERT同一学员多标签页 | 唯一约束 uk_user_knowledge 防止重复插入;多标签页同步由前端 BroadcastChannel 控制关闭重复 Tab |
| 视频播放中途退出 | 下次进入从 video_position 断点续播 |
| 学习进度上报时网络中断 | 前端重试后端幂等UPSERT 语义,重复上报取最大值或继续累加) |
| 分类下有知识时删除分类 | 检查该分类下是否有 deleted=0 的知识若有则拒绝400 请先移除分类下的知识 |