接口设计
1. 协议:HTTP/1.1 + JSON;实时答题另有 WebSocket 通道用于状态推送(断线时前端自动降级为轮询)。
本页目录
6.1 接口约定
- 协议:HTTP/1.1 + JSON;实时答题另有 WebSocket 通道用于状态推送(断线时前端自动降级为轮询)。
- 鉴权:会话 Cookie(名称
qt,HttpOnly + SameSite=lax,有效期 30 天)。 - 管理面守卫:中间件统一拦截
- 页面前缀
/admin、/qbank→ 需教师及以上(is_staff); - 接口前缀
/api/admin、/api/qbank、/api/users、/api/import、/api/update→ 需教师及以上; - 超出学校域(
school_id)或房间域(room_code)的访问一律拒绝。
- 页面前缀
- 房间域校验:实时答题与场控类接口均要求"已登录 + 房间存在 + 对该房间有访问权"。
- 统一错误返回:
{"detail": "错误说明"};常见状态码:400参数/业务错误、401未登录、403无权限、404不存在、409冲突(如重复作答)、429触发限流。 - 静态资源:
/static(带 gzip 与长缓存,URL 带?v=版本自动击穿缓存)、/static/uploads(仅下发图片扩展名)、/excelgrade(判分引擎前端,/excelgrade/testdata/被拦截)。
6.2 页面路由(14 条)
| 方法 | 路径 | 权限 | 说明 |
|---|---|---|---|
| GET | / |
公开 | 学生端答题现场首页 |
| GET | /login |
公开 | 登录页 |
| GET | /profile |
公开 | 首次登录资料确认页 |
| GET | /me |
公开 | 学生个人中心(我的记录 / 错题本) |
| GET | /exam、/exam/{sid} |
公开 | 整卷测验页(无参自动分流) |
| GET | /admin |
教师及以上 | 实时答题主持台 |
| GET | /admin/rooms |
教师及以上 | 房间 & 考试管理 |
| GET | /admin/exam |
教师及以上 | 整卷场控页(?s=场次ID) |
| GET | /admin/users |
教师及以上 | 账号管理(含学校管理页签) |
| GET | /admin/stats |
教师及以上 | 统计报告 |
| GET | /admin/schools |
教师及以上 | 307 跳转 /admin/users?tab=schools |
| GET | /admin/update |
管理员 | 版本与升级页 |
| GET | /qbank |
教师及以上 | 题库与组卷 |
| GET | /healthz |
公开 | 健康检查(非 HTML) |
6.3 接口清单(162 条,按模块分组)
(1)认证与账号(22 条)
| 方法 | 路径 | 权限 | 说明 |
|---|---|---|---|
| GET | /api/auth/me |
公开 | 当前登录用户与学校信息 |
| POST | /api/auth/login |
公开 | 登录(含 IP 限流) |
| POST | /api/auth/logout |
公开 | 服务端销毁会话 |
| POST | /api/auth/confirm |
学生 | 首次登录确认资料 |
| PUT | /api/auth/me |
学生 | 修改本人资料 |
| POST | /api/auth/password |
学生 | 自助改密(保留本机会话) |
| GET/POST | /api/users |
教师及以上 | 账号列表 / 新建账号 |
| PATCH/DELETE | /api/users/{uid} |
教师及以上 | 修改账号 / 删除账号 |
| POST | /api/users/{uid}/pwd |
教师及以上 | 重置密码 |
| POST | /api/users/{uid}/unlock |
教师及以上 | 解除锁定 |
| POST | /api/users/batch-status |
教师及以上 | 批量启用/停用 |
| POST | /api/users/batch-delete |
教师及以上 | 批量删除 |
| POST | /api/users/batch-add |
教师及以上 | 批量新增 |
(2)学校与房间(16 条)
| 方法 | 路径 | 权限 | 说明 |
|---|---|---|---|
| GET | /api/schools |
公开 | 登录页学校下拉 |
| POST | /api/school/apply |
公开 | 学校开通申请(限流) |
| GET/POST | /api/admin/schools |
超管 | 学校列表 / 新建学校 |
| PATCH/DELETE | /api/admin/schools/{sid} |
超管 | 修改 / 删除学校 |
| POST | /api/admin/schools/{sid}/admin |
超管 | 创建学校管理员 |
| GET | /api/admin/school-applies |
超管 | 申请列表 |
| POST | /api/admin/school-applies/{aid}/approve、/reject |
超管 | 批准 / 驳回申请 |
| GET | /api/room/me |
学生 | 当前浏览器所属房间 |
| POST | /api/room/enter |
学生 | 凭房间码进房 |
| GET | /api/admin/my-rooms |
教师及以上 | 本人创建的房间 |
| GET | /api/admin/rooms |
教师及以上 | 房间总览(含场次统计) |
| POST | /api/admin/room |
教师及以上 | 创建房间 |
| PATCH/DELETE | /api/admin/rooms/{code} |
教师及以上 | 修改 / 删除房间 |
(3)题库与组卷(23 条,前缀 /api/qbank,均教师及以上)
分类:GET/POST /cats、PUT/DELETE /cats/{cid};标签:GET/POST /tags、PUT/DELETE /tags/{tid};
题目:GET /qs(列表筛选分页)、GET /qs/ids(当前筛选全部 ID)、GET /qs/{qid}、POST /qs(新建/保存)、DELETE /qs/{qid}、POST /qs/reorder(子题排序)、POST /qs/batch(批量改分类/标签/可见范围/删除)、POST /upload(富文本图片上传)、POST /purge(超管:清空题库,自动备份);
试卷:GET/POST /papers、PUT/DELETE /papers/{pid}、GET /papers/{pid}、PUT /papers/{pid}/items(同步卷内题目)。
(4)实时答题主持台(23 条,前缀 /api/admin,均教师及以上 + 房间域)
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /start、/stop、/resume |
开始本轮 / 暂停 / 继续 |
| POST | /next、/prev |
下一题 / 上一题(主持台亦支持翻页笔 PageUp/PageDown) |
| POST | /reveal、/reveal_ana |
公布答案 / 公布解析 |
| POST | /settle |
结束本场并结算归档 |
| POST | /set_mode |
切换答题次序(顺序/随机/抢答) |
| POST | /set_limit |
设置每题限时 |
| POST | /shuffle_opts |
选项乱序开关 |
| POST | /set_q |
临时出某题(加入题池并立即出题) |
| POST | /pool |
设置本场题池 |
| POST | /qb_draw |
从题库/组卷抽题 |
| GET | /questions |
房间题目列表 |
| POST | /q_edit |
现场编辑题目 |
| DELETE | /del_q/{qid} |
删除房间题目 |
| POST | /clear |
清空现场考生与记录 |
| GET | /player_answers/{pid} |
查看本轮某考生逐题作答 |
| GET | /dist_batch |
批量取逐题选项分布(计数) |
| GET | /dist_names |
取某题各选项的学生名单(悬停浮层用) |
| POST | /free、GET /free_progress |
自由答题开关 / 补答进度 |
(5)学生作答(实时现场,9 条)
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /api/join |
进入本房间实时玩法(绑定选手记录) |
| GET | /api/current |
拉取当轮全量状态(轮询/推送兜底) |
| POST | /api/beat |
心跳(仅刷新在线时间) |
| POST | /api/submit |
提交答案 |
| POST | /api/buzz |
抢答 |
| GET | /api/rank |
本轮排行榜 |
| GET | /api/free/sheet、/api/free/q |
补答答题卡 / 取当前补答题 |
| POST | /api/free/submit |
提交补答 |
(6)整卷测验与场次(26 条,core/records.py)
| 方法 | 路径 | 权限 | 说明 |
|---|---|---|---|
| GET | /api/exam/room/{code} |
学生 | 考试码解析并进入所属房间 |
| POST | /api/exam/new |
教师及以上 | 新建整卷测验 |
| DELETE | /api/exam/{sid} |
教师及以上 | 删除场次 |
| GET | /api/exam/open |
学生 | 本房间进行中的测验列表 |
| GET | /api/exam/{sid}/paper |
学生 | 取本人试卷(含随机题序) |
| PUT | /api/exam/{sid}/answer |
学生 | 保存单题作答(断线续答) |
| POST | /api/exam/{sid}/submit |
学生 | 交卷并判分 |
| GET | /api/practice/papers、POST /api/practice/start |
学生 | 在线练习 |
| POST | /api/sessions/{sid}/close、/reveal |
教师及以上 | 收卷 / 公布 |
| GET | /api/me/sessions、/api/me/sessions/{sid} |
学生 | 我的记录 / 单场详情 |
| GET | /api/me/mistakes、POST /api/me/mistakes/redo_start、/mark |
学生 | 错题本、错题重做、掌握标记 |
| GET | /api/users/{uid}/sessions、/sessions/{sid} |
教师及以上 | 管理端下钻某学生成绩 |
(7)统计与报告(7 条)
GET /api/stats/sessions(场次列表)、PATCH/DELETE /api/stats/sessions/{sid}、GET /api/stats/players/{sid}(考生成绩)、GET /api/stats/overview/{sid}(总览)、GET /api/stats/questions/{sid}(逐题分析)、GET /api/stats/exam-dist/{sid}(整卷逐题选项分布)。均教师及以上,按学校域隔离。
(8)Excel/WPS 操作题(14 条,前缀 /api/excel)
| 方法 | 路径 | 权限 | 说明 |
|---|---|---|---|
| GET | /meta/{qid} |
教师及以上 | 题目三件套状态 |
| POST | /q/{qid}/files、DELETE /q/{qid}/files/{kind} |
教师及以上 | 上传 / 删除判分文件 |
| POST | /tmp/{key}/files、/q/{qid}/attach |
教师及以上 | 草稿资源上传与挂接 |
| GET | /res/{qid}/{kind} |
教师/学生 | 读取判分资源(按题库范围或参与场次鉴权) |
| GET | /res/tmp/{key}/{kind} |
教师及以上 | 读取草稿资源 |
| POST | /exam/{sid}/answer |
学生 | 上传整卷表格题作答(含分值折算) |
| GET | /exam/{sid}/{qn_id}/mine |
学生 | 查看本人判分结果 |
| POST | /live/submit |
学生 | 实时场表格题提交并累加分数 |
| GET | /stats/{sid} |
教师及以上 | 场次判分统计 |
| GET | /detail/{sub_id} |
教师及以上 | 单份作答判分明细 |
| GET | /sub/{sub_id}/file |
教师及以上 | 下载学生作答文件 |
| POST | /zip/{sid} |
教师及以上 | 批量打包下载作答 |
(9)编程题 OJ(2 条)
POST /api/admin/oj_rejudge(主持台重判当前编程题)、POST /api/users/{uid}/sessions/{sid}/oj_rejudge(教师重判某生某场编程题)。
(10)导入与导出(15 条)
题库包:GET /api/qbank/export_pack(导出,可选附带素材)、POST /api/qbank/import_pack(导入);
题库导入:POST /api/qbank/import/preview|commit|cancel、GET /api/qbank/import/batches、GET /api/qbank/import/template、GET /api/qbank/import/batches/{bid}/fails;
账号导入:POST /api/import/preview|commit|cancel、GET /api/import/batches、GET /api/import/template、GET /api/import/batches/{bid}/pwd、GET /api/import/batches/{bid}/fails。
(11)更新与运维(17 条)
| 方法 | 路径 | 权限 | 说明 |
|---|---|---|---|
| GET | /api/update/check |
教师及以上 | 检查程序与题库更新 |
| POST | /api/update/start、/apply、/rollback |
管理员 | 下载 / 应用升级 / 回退 |
| GET | /api/update/status |
教师及以上 | 升级状态与进度 |
| GET | /api/update/qbank_check、/qbank_status |
教师及以上 | 题库更新检查 / 状态 |
| POST | /api/update/qbank_start、/qbank_apply |
管理员 | 下载 / 应用题库包 |
| GET | /api/svc/ping |
公开 | 单实例存活标识(含版本) |
| GET | /api/svc/info |
教师及以上 | 运行与数据目录信息 |
| POST | /api/svc/shutdown |
教师及以上 | 优雅关闭服务 |
| POST | /api/svc/stop_local |
本机令牌 | 本机一键关闭(X-Stop-Token 校验) |
| GET | /api/qbank/selfcheck |
教师及以上 | 题库自检 |
| GET/POST | /api/qbank/dedupe |
管理员 | 重复题清理(GET 只读预览,POST 执行并自动备份) |
| GET | /api/admin/backups、POST /api/admin/backup/create、/backup/delete |
管理员 | 备份列表 / 立即备份 / 删除备份 |
6.4 关键接口示例
(1)登录
POST /api/auth/login
Content-Type: application/json
{"school": 1, "username": "20250001", "password": "********"}
{"ok": true,
"user": {"id": 1201, "username": "20250001", "display_name": "张伟",
"role": "student", "school_id": 1, "profile_confirmed_at": 1758700000},
"school": {"id": 1, "name": "默认学校", "code": "DEFAULT"}}
失败情形统一返回 400 {"detail": "登录失败,用户名/邮箱或密码错误,或账号不可用(连续失败会被临时锁定;如急需帮助请联系管理员)"}(不区分"账号不存在/密码错误/已锁定",防止账号枚举);IP 维度超限返回 429。
(2)学生拉取当轮状态
GET /api/current?room=DM3001&name=张伟
返回当轮全量状态:running、mode、qid、题目内容(题干/选项/分值)、本人作答与得分、排行榜增量、reveal/reveal_ana(是否已公布答案/解析)等。
(3)提交答案
POST /api/submit?room=DM3001
Content-Type: application/x-www-form-urlencoded
name=张伟&qid=2855&sel=A
{"ok": true, "correct": true, "msg": "回答正确 +10 分", "score": 10}
重复提交返回"已经答过";未开放答题返回 400。
(4)场控:开始本轮 / 出题 / 结算
POST /api/admin/start → {"ok": true, "total": 8, "scope": "room"}
POST /api/admin/set_q body: qid=2857 → 将该题加入题池并立即出题
POST /api/admin/settle → 本场归档为一场答题记录,写入统计报告
(5)表格操作题上传作答
POST /api/excel/exam/{sid}/answer (multipart/form-data:文件 + 题号)
→ {"ok": true, "score": 8, "score_max": 10, "subs": [...]}
(6)程序升级
GET /api/update/check → {"has_update": true, "version": "2026.09.25.1", "notes": "..."}
POST /api/update/start → 开始下载(分卷合并 + MD5 校验)
GET /api/update/status → {"state": "ready", "percent": 100}
POST /api/update/apply → 原地替换 exe(旧文件存为 .old),随后本进程优雅退出,用户双击重启
POST /api/update/rollback → 回退到上一版本(管理员显式操作)