Files
training-system/training/context/02-产品架构/01-产品整体架构.md
2026-05-12 12:24:11 +08:00

380 lines
15 KiB
Markdown
Raw Permalink 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.

# 产品整体架构文档 — 道路救援企业培训系统
> 版本V1.0
> 生成日期2026-04-07
> 证据状态:✅ 已验证
> 证据来源:[SRC-FEAT-01] [SRC-SQL-01] [SRC-API-01] [SRC-CODE-01]
---
## 1. 产品定位
### 1.1 产品目标
为道路救援企业提供**一站式内部培训管理平台**,通过数字化方式替代口口相传的知识传承模式,实现知识沉淀、在线考核、培训过程管控三位一体。[SRC-FEAT-01]
### 1.2 核心价值
| 价值维度 | 解决的痛点 | 实现方式 |
|---------|---------|---------|
| 知识沉淀 | 知识依赖口口相传,无法沉淀 | 结构化知识库(文档+视频) |
| 高效考核 | 出题组卷效率低,纸质考试成本高 | 在线题库 + 自动/手动组卷 + 在线考试 |
| 培训管控 | 培训效果难追踪,进度不透明 | 培训计划+进度跟踪+成绩统计 |
| 标准化输出 | 服务标准参差不齐 | 统一平台 + 及格线控制 + 必考机制 |
### 1.3 目标用户
| 角色 | 人数 | 核心诉求 |
|------|------|---------|
| 管理员 | 3-5人 | 系统配置、人员管理、全平台数据可见 |
| 讲师(技师) | 30-50人 | 本部门知识上传、出题、发布考试、管理培训计划 |
| 学员 | ~450人 | 学习资料、参加考试、查看进度 |
[SRC-FEAT-01二、用户画像]
### 1.4 使用场景
- **管理员场景**:系统初始化时维护组织架构;日常监控各部门培训完成情况。
- **讲师场景**:救援规范更新后,上传新手册并更新题库,发布新考试,关联到培训计划。
- **学员场景**PC端浏览知识库预习、参加指定考试、查看自己的培训进度。
- **企业微信场景**:学员通过企业微信 H5 入口完成移动端学习和考试。
---
## 2. 系统整体架构
### 2.1 架构分层
| 层次 | 组件 | 职责 |
|-----|------|------|
| **表现层** | PC浏览器管理员/讲师、企业微信H5学员、移动端浏览器 | 用户交互HTML+CSS+JS 原生技术栈 |
| **网关层** | Spring Boot 应用JWT认证、权限拦截、日志、异常处理 | 请求入口,统一认证鉴权,全局异常处理 |
| **业务层** | 5个业务模块auth / system / knowledge / exam / training | 核心业务逻辑,按模块边界划分,禁止跨模块直接调用数据层 |
| **数据层** | MySQL 8.0MyBatis Plus ORM+ 文件存储(本地/MinIO/OSS | 持久化业务数据和媒体文件 |
[SRC-FEAT-01七、架构设计蓝图]
### 2.2 技术架构概览
| 技术选型 | 版本 | 用途 |
|---------|------|------|
| Spring Boot | 3.1.2 | 主框架 |
| MyBatis Plus | 3.5.3+ | ORM简化CRUD |
| MySQL | 8.0 | 主数据库 |
| java-jwt | 4.4+ | JWT Token 签发与验证 |
| Spring Security | 6.x | BCrypt 密码加密 |
| weixin-java-cp | - | 企业微信 SDKOAuth 登录) |
| Springdoc OpenAPI | 2.2+ | API 文档 |
| Spring @Scheduled | - | 考试超时自动交卷定时任务 |
| 文件存储 | - | V1 本地存储V2 可扩展 MinIO/OSS |
[SRC-FEAT-017.3 技术选型]
### 2.3 系统依赖关系
```
外部系统依赖:
企业微信API ←→ auth 模块OAuth 换 userid
文件存储服务 ←→ knowledge 模块(上传/下载文件)
文档预览服务(可选) ←→ knowledge 模块(在线预览)
内部模块依赖方向(单向,禁止逆向调用):
training → knowledge引用知识内容、学习进度
training → exam引用考试通过状态
knowledge / exam / training → system查询用户/部门信息)
所有模块 → auth权限校验拦截器
```
---
## 3. 业务架构图
```mermaid
graph TD
subgraph 客户端
PC[PC浏览器<br>管理员/讲师]
WX[企业微信H5<br>学员]
MB[移动端浏览器<br>学员]
end
subgraph 后端服务
subgraph 网关层
GW[JWT认证 / 权限拦截 / 异常处理]
end
subgraph 业务域
AUTH[认证模块<br>auth]
SYS[系统管理<br>system]
KM[知识库模块<br>knowledge]
EX[考试模块<br>exam]
TR[培训模块<br>training]
end
end
subgraph 数据层
DB[(MySQL 8.0)]
FS[文件存储<br>本地/MinIO]
end
subgraph 外部服务
WXAPI[企业微信API]
PREVIEW[文档预览服务<br>可选]
end
PC --> GW
WX --> GW
MB --> GW
GW --> AUTH
GW --> SYS
GW --> KM
GW --> EX
GW --> TR
AUTH --> WXAPI
KM --> FS
KM --> PREVIEW
TR --> KM
TR --> EX
KM --> SYS
EX --> SYS
TR --> SYS
AUTH --> DB
SYS --> DB
KM --> DB
EX --> DB
TR --> DB
```
---
## 4. 核心业务流程说明
### 4.1 用户主流程(学员)
```mermaid
sequenceDiagram
participant 学员
participant 前端
participant 后端
participant 企业微信
学员->>前端: 点击企业微信登录
前端->>企业微信: 跳转 OAuth 授权
企业微信-->>前端: 返回 code
前端->>后端: code 换 Token
后端->>企业微信: code → userid
后端->>后端: 查 sys_user 匹配
alt 用户已录入
后端-->>前端: JWT Token + 用户信息
前端->>学员: 进入工作台
else 用户未录入
后端-->>前端: 错误:联系管理员
end
学员->>前端: 查看培训计划
前端->>后端: GET /api/student/training
后端-->>前端: 计划列表 + 进度
学员->>前端: 参加考试
前端->>后端: POST /api/student/exam/{id}/start
后端->>后端: 校验时间窗口 + 剩余次数
后端-->>前端: 试题 + 考试时长
学员->>前端: 答题 + 交卷
前端->>后端: POST /api/student/exam/{id}/submit
后端->>后端: 自动判分
后端-->>前端: 成绩 + 排名 + 答案解析
```
### 4.2 管理流程(讲师)
```mermaid
flowchart LR
A[上传知识<br>DRAFT] --> B[发布知识<br>PUBLISHED]
B --> C{有培训计划?}
C -->|是| D[关联到培训计划]
C -->|否| E[学员自由学习]
F[创建题目<br>DRAFT] --> G[发布题目<br>PUBLISHED]
G --> H[组卷<br>手动/自动]
H --> I[发布试卷<br>PUBLISHED]
I --> J[创建考试<br>设置时间/次数]
J --> K[指定考试对象<br>部门/小组/个人]
D --> L[创建培训计划]
J --> L
L --> M[分配学员<br>部门/小组/个人]
M --> N[发布培训计划]
```
### 4.3 数据流转流程
```mermaid
flowchart TB
subgraph 内容生产
KM_CREATE[知识创建<br>km_knowledge DRAFT]
KM_PUBLISH[发布知识<br>PUBLISHED]
QS_CREATE[题目创建<br>ex_question DRAFT]
QS_PUBLISH[发布题目<br>PUBLISHED]
PP_CREATE[组卷<br>ex_paper + ex_paper_question]
EX_CREATE[创建考试<br>ex_exam + ex_exam_target]
TR_CREATE[培训计划<br>tr_plan + tr_plan_knowledge<br>+ tr_plan_exam + tr_plan_target]
end
subgraph 学员消费
LEARN[学习知识<br>→ km_knowledge_progress UPSERT]
EXAM[参加考试<br>→ ex_exam_record 创建/更新]
PROGRESS[进度计算<br>必修知识完成数 + 必考通过数]
end
KM_CREATE --> KM_PUBLISH --> LEARN
QS_CREATE --> QS_PUBLISH --> PP_CREATE --> EX_CREATE --> EXAM
TR_CREATE --> LEARN
TR_CREATE --> EXAM
LEARN --> PROGRESS
EXAM --> PROGRESS
```
---
## 5. 数据架构
### 5.1 核心数据实体共19张表
[SRC-SQL-01] [SRC-SQL-02]
| 数据域 | 表名 | 核心字段 | 说明 |
|-------|------|---------|------|
| **系统** | sys_center | id, name | 中心(最高层级) |
| **系统** | sys_department | id, name, center_id | 部门(隶属中心) |
| **系统** | sys_group | id, name, department_id | 小组(隶属部门) |
| **系统** | sys_user | id, wx_userid, role(0/1/2), department_id, group_id, status | 用户ADMIN/LECTURER/STUDENT |
| **知识库** | km_category | id, name, parent_id, department_id | 知识分类(多级树) |
| **知识库** | km_knowledge | id, title, type(0文档/1视频), file_url, department_id, status(0/1/2) | 知识内容 |
| **知识库** | km_knowledge_progress | id, user_id, knowledge_id, status, progress, duration, video_position, source, plan_id | 学习进度 |
| **考试** | ex_question_category | id, name, parent_id, department_id | 题目分类 |
| **考试** | ex_question | id, type(0/1/2), content, options(JSON), answer, analysis, status | 题目 |
| **考试** | ex_paper | id, title, total_score, duration, pass_score, status | 试卷 |
| **考试** | ex_paper_question | paper_id, question_id, score, sort_order | 试卷-题目关联 |
| **考试** | ex_exam | id, title, paper_id, start_time, end_time, max_attempts, status(0/1/2) | 考试 |
| **考试** | ex_exam_target | exam_id, target_type(0部门/1小组/2个人), target_id | 考试对象 |
| **考试** | ex_exam_record | id, exam_id, user_id, attempt_no, score, passed, answers(JSON), status, version | 考试记录(含乐观锁) |
| **培训** | tr_plan | id, title, start_date, end_date, department_id, status(0/1/2) | 培训计划 |
| **培训** | tr_plan_knowledge | plan_id, knowledge_id, required, sort_order | 计划-知识关联 |
| **培训** | tr_plan_exam | plan_id, exam_id, required, sort_order | 计划-考试关联V1.0.1 |
| **培训** | tr_plan_target | plan_id, target_type, target_id | 计划-对象 |
| **培训** | tr_plan_progress | plan_id, user_id, knowledge_id, completed, complete_time | 旧版进度(已被 km_knowledge_progress 替代)|
### 5.2 实体关系图
```mermaid
erDiagram
sys_center ||--o{ sys_department : "中心下辖多个部门"
sys_department ||--o{ sys_group : "部门下辖多个小组"
sys_department ||--o{ sys_user : "用户属于部门"
sys_group ||--o{ sys_user : "用户可归属小组"
sys_department ||--o{ km_category : "按部门隔离"
km_category ||--o{ km_knowledge : "知识归属分类"
sys_user ||--o{ km_knowledge_progress : "学员学习进度"
km_knowledge ||--o{ km_knowledge_progress : "知识对应进度"
sys_department ||--o{ ex_question_category : "按部门隔离"
ex_question_category ||--o{ ex_question : "题目归属分类"
ex_paper ||--o{ ex_paper_question : "试卷包含多道题"
ex_question ||--o{ ex_paper_question : "题目被多张试卷引用"
ex_paper ||--|| ex_exam : "考试使用某试卷"
ex_exam ||--o{ ex_exam_target : "考试指定对象"
ex_exam ||--o{ ex_exam_record : "考试产生记录"
sys_user ||--o{ ex_exam_record : "学员的考试记录"
tr_plan ||--o{ tr_plan_knowledge : "计划包含多个知识"
tr_plan ||--o{ tr_plan_exam : "计划关联多场考试"
tr_plan ||--o{ tr_plan_target : "计划分配给对象"
km_knowledge ||--o{ tr_plan_knowledge : "知识被计划引用"
ex_exam ||--o{ tr_plan_exam : "考试被计划引用"
```
### 5.3 数据生命周期
| 数据类型 | 创建 | 有效态 | 失效态 | 删除方式 |
|---------|------|-------|-------|---------|
| 知识/题目/试卷 | DRAFT | PUBLISHED | OFFLINE | 逻辑删除deleted=1 |
| 考试 | NOT_STARTED | IN_PROGRESS | ENDED | 逻辑删除 |
| 培训计划 | NOT_STARTED | IN_PROGRESS | ENDED | 逻辑删除 |
| 考试记录 | IN_PROGRESS | SUBMITTED | 永久保留(取最高分) | 不删除 |
| 学习进度 | NOT_STARTED | IN_PROGRESS | COMPLETED | UPSERT更新 |
---
## 6. 权限与角色体系
### 6.1 角色定义
[SRC-FEAT-014.1 权限规则] [SRC-SQL-01sys_user.role]
| 角色 | 枚举值DB | 数据范围 |
|------|------------|---------|
| 管理员 ADMIN | role=0 | 全平台(无部门隔离) |
| 讲师 LECTURER | role=1 | 本部门department_id匹配 |
| 学员 STUDENT | role=2 | 本部门(只读;自己的进度/成绩) |
### 6.2 权限分层(按功能菜单)
| 菜单/功能 | ADMIN | LECTURER | STUDENT |
|---------|-------|---------|---------|
| 组织架构管理 | ✅ 全部 | ❌ | ❌ |
| 员工管理 | ✅ 全部 | 👁️ 本部门只读 | ❌ |
| 知识库-分类管理 | ✅ 全部 | ✅ 本部门 | ❌ |
| 知识库-知识列表 | ✅ 全部 | ✅ 本部门(含草稿) | 👁️ 本部门已发布 |
| 考题管理-题库分类 | ✅ | ✅ 本部门 | ❌ |
| 考题管理-题目列表 | ✅ | ✅ 本部门 | ❌ |
| 试卷管理 | ✅ | ✅ 本部门 | ❌ |
| 考试管理 | ✅ | ✅ 本部门发布 | 👁️ 我的考试 |
| 培训计划 | ✅ | ✅ 本部门创建/管理 | 👁️ 我的培训 |
| 系统设置 | ✅ | ❌ | ❌ |
| 工作台 | ✅ | ✅ | ✅(学员视图) |
[SRC-FEAT-018.1 角色菜单权限对照表]
### 6.3 控制逻辑
**认证层**JWT Token 携带 userId + role每次请求由 AuthInterceptor 解析验证。[SRC-CODE-01common/interceptor/AuthInterceptor.java]
**授权层**
- 接口级:`@PreAuthorize` / SecurityConfig 按角色匹配路径(`/api/student/**` 仅 STUDENT
- 数据级Service 层注入 `department_id` 过滤,讲师/学员查询一律追加 `WHERE department_id = ?`
**隔离规则**
- 4类数据知识库、题库、试卷/考试、培训计划)均按 `department_id` 隔离
- 管理员不注入部门过滤,讲师注入本部门,学员额外限制只查 PUBLISHED 状态
---
## 7. 系统扩展点分析
### 7.1 可扩展模块
| 扩展点 | 当前状态 | V2+ 扩展方向 |
|-------|---------|------------|
| 文件存储 | 本地文件系统 | 抽象 `FileStorageService` 接口 → MinIO/OSS 实现切换 |
| 认证方式 | 企业微信 OAuth账号密码作备选 | 可接入 SSO/LDAP |
| 定时任务 | Spring @Scheduled(单机) | 可替换为 XXL-Job/SchedulerX 支持集群 |
| 统计报表 | 无V2规划 | 新增 `statistics` 模块,不影响现有模块 |
| 通知 | 无V2规划 | 可插入企业微信消息推送 |
### 7.2 可插拔能力
- **文档预览**kkFileView / OnlyOffice 作为可选外部服务knowledge 模块通过 URL 调用,可随时替换
- **视频播放器**video.js 为前端组件,与后端解耦,可替换
- **批量导入**EasyExcel 依赖已选型,可随时为题目/用户管理添加 Excel 导入功能
### 7.3 易变业务点
| 易变点 | 变化方向 | 影响范围 |
|-------|---------|---------|
| 培训完成判定逻辑(当前:必修知识+必考通过) | V2 可能增加签到、线下课时 | `TrainingProgressService.calculateProgress()` |
| 知识学习完成判定视频90%/文档时长) | 可能改为100%或按章节 | `KnowledgeLearningService.isCompleted()` |
| 考试排名计算口径(当前:最高分排名 DENSE_RANK | 可能改为平均分/最后一次 | SQL窗口函数需同步修改 |
| 组织架构层级(当前:中心→部门→小组三级) | 可能增减层级 | system 模块全面影响 |