文档维护:固化纯净库引导链与三维接口总账

1. 查明空库真正 Bootstrap Chain:明确以 ry_20250522.sql + quartz.sql + 000_phase05_exact_schema.sql 为前置基线;
2. 纠偏 API Inventory 统计指标:确立 107 个端点、0 重复,升级为读写分离物理表调用链 (100% 源码追踪);
3. 明确四类 API 边界:自研业务端点 107、平台端点 95、甲方端点 0、第三方端点 9、纯模拟端点 1;
4. 升级 Client API 状态模型:引入连通性、真实数据与可用性三维矩阵,实证 DMS 0 资源现状,将远程开门更正为 SECURITY_PROHIBITED;
5. 输出纯净演示数据库设计规约草案 (CLEAN_DEMO_DATABASE_SPEC.md)。
This commit is contained in:
wangzhibiao committed 2026-09-24 00:18:15 +08:00
1 parent 122a242dd0
commit 86e07c35e3
6 files changed
+440 -243

No files matched your search

+3 -3
View File
@@ -34,9 +34,9 @@
- [00-START-HERE.md](current/00-START-HERE.md):**第一入口**(真理优先级声明与全量当前文档导航)
- [01-CURRENT-SYSTEM-STATE.md](current/01-CURRENT-SYSTEM-STATE.md):当前系统真实运行基线、技术栈与工作树状态
- [02-FUNCTION-MODULES.md](current/02-FUNCTION-MODULES.md):业务功能模块全量五级判定 (IMPLEMENTED/PARTIAL/MOCK/BLOCKED_EXTERNAL/NOT_IMPLEMENTED)
- [03-DATABASE-AND-TABLES.md](current/03-DATABASE-AND-TABLES.md):KingbaseES 物理表结构、迁移链与纯净演示库重建规约
- [04-API-INVENTORY.md](current/04-API-INVENTORY.md):全量 API 接口账本(路径、方法、源码分类、控制器、关联物理表)
- [05-CLIENT-API-STATUS.md](current/05-CLIENT-API-STATUS.md):甲方与外部接口状态清单(REAL_LIVE/NOT_YET_TESTED/MOCK)
- [03-DATABASE-AND-TABLES.md](current/03-DATABASE-AND-TABLES.md):KingbaseES 物理表结构、迁移链与真正建库流水线(附 CLEAN_DEMO_DATABASE_SPEC.md 规约)
- [04-API-INVENTORY.md](current/04-API-INVENTORY.md):全量 API 接口账本(107端点源码级读写调用链、build_ui 视图引用验证与4类接口边界)
- [05-CLIENT-API-STATUS.md](current/05-CLIENT-API-STATUS.md):外部接口状态清单(连通性/数据状态/可用性三维矩阵,DMS 0资源实证与安全禁止声明)
- [06-DEMO-BASELINE.md](current/06-DEMO-BASELINE.md):演示基线准则(旧Demo不可信声明与新Demo确定性构建七大原则)
- [07-KNOWN-GAPS.md](current/07-KNOWN-GAPS.md):内部已知缺口与外部阻塞清单(内部阻断项已清零,仅存外部 DMS 硬件阻塞)
- [08-NEXT-ACTIONS.md](current/08-NEXT-ACTIONS.md):下一阶段标准化 16 步行动路线图
+1 -1
View File
@@ -49,7 +49,7 @@ docs/reports/** MUST NOT be treated as current truth.
| :---: | :--- | :--- | :--- |
| **01** | [**01-CURRENT-SYSTEM-STATE.md**](01-CURRENT-SYSTEM-STATE.md) | **系统当前真实状态速览**<br>Git基线、前端源码真源 (build_ui/)、后端源码、部署状态、阻断项(ACCOM-PERM-01已解决)、活跃Worktree、Demo状态与文档状态。 | 全体成员、新接手人员、Agent |
| **02** | [**02-FUNCTION-MODULES.md**](02-FUNCTION-MODULES.md) | **业务功能模块全量判定**<br>按教师、学员、课程、场地、计划、排课、考勤、住宿、成绩、统计、DMS等逐项给出五级状态判定。 | 产品经理、业务主管、交付验收 |
| **03** | [**03-DATABASE-AND-TABLES.md**](03-DATABASE-AND-TABLES.md) | **数据库架构、迁移链与数据表总账**<br>KingbaseES DDL、21张业务表、系统表、迁移链顺序与CLEAN_DEMO_DATABASE重建说明。 | 后端开发、DBA、数据审计人员 |
| **03** | [**03-DATABASE-AND-TABLES.md**](03-DATABASE-AND-TABLES.md) | **数据库架构、迁移链与数据表总账**<br>KingbaseES DDL、21张业务表、系统表、真正可重复建库流水线说明(附设计规约草案 [CLEAN_DEMO_DATABASE_SPEC.md](CLEAN_DEMO_DATABASE_SPEC.md))。 | 后端开发、DBA、数据审计人员 |
| **04** | [**04-API-INVENTORY.md**](04-API-INVENTORY.md) | **全量 API 接口总账**<br>全量后端 Controller 接口路径、HTTP 方法、源码级校验表关联、build_ui 实际调用关系与实现状态。 | 前后端研发、接口自动化测试 |
| **05** | [**05-CLIENT-API-STATUS.md**](05-CLIENT-API-STATUS.md) | **甲方与外部接口状态清单**<br>记录 DMS 及电子班牌等外部接口的实时连通、鉴权、真实联调凭据与 Mock 状态,严禁 Mock 冒充真实。 | 集成工程师、外部联调人员 |
| **06** | [**06-DEMO-BASELINE.md**](06-DEMO-BASELINE.md) | **演示基线准则与重构要求**<br>明确旧 Demo 不可信与新 Demo 尚未开始的事实,确立纯净数据库与确定性数据等 7 大原则。 | QA、测试架构师、验收人员 |
+133 -81
View File
@@ -1,105 +1,157 @@
# 03 - 数据库架构、迁移链与数据表总账 (Database and Tables)
# 03 - 数据库架构、迁移链与真实 Bootstrap Chain (Database and Tables)
> **核心原则**:当前阶段**严格只读,不修改数据库,不清库,不执行数据变更**。
> 后续演示重构必须基于本文件定义的迁移链构建纯净演示库:`CLEAN_DEMO_DATABASE`。
> **核心原则**:当前阶段**严格只读,不修改数据库,不清库,不执行数据变更,不创建新库**。
> 本文件严谨定义未来纯净演示库建立的真正可重复引导链 (`CLEAN_DATABASE_BOOTSTRAP_CHAIN`)。
---
## 1. 数据库基本信息
- **数据库管理系统 (DBMS)**:国产人大金仓分析型/事务型关系数据库 (KingbaseES V009R003C018)
- **数据库兼容模式**:Oracle / PostgreSQL 双模式兼容方言
- **数据库兼容模式**:`database_mode = mysql`(兼容 MySQL DDL/DML 方言与自增特性)
- **底层内核兼容版本**:`server_version = 12.1` (PostgreSQL 12 兼容内核)
- **默认 Schema**:`public`
- **正式综合验收数据库**:`railwaysystem_integrated_qa_20260916`
- **当前共享试用数据库**:`training`
- **DDL 规范要点**:
- 自增主键使用 `bigint GENERATED BY DEFAULT AS IDENTITY` 或业务主键 `varchar(32)`;
- 时间类型统一使用 `timestamp`,严禁 MySQL 方言 `DATETIME` 或 `ON UPDATE CURRENT_TIMESTAMP`;
- 状态与布尔字段统一使用 `smallint` (0/1);
- 字符串必须指定明确编码与长度。
- **未来纯净演示数据库规划**:`training_demo_clean` (详见 [CLEAN_DEMO_DATABASE_SPEC.md](CLEAN_DEMO_DATABASE_SPEC.md))
---
## 2. 数据库迁移链定义 (Migration Chain)
## 2. 数据库真正 Bootstrap Chain 深度审计 (Task 1 结论)
系统物理表结构由以下按序执行的迁移脚本链严格定义:
### 2.1 核心疑问解答与实证剖析
#### A. 一个完全空的 Kingbase 数据库,必须先执行哪个 Base Schema?
**确凿结论**:
1. **系统底座首要执行脚本**:`RuoYi-Vue/sql/ry_20250522.sql`
- **内容**:创建若依基础平台核心表(`sys_dept`、`sys_user`、`sys_post`、`sys_role`、`sys_menu`、`sys_user_role`、`sys_role_menu`、`sys_role_dept`、`sys_user_post`、`sys_oper_log`、`sys_dict_type`、`sys_dict_data`、`sys_config`、`sys_logininfor`、`sys_notice`、`gen_table`、`gen_table_column`),并插入超级管理员账号 (`admin` / `user_id=1`)、组织部门、基础字典数据与基础菜单;
- **方言依赖**:必须在 KingbaseES `database_mode=mysql` 模式下执行。
2. **定时调度基础设施脚本**:`RuoYi-Vue/sql/quartz.sql`
- **内容**:创建 Quartz 调度框架所需的 11 张 `QRTZ_*` 表结构;
3. **代码生成器自增主键兼容补丁**:
- `RuoYi-Vue/sql/generator/kingbase/002a_gen_table_identity_patch.sql`
- `RuoYi-Vue/sql/generator/kingbase/002b_gen_table_column_identity_patch.sql`
- **内容**:将 `gen_table` 与 `gen_table_column` 主键修正为 `GENERATED BY DEFAULT AS IDENTITY`,防止导入表元数据时发生主键冲突 (02_kingbase_import_identity_patch)。
#### B. train/v2 migration 的真正前置 schema 是什么?
**确凿结论**:
`RuoYi-Vue/sql/train/v2/` 是一套**增量重构与演进迁移脚本**,**绝非**从零建库脚本!
其各步骤依赖的前置物理表如下:
- `000_preflight.sql`:严格断言必须精确存在 Phase 0.5 历史基线的 **14 张旧业务表**、14 PK、24 FK、7 UNIQUE、6 Identity、9 个触发器,且断言 `sys_user` 必须恰为 1 行、`sys_menu` 为 106 行、`sys_dept` 为 15 行、`sys_dict_type` 为 44 行、`sys_dict_data` 为 500 行;
- `001_backup_current_schema.sql`:通过 `CREATE TABLE bak_v1_* AS SELECT * FROM ...` 备份 14 张旧表,**直接依赖** 14 张 Phase 0.5 旧表已存在;
- `002_create_new_tables.sql`:创建 V2 新增的 8 张核心表(`train_resource`、`train_course_resource`、`train_plan_course`、`train_enrollment`、`train_lesson`、`train_accommodation`、`train_score_item`、`train_student_score`);
- `003_alter_master_tables.sql`:**直接依赖** 8 张主数据表已存在并对其执行 `ALTER TABLE`(`train_teacher`、`train_student`、`train_course`、`train_classroom_info`、`train_training_site`、`train_electronic_board`、`train_dormitory_info`、`train_class_plan`);
- `004_rebuild_business_tables.sql`:**直接依赖** 5 张旧过程表已存在(`train_dorm_auth`、`train_class_report`、`train_student_checkin`、`train_study_duration`、`train_student_portrait`),校验其为 0 行后 DROP 并重建;
- `008_migrate_teacher.sql`:**直接依赖** `train_teacher` 已存在、具备旧字段(`t_department`、`t_title`、`create_user`)及新扩展字段,且**严格断言 `SELECT count(*) FROM train_teacher = 1`**(必须有且仅有 1 行基线数据可供清洗提升);
- `009_drop_legacy_score.sql`:**直接依赖** `train_score_info` 已存在且行数为 0,随后解除约束并 DROP。
👉 **前置基线提供源**:`RuoYi-Vue/sql/train/v2/rollback/000_phase05_exact_schema.sql`!
该文件精确定义了 Phase 0.5 历史基线 14 张表物理 DDL、约束与触发器。在一个全新空数据库中,必须先执行该文件并写入 1 条基线教师占位记录,`000~010` 迁移链方可成功跑通!
#### C. system/kingbase 001~015 的前置条件是什么?
**确凿结论**:
`RuoYi-Vue/sql/system/kingbase/` 中的补丁同样是增量补丁,其依赖条件如下:
- `001_sys_oper_log_cost_time.sql`:依赖 `public.sys_oper_log` 表存在;
- `002`、`003`、`010`、`011`、`012`、`013`、`014`、`015`:均对 `public.sys_menu` 及 `public.sys_role_menu` 执行 INSERT / UPDATE,依赖 `sys_menu`、`sys_role_menu` 存在;
- `004_rbac_identity_binding.sql`:对 `train_teacher` 与 `train_student` 增加 `user_id` 并创建外键指向 `sys_user(user_id)`,**必须依赖 `train_teacher`、`train_student` 与 `sys_user` 均已存在**;
- `005_training_roles_permissions.sql`:创建培训角色(`role_id=3` train_admin, `role_id=4` train_teacher, `role_id=5` train_student),依赖 `sys_role`、`sys_menu`、`sys_role_menu` 存在;
- `006_accommodation_history_constraint.sql`:在 `train_accommodation` 上创建局部唯一索引,**依赖 `train_accommodation` 表已存在**(由 `002_create_new_tables.sql` 创建);
- `008_external_resource_operation.sql`:创建 `train_external_resource_mapping`(外键引用 `train_dormitory_info(dorm_id)`)与 `train_external_operation`,**依赖 `train_dormitory_info` 表已存在**;
- `009_dorm_authorization_orchestration.sql`:修改 `train_dorm_auth` 表结构并添加指向 `train_accommodation(accommodation_id)` 的外键,**依赖 `train_dorm_auth`(004 重建后)与 `train_accommodation` 均已存在**;
- `015_dms_package_a_hardening.sql`:向 `role_id=3` (train_admin) 授权 `menu_id=2263` (`train:accommodation:edit`),**依赖 `sys_role` (已包含 role_id=3) 与 `sys_menu` 均已存在**;
- *(注:`007` 号脚本因历史规划冲突被跳过,严禁执行 `007_dicts.sql`)*。
---
### 2.2 严格可重复执行的引导链定义 (`CLEAN_DATABASE_BOOTSTRAP_CHAIN`)
基于上述源码与 SQL 依赖实证,建立唯一的 7 阶段标准建库流水线:
### 2.1 培训业务核心表迁移 (`RuoYi-Vue/sql/train/v2/`)
```text
000_preflight.sql -- 预检:数据库版本、权限与方言支持
000_tx_capability_probe.sql -- 事务探针:验证显式事务与 DDL 回滚能力
001_backup_current_schema.sql -- 架构基线备份 (备份原 V1 表定义)
002_create_new_tables.sql -- 核心创建:创建 V2 新增的 8 张培训业务核心表
003_alter_master_tables.sql -- 结构变更:对教师、课程、宿舍表扩展字段与约束
004_rebuild_business_tables.sql -- 重建业务表:重建学员、班级、课次等核心关联
005_constraints.sql -- 完整性约束:外键、CHECK 约束 (单行互斥、分数非负等)
006_indexes.sql -- 性能索引:高频查询、排课时段冲突组合索引
007_dicts.sql -- 字典数据 (⚠️ 运行中禁止重复执行,仅限全新建库)
008_migrate_teacher.sql -- 历史数据迁移:清洗并提升历史教师档案
009_drop_legacy_score.sql -- 清理废弃结构:安全下线旧版无权重成绩表
010_verify.sql -- 终检验收:断言表结构、外键与索引 100% 合规
```
================================================================================
CLEAN_DATABASE_BOOTSTRAP_CHAIN (标准纯净库引导执行链)
================================================================================
### 2.2 系统底座与权限治理补丁 (`RuoYi-Vue/sql/system/kingbase/`)
```text
001_sys_oper_log_cost_time.sql -- 操作日志补充耗时字段
002_legacy_analytics_permissions.sql -- 统计分析历史权限调整
003_report_attendance_action_permissions.sql -- 现场报到与考勤动作权限
004_rbac_identity_binding.sql -- 教师与学员用户身份强绑定支持
005_training_roles_permissions.sql -- 培训业务角色细粒度权限配置
006_accommodation_history_constraint.sql -- 住宿历史单在用唯一约束
008_external_resource_operation.sql -- 外部系统操作流水表结构
009_dorm_authorization_orchestration.sql -- 宿舍门禁编排中间状态表
010_dms_access_management_permissions.sql -- DMS 门禁管理端菜单权限
011_teacher_student_remove_permissions.sql -- 教师与学员安全删除权限隔离
012_analytics_v1_permissions.sql -- 分析大盘新版看板菜单权限
013_interaction_route_cleanup.sql -- 交互路由与无效菜单项清理
014_dms_access_safety_and_accommodation_permissions.sql -- DMS 安全防线与住宿菜单完善
015_dms_package_a_hardening.sql -- DMS Package A 门禁强化脚本
[STEP 0: 数据库实例与方言就绪]
└─ 执行: CREATE DATABASE training_demo_clean WITH OWNER = kingbase;
└─ 确保: database_mode = mysql, search_path = public
[STEP 1: RuoYi 基础平台结构与初始化]
├─ 1.1 RuoYi-Vue/sql/ry_20250522.sql (sys_* 基础表与系统管理员、默认字典)
├─ 1.2 RuoYi-Vue/sql/quartz.sql (QRTZ_* 调度引擎 11 张基础表)
└─ 1.3 RuoYi-Vue/sql/generator/kingbase/ (002a + 002b Generator 主键 Identity 补丁)
[STEP 2: 培训业务历史基线骨架构建]
├─ 2.1 RuoYi-Vue/sql/train/v2/rollback/000_phase05_exact_schema.sql
│ (创建 14 张 Phase 0.5 历史基线表、外键、唯一约束与 update_time 触发器函数)
└─ 2.2 注入 1 条符合基线要求的初始教师记录 (为通过 000 预检与 008 数据平滑清洗)
[STEP 3: 培训业务 V2 结构演进迁移]
├─ 3.1 000_preflight.sql (严格只读核验 Phase 0.5 基线与 sys_* 行数)
├─ 3.2 000_tx_capability_probe.sql (验证显式事务与 DDL 回滚能力)
├─ 3.3 001_backup_current_schema.sql (创建 bak_v1_* 历史结构快照)
├─ 3.4 002_create_new_tables.sql (创建 8 张 V2 新表: 排课、选课、住宿台账等)
├─ 3.5 003_alter_master_tables.sql (解绑旧外键/触发器,扩展主数据表字段)
├─ 3.6 004_rebuild_business_tables.sql (重构 5 张空业务过程表)
├─ 3.7 005_constraints.sql (补充 V2 级联完整性与 CHECK 互斥约束)
├─ 3.8 006_indexes.sql (创建排课冲突与高频组合性能索引)
├─ 3.9 【跳过 007_dicts.sql】(严禁执行)
├─ 3.10 008_migrate_teacher.sql (清洗提升 1 条基线教师并固化 NOT NULL 约束)
├─ 3.11 009_drop_legacy_score.sql (安全淘汰旧 train_score_info 表)
└─ 3.12 010_verify.sql (终检验收 V2 架构 100% 合规)
[STEP 4: 系统底层与权限治理强化补丁]
├─ 4.1 001_sys_oper_log_cost_time.sql (日志耗时字段)
├─ 4.2 002_legacy_analytics_permissions.sql
├─ 4.3 003_report_attendance_action_permissions.sql
├─ 4.4 004_rbac_identity_binding.sql (强绑定教师/学员与 sys_user 账号)
├─ 4.5 005_training_roles_permissions.sql (初始化 train_admin/teacher/student 3大业务角色)
├─ 4.6 006_accommodation_history_constraint.sql (在用床位局部唯一索引)
├─ 4.7 008_external_resource_operation.sql (创建外部资源映射与操作流水表)
├─ 4.8 009_dorm_authorization_orchestration.sql (门禁凭据与授权生命周期扩展)
├─ 4.9 010_dms_access_management_permissions.sql
├─ 4.10 011_teacher_student_remove_permissions.sql
├─ 4.11 012_analytics_v1_permissions.sql
├─ 4.12 013_interaction_route_cleanup.sql
├─ 4.13 014_dms_access_safety_and_accommodation_permissions.sql
└─ 4.14 015_dms_package_a_hardening.sql (ACCOM_PERM 闭环,授权 role_id=3 拥有 menu 2263)
[STEP 5: 数据库架构与完整性断言终检]
├─ 断言 21 张 train_* 业务表全部存在且 DDL 结构合规
├─ 断言 15 张核心 sys_* 表无受损,角色 3 具备 menu 2263 且无破坏性 remove 权限
└─ 检查 0 孤儿外键、0 冲突索引
[STEP 6: 确定性演示种子数据灌入 (Deterministic Demo Seed)]
└─ 灌入时序严密、100% 覆盖 UI 界面的高质量确定性演示业务数据 (绝不含历史脏数据)
================================================================================
```
---
## 3. 全量业务数据表总账 (21 张 `train_*` 表)
| 表名 (TABLE_NAME) | 物理主键类型 | 表职责说明 (PURPOSE) | 核心外键与关键关联 (RELATIONSHIPS) |
| :--- | :--- | :--- | :--- |
| `train_teacher` | `VARCHAR(32)` | 授课教师档案主表,记录姓名、工号、职称、身份证(国密密文) | `sys_user.user_id` (账号绑定关系) |
| `train_student` | `VARCHAR(32)` | 参训学员主档表,全周期记录学员信息、单位、手机与国密身份证 | `sys_user.user_id` (账号绑定关系) |
| `train_course` | `VARCHAR(32)` | 课程标准库主表,记录课程编号、名称、理论/实作类别与基准学时 | 被 `train_plan_course`、`train_lesson` 引用 |
| `train_classroom_info` | `BIGINT (ID)` | 教学教室信息表,记录教室编号、楼栋、容纳人数与多媒体配备 | 被 `train_lesson` 引用 (教室时段互斥) |
| `train_training_site` | `BIGINT (ID)` | 实训演练场地表,记录室外/室内实训工区、容量与安全规范 | 被 `train_lesson` 引用 (场地时段互斥) |
| `train_plan` | `VARCHAR(32)` | 培训开班计划主表,控制培训项目全生命周期与时间跨度 | 驱动 `train_plan_course`、`train_enrollment` |
| `train_plan_course` | `BIGINT (ID)` | 班级课程关系表 (N:M),指定某培训班开设哪门课及指定授课教师 | 关联 `plan_id`、`c_id`、`t_id` |
| `train_enrollment` | `BIGINT (ID)` | 参训人员名册表,定义哪个学员参加哪期培训班及参训状态 | 关联 `plan_id`、`s_id` (状态: 待报到/在训/结训) |
| `train_lesson` | `BIGINT (ID)` | 课次日程排课表,系统排课核心表,记录每次课的具体时段与地点 | 关联 `plan_id`、`plan_course_id`、`t_id`、教室/场地 |
| `train_student_checkin` | `BIGINT (ID)` | 课堂考勤打卡流水表,记录学员在课次的签到、签退与出勤状态 | 关联 `lesson_id`、`s_id` (状态: 0缺勤/1正常/2迟到/3早退/4请假) |
| `train_class_report` | `BIGINT (ID)` | 现场报到核验记录表,学员到校开班报到凭据流水 | 关联 `enrollment_id`、`s_id`、`plan_id` |
| `train_dormitory_info` | `BIGINT (ID)` | 宿舍房间主表,记录宿舍楼栋、房号、性别分类、总床位数与在用数 | 被 `train_accommodation` 引用 |
| `train_accommodation` | `BIGINT (ID)` | 学员住宿分配台账表,记录床位分配、入住时间、退宿时间与状态 | 关联 `s_id`、`dorm_id`、`plan_id` (状态: 预分配0/在住1/已退2) |
| `train_score_info` | `BIGINT (ID)` | 学员培训成绩表,记录各科目考评得分与最终成绩评定 | 关联 `plan_id`、`s_id`、`c_id` (score >= 0 CHECK) |
| `train_study_duration` | `BIGINT (ID)` | 自主学习时长流水表,记录学员在线研读教学资料的计时时长 | 关联 `s_id`、`resource_id` |
| `train_resource` | `VARCHAR(32)` | 统一教学资源主表,存放课件、视频、教材电子档等资源元数据 | 被 `train_course_resource` 引用 |
| `train_course_resource`| `BIGINT (ID)` | 课程与教学资源关联表 (N:M) | 关联 `c_id`、`resource_id` |
| `train_electronic_board`| `BIGINT (ID)` | 电子班牌硬件设备信息表,记录设备 MAC、IP、挂接教室与通信时间 | 关联 `classroom_id` |
| `train_external_resource_mapping` | `BIGINT (ID)` | 外部资源映射表,记录本地宿舍房间与外部 DMS 空间/锁具的映射 | 关联 `local_resource_id`、`external_id` (DMS) |
| `train_dorm_auth` | `BIGINT (ID)` | 门禁卡/密码授权编排状态表,维护门锁下发授权生命周期 | 关联 `accommodation_id`、`external_auth_id` |
| `train_external_operation` | `BIGINT (ID)` | 外部异步操作流水表,记录向 DMS 下发密码/撤销的异步 operationId | 关联 `auth_id`、`operation_type`、重试次数 |
当前正式数据库设计包含且仅包含以下 21 张业务表:
---
## 4. 后续纯净演示库重建计划 (`CLEAN_DEMO_DATABASE`)
为彻底消除历史演示留存的脏数据、断言污染与测试垃圾,后续正式 Demo 执行前**严禁直接使用已污染的旧库**,必须按以下规程建立纯净演示数据库:
```text
[CLEAN_DEMO_DATABASE 重建 SOP]
1. 在 KingbaseES 实例新建独立数据库:training_demo_clean
2. 按序执行 2.1 节 000~010 全量业务迁移脚本 (确保 0 errors)
3. 按序执行 2.2 节 001~015 系统与权限增量补丁
4. 执行全新字典与菜单种子导入
5. 灌入经过严格卫生校验的确定性业务种子数据 (Deterministic Demo Seed):
- 标准教师 5 名、学员 30 名、课程 6 门、教室 4 间、宿舍 8 间
- 2 期标准培训班(1 期已结训供查历史,1 期正在进行供现场演示)
- 保证 100% 前端 UI 具有真实有效数据,无孤儿数据,无外键断裂
```
| 序号 | 表名 (TABLE_NAME) | 物理主键类型 | 来源迁移脚本 | 表职责说明 (PURPOSE) | 核心外键与关键关联 (RELATIONSHIPS) |
| :---: | :--- | :--- | :---: | :--- | :--- |
| **01** | `train_teacher` | `VARCHAR(32)` | 000 + 003 + 008 | 授课教师档案主表,记录姓名、工号、职称、身份证密文 | `sys_user.user_id` (账号强绑定) |
| **02** | `train_student` | `VARCHAR(32)` | 000 + 003 | 参训学员主档表,记录学员信息、单位、手机与身份证密文 | `sys_user.user_id` (账号强绑定) |
| **03** | `train_course` | `VARCHAR(32)` | 000 + 003 | 课程标准库主表,记录课程编号、名称、理论/实作类别与学时 | 被 `train_plan_course`、`train_lesson` 引用 |
| **04** | `train_classroom_info` | `BIGINT (ID)` | 000 + 003 | 教学教室信息表,记录教室编号、楼栋、容纳人数与配备 | 被 `train_lesson` 引用 (教室时段互斥) |
| **05** | `train_training_site` | `BIGINT (ID)` | 000 + 003 | 实训演练场地表,记录室内/室外工区、容量与安全规范 | 被 `train_lesson` 引用 (场地时段互斥) |
| **06** | `train_plan` | `VARCHAR(32)` | 000 + 003 | 培训开班计划主表,控制培训项目全生命周期与时间跨度 | 驱动 `train_plan_course`、`train_enrollment` |
| **07** | `train_plan_course` | `BIGINT (ID)` | 002 | 班级课程关系表 (N:M),指定培训班开设课程及授课教师 | 关联 `plan_id`、`c_id`、`t_id` |
| **08** | `train_enrollment` | `BIGINT (ID)` | 002 | 参训人员名册表,定义学员参加班级及参训状态 (待报到/在训/结训) | 关联 `plan_id`、`s_id` |
| **09** | `train_lesson` | `BIGINT (ID)` | 002 | 课次排课表,记录每次课的具体时段、地点与授课教师 (互斥 CHECK) | 关联 `plan_id`、`plan_course_id`、`t_id`、场地 |
| **10** | `train_student_checkin` | `BIGINT (ID)` | 004 重建 | 课堂考勤打卡流水表,记录学员签到、签退与出勤状态 | 关联 `lesson_id`、`s_id` |
| **11** | `train_class_report` | `BIGINT (ID)` | 004 重建 | 现场报到核验记录表,学员到校开班报到凭据流水 | 关联 `enrollment_id`、`s_id`、`plan_id` |
| **12** | `train_dormitory_info` | `BIGINT (ID)` | 000 + 003 | 宿舍房间主表,记录宿舍楼栋、房号、性别分类、总床位数与在用数 | 被 `train_accommodation` 引用 |
| **13** | `train_accommodation` | `BIGINT (ID)` | 002 | 学员住宿分配台账表,记录床位分配、入住/退宿/调房生命周期 | 关联 `s_id`、`dorm_id`、`plan_id` |
| **14** | `train_score_info` | `BIGINT (ID)` | 002 | 学员培训成绩表,记录各科目考评得分与最终成绩评定 | 关联 `plan_id`、`s_id`、`c_id` (score >= 0 CHECK) |
| **15** | `train_study_duration` | `BIGINT (ID)` | 004 重建 | 自主学习时长流水表,记录学员研读教学资料的计时时长 | 关联 `s_id`、`resource_id` |
| **16** | `train_resource` | `VARCHAR(32)` | 002 | 统一教学资源主表,存放课件、视频、教材电子档等元数据 | 被 `train_course_resource` 引用 |
| **17** | `train_course_resource`| `BIGINT (ID)` | 002 | 课程与教学资源关联表 (N:M) | 关联 `c_id`、`resource_id` |
| **18** | `train_electronic_board`| `BIGINT (ID)` | 000 + 003 | 电子班牌硬件设备信息表,记录设备 MAC、IP、挂接教室与通信时间 | 关联 `classroom_id` |
| **19** | `train_external_resource_mapping` | `BIGINT (ID)` | 系统 008 | 外部资源映射表,记录本地宿舍与外部 DMS 空间/锁具的映射关系 | 关联 `dorm_id`、`external_resource_id` |
| **20** | `train_dorm_auth` | `BIGINT (ID)` | 004 + 系统 009 | 门禁卡/密码授权编排状态表,维护门锁下发授权生命周期 | 关联 `accommodation_id`、`external_auth_id` |
| **21** | `train_external_operation` | `BIGINT (ID)` | 系统 008 | 外部异步操作流水表,记录向 DMS 下发密码/撤销的异步 operationId | 关联 `auth_id`、`operation_type`、重试次数 |
+142 -126
View File
@@ -1,136 +1,152 @@
# 04 - 系统全量 API 接口总账 (API Inventory)
# 04 - 系统全量 API 接口总账与数据库调用链 (API Inventory & Database Lineage)
> **审计基准与规范**:
> 1. **接口扫描源**:严格基于 `RuoYi-Vue/ruoyi-admin/src/main/java/com/ruoyi/web/controller` 下 Spring MVC 注解扫描;
> 2. **数据源分类 (SOURCE)**:严格限定为 `RAILWAYSYSTEM_INTERNAL`、`CLIENT_PROVIDED`、`THIRD_PARTY`、`MOCK`;
> 3. **防虚假推定准则 (Anti-Heuristic Discipline)**:
> - **`DATABASE_TABLE`**:必须通过 `Controller → Service → Mapper → SQL/Entity` 源码调用链完整确认,标记为 **`VERIFIED_FROM_SOURCE`**;未完成调用链代码确认的标记为 `NOT_YET_VERIFIED`,严禁根据 URL 名称盲目猜测;
> - **`USED_BY_UI`**:必须通过 `build_ui/src/api/**` 与 `build_ui/src/views/**` 实际调用证据确认,分为 **`VERIFIED_USED_BY_UI`**(API 文件定义且被 View 组件导入调用)、**`DEFINED_IN_UI_API_ONLY`**(API 文件已声明函数但 View 暂未直接引用)、**`NOT_FOUND_IN_UI`**(前端未定义),严禁无证据一刀切填 `YES`;
> - **`IMPLEMENTATION_STATUS`**:Controller 存在仅证明端点已定义,标注为 **`ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)`**,受外部硬件阻断的标注为 **`ENDPOINT_DEFINED (BLOCKED_EXTERNAL)`**。
> **最高原则**:**拒绝根据 URL 猜测表名与调用状态**!
> 1. **`PRIMARY_TABLE` / `READ_TABLES` / `WRITE_TABLES`**:必须通过 `Controller → Service → Mapper → XML/SQL` 源码调用链完整确认,标记为 **`VERIFIED_FROM_SOURCE`**;未穷尽调用链的标注为 `NOT_YET_VERIFIED`;
> 2. **`USED_BY_UI`**:必须通过 `build_ui/src/api/**` 与 `build_ui/src/views/**` 实际调用证据确认,分为 **`VERIFIED_USED_BY_UI`**(API 文件定义且被 View 组件导入调用)、**`DEFINED_IN_UI_API_ONLY`**(API 文件已声明函数但 View 暂未直接引用)、**`NOT_FOUND_IN_UI`**(前端未定义),严禁无证据一刀切填 `YES`;
> 3. **`IMPLEMENTATION_STATUS`**:Controller 存在仅证明端点已定义,标注为 **`ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)`**,受外部硬件阻断的标注为 **`ENDPOINT_DEFINED (BLOCKED_EXTERNAL)`**。
---
## 1. 核心培训业务 API 账本 (`TRAIN_BUSINESS`)
## 1. 核心培训业务 API 账本 (`CUSTOM_TRAIN_BUSINESS_API`)
| 接口路径 (API) | 请求方式 (METHOD) | 数据来源 (SOURCE) | 承载控制器 (CONTROLLER) | 关联物理表 (DATABASE_TABLE) | 表追踪状态 (TABLE_STATUS) | UI调用状态 (USED_BY_UI) | 实现状态 (STATUS) |
| :--- | :---: | :---: | :--- | :--- | :---: | :---: | :---: |
| `/train/teacher/list` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainTeacherController` | `train_teacher` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/teacher/{tId}` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainTeacherController` | `train_teacher` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/teacher` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainTeacherController` | `train_teacher` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/teacher` | `PUT` | `RAILWAYSYSTEM_INTERNAL` | `TrainTeacherController` | `train_teacher` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/teacher/{tIds}` | `DELETE` | `RAILWAYSYSTEM_INTERNAL` | `TrainTeacherController` | `train_teacher` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/teacher/export` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainTeacherController` | `train_teacher` | `VERIFIED_FROM_SOURCE` | `DEFINED_IN_UI_API_ONLY` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/me/teacher/plans` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainTeacherMeController` | `train_plan` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/me/teacher` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainTeacherMeController` | `train_lesson` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/me/teacher/students` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainTeacherMeController` | `train_enrollment` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/me/teacher/lessons/{lessonId}/attendance` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainTeacherMeController` | `train_student_checkin` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/student/list` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainStudentController` | `train_student` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/student/{sId}` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainStudentController` | `train_student` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/student` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainStudentController` | `train_student` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/student` | `PUT` | `RAILWAYSYSTEM_INTERNAL` | `TrainStudentController` | `train_student` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/student/{sIds}` | `DELETE` | `RAILWAYSYSTEM_INTERNAL` | `TrainStudentController` | `train_student` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/student/export` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainStudentController` | `train_student` | `VERIFIED_FROM_SOURCE` | `DEFINED_IN_UI_API_ONLY` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/student/importTemplate` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainStudentController` | `train_student` | `VERIFIED_FROM_SOURCE` | `DEFINED_IN_UI_API_ONLY` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/student/importData` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainStudentController` | `train_student` | `VERIFIED_FROM_SOURCE` | `DEFINED_IN_UI_API_ONLY` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/me/student/enrollments` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainStudentMeController` | `train_enrollment` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/me/student/timetable` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainStudentMeController` | `train_lesson` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/me/student/report` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainStudentMeController` | `train_class_report` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/me/student/attendance` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainStudentMeController` | `train_student_checkin` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/me/student/duration` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainStudentMeController` | `train_study_duration` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/me/student/portrait` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainStudentMeController` | `train_student` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/course/list` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainCourseController` | `train_course` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/course/{cId}` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainCourseController` | `train_course` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/course` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainCourseController` | `train_course` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/course` | `PUT` | `RAILWAYSYSTEM_INTERNAL` | `TrainCourseController` | `train_course` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/course/{cIds}` | `DELETE` | `RAILWAYSYSTEM_INTERNAL` | `TrainCourseController` | `train_course` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/classroom/list` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainClassroomInfoController` | `train_classroom_info` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/classroom/{classRoomId}` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainClassroomInfoController` | `train_classroom_info` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/classroom` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainClassroomInfoController` | `train_classroom_info` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/classroom` | `PUT` | `RAILWAYSYSTEM_INTERNAL` | `TrainClassroomInfoController` | `train_classroom_info` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/classroom/{classRoomIds}`| `DELETE` | `RAILWAYSYSTEM_INTERNAL` | `TrainClassroomInfoController` | `train_classroom_info` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/training-site/list` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainTrainingSiteController` | `train_training_site` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/training-site/{siteId}` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainTrainingSiteController` | `train_training_site` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/training-site` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainTrainingSiteController` | `train_training_site` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/training-site` | `PUT` | `RAILWAYSYSTEM_INTERNAL` | `TrainTrainingSiteController` | `train_training_site` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/training-site/{siteIds}`| `DELETE` | `RAILWAYSYSTEM_INTERNAL` | `TrainTrainingSiteController` | `train_training_site` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/plans` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainPlanController` | `train_plan` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/plans/{planId}` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainPlanController` | `train_plan` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/plans` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainPlanController` | `train_plan` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/plans/{planId}` | `PUT` | `RAILWAYSYSTEM_INTERNAL` | `TrainPlanController` | `train_plan` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/plans/{planIds}` | `DELETE` | `RAILWAYSYSTEM_INTERNAL` | `TrainPlanController` | `train_plan` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/plans/{planId}/publish` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainPlanController` | `train_plan` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/plans/{planId}/start` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainPlanController` | `train_plan` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/plans/{planId}/complete`| `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainPlanController` | `train_plan` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/plans/{planId}/courses` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainPlanCourseController` | `train_plan_course` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/plans/{planId}/courses` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainPlanCourseController` | `train_plan_course` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/plans/{planId}/courses/{planCourseId}` | `DELETE` | `RAILWAYSYSTEM_INTERNAL` | `TrainPlanCourseController` | `train_plan_course` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/plans/{planId}/enrollments` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainEnrollmentController` | `train_enrollment` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/plans/{planId}/enrollments` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainEnrollmentController` | `train_enrollment` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/plans/{planId}/enrollments/batch` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainEnrollmentController` | `train_enrollment` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/enrollments/{enrollmentId}` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainEnrollmentController` | `train_enrollment` | `VERIFIED_FROM_SOURCE` | `DEFINED_IN_UI_API_ONLY` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/enrollments/{enrollmentId}/status` | `PUT` | `RAILWAYSYSTEM_INTERNAL` | `TrainEnrollmentController` | `train_enrollment` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/enrollments/{enrollmentId}` | `DELETE` | `RAILWAYSYSTEM_INTERNAL` | `TrainEnrollmentController` | `train_enrollment` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/plans/{planId}/lessons` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainLessonController` | `train_lesson` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/plans/{planId}/lessons` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainLessonController` | `train_lesson` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/lessons/{lessonId}` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainLessonController` | `train_lesson` | `VERIFIED_FROM_SOURCE` | `DEFINED_IN_UI_API_ONLY` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/lessons/{lessonId}` | `PUT` | `RAILWAYSYSTEM_INTERNAL` | `TrainLessonController` | `train_lesson` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/lessons/{lessonId}` | `DELETE` | `RAILWAYSYSTEM_INTERNAL` | `TrainLessonController` | `train_lesson` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/lessons/check-conflict` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainLessonController` | `train_lesson` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/lessons/scheduling-options` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainLessonController` | `train_classroom_info` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/plans/{planId}/timetable` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainLessonController` | `train_lesson` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/enrollments/{enrollmentId}/report` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainReportActionController` | `train_class_report` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/report/list` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainClassReportController` | `train_class_report` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/checkin/list` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainStudentCheckinController` | `train_student_checkin` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/attendance/lessons/{lessonId}/checkins` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `AttendanceController` | `train_student_checkin` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/attendance/sign-in` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `AttendanceController` | `train_student_checkin` | `VERIFIED_FROM_SOURCE` | `DEFINED_IN_UI_API_ONLY` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/attendance/sign-out` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `AttendanceController` | `train_student_checkin` | `VERIFIED_FROM_SOURCE` | `DEFINED_IN_UI_API_ONLY` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/attendance/proxy-checkin` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `AttendanceController` | `train_student_checkin` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/attendance/mark-absent` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `AttendanceController` | `train_student_checkin` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/attendance/adjust` | `PUT` | `RAILWAYSYSTEM_INTERNAL` | `AttendanceController` | `train_student_checkin` | `VERIFIED_FROM_SOURCE` | `DEFINED_IN_UI_API_ONLY` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/dormitory/list` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainDormitoryInfoController` | `train_dormitory_info` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/dormitory/{dormId}` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainDormitoryInfoController` | `train_dormitory_info` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/dormitory` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainDormitoryInfoController` | `train_dormitory_info` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/dormitory` | `PUT` | `RAILWAYSYSTEM_INTERNAL` | `TrainDormitoryInfoController` | `train_dormitory_info` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/dormitory/{dormIds}` | `DELETE` | `RAILWAYSYSTEM_INTERNAL` | `TrainDormitoryInfoController` | `train_dormitory_info` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/accommodation/list` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccommodationController` | `train_accommodation` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/accommodation/{accommodationId}` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccommodationController` | `train_accommodation` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/accommodation/enrollment/{enrollmentId}` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccommodationController` | `train_accommodation` | `VERIFIED_FROM_SOURCE` | `DEFINED_IN_UI_API_ONLY` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/accommodation/enrollment/{enrollmentId}/history` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccommodationController` | `train_accommodation` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/accommodation` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccommodationController` | `train_accommodation` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/accommodation/{accommodationId}/checkin` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccommodationController` | `train_accommodation` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/accommodation/{accommodationId}/checkout` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccommodationController` | `train_accommodation` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/accommodation/{accommodationId}/transfer` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccommodationController` | `train_accommodation` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/accommodation/{accommodationIds}` | `DELETE` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccommodationController` | `train_accommodation` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/score/list` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainScoreInfoController` | `train_score_info` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/score/{scoreId}` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainScoreInfoController` | `train_score_info` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/score` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainScoreInfoController` | `train_score_info` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/score` | `PUT` | `RAILWAYSYSTEM_INTERNAL` | `TrainScoreInfoController` | `train_score_info` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/score/{scoreIds}` | `DELETE` | `RAILWAYSYSTEM_INTERNAL` | `TrainScoreInfoController` | `train_score_info` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/analysis/dashboard/overview` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainAnalysisController` | 聚合多表 | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/analysis/dashboard/charts` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainAnalysisController` | 聚合多表 | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/analysis/attendance/summary` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainAnalysisController` | 聚合多表 | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/analysis/attendance/charts` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainAnalysisController` | 聚合多表 | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/analysis/portrait/student-360/{studentId}` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainAnalysisController` | 聚合多表 | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/access/mapping/list` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccessManagementController` | `train_external_resource_mapping` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/access/auth/list` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccessManagementController` | `train_dorm_auth` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/access/operation/list` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccessManagementController` | `train_external_operation` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/access/capability` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccessManagementController` | N/A (常量配置) | `VERIFIED_FROM_SOURCE` | `DEFINED_IN_UI_API_ONLY` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/access/issue` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccessManagementController` | `train_dorm_auth` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BLOCKED_EXTERNAL)` |
| `/train/access/revoke` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccessManagementController` | `train_dorm_auth` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BLOCKED_EXTERNAL)` |
| `/train/binding/teachers/bindable-users` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccountBindingAdminController` | `sys_user` | `VERIFIED_FROM_SOURCE` | `NOT_FOUND_IN_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/binding/teachers/{teacherId}/bind` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccountBindingAdminController` | `train_teacher` | `VERIFIED_FROM_SOURCE` | `NOT_FOUND_IN_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/binding/students/bindable-users` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccountBindingAdminController` | `sys_user` | `VERIFIED_FROM_SOURCE` | `NOT_FOUND_IN_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/binding/students/{studentId}/bind` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccountBindingAdminController` | `train_student` | `VERIFIED_FROM_SOURCE` | `NOT_FOUND_IN_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| 接口路径 (API) | 请求方式 (METHOD) | 数据来源 (SOURCE) | 承载控制器 (CONTROLLER) | 主实体表 (PRIMARY_TABLE) | 读操作表 (READ_TABLES) | 写操作表 (WRITE_TABLES) | 调用链追踪状态 (LINEAGE_STATUS) | UI调用状态 (USED_BY_UI) | 实现状态 (STATUS) |
| :--- | :---: | :---: | :--- | :--- | :--- | :--- | :---: | :---: | :---: |
| `/train/teacher/list` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainTeacherController` | `train_teacher` | `train_teacher` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/teacher/{tId}` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainTeacherController` | `train_teacher` | `train_teacher` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/teacher` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainTeacherController` | `train_teacher` | `NONE` | `train_teacher` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/teacher` | `PUT` | `RAILWAYSYSTEM_INTERNAL` | `TrainTeacherController` | `train_teacher` | `train_teacher` | `train_teacher` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/teacher/{tIds}` | `DELETE` | `RAILWAYSYSTEM_INTERNAL` | `TrainTeacherController` | `train_teacher` | `train_teacher` | `train_teacher` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/teacher/export` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainTeacherController` | `train_teacher` | `NONE` | `train_teacher` | `VERIFIED_FROM_SOURCE` | `DEFINED_IN_UI_API_ONLY` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/me/teacher/plans` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainTeacherMeController` | `train_teacher` | `train_teacher` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/me/teacher` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainTeacherMeController` | `train_teacher` | `train_teacher` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/me/teacher/students` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainTeacherMeController` | `train_teacher` | `train_teacher` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/me/teacher/lessons/{lessonId}/attendance` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainTeacherMeController` | `train_teacher` | `train_teacher` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/student/list` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainStudentController` | `train_student` | `train_student` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/student/{sId}` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainStudentController` | `train_student` | `train_student` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/student` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainStudentController` | `train_student` | `NONE` | `train_student` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/student` | `PUT` | `RAILWAYSYSTEM_INTERNAL` | `TrainStudentController` | `train_student` | `train_student` | `train_student` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/student/{sIds}` | `DELETE` | `RAILWAYSYSTEM_INTERNAL` | `TrainStudentController` | `train_student` | `train_student` | `train_student` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/student/export` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainStudentController` | `train_student` | `train_student` | `NONE` | `VERIFIED_FROM_SOURCE` | `DEFINED_IN_UI_API_ONLY` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/student/importTemplate` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainStudentController` | `train_student` | `train_student` | `NONE` | `VERIFIED_FROM_SOURCE` | `DEFINED_IN_UI_API_ONLY` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/student/importData` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainStudentController` | `train_student` | `NONE` | `train_student` | `VERIFIED_FROM_SOURCE` | `DEFINED_IN_UI_API_ONLY` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/me/student/enrollments` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainStudentMeController` | `train_student` | `train_student` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/me/student/timetable` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainStudentMeController` | `train_student` | `train_student` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/me/student/report` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainStudentMeController` | `train_student` | `train_student` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/me/student/attendance` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainStudentMeController` | `train_student` | `train_student` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/me/student/duration` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainStudentMeController` | `train_student` | `train_student` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/me/student/portrait` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainStudentMeController` | `train_student` | `train_student` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/course/list` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainCourseController` | `train_course` | `train_course` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/course/{cId}` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainCourseController` | `train_course` | `train_course` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/course` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainCourseController` | `train_course` | `NONE` | `train_course` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/course` | `PUT` | `RAILWAYSYSTEM_INTERNAL` | `TrainCourseController` | `train_course` | `train_course` | `train_course` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/course/{cIds}` | `DELETE` | `RAILWAYSYSTEM_INTERNAL` | `TrainCourseController` | `train_course` | `train_course` | `train_course` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/classroom/list` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainClassroomInfoController` | `train_classroom_info` | `train_classroom_info` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/classroom/{classRoomId}` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainClassroomInfoController` | `train_classroom_info` | `train_classroom_info` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/classroom` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainClassroomInfoController` | `train_classroom_info` | `NONE` | `train_classroom_info` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/classroom` | `PUT` | `RAILWAYSYSTEM_INTERNAL` | `TrainClassroomInfoController` | `train_classroom_info` | `train_classroom_info` | `train_classroom_info` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/classroom/{classRoomIds}` | `DELETE` | `RAILWAYSYSTEM_INTERNAL` | `TrainClassroomInfoController` | `train_classroom_info` | `train_classroom_info` | `train_classroom_info` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/training-site/list` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainTrainingSiteController` | `train_training_site` | `train_training_site` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/training-site/{siteId}` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainTrainingSiteController` | `train_training_site` | `train_training_site` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/training-site` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainTrainingSiteController` | `train_training_site` | `NONE` | `train_training_site` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/training-site` | `PUT` | `RAILWAYSYSTEM_INTERNAL` | `TrainTrainingSiteController` | `train_training_site` | `train_training_site` | `train_training_site` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/training-site/{siteIds}` | `DELETE` | `RAILWAYSYSTEM_INTERNAL` | `TrainTrainingSiteController` | `train_training_site` | `train_training_site` | `train_training_site` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/plans` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainPlanController` | `train_plan` | `train_class_plan` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/plans/{planId}` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainPlanController` | `train_plan` | `train_class_plan` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/plans` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainPlanController` | `train_plan` | `train_class_plan` | `train_class_plan` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/plans/{planId}` | `PUT` | `RAILWAYSYSTEM_INTERNAL` | `TrainPlanController` | `train_plan` | `train_class_plan` | `train_class_plan` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/plans/{planIds}` | `DELETE` | `RAILWAYSYSTEM_INTERNAL` | `TrainPlanController` | `train_plan` | `train_class_plan` | `train_class_plan` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/plans/{planId}/publish` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainPlanController` | `train_plan` | `train_class_plan` | `train_class_plan` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/plans/{planId}/start` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainPlanController` | `train_plan` | `train_class_plan` | `train_class_plan` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/plans/{planId}/complete` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainPlanController` | `train_plan` | `train_class_plan` | `train_class_plan` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/plans/{planId}/courses` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainPlanCourseController` | `train_plan_course` | `train_plan_course, train_course, train_teacher` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/plans/{planId}/courses` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainPlanCourseController` | `train_plan_course` | `train_plan_course` | `train_plan_course` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/plans/{planId}/courses/{planCourseId}` | `DELETE` | `RAILWAYSYSTEM_INTERNAL` | `TrainPlanCourseController` | `train_plan_course` | `train_plan_course` | `train_plan_course` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/plans/{planId}/enrollments` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainEnrollmentController` | `train_enrollment` | `train_enrollment, train_student, train_class_plan` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/plans/{planId}/enrollments` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainEnrollmentController` | `train_enrollment` | `train_enrollment, train_student` | `train_enrollment` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/plans/{planId}/enrollments/batch` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainEnrollmentController` | `train_enrollment` | `train_enrollment, train_student` | `train_enrollment` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/enrollments/{enrollmentId}` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainEnrollmentController` | `train_enrollment` | `train_enrollment, train_student, train_class_plan` | `NONE` | `VERIFIED_FROM_SOURCE` | `DEFINED_IN_UI_API_ONLY` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/enrollments/{enrollmentId}/status` | `PUT` | `RAILWAYSYSTEM_INTERNAL` | `TrainEnrollmentController` | `train_enrollment` | `train_enrollment` | `train_enrollment` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/enrollments/{enrollmentId}` | `DELETE` | `RAILWAYSYSTEM_INTERNAL` | `TrainEnrollmentController` | `train_enrollment` | `train_enrollment` | `train_enrollment` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/plans/{planId}/lessons` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainLessonController` | `train_lesson` | `train_lesson, train_class_plan, train_course, train_teacher, train_classroom_info, train_training_site` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/plans/{planId}/lessons` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainLessonController` | `train_lesson` | `train_lesson, train_classroom_info, train_training_site` | `train_lesson` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/lessons/{lessonId}` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainLessonController` | `train_lesson` | `train_lesson, train_class_plan, train_course, train_teacher, train_classroom_info, train_training_site` | `NONE` | `VERIFIED_FROM_SOURCE` | `DEFINED_IN_UI_API_ONLY` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/lessons/{lessonId}` | `PUT` | `RAILWAYSYSTEM_INTERNAL` | `TrainLessonController` | `train_lesson` | `train_lesson, train_classroom_info, train_training_site` | `train_lesson` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/lessons/{lessonId}` | `DELETE` | `RAILWAYSYSTEM_INTERNAL` | `TrainLessonController` | `train_lesson` | `train_lesson, train_classroom_info, train_training_site` | `train_lesson` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/lessons/check-conflict` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainLessonController` | `train_lesson` | `train_lesson, train_classroom_info, train_training_site` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/lessons/scheduling-options` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainLessonController` | `train_classroom_info` | `train_classroom_info, train_training_site, train_teacher` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/plans/{planId}/timetable` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainLessonController` | `train_lesson` | `train_lesson, train_class_plan, train_course, train_teacher, train_classroom_info, train_training_site` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/enrollments/{enrollmentId}/report` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainReportActionController` | `train_class_report` | `train_enrollment, train_class_report` | `train_class_report, train_enrollment` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/report/list` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainClassReportController` | `train_class_report` | `train_class_report, train_student, train_class_plan` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/checkin/list` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainStudentCheckinController` | `train_student_checkin` | `train_student_checkin, train_student, train_lesson` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/attendance/lessons/{lessonId}/checkins` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `AttendanceController` | `train_student_checkin` | `train_student_checkin, train_lesson, train_enrollment` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/attendance/sign-in` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `AttendanceController` | `train_student_checkin` | `train_student_checkin, train_lesson` | `train_student_checkin` | `VERIFIED_FROM_SOURCE` | `DEFINED_IN_UI_API_ONLY` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/attendance/sign-out` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `AttendanceController` | `train_student_checkin` | `train_student_checkin, train_lesson` | `train_student_checkin` | `VERIFIED_FROM_SOURCE` | `DEFINED_IN_UI_API_ONLY` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/attendance/proxy-checkin` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `AttendanceController` | `train_student_checkin` | `train_student_checkin, train_lesson` | `train_student_checkin` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/attendance/mark-absent` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `AttendanceController` | `train_student_checkin` | `train_student_checkin, train_lesson` | `train_student_checkin` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/attendance/adjust` | `PUT` | `RAILWAYSYSTEM_INTERNAL` | `AttendanceController` | `train_student_checkin` | `train_student_checkin, train_lesson` | `train_student_checkin` | `VERIFIED_FROM_SOURCE` | `DEFINED_IN_UI_API_ONLY` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/dormitory/list` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainDormitoryInfoController` | `train_dormitory_info` | `train_dormitory_info` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/dormitory/{dormId}` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainDormitoryInfoController` | `train_dormitory_info` | `train_dormitory_info` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/dormitory` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainDormitoryInfoController` | `train_dormitory_info` | `NONE` | `train_dormitory_info` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/dormitory` | `PUT` | `RAILWAYSYSTEM_INTERNAL` | `TrainDormitoryInfoController` | `train_dormitory_info` | `train_dormitory_info` | `train_dormitory_info` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/dormitory/{dormIds}` | `DELETE` | `RAILWAYSYSTEM_INTERNAL` | `TrainDormitoryInfoController` | `train_dormitory_info` | `train_dormitory_info` | `train_dormitory_info` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/accommodation/list` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccommodationController` | `train_accommodation` | `train_accommodation, train_dormitory_info, train_student` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/accommodation/{accommodationId}` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccommodationController` | `train_accommodation` | `train_accommodation, train_dormitory_info, train_student` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/accommodation/enrollment/{enrollmentId}` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccommodationController` | `train_accommodation` | `train_accommodation, train_dormitory_info, train_student` | `NONE` | `VERIFIED_FROM_SOURCE` | `DEFINED_IN_UI_API_ONLY` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/accommodation/enrollment/{enrollmentId}/history` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccommodationController` | `train_accommodation` | `train_accommodation, train_dormitory_info, train_student` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/accommodation` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccommodationController` | `train_accommodation` | `train_accommodation, train_dormitory_info` | `train_accommodation, train_dormitory_info` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/accommodation/{accommodationId}/checkin` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccommodationController` | `train_accommodation` | `train_accommodation, train_dormitory_info` | `train_accommodation, train_dormitory_info` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/accommodation/{accommodationId}/checkout` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccommodationController` | `train_accommodation` | `train_accommodation, train_dormitory_info` | `train_accommodation, train_dormitory_info` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/accommodation/{accommodationId}/transfer` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccommodationController` | `train_accommodation` | `train_accommodation, train_dormitory_info` | `train_accommodation, train_dormitory_info` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/accommodation/{accommodationIds}` | `DELETE` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccommodationController` | `train_accommodation` | `train_accommodation` | `train_accommodation, train_dormitory_info` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/score/list` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainScoreInfoController` | `train_score_info` | `train_score_info, train_student, train_course` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/score/{scoreId}` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainScoreInfoController` | `train_score_info` | `train_score_info, train_student, train_course` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/score` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainScoreInfoController` | `train_score_info` | `NONE` | `train_score_info` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/score` | `PUT` | `RAILWAYSYSTEM_INTERNAL` | `TrainScoreInfoController` | `train_score_info` | `train_score_info` | `train_score_info` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/score/{scoreIds}` | `DELETE` | `RAILWAYSYSTEM_INTERNAL` | `TrainScoreInfoController` | `train_score_info` | `train_score_info` | `train_score_info` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/analysis/dashboard/overview` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainAnalysisController` | `聚合多表` | `train_class_plan, train_enrollment, train_lesson, train_student_checkin, train_accommodation` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/analysis/dashboard/charts` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainAnalysisController` | `聚合多表` | `train_class_plan, train_enrollment, train_lesson, train_student_checkin, train_accommodation` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/analysis/attendance/summary` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainAnalysisController` | `聚合多表` | `train_student_checkin, train_lesson, train_class_plan` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/analysis/attendance/charts` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainAnalysisController` | `聚合多表` | `train_student_checkin, train_lesson, train_class_plan` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/analysis/portrait/student-360/{studentId}` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainAnalysisController` | `聚合多表` | `train_student, train_enrollment, train_student_checkin, train_score_info, train_study_duration` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/access/mapping/list` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccessManagementController` | `train_external_resource_mapping` | `train_external_resource_mapping, train_dormitory_info` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/access/auth/list` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccessManagementController` | `train_dorm_auth` | `train_dorm_auth, train_accommodation, train_student` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/access/operation/list` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccessManagementController` | `train_external_operation` | `train_external_operation` | `NONE` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/access/capability` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccessManagementController` | `N/A (配置与常量)` | `NONE` | `NONE` | `VERIFIED_FROM_SOURCE` | `DEFINED_IN_UI_API_ONLY` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/access/issue` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccessManagementController` | `train_dorm_auth` | `train_dorm_auth, train_accommodation` | `train_dorm_auth, train_external_operation` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BLOCKED_EXTERNAL)` |
| `/train/access/revoke` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccessManagementController` | `train_dorm_auth` | `train_dorm_auth, train_accommodation` | `train_dorm_auth, train_external_operation` | `VERIFIED_FROM_SOURCE` | `VERIFIED_USED_BY_UI` | `ENDPOINT_DEFINED (BLOCKED_EXTERNAL)` |
| `/train/binding/teachers/bindable-users` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccountBindingAdminController` | `sys_user` | `sys_user, train_teacher, train_student` | `NONE` | `VERIFIED_FROM_SOURCE` | `NOT_FOUND_IN_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/binding/teachers/{teacherId}/bind` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccountBindingAdminController` | `train_teacher` | `sys_user, train_teacher` | `train_teacher (user_id)` | `VERIFIED_FROM_SOURCE` | `NOT_FOUND_IN_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/binding/students/bindable-users` | `GET` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccountBindingAdminController` | `sys_user` | `sys_user, train_teacher, train_student` | `NONE` | `VERIFIED_FROM_SOURCE` | `NOT_FOUND_IN_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
| `/train/binding/students/{studentId}/bind` | `POST` | `RAILWAYSYSTEM_INTERNAL` | `TrainAccountBindingAdminController` | `train_student` | `sys_user, train_student` | `train_student (user_id)` | `VERIFIED_FROM_SOURCE` | `NOT_FOUND_IN_UI` | `ENDPOINT_DEFINED (BACKEND_IMPLEMENTED)` |
---
## 2. 统计汇总与实证说明
- **扫描端点总数**:104 个核心业务端点(全部完成源码链路检验)
- **`DATABASE_TABLE` 状态分布**:
- `VERIFIED_FROM_SOURCE`:104 / 104 (100% 经 Controller → Service → Mapper → XML 链路追踪验证)
- `HEURISTIC` / `NOT_YET_VERIFIED`:0 项(无未经证实的猜测项)
- **`USED_BY_UI` 状态分布 (build_ui/ 验证)**:
- `VERIFIED_USED_BY_UI`:78 项(在 `build_ui/src/views/` 页面中实际被用户交互触发)
- `DEFINED_IN_UI_API_ONLY`:20 项(在 `build_ui/src/api/` 中已封装接口,但页面视图暂未直接引用,如部分导出/批量导入端点)
- `NOT_FOUND_IN_UI`:6 项(纯管理端或测试后端端点,前端未声明,如账号手动绑定端点)
### 2.1 端点数量与结构化审计指标
- **表格端点行数 (TOTAL_ENDPOINT_ROWS)**:107 行
- **唯一端点标识 (UNIQUE_METHOD_PATH_COUNT)**:107 项(以 `METHOD + PATH` 为联合主键)
- **重复端点数量 (DUPLICATE_METHOD_PATH_COUNT)**:0 项(0 冲突,0 重复记录)
### 2.2 数据库调用链追踪分布 (`LINEAGE_STATUS`)
- **`VERIFIED_FROM_SOURCE`**:107 / 107 (100% 经 Controller → Service → Mapper → XML 链路追踪验证)
- **`NOT_YET_VERIFIED`**:0 项(无未经证实的猜测项)
- **细粒度读写分离**:所有 107 个端点均明确标注了读取表清单 (`READ_TABLES`) 与写入变更表清单 (`WRITE_TABLES`),包含 5 个聚合分析类复杂多表只读端点。
### 2.3 前端调用状态分布 (`USED_BY_UI` 基于 `build_ui/` 扫描)
- **`VERIFIED_USED_BY_UI`**:92 项(在 `build_ui/src/views/` 页面中实际被用户交互触发)
- **`DEFINED_IN_UI_API_ONLY`**:11 项(在 `build_ui/src/api/` 中已封装接口,但页面视图暂未直接引用,如部分导出/批量导入端点)
- **`NOT_FOUND_IN_UI`**:4 项(纯管理端底层端点,前端未声明:教师/学员账号手工绑定与候选人过滤接口)
### 2.4 四类 API 边界范围确立 (API Scope Definition)
为彻底杜绝不同领域接口职责混淆,系统 API 划分为以下四大独立边界:
1. **`CUSTOM_TRAIN_BUSINESS_API` (RailwaySystem 自研培训业务端点)**:**107 个**
- 涵盖 24 个培训核心控制器,承载开班、排课、学员、考勤、报到、住宿、成绩与画像全生命周期;
2. **`RUOYI_PLATFORM_API` (RuoYi 底座系统平台端点)**:**95 个**
- 涵盖 `/login`、`/captchaImage`、`/system/user/*`、`/system/role/*`、`/system/menu/*`、`/system/dict/*`、`/monitor/*` 等若依通用平台能力;
3. **`CLIENT_PROVIDED_API` (甲方沈阳房建公寓段自身提供的接口)**:**0 个**
- 甲方当前未向本项目开放或提供任何内部信息化系统的 Web API,系统业务主流程完全由自建数据库闭环;
4. **`THIRD_PARTY_API` (第三方外部服务端点,以 DMS 门锁平台为主)**:**9 个**
- 涵盖 DMS Token、建筑、楼层、房间、门锁查询、在线密码增删及状态轮询;
5. **`MOCK_ONLY_INTERFACE` (纯本地模拟桩接口)**:**1 个**
- 电子班牌硬件数据推送(由于缺少现场物理联网班牌,当前由本地模拟桩与心跳表驱动)。
+49 -32
View File
@@ -1,47 +1,64 @@
# 05 - 甲方与外部接口状态清单 (Client API Status)
> **最高原则**:**严禁将模拟桩 (Mock) 误报为真实在线 (REAL_LIVE)!**
> 任何标记为 `CLIENT_REAL_LIVE` 的接口,必须严格具备真实联调证据来源(`EVIDENCE_SOURCE`)与可查验的实时返回结果(`LIVE_RESULT`)。
> **安全红线**:当前阶段**严禁发起任何未经授权的破坏性写操作 (Mutation)**。
> 任何标记为 `REAL_LIVE` 的接口,必须严格具备真实联调证据来源(`EVIDENCE_SOURCE`)与可查验的实时返回结果(`LIVE_RESULT`)。
> **安全红线**:当前阶段**严禁发起任何未经授权的破坏性写操作 (Mutation)**;安全政策禁止集成的接口明确标记为 `SECURITY_PROHIBITED`。
---
## 1. 外部接口状态枚举与证据分级
## 1. 外部接口状态模型与三维判定准则
- **状态枚举 (STATUS)**:
- **`CLIENT_REAL_LIVE`**:外部真实网络畅通、凭据认证通过、在真实网络环境下成功发起调用并返回符合契约的数据报文;
- **`CLIENT_REAL_AUTH_BLOCKED`**:外部网络可达,但因密钥错误、凭据失效或缺少角色权限被 401/403 阻断;
- **`CLIENT_REAL_UNREACHABLE`**:外部网络不通、连接超时、域名未解析或接口已下线;
- **`NOT_YET_TESTED`**:代码已编写适配器,但受安全红线约束或缺少设备资源,尚未在真实网络发起调用;
- **`MOCK_SIMULATION`**:无外部真实服务支撑,完全由本地假数据桩或单元测试套件仿真驱动。
- **证据属性要求**:
- `LAST_VERIFIED_AT`:最近一次真实验证日期;
- `VERIFICATION_METHOD`:验证方式(如真实局域网 HTTP 探测、MockServer 契约测试等);
- `EVIDENCE_SOURCE`:可核验的原始凭证路径;
- `LIVE_RESULT`:真实调用返回特征(HTTP 码、响应字段摘要、数据量)。
为了杜绝“接口 HTTP 200”与“演示业务可用”之间的混淆,外部接口引入**三维判定模型**:
1. **真实网络连通性 (CONNECTIVITY_STATUS)**:
- **`REAL_LIVE`**:外部真实网络畅通、凭据认证通过、成功发起 HTTP 请求并收到 200 响应;
- **`CLIENT_REAL_AUTH_BLOCKED`**:外部网络可达,但因密钥错误或缺少角色权限被 401/403 阻断;
- **`CLIENT_REAL_UNREACHABLE`**:外部网络不通、连接超时、域名未解析或接口已下线;
- **`NOT_YET_TESTED`**:代码已编写适配器,但受安全红线或硬件限制尚未发起真实外网调用;
- **`MOCK_SIMULATION`**:无外部真实服务支撑,完全由本地假数据桩或单元测试套件驱动;
- **`SECURITY_PROHIBITED` / `OUT_OF_SCOPE`**:系统安全政策明确禁止实现与调用的高危接口(如远程开门)。
2. **真实数据状态 (REAL_DATA_STATUS)**:
- **`REAL_DATA_AVAILABLE`**:真实接口返回了非空的物理硬件或业务资源数据;
- **`EMPTY_DATA`**:真实接口返回成功,但目标列表数据量为 0(如 0 栋楼、0 间房、0 把锁);
- **`NOT_APPLICABLE`**:接口属于写操作、认证或禁止调用,不适用数据查询。
3. **演示可用性 (DEMO_USABILITY)**:
- **`LIVE_API_BUT_NO_REAL_RESOURCE_DATA`**:接口虽在线但因厂商测试环境缺少物理资源,不可用于全真实数据演示;
- **`MOCK_SIMULATION_REQUIRED`**:端到端演示必须使用受控 Mock 桩模拟硬件反馈;
- **`PROHIBITED_FROM_DEMO`**:绝不允许在演示中调用。
---
## 2. 外部接口状态与证据矩阵表
## 2. 外部接口状态与证据矩阵表 (External API Matrix)
| 序号 | 外部接口名称 | 协议与端点 (API ENDPOINT) | 提供方 (PROVIDER) | 真实状态判定 (STATUS) | 最近验证时间 (LAST_VERIFIED_AT) | 验证方式 (VERIFICATION_METHOD) | 证据来源 (EVIDENCE_SOURCE) | 真实返回特征 (LIVE_RESULT) | 破坏性风险说明 |
| :---: | :--- | :--- | :--- | :---: | :---: | :--- | :--- | :--- | :--- |
| **01** | **DMS 第三方应用凭据获取** | `POST /public/rest/third-party-app/token/get` | DMS 门锁厂商平台 | **`CLIENT_REAL_LIVE`** | 2026-09-17 | 真实网络 HTTP POST 携带有效 AppId/Secret 探测 | `docs/reports/integrated-acceptance/FINAL_PHASE1_20260917_101044/dms-final-status.md` | HTTP 200,取得有效 Token,`expires_in: 7200`,Cookie Token 认证机制验证通过 | 只读认证,无破坏性风险 |
| **02** | **DMS 建筑空间列表查询** | `POST /rest/place/building/list` | DMS 门锁厂商平台 | **`CLIENT_REAL_LIVE`** | 2026-09-17 | 真实网络携带 Cookie Token 发起 POST 查询 | `docs/reports/integrated-acceptance/FINAL_PHASE1_20260917_101044/dms-final-status.md` | HTTP 200,外层 JSON 符合契约,列表数据量为 0 (`BUILDING=0`) | 只读查询,安全 |
| **03** | **DMS 楼层空间列表查询** | `POST /rest/place/floor/list` | DMS 门锁厂商平台 | **`CLIENT_REAL_LIVE`** | 2026-09-17 | 真实网络携带 Cookie Token 发起 POST 查询 | `docs/reports/integrated-acceptance/FINAL_PHASE1_20260917_101044/dms-final-status.md` | HTTP 200,外层 JSON 符合契约,列表数据量为 0 (`FLOOR=0`) | 只读查询,安全 |
| **04** | **DMS 房间空间列表查询** | `POST /rest/place/room/list` | DMS 门锁厂商平台 | **`CLIENT_REAL_LIVE`** | 2026-09-17 | 真实网络携带 Cookie Token 发起 POST 查询 | `docs/reports/integrated-acceptance/FINAL_PHASE1_20260917_101044/dms-final-status.md` | HTTP 200,外层 JSON 符合契约,列表数据量为 0 (`ROOM=0`) | 只读查询,安全 |
| **05** | **DMS 智能门锁设备列表查询** | `POST /rest/doorlock/list` | DMS 门锁厂商平台 | **`CLIENT_REAL_LIVE`** | 2026-09-17 | 真实网络携带 Cookie Token 发起 POST 查询 | `docs/reports/integrated-acceptance/FINAL_PHASE1_20260917_101044/dms-final-status.md` | HTTP 200,外层 JSON 符合契约,挂载门锁数为 0 (`LOCK=0`) | 只读查询,安全 |
| **06** | **DMS 在线密码下发 (Mutation)** | `POST /rest/doorlock/online-password-key/create`| DMS 门锁厂商平台 | **`NOT_YET_TESTED`**<br>(本地测试为 `MOCK_SIMULATION`) | 2026-09-17 (Mock) | 本地 MockServer 单元契约测试 (`MockDmsServer.java`) | `RuoYi-Vue/ruoyi-train/src/test/java/com/ruoyi/train/integration/dms/client/DmsPasswordAdapterTest.java` | 真实环境因无指定房间与锁具,禁止发起调用 (`REAL_DMS_MUTATION_COUNT = 0`);Mock 环境返回模拟 operationId | **写操作**:严禁向未知门锁发起下发,待划拨测试硬件后联调 |
| **07** | **DMS 在线密码撤销 (Mutation)** | `POST /rest/doorlock/online-password-key/delete`| DMS 门锁厂商平台 | **`NOT_YET_TESTED`**<br>(本地测试为 `MOCK_SIMULATION`) | 2026-09-17 (Mock) | 本地 MockServer 单元契约测试 | `RuoYi-Vue/ruoyi-train/src/test/java/com/ruoyi/train/integration/dms/client/DmsPasswordAdapterTest.java` | 真实环境未调用;Mock 环境成功模拟撤销响应 | **写操作**:严禁向未知设备发起撤销 |
| **08** | **DMS 异步操作状态轮询** | `POST /rest/doorlock/operation/status` | DMS 门锁厂商平台 | **`NOT_YET_TESTED`**<br>(本地测试为 `MOCK_SIMULATION`) | 2026-09-17 (Mock) | 本地 MockServer 轮询测试 (`DmsOperationStatusAdapterTest.java`) | `RuoYi-Vue/ruoyi-train/src/test/java/com/ruoyi/train/integration/dms/client/DmsOperationStatusAdapterTest.java` | 真实环境无有效 operationId 供轮询;Mock 仿真状态机轮询成功 | 只读轮询,安全 |
| **09** | **DMS 远程开门 (Remote Unlock)** | 门锁远程触发开门接口 | DMS 门锁厂商平台 | **`CLIENT_REAL_UNREACHABLE`**<br>(`OUT_OF_CURRENT_SCOPE`) | 2026-09-17 | 架构与安全红线基线审查 | `docs/decisions/security/` 与项目安全红线规则 | 系统严禁集成任何远程开锁 API,未进行网络配置与客户端实现 | **极高危险**:绝对禁止集成与调用 |
| **10** | **电子班牌实时数据推送** | 班牌通信端口与协议 | 电子班牌硬件厂商 | **`MOCK_SIMULATION`** | 2026-09-20 | 本地数据库档案与模拟心跳更新 | `TrainElectronicBoardController.java` | 现场缺少实际联网电子班牌设备;系统当前在数据库记录心跳时间与班牌档案,通信属于模拟桩 | 无物理设备破坏风险 |
| 序号 | 外部接口名称 | 协议与端点 (API ENDPOINT) | 提供方 (PROVIDER) | 网络连通性 (CONNECTIVITY) | 真实数据状态 (DATA_STATUS) | 演示可用性 (DEMO_USABILITY) | 最近验证时间 (LAST_VERIFIED_AT) | 验证方式 (METHOD) | 证据来源 (EVIDENCE_SOURCE) | 实时返回特征 (LIVE_RESULT) | 破坏性风险说明 |
| :---: | :--- | :--- | :---: | :---: | :---: | :---: | :---: | :--- | :--- | :--- | :--- |
| **01** | **DMS 第三方应用凭据获取** | `POST /public/rest/third-party-app/token/get` | DMS 厂商平台 | **`REAL_LIVE`** | `NOT_APPLICABLE` | **`LIVE_AUTH_READY`** | 2026-09-17 | 真实外网 HTTP POST 携带有效 AppId/Secret 探测 | `docs/reports/integrated-acceptance/FINAL_PHASE1_20260917_101044/dms-final-status.md` | HTTP 200,取得有效 Token,`expires_in: 7200`,Cookie Token 认证机制验证通过 | 只读认证,无破坏性风险 |
| **02** | **DMS 建筑空间列表查询** | `POST /rest/place/building/list` | DMS 厂商平台 | **`REAL_LIVE`** | **`EMPTY_DATA`**<br>(`BUILDING=0`) | **`LIVE_API_BUT_NO_REAL_RESOURCE_DATA`** | 2026-09-17 | 真实外网携带 Cookie Token 发起 POST 查询 | `docs/reports/integrated-acceptance/FINAL_PHASE1_20260917_101044/dms-final-status.md` | HTTP 200,外层 JSON 符合契约,列表数据量为 0 (`BUILDING=0`) | 只读查询,安全 |
| **03** | **DMS 楼层空间列表查询** | `POST /rest/place/floor/list` | DMS 厂商平台 | **`REAL_LIVE`** | **`EMPTY_DATA`**<br>(`FLOOR=0`) | **`LIVE_API_BUT_NO_REAL_RESOURCE_DATA`** | 2026-09-17 | 真实外网携带 Cookie Token 发起 POST 查询 | `docs/reports/integrated-acceptance/FINAL_PHASE1_20260917_101044/dms-final-status.md` | HTTP 200,外层 JSON 符合契约,列表数据量为 0 (`FLOOR=0`) | 只读查询,安全 |
| **04** | **DMS 房间空间列表查询** | `POST /rest/place/room/list` | DMS 厂商平台 | **`REAL_LIVE`** | **`EMPTY_DATA`**<br>(`ROOM=0`) | **`LIVE_API_BUT_NO_REAL_RESOURCE_DATA`** | 2026-09-17 | 真实外网携带 Cookie Token 发起 POST 查询 | `docs/reports/integrated-acceptance/FINAL_PHASE1_20260917_101044/dms-final-status.md` | HTTP 200,外层 JSON 符合契约,列表数据量为 0 (`ROOM=0`) | 只读查询,安全 |
| **05** | **DMS 智能门锁设备列表查询** | `POST /rest/doorlock/list` | DMS 厂商平台 | **`REAL_LIVE`** | **`EMPTY_DATA`**<br>(`LOCK=0`) | **`LIVE_API_BUT_NO_REAL_RESOURCE_DATA`** | 2026-09-17 | 真实外网携带 Cookie Token 发起 POST 查询 | `docs/reports/integrated-acceptance/FINAL_PHASE1_20260917_101044/dms-final-status.md` | HTTP 200,外层 JSON 符合契约,挂载门锁数为 0 (`LOCK=0`) | 只读查询,安全 |
| **06** | **DMS 在线密码下发 (Mutation)** | `POST /rest/doorlock/online-password-key/create` | DMS 厂商平台 | **`NOT_YET_TESTED`**<br>(本地单测为 `MOCK_SIMULATION`) | `NOT_APPLICABLE` | **`MOCK_SIMULATION_REQUIRED`** | 2026-09-17 (Mock) | 本地 MockServer 单元契约测试 (`MockDmsServer.java`) | `RuoYi-Vue/ruoyi-train/src/test/java/com/ruoyi/train/integration/dms/client/DmsPasswordAdapterTest.java` | 真实环境因无指定房间与锁具,禁止发起调用 (`REAL_DMS_MUTATION_COUNT = 0`);Mock 环境返回模拟 operationId | **写操作**:严禁向未知门锁发起下发,待划拨测试硬件后联调 |
| **07** | **DMS 在线密码撤销 (Mutation)** | `POST /rest/doorlock/online-password-key/delete` | DMS 厂商平台 | **`NOT_YET_TESTED`**<br>(本地单测为 `MOCK_SIMULATION`) | `NOT_APPLICABLE` | **`MOCK_SIMULATION_REQUIRED`** | 2026-09-17 (Mock) | 本地 MockServer 单元契约测试 | `RuoYi-Vue/ruoyi-train/src/test/java/com/ruoyi/train/integration/dms/client/DmsPasswordAdapterTest.java` | 真实环境未调用;Mock 环境成功模拟撤销响应 | **写操作**:严禁向未知设备发起撤销 |
| **08** | **DMS 异步操作状态轮询** | `POST /rest/doorlock/operation/status` | DMS 厂商平台 | **`NOT_YET_TESTED`**<br>(本地单测为 `MOCK_SIMULATION`) | `NOT_APPLICABLE` | **`MOCK_SIMULATION_REQUIRED`** | 2026-09-17 (Mock) | 本地 MockServer 轮询测试 (`DmsOperationStatusAdapterTest.java`) | `RuoYi-Vue/ruoyi-train/src/test/java/com/ruoyi/train/integration/dms/client/DmsOperationStatusAdapterTest.java` | 真实环境无有效 operationId 供轮询;Mock 仿真状态机轮询成功 | 只读轮询,安全 |
| **09** | **DMS 远程开门 (Remote Unlock)** | 门锁远程触发开门接口 | DMS 厂商平台 | **`SECURITY_PROHIBITED`**<br>(`OUT_OF_SCOPE`) | `NOT_APPLICABLE` | **`PROHIBITED_FROM_DEMO`** | 2026-09-17 | 架构与安全红线基线审查 | `docs/decisions/security/` 与项目安全红线规则 | 历史证据表明系统安全政策严格禁止实现与调用远程开锁,未配置客户端亦未调用(非网络故障不可达,系范围外安全阻断) | **极高危险**:绝对禁止集成与调用 |
| **10** | **电子班牌实时数据推送** | 班牌通信端口与协议 | 电子班牌硬件厂商 | **`MOCK_SIMULATION`** | `SIMULATED_DATA` | **`LOCAL_SIMULATION_READY`** | 2026-09-20 | 本地数据库档案与模拟心跳更新 | `TrainElectronicBoardController.java` | 现场缺少实际联网电子班牌设备;系统当前在数据库记录心跳时间与班牌档案,通信属于模拟桩 | 无物理设备破坏风险 |
---
## 3. 外部接口联调与解锁条件 (Unblocking Criteria)
## 3. 统计汇总与客观边界说明
针对当前处于 `NOT_YET_TESTED` 与 `BLOCKED_EXTERNAL` 的接口,解除受限状态必须满足以下前置条件:
1. **真实硬件设备划拨**:由沈阳房建公寓段主管领导或厂商指派具体的、通电的、物理隔离的 **真实测试房间与门锁编号**;
2. **测试授权协议签署**:明确现场测试期间密码下发与冲正补偿的法律责任边界;
3. **禁止自动化无限制重试**:写操作调用必须保持 Single-Flight,超时严禁无限制自动重发,必须走人工或受控冲正通道。
### 3.1 外部接口统计指标 (Task 6 对齐)
- **`RAILWAYSYSTEM_CUSTOM_BUSINESS_API_COUNT`**:107 个(详见 04-API-INVENTORY.md)
- **`RUOYI_PLATFORM_API_COUNT`**:95 个(底座通用管理与监控接口)
- **`CLIENT_PROVIDED_API_COUNT`**:0 个(甲方沈阳房建公寓段自身未提供信息化接口)
- **`THIRD_PARTY_API_COUNT`**:9 个(DMS 门锁平台接口:01~09)
- **`MOCK_ONLY_INTERFACE_COUNT`**:1 个(电子班牌推送接口:10)
### 3.2 外部接口真实状态分布
- **真实网络连通端点数 (`CLIENT_API_REAL_CONNECTIVITY_COUNT`)**:5 个 (Token, Building, Floor, Room, Lock)
- **真实数据非空端点数 (`CLIENT_API_REAL_DATA_NONEMPTY_COUNT`)**:0 个 (**当前真实资源数量:BUILDING=0, FLOOR=0, ROOM=0, LOCK=0**)
- **受控待测写操作端点数 (`CLIENT_API_NOT_YET_TESTED_COUNT`)**:3 个 (密码下发、撤销、操作轮询)
- **安全红线禁止端点数 (`CLIENT_API_SECURITY_PROHIBITED_COUNT`)**:1 个 (远程开门)
- **纯本地模拟桩端点数 (`CLIENT_API_MOCK_COUNT`)**:1 个 (电子班牌)
+112
View File
@@ -0,0 +1,112 @@
# 纯净演示数据库设计规约草案 (CLEAN_DEMO_DATABASE_SPEC)
> **文件性质**:设计规约与构建方案草案 (PREFLIGHT SPECIFICATION DRAFT)
> **执行约束**:**本轮禁止创建数据库、禁止 DROP、禁止 TRUNCATE、禁止执行建库 SOP**。
---
## 1. 数据库基本属性定义
| 属性项 | 规划取值 | 依据与说明 |
| :--- | :--- | :--- |
| **数据库标识 (Database Name)** | `training_demo_clean` | 与当前开发库 (`training`) 及验收库 (`railwaysystem_integrated_qa_20260916`) 彻底物理隔离 |
| **数据库管理系统 (DBMS)** | `KingbaseES V009R003C018` | 国产人大金仓数据库,兼容 MySQL 与 PostgreSQL 方言 |
| **方言兼容模式 (Database Mode)**| `mysql` | 兼容若依平台自增主键、数据类型与系统函数 |
| **默认命名空间 (Schema)** | `public` | 严格在 public schema 下构建,防止 search_path 歧义 |
| **数据库属主 (Owner)** | `kingbase` | 拥有完整 DDL/DML 权限 |
| **字符集与排序规则** | `UTF8` / `zh_CN.utf8` | 保证中文字符与国密密文存储无乱码 |
---
## 2. 基础结构源与迁移引导链 (Bootstrap Chain)
纯净库构建必须按以下严格经过验证的顺序执行:
### 2.1 基础平台结构源 (Base Schema Source)
1. **`RuoYi-Vue/sql/ry_20250522.sql`**:
- 创建若依基础平台表结构并初始化系统管理账号;
2. **`RuoYi-Vue/sql/quartz.sql`**:
- 创建 Quartz 任务调度表结构;
3. **`RuoYi-Vue/sql/generator/kingbase/`**:
- 执行 `002a_gen_table_identity_patch.sql` 与 `002b_gen_table_column_identity_patch.sql`,修正 Identity 自增列。
### 2.2 培训历史基线骨架构建 (Phase 0.5 Baseline)
1. **`RuoYi-Vue/sql/train/v2/rollback/000_phase05_exact_schema.sql`**:
- 创建 14 张 Phase 0.5 历史基线表、外键、局部唯一约束与触发器函数;
2. **基线数据占位**:
- 插入 1 条基础教师占位数据,确保 `000_preflight.sql` 与 `008_migrate_teacher.sql` 断言平滑通过。
### 2.3 业务 V2 演进迁移链 (Train V2 Migration Chain)
按序执行 `RuoYi-Vue/sql/train/v2/` 目录下脚本:
- `000_preflight.sql` → `000_tx_capability_probe.sql` → `001_backup_current_schema.sql` → `002_create_new_tables.sql` → `003_alter_master_tables.sql` → `004_rebuild_business_tables.sql` → `005_constraints.sql` → `006_indexes.sql` → `008_migrate_teacher.sql` → `009_drop_legacy_score.sql` → `010_verify.sql`。
- *(⚠️ 严禁执行 `007_dicts.sql`)*。
### 2.4 系统与权限治理补丁链 (System Patches 001~015)
按序执行 `RuoYi-Vue/sql/system/kingbase/` 目录下脚本:
- `001_sys_oper_log_cost_time.sql`
- `002_legacy_analytics_permissions.sql`
- `003_report_attendance_action_permissions.sql`
- `004_rbac_identity_binding.sql`
- `005_training_roles_permissions.sql` (创建 train_admin, teacher, student 角色)
- `006_accommodation_history_constraint.sql`
- `008_external_resource_operation.sql` (创建外部资源映射与操作流水表)
- `009_dorm_authorization_orchestration.sql`
- `010_dms_access_management_permissions.sql`
- `011_teacher_student_remove_permissions.sql`
- `012_analytics_v1_permissions.sql`
- `013_interaction_route_cleanup.sql`
- `014_dms_access_safety_and_accommodation_permissions.sql`
- `015_dms_package_a_hardening.sql` (授权 train_admin 拥有 menu 2263)
---
## 3. 物理数据表容量预期基准
| 表分类 | 预期表数量 | 表名清单摘要 |
| :--- | :---: | :--- |
| **培训业务核心表 (`train_*`)** | **21 张** | `train_teacher`, `train_student`, `train_course`, `train_classroom_info`, `train_training_site`, `train_plan`, `train_plan_course`, `train_enrollment`, `train_lesson`, `train_student_checkin`, `train_class_report`, `train_dormitory_info`, `train_accommodation`, `train_score_info`, `train_study_duration`, `train_resource`, `train_course_resource`, `train_electronic_board`, `train_external_resource_mapping`, `train_dorm_auth`, `train_external_operation` |
| **若依系统底座表 (`sys_*`)** | **15 张** | `sys_user`, `sys_dept`, `sys_post`, `sys_role`, `sys_menu`, `sys_user_role`, `sys_role_menu`, `sys_role_dept`, `sys_user_post`, `sys_oper_log`, `sys_dict_type`, `sys_dict_data`, `sys_config`, `sys_logininfor`, `sys_notice` |
| **代码生成器表 (`gen_*`)** | **2 张** | `gen_table`, `gen_table_column` |
| **Quartz 调度表 (`qrtz_*`)** | **11 张** | `qrtz_job_details`, `qrtz_triggers`, `qrtz_simple_triggers`, `qrtz_cron_triggers`, `qrtz_simprop_triggers`, `qrtz_blob_triggers`, `qrtz_calendars`, `qrtz_paused_trigger_grps`, `qrtz_fired_triggers`, `qrtz_scheduler_state`, `qrtz_locks` |
| **历史结构快照备份表 (`bak_v1_*`)**| **14 张** | 由 `001_backup_current_schema.sql` 自动生成,属于备份验证表,不参与业务读写 |
---
## 4. 确定性演示种子数据策略 (Demo Seed Strategy)
### 4.1 目标:`UI_DATA_COVERAGE_TARGET = 100%`
演示数据库必须确保前端 `build_ui/src/views/train/` 下每一个业务视图组件均有丰富、真实、时序合规的业务数据,**0 空白页、0 占位符、0 孤儿外键**。
### 4.2 三层种子数据体系
1. **主数据层 (Master Data)**:
- 教师档案:5 名资深高铁/房建领域教师,具备完整职称、部门与已绑定的系统登录账号;
- 课程标准库:6 门理论与实作课程(如《高速铁路路基施工与养护》、《智能门禁系统操作规范》等);
- 教学场地:3 间多媒体教室与 2 个专业实训基地;
- 宿舍资源:2 栋宿舍楼(致远楼、博学楼),共 20 间标准化男女生宿舍。
2. **业务状态数据层 (Business State Data)**:
- 开班计划:2 期培训班(1 期正在进行中,1 期即将开班);
- 班级排课与课表:已排定完备课次日程,无时段冲突,涵盖教室与实训场地;
- 参训学员名册:每班 15~20 名学员,已完成报到,已生成在训状态;
- 住宿台账:涵盖“预分配”、“在住”与“已退宿”完整生命周期状态;
- 考勤与打卡:历史课次具备正常的签到、签退与请假记录;
- 成绩与档案:历史科目具备考评得分,学员画像视图具备出勤率与能力雷达展示。
3. **交互突变数据层 (Scenario Mutation Data)**:
- 专为演示现场交互预留的可操作记录:
- 预留 2 名处于“预分配”状态的学员,供业务人员现场点击“入住”;
- 预留 2 名处于“在住”状态的学员,供现场点击“调房”与“退宿”;
- 预留 1 节尚未开始的课次,供现场演示教师“代签”与“补卡”;
- 预留排课冲突检测用例,展示系统四维冲突拦截能力。
---
## 5. 外部系统与接口策略 (External API & Mock Policy)
1. **Client Real API 策略**:
- 只读接口(DMS Token、空间查询等)在具备网络条件下接入真实通道;
- 写操作(密码下发/撤销)在无真实测试门锁前严格禁止发起外网 Mutation。
2. **Mock 标识策略**:
- 对缺少硬件支撑的模块(如门锁密码生成反馈、电子班牌推送),统一在前端或 Mock 适配层明确标识 `[DEMO MOCK]`,绝不伪造真实硬件回执。
3. **重置策略 (Reset Strategy)**:
- 编制确定性重置脚本 `reset_demo_data.sql`,执行后可一键将数据库还原为“演示开始前”初始黄金状态,支持反复多次演练。
4. **备份策略 (Backup Strategy)**:
- 种子数据完全灌入并通过 100% UI 验收后,立即执行物理快照导出 `pg_dump -Fc training_demo_clean > training_demo_clean_frozen.dump`,封存 SHA-256 校验和作为基线。