题王 QKing 局域网答题系统 · 软件说明书
第 6 章

接口设计

1. 协议:HTTP/1.1 + JSON;实时答题另有 WebSocket 通道用于状态推送(断线时前端自动降级为轮询)。

6.1 接口约定

  1. 协议:HTTP/1.1 + JSON;实时答题另有 WebSocket 通道用于状态推送(断线时前端自动降级为轮询)。
  2. 鉴权:会话 Cookie(名称 qt,HttpOnly + SameSite=lax,有效期 30 天)。
  3. 管理面守卫:中间件统一拦截
    • 页面前缀 /admin、/qbank → 需教师及以上(is_staff);
    • 接口前缀 /api/admin、/api/qbank、/api/users、/api/import、/api/update → 需教师及以上;
    • 超出学校域(school_id)或房间域(room_code)的访问一律拒绝。
  4. 房间域校验:实时答题与场控类接口均要求"已登录 + 房间存在 + 对该房间有访问权"。
  5. 统一错误返回:{"detail": "错误说明"};常见状态码:400 参数/业务错误、401 未登录、403 无权限、404 不存在、409 冲突(如重复作答)、429 触发限流。
  6. 静态资源:/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 → 回退到上一版本(管理员显式操作)