# RailwaySystem API 设计原则与规范 > **状态:** Phase 2 规范冻结 (Review Round 1 修订版) > **适用范围:** 所有 Controller、API 契约、DTO/VO 及前端调用 --- ## 1. 业务驱动与工作台优先原则 ### 1.1 拒绝单表 CRUD 堆砌 本系统是面向铁路培训基地的**智慧培训业务系统**,不是 21 张数据库表的 CRUD 管理后台。严禁出现以下反模式: ```mermaid flowchart TD A["一张数据库表"] --> B["一个单表 Controller"] B --> C["一个单表 Service"] C --> D["一套单表 CRUD 页面"] ``` ### 1.2 业务工作台与聚合驱动 业务人员在日常管理中是以“**开班计划**”为主线推进各阶段工作的。因此系统核心页面是以 **培训计划工作台 (Plan Workbench)** 为枢纽,通过聚合视图直观展示当前培训所处的阶段(筹备中、排课中、住宿分配中、报到中、培训进行中、已结束),并提供进入各业务动作的明确入口,而不是让用户在几十个左侧菜单栏来回跳转拼接数据。 --- ## 2. Resource API 与 Command API 区分 为了保持 API 语义清晰,明确操作意图与事务边界,所有接口严格区分 **资源查询 (Resource API)** 与 **业务动作 (Command API)**。 ### 2.1 资源型 API (Resource API) - **定位:** 用于获取业务实体详情、列表、看板或特定维度的只读数据。 - **HTTP 动词:** 纯 `GET`。 - **特点:** 无副作用、幂等,不触发跨表业务状态跃迁。 - **示例:** ```text GET /train/plans/{planId} // 获取计划详情 GET /train/plans/{planId}/courses // 查询计划本期课程列表 GET /train/plans/{planId}/timetable // 获取完整课程表 GET /train/enrollments/{id} // 查询参训档案详情 GET /train/dormitory/occupancy-board // 获取宿舍房态看板 ``` ### 2.2 命令型 API (Command API) - **定位:** 用于驱动业务流程流转、触发状态机跃迁、执行跨表批量操作或外部协作。 - **HTTP 动词:** 业务动作用名词或动宾短语结尾(如 `/complete`, `/preallocate`, `/sign-in`)。 - **与普通 CRUD 更新的区分:** - 普通的字段修改(如改教师电话、改教室容量)属于标准资源更新 (`PUT /train/teacher/{id}`); - 真正业务 Command(如 `POST /train/plans/{id}/complete`, `POST /train/plans/{id}/accommodations/preallocate`, `POST /train/attendance/sign-in`)必须具有跨表状态推动语义,受严格事务保护与不变量拦截。 --- ## 3. URL 命名与路径规范 1. **统一前缀:** 所有培训业务接口统一以 `/train` 开头,兼容 RuoYi 路由机制与安全过滤器。 2. **RESTful 资源层级:** 遵循“父资源/ID/子资源”层级表达从属关系: - `/train/plans/{planId}/courses` - `/train/plans/{planId}/lessons` - `/train/plans/{planId}/enrollments` 3. **领域主键显式声明:** 路径变量统一使用数据库 V2 确立的领域 ID 名称: - `{planId}` (String, 32位) - `{planCourseId}` (Long) - `{enrollmentId}` (Long) - `{lessonId}` (Long) - `{accommodationId}` (Long) - `{checkinId}` (Long) - `{scoreItemId}` (Long) 4. **禁止隐式复合参数替代主键:** 严禁在 URL 或 RequestBody 中反复退化为 `plan_id + student_id + c_id + time` 查找记录。 --- ## 4. 分页与列表控制规范 严禁前端通过 `pageSize=99999` 获取全量业务数据,必须严格划分分页接口与专用聚合接口: | 分类 | 典型接口 | 控制策略 | 说明 | |:---|:---|:---|:---| | **常规主数据列表** | 教师、学员、公共课程库、教学资源、教室、场地、电子班牌 | **必须分页** (`pageNum`, `pageSize`) | 默认 `pageSize=10`,最大允许 `pageSize=100` | | **大型业务流列表** | 培训计划列表、参训学员名单、课次列表、学习记录流水 | **必须分页** (`pageNum`, `pageSize`) | 参训学员按计划筛选时分页呈现,提供按状态过滤 | | **业务聚合视图** | 培训计划工作台 (`/workbench`)、完整课程表 (`/timetable`) | **不分页** (专用聚合 VO 返回) | 课程表按时间周期或开班全程以结构化日历网格返回 | | **业务配置项** | 本期成绩项目配置 (`/score-items`)、本期课程清单 (`/courses`) | **不分页** (全量返回) | 一个培训班课程通常为 3~10 门,成绩项为 3~6 项,数量可控 | | **统计与看板** | 统计概览 (`/overview`)、房态看板 (`/occupancy-board`) | **不分页** (结构化聚合看板) | 服务端完成聚合计算,返回统计指标及图表数据结构 | --- ## 5. 响应体规范 (RuoYi 体系兼容) 系统全面兼容若依现有的 `AjaxResult` 和 `TableDataInfo` 标准,前端不需要额外定制拦截器: ### 5.1 单一实体 / 命令响应 / 聚合 VO 采用 `AjaxResult` 包装: ```json { "code": 200, "msg": "操作成功", "data": { "planId": "PLAN202609001", "planName": "沈阳局2026年第1期高速铁路综合培训班" } } ``` ### 5.2 分页列表响应 采用若依标准 `TableDataInfo` 包装: ```json { "total": 45, "rows": [ { "enrollmentId": 1001, "studentName": "张三", "enrollmentStatus": 1 } ], "code": 200, "msg": "查询成功" } ``` ### 5.3 业务异常响应 发生业务校验失败时返回标准 HTTP 200 或业务错误码(如 500),由全局异常捕获器统一封装: ```json { "code": 40901, "msg": "排课冲突:王老师在该时段已有授课任务(安全理论基础 09:00-11:00)", "data": { "conflictType": "TEACHER", "conflictLessonId": 801 } } ``` --- ## 6. 确定性标记与 API 优先级规范 ### 6.1 需求确定性分级 - **【确认】:** PRD V1.0 与第二次项目会议纪要已明确冻结的业务需求与规则,不可随意擅改。 - **【默认/建议方案(待现场确认)】:** 设计层给出的标准工程实现方案,若现场验证后甲方有微调,可平滑变更。 - **【待现场确认】:** 明确属于 PRD V-01 ~ V-14 范围的事项(如及格线判定、学员画像标签、超期报到处理策略),API 契约保持高弹性,严禁硬编码。 - **【扩展】:** 一期不开发、仅在模型或契约层预留扩展兼容能力(如分布式事务、Kafka、Outbox模式、复杂证书体系),严禁过度设计。 ### 6.2 API 优先级分级 (P0 / P1 / P2) - **P0 (一期核心闭环必须实现):** 支撑培训班从立项、选课、入班、排课、住宿、报到、上课打卡、打分、统计到结训的最小可用闭环接口。后续 Issue 拆分优先以此作为开发基线。 - **P1 (一期辅助管理能力):** 在主链路畅通后实现的辅助运维、人工修正、主档维护与报表查询接口。 - **P2 (依赖现场确认或非首轮必须):** 依赖现场硬件协议确认或面向学员端的次要门户接口,实现前需再次确认。