文档权限:冻结R2A三角色权限设计与审计文档

This commit is contained in:
wangzhibiao committed 2026-09-15 13:30:07 +08:00
1 parent 82da706006
commit 35832f2fce
9 files changed
+1243

No files matched your search

+188
View File
@@ -0,0 +1,188 @@
# 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` | "您并非该班级或课次的任课教师,无权查看学员信息" | 教师尝试横向探测试图读取无关班级名册 |