28 KiB
报到机接口 API 文档
| 项目 | 内容 |
|---|---|
| 控制器 | com.ruoyi.web.controller.api.TrainRegisterApiController |
| 源文件 | ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TrainRegisterApiController.java |
| BasePath | /api/register/v1 |
| 接口数量 | 12(8 个 GET + 4 个 POST) |
| 鉴权 | Spring Security 已放行 /api/register/v1/**(permitAll);仅 /report/reset 内部取登录用户,需携带 RuoYi Bearer Token |
| 统一响应 | AjaxResult(code / msg / data) |
| 日期格式 | yyyy-MM-dd HH:mm:ss(spring.jackson.date-format,时区 GMT+8) |
| 文档更新 | 2026-11-09(新增宿舍布局接口) |
| 编写依据 | 控制器源码逐行核对,与当前实现一致 |
目录
1. 通用约定
1.1 鉴权说明
- 源代码类注释声明“其余接口复用 RuoYi Bearer 鉴权”,但当前
SecurityConfig中已配置:
.requestMatchers("/api/register/v1/**").permitAll();
即 整个 /api/register/v1/** 路径实际为匿名可访问,查询类与人脸上传接口不强制 Token。
- 例外:
POST /report/reset内部通过SecurityUtils.getUsername()写入操作人,无登录态时该方法会抛ServiceException("获取用户账户异常", 401)。因此该接口必须携带Authorization: Bearer {token}。 - 控制器注释提到的
X-Signature/X-Nonce(HMAC)验签目前未在本控制器内实现,DeviceHmacFilter仅对/api/iot/v1/device/login生效。
1.2 统一响应结构
所有接口返回 AjaxResult:
{ "code": 200, "msg": "操作成功", "data": {} }
| 字段 | 类型 | 说明 |
|---|---|---|
code |
number | 业务状态码,见 1.3 |
msg |
string | 提示信息;成功时通常为 操作成功 |
data |
object / array | 业务数据,无数据时该字段不出现 |
1.3 状态码与错误提示
| code | 含义 | 触发来源 |
|---|---|---|
| 200 | 成功 | 正常返回 |
| 401 | 未认证 / 无登录上下文 | SecurityUtils 抛出的 ServiceException |
| 500 | 参数缺失、图片解析失败、目标记录不存在等业务失败 | 控制器内 AjaxResult.error(...) |
除框架级 401/404 外,业务失败统一为
code=500,调用方需读取msg区分原因。
1.4 公共数据结构
StudentItemVO(学员列表项,/student/list)
| 字段 | 类型 | 说明 |
|---|---|---|
sId |
string | 学员ID(业务主键) |
sName |
string | 学员姓名 |
personNo |
string | 人员编号 |
sGender |
string | 性别 |
sBirth |
string | 出生日期,yyyy-MM-dd |
deptName |
string | 所属部门名称 |
cardNo |
string | 卡号 |
sPhone |
string | 手机号 |
sEmail |
string | 邮箱 |
idCardMasked |
string | 证件号掩码 |
idCardLast4 |
string | 证件号后 4 位 |
sourceType |
number | 数据来源类型 |
status |
number | 状态 |
avatar |
string | 头像访问路径(如 /profile/upload/...png) |
dutyLevel |
number | 职务级别 |
extractStatus / extractTime / extractMsg |
string / string / string | 人脸特征提取状态、时间、描述 |
photoMd5 |
string | 人脸照片 MD5 |
featureData / featureMd5 / featureAlgoVersion / featureSize |
string / string / string / number | 人脸特征数据及元信息 |
id |
number | 主键 |
deptId |
number | 部门ID |
enrollmentStatus |
number | 报到状态:0 待报到、1 已报到、2 请假、3 放弃、4 已完成 |
joinTime |
string | 报到/入学时间 |
门锁入住结果 lockCheckin(LockStayCheckinResult)
| 字段 | 类型 | 说明 |
|---|---|---|
success |
boolean | 是否成功 |
status |
string | 处理状态 |
bizNo |
string | 门锁业务流水号 |
httpStatus |
number | 下游 HTTP 状态 |
code |
string | 下游业务码 |
message |
string | 下游提示信息 |
rawBody |
string | 下游原始响应体 |
2. 接口总览
| 序号 | 分组 | 方法 | 路径 | 功能说明 |
|---|---|---|---|---|
| 1 | 学员信息 | GET | /api/register/v1/student/list |
获取全部学员列表(含报到状态) |
| 2 | 学员信息 | GET | /api/register/v1/student/{sId} |
获取单个学员详情(含账号绑定信息) |
| 3 | 学员信息 | GET | /api/register/v1/student/{sId}/base |
获取学员基础信息(个人信息/开班/宿舍/教室/实训场地) |
| 4 | 学员信息 | GET | /api/register/v1/student/{sId}/resources |
获取学员关联资源(基础信息 + 课程 + 课表) |
| 5 | 教师信息 | GET | /api/register/v1/teacher/list |
获取全部教师列表(结构同学员列表) |
| 6 | 教师信息 | GET | /api/register/v1/teacher/{tId}/base |
获取教师基础信息(个人信息/宿舍/授课课表) |
| 7 | 班级名单 | GET | /api/register/v1/class/student |
获取进行中班级及其未报到学员名单 |
| 8 | 人脸照片 | POST | /api/register/v1/student/face |
上传学员人脸照片并同步人脸设备、办理报到 |
| 9 | 人脸照片 | POST | /api/register/v1/teacher/face |
上传教师人脸照片并同步人脸设备 |
| 10 | 人脸照片 | POST | /api/register/v1/face |
按 employeeId 后缀统一分发到学员/教师上传 |
| 11 | 报到业务 | POST | /api/register/v1/report/reset |
报到重置(解绑人脸、清门锁授权、状态回退) |
| 12 | 宿舍布局 | GET | /api/register/v1/dormitory/layout |
按楼栋/楼层/房间返回宿舍布局及已分配床位数 |
3. 学员信息
3.1 获取学员信息列表
- 接口路径:
/api/register/v1/student/list - 请求方法:
GET - 功能说明:读取学员主档列表(
train_student),并按sId反查train_enrollment报名记录,用第一条记录的报到状态与报到时间补齐enrollmentStatus、joinTime。
请求参数:无(无分页、无过滤条件,返回全量)
返回结果说明:
data:StudentItemVO数组,字段见 1.4。- 学员无报名记录时,
enrollmentStatus与joinTime为null。
{
"code": 200,
"msg": "操作成功",
"data": [
{
"sId": "S0001",
"sName": "张三",
"personNo": "P1001",
"sGender": "1",
"sBirth": "2000-01-01",
"deptName": "供电段",
"sPhone": "13800000000",
"status": 1,
"avatar": "/profile/upload/2026/11/05/xxxx.png",
"enrollmentStatus": 1,
"joinTime": "2026-11-05 09:12:33"
}
]
}
3.2 获取学员详情
- 接口路径:
/api/register/v1/student/{sId} - 请求方法:
GET - 功能说明:按学员ID查询详情,并在基础字段上补充账号绑定信息(
userId、userName、nickName、accountBindingStatus)。
请求参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
sId |
path | string | 是 | 学员ID,如 S0001 |
返回结果说明:
data为StudentAdminVO,继承StudentDetailVO←StudentItemVO。- 在 1.4 StudentItemVO 字段基础上,追加:
| 字段 | 类型 | 说明 |
|---|---|---|
faceRef |
string | 人脸引用 |
remark |
string | 备注 |
createBy / createTime |
string / string | 创建人 / 创建时间 |
userId |
number | 绑定的系统用户ID |
userName |
string | 登录账号 |
nickName |
string | 用户昵称 |
accountBindingStatus |
number | 账号绑定状态:1 已绑定,0 未绑定 |
- 学员不存在时返回
{"code":200,"msg":"操作成功","data":null}。
3.3 获取学员基础信息
- 接口路径:
/api/register/v1/student/{sId}/base - 请求方法:
GET - 功能说明:按
sId聚合该学员的个人信息、所属开班计划、宿舍、教室、实训场地,供报到机首屏展示。开班 planId 取值优先取最新报到记录,缺失时从报名关系兜底。
请求参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
sId |
path | string | 是 | 学员ID |
返回结果说明:data 为对象(字段可能为 null):
| 字段 | 类型 | 说明 |
|---|---|---|
studInfo |
object | 学员基础信息:sId、sName、sPhone、sGender、deptName、personNo |
classPlan |
object | 开班信息:planId、planName、startTime、endTime |
dormitory |
object | 宿舍信息:dormId、bedNo、dormBuilding、dormRoom |
classroom |
object | 教室信息(取自本计划首个带教室的课次):classRoomId、roomLocation、roomName |
trainingSite |
object | 实训场地信息(取自本计划首个带场地的课次):siteId、siteLocation、siteName、major |
{
"code": 200,
"msg": "操作成功",
"data": {
"studInfo": { "sId": "S0001", "sName": "张三", "sPhone": "13800000000", "sGender": "1", "deptName": "供电段", "personNo": "P1001" },
"classPlan": { "planId": "P2026001", "planName": "2026年第一期", "startTime": "2026-11-01 08:00:00", "endTime": "2026-11-30 18:00:00" },
"dormitory": { "dormId": "D01", "bedNo": "3", "dormBuilding": "1号楼", "dormRoom": "101" },
"classroom": { "classRoomId": "R01", "roomLocation": "教学楼2层", "roomName": "201" },
"trainingSite": { "siteId": "T01", "siteLocation": "实训楼1层", "siteName": "接触网实训场", "major": "接触网" }
}
}
注意:本接口不返回
courses与lesson(源码中已注释),需要课表请使用 3.4。
3.4 获取学员关联资源
- 接口路径:
/api/register/v1/student/{sId}/resources - 请求方法:
GET - 功能说明:在 3.3 的基础上额外返回本计划课程列表与课次(含课程名),供报到机展示课表。
请求参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
sId |
path | string | 是 | 学员ID |
返回结果说明:data 在 3.3 全部字段之外,追加:
| 字段 | 类型 | 说明 |
|---|---|---|
courses |
array | 本计划课程:cId(计划课程主键)、cName(课程名称) |
lesson |
array | 课次列表:startTime、endTime、planCourseId、cName |
{
"code": 200,
"msg": "操作成功",
"data": {
"studInfo": { "sId": "S0001", "sName": "张三" },
"classPlan": { "planId": "P2026001", "planName": "2026年第一期" },
"courses": [ { "cId": 1001, "cName": "接触网巡视" } ],
"lesson": [ { "startTime": "2026-11-06 08:00:00", "endTime": "2026-11-06 10:00:00", "planCourseId": 1001, "cName": "接触网巡视" } ],
"dormitory": { "dormId": "D01", "bedNo": "3" },
"classroom": { "classRoomId": "R01", "roomName": "201" },
"trainingSite": { "siteId": "T01", "siteName": "接触网实训场" }
}
}
4. 教师信息
4.1 获取教师信息列表
- 接口路径:
/api/register/v1/teacher/list - 请求方法:
GET - 功能说明:读取教师主档(
train_teacher),按与学员列表完全一致的结构返回,便于报到机统一处理。转换规则:sId=tId + "_teacher"(与人脸库教师employee_id口径一致)sName=tName,其余字段一一映射- 教师无报名记录,
enrollmentStatus、joinTime恒为null
请求参数:无
返回结果说明:data 为 StudentItemVO 数组,实际填充字段:sId、sName、personNo、sGender、sBirth、deptName、cardNo、sPhone、sEmail、status、avatar、id。
{
"code": 200,
"msg": "操作成功",
"data": [
{
"sId": "T0001_teacher",
"sName": "李老师",
"personNo": "P2001",
"sGender": "1",
"sPhone": "13900000000",
"deptName": "供电段",
"status": 1,
"avatar": null,
"enrollmentStatus": null,
"joinTime": null
}
]
}
4.2 获取教师基础信息
- 接口路径:
/api/register/v1/teacher/{tId}/base - 请求方法:
GET - 功能说明:按教师工号聚合个人信息、宿舍信息与授课课表。兼容传入
tId + "_teacher"口径:路径参数以_teacher结尾时会自动去除后缀再查询。
请求参数
| 名称 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
tId |
path | string | 是 | 教师工号;可传 T0001 或 T0001_teacher |
返回结果说明:
| 字段 | 类型 | 说明 |
|---|---|---|
teacherInfo |
object | 教师信息:tId、tName、tPhone、tGender、deptName、personNo、avatar;教师不存在时为 null |
dormitory |
object | dormId、bedNo、dormBuilding、dormRoom(无有效住宿时 dormId 为 null) |
lesson |
array | 授课课次(按开始时间升序,不传日期范围即全部);字段:lessonId、planCourseId、courseName、tId、teacherName、startTime、endTime、venueType、classRoomId、classRoomName、siteId、siteName、venueName、boardSn、remark |
{
"code": 200,
"msg": "操作成功",
"data": {
"teacherInfo": { "tId": "T0001", "tName": "李老师", "tPhone": "13900000000", "tGender": "1", "deptName": "供电段", "personNo": "P2001", "avatar": null },
"dormitory": { "dormId": "D02", "bedNo": "1", "dormBuilding": "2号楼", "dormRoom": "205" },
"lesson": [
{ "lessonId": 9001, "courseName": "接触网巡视", "tId": "T0001", "teacherName": "李老师", "startTime": "2026-11-06 08:00:00", "endTime": "2026-11-06 10:00:00", "classRoomId": "R01", "classRoomName": "201", "venueName": "教学楼201" }
]
}
}
5. 班级名单
5.1 获取进行中班级的学员名单
- 接口路径:
/api/register/v1/class/student - 请求方法:
GET - 功能说明:查询所有进行中(
planStatus = 1)的开班计划,并按计划取报名记录中未报到(enrollmentStatus = 0)的学员,学员列表作为班级属性students一并返回。单个学员主档缺失时用报名记录的冗余字段兜底,不会中断整体返回。
请求参数:无
返回结果说明:data 为班级数组:
| 字段 | 类型 | 说明 |
|---|---|---|
planId |
string | 开班计划ID |
planName |
string | 开班计划名称 |
classId |
string | 班级ID |
className |
string | 班级名称 |
students |
array | 未报到学员:sId、sName、deptId、deptName |
{
"code": 200,
"msg": "操作成功",
"data": [
{
"planId": "P2026001",
"planName": "2026年第一期",
"classId": "C01",
"className": "接触网一班",
"students": [
{ "sId": "S0001", "sName": "张三", "deptId": 103, "deptName": "供电段" }
]
}
]
}
6. 人脸照片上传
三个接口均为
POST+application/json,faceImage支持纯 base64 或 data URI(data:image/png;base64,....)两种形式;服务端统一解码并转码为 PNG 落盘,路径形如/profile/upload/yyyy/MM/dd/{uuid}.png,随后写回对应主档的avatar字段。
6.1 上传学员人脸照片
- 接口路径:
/api/register/v1/student/face - 请求方法:
POST - 功能说明:保存学员人脸照片到
train_student.avatar,同步人脸识别设备(employee_id = sId),并按住宿记录办理报到:- 更新报名记录
enrollmentStatus = 1、joinTime = 当前时间(存在报名记录时); - 若学员有有效住宿记录(按
create_time降序首条且dormId非空),生成门锁业务流水号并调用入住接口/openapi/iot/stay/checkin。
- 更新报名记录
请求参数(JSON Body)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
sId |
string | 是 | 学员ID |
faceImage |
string | 是 | 人脸图片 base64,可带 data:image/xxx;base64, 前缀 |
返回结果说明:data 字段:
| 字段 | 类型 | 说明 |
|---|---|---|
sId |
string | 学员ID |
avatar |
string | 头像访问路径 |
faceSync |
string | 设备同步状态:success / failed / skipped |
faceMsg |
string | 同步失败原因(仅失败时存在) |
faceData |
any | 设备返回的非 Map 数据(成功时可能追加) |
lockCheckin |
object | 门锁入住结果,结构见 1.4 lockCheckin(有住宿时返回) |
lockAuthId |
string | 门锁授权ID,当前固定为空串(有住宿时返回) |
joinTime |
string | 报到时间(有住宿时返回) |
失败场景(code=500):
| msg | 触发条件 |
|---|---|
参数缺失:sId 与 faceImage 均为必填 |
任一参数为 null |
sId 不能为空 |
sId 为空串 |
图片解析失败:... |
base64 非法 / 非图片 / 无法编码为 PNG |
创建存储目录失败 |
落盘目录创建失败 |
图片写入失败:... |
文件写入 IO 异常 |
学员不存在或更新失败 |
更新 train_student 影响行数为 0 |
人脸设备同步失败不影响接口成功返回,仅通过
faceSync=failed+faceMsg体现。
6.2 上传教师人脸照片
- 接口路径:
/api/register/v1/teacher/face - 请求方法:
POST - 功能说明:保存教师人脸照片到
train_teacher.avatar,以employee_id = tId + "_teacher"同步人脸识别设备。教师无报名记录,不处理报到状态;若教师已有有效住宿且已生成门锁流水号,则补发一次入住授权(有效期 15 天)。
请求参数(JSON Body)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
teacherId |
string | 是 | 教师工号(train_teacher.t_id),不含 _teacher 后缀 |
faceImage |
string | 是 | 人脸图片 base64,可带 data URI 前缀 |
返回结果说明:data 字段:
| 字段 | 类型 | 说明 |
|---|---|---|
tId |
string | 教师工号 |
avatar |
string | 头像访问路径 |
faceSync |
string | 设备同步状态:success / failed / skipped |
faceMsg |
string | 同步失败原因(仅失败时存在) |
lockCheckin |
object | 补发入住授权结果(教师有住宿且已生成 lockApiBizNo 时返回) |
lockAuthId |
string | 当前固定为空串(补发授权时返回) |
失败场景(code=500):
| msg | 触发条件 |
|---|---|
参数缺失:teacherId 与 faceImage 均为必填 |
任一参数为 null |
teacherId 不能为空 |
teacherId 为空串 |
图片解析失败:... / 创建存储目录失败 / 图片写入失败:... |
同 6.1 |
教师不存在或更新失败 |
更新 train_teacher 影响行数为 0 |
6.3 上传人脸照片(统一入口)
- 接口路径:
/api/register/v1/face - 请求方法:
POST - 功能说明:按
employeeId后缀分发到 6.1 / 6.2,返回被调用方法的原样结果:employeeId以_teacher结尾 → 去掉后缀作为teacherId,转 6.2;- 其他情况 →
employeeId即sId,转 6.1。
- 后缀匹配区分大小写且不做
trim(_TEACHER会被当作学员ID)。
请求参数(JSON Body)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
employeeId |
string | 是 | 人脸库人员ID:学员 sId 或教师 tId + "_teacher" |
faceImage |
string | 是 | 人脸图片 base64,可带 data URI 前缀 |
返回结果说明:与分发目标接口完全一致(见 6.1 / 6.2 的 data 说明)。
失败场景(code=500):
| msg | 触发条件 |
|---|---|
参数缺失:employeeId 与 faceImage 均为必填 |
任一参数为 null |
employeeId 不能为空 |
employeeId 为空串 |
employeeId 非法:教师工号(tId)不能为空 |
employeeId 仅由 _teacher 组成 |
7. 报到业务
7.1 报到重置
- 接口路径:
/api/register/v1/report/reset - 请求方法:
POST - 功能说明:用于“误点他人信息导致人脸错绑”的补救。按顺序执行 4 步,任一关键步骤失败即中止并返回原因:
- 解绑人脸(复用
TrainFaceApiController.deleteEmployee,employee_id = studentId); - 清除门锁入住授权(复用
TrainLockApiController.checkout),住宿分配记录保留; - 参训状态重置为未报到
0(备注保持不变); - 清空学员头像(
train_student.avatar置 NULL)。
- 解绑人脸(复用
请求参数(Query / Form,@RequestParam,非 JSON Body)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
planId |
string | 是 | 开班计划ID(train_enrollment.plan_id) |
studentId |
string | 是 | 学员ID(train_enrollment.student_id) |
返回结果说明:data 字段:
| 字段 | 类型 | 说明 |
|---|---|---|
planId |
string | 开班计划ID |
studentId |
string | 学员ID |
enrollmentId |
number | 参训记录主键 |
previousStatus |
number | 重置前的报到状态 |
faceUnbind |
string | 人脸解绑结果,成功为 success |
lockCheckout |
string | 门锁授权清除结果:success / skipped: 无有效住宿记录 / skipped: 缺少门锁业务流水号与宿舍信息 |
lockApiBizNo |
string | 门锁业务流水号(清除成功时返回) |
currentStatus |
number | 重置后状态,固定 0 |
alreadyReset |
boolean | 重置前是否已是未报到 |
accommodationKept |
boolean | 是否保留了住宿记录 |
avatarCleared |
boolean | 头像是否已清空(成功路径) |
avatarSId |
string | 清空头像的学员ID(成功路径) |
失败场景(code=500):
| msg | 触发条件 |
|---|---|
planId 和 studentId 不能为空 |
任一参数为空 |
未找到学员[xxx]在班级[yyy]的参训记录 |
报名记录不存在 |
学员已放弃培训,不允许重置报到状态 |
previousStatus = 3 |
学员已结训,不允许重置报到状态 |
previousStatus = 4 |
步骤1 人脸解绑失败:...;参训状态未变更 |
人脸解绑未返回 200 |
步骤2 门锁授权清除响应解析失败:...;人脸已解绑,参训状态未变更 |
下游响应非法 JSON |
步骤2 门锁授权清除失败:...;人脸已解绑,参训状态未变更 |
下游返回非 200 |
步骤3 参训状态重置失败;人脸与门锁授权已解除,请人工核对后重试 |
状态更新影响行数为 0 |
报到重置已完成,但未找到有效学员档案[xxx],avatar 未清空 |
主档缺失(data 仍返回已完成信息) |
报到重置已完成,但清空学员头像失败:... |
头像更新异常(data 仍返回已完成信息) |
{
"code": 200,
"msg": "报到重置成功",
"data": {
"planId": "P2026001",
"studentId": "S0001",
"enrollmentId": 5001,
"previousStatus": 1,
"faceUnbind": "success",
"lockCheckout": "success",
"lockApiBizNo": "STAY20261105001",
"currentStatus": 0,
"alreadyReset": false,
"accommodationKept": true,
"avatarCleared": true,
"avatarSId": "S0001"
}
}
8. 宿舍布局
8.1 获取宿舍布局信息
- 接口路径:
/api/register/v1/dormitory/layout - 请求方法:
GET - 功能说明:查询
train_dormitory_info(仅未删除房间),依次按dorm_building(楼栋)→dorm_floor(楼层)→dorm_room(房间号)分组;并左关联train_accommodation统计每个房间的已分配床位数(住宿状态0 预分配/1 已入住计入,2 已退宿不计),总床位数取房间核定容量capacity。
请求参数:无
返回结果说明:
data为三层嵌套对象,键依次为「楼栋名称 → 楼层 → 房间号」,每间房的值包含:
| 字段 | 类型 | 说明 |
|---|---|---|
id |
number | 宿舍自增编号(train_dormitory_info.id) |
dorm_room |
string | 房间号 |
accommodation |
string | 已分配床位数/总床位数,如 "2/4" |
- 楼栋、楼层、房间均按数据库升序排列(
dorm_building, dorm_floor, dorm_room),嵌套对象使用有序 Map 输出,顺序稳定。 - 无房间数据时
data为空对象{}。
{
"code": 200,
"msg": "操作成功",
"data": {
"1号楼": {
"1": {
"101": { "id": 1, "dorm_room": "101", "accommodation": "2/4" },
"102": { "id": 2, "dorm_room": "102", "accommodation": "0/4" }
},
"2": {
"201": { "id": 5, "dorm_room": "201", "accommodation": "4/6" }
}
},
"2号楼": {
"1": {
"101": { "id": 9, "dorm_room": "101", "accommodation": "1/2" }
}
}
}
}
说明:同一楼栋内房间号唯一(约束
uq_dorm_building_room),因此以房间号作为楼层下的键不会冲突;楼层为空时键为未标注楼层。
9. 附录
9.1 典型调用流程
GET /student/list或GET /class/student—— 报到机展示待报到人员。GET /teacher/list—— 展示教师名单(sId形如T0001_teacher)。- 人员点击后:
GET /student/{sId}/resources(或/base)—— 展示开班、宿舍、教室、课表。 - 采集人脸后:
POST /face(统一入口,传employeeId+faceImage)—— 完成照片入库、设备下发、报到登记、门锁入住。 - 宿舍看板:
GET /dormitory/layout—— 按楼栋/楼层/房间展示床位占用情况。 - 误绑时:
POST /report/reset?planId=...&studentId=...—— 回退报到与人脸/门锁授权。
9.2 调用示例
# 学员列表
curl "http://localhost:8096/api/register/v1/student/list"
# 学员关联资源
curl "http://localhost:8096/api/register/v1/student/S0001/resources"
# 教师基础信息(tId 可带 _teacher 后缀)
curl "http://localhost:8096/api/register/v1/teacher/T0001_teacher/base"
# 统一人脸上传
curl -X POST "http://localhost:8096/api/register/v1/face" \
-H "Content-Type: application/json" \
-d '{"employeeId":"S0001","faceImage":"data:image/jpeg;base64,/9j/4AAQSkZJRg..."}'
# 报到重置(需登录态)
curl -X POST "http://localhost:8096/api/register/v1/report/reset?planId=P2026001&studentId=S0001" \
-H "Authorization: Bearer {token}"
# 宿舍布局
curl "http://localhost:8096/api/register/v1/dormitory/layout"
9.3 与源码注释的差异说明
| 位置 | 注释/声明 | 实际实现 |
|---|---|---|
| 类注释 | 登录接口需 HMAC 签名(X-Signature/X-Nonce) |
控制器内未实现;DeviceHmacFilter 仅覆盖 /api/iot/v1/device/login |
SecurityConfig 注释 |
/api/register/v1/** 走 Bearer 鉴权 |
已配置 permitAll,除 /report/reset 外不校验 Token |
/student/{sId}/base |
注释称返回“课表、实训场地” | 实际不返回 courses、lesson,需调用 /student/{sId}/resources |