# 知识库模块(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(树) | - | | 知识内容 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 | - | | 知识列表查询(学员端) | 只查 PUBLISHED 状态,携带个人学习状态 | department_id, KnowledgeQueryDTO | PageResult | auth | | 知识在线预览 | 文档在线预览(PDF/Word等)、视频在线播放 | knowledgeId | 文件 URL / 预览链接 | 文件存储/文档预览服务 | | 开始学习 | 创建或获取学习进度记录,记录首次学习时间 | knowledgeId, [source, planId] | - | auth | | 更新学习进度 | 定时上报学习进度(每60秒),累加时长,判断完成 | ProgressUpdateDTO(duration, progress, videoPosition, source, planId) | - | training(若来源=TRAINING) | | 完成学习 | 前端显式标记完成(文档)| knowledgeId | - | - | | 查询学习进度 | 查询学员对某知识/某批知识的学习状态 | userId/knowledgeIds | List | - | | 引用保护检查 | 检查知识是否被培训计划引用,下架前警告 | 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 请先移除分类下的知识 |