chore(sync): 同步当前工作区全部变更(学员学号可编辑并留空自动生成等)
This commit is contained in:
1 parent
01e949093a
commit
f5e8d7f564
531 files changed
+72978
-2720
No files matched your search
@@ -0,0 +1,612 @@
|
||||
# 电子班牌接口 API 文档
|
||||
|
||||
| 项目 | 内容 |
|
||||
|---|---|
|
||||
| 控制器 | `com.ruoyi.web.controller.api.TrainBoardApiController` |
|
||||
| 源文件 | `ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TrainBoardApiController.java` |
|
||||
| BasePath | `/api/board/v1` |
|
||||
| 接口数量 | 7(4 个查询类 + 1 个签到上报 + 2 个新增能力) |
|
||||
| 鉴权 | RuoYi Bearer Token(`Authorization: Bearer {token}`) |
|
||||
| 文档更新 | 2026-11-03 |
|
||||
| 编写依据 | 控制器源码逐行核对,与当前实现一致 |
|
||||
|
||||
---
|
||||
|
||||
## 目录
|
||||
|
||||
- [1. 通用约定](#1-通用约定)
|
||||
- [1.1 鉴权](#11-鉴权)
|
||||
- [1.2 统一响应结构](#12-统一响应结构)
|
||||
- [1.3 状态码](#13-状态码)
|
||||
- [1.4 列表数据包装](#14-列表数据包装)
|
||||
- [1.5 字段类型说明](#15-字段类型说明)
|
||||
- [2. 接口总览](#2-接口总览)
|
||||
- [3. 接口详情](#3-接口详情)
|
||||
- [3.1 查询教室信息](#31-查询教室信息)
|
||||
- [3.2 查询指定教室当天课程](#32-查询指定教室当天课程)
|
||||
- [3.3 查询指定班级在指定教室的座位](#33-查询指定班级在指定教室的座位)
|
||||
- [3.4 查询班级学员卡号](#34-查询班级学员卡号)
|
||||
- [3.5 上报签到数据](#35-上报签到数据)
|
||||
- [3.6 查询本节课签到记录](#36-查询本节课签到记录)
|
||||
- [3.7 查询座位布局](#37-查询座位布局)
|
||||
- [4. 异常与错误汇总](#4-异常与错误汇总)
|
||||
- [5. 调用示例](#5-调用示例)
|
||||
- [6. 附录](#6-附录)
|
||||
|
||||
---
|
||||
|
||||
## 1. 通用约定
|
||||
|
||||
### 1.1 鉴权
|
||||
|
||||
- 所有接口均需携带 `Authorization: Bearer {token}`,Token 由平台登录接口签发。
|
||||
- 未携带或 Token 失效时,返回 **HTTP 200** + 响应体 `code=401`:
|
||||
|
||||
```json
|
||||
{ "code": 401, "msg": "请求访问:/api/board/v1/signageService/selectClassroom,认证失败,无法访问系统资源" }
|
||||
```
|
||||
|
||||
> 本控制器未使用 `@PreAuthorize` 数据权限注解,因此不存在 `403` 业务场景。
|
||||
|
||||
### 1.2 统一响应结构
|
||||
|
||||
所有接口返回 `AjaxResult`:
|
||||
|
||||
```json
|
||||
{ "code": 200, "msg": "操作成功", "data": {} }
|
||||
```
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `code` | number | 业务状态码,见 1.3 |
|
||||
| `msg` | string | 提示信息;成功固定为 `操作成功` |
|
||||
| `data` | object / array | 业务数据,无数据时字段不出现 |
|
||||
|
||||
### 1.3 状态码
|
||||
|
||||
| code | 含义 | HTTP 状态 | 触发来源 |
|
||||
|---|---|---|---|
|
||||
| 200 | 成功 | 200 | 正常返回 |
|
||||
| 401 | 未认证 / Token 无效 | **200** | `AuthenticationEntryPointImpl` |
|
||||
| 404 | 接口路径不存在 | 404 | `NoResourceFoundException` |
|
||||
| 500 | 参数缺失、参数格式错误、数据校验失败、控制器内业务拦截、系统异常 | 200 | `GlobalExceptionHandler` / 控制器返回值 |
|
||||
| 40080 / 40081 / 40085 / 40086 / 40087 | 考勤业务码(计划不一致 / 课次不存在 / 未报到 / 已放弃 / 已结训) | 200 | `ServiceException`(`AttendanceErrorCode`) |
|
||||
|
||||
> **调用方必须判断响应体 `code`**:除 404 外,失败场景的 HTTP 状态码仍是 200。
|
||||
|
||||
### 1.4 列表数据包装
|
||||
|
||||
除 `3.1 查询教室信息`(`data` 直接是数组)外,其余查询接口的 `data` 为:
|
||||
|
||||
```json
|
||||
{ "total": 2, "rows": [ ... ] }
|
||||
```
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `total` | number | 本次返回的记录数(非分页总数) |
|
||||
| `rows` | array | 数据列表,无数据时为 `[]` |
|
||||
|
||||
### 1.5 字段类型说明
|
||||
|
||||
类注释约定 `id / classId / classroomId / courseId / teacherId / stuId / studentId` 为 Long,
|
||||
但本系统相关表以业务编码为主键(字符串),因此这些字段**返回字符串**;
|
||||
仅 `lessonId(id)`、`enrollmentId`、`zoneId`、`seatId`、`capacity`、`classHour` 等为数值。
|
||||
|
||||
---
|
||||
|
||||
## 2. 接口总览
|
||||
|
||||
| # | 接口名称 | 方法 | 路径 | 用途 |
|
||||
|---|---|---|---|---|
|
||||
| 3.1 | 查询教室信息 | GET | `/api/board/v1/signageService/selectClassroom` | 返回全部教学教室与实训场地 |
|
||||
| 3.2 | 查询指定教室当天课程 | GET | `/api/board/v1/signageService/coursesInClassroom` | 按教室与日期范围返回排课 |
|
||||
| 3.3 | 查询指定班级在指定教室的座位 | GET | `/api/board/v1/signageService/studentInClassroom` | 返回座位网格(含学员姓名) |
|
||||
| 3.4 | 查询班级学员卡号 | GET | `/api/board/v1/signageService/studentCard` | 刷卡校验用卡号与班级信息 |
|
||||
| 3.5 | 上报签到数据 | POST | `/api/board/v1/signageService/checkin/upload` | JSON 上报签到并落库 |
|
||||
| 3.6 | 查询本节课签到记录 | GET | `/api/board/v1/signageService/checkin/list` | 按课次返回签到流水与学员姓名 |
|
||||
| 3.7 | 查询座位布局 | GET | `/api/board/v1/signageService/seatLayout` | 仅读 `train_class_seat` 的座位布局 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 接口详情
|
||||
|
||||
### 3.1 查询教室信息
|
||||
|
||||
**用途**:返回全部教学教室 + 实训场地(`train_classroom_info` UNION `train_training_site`),供班牌后台定位终端绑定教室。
|
||||
|
||||
| 项 | 内容 |
|
||||
|---|---|
|
||||
| HTTP 方法 | `GET` |
|
||||
| 请求路径 | `/api/board/v1/signageService/selectClassroom` |
|
||||
| 鉴权 | 需要 |
|
||||
|
||||
**请求参数**:无。
|
||||
|
||||
**请求体**:无。
|
||||
|
||||
**响应结构**:`data` 为数组(**不是** `{total, rows}` 包装)。
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `id` | string | 教室ID(`class_room_id`)或场地ID(`site_id`) |
|
||||
| `name` | string | 教室/场地名称 |
|
||||
| `campus` | string | 校区/位置 |
|
||||
| `capacity` | number | 容量 |
|
||||
| `outside` | number | `0`=教室,`1`=实训场地 |
|
||||
| `category` | string | `教室` / `实训场地` |
|
||||
|
||||
**成功示例**
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "操作成功",
|
||||
"data": [
|
||||
{ "id": "CR01", "name": "多媒体教室01", "campus": "一号教学楼3层", "capacity": 60, "outside": 0, "category": "教室" },
|
||||
{ "id": "SITE01", "name": "信号实训场", "campus": "实训楼1层", "capacity": 40, "outside": 1, "category": "实训场地" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**异常说明**:未认证 → `code=401`;无数据 → `data: []`。
|
||||
|
||||
---
|
||||
|
||||
### 3.2 查询指定教室当天课程
|
||||
|
||||
**用途**:按教室/场地与日期范围(含首尾日期)返回排课列表。文档约定 `beginDate=endDate=当天`,接口本身不限制两者相等。
|
||||
|
||||
| 项 | 内容 |
|
||||
|---|---|
|
||||
| HTTP 方法 | `GET` |
|
||||
| 请求路径 | `/api/board/v1/signageService/coursesInClassroom` |
|
||||
| 鉴权 | 需要 |
|
||||
|
||||
**请求参数(Query String)**
|
||||
|
||||
| 名称 | 类型 | 必填 | 默认值 | 说明 |
|
||||
|---|---|---|---|---|
|
||||
| `classroomId` | string | 是 | 无 | 教室ID(`class_room_id`)或场地ID(`site_id`),SQL 同时匹配两列 |
|
||||
| `beginDate` | string | 是 | 无 | 开始日期 `yyyy-MM-dd`,条件 `start_time >= beginDate` |
|
||||
| `endDate` | string | 是 | 无 | 结束日期 `yyyy-MM-dd`,条件 `start_time < endDate + 1 天`(含当天) |
|
||||
|
||||
**请求体**:无。
|
||||
|
||||
**响应结构**:`data = { total, rows[] }`
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `id` | number | 排课ID(`train_lesson.lesson_id`),**即 3.5 的 `lessonId`** |
|
||||
| `courseId` | string | 课程主数据ID(`train_course.c_id`) |
|
||||
| `classId` | string | 班级ID(`train_class_plan.plan_id`) |
|
||||
| `classroomId` | string | 教室ID或场地ID(`COALESCE(class_room_id, site_id)`) |
|
||||
| `courseName` | string | 课程名称 |
|
||||
| `couresName` | string | 兼容旧拼写的课程名称(与 `courseName` 同值) |
|
||||
| `courseTime` | string | 上课时间 `yyyy-MM-dd HH:mm:ss` |
|
||||
| `classHour` | number | 时长(分钟) |
|
||||
| `className` | string | 班级名称 |
|
||||
| `teacherId` | string | 教师ID(`train_lesson.t_id`) |
|
||||
| `teacherName` | string | 教师姓名,未排教师为 `null` |
|
||||
| `courseIntro` | string | 课程简介(`train_course.teaching_objective`) |
|
||||
| `isPublic` | number | 固定 `0` |
|
||||
|
||||
**成功示例**
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "操作成功",
|
||||
"data": {
|
||||
"total": 1,
|
||||
"rows": [
|
||||
{
|
||||
"id": 1001, "courseId": "CR01", "classId": "PLAN_A", "classroomId": "CR01",
|
||||
"courseName": "电子班牌数字化实务", "couresName": "电子班牌数字化实务",
|
||||
"courseTime": "2026-11-02 09:00:00", "classHour": 90,
|
||||
"className": "2026年第一期培训班", "teacherId": "T101", "teacherName": "张三",
|
||||
"courseIntro": "班牌设备安装与配置", "isPublic": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**异常说明**
|
||||
|
||||
| 场景 | 响应 |
|
||||
|---|---|
|
||||
| 缺少 `classroomId` | `{"code":500,"msg":"Required request parameter 'classroomId' for method parameter type String is not present"}` |
|
||||
| 无排课 | `{"code":200,"msg":"操作成功","data":{"total":0,"rows":[]}}` |
|
||||
|
||||
---
|
||||
|
||||
### 3.3 查询班级学员卡号
|
||||
|
||||
**用途**:按班级返回学员卡号与班级、住宿信息,用于班牌刷卡校验。仅返回参训状态非“已放弃(3)”的学员。
|
||||
|
||||
| 项 | 内容 |
|
||||
|---|---|
|
||||
| HTTP 方法 | `GET` |
|
||||
| 请求路径 | `/api/board/v1/signageService/studentCard` |
|
||||
| 鉴权 | 需要 |
|
||||
|
||||
**请求参数(Query String)**
|
||||
|
||||
| 名称 | 类型 | 必填 | 默认值 | 说明 |
|
||||
|---|---|---|---|---|
|
||||
| `classId` | string | 是 | 无 | 班级ID(`train_enrollment.plan_id`) |
|
||||
|
||||
**请求体**:无。
|
||||
|
||||
**响应结构**:`data = { total, rows[] }`
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `cardNo` | string | 卡号(`train_student.card_no`,保留前导零) |
|
||||
| `studentId` | string | 学员ID(`s_id`) |
|
||||
| `classId` | string | 班级ID |
|
||||
| `studentName` | string | 学员姓名 |
|
||||
| `className` | string | 班级名称 |
|
||||
| `id` | number | 参训档案ID(`enrollment_id`,**不是学员ID**) |
|
||||
| `roomId` | string | 宿舍ID,未分配为 `null` |
|
||||
| `bedType` | string | 床位类型(预留,固定 `null`) |
|
||||
| `seatNumber` | string | 床位号,未分配为 `null` |
|
||||
|
||||
**成功示例**
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "操作成功",
|
||||
"data": {
|
||||
"total": 1,
|
||||
"rows": [
|
||||
{ "cardNo": "00012345", "studentId": "STU_1", "classId": "PLAN_A", "studentName": "王五", "className": "2026年第一期培训班", "id": 201, "roomId": "DORM-101", "bedType": null, "seatNumber": "1" }
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**异常说明**:缺少 `classId` → `code=500`;无数据 → `{total:0, rows:[]}`。
|
||||
|
||||
---
|
||||
|
||||
### 3.4 上报签到数据
|
||||
|
||||
**用途**:班牌上报学员签到。服务端按 `studentId` 在课次所属培训班内查询 `train_enrollment` 得到 `enrollmentId`,写入 `train_student_checkin`(`student_id`、`board_id`、`lesson_id`、`sign_in_time` 一并落库)。
|
||||
|
||||
| 项 | 内容 |
|
||||
|---|---|
|
||||
| HTTP 方法 | `POST` |
|
||||
| 请求路径 | `/api/board/v1/signageService/checkin/upload` |
|
||||
| 鉴权 | 需要 |
|
||||
| Content-Type | **必须 `application/json`** |
|
||||
| 文件上传 | 无 |
|
||||
|
||||
**请求参数**:无 Query 参数,全部字段在请求体中。
|
||||
|
||||
**请求体结构**(`BoardCheckinUploadRequest`)
|
||||
|
||||
| 名称 | 类型 | 必填 | 默认值 | 说明 |
|
||||
|---|---|---|---|---|
|
||||
| `studentId` | string | 是 | 无 | 学员ID(`train_student.s_id`),首尾空格会被去除 |
|
||||
| `boardId` | string | 否 | `null` | 门牌(班牌)ID,写入 `train_student_checkin.board_id`;空串按 `null` 处理 |
|
||||
| `lessonId` | number(long) | 是 | 无 | 课程(课次)ID,对应 `train_student_checkin.lesson_id`,取值来自 3.2 的 `id` |
|
||||
| `signInTime` | string | 否 | 服务器当前时间 | 签到时间,格式 `yyyy-MM-dd HH:mm:ss`;格式非法直接报错,不静默改写 |
|
||||
|
||||
```json
|
||||
{
|
||||
"studentId": "STU_1",
|
||||
"boardId": "BP001",
|
||||
"lessonId": 1001,
|
||||
"signInTime": "2026-11-02 08:30:00"
|
||||
}
|
||||
```
|
||||
|
||||
**响应结构**(`data` 为单对象)
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `checkinId` | number | 考勤记录ID |
|
||||
| `studentId` | string | 学员ID(库中 `student_id`,为空时回填请求值) |
|
||||
| `enrollmentId` | number | 参训档案ID(由 `studentId` + 班次推导) |
|
||||
| `lessonId` | number | 课次ID |
|
||||
| `boardId` | string | 班牌ID,未传为 `null` |
|
||||
| `signInTime` | string | 实际落库的签到时间 `yyyy-MM-dd HH:mm:ss` |
|
||||
|
||||
**成功示例**
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "操作成功",
|
||||
"data": {
|
||||
"checkinId": 9001, "studentId": "STU_1", "enrollmentId": 201,
|
||||
"lessonId": 1001, "boardId": "BP001", "signInTime": "2026-11-02 08:30:00"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**异常与错误说明**
|
||||
|
||||
| 场景 | code | 响应 msg |
|
||||
|---|---|---|
|
||||
| `studentId` 为空 | 500 | `studentId 不能为空` |
|
||||
| `lessonId` 为空 | 500 | `lessonId 不能为空` |
|
||||
| `signInTime` 格式错误 | 500 | `signInTime 格式不正确,应为 yyyy-MM-dd HH:mm:ss` |
|
||||
| 课次不存在 | 500 | `课程(课次)不存在: 1001` |
|
||||
| 课次未关联有效培训计划 | 500 | `课程(课次)[1001]未关联有效的培训计划` |
|
||||
| 学员无该班参训记录 | 500 | `未找到学员[STU_1]在班级[PLAN_A]的参训记录` |
|
||||
| 非 JSON / 空请求体 | 500 | Spring 反序列化异常信息(如 `Content-Type 'text/plain' is not supported`) |
|
||||
| 未认证 | 401 | `请求访问:/api/board/v1/signageService/checkin/upload,认证失败,无法访问系统资源` |
|
||||
| 学员未报到 / 已放弃 / 已结训 | 40085 / 40086 / 40087 | 对应中文提示(见 `AttendanceErrorCode`) |
|
||||
| 课次所属计划与参训计划不一致 | 40080 | `业务不变量校验失败:考勤学员与课次所属培训班不一致` |
|
||||
|
||||
**业务规则**
|
||||
|
||||
1. **幂等**:同一 `enrollmentId + lessonId` 已有签到记录(`sign_in_time` 非空)时返回已有记录,不覆盖首次签到时间。
|
||||
2. **生命周期**:仅“已报到(1)”“请假(2)”状态允许签到。
|
||||
3. **计划一致性**:学员参训档案所属培训班必须与课次所属培训班一致。
|
||||
4. **打卡方式**:固定按设备打卡 `checkinWay=1` 落库。
|
||||
|
||||
---
|
||||
|
||||
### 3.5 查询本节课签到记录
|
||||
|
||||
**用途**:按 `lessonId` 返回 `train_student_checkin` 签到流水,并按 `studentId` 关联 `train_student` 返回学员姓名(`s_name`)。
|
||||
|
||||
| 项 | 内容 |
|
||||
|---|---|
|
||||
| HTTP 方法 | `GET` |
|
||||
| 请求路径 | `/api/board/v1/signageService/checkin/list` |
|
||||
| 鉴权 | 需要 |
|
||||
|
||||
**请求参数(Query String)**
|
||||
|
||||
| 名称 | 类型 | 必填 | 默认值 | 说明 |
|
||||
|---|---|---|---|---|
|
||||
| `lessonId` | number(long) | 是 | 无 | 课程(课次)ID;非数字时返回参数类型不匹配错误 |
|
||||
|
||||
**请求体**:无。
|
||||
|
||||
**响应结构**:`data = { total, rows[] }`,`rows[]` 为 `TrainStudentCheckin`:
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `checkinId` | number | 考勤记录ID |
|
||||
| `enrollmentId` | number | 参训档案ID |
|
||||
| `lessonId` | number | 课次ID |
|
||||
| `studentId` | string | 学员ID(优先取 `train_student_checkin.student_id`,为空取参训档案的 `student_id`) |
|
||||
| `studentName` | string | 学员姓名(`train_student.s_name`) |
|
||||
| `planId` | string | 培训班ID |
|
||||
| `planName` | string | 培训班名称 |
|
||||
| `className` | string | 班级名称 |
|
||||
| `courseName` | string | 课程名称 |
|
||||
| `boardId` | string | 打卡班牌ID |
|
||||
| `boardSn` | string | 班牌序列号 |
|
||||
| `boardName` | string | 班牌名称 |
|
||||
| `checkinWay` | number | 打卡方式:1 人脸/设备,2 刷卡,3 扫码,4 教师代签 |
|
||||
| `signInTime` | string | 签到时间 `yyyy-MM-dd HH:mm:ss`,未签到为 `null` |
|
||||
| `signOutTime` | string | 签退时间 `yyyy-MM-dd HH:mm:ss`,未签退为 `null` |
|
||||
| `attendanceStatus` | number | 考勤结论:0 缺勤,1 正常,2 迟到,3 早退,4 请假 |
|
||||
| `manualFlag` | number | 是否人工修正:0 否,1 是 |
|
||||
| `createBy` / `createTime` / `updateBy` / `updateTime` / `remark` | string | 审计字段(时间格式 `yyyy-MM-dd HH:mm:ss`) |
|
||||
|
||||
> `params` 为空时不输出;`searchValue` 始终不输出。
|
||||
|
||||
**成功示例**
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "操作成功",
|
||||
"data": {
|
||||
"total": 1,
|
||||
"rows": [
|
||||
{
|
||||
"checkinId": 9001, "enrollmentId": 201, "lessonId": 1001,
|
||||
"studentId": "STU_1", "studentName": "张三",
|
||||
"planId": "PLAN_A", "planName": "2026年第一期培训班", "className": "一班",
|
||||
"courseName": "电子班牌数字化实务",
|
||||
"boardId": "BP001", "boardSn": "BP001", "boardName": "1号班牌",
|
||||
"checkinWay": 1, "signInTime": "2026-11-02 08:30:00", "signOutTime": null,
|
||||
"attendanceStatus": 1, "manualFlag": 0,
|
||||
"createBy": "board_device", "createTime": "2026-11-02 08:30:01",
|
||||
"updateBy": null, "updateTime": null, "remark": null
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**异常与错误说明**
|
||||
|
||||
| 场景 | 响应 |
|
||||
|---|---|
|
||||
| 缺少 `lessonId` | `{"code":500,"msg":"Required request parameter 'lessonId' for method parameter type Long is not present"}` |
|
||||
| `lessonId` 非数字 | `{"code":500,"msg":"请求参数类型不匹配,参数[lessonId]要求类型为:'java.lang.Long',但输入值为:'abc'"}` |
|
||||
| 课次无签到记录 | `{"code":200,"msg":"操作成功","data":{"total":0,"rows":[]}}` |
|
||||
|
||||
---
|
||||
|
||||
### 3.6 查询座位布局
|
||||
|
||||
**用途**:按班级与教室查询座位布局,**仅读取 `train_class_seat` 单表**,不关联学员、教室、班级表;不校验班级是否删除、学员是否存在。
|
||||
|
||||
| 项 | 内容 |
|
||||
|---|---|
|
||||
| HTTP 方法 | `GET` |
|
||||
| 请求路径 | `/api/board/v1/signageService/seatLayout` |
|
||||
| 鉴权 | 需要 |
|
||||
|
||||
**请求参数(Query String)**
|
||||
|
||||
| 名称 | 类型 | 必填 | 默认值 | 说明 |
|
||||
|---|---|---|---|---|
|
||||
| `planId` | string | 是 | 无 | 班级ID,对应 `train_class_seat.plan_id` |
|
||||
| `classroomId` | string | 是 | 无 | 教室ID,对应 `train_class_seat.classroom_id` |
|
||||
|
||||
**请求体**:无。
|
||||
|
||||
**响应结构**:`data = { total, rows[] }`
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `seatId` | number | 座位主键(`seat_id`) |
|
||||
| `planId` | string | 班级ID(`plan_id`) |
|
||||
| `classroomId` | string | 教室ID(`classroom_id`) |
|
||||
| `rowIndex` | number | 行号,从 1 开始 |
|
||||
| `colIndex` | number | 列号,从 1 开始 |
|
||||
| `seatCode` | string | 物理座位标识(`seat_code`) |
|
||||
| `canceled` | number | `0`=正常,`1`=取消位置(**不做过滤,原样返回**) |
|
||||
| `studentId` | string | 占用座位学员ID,空座为 `null` |
|
||||
| `zoneId` | number | 区域ID |
|
||||
| `deptDetail` | string | 部门 |
|
||||
| `job` | string | 职务 |
|
||||
|
||||
排序:`row_index, col_index` 升序。
|
||||
|
||||
**成功示例**
|
||||
|
||||
```json
|
||||
http://localhost:8096/api/board/v1/signageService/seatLayout?classroomId=afcf21a8bd99488cb19638d285f157a8&planId=f70ec13a651942e8a704ee4cc010c95e
|
||||
|
||||
{
|
||||
"msg": "操作成功",
|
||||
"code": 200,
|
||||
"data": {
|
||||
"total": 2,
|
||||
"rows": [
|
||||
{
|
||||
"canceled": 0,
|
||||
"classroomId": "afcf21a8bd99488cb19638d285f157a8",
|
||||
"colIndex": 5,
|
||||
"deptDetail": null,
|
||||
"job": null,
|
||||
"planId": "f70ec13a651942e8a704ee4cc010c95e",
|
||||
"rowIndex": 2,
|
||||
"seatCode": "2-5",
|
||||
"seatId": 29,
|
||||
"studentId": "c78c425e66384104bf37d150519fc5d3",
|
||||
"zoneId": null
|
||||
},
|
||||
{
|
||||
"canceled": 0,
|
||||
"classroomId": "afcf21a8bd99488cb19638d285f157a8",
|
||||
"colIndex": 9,
|
||||
"deptDetail": null,
|
||||
"job": null,
|
||||
"planId": "f70ec13a651942e8a704ee4cc010c95e",
|
||||
"rowIndex": 3,
|
||||
"seatCode": "3-9",
|
||||
"seatId": 30,
|
||||
"studentId": "63d889e8be2c4d61900d09b51b2108a5",
|
||||
"zoneId": null
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**异常与错误说明**
|
||||
|
||||
| 场景 | 响应 |
|
||||
|---|---|
|
||||
| 缺少 `planId` 或 `classroomId` | `code=500`,`msg` 为 Spring 缺参提示 |
|
||||
| 该班该教室无座位数据 | `{"code":200,"msg":"操作成功","data":{"total":0,"rows":[]}}` |
|
||||
| 表 `train_class_seat` 不存在 | `code=500`,`msg` 含 `Table 'xxx.train_class_seat' doesn't exist`(需先执行 `sql/train/v2/019_signage.sql`) |
|
||||
|
||||
---
|
||||
|
||||
## 4. 异常与错误汇总
|
||||
|
||||
| 类型 | 返回形式 | 说明 |
|
||||
|---|---|---|
|
||||
| 未认证 | HTTP 200,`code=401` | Token 缺失、过期、伪造 |
|
||||
| 路径不存在 | HTTP 404,`code=404`,`msg=接口不存在或未启用` | 路由未匹配 |
|
||||
| 缺少必填 Query 参数 | HTTP 200,`code=500` | `Required request parameter 'xxx' ... is not present` |
|
||||
| 参数类型不匹配 | HTTP 200,`code=500` | `请求参数类型不匹配,参数[lessonId]要求类型为:'java.lang.Long',但输入值为:'abc'` |
|
||||
| 请求方法不支持 | HTTP 200,`code=500` | `Request method 'GET' is not supported` |
|
||||
| 请求体非 JSON | HTTP 200,`code=500` | `Content-Type 'xxx' is not supported` |
|
||||
| 控制器内业务拦截 | HTTP 200,`code=500` | 见 3.5 异常表 |
|
||||
| 考勤业务异常 | HTTP 200,`code=40080/40081/40085/40086/40087` | `AttendanceErrorCode` |
|
||||
|
||||
`AttendanceErrorCode` 常用码:
|
||||
|
||||
| code | 含义 |
|
||||
|---|---|
|
||||
| 40080 | 考勤学员与课次所属培训班不一致 |
|
||||
| 40081 | 课次不存在 |
|
||||
| 40085 | 学员尚未完成开班报到,禁止录入课次考勤 |
|
||||
| 40086 | 学员已放弃培训 |
|
||||
| 40087 | 学员已结训 |
|
||||
|
||||
---
|
||||
|
||||
## 5. 调用示例
|
||||
|
||||
```bash
|
||||
# 登录获取 token(按平台实际登录接口调整)
|
||||
TOKEN=$(curl -s -X POST 'http://192.168.106.24:8096/login' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"username":"admin","password":"admin123"}' | sed -n 's/.*"token":"\([^"]*\)".*/\1/p')
|
||||
|
||||
# 3.1 教室信息
|
||||
curl -s 'http://192.168.106.24:8096/api/board/v1/signageService/selectClassroom' \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
|
||||
# 3.2 指定教室当天课程
|
||||
curl -s 'http://192.168.106.24:8096/api/board/v1/signageService/coursesInClassroom?classroomId=CR01&beginDate=2026-11-02&endDate=2026-11-02' \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
|
||||
# 3.3 指定班级在指定教室的座位
|
||||
curl -s 'http://192.168.106.24:8096/api/board/v1/signageService/studentInClassroom?classroomId=CR01&classId=PLAN_A' \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
|
||||
# 3.4 班级学员卡号
|
||||
curl -s 'http://192.168.106.24:8096/api/board/v1/signageService/studentCard?classId=PLAN_A' \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
|
||||
# 3.5 上报签到(JSON 请求体)
|
||||
curl -s -X POST 'http://192.168.106.24:8096/api/board/v1/signageService/checkin/upload' \
|
||||
-H 'Content-Type: application/json' -H "Authorization: Bearer $TOKEN" \
|
||||
-d '{"studentId":"STU_1","boardId":"BP001","lessonId":1001,"signInTime":"2026-11-02 08:30:00"}'
|
||||
|
||||
# 3.6 本节课签到记录
|
||||
curl -s 'http://192.168.106.24:8096/api/board/v1/signageService/checkin/list?lessonId=1001' \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
|
||||
# 3.7 座位布局
|
||||
curl -s 'http://192.168.106.24:8096/api/board/v1/signageService/seatLayout?planId=P2026001&classroomId=CR-001' \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 附录
|
||||
|
||||
### 6.1 数据来源
|
||||
|
||||
| 接口 | 主要数据表 |
|
||||
|---|---|
|
||||
| 3.1 | `train_classroom_info`、`train_training_site` |
|
||||
| 3.2 | `train_lesson`、`train_plan_course`、`train_course`、`train_class_plan`、`train_teacher` |
|
||||
| 3.3 | `train_class_seat`、`train_class_plan`、`train_student` |
|
||||
| 3.4 | `train_enrollment`、`train_student`、`train_class_plan`、`train_accommodation`、`train_dormitory_info` |
|
||||
| 3.5 | `train_lesson`、`train_plan_course`、`train_enrollment`、`train_student_checkin` |
|
||||
| 3.6 | `train_student_checkin`、`train_enrollment`、`train_student`、`train_class_plan`、`train_plan_course`、`train_course`、`train_electronic_board` |
|
||||
| 3.7 | `train_class_seat`(单表) |
|
||||
|
||||
### 6.2 Swagger
|
||||
|
||||
Swagger UI:`/swagger-ui/index.html`,分组 `电子班牌接口`。
|
||||
若 3.5 的 Request body 显示为 query 参数,说明部署的是旧包(当前实现为 `@RequestBody`)。
|
||||
|
||||
### 6.3 已知约束
|
||||
|
||||
1. `lessonId` 是**课次ID(`train_lesson.lesson_id`,数值)**,不是课程编码(`c_id`,如 `CR01`);班牌须先调用 3.2 获取 `id`。
|
||||
2. 3.5 只接受 JSON 请求体,query/form 写法无效。
|
||||
3. 3.5 依赖 `train_student_checkin.student_id` 列;报 `Unknown column 'a.student_id'` 时需执行 `sql/train/v2/020b_add_checkin_student_id_mysql.sql`(MySQL)或 `sql/train/v2/020_add_checkin_student_id.sql`(KingbaseES/PostgreSQL)。
|
||||
4. 3.3 与 3.7 的区别:3.3 关联 `train_student` 返回姓名并过滤已删除班级;3.7 严格单表返回,含 `canceled=1` 的座位,不做班级有效性校验。
|
||||
5. 所有查询接口的 `total` 为本次返回条数,不是分页总数。
|
||||
Reference in new issue
Block a user