05 · 接口与实时协议
所属:运动会积分榜系统 · 开发文档集
版本:v0.1(讨论稿) · 2026-09-09
上游:README · 相关:04-数据模型、06-大屏端设计
第一部分 · 实时同步协议
1. 通道
- Socket.IO,路径
/socket.io,与 HTTP 同端口。
- 房间:
display(所有大屏)、admin(所有管理端)、admin:<userId>(定向通知,如「你的草稿已被发布」)。
- 传输:优先 WebSocket,失败自动降级 polling(Socket.IO 内建)。
2. 版本号 + 快照/增量(保证断线不错乱)
3. 事件清单
| 事件 |
方向 |
载荷 |
hello |
C→S |
{ role, lastVersion?, displayKey? } |
snapshot |
S→C |
{ version, settings, teams, events, standings, records, latestResults } |
catchup |
S→C |
{ fromVersion, version, changes[] } |
change |
S→C |
{ version, changes[] } |
resync |
C→S |
{} |
ack |
C→S |
{ version } |
heartbeat |
S→C |
{ version, serverTime } |
display:command |
S→C |
{ action: 'goto'|'lock'|'unlock'|'reload'|'announce', payload } |
changes[] 元素形如:
action 取值:upsert / void / replace(replace 用于整体替换的列表,如积分榜)。
4. 断线与降级
| 场景 |
行为 |
| 大屏断网 |
继续显示 localStorage 最后一次快照,右上角显示「⚠ 连接中断 · 数据可能不是最新」 |
| 大屏重连 |
按 lastVersion 增量补发;补不上就整包快照 |
| 管理端断网 |
顶部横幅提示,禁止提交写操作(避免双写) |
| 服务端重启 |
客户端自动重连,版本号从数据库恢复(不重置) |
| 多管理端同时改同一项目 |
服务端事务串行化;后提交者收到冲突提示,前端刷新最新数据 |
5. 幂等与顺序
- 客户端按
version 去重:重复或乱序的变更直接丢弃。
- 服务端写操作带
requestId,重复提交返回首次结果。
第二部分 · REST API
6. 约定
- 前缀
/api,JSON,UTF-8。
- 认证:
HttpOnly Cookie 会话 + CSRF Token(管理端);大屏端免认证只读。
- 统一响应:
{ ok: true, data } / { ok: false, error: { code, message, detail? } }。
- 分页:
?page=&size=,返回 { items, total, page, size }。
7. 接口清单(初稿)
认证
| 方法 |
路径 |
说明 |
| POST |
/api/auth/login |
登录 |
| POST |
/api/auth/logout |
登出 |
| GET |
/api/auth/me |
当前用户 |
基础配置
| 方法 |
路径 |
说明 |
| GET/PUT |
/api/settings |
赛事配置 |
| GET/POST/PUT/DELETE |
/api/teams[/:id] |
单位 CRUD |
| GET/POST/PUT/DELETE |
/api/sports[/:id] |
大项 CRUD |
| GET/POST/PUT/DELETE |
/api/events[/:id] |
小项 CRUD |
| GET/POST/PUT |
/api/scoring-profiles[/:id] |
积分模板 |
| GET/POST/PUT |
/api/athletes[/:id] |
运动员 |
| POST |
/api/entries/import |
导入报名表 |
成绩(核心)
| 方法 |
路径 |
说明 |
| GET |
/api/events/:id/entries |
该项目全部报名项 + 现有成绩 |
| PUT |
/api/results/draft |
批量保存草稿(一次一个项目的整组) |
| POST |
/api/results/publish |
发布(触发积分重算与推送) |
| POST |
/api/results/unpublish |
撤销发布 |
| POST |
/api/results/:id/void |
作废单条成绩 |
| GET |
/api/results?eventId=&state= |
查询 |
积分与排名
| 方法 |
路径 |
说明 |
| GET |
/api/standings |
总积分榜(含奖牌数) |
| GET |
/api/standings/teams/:id/breakdown |
某单位积分明细(可解释每一分) |
| GET |
/api/standings/athletes |
个人积分榜 |
| GET/POST |
/api/adjustments[/:id/void] |
人工加减分 |
纪录
| 方法 |
路径 |
说明 |
| GET |
/api/records |
纪录榜 |
| POST |
/api/record-breaks |
登记破纪录 |
| POST |
/api/record-breaks/:id/approve |
确认加分 |
大屏控制与导出
| 方法 |
路径 |
说明 |
| POST |
/api/display/command |
切页 / 锁定 / 刷新 / 公告 |
| GET |
/api/export/standings.xlsx |
导出总积分榜 |
| GET |
/api/export/breakdown.xlsx |
导出单位积分明细 |
| GET |
/api/export/results.xlsx |
导出成绩册 |
| GET |
/api/audit-logs |
审计日志 |
| POST |
/api/backup |
立即备份 |
| GET |
/api/health |
健康检查(供运维/守护脚本) |
8. 错误码
| code |
含义 |
AUTH_REQUIRED / AUTH_FAILED / FORBIDDEN |
认证与权限 |
VALIDATION_FAILED |
入参不合法(附字段级 detail) |
CONFLICT |
并发修改冲突 |
STATE_INVALID |
状态不允许该操作(如未发布就想撤销发布) |
RATE_LIMITED |
触发限流 |
INTERNAL |
服务端异常 |
附录 · 实时事件样例