# RailwaySystem 自助服务接口体系设计 (Self-Service API Design) - **设计版本**: R.2A Design Freeze - **设计日期**: 2026-09-15 - **核心目标**: 建立专属的 Teacher 和 Student 自服务 API 契约(`/train/me/**`),彻底切断客户端参数越权可能性,确保后端 100% 服务端自主推导身份。 --- ## 1. API 设计原则与边界 1. **禁止复用 Admin 全量管理接口**: - 严禁让教师或学员调用 `/train/student/list` 或 `/train/plans/{id}/timetable` 并寄希望于前端过滤。 - 前端代码可被逆向、调试或通过 Postman 直接调用,任何客户端过滤均等于零安全防护。 2. **专属 `/train/me/**` 统一前缀**: - 所有自服务请求均指向当前登录人上下文。 - 接口入参完全不接收 `studentId`、`teacherId` 等身份主键,参数只允许包含时间范围(如 `startDate`, `endDate`)或分页标记。 3. **严格对应真实业务能力 (No Fictional APIs)**: - 仅设计当前数据库与领域服务已真实支撑的业务模块(课表、入班名单、报到、考勤、学时、画像)。 - 当前一期暂未实现正式闭环的成绩填报或复杂选课,一律不虚构开放。 --- ## 2. 教师自服务接口规格 (Teacher Self-Service APIs) ### 2.1 获取教师本人档案信息 - **端点**: `GET /train/me/teacher` - **鉴权要求**: `@PreAuthorize("@ss.hasRole('train_teacher')")` - **响应示例**: ```json { "code": 200, "msg": "操作成功", "data": { "tId": "1540e76a34c54596b0e365ae8804ef68", "tName": "DEMO_E2E_20260915_122800_王老师", "tGender": "1", "tPhone": "13900000000", "tEmail": "wang@railway.cn", "orgName": "机务段技能实训中心", "jobTitle": "高级讲师", "status": 1 } } ``` ### 2.2 获取我参与任课的培训班列表 - **端点**: `GET /train/me/plans` - **逻辑**: 通过 `train_timetable_lesson` 与 `train_plan_course` 逆向查出教师受聘的全部有效培训班。 - **参数**: `pageNum`, `pageSize`, `planStatus` (可选) - **响应示例**: ```json { "code": 200, "rows": [ { "planId": "613b316621e5466c9039650ced299aa1", "planName": "DEMO_E2E_20260915_122800_铁路综合培训第一期", "startDate": "2026-09-15", "endDate": "2026-09-20", "planStatus": 0, "myCourseCount": 2, "myLessonCount": 2 } ], "total": 1 } ``` ### 2.3 获取我的授课课表日程 - **端点**: `GET /train/me/timetable` - **参数**: `startDate` (如 `2026-09-15`), `endDate` (如 `2026-09-21`) - **逻辑**: 仅查询 `teacher_id = #{currentTeacherId}` 的已排课次。 - **响应示例**: ```json { "code": 200, "data": [ { "lessonId": 97, "planId": "613b316621e5466c9039650ced299aa1", "planName": "铁路综合培训第一期", "cId": "f4a28c4079fe47a1a542d3a34768f9fd", "courseName": "铁路安全理论", "venueType": 2, "venueName": "实训区A", "startTime": "2026-09-15 08:30:00", "endTime": "2026-09-15 10:00:00", "status": 1 } ] } ``` ### 2.4 获取我所带班级学员花名册 (敏感信息脱敏) - **端点**: `GET /train/me/students` - **参数**: `planId` (必填,后端校验教师是否有该班任教关系) - **安全保障**: 身份证号脱敏为后四位,手机号中间四位脱敏。 - **响应示例**: ```json { "code": 200, "rows": [ { "studentId": "f1b524da49da4a54a6d832ab22c2d092", "studentName": "张三", "maskedPhone": "138****0001", "maskedIdCard": "************1234", "orgName": "车辆段检修一车间", "reportStatus": 1, "enrollmentStatus": 0 } ], "total": 2 } ``` ### 2.5 获取我授课课次的学员出勤情况 - **端点**: `GET /train/me/lessons/{lessonId}/attendance` - **逻辑**: 后端严格核验 `lessonId` 的授课教师是否为当前登录人,然后输出该课次应到学员的打卡流水。 --- ## 3. 学员自服务接口规格 (Student Self-Service APIs) ### 3.1 获取学员个人档案 - **端点**: `GET /train/me/student` - **鉴权要求**: `@PreAuthorize("@ss.hasRole('train_student')")` - **响应字段**: 学员工号、姓名、性别、联系电话、所属单位、照片凭证引用。身份证号仅向本人展示后四位。 ### 3.2 获取我的参训班级与生命周期状态 - **端点**: `GET /train/me/enrollments` - **逻辑**: 从 `train_training_enrollment` 查询 `student_id = #{currentStudentId}`。 - **状态字段**: - `enrollmentStatus`: `0 (待报到)`, `1 (已报到)`, `2 (请假)`, `3 (退训)`, `4 (已完成)`。 - `planId`, `planName`, `startTime`, `endTime`, `reportDeadline`。 ### 3.3 获取我的参训课表 - **端点**: `GET /train/me/timetable` - **参数**: `startDate`, `endDate`, `viewType` (`day`/`week`) - **逻辑**: 关联当前学员所在有效班级(`enrollmentStatus IN (0, 1, 4)`),汇总返回所有授课课次、场地位置与任课教师姓名。 ### 3.4 获取我的报到凭据与状态 - **端点**: `GET /train/me/report` - **逻辑**: 查询当前学员在最新培训计划中的报到记录(`train_class_report`),返回报到时间、分配教室、分配场地与当前报到状态。 ### 3.5 获取我的考勤打卡流水 - **端点**: `GET /train/me/attendance` - **参数**: `planId` (可选), `month` (可选) - **逻辑**: 查询 `train_student_checkin WHERE student_id = #{currentStudentId}`。 - **响应示例**: ```json { "code": 200, "rows": [ { "checkinId": 10, "lessonId": 97, "courseName": "铁路安全理论", "checkinTime": "2026-09-15 08:28:10", "checkoutTime": "2026-09-15 12:48:42", "attendanceStatus": 2, "statusLabel": "迟到", "manualFlag": 1, "adjustReason": "因列车调度交接延误10分钟" } ] } ``` ### 3.6 获取我的累计学习时长 - **端点**: `GET /train/me/duration` - **逻辑**: 归集 `train_study_duration`,按理论课时与实训课时分别统计有效累计秒数与达标折算学时。 ### 3.7 获取我的多维成长画像雷达 - **端点**: `GET /train/me/portrait` - **逻辑**: 查询 `train_student_portrait WHERE student_id = #{currentStudentId}`,返回出勤率、测评平均分、技能掌握度等 5 维雷达数据。 --- ## 4. 身份异常与边界错误码规范 | HTTP 状态码 | 业务错误代码 (Code) | 错误提示说明 (Message) | 触发边界与处理方式 | | :---: | :---: | :--- | :--- | | `401` | `401` | "认证凭据无效或会话已过期" | Token 缺失、伪造或 Redis 缓存失效,引导至登录页 | | `403` | `403` | "非教师身份,禁止访问教师专属工作台" | 学员账号或非授课管理员访问 `/train/me/teacher/**` | | `403` | `403` | "非学员身份,禁止访问学员个人培训中心" | 教师或管理员账号访问 `/train/me/student/**` | | `400` | `40041` | "当前登录账号未绑定任何业务档案,请联系管理员" | 存在 `sys_user` 账号,但 `train_teacher/student` 表中未关联对应主体 | | `403` | `40042` | "您并非该班级或课次的任课教师,无权查看学员信息" | 教师尝试横向探测试图读取无关班级名册 |