feat: 分批发布 + 实时赛况页 + 显式批次层 + 成绩框实时提示 + 窄屏适配 + 版本号单一真相
## 分批发布(现场:100 米跑道只有 8 条,不能等所有人跑完才发) - 空成绩从"错误"降级为"提示",不再阻塞发布;真会算错(写法无法识别、秒位 ≥ 60、 手动名次缺名次)仍挡住。发布确认框说明"只发已填的 M 人,其余保持未发布"。 - 服务端核实:publishResults/computeEventScore 本就不会因缺成绩报错 (collectCandidates 直接跳过没有 results 的报名项),根因在前端防呆。 ## 实时赛况(新大屏页 + 定向接口) - 新增 `GET /api/display/live`(guest 可读):返回「当前项目」判定 + 该项目**全量**已发布成绩 (不受快照 latestResults 的 20 行截断)。回退链:manual 指定 > 排期命中 > 最近发布。 设置键 display.live_events / display.live_source。 - 大屏新页 `live`「实时赛况」:1 个项目单栏、2 个自动左右分栏;失败保留上一次画面 (下一场开始前持续显示上一场);30s 轮询(判定依赖当前时间)+ 快照变更触发。 - 管理端「大屏控制」新增「实时赛况」卡;该卡走 PUT /api/settings(admin-only), 故对非管理员整组置灰 + 提示条(不新增角色)。 ## 显式批次层(组别之下) - 迁移 0019 `entries.heat`;批次仅是录入/展示分组,**不参与算分**(有"分批与不分批结果 完全一致"的断言守住)。批量设置接口 + 导入 CSV 可选列 heat + 录入页批次下拉 + 一键均分(按 N 人切片,已有批次号接着往后排)。 ## 成绩输入框实时悬浮提示 - 聚焦格旁的浮动气泡:pointer-events:none、不占布局不改行高、贴底自动上翻; 合法显示解析结果(1:06 → = 66 秒)、可疑/不合法显示原因并带那一格原文; 与发布防呆共用同一套纯函数(entryGuards.ts),口径不会分叉。 ## 窄屏 / 手机端布局 - 真浏览器(Playwright + chromium)在 1440/1024/768/390 四宽度逐页审计 + 溢出探针, 四轮迭代修复;桌面端 1440 前后像素差异 < 0.25%(无回归);修掉如「修改密码」输入框 塌成 22px 这类真问题。 ## 版本号单一真相 - 新增仓库根 `VERSION`:构建时注入二进制(-X main.version)并同步 console/package.json 的版本(产物名跟随)。源码里不再有人工维护的版本号(兜底值改为 `dev`,故意不写数字)。 测试:服务端 13 包全绿;前端 vue-tsc 通过、249 例全过;Console 18 文件。 docs/ 与 devdocs/ 同步(FAQ 到 Q80、新增 devdocs/16 自定义大屏模板设计文档)。
This commit is contained in:
1 parent
e5e0944d26
commit
08a5740fb2
64 files changed
+4968
-270
No files matched your search
+45
-14
@@ -88,7 +88,7 @@
|
||||
- 距离 / 计数 / 得分类:按工具栏提示的单位填数字,如米 `12.34`、次 `12`、分 `96.5`;
|
||||
- 秒位 ≥ 60 仍然拒绝(`1:70` 不是 70 秒),但报错会写明原因(见 4.4)。
|
||||
|
||||
**示例文本不是已填内容**:空格子里显示的 `例 1:06.33`(距离 `例 12.34`、计数 `例 12`、得分 `例 96.5`)是**更淡的斜体灰字**,只是告诉你大概怎么写,**不代表这一格已经有成绩**。灰字不会被提交;点发布时如果那一格还是灰字,就按「成绩为空」拦下。过去示例文本长得和真实输入一样,容易看成「我已经填了」。
|
||||
**示例文本不是已填内容**:空格子里显示的 `例 1:06.33`(距离 `例 12.34`、计数 `例 12`、得分 `例 96.5`)是**更淡的斜体灰字**,只是告诉你大概怎么写,**不代表这一格已经有成绩**。灰字不会被提交;点发布时如果那一格还是灰字,就按「还没录」自动跳过(本次不发布这一行),不会连累其他已填成绩的发布。过去示例文本长得和真实输入一样,容易看成「我已经填了」。
|
||||
|
||||
右侧「实时积分预览」显示:若现在发布,各单位积分的变化、最大分差、受影响单位数。
|
||||
|
||||
@@ -110,26 +110,40 @@
|
||||
|
||||
### 4.4 防呆校验
|
||||
|
||||
页面下方「防呆校验」会实时列出问题:
|
||||
页面下方「防呆校验」会实时列出问题,分两档:
|
||||
|
||||
- **错误(阻止发布)**:成绩格有三种原因,文案都会**把那一格的实际内容原样打出来**,并对症给出改法,不会只说一句「缺少成绩」让你去改本来就对的格式:
|
||||
- 空格子:`第 3 行 张三:成绩为空(当前「(空)」),请填写成绩`;
|
||||
- **错误(阻止发布)**:只有**会让名次或积分算错**的才挡发布,文案都会**把那一格的实际内容原样打出来**并对症给改法:
|
||||
- 秒位 ≥ 60:`第 3 行 张三:秒位不能 ≥ 60(当前「1:70」),请写成 1:06 或 66 这类`;
|
||||
- 写法无法识别:`第 3 行 张三:成绩写法无法识别(当前「约1分06秒」),可用 66、66.33、1:06、1:06.33、1分06秒`——非时间单位会换成对应的数字提示(不会拿时间格式去教距离项目);
|
||||
- 另外还有:手动名次项目缺少名次。
|
||||
- **提醒(不阻止发布)**:成绩 ≤ 0、名次重复(请确认是否并列)、成绩与赛会纪录差距过大。
|
||||
- 手动名次项目缺少名次。
|
||||
- **提醒(不阻止发布)**:
|
||||
- **成绩还没录**(空格子):`第 3 行 张三:还没录成绩(当前「(空)」),本次发布不计入这一行`。这是中性状态,**不挡发布**——跑完一批就能先发一批,剩下没跑的补录后再发(见 4.6);
|
||||
- 成绩 ≤ 0、名次重复(请确认是否并列)、成绩与赛会纪录差距过大。
|
||||
|
||||
有错误时点「发布」会被拦下并提示第一处问题。
|
||||
有**错误**时点「发布」会被拦下并提示第一处问题;只有提醒(含还没录的行)时发布会照常进行,未录的行自动跳过。
|
||||
|
||||
### 4.5 存草稿与发布
|
||||
|
||||
1. **存草稿**:保存当前组别的成绩,草稿**不会上屏**,也不计入积分榜;有未保存修改时页面会显示「有未保存修改」徽标。
|
||||
- **未保存的成绩不会被静默丢掉**:有未保存修改时,点左侧菜单切到别的页面(以及浏览器前进 / 后退)会先弹出确认框,确认丢弃才离开;关闭或刷新浏览器时浏览器也会原生提示;切换项目本来就会先确认。选「取消」留在本页,改动都还在。
|
||||
2. **发布**:点击后弹出确认框,显示本次影响的单位数与最大分差;确认后成绩立即上屏并重算积分榜。
|
||||
2. **发布**:点击后弹出确认框,说明本次将发布多少人、还有多少人没成绩,以及影响的单位数与最大分差;确认后这批成绩立即上屏并重算积分榜。
|
||||
- 发布前系统会自动把当前内容整组保存为草稿再发布,无需手动先存;
|
||||
- 示例数据模式下「发布」按钮不可用,避免把未落库的改动当成发布成功。
|
||||
|
||||
### 4.6 撤销发布
|
||||
### 4.6 分批发布(跑一批发一批)
|
||||
|
||||
跑道只有 8 条、一个项目可能要分好几场跑时,**不需要等所有人都跑完**:每跑完一批就发一批,没跑到的先空着。
|
||||
|
||||
1. 这一批跑完,把已出的成绩填上(其他还没跑的行保持空白即可);
|
||||
2. 点「发布」(该组已有发布过的成绩、且还有没发的已填行时,按钮显示为「**发布本批**」);
|
||||
3. 确认框会写明:`本组还有 N 人没有成绩,本次将发布已填的 M 人;其余保持未发布,补录后再发布即可。本次影响 … 个单位,最大分差变化 … 分。发布后立即上屏并重算积分榜。`——**看完再确认**,系统只发布已填的那 M 人,不会把没成绩的人当成 0 分发出去;
|
||||
4. 确认后这批成绩立即上屏,**名次与积分先按已发布的这部分算**,大屏立刻有内容;
|
||||
5. 下一批跑完,回到本页补录成绩,再点一次「发布本批」——系统会把两批放在一起重算名次与积分,先发的部分自动跟着更新;
|
||||
6. 全部发完后按钮不再显示「本批」(并变为不可用),此时该组视为已全部发布,要改就得走「撤销发布 → 修改 → 重新发布」(见 4.7)。
|
||||
|
||||
> 只有「会被算错」的写法才会挡住发布(见 4.4);空格子只是「还没录」,属于提醒,不影响发布。审核页(第 5 节)也是同一套口径:只有写错或缺名次才挡「发布整组」,空成绩只是本次跳过。
|
||||
|
||||
### 4.7 撤销发布
|
||||
|
||||
已发布的组别会出现「撤销发布」按钮:
|
||||
|
||||
@@ -148,10 +162,10 @@
|
||||
3. 用「整组对比 / 逐条对比」切换,查看发布后各单位积分的变化;
|
||||
4. 「发布影响」列出受影响单位与分值变化;
|
||||
5. 操作:
|
||||
- **发布整组**:确认后整组发布并重算积分榜;
|
||||
- **发布整组**:确认框会写明本组还有多少条没有成绩、本次将发布已填的多少条;确认后**只发布已填的那部分**并重算积分榜,没录的保持未发布,补录后再发一次即可(分批发布,见 4.6);
|
||||
- **退回**:当前版本服务端没有「退回」接口,此操作**仅在管理端本地标记**,不会改动成绩数据;刷新页面后标记可能消失。如需真正退回,请通知录入员到「成绩录入」修改后重新保存。
|
||||
|
||||
> 草稿态永远不会上屏;发布以「小项 + 组别」为一组整体生效。
|
||||
> 草稿态永远不会上屏;发布以「小项 + 组别」为一组整体生效,但**没录成绩的条目会被跳过**——它既不挡发布,也不会被当成 0 分(防呆口径与录入页一致,见 4.4)。
|
||||
|
||||
---
|
||||
|
||||
@@ -240,7 +254,7 @@
|
||||
|
||||
| 区块 | 操作 |
|
||||
| --- | --- |
|
||||
| 切页 | 选择「总积分榜 / 团体奖牌榜 / 个人积分奖牌榜 / 分项成绩 / 公告」,点「立即跳转」(**所有大屏一起切**);只想切某一块屏或某台设备,用右侧「在线大屏」卡片里那一行的下拉与「切到此页」 |
|
||||
| 切页 | 选择「总积分榜 / 团体奖牌榜 / 个人积分奖牌榜 / 分项成绩 / 实时赛况 / 公告」,点「立即跳转」(**所有大屏一起切**);只想切某一块屏或某台设备,用右侧「在线大屏」卡片里那一行的下拉与「切到此页」 |
|
||||
| 锁定与刷新 | **锁定**:停止自动轮播并停在当前页;**解锁**:恢复轮播;**强制刷新**:让所有大屏重新拉取快照,用于排障 |
|
||||
| 公告 | 输入公告文字,设置「滚动时长」(5–120 秒,实际是全屏展示的秒数),点「推送公告」;点「清除公告」撤下当前公告 |
|
||||
|
||||
@@ -248,6 +262,14 @@
|
||||
|
||||
**公告**:点「推送公告」后所有大屏先**全屏**展示这条公告,到时间后自动退回原来的页面(没锁定就继续轮播),公告正文留在底栏的「公告」槽位继续显示,直到被新公告替换或点「清除公告」。公告卡片顶部徽标显示「当前公告:有 / 无」,徽标下面那一行就是当前公告正文(没有公告时显示「暂无公告(大屏底栏显示占位)」)。公告会随赛事设置保存:新开的大屏窗口、断线重连之后,会先把当前公告再全屏播一遍(默认 15 秒)后留在底栏;点「清除公告」后底栏回到「暂无公告」占位。
|
||||
|
||||
**实时赛况**:「实时赛况」卡片决定大屏「实时赛况」页显示哪几个项目(**最多 2 个**)。
|
||||
|
||||
- **自动判定 / 人工指定**:卡片右上角徽标显示当前模式。选「自动判定」时按三条依据依次判定——**人工指定 → 排期命中(项目开始时间前后 30 分钟内)→ 最近发布过成绩的项目**;选「人工指定」时只显示下面指定的项目,不做任何回退;
|
||||
- **项目 1 / 项目 2** 两个下拉:从当前赛事的小项里选(选项里有「未指定」),已选的行可以「清除」;同一个项目不会重复占两个槽位;
|
||||
- **当前生效**:显示此刻大屏实际会显示的项目与入选原因,格式如 `男子 100 米(排期命中)`;没有可显示的项目时显示「当前没有可显示的项目」。旁边的「刷新」只重新读取,不改配置;
|
||||
- **保存**:改完模式或项目后点「保存」,提示「实时赛况设置已保存」后大屏按新配置显示;卡片底部注明「当前项目最多 2 个」;
|
||||
- 该卡片的「保存」需要**管理员**身份(实时赛况属于赛事设置,只有管理员能改);示例数据模式下不能保存。
|
||||
|
||||
**在线大屏**:右侧「在线大屏」卡片列出的是**真实**的在线实例,直接读服务端 `GET /api/display/instances`,打开页面时每 5 秒自动刷新一次(浏览器切到后台时暂停,切回来立刻补一次)。每个实例一行,显示实例 ID、在线 / 离线徽标、「局域网浏览器」或「屏 N」标记、当前所在页、来源地址与最后心跳;服务端判定某个实例落后时还会多一个「落后」徽标(大屏可能在卡或网络差)。**本机用 Console 打开的大屏窗口、以及局域网设备打开 `/display` 连上的浏览器,都会出现在这里**——局域网浏览器没有屏号,那一栏显示「局域网浏览器」。离线实例会在服务端保留一段时间,方便排查它是什么时候掉的。
|
||||
|
||||
**逐屏 / 逐设备切页**:在线大屏列表里每一行都在「当前页」旁带一个页面下拉和「切到此页」按钮,只把**这一块屏 / 这一台设备**切过去,其他屏不受影响;上方「切页」卡片里的「立即跳转」则是**所有大屏一起切**。离线实例的下拉与按钮是灰的,发不到它;点名的大屏一台都没收到指令时会明确提示「目标大屏已离线,请刷新在线列表」,不会谎报成功。列表读取失败时页面会提示「读取在线大屏失败」,并保留上一次的结果,不会把列表清空。
|
||||
@@ -633,7 +655,7 @@
|
||||
|
||||
### 17.1 页面
|
||||
|
||||
大屏支持五个页面:
|
||||
大屏支持六个页面:
|
||||
|
||||
| 页面 | 内容 |
|
||||
| --- | --- |
|
||||
@@ -641,8 +663,17 @@
|
||||
| 团体奖牌榜 | 名次、单位(带单位 logo)、金 / 银 / 铜、合计 |
|
||||
| 个人积分奖牌榜 | 名次、姓名(姓名前显示所属单位 logo)、单位、总分、奖牌 |
|
||||
| 分项成绩 | 最新已完成项目的成绩,单位列名字前显示单位 logo |
|
||||
| 实时赛况 | 当前正在进行项目的实时排名(见下方说明) |
|
||||
| 公告 | 管理端推送的公告:推送后先全屏展示,之后常驻底栏的「公告」槽位 |
|
||||
|
||||
**实时赛况**:专门给「现在正在比的项目」用,每一行显示**名次、运动员 / 队、单位(带单位 logo)、成绩**,按名次升序。
|
||||
|
||||
- **显示哪个项目**由管理端判定(见第 9 节的「实时赛况」卡片):优先按人工指定的项目,其次按项目排期(开始时间前后 30 分钟内),都没有时显示**最近发布过成绩的项目**——所以**在下一场开始之前,这一页会一直保持显示上一场的成绩**;
|
||||
- **1 个项目单栏铺开,2 个项目自动左右分栏**(最多 2 栏,对应「两个项目时间撞在一起」的现场);
|
||||
- 只显示**已发布**的成绩:配合分批发布,发一批这一页就更新一批(见 4.6);
|
||||
- 同一个小项分了多个组别时,栏里显示**最近发布的那一组**,标题旁用「另有 N 组」标注;该项目还没有已发布成绩时栏内显示「该项目暂无已发布的成绩」;
|
||||
- 每栏最多列前 10 个名次;一个项目都没有时整页显示「暂无进行中的项目」(刚切到本页、结果还没回来时显示「正在获取当前项目…」)。
|
||||
|
||||
> 单位 logo 取自「基础数据 → 参赛单位」里上传的图片(见 10.1),按行内文字大小显示,不会撑开行高;没传 logo 的单位不占位,图片临时加载不出来时保留占位、刷新后恢复,队名不会跳动。
|
||||
|
||||
> 大屏的标题字体与正文字体取自「系统设置 → 赛事信息 → 字体」(见 14.3):可选四款内置字体,也可以上传自己的字体;上传字体加载失败时自动回落到默认字体,画面不会出现方块或空白。
|
||||
@@ -653,7 +684,7 @@
|
||||
|
||||
- Console 启动的多屏大屏窗口默认**每屏锁定一页**,不轮播;
|
||||
- 在管理端「大屏控制」点「解锁」后开始整页轮播,**每 20 秒切换一页**;
|
||||
- 公告页是手动触发的页面,不参与自动轮播;个人积分榜可在「赛事信息」里关闭上屏;
|
||||
- 公告页是手动触发的页面,不参与自动轮播;个人积分榜可在「赛事信息」里关闭上屏;「实时赛况」页参与轮播(见 17.1);
|
||||
- 底部滚条固定有「公告」槽位:管理端推送过公告就一直显示最近那条,没有公告时显示「暂无公告」(见第 9 节);
|
||||
- 点「锁定」可停在当前页。
|
||||
|
||||
|
||||
Reference in new issue
Block a user