206 lines
10 KiB
Markdown
206 lines
10 KiB
Markdown
# 知识库模块(knowledge)
|
||
|
||
> 证据来源:[SRC-FEAT-01] [SRC-FEAT-02] [SRC-SQL-01] [SRC-SQL-02] [SRC-API-01] [SRC-CODE-01:module/knowledge/]
|
||
|
||
---
|
||
|
||
## 1. 模块定位
|
||
|
||
- **模块目标**:管理企业的结构化知识资产,支持文档和视频两种内容类型的上传、分类管理、状态发布,并记录学员的个人学习进度。
|
||
- **解决问题**:解决救援知识依赖口口相传的问题;同时为培训计划提供可引用的学习内容,并跟踪学员是否真实完成学习(防刷机制)。
|
||
|
||
---
|
||
|
||
## 2. 功能清单
|
||
|
||
[SRC-FEAT-01:模块二] [SRC-FEAT-02:3.2 知识学习]
|
||
|
||
| 功能名称 | 功能描述 | 输入 | 输出 | 依赖模块 |
|
||
|---------|---------|------|------|---------|
|
||
| 知识分类管理 | 创建/修改/删除多级分类树,按部门隔离 | CategoryDTO(name, parent_id, department_id) | CategoryVO | system(部门) |
|
||
| 知识分类树查询 | 返回树形结构的分类目录 | department_id | List<CategoryVO>(树) | - |
|
||
| 知识内容 CRUD | 创建/修改/删除知识(文档/视频),状态为草稿时可修改 | KnowledgeDTO(title, type, file_url, category_id…) | KnowledgeVO | system |
|
||
| 文件上传 | 上传 PDF/Word/Excel/PPT/视频文件,返回文件 URL | MultipartFile | FileDTO(url, fileName, size, type) | 文件存储服务 |
|
||
| 知识发布/下架 | 变更知识状态(草稿→发布/发布→下架/下架→再发布)| knowledgeId, action | - | - |
|
||
| 知识列表查询(讲师端) | 管理端分页查询,可查所有状态,含草稿 | KnowledgeQueryDTO(category_id, status, keyword) | PageResult<KnowledgeVO> | - |
|
||
| 知识列表查询(学员端) | 只查 PUBLISHED 状态,携带个人学习状态 | department_id, KnowledgeQueryDTO | PageResult<KnowledgeVO + 学习状态> | auth |
|
||
| 知识在线预览 | 文档在线预览(PDF/Word等)、视频在线播放 | knowledgeId | 文件 URL / 预览链接 | 文件存储/文档预览服务 |
|
||
| 开始学习 | 创建或获取学习进度记录,记录首次学习时间 | knowledgeId, [source, planId] | - | auth |
|
||
| 更新学习进度 | 定时上报学习进度(每60秒),累加时长,判断完成 | ProgressUpdateDTO(duration, progress, videoPosition, source, planId) | - | training(若来源=TRAINING) |
|
||
| 完成学习 | 前端显式标记完成(文档)| knowledgeId | - | - |
|
||
| 查询学习进度 | 查询学员对某知识/某批知识的学习状态 | userId/knowledgeIds | List<KnowledgeProgressVO> | - |
|
||
| 引用保护检查 | 检查知识是否被培训计划引用,下架前警告 | knowledgeId | Boolean + 引用计划数 | training |
|
||
|
||
---
|
||
|
||
## 3. 核心逻辑
|
||
|
||
### 3.1 业务规则
|
||
|
||
[SRC-FEAT-01:4.5 引用保护规则] [SRC-API-01:5.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-01:6.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-01:4.3 知识学习接口] [SRC-CODE-01:module/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 请先移除分类下的知识 |
|