Files
Scoreboard/README.md
T
AskaEth 8dd599bd97 fix: 实机复测六批发现的 16 条缺陷(导入编码静默错误 / 导出观感 / 错误分级 / 大屏裁切)
先把「实机复测」能在这台 Linux 机器上验的全部自己验掉(真服务端 + 真 Chromium + 真样本),
六批全部通过,另挖出 16 条缺陷,逐条修完并复验:

导入
- 坏字节被静默替换成 U+FFFD 却报「组别不存在」→ 检测 RuneError 回 400 + 可操作中文文案
- UTF-16 无 BOM 误报「缺少列 event_code」→ 保守判据识别并正确解码
- CSV 语法错只有英文 → 中文提示,英文原文保留在 detail
- 表头缺列补「第 1 行应是表头」的指向

导出
- 名次列宽 8 → 11(放得下「3(并列)」,Excel 里不再硬裁)
- 运动员/队列宽 18 → 24(含奖牌明细的同一列)
- 聚合流水行补组别(仅单位在该小项只参加一个组别时回推;多组别宁可留空也不猜)
- docProps 作者从 excelize 默认的 xuri 改成中性名 + 真实导出时间
- Content-Disposition 补 ASCII 退化 filename(9 个下载端点,含此前没有测试的 project.zip)

错误分级与限流
- 未知大屏指令 500 → 400 VALIDATION_FAILED(传输层真失败仍走 5xx)
- 5xx 的 ERROR 日志补 role / ip(4xx 的 WARN 一直有)
- 写限流 30 → 120 次/分钟/用户(登录 5 次/分/IP 不动,性质不同)
- 赛事名含非法字符时导出给 400 + 可操作提示(原来永远 500「服务端异常」)

大屏与基础设施
- 实时赛况 2 栏成绩末位被裁(1:09.00 显示成 1:09.0)→ 成绩列按内容定宽 + nowrap;
  字号不缩,让位给可省略号截断的运动员列。真 Chromium 实测 slack −45px → +6px、0 裁切、
  scrollWidth 恒 1920(无横向滚动条);顺带修掉 1 栏长成绩同样被裁 8px 的问题
- logging 启动即预建两个日志目录(原来 interceptions/ 懒创建,现场会以为日志坏了)
- C→S 裸帧由静默忽略改为 WARN,并把「要套 {event,data} 外壳」写进日志
- 建单位/大项漏传 active 不再静默建成「停用」(新增 decodeJSONPresence 按键是否存在判意图)

文档
- README 单位 logo 措辞收窄到「大屏端」(管理端只负责上传配置)
- 导入规范补三类编码报错说明 + 现场另存结论 + 限流提示
- 部署指南补「导出前先看赛事名称」与「切换后怎么确认真的切过去了」
- devdocs 05/08/13 同步(含第三十五轮的完整记录与教训)

自检:服务端 13 包连跑两遍全绿;前端 257 例;vue-tsc + build 通过;Console 18 文件。
版本号 dev_0.1.4 → dev_0.1.5。
2026-09-11 15:35:42 +08:00

62 lines
7.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Scoreboard · 赛事积分榜系统
一套局域网内部署的赛事成绩与积分系统:**一个服务端 + 两个界面**,后台一改数据,前台大屏实时跟着变。
| 界面 | 地址 | 用途 |
| --- | --- | --- |
| 实时积分大屏 | `/display` | 只读、无人值守;成绩发布后 1 秒内更新 |
| 管理面板 | `/admin` | 录入、发布成绩,控制大屏;未登录可只读查看全部赛事数据 |
## 功能概览
- **四个榜**:总积分榜、团体奖牌榜、个人积分奖牌榜、分项成绩表
- **录入即上屏**:成绩录入 → 发布 → 大屏即时更新
- **可追溯、可撤销**:草稿不上屏;发布后纠错走「撤销发布 → 改 → 重新发布」,全程留痕
- **变更历史**:仿 Git 图谱,一眼看清成绩是怎么变成现在这样的
- **现场公开**:积分明细可下钻,争议时一键推送到大屏
- **全屏公告**:推送后先全屏显示(5–120 秒),随即常驻大屏底部公告栏,直到替换或清除
- **分批发布**:一个项目分多场跑(如跑道 8 条、30 人分 4 场)时,**每跑完一批就能先发布一批**——空成绩只是提示、**不再挡发布**,未录的行自动跳过,补录后再发一次即自动重算;名次与积分先按已发布的那部分算,大屏立刻有内容
- **实时赛况大屏页**:新增「实时赛况」页,显示当前进行中项目的实时排名(名次 / 运动员·队 / 单位 / 成绩);1 个项目单栏、2 个自动左右分栏;当前项目按「人工指定 → 排期命中(开始时间前后 30 分钟)→ 最近发布过成绩的项目」判定,**下一场开始前持续显示上一场**;可在「大屏控制 → 实时赛况」卡片配置
- **显式批次层**:组别之下可再分批(`第 1 批`、`第 2 批`…),录入页按批筛选、只在自己这一批里找人;支持手动勾选设置批次、报名表可选列 `heat`、以及按人数「一键均分」。**批次只是录入 / 展示分组,不参与算分**——名次与积分仍按「小项 + 组别」计算
- **成绩框实时提示**:聚焦成绩格打字时旁边浮出小气泡——合法显示解析结果(`1:06` → `= 66 秒`)、可疑 / 不合法直接说原因并带出那一格原文;不挡输入、不改行高,与发布前防呆同一套口径
- **窄屏 / 手机可用**:管理面板适配窄窗口与手机浏览器(局域网访问 `/admin`):侧栏收成抽屉、宽表格横向滑动、对话框不超出屏幕、触控目标放大
- **小项类型齐全**:个人 / 团体 / 对抗比赛 / **个人+团体**(同一个项目同时按个人与团体通道记分)
- **多显示器**:支持多屏各锁一页(kiosk 全屏),也能在管理端为指定显示器单独开窗或收窗;「大屏控制」页的「在线大屏」列表实时显示每个在线实例(含局域网浏览器打开的 `/display`)当前在哪一页,可逐屏 / 逐设备单独切页
- **规则可配置**:积分规则以规则包(YAML)描述,可导入导出、跨赛事复用
- **运动员名册**:启用 / 停用 / **彻底删除**三档——「停用」保留全部历史数据、随时可启用;「彻底删除」把人员档案连同他名下的报名、成绩与积分流水一起删掉且不可恢复,并自动按新排序重算受影响小项的排名与积分(大屏同步更新)
- **参赛单位名册**:启用 / 停用 / **彻底删除**三档——「停用」保留全部历史数据、随时可启用;「彻底删除」是**假删除**,只把单位从列表里移除(界面上没有恢复入口),它的报名、成绩、积分流水与名下运动员全部保留,**积分榜不会变化**;报名表里再次用到该单位编码会让它自动恢复
- **赛事独立存档**:每个赛事一个独立项目目录,整包可导出/导入(含会标、背景图、单位 logo 与上传的字体),并可在管理端页内一键切换当前赛事
- **结果导出**:Excel 总表、全部(多 sheet)、**全部(单页)**、分项成绩表、单位积分明细可分别导出;「积分榜」页三个榜单的卡片头各有自己的明细导出——单位总分榜**导出总明细**(总表 + 每个有数据的单位一张分表)、团体奖牌榜**导出奖牌明细**(逐枚奖牌列出来源)、个人积分榜**导出个人明细**(逐条得分来源,与个人榜一致且不受折算系数影响),展开单位还能**导出该单位明细**
- **日志可复盘**:服务端在数据目录 `logs\` 下按「放行 / 拦截」两类分目录落盘——`operations\` 记放行的写操作与常规运行日志,`interceptions\` 记我们主动拦下的报错与服务端异常;拦截日志带中文原因与**拦截点 `文件:行 函数名`**、操作人与 requestId,两类都按天 + 按大小轮转并自动清理旧文件(见部署指南第 10 节)
- **成绩写法容错**:时间类接受 `66`、`66.33`、`1:06`、`1:06.33`、`1分06秒`、`1小时2分3秒` 等写法(全角冒号 / 全角数字也认),秒位 ≥ 60 会被拒但报错写明原因;成绩格里的示例是带「例」字的淡色斜体灰字,不会和已填内容混淆
- **单位 logo**:**大屏端**的积分榜、奖牌榜、分项成绩表与个人榜都会显示参赛单位 logo(个人榜显示在姓名前;管理端页面只负责上传与配置,不显示 logo)
- **大屏字体可配**:标题字体与正文字体可在「系统设置 → 赛事信息 → 字体」里从四款内置字体中选,或上传自己的字体(ttf / otf / woff / woff2,单个不超过 20 MiB);只作用于大屏,加载失败自动回落默认字体,字体文件随赛事项目包一起导出/导入
## 快速开始
1. 解压部署包
2. 双击 `Scoreboard_Console.exe`(现场推荐:守护服务端、把大屏投到扩展屏、防熄屏、开机自启)
3. 浏览器打开终端提示的地址
```
大屏 http://<主机IP>:19540/display
管理面板 http://<主机IP>:19540/admin
```
> 也可以直接双击 `scoreboard.exe`(Linux 下执行 `./scoreboard`)只跑服务端,大屏投放与进程守护需自行接管。
>
> 完全离线运行,不依赖外网,不需要安装任何运行时。
## 文档
- [上线检查清单](./docs/上线检查清单.md):比赛当天照着走一遍的核对表(含交付物、目标机、首次启动、赛事项目包与规则包导入、大屏与公告、备份与回退)
- [部署指南](./docs/部署指南.md):运行环境、安装与首次启动、端口与配置、大屏接线、赛事项目包导入/切换、备份恢复、故障排查
- [使用手册](./docs/使用手册.md):角色权限、各功能页面的操作步骤、大屏端使用、常见操作问题
- [报名名单导入规范](./docs/报名名单导入规范.md):报名表该用什么格式、11 列逐列怎么填、个人/团体/「个人+团体」三种项目的填法、常见报错对照(可直接发给各单位填表人)
- [常见问题(FAQ)](./docs/常见问题.md):账号、成绩与积分、大屏、数据备份、导出导入
- 规则包格式:见 [rules/README.md](./rules/README.md)
## 许可证
MIT