Files
railwaysystem/docs/development/rbac-r2/04_api_design.md
T

7.3 KiB

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')")
  • 响应示例:
    {
      "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 (可选)
  • 响应示例:
    {
      "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} 的已排课次。
  • 响应示例:
    {
      "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 (必填,后端校验教师是否有该班任教关系)
  • 安全保障: 身份证号脱敏为后四位,手机号中间四位脱敏。
  • 响应示例:
    {
      "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}。
  • 响应示例:
    {
      "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 "您并非该班级或课次的任课教师,无权查看学员信息" 教师尝试横向探测试图读取无关班级名册