文档优化:将核心架构与流程字符图转换为Mermaid
This commit is contained in:
1 parent
8b54dee004
commit
18a3bfb50e
12 files changed
+141
-244
No files matched your search
@@ -9,11 +9,11 @@
|
||||
|
||||
### 1.1 拒绝单表 CRUD 堆砌
|
||||
本系统是面向铁路培训基地的**智慧培训业务系统**,不是 21 张数据库表的 CRUD 管理后台。严禁出现以下反模式:
|
||||
```text
|
||||
一张数据库表
|
||||
→ 一个单表 Controller
|
||||
→ 一个单表 Service
|
||||
→ 一套单表 CRUD 页面
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["一张数据库表"] --> B["一个单表 Controller"]
|
||||
B --> C["一个单表 Service"]
|
||||
C --> D["一套单表 CRUD 页面"]
|
||||
```
|
||||
|
||||
### 1.2 业务工作台与聚合驱动
|
||||
|
||||
@@ -31,21 +31,15 @@
|
||||
|
||||
为确保试用反馈高效闭环,请按以下流程反馈问题与建议:
|
||||
|
||||
```text
|
||||
[试用人员发现问题/提出需求]
|
||||
│
|
||||
▼
|
||||
[记录现象截图与复现步骤]
|
||||
│
|
||||
▼
|
||||
[提交至项目微信群 / 试用问题登记表]
|
||||
│
|
||||
▼
|
||||
[研发团队定级分类]
|
||||
├── 🔴 BUG (功能缺陷) ── 即时排查,进入热修复流程
|
||||
├── 🟡 UX (操作体验/展示优化) ── 纳入小版本 UI 优化
|
||||
├── 🔵 KNOWN_GAP (已知缺口) ── 对齐 C03/C05 计划进度
|
||||
└── ⚪ REQUIREMENT (新增需求) ── 登记入《甲方需求确认清单》待甲方定级
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["试用人员发现问题 / 提出需求"] --> B["记录现象截图与复现步骤"]
|
||||
B --> C["提交至项目微信群 / 试用问题登记表"]
|
||||
C --> D["研发团队定级分类"]
|
||||
D --> E1["🔴 BUG (功能缺陷)<br/>即时排查,进入热修复流程"]
|
||||
D --> E2["🟡 UX (操作体验/展示优化)<br/>纳入小版本 UI 优化"]
|
||||
D --> E3["🔵 KNOWN_GAP (已知缺口)<br/>对齐 C03/C05 计划进度"]
|
||||
D --> E4["⚪ REQUIREMENT (新增需求)<br/>登记入《甲方需求确认清单》待甲方定级"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -8,26 +8,14 @@
|
||||
|
||||
后续研发与交付严格遵循以下反馈流转机制:
|
||||
|
||||
```text
|
||||
┌────────────────────────────────────────────────────────┐
|
||||
│ 1. 局域网共享试用 (http://192.168.139.230:8082/) │
|
||||
│ 段内业务老师与教务主管开展真实教学排课与考勤试用 │
|
||||
└─────────────────────────┬──────────────────────────────┘
|
||||
│ 发现问题/提出需求
|
||||
▼
|
||||
┌────────────────────────────────────────────────────────┐
|
||||
│ 2. 问题归类与定级 (Triage) │
|
||||
│ - 🔴 BUG : 阻断缺陷,当日修复并自动化回归 │
|
||||
│ - 🟡 UX : 界面与交互体验,周版本批次优化 │
|
||||
│ - 🔵 KNOWN_GAP : 归入已知技术缺口专项排期 │
|
||||
│ - ⚪ REQUIREMENT : 登记入甲方确认清单待批复 │
|
||||
└─────────────────────────┬──────────────────────────────┘
|
||||
│ 敏捷推进
|
||||
▼
|
||||
┌────────────────────────────────────────────────────────┐
|
||||
│ 3. 小版本迭代与发布 (Release Cycles) │
|
||||
│ 本地构建验证 → Surefire 全量通过 → 部署试用分支 │
|
||||
└────────────────────────────────────────────────────────┘
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Step1["1. 局域网共享试用<br/>段内业务老师与教务主管开展真实教学排课与考勤试用"]
|
||||
Step2["2. 问题归类与定级 (Triage)<br/>🔴 BUG:阻断缺陷,当日修复并自动化回归<br/>🟡 UX:界面与交互体验,周版本批次优化<br/>🔵 KNOWN_GAP:归入已知技术缺口专项排期<br/>⚪ REQUIREMENT:登记入甲方确认清单待批复"]
|
||||
Step3["3. 小版本迭代与发布 (Release Cycles)<br/>本地构建验证 → Surefire 全量通过 → 部署试用分支"]
|
||||
|
||||
Step1 -->|"发现问题 / 提出需求"| Step2
|
||||
Step2 -->|"敏捷推进"| Step3
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -77,28 +77,25 @@
|
||||
|
||||
当前系统必须在概念模型与后续实现中**严格切分以下三个业务对象**,严禁混为一谈:
|
||||
|
||||
```
|
||||
+-----------------------------------------------------------------------------+
|
||||
| A. 物理宿舍资源 (Dormitory Resource - train_dormitory_info) |
|
||||
| - 物理属性:楼栋、楼层、房间号、核定床位容量、适用性别、房间可用/停用状态 |
|
||||
| - 生命周期:独立于任何培训班和学员,长期相对稳定 |
|
||||
+-----------------------------------------------------------------------------+
|
||||
▲
|
||||
│ 1 间宿舍可容纳多个住宿安排
|
||||
+-----------------------------------------------------------------------------+
|
||||
| B. 住宿业务事实 (Accommodation - train_accommodation) |
|
||||
| - 业务属性:某个学员参训档案 (enrollment_id) 在本次开班中分配到了哪个房间与床位 |
|
||||
| - 状态流转:预分配 (0) -> 已入住 (1) -> 已退宿 (2) |
|
||||
| - 事实归属:RailwaySystem 是本业务的绝对 Source of Truth (事实唯一真源) |
|
||||
+-----------------------------------------------------------------------------+
|
||||
▲
|
||||
│ 1 条住宿事实产生门禁授权要求
|
||||
+-----------------------------------------------------------------------------+
|
||||
| C. 门锁设备授权 (Door Authorization - 门禁授权模型) |
|
||||
| - 设备属性:基于该住宿事实,向 DMS 门锁下发的有效时间区间与电子钥匙凭据 (密码/卡片) |
|
||||
| - 状态流转:待下发 -> 平台已受理 -> 设备执行中 -> 设备生效 -> 撤销中 -> 已注销 |
|
||||
| - 属性特征:依赖外部网络与硬件状态,可异步重试,失败不推翻住宿业务事实 |
|
||||
+-----------------------------------------------------------------------------+
|
||||
```mermaid
|
||||
flowchart TB
|
||||
subgraph LayerA["A. 物理宿舍资源 (train_dormitory_info)"]
|
||||
direction TB
|
||||
A1["物理属性:楼栋、楼层、房间号、核定床位容量、适用性别、房间可用/停用状态<br/>生命周期:独立于任何培训班和学员,长期相对稳定"]
|
||||
end
|
||||
|
||||
subgraph LayerB["B. 住宿业务事实 (train_accommodation)"]
|
||||
direction TB
|
||||
B1["业务属性:学员参训档案 (enrollment_id) 在本次开班中分配到的房间与床位<br/>状态流转:预分配 (0) -> 已入住 (1) -> 已退宿 (2)<br/>事实归属:RailwaySystem 是本业务的绝对 Source of Truth (事实唯一真源)"]
|
||||
end
|
||||
|
||||
subgraph LayerC["C. 门锁设备授权 (门禁授权模型)"]
|
||||
direction TB
|
||||
C1["设备属性:向 DMS 门锁下发的有效时间区间与电子钥匙凭据 (密码/卡片)<br/>状态流转:待下发 -> 平台已受理 -> 设备执行中 -> 设备生效 -> 撤销中 -> 已注销<br/>属性特征:依赖外部网络与硬件状态,可异步重试,失败不推翻住宿业务事实"]
|
||||
end
|
||||
|
||||
LayerB -->|"1 间宿舍可容纳多个住宿安排"| LayerA
|
||||
LayerC -->|"1 条住宿事实产生门禁授权要求"| LayerB
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -113,26 +113,16 @@ sequenceDiagram
|
||||
|
||||
当由于外部原因(例如运维人员在第三方控制台手动注销、或 DMS 服务端异常重启导致 Session 丢失)出现 `401 Unauthorized` 时的处理规范:
|
||||
|
||||
```
|
||||
业务请求触发调用
|
||||
│
|
||||
▼
|
||||
使用本地 Token 调用 DMS API
|
||||
│
|
||||
├─────────────────────────────────┐
|
||||
▼ [成功 200 OK] ▼ [失败 401 Unauthorized]
|
||||
正常返回业务数据 立即令本地缓存的 Token 失效 (invalidate)
|
||||
通知 TokenManager.touch() 延展寿命 │
|
||||
▼
|
||||
单飞排他锁获取新 Token (Single-Flight Login)
|
||||
│
|
||||
├─────────────────────────┐
|
||||
▼ [重登录成功] ▼ [重登录失败]
|
||||
安全重试原始业务请求 (最多 1 次) 标记操作失败 (FAILED)
|
||||
│ 记录审计日志
|
||||
├──────────────┐ 不影响本地住宿业务事实
|
||||
▼ [重试成功] ▼ [依然401]
|
||||
成功返回 熔断抛出异常
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start["业务请求触发调用"] --> CallDms["使用本地 Token 调用 DMS API"]
|
||||
CallDms -->|"成功 200 OK"| Success1["正常返回业务数据<br/>通知 TokenManager.touch() 延展寿命"]
|
||||
CallDms -->|"失败 401 Unauthorized"| Invalidate["立即令本地缓存的 Token 失效 (invalidate)"]
|
||||
Invalidate --> SingleFlight["单飞排他锁获取新 Token (Single-Flight Login)"]
|
||||
SingleFlight -->|"重登录成功"| Retry["安全重试原始业务请求 (最多 1 次)"]
|
||||
SingleFlight -->|"重登录失败"| LoginFail["标记操作失败 (FAILED)<br/>记录审计日志<br/>不影响本地住宿业务事实"]
|
||||
Retry -->|"重试成功"| Success2["成功返回"]
|
||||
Retry -->|"依然 401"| CircuitBreak["熔断抛出异常"]
|
||||
```
|
||||
|
||||
### 5.1 恢复红线守则
|
||||
|
||||
@@ -11,22 +11,11 @@
|
||||
- 官方文档明示:**“门锁的实际执行结果,务必在调用相关操作后 10 秒查询”**。
|
||||
- **严重红线**:绝对禁止在 Web 请求线程(Controller/Service)中执行 `Thread.sleep(10000)`!这会迅速耗尽 Tomcat 工作线程池,引发系统雪崩。
|
||||
- **轮询架构设计**:
|
||||
```
|
||||
Web 请求 (如确认入住)
|
||||
│
|
||||
▼
|
||||
本地持久化 Accommodation (已入住) 与 DoorAuthorization (ISSUING)
|
||||
提交本地数据库事务 (Commit Local DB)
|
||||
│
|
||||
▼
|
||||
异步派发调用 DMS 创建钥匙 -> 返回 operationId (耗时 ~200ms)
|
||||
本地记录 ExternalOperationRecord (status = ACCEPTED, next_poll_time = now + 10s)
|
||||
快速向前端返回 HTTP 200 (附带提示:“住宿已分配,门锁授权下发中”)
|
||||
│
|
||||
▼
|
||||
后台调度引擎 (Quartz / Spring Scheduled ThreadPool - 专用IO线程池)
|
||||
扫描 next_poll_time <= NOW() 的任务 -> 调用 /doorlock/query-operation-status
|
||||
更新操作记录与授权记录状态 -> 若为 success 则推为 ACTIVE
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Req["Web 请求 (如确认入住)"] --> LocalDB["本地持久化 Accommodation (已入住) 与 DoorAuthorization (ISSUING)<br/>提交本地数据库事务 (Commit Local DB)"]
|
||||
LocalDB --> AsyncDms["异步派发调用 DMS 创建钥匙 -> 返回 operationId (耗时 ~200ms)<br/>本地记录 ExternalOperationRecord (status = ACCEPTED, next_poll_time = now + 10s)<br/>快速向前端返回 HTTP 200 (附带提示:“住宿已分配,门锁授权下发中”)"]
|
||||
AsyncDms --> Scheduler["后台调度引擎 (Quartz / Spring Scheduled ThreadPool - 专用IO线程池)<br/>扫描 next_poll_time <= NOW() 的任务 -> 调用 /doorlock/query-operation-status<br/>更新操作记录与授权记录状态 -> 若为 success 则推为 ACTIVE"]
|
||||
```
|
||||
|
||||
### 1.2 门锁 vs 网关轮询参数隔离
|
||||
|
||||
@@ -35,20 +35,12 @@
|
||||
|
||||
官方文档对在线卡片(`POST /rest/doorlock/online-card/create`)的卡号规定了非常特殊的**小端字节序十六进制转换规则**:
|
||||
|
||||
```
|
||||
[读卡器读取 10 进制原始卡号]
|
||||
│
|
||||
▼ 例: 3161082660
|
||||
[转成标准 16 进制大端串]
|
||||
│
|
||||
▼ 例: BC 6A 4B 24
|
||||
[不足 8 位时高位补零]
|
||||
│
|
||||
▼ 例: 09 99 ED 24
|
||||
[低位在前的字节序逆序转换 (Little-Endian)]
|
||||
│
|
||||
▼ 例: 24 4B 6A BC (或 24 ED 99 09)
|
||||
[送入 DMS API 的 cardNumber 参数]
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Step1["读卡器读取 10 进制原始卡号"] -->|"例: 3161082660"| Step2["转成标准 16 进制大端串"]
|
||||
Step2 -->|"例: BC 6A 4B 24"| Step3["不足 8 位时高位补零"]
|
||||
Step3 -->|"例: 09 99 ED 24"| Step4["低位在前的字节序逆序转换 (Little-Endian)"]
|
||||
Step4 -->|"例: 24 4B 6A BC 或 24 ED 99 09"| Step5["送入 DMS API 的 cardNumber 参数"]
|
||||
```
|
||||
|
||||
### 2.1 架构封装纪律
|
||||
|
||||
@@ -96,23 +96,13 @@
|
||||
## 5. DMS 资源映射与同步管理界面设计 (`Resource Sync UI`)
|
||||
|
||||
### 5.1 房源对齐工作流
|
||||
```
|
||||
[管理员进入"门锁资源映射"界面]
|
||||
│
|
||||
▼
|
||||
[点击"从DMS拉取房源目录"]
|
||||
│
|
||||
▼ 适配器调用 POST /rest/place/room/list
|
||||
[系统解析出 DMS 的 Building, Floor, Room, placeId, 挂载的 lockId, 硬件SN]
|
||||
│
|
||||
▼
|
||||
[系统依据"楼栋-楼层-房间"名称执行规则预匹配]
|
||||
│
|
||||
▼
|
||||
[管理员在界面核对预配对结果, 确认手动微调后点击"确认持久化绑定"]
|
||||
│
|
||||
▼
|
||||
[写入 train_external_resource_mapping, 完成两套系统物理基线的稳定锁定]
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Step1["管理员进入“门锁资源映射”界面"] --> Step2["点击“从 DMS 拉取房源目录”"]
|
||||
Step2 -->|"适配器调用 POST /rest/place/room/list"| Step3["系统解析出 DMS 的 Building, Floor, Room, placeId, 挂载的 lockId, 硬件SN"]
|
||||
Step3 --> Step4["系统依据“楼栋-楼层-房间”名称执行规则预匹配"]
|
||||
Step4 --> Step5["管理员在界面核对预配对结果,确认手动微调后点击“确认持久化绑定”"]
|
||||
Step5 --> Step6["写入 train_external_resource_mapping,完成两套系统物理基线的稳定锁定"]
|
||||
```
|
||||
- **核心保障**:同步操作仅建立与更新映射表,**绝不自动删除或篡改本地 `train_dormitory_info` 的基础房源台账**。本地房源依然是学员管理系统的独立主数据。
|
||||
|
||||
|
||||
@@ -8,16 +8,16 @@
|
||||
|
||||
## 1. 分层测试策略体系 (Testing Strategy)
|
||||
|
||||
```
|
||||
+--------------------------------------------------------------------------------+
|
||||
| L4. 现场沙箱验收测试 (Live Sandbox E2E - 独立测试账号 + 实验台独立挂载测试锁) |
|
||||
+--------------------------------------------------------------------------------+
|
||||
| L3. 契约与故障注入测试 (WireMock Failure Injection - 401/超时/宕机/乱序状态) |
|
||||
+--------------------------------------------------------------------------------+
|
||||
| L2. 并发与状态机集成测试 (Concurrency & State Machine Test - 20并发Token竞争/幂等) |
|
||||
+--------------------------------------------------------------------------------+
|
||||
| L1. 纯领域单元测试 (Unit Test - CardNumberCodec 编码 / 状态机转换 / DTO 转换) |
|
||||
+--------------------------------------------------------------------------------+
|
||||
```mermaid
|
||||
flowchart BT
|
||||
L1["L1. 纯领域单元测试<br/>Unit Test - CardNumberCodec 编码 / 状态机转换 / DTO 转换"]
|
||||
L2["L2. 并发与状态机集成测试<br/>Concurrency & State Machine Test - 20并发Token竞争/幂等"]
|
||||
L3["L3. 契约与故障注入测试<br/>WireMock Failure Injection - 401/超时/宕机/乱序状态"]
|
||||
L4["L4. 现场沙箱验收测试<br/>Live Sandbox E2E - 独立测试账号 + 实验台独立挂载测试锁"]
|
||||
|
||||
L1 --> L2
|
||||
L2 --> L3
|
||||
L3 --> L4
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -75,23 +75,20 @@
|
||||
|
||||
## 5. 推荐技术架构设计
|
||||
|
||||
```
|
||||
[前端 Accommodation / 个人中心]
|
||||
│
|
||||
▼
|
||||
[业务领域层: 住宿分配 / 换房补偿 / 报到联动] <--- 绝对 Source of Truth
|
||||
│
|
||||
▼ (通过强类型 DTO,完全屏蔽外部厂商细节)
|
||||
[中立网关接口: DoorAccessGateway (grant / revoke / query)]
|
||||
│
|
||||
▼ (SPI 模式)
|
||||
[DMS 集成适配器: DmsDoorAccessGateway]
|
||||
├── DmsTokenManager: 进程级单飞排他锁 (防并发覆盖踩踏)
|
||||
├── 细分 HTTP 客户端: PlaceClient / DoorLockClient / KeyClient / OpClient
|
||||
└── DmsOperationPoller: 后台 10 秒对账调度器 (解除 HTTP 线程阻塞)
|
||||
│
|
||||
▼ (HTTPS / Cookie 传递 token)
|
||||
[外部 DMS 物联网平台: https://dms.dmsiot.com]
|
||||
```mermaid
|
||||
flowchart TD
|
||||
UI["前端 Accommodation / 个人中心"] --> Domain["业务领域层: 住宿分配 / 换房补偿 / 报到联动<br/>(绝对 Source of Truth)"]
|
||||
Domain -->|"通过强类型 DTO,屏蔽外部厂商细节"| Gateway["中立网关接口: DoorAccessGateway<br/>(grant / revoke / query)"]
|
||||
|
||||
subgraph Adapter["DMS 集成适配器: DmsDoorAccessGateway (SPI 模式)"]
|
||||
direction TB
|
||||
TM["DmsTokenManager: 进程级单飞排他锁 (防并发覆盖踩踏)"]
|
||||
Clients["细分 HTTP 客户端: PlaceClient / DoorLockClient / KeyClient / OpClient"]
|
||||
Poller["DmsOperationPoller: 后台 10 秒对账调度器 (解除 HTTP 线程阻塞)"]
|
||||
end
|
||||
|
||||
Gateway --> Adapter
|
||||
Adapter -->|"HTTPS / Cookie 传递 token"| External["外部 DMS 物联网平台: https://dms.dmsiot.com"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -10,27 +10,20 @@
|
||||
|
||||
在多角色(Admin, Teacher, Student)登录体系中,数据范围安全必须建立在**零信任前端参数**的基石之上:
|
||||
|
||||
```
|
||||
+─────────────────────────────────────────────────────────────────────────────+
|
||||
| 零信任推导核心防线 (Secure Chain) |
|
||||
| |
|
||||
| 客户端 HTTP Request |
|
||||
| │ (仅携带 Bearer JWT Token,禁止/忽略 query 或 body 中的 identityId) |
|
||||
| ▼ |
|
||||
| Spring Security Filter: JwtAuthenticationTokenFilter |
|
||||
| │ (验签并提取 claims 中的 userId) |
|
||||
| ▼ |
|
||||
| SecurityContextHolder.getContext().getAuthentication() |
|
||||
| │ (获取受信任的 LoginUser.getUserId()) |
|
||||
| ▼ |
|
||||
| Service 内部数据推导 (SecurityContextHelper) |
|
||||
| ├─ 若拥有 train_teacher 角色: |
|
||||
| │ SELECT t_id FROM train_teacher WHERE user_id = #{userId} |
|
||||
| ├─ 若拥有 train_student 角色: |
|
||||
| │ SELECT s_id FROM train_student WHERE user_id = #{userId} |
|
||||
| └─ 若拥有 admin / train_admin 角色: |
|
||||
| 按管理员角色规则放行或基于组织机构过滤 |
|
||||
+─────────────────────────────────────────────────────────────────────────────+
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Req["客户端 HTTP Request<br/>(仅携带 Bearer JWT Token,禁止/忽略 query 或 body 中的 identityId)"]
|
||||
Filter["Spring Security Filter: JwtAuthenticationTokenFilter<br/>(验签并提取 claims 中的 userId)"]
|
||||
SecCtx["SecurityContextHolder.getContext().getAuthentication()<br/>(获取受信任的 LoginUser.getUserId())"]
|
||||
Helper["Service 内部数据推导 (SecurityContextHelper)"]
|
||||
|
||||
Req --> Filter
|
||||
Filter --> SecCtx
|
||||
SecCtx --> Helper
|
||||
|
||||
Helper -->|"拥有 train_teacher 角色"| TeacherRole["SELECT t_id FROM train_teacher WHERE user_id = #{userId}"]
|
||||
Helper -->|"拥有 train_student 角色"| StudentRole["SELECT s_id FROM train_student WHERE user_id = #{userId}"]
|
||||
Helper -->|"拥有 admin / train_admin 角色"| AdminRole["按管理员角色规则放行或基于组织机构过滤"]
|
||||
```
|
||||
|
||||
### 1.1 核心铁律
|
||||
@@ -44,30 +37,16 @@
|
||||
|
||||
教师登录后,其可访问的所有教学资源必须严格基于其受聘授课关系动态推导:
|
||||
|
||||
```
|
||||
┌──────────────────────┐
|
||||
│ sys_user (userId) │
|
||||
└──────────┬───────────┘
|
||||
│ WHERE user_id = #{userId}
|
||||
▼
|
||||
┌──────────────────────┐
|
||||
│ train_teacher (t_id)│
|
||||
└──────────┬───────────┘
|
||||
│
|
||||
┌───────────────────────┼────────────────────────┐
|
||||
│ (排课直接授课) │ (计划课程关联) │ (关联教学班级)
|
||||
▼ ▼ ▼
|
||||
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
|
||||
│timetable_lesson │ │train_plan_course │ │ train_class_plan │
|
||||
│WHERE teacher_id │ │WHERE teacher_id │ │ WHERE plan_id IN │
|
||||
│ = #{t_id} │ │ = #{t_id} │ │ (授课班级集合) │
|
||||
└────────┬─────────┘ └──────────────────┘ └────────┬─────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌──────────────────┐ ┌──────────────────┐
|
||||
│student_checkin │ │training_enrollment
|
||||
│(本人课次考勤流水) │ │(我带的班级学员名单)│
|
||||
└──────────────────┘ └──────────────────┘
|
||||
```mermaid
|
||||
flowchart TD
|
||||
User["sys_user (userId)"] -->|"WHERE user_id = #{userId}"| Teacher["train_teacher (t_id)"]
|
||||
|
||||
Teacher -->|"排课直接授课"| Lesson["timetable_lesson<br/>WHERE teacher_id = #{t_id}"]
|
||||
Teacher -->|"计划课程关联"| PlanCourse["train_plan_course<br/>WHERE teacher_id = #{t_id}"]
|
||||
Teacher -->|"关联教学班级"| ClassPlan["train_class_plan<br/>WHERE plan_id IN (授课班级集合)"]
|
||||
|
||||
Lesson --> Checkin["student_checkin<br/>(本人课次考勤流水)"]
|
||||
ClassPlan --> Enrollment["training_enrollment<br/>(我带的班级学员名单)"]
|
||||
```
|
||||
|
||||
- **授课课表数据**: 仅能查到 `train_timetable_lesson.teacher_id = #{currentTeacherId}` 的课次。
|
||||
@@ -80,29 +59,17 @@
|
||||
|
||||
学员登录后,进入极简个人培训中心,数据范围完全收敛于“本人”:
|
||||
|
||||
```
|
||||
┌──────────────────────┐
|
||||
│ sys_user (userId) │
|
||||
└──────────┬───────────┘
|
||||
│ WHERE user_id = #{userId}
|
||||
▼
|
||||
┌──────────────────────┐
|
||||
│ train_student (s_id)│
|
||||
└──────────┬───────────┘
|
||||
│
|
||||
┌─────────────┬───────────────┼───────────────┬─────────────┐
|
||||
▼ ▼ ▼ ▼ ▼
|
||||
┌───────┐ ┌──────────────┐ ┌───────────┐ ┌──────────────┐ ┌────────────┐
|
||||
│ 个人 │ │ 参训班级名单 │ │ 个人报到 │ │ 个人考勤记录 │ │ 个人画像/ │
|
||||
│ 档案 │ │ Enrollment │ │ Report │ │ Checkin │ │ 学时累计 │
|
||||
│(只读) │ │WHERE s_id=...│ │WHERE s_id │ │WHERE s_id=...│ │WHERE s_id │
|
||||
└───────┘ └──────┬───────┘ └───────────┘ └──────────────┘ └────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────┐
|
||||
│ 班级参训课表 │
|
||||
│(仅限正常在训)│
|
||||
└──────────────┘
|
||||
```mermaid
|
||||
flowchart TD
|
||||
User["sys_user (userId)"] -->|"WHERE user_id = #{userId}"| Student["train_student (s_id)"]
|
||||
|
||||
Student --> Profile["个人档案 (只读)"]
|
||||
Student --> Enrollment["参训班级名单 (Enrollment)<br/>WHERE s_id = ..."]
|
||||
Student --> Report["个人报到 (Report)<br/>WHERE s_id = ..."]
|
||||
Student --> Checkin["个人考勤记录 (Checkin)<br/>WHERE s_id = ..."]
|
||||
Student --> Portrait["个人画像 / 学时累计<br/>WHERE s_id = ..."]
|
||||
|
||||
Enrollment --> Timetable["班级参训课表<br/>(仅限正常在训)"]
|
||||
```
|
||||
|
||||
- **学员档案**: 仅能读取与更新本人通讯电话、邮箱。
|
||||
|
||||
@@ -35,26 +35,19 @@
|
||||
|
||||
系统全员使用同一个登录入口 `http://192.168.139.230:8082/login`。用户验证成功颁发 JWT 后,前端路由守卫(`permission.js`)执行如下分流重定向策略:
|
||||
|
||||
```
|
||||
用户输入账号密码
|
||||
│
|
||||
▼
|
||||
POST /login (200 OK)
|
||||
│
|
||||
▼
|
||||
GET /getInfo (拉取 roles 与 permissions)
|
||||
│
|
||||
▼
|
||||
角色判定 (Role Branching)
|
||||
│
|
||||
┌───────────────────────────┼───────────────────────────┐
|
||||
▼ ▼ ▼
|
||||
拥有 admin 或 train_admin 拥有 train_teacher 拥有 train_student
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
Landing 重定向至: Landing 重定向至: Landing 重定向至:
|
||||
/index /train/teacher/dashboard /train/student/portal
|
||||
(系统综合驾驶舱) (教师授课工作台) (学员个人培训中心)
|
||||
```mermaid
|
||||
flowchart TD
|
||||
LoginInput["用户输入账号密码"] --> PostLogin["POST /login (200 OK)"]
|
||||
PostLogin --> GetInfo["GET /getInfo (拉取 roles 与 permissions)"]
|
||||
GetInfo --> RoleBranch["角色判定 (Role Branching)"]
|
||||
|
||||
RoleBranch --> BranchAdmin["拥有 admin 或 train_admin"]
|
||||
RoleBranch --> BranchTeacher["拥有 train_teacher"]
|
||||
RoleBranch --> BranchStudent["拥有 train_student"]
|
||||
|
||||
BranchAdmin --> LandingAdmin["Landing 重定向至:<br/>/index (系统综合驾驶舱)"]
|
||||
BranchTeacher --> LandingTeacher["Landing 重定向至:<br/>/train/teacher/dashboard (教师授课工作台)"]
|
||||
BranchStudent --> LandingStudent["Landing 重定向至:<br/>/train/student/portal (学员个人培训中心)"]
|
||||
```
|
||||
|
||||
- **兜底方案 (Fallback)**: 若用户被赋予复合角色或自定义角色,前端自动跳转至 `asyncRoutes` 生成的动态路由树的第一个叶子节点页面,杜绝 404 或白屏。
|
||||
|
||||
Reference in new issue
Block a user