feat(import): 报名模板按「小项 × 组别」分工作表;号码布判重改认证件号;备份改原子落盘

三件事合成一次提交(其中两件都落在 handlers_config.go,无法按文件拆开):

一、分工作表报名模板(新增能力)
- 新增 GET /api/entries/template.xlsx:按当前赛事的「小项 × 组别」生成模板,
  一个小项组别一张工作表,工作表名 = <小项>@<组别>(31 字符上限、重名自动去重)。
- 导入解析器认工作表名还原小项 + 组别;若与表内列冲突则报错,不静默取其一。
- 小项名与组别名禁用 @,基础数据界面 / 规则包导入 / 服务端校验三处一并拦截。
- 单表 CSV/XLSX 导入路径不回归。

二、号码布判重(修误判)
- 旧逻辑依赖证件号本身,而证件号是可选字段 → 同一个人报多个项目会被整块拦下。
- 改为:号码布相同且证件号相同 → 判定为同一人报多项,放行;
  号码布相同且证件号都能填且不同 → 仍报错(真抢号);一方证件号为空 → 放行并给提示。
- 团体行的号码布一并纳入查重。

三、自动备份的关停与落盘(修数据安全隐患)
- export.Service 增加 Wait():StartAuto 的协程进 WaitGroup,关停时 join(10 秒上限,
  超时只记 WARN 不拖死关闭),不再在备份写到一半时退出。
- vacuumInto 改为先写 <最终名>.tmp-<随机> 再 rename,失败则删临时文件;
  Backup / SafetySnapshot / ExportProjectZip 三个调用方一并受益。
- 新增 isFinalBackupName,ListBackups / safetyCopies / KindOfBackupName 统一过滤中间文件,
  避免半截 .db 被列进备份列表、进而被「一键恢复」选中。

文档:docs/ 五份(使用手册 / 报名名单导入规范 / 升级说明 / 部署指南 / 上线检查清单)同步。
This commit is contained in:
AskaEth committed 2026-09-14 01:10:16 +08:00
1 parent b74768b7d5
commit 1b8a37ff8c
32 files changed
+3302 -233

No files matched your search

+14 -5
View File
@@ -10,7 +10,7 @@
### 一句话
**两条数据迁移、三处计分口径变化、安装器换新,升级后建议重新导入一次新版规则包**:迁移 `0022` 把「小项已被删除、积分流水却还挂在榜上」的历史脏数据一次性作废(**只影响分数,不影响名次与奖牌,人工调整分不受影响**);迁移 `0023` 给计分通道加一列「聚合口径」(默认「平均」,不切就与升级前一样);**单位奖牌榜改为按奖牌数独立排名,可能与积分榜顺序不同**;安装界面全面重做(**安装逻辑不变**)。
**两条数据迁移、三处计分口径变化、安装器换新,升级后建议重新导入一次新版规则包**:迁移 `0022` 把「小项已被删除、积分流水却还挂在榜上」的历史脏数据一次性作废(**只影响分数,不影响名次与奖牌,人工调整分不受影响**);迁移 `0023` 给计分通道加一列「聚合口径」(默认「平均」,不切就与升级前一样);**单位奖牌榜改为按奖牌数独立排名,可能与积分榜顺序不同**;安装器换新——界面全面重做,并且**安装时改了三处行为**(一启动就申请管理员、自动关闭正在运行的旧版本、装到哪与「上次安装目录」的关系,见 ③)。
### ① 数据迁移:两条(0022 / 0023)
@@ -46,11 +46,20 @@
- 重新导入规则包会把这条口径按规则包的值写回库里(本赛会包是 **总分 → 金 → 银 → 铜 → 单位编码**):**此前导入过排序口径写法不同的规则包**的机器,这一段里单位的先后可能变化——**变的是顺序,分数与奖牌都不变**,看到顺序变了不要当成故障。
- **单位奖牌榜不受这条影响**:它固定按金 → 银 → 铜 → 单位编码(见上面第 2 条)。
### ③ 安装器换新(界面重做,安装逻辑不变)
### ③ 安装器换新(界面重做 + 三处安装行为变化)
- 安装程序(`Scoreboard Console-<版本>-x64.exe`)**界面全面重做**:欢迎 / 目录 / 许可 / 进度 / 完成各页与按钮换成新素材,并**支持 4K 高 DPI**(系统缩放到 200% 时界面按缩放后的尺寸排布,字与按钮不会糊成一团)。
- **安装逻辑一个字没改**:装到哪、装什么、桌面快捷方式(「赛事积分榜」)、卸载方式、覆盖安装时先静默跑一遍旧卸载器、数据与配置在 `%LOCALAPPDATA%\ScoreboardConsole\`(**覆盖安装不会丢**)——全部与升级前一致。
- 默认安装模式是**「为所有用户安装」**(装到 Program Files,安装时提一次权);**这台机器上次装过时,向导沿用上次的装法**,静默安装也可以用 `/allusers` / `/currentuser` 指定。这一趟**仍然自动放行防火墙入站 19540**(在防火墙里能看到规则 `Scoreboard Console (TCP 19540)`),局域网大屏不用再手工放行;选「仅为我安装」的机器要手工放行(命令见《部署指南》7.5)。
- **界面全面重做**:安装程序(`Scoreboard Console-<版本>-x64.exe`)的欢迎 / 目录 / 许可 / 进度 / 完成各页与按钮换成新素材,并**支持 4K 高 DPI**(系统缩放到 200% 时界面按缩放后的尺寸排布,字与按钮不会糊成一团)。
- **① 安装程序现在一启动就申请管理员**:双击安装包会**先弹一次 UAC**(Windows 的「是否允许此应用对你的设备进行更改?」),点「是」之后整个安装过程都在提权状态下进行 —— 装到 `C:\Program Files\…`、自动放行防火墙入站 19540(规则名 `Scoreboard Console (TCP 19540)`,卸载时会自动删掉)都靠它。
- **管理员机器**:会弹这一次 UAC;装完不用再手工放行防火墙。
- **受限账户(不是管理员)的机器**:**不会弹 UAC**(弹了也没用),安装程序会**自动降级为「仅为我安装」**,装到你的用户目录(`%LOCALAPPDATA%\Programs\…`),**不装**到 Program Files,也**加不了**防火墙规则 —— 这种机器要照《部署指南》7.5 在管理员账户下手工放行一次。
- **② 安装时会自动关闭正在运行的旧版本**:升级前**不用手工退出**「赛事积分榜」——安装程序会自己找到在跑的旧版本进程并关掉(连它拉起的 `scoreboard.exe` 服务端进程一起关)。以前那个「请先关闭程序」的提示框会被新界面压在下面,看不到又挡着流程,现场很容易卡在那儿出不来。
- **③ 安装位置(装到哪个目录)**:
- 向导里**默认填这台机器上次装的那个目录**;
- 切换「为所有用户安装 / 仅为我安装」时,**目录输入框会跟着变成该模式的默认目录**(分别是 `C:\Program Files\Scoreboard_Console` 和你的用户目录);
- 但你**手工改过路径(或点过「浏览…」)之后,再切模式也不会冲掉你填的那个目录** —— 想回到模式默认目录,把路径清空重新切一次模式即可;
- 想知道这次装到哪了:右键桌面「赛事积分榜」快捷方式 →「属性」→ 看「目标」。
- **静默安装**(`安装包.exe /S`,无人值守用):**会跳过旧版本卸载器** —— 旧卸载器自己可能弹一个没人能点的提权框,跳过它才能保证无人值守下一定跑得完。静默安装也可以用 `/allusers` / `/currentuser` 指定装法;用 `/D=` 指定目录时**以 `/D=` 为准**(不取「上次安装目录」的记忆)。
- 装到哪、装什么、桌面快捷方式(「赛事积分榜」)、卸载方式、数据与配置在 `%LOCALAPPDATA%\ScoreboardConsole\`(**覆盖安装不会丢**)—— 这些与升级前一致(交互式升级仍会先跑一遍旧版本的卸载器,这也是数据不能放在安装目录里的原因,见《部署指南》3.4)。
### ④ 升级后建议:把新版规则包重新导入一次