Files
Scoreboard/docs/升级说明.md
T
AskaEth ed2c0b3f3c feat: 主人拍板的 4 条全部落地(单条作废/重录、破纪录驳回、历史纪录、仪表盘卡片)+ 迁移 0021(dev_0.3.0)
## ① 成绩「作废本条 / 重新录入」——手滑填错了怎么办
- 新增 `POST /api/results/{id}/reopen`:把已发布的那条退回草稿(state=draft、
  status=ok、rank=NULL、note=原因)并重算推榜;口径与既有 `void` 完全一致
  (回滚类动作,不受 `standings.live_on_publish` 约束)。
- 成绩录入页新增「操作」列:已发布行可「作废本条」,已作废行可「重新录入」,
  两者都必填原因、确认后立即重算+推大屏。**验收用例**:作废→重录→改→重发,
  名次/流水/榜单与「一开始就填对」逐字节一致。

## ② 破纪录的驳回 / 作废
- 迁移 `0021_record_breaks_note.sql`:`record_breaks` 加一列可空 `note`。
- 新增 `GET /api/record-breaks?state=`(recorder 起可读,guest 403)与
  `POST /api/record-breaks/{id}/reject`(必填原因):已批准的登记被作废时
  **撤回该笔加分、重算推榜、并把该级别当前纪录恢复为上一条**;`approve`
  放开为可对 rejected 再次批准。
- 破纪录页新增「已批准的破纪录」卡片(作废入口);原先只存在浏览器内存里的
  「拒绝」改为持久化(先登记再驳回,刷新不再复现)。

## ③ 历史纪录的写入路径(`records.source` 以前恒为「本届」)
- 新增 `POST /api/records`(source 只收 history)与 `DELETE /api/records/{id}`
  (删当前纪录时恢复上一条)。纪录库卡片新增「新增历史纪录」与「删除」。
- 至此《使用手册》6.2 承诺的「来源(本届/历史)」这一列才真正有意义。

## ④ 仪表盘补齐承诺的卡片
今天的小项(按 scheduledAt 的本地时区当天 + 进度)、草稿待发布、待确认破纪录、
大屏在线数;数据源读不到显示 `—` 而不是 0。文档里「管理端在线数」服务端没有
接口,按实际改写成本机管理端连接状态。

## 旧版数据包兼容(主人特别交代,三处验证)
迁移只加**可空**列、不重建表、不动数据行;旧赛事包导入后由 `main.go` 的
`store.MigrateEvent` 在启动时补跑迁移。证据:`migration_0021_test.go`
(旧库升级 + 幂等 + 老行取 NULL)、`migration_legacy_test.go` 扩到 0021、
`legacy_pack_upgrade_test.go`(真实旧 event.db 走 main 同一条路径后装配 API,
驳回老登记 → 加分撤回、纪录回退、旧数据逐表一行不差),另有真二进制冒烟。
未迁移的库上不存在任何新列读取。

## 文档
升级说明新增 dev_0.3.0(含「旧包仍可导入、自动补跑迁移」);使用手册新增
§4.10 与 §6.1/§6.2 明细;常见问题新增 Q98/Q99/Q100;devdocs 04/05/07/13/02
同步(含新接口表与错误分级)。

自检:服务端 13 包 ×2 全绿(httpapi 新增 reopen/reject/records/旧包 四个用例文件)、
前端 vue-tsc + 604 例 ×2 + build、Console 19 文件 + 54 例。
2026-09-12 01:27:09 +08:00

188 lines
16 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.
# 升级说明
> **按版本倒序,最新在最上面。** 每次升级前先看「要升到的那一版」这一节,照着做完再开赛。
> 数据、配置、规则包都在用户数据目录(`%LOCALAPPDATA%\ScoreboardConsole\`),**覆盖安装不会丢**,见《部署指南》3.4 / 3.5。
> 常规升级流程(停服务 → 覆盖安装 → 启动 → 核对)见《部署指南》3.1 / 3.4。
---
## dev_0.3.0(当前版本)
### 一句话
**旧版赛事项目包仍可导入**:本版只有一条迁移(**0021**),只给破纪录登记表加一列可空的「理由」。升级后榜单数字应当与升级前一致;新增四个现场入口(作废 / 重新录入成绩、作废已批准的破纪录、录入历史纪录、仪表盘四张新卡片)。
### ① 迁移只有一条(0021),而且只是「加一列」
- 迁移 **`0021_record_breaks_note.sql`**:给 `record_breaks` 表加一列 **`note`**(TEXT,**可空**,默认 NULL)——记「这条破纪录登记为什么被驳回 / 作废」。
- 它**只加列**:不重建表、不改任何既有数据行;老登记的 `note` 保持 `NULL`(「本来就没有理由」是事实,不会被写成一条假理由)。
- ✅ **旧版赛事项目包仍可导入**。导入一个不含 `note` 列的旧包后,它**成为当前赛事时(切换过去、服务端启动打开赛事库时)会自动补跑迁移**,**不需要任何手工处理**;旧的破纪录登记、纪录库、成绩与积分一行不丢。
- 备份同理:升级前的备份文件(旧 `event.db`)照常能恢复,恢复后再打开时也会自动补迁移。
### ② 四个新入口
| 入口 | 位置 | 做什么 |
| --- | --- | --- |
| **作废本条 / 重新录入** | 成绩录入页每行的「操作」列 | 手滑填错了不必整组撤销发布:已发布的行仍然是锁的,但可以点「作废本条」(**必填原因**)让这一条退出名次与积分;已作废的行显示红徽标「已作废」,点「重新录入」(必填原因)退回草稿,改完再发布本组。两者都**立即重算并推大屏**,不受「分批发布时实时更新榜单」这个延迟结算开关影响 |
| **已批准的破纪录 / 作废** | 破纪录页新增的「已批准的破纪录」卡片 | 批错的破纪录可以撤回:点「作废」(**必填原因**)→ 撤回该笔加分、重算推榜,并把该级别的当前纪录**恢复为上一条** |
| **新增历史纪录 / 删除** | 破纪录页「纪录库」卡片 | 赛前手工登记历史纪录(小项 / 级别 / 成绩值或文本 / 保持人 / 保持单位 / 创造日期);每行可「删除」,删的是当前纪录时会恢复上一条。**「来源」列现在真的会显示「历史」或「本届」**(以前没有历史录入入口,实际只会是「本届」) |
| **仪表盘四张新卡片** | 仪表盘 | 今天的小项(按排期 + 进度)、草稿待发布、待确认破纪录、大屏在线数;旧卡片保留 |
### ③ 「拒绝」从内存改持久带来的行为变化
- 以前点「拒绝」只在**本机浏览器里**把这条疑似破纪录藏起来,刷新就回来。现在改成**先登记再驳回**:服务端会登记一条破纪录记录并立即驳回(理由写「现场判定不是破纪录」),**刷新后不再出现**;谁在什么时候否掉了哪一条,也能在审计日志里查到。
- ⚠️ **升级前在本机「拒绝」过的疑似破纪录,升级后刷新会重新出现一次**——因为那次拒绝从来没有写到服务端。重新点一次「拒绝」即可(这次会落到服务端)。
- 只有真的写不进去时(示例数据模式 / 未连接服务端)才退回本机隐藏,提示会如实说明「刷新页面后该条会重新出现」。
### ④ 升级后 5 分钟核对
1. 打开一次「成绩录入」页,确认表格最后一列是「操作」;
2. 打开「破纪录」页,确认多出「已批准的破纪录」卡片,且「纪录库」卡片有「新增历史纪录」按钮与每行的「删除」;
3. 打开仪表盘,确认多出今天的小项 / 草稿待发布 / 待确认破纪录 / 大屏在线数四张卡片;
4. 旧赛事包核对:导入一个**升级前导出的赛事项目包**并切换为当前赛事,确认能正常打开、破纪录与纪录库数据都在(迁移 0021 会自动补跑);
5. 用《上线检查清单》过一遍。
### ⑤ 详细说明在哪
| 想了解 | 看 |
| --- | --- |
| 手滑填错一条成绩怎么改 | 《使用手册》4.10;《常见问题》Q98 |
| 破纪录批错了 / 怎么拒绝 | 《使用手册》6.1;《常见问题》Q99 |
| 历史纪录怎么录 | 《使用手册》6.2;《常见问题》Q100 |
| 仪表盘四张卡片 | 《使用手册》第 3 节;开发侧 `devdocs/07` §7 |
---
## dev_0.2.0
### 一句话
**没有需要迁移的数据**:这一版是 100 多项缺陷与体验修复的合集(含一次改名、几处口径收紧)。升级后榜单数字应当与升级前一致。
### ① 三件升级前必须知道的事
**1)「团体奖牌榜」改名为「单位奖牌榜」**,导出件也跟着改了名:
- 界面上:大屏控制页的切页下拉、大屏奖牌榜页标题、管理端「积分榜」页的页签,都叫 **单位奖牌榜**;
- 导出件:下载文件名由 `团体奖牌明细.xlsx` 改为 **`单位奖牌明细.xlsx`**,Excel 里的工作表名同步改为 **`单位奖牌榜`** / **`单位奖牌明细`**。
→ **如果你把旧文件名写进了对账脚本、打印模板或交接文档,记得改**。
- **旧名仍然可用**:老链接(`?page=团体奖牌榜`)与老配置(`display.pages` 里写 `medals` 或旧名)照常生效,不用改。
**2)审计日志的动作前缀统一了**(`entries.import` → `entry.import`,`entries.import.resolve` → `entry.import.resolve`):
- **升级前落库的历史记录不会跟着改**——它们仍写着旧前缀。所以**查历史时请用子串 `import` 筛**(新旧都能筛到);用 `entry.` 只能筛到升级之后的记录。审计是只追加的,我们不会改写历史。
**3)密码长度改成按「字符」数**(原来是按字节):
- 下限仍是 8 **位**,但现在按字符算:**7 个汉字(原来 21 字节能过)现在会被拒**;`3 个汉字 + 5 个字母`(8 字符)正常通过。
- 上限仍是 72 字节(bcrypt 的边界),文案里会分别写清「位」与「字节」。
### ② 现场会看到的变化
- **导出件里的「未结算」**:开了延迟结算时,「已发布但那一组还没结算」的行,导出的「分项成绩表 / 全部 / 全部(单页)」现在写 **名次 `—` / 积分 `—` / 状态 `未结算`**(成绩照常打印)。原来这三列是「空名次 + 0 分 + 有效」,读起来像「算出来就是 0 分」。
- **基础数据包导入遇到「已彻底删除的单位」**:那一行**整行跳过**并在导入结果里说明原因(不再更新它的字段、也不会把它翻出来);要让单位回来,先到「基础数据 → 参赛单位」勾选「显示已彻底删除的单位」再点「恢复」。
- **报名名单导入换了单位会明确提示**:「第 N 行:某某 换了单位,原单位 A 在本组别的报名已移出,已改在单位 B 加入」——数据行为没变(一直是这样),现在会说出来了。
- **「从已有名单勾选报名」有冲突时不再报「已加入」**:会明确提示「有 N 行没有加入,需要逐条确认」,并在页内列出是哪几行。
- **导出核对更省事**:单位积分明细的「成绩」列与分项成绩表、个人明细**逐字一致**(原来少个单位,如 `11.58` vs `11.58 秒`);空单位的「单位积分明细」也会打印末行「合计」。
- **收不到回执的危险操作不再误导**:一键恢复请求超时/断连时,提示由「恢复未执行」改为「**没收到回执,恢复可能已经生效**」,并单独放宽了超时时间;两个管理员同时点恢复时,第二个会拿到「正在恢复,请稍后」。
### ③ 部署相关的两处
- **赛事包上传上限是 512MB**(名单 CSV 与基础数据包那一档仍是 32MB,赛事包刻意放宽——它要装字体、背景图、各单位 logo;字体单个就允许 20MB)。超限会提示「解析上传失败」。
- **反向代理(nginx 等)**:若以前遇到「登录一定 403」,本版起错误提示会指明原因与修法;正解是让代理透传原 Host(`proxy_set_header Host $host;`),或配置可信代理并把原 Host 透传在 `X-Forwarded-Host` 上。**不要**为了绕过它把校验放宽——那等于开登录 CSRF 的口子。
- 顺带:**丢了 CSRF Cookie 不再等于「能看不能写」**——管理面板会自动补发,症状消失后无需再刷新页面。
### ④ 升级后 5 分钟核对
1. 打开服务管理窗口的运行日志:**这一次升级没有那条「通道名次自愈」记录是正常的**(本版没有新迁移,不需要重算);若看到它,说明你从上上版直接跳过来,等它跑完即可;
2. 刷新积分大屏与管理面板:**单位总分榜、单位奖牌榜、个人积分榜的数字与升级前一致**;
3. 随便挑一个小项导出一次「分项成绩表」,确认表头与列都对;
4. 用《上线检查清单》过一遍。
### ⑤ 详细说明在哪
| 想了解 | 看 |
| --- | --- |
| 榜名/导出文件名的变化 | 本文件 ①;《使用手册》8.2、11.1 |
| 导出里三种「还没出结果」的行 | 《使用手册》11.1;《常见问题》Q90 |
| 基础数据包遇到已删除的单位 | 《使用手册》11.4;《常见问题》Q88 |
| 恢复与安全副本保留份数 | 《部署指南》8.3;《常见问题》Q40 |
| 反代/登录 403 | 《部署指南》7.x 与应用内提示 |
---
## dev_0.1.8
### 一句话
修掉了一个**会多算单位总分**的计分缺陷;奖牌改成可以按小项、按通道开关;报名名单认人改成**以证件号为准**。
### ① 升级后必须补的一件事(本版唯一需要人工补录的地方)
**「团体引体向上」这类「个人+团体」项目的团体名次,要到成绩录入页补录一遍。**
原因是旧版**没有录团体名次的地方**:这类项目的团体分是拿**个人名次顶替**着算出来的(所以会算多)。本版改成从「团体名次」区块读,**没录就是 0 分**。
- 补录位置:**成绩录入**页 → 选中该小项与组别 → 表格下方 **「团体名次」** 卡片 → 按单位填名次 → **保存团体名次**(留空 = 清空该单位;名次允许并列;个人名次不受影响)。
- 如果某单位不参加该项,留空即可。
- **不想手填的替代方案**:把该小项的团体通道从「手动名次」改成「按队内平均」(**基础数据 → 计分通道**),系统会按每队成员成绩自动算团体名次。
**两种口径二选一,由赛会规则决定**——「团体引体向上」这条现在还挂着旧模板(手动名次),要按领导定的口径确认一次。
### ② 分数会变,这是对的(不是坏了)
- **单位总分**:旧版在「个人+团体」项目上会把**个人**名次当成**团体**名次、按团体表再发一次分。实测某队在成绩没改的情况下,第一次发布 45 分、再点一次发布变 85 分。
本版已修正:**同一份数据无论发布几次,结果完全一致**。
- 所以升级后如果你之前录过并发布过这类项目,**单位总分会出现变化**(变小是正常的,那是修正后的值)。按 ① 把团体名次补录完,再核对一次即可。
- **个人积分不受影响**(个人通道的算法没变);奖牌数可能变化(见 ③)。
### ③ 现场会看到的新东西
**奖牌可以开关了**(三层,从粗到细):
1. 小项级:**基础数据 → 大项 / 小项 → 编辑小项**,「选项」里有 **「该项启用奖牌结算」**(**默认勾上**)。取消 = 这个小项只出积分、一块牌都不发;
2. 通道级:**基础数据 → 计分通道**,表里多了 **「奖牌通道」**列,两个开关——**「发奖牌」**(这条通道的名次发不发牌)与 **「个人奖牌并入单位金牌榜」**(个人项目拿的牌算不算进单位金牌总数);
3. 名次仍然只发给**前三名**(并列口径不变)。
> ⚠️ 迁移默认把三个开关都设成**开**,也就是和升级前一致,不会让既有小项突然掉牌。要改哪个小项,按赛事规则逐个去关。
**成绩录入页多了「团体名次」卡片**——只在配了「团体名次 = 手动名次」通道的小项上出现;纯团体项目(篮球等)和「按队内平均」的项目不会出现,那是正常的。
**报名名单认人改成以证件号为准**:匹配顺序 **证件号 → 号码布 → 姓名 + 单位**。同一份表里同一证件号出现多次 = 同一个人报多个组别(会给提示,不再报错);只有「同证件号 + 同一个小项同一个组别」才会进冲突面板问你保留哪一条。
**下面这些动作现在会立刻重算并刷新大屏,即使管理员开了「延迟结算」**:
撤销发布 / 作废单条成绩 / 批量退赛·恢复·移出报名 / **报名名单导入改了状态**(例如把某人改成退赛)。
「延迟结算」只影响**发布成绩**这一件事(不因一批成绩跳动榜单),不会让退赛、作废这类「谁还算数」的改动被拖着。
### ④ 其它修复
- 管理员**撤销会话 / 停用账号 / 改密码**后,那台机器上还开着的实时连接会立刻断开,不再继续收数据;
- 访客(guest)身份收不到系统配置类的实时推送;
- 导出一份不存在的小项 / 单位、手填名次填 0 或负数、性别或年龄填了非法值 → 现在是**明确的错误提示**,不再是「服务端异常」;
- **示例数据模式**(后端连不上时的演示模式)下,批量停用 / 批量或单条彻底删除会被拦下并提示,不会假成功;
- **服务管理窗口**:显示器短暂只剩一块(拔线 / 电视待机)之后,再把扩展屏插回来会**自动恢复全屏**,不用重启程序;
- **自定义大屏模板**:嵌套过深或体积过大的模板会给出明确提示,不会让大屏白屏。
### ⑤ 升级后 5 分钟核对
1. 打开服务管理窗口的**运行日志**,看有没有那两行自愈记录(`检测到通道名次为空但已有已发布成绩…` / `一次性全量重算完成…`),**这是正常的**;
2. 刷新积分大屏 / 管理面板:**奖牌榜不是全 0**;
3. **单位总分与升级前一致**(除了 ② 说的「个人+团体」项目);
4. 打开一次成绩录入页,确认该录团体名次的小项上有**「团体名次」**卡片;
5. 打开一次**基础数据 → 大项 / 小项**,确认「该项启用奖牌结算」是按赛事规则勾的;
6. 用《上线检查清单》从头过一遍。
### ⑥ 详细说明在哪
| 想了解 | 看 |
| --- | --- |
| 奖牌开关怎么用 / 什么时候关 | 《使用手册》10.2(小项)、10.4(计分通道) |
| 奖牌榜没牌 / 金牌数不对怎么查 | 《常见问题》Q94 |
| 团体名次怎么录 / 为什么没有那一块 | 《使用手册》4.9、《常见问题》Q95 |
| 升级后奖牌榜是空的 | 《部署指南》3.4、《常见问题》Q96 |
| 名单导入怎么认人、怎么填 | 《报名名单导入规范》 |
| 延迟结算下哪些动作会立刻生效 | 《使用手册》4.8、《常见问题》Q91 |
| 历史成绩版本重放与团体名次 | 《常见问题》Q97(已知限制) |
---
## dev_0.1.7 及更早
本文件从 **dev_0.1.8** 起维护;更早版本的改动不再逐版补记。若需要,可在《使用手册》与当时的发布记录里查。