380 lines
15 KiB
Markdown
380 lines
15 KiB
Markdown
# 产品整体架构文档 — 道路救援企业培训系统
|
||
|
||
> 版本: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.0(MyBatis 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 | - | 企业微信 SDK(OAuth 登录) |
|
||
| Springdoc OpenAPI | 2.2+ | API 文档 |
|
||
| Spring @Scheduled | - | 考试超时自动交卷定时任务 |
|
||
| 文件存储 | - | V1 本地存储,V2 可扩展 MinIO/OSS |
|
||
|
||
[SRC-FEAT-01:7.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-01:4.1 权限规则] [SRC-SQL-01:sys_user.role]
|
||
|
||
| 角色 | 枚举值(DB) | 数据范围 |
|
||
|------|------------|---------|
|
||
| 管理员 ADMIN | role=0 | 全平台(无部门隔离) |
|
||
| 讲师 LECTURER | role=1 | 本部门(department_id匹配) |
|
||
| 学员 STUDENT | role=2 | 本部门(只读;自己的进度/成绩) |
|
||
|
||
### 6.2 权限分层(按功能菜单)
|
||
|
||
| 菜单/功能 | ADMIN | LECTURER | STUDENT |
|
||
|---------|-------|---------|---------|
|
||
| 组织架构管理 | ✅ 全部 | ❌ | ❌ |
|
||
| 员工管理 | ✅ 全部 | 👁️ 本部门只读 | ❌ |
|
||
| 知识库-分类管理 | ✅ 全部 | ✅ 本部门 | ❌ |
|
||
| 知识库-知识列表 | ✅ 全部 | ✅ 本部门(含草稿) | 👁️ 本部门已发布 |
|
||
| 考题管理-题库分类 | ✅ | ✅ 本部门 | ❌ |
|
||
| 考题管理-题目列表 | ✅ | ✅ 本部门 | ❌ |
|
||
| 试卷管理 | ✅ | ✅ 本部门 | ❌ |
|
||
| 考试管理 | ✅ | ✅ 本部门发布 | 👁️ 我的考试 |
|
||
| 培训计划 | ✅ | ✅ 本部门创建/管理 | 👁️ 我的培训 |
|
||
| 系统设置 | ✅ | ❌ | ❌ |
|
||
| 工作台 | ✅ | ✅ | ✅(学员视图) |
|
||
|
||
[SRC-FEAT-01:8.1 角色菜单权限对照表]
|
||
|
||
### 6.3 控制逻辑
|
||
|
||
**认证层**:JWT Token 携带 userId + role,每次请求由 AuthInterceptor 解析验证。[SRC-CODE-01:common/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 模块全面影响 |
|