用户点名的三件事(模板功能、删死代码、剩余缺口)这一批全部落地,另修掉两个刚暴露的导入缺陷:
**新增能力**
- 备份恢复:`POST /api/backup/restore`(admin)。先把校验做在拍快照之前(只读打开 + integrity_check +
关键表校验 + 异类库标志表互斥),再用 VACUUM INTO 拍「恢复前安全副本」,然后关连接、整文件替换、
触发优雅重启;`-wal` 还在时直接拒绝(宁可失败也不让旧库 WAL 套到新库上);恢复后审计直写"恢复之后
还在的那份库"(不走通用 Auditor,否则记录只会落在被替换掉的旧文件上)。顺带修掉:裸服务端连续恢复
第二次会在拍副本处崩出一句看不懂的 500,现在回 503「上次恢复后尚未重启,请先重启服务端」。
- 安全副本保留策略:每类库保留最近 5 份,独立于 .db 的 20 份滚动清理。
- 图片管理:`DELETE /api/uploads/{name}`(被引用 409 并列出引用点)、`GET /api/uploads/orphans`、
`POST /api/uploads/orphans/delete`(只删列出的孤儿,宁漏勿误),全部 admin(与字体删除同档);
`deploy/backup.bat` 补上 uploads/ 归档(logs 不归档:可再生的诊断且会无上限增长)。
- 已彻底删除单位的恢复:`POST /api/teams/{id}/restore`(与 hideTeam 同档)。幂等;恢复不会把「停用」
变成「启用」;真机确认恢复前后榜单逐字节一致、change_log 最大值不变(数据一行没动,不需要重算)。
界面加「显示已彻底删除的单位」(仅 admin)与恢复按钮;非 admin 的删除确认框里写明"本账号无法自行恢复"。
- 审计日志按 `action` 过滤(子串模糊,输入里的 %/_/\ 转义成字面量)。
- 删除死表 recent_projects(新增 system 迁移 0006,未动已应用的迁移)。
- points_override 不再"设了没效果":写入侧 400 + 引擎侧守卫,提示改用「积分调整」。
- 联队份额空壳清理(UnionAttribution/UnionSplit/Entry.TeamShares/resolvedShares 等;TeamShare 类型保留,
因为 export/realtime/奖牌流水三处在生产路径上构造它)。
- 自定义大屏模板 M1:插值引擎(parseTemplate/renderTemplate),任何情况都不抛异常、未定义→空串+警告、
警告按 (code,path) 合并计数、无 eval/innerHTML,57 个新用例。
**两个真缺陷(前两个已随 0.1.6 出包)**
- 基础数据包导入「排序」列口径不一致:小项/组别留空保持原值,单位/大项留空被写成 0(plan 没从库里
现值起手)→ 四张表统一为「留空保持原值」。
- 同类第二处:布尔列「整列被删掉」被当成"取默认值",会把库里所有停用的单位/大项静默改回启用 →
改为「缺列 = 不动」(写侧与解析侧都收口,补了"缺列保持/空格子=是/显式否=停用"三组对照用例)。
**删死代码**
- createEntry / updateEntry / deleteEntry / entryEventID / checkCategoryInEvent / getEntry /
normalizeEntryStatus / ExportBaseDataXLSX(全仓 grep 零引用)。⚠️ 随之记入文档:「组别必须属于该小项」
这道校验现在只由导入路径"按小项+组别名解析"天然保证,将来若新增从请求体接收 categoryId 的接口,
必须自己补校验(库层没有复合外键)。
**文档**
- devdocs 全面同步(01/02/03/04/05/06/07/09/11/12/13/README;含身份口径、延迟结算、大屏单栏新版式、
新增路由与设置键、R18/R19 风险);docs 复核 + 第二轮(身份口径三个易写反的分支、图片删除、备份覆盖、
审计过滤、单位恢复、去掉硬编码版本号、上线检查清单 +5 项);debug/使用说明 6 份逐份 diff 一致。
测试:服务端 13 包(连跑两遍)、前端 406 例、Console 28 例 + 18 文件语法检查 —— 全绿。
版本号 dev_0.1.6 → dev_0.1.7。
21 KiB
报名名单导入规范
这份文件说明报名名单应该做成什么样子、每一列怎么填,用于把各单位报上来的名单一次性导入积分榜系统。 给负责收表、填表的同志看即可,不需要懂系统内部。
配套模板可在系统里直接下载:基础数据 → 报名导入 → 下载 CSV 模板。
一、先看懂三件事
- 用什么软件做表:Excel 或 WPS 都行,做完存成
.xlsx或.csv都可以(推荐.csv,系统兼容性最好,不用管编码)。 - 表格长什么样:第一行是表头(固定的 12 个英文列名),从第二行开始每人一行。不要合并单元格,不要在表头上方再加标题行、说明行。
- 编码不能自己编:表里的「小项编码」「单位编码」「组别名称」必须是系统里已经配好的,照抄系统里的写法。系统里没有的编码,这一行会被跳过并报错。
二、表头(第一行的列名)
一共 12 列。列名请直接用下面这套英文名,不要翻译成中文;列的先后顺序可以随便调,多出来的列系统会忽略。
| 列名 | 是否必须 | 填什么 | 示例 |
|---|---|---|---|
event_code |
必须 | 小项编码,抄系统里配好的 | M100 |
category |
必须 | 组别名称(中文,要跟系统里一字不差) | 男子30岁以下 |
team_code |
必须 | 参赛单位编码,抄系统里配好的 | F1 |
athlete_name |
必须 | 运动员姓名。团体项目这一列留空 | 张伟 |
id_card |
可选 | 证件号(身份证号)。只是档案信息,不参与认人;一个证件号只能属于一个人 | 110101199001011234 |
gender |
可选 | 性别,只写「男」或「女」 | 男 |
age |
可选 | 年龄,0–120 的整数 | 26 |
bib |
可选 | 号码布,单人的唯一标识(同名同姓的人靠它区分) | 101 |
seed |
可选 | 道次 / 种子,随便写或留空 | 种子1 |
heat |
可选 | 批次号:1–999 的整数;留空 = 未分批(不参与算分,见下) | 1 |
status |
可选 | 报名状态:4 个英文词(大小写都行)或等价的中文别名(见下) | registered |
member_names |
可选 | 团体项目的队员名单,多人用 / 隔开 |
张三/李四/王五 |
「必须」指的是这一列的表头要有。至于每格里能不能留空,看下面第三节逐列的说明。
表头大小写不敏感:写 Event_Code 或 event_code 都认。
三、逐列怎么填(重点)
event_code 小项编码 —— 必须填
在系统「基础数据 → 大项 / 小项」里给每个小项配的编码,比如 M100(男子100米)、BB(多人抓杆蛇形跑)。
填了系统里没有的编码,这一行会被跳过,提示「小项 XXX 不存在」。
category 组别名称 —— 必须填
填组别的名字,不是编码。比如「男子30岁以下」「男子31岁以上」「女子组」「基层组」「领导组」。
- 必须和系统里该小项的组别名称完全一致(含标点),否则提示「组别 XXX 不存在」。
- 这一格留空也可以:系统会自动放到该小项排序最靠前的那个组别。一个单位一个项目只报一个组时,留空能省事;报了多个组别的项目,必须写明。
team_code 单位编码 —— 必须填
在系统「基础数据 → 参赛单位」里给每个大单位配的编码,比如 F1、F2。系统里没有的会提示「单位 XXX 不存在」。
被「彻底删除」的单位,导入时若再次用到它的编码,它会重新出现(复活),这一行照常导入——单位编码是唯一的,系统按编码复用原来那条记录,它以前的报名、成绩与积分都还在。
athlete_name 运动员姓名
- 个人项目:填姓名,必填。
- 团体项目:这一列留空,表示"这是某个单位的一条团体报名",队员写在
member_names里。 - 姓名为空的行,系统只建一条单位报名,不会去建运动员档案。
id_card 证件号 / bib 号码布 —— 有姓名就至少填一个
只要有姓名,证件号与号码布至少要填一个,否则无法确认是哪一个人,这一行会被跳过,提示「填写了 athlete_name 就必须填 id_card 或 bib」。
- 号码布是单人的唯一标识,也是系统认人的依据:先按号码布找人,号码布为空或没找到时,再按「姓名 + 单位」找(完整顺序见本节的「系统怎么认人」)。
- 证件号是可选的档案信息,不参与认人:它只写进 / 更新人员档案,用来登记身份;没有身份证、外聘人员只填号码布就行。
- 但一个证件号在系统里只能属于一个人:如果表里给的证件号已经登记在另一个人名下(姓名、号码布都对不上),这一行会报
证件号 X 已被另一个人占用(姓名 Y,号码布 Z)并跳过——证件号不会被抢过来,那个人也不会被改成表里的人。 - 同一个证件号在同一份表里重复出现不再报错(同一个人报多项时本来就会重复),照常导入。
- 号码布不能在一份表里重复出现:重号说明要么是填错、要么是把号码布给了两个人,重复的行会被跳过并报错。
- 号码布会同时写进人员档案和报名记录。
gender 性别
只认「男」「女」两个字。留空没问题;写「男性」「女 」等其它写法会被当成没填(不报错,但也不记录)。
age 年龄
0–120 的整数,可以留空。填了「二十六」「26岁」这种会被跳过,提示「age 需要是 0-120 的整数」。
seed 道次 / 种子
自由填写,可以留空。系统只做记录,不参与算分、不影响名次。
heat 批次 —— 可以留空
给同一组别的人分批用的号:填 1–999 的正整数,留空表示「未分批」。现场分批比赛(例如 100 米跑道只有 8 条、一组 30 人要分 4 场跑)时,填上批次,录入员就能在「成绩录入」页按批筛选,只在自己这一批里找人录成绩。
- 批次不参与算分:名次与积分仍然按「小项 + 组别」整体计算,分批与否不会改变任何分数与名次;批次只是录入 / 展示分组;
- 同一小项、同一组别里,批次号相同的人就是同一批;批次号不要求连续,也不要求从 1 开始;
- 格子留空就是未分批,不报错;
- 填了不是整数、或超出 1–999(例如
第1批、0、1000),这一行会被跳过并提示「heat 需要是 1-999 的整数(留空表示未分批)」,其余行照常导入; - 重新上传同一份表会把这一列整条覆盖:表里留空就会把这行原来的批次清掉(见第七节第 2 条)。
不想在报名表里写批次也行:导入后到「成绩录入」页勾选若干行点「设为第 N 批」,或用「一键均分」按人数自动分批(见使用手册 · 4.1)。
status 报名状态 —— 英文词或中文别名都认
大小写不敏感(registered、Registered、DNS 都认),也可以直接写中文:
| 英文写法 | 等价的中文别名 | 含义 |
|---|---|---|
registered |
正常 / 正常参赛 / 参赛 |
正常参赛 |
scratched |
退赛 / 弃赛 / 请假 |
退赛 / 弃赛 |
dq |
取消资格 / 犯规 |
取消资格 |
dns |
未出场 / 未到 / 缺席 |
未出场 |
留空 = registered(正常参赛),拿不准就留空,特殊情况再填。
真正认不出的写法(例如「已报到」「未参赛」):这一行会被跳过,并给出中文行级提示,其余行照常导入。
第 12 行:status「已报到」无法识别,只能填 registered / scratched / dq / dns(或留空)
member_names 队员名单
团体项目用这一列写队员,多人之间用 /、, 或 , 分开:
张三/李四/王五
张三,李四,王五
- 团体项目可以只报单位、不写队员(这一列留空即可),队员名单以后还能补。
- 系统界面里会把这条名单显示成「张三、李四、王五」。
系统怎么认人(号码布 → 姓名 + 单位)
有姓名的行,系统按下面的顺序认人。号码布是唯一标识,证件号只当档案信息,不参与这一步:
| 情况 | 系统怎么处理 |
|---|---|
| 表里的号码布在系统里已有 | 认作同一个人;若表里的姓名 / 性别 / 年龄 / 单位 / 号码布与他的档案对不上,会进「冲突」列表等你逐条决定(保留哪一侧),该行本轮不写入 |
| 号码布为空,或按号码布没找到 | 按「姓名 + 单位」找: · 找不到 → 新建人员档案; · 恰好一人、且他还没有号码布 → 认定是同一人,此时若表里给了号码布,会回填到他的档案; · 恰好一人、且他已有号码布,但表里号码布为空或与他相同 → 仍认定是同一人(重传不带号码布的名单不会把每个人复制一份); · 恰好一人、他已有号码布、且表里给的号码布与他不同 → 按「同名的另一个人」新建档案,并在导入结果里单独列出(姓名 / 单位 / 原号码布 / 新号码布)提醒你核对,不拦截、不报错; · 多人 → 分不清是谁,进「冲突」列表等逐条决定 |
「同名的另一个人」多半是号码布写错了。收到这条提醒时,先核对新号码布是不是本人:是别人(真的同名),确认无误即可;是本人写错了号,到「基础数据 → 运动员」把档案里的号码布改回来,并把多出来的那条新档案删掉。
四、三个完整例子
例 1:个人项目(七单位 × 若干人)
表头那一行照抄,下面每人一行。假设 M100 是按年龄分组的男子100米,F1/F2 是两个单位:
| event_code | category | team_code | athlete_name | id_card | gender | age | bib | seed | heat | status | member_names |
|---|---|---|---|---|---|---|---|---|---|---|---|
| M100 | 男子30岁以下 | F1 | 张伟 | 110101199001011234 | 男 | 26 | 101 | 1 | registered | ||
| M100 | 男子31岁以上 | F1 | 李强 | 110101198505054321 | 男 | 41 | 102 | 1 | registered | ||
| M100 | 女子组 | F2 | 王芳 | 女 | 202 | 2 | registered | ||||
| W100 | 女子组 | F2 | 王芳 | 110101199203031234 | 女 | 34 | 202 | 2 | registered |
要点:同一个人报多个项目,就写多行(如上面的王芳报了两项);每行的 event_code 不同。
例 2:团体项目(七单位 × 两组)
BB 是「多人抓杆蛇形跑」,七家单位各出基层组和领导组两支队伍:
| event_code | category | team_code | athlete_name | id_card | gender | age | bib | seed | heat | status | member_names |
|---|---|---|---|---|---|---|---|---|---|---|---|
| BB | 基层组 | F1 | registered | 张三/李四/王五/赵六 | |||||||
| BB | 基层组 | F2 | registered | 钱七/孙八 | |||||||
| BB | 领导组 | F1 | registered | 周九 | |||||||
| BB | 领导组 | F3 | registered |
要点:athlete_name 一列全部留空;不参赛的单位不写行(不写就是没报名);最后一行是不写队员的纯单位报名,也是允许的。
例 3:「个人 + 团体」项目
这类项目(比如团体引体向上)按个人报名填:每人一行、填姓名和单位。系统会自己算两份成绩——个人的名次分记在个人身上,团体分按各队成员的平均成绩排名后算给单位。不需要再单独写团体行。
五、导入前请先检查(自检清单)
- 第一行是那 12 个英文列名,没有被翻译、没有被合并单元格
- 表头上方没有多余的标题行或空行
event_code、team_code都是从系统里抄的编码,没有空格category与系统里的组别名一字不差- 个人行都有姓名,且都有证件号或号码布
- 一份表里没有重复的号码布(号码布是唯一标识,重号会报错)
- 证件号可以重复(同一个人报多项很正常),但每个证件号在系统里只属于一个人,别和别人的档案重号
status只用那 4 个英文词(大小写都行)或第三节列的中文别名,不写别的词;拿不准就留空heat要么留空,要么是 1–999 的整数(不参与算分,只是录入分组)- 全表没有因为"怕麻烦"把某些列删掉——表头 8 个必须列一个都不能少(哪怕整列是空的)
六、常见报错怎么办
| 提示 | 原因 | 怎么办 |
|---|---|---|
| 第 N 行:event_code / team_code 必填 | 这两格至少有一格是空的 | 每行都必须有小项编码和单位编码 |
| 报名表缺少列 xxx | 表头少了这一列,或者列名被写成中文 / 有错别字 / 上面多了标题行 | 对照第二节的表头逐字核对;最稳的是重新下载模板,把数据粘进去 |
| 中文变成乱码 | 编码问题,现在已修好:Excel 另存的 GB18030 / GBK / UTF-8(带 BOM) / UTF-16(带 BOM) 都认 | 直接传原文件即可,不用转码。唯一例外见下面两条 |
| 报名表编码无法识别:文件里混有无法解码的字节 | 这个文件本身坏了(复制粘贴、转换工具、半路截断都会这样):坏字节会被静默解成 �,导进去就是一串乱码人名,比报错更危险,所以系统直接拦下 |
用 Excel 打开原文件,另存为「CSV UTF-8」后再上传;如果另存后仍报同一句,说明原文件已经损坏,请找原始数据重新导出一份 |
| 文件像 UTF-16 但缺 BOM | 用记事本「另存为 Unicode」会产出不带 BOM 的 UTF-16;这种文件以前会被误报成「缺少列 event_code」,指向完全错误的方向 | 多数情况系统能自动认出字节序并正确导入;仍报此提示时,用 Excel 另存为「CSV UTF-8」 |
| 无法解析 CSV:表格里多半有没配对的双引号 | 格子里手工写了双引号,或只有一个引号没配对 | 让 Excel 重新另存一次(引号由 Excel 按规则加,别手工写);确实需要引号的,写成 "" 转义 |
| 第 N 行:小项 XXX 不存在 | event_code 写错,或该小项还没在系统里配 |
到「基础数据 → 大项 / 小项」核对编码;没配的先配 |
| 第 N 行:单位 XX 不存在 | team_code 写错,或该单位还没配 |
到「基础数据 → 参赛单位」核对 |
| 第 N 行:组别 XXX 不存在 | 组别名和系统里不一致,或该小项还没有这个组别 | 到「基础数据 → 组别」核对名称(注意别多字少字) |
| 第 N 行:小项 XXX 没有组别 | 该小项一个组别都没配 | 先在「组别」里配好,再导入 |
| 第 N 行:填写了 athlete_name 就必须填 id_card 或 bib | 个人行缺两项唯一标识 | 补证件号或号码布;确实都没有的,请先在「运动员」里登记 |
| 第 N 行:号码布 XX 在报名表内重复出现 | 同一份表里同一个号码布出现了两次 | 删掉重复行(同一个人报多个项目时,event_code 必须不同;同一个号码布也不能给两个人) |
| 第 N 行:证件号 X 已被另一个人占用(姓名 Y,号码布 Z) | 表里给的证件号已经登记在另一个人名下。证件号不参与认人,但系统里一个证件号只能属于一个人 | 先核对证件号是不是抄错了:不是这个人的,把这一格留空即可(只填号码布也能导入);是他的,先到「基础数据 → 运动员」把另一条档案里的证件号清掉或改对,再重新上传这一步列出的行 |
| 第 N 行:status「xxx」无法识别 | status 填了系统不认的词(4 个标准词以外的英文,或第三节没列的中文) |
改成 registered / scratched / dq / dns(大小写都行)或第三节列的中文别名,也可以留空(= 正常参赛);改完重新上传 |
| 第 N 行:heat 需要是 1-999 的整数(留空表示未分批) | heat 填了非整数、0、负数或超过 999 的值(如 第1批、一组、1000) |
改成 1–999 的整数,或者整格留空(= 未分批);批次只影响录入分组,不参与算分 |
| 提示「冲突」,人员没有写入 | 按号码布(或「姓名 + 单位」唯一命中)的人在系统里已有记录,但姓名 / 性别 / 年龄 / 单位 / 号码布跟表里对不上 | 在导入结果里逐条选「保留已有数据」或「使用新数据」,选完再提交 |
| 文件传不上去 | 超过 16MB | 拆分上传,或改用 xlsx |
| 只导入了第一张表 | xlsx 只读第一个工作表 | 把要导入的数据放在第一个工作表里 |
七、导入以后
- 系统会显示新增 / 更新 / 跳过的数量:
- 新增:这次新建的报名;
- 更新:这个人本来就有这个项目的报名,用表里的信息覆盖了(不会产生重复报名);
- 跳过:没能导入的行,会带着行号列出来,改好那几行重新上传即可。
- 另有一份**「按同名的另一个人新建了档案(号码布不同)」清单,单独列出姓名 / 单位 / 原号码布 / 新号码布。它不是错误:这些行已经导入成功**,只是提醒你核对号码布有没有写错(见第三节的「系统怎么认人」)。
- 重复上传同一份表是安全的,不会把名单变成两份。改完再传一遍就行。
- ⚠️ 但要注意「更新」是整条覆盖:表里空着的格会把系统里原来的值清掉(队员名单、道次、号码布、批次都会被清空),
status空着会被重置成「正常参赛」。如果之前手工调整过某些人的状态或批次,重传前请在表里把status、heat写清楚。
- ⚠️ 但要注意「更新」是整条覆盖:表里空着的格会把系统里原来的值清掉(队员名单、道次、号码布、批次都会被清空),
- 名单导入后,到「成绩录入」里录成绩、发布,积分榜就会自动更新。
- 被「彻底删除」的人,导入时会以新人员建档:管理员彻底删除某个人时,他的档案连同他名下的报名与成绩会一起从库里删掉;之后表里再出现同一个号码布(或同一「姓名 + 单位」),系统匹配不到旧档案,会把他当作新人员重新建档——名单里多出一条「以前删过的人」通常就是这么来的。新档案是全新的,他以前的报名、成绩与积分不会回来,需要重新录。
- 被「彻底删除」的单位则相反,导入时会「复活」:管理员彻底删除某个单位,只是把它从单位列表里移除,它的报名与成绩一条都没删;表里再出现这个
team_code,系统按编码复用原来那条单位记录,清掉删除标记并让它重新出现在列表里,原有的报名、成绩与积分都还在,也不会新建第二个同名单位。 - 别一口气连传几十次:写操作限 120 次/分钟/用户,超了会返回「操作过于频繁,请稍后再试」。正常一次导入只算一次;真被限了就等一分钟再传,不要连点。
八、给填写人的最短提示(一页版)
- 用系统里下载的模板,第一行不要动;
- 一个人一行;一个人报几项就写几行;
event_code(小项)、team_code(单位)、category(组别)照抄系统里配好的,不自己编;- 每人要有证件号或号码布,至少一个;号码布是系统认人的唯一标识(优先填、别重号),证件号只是可选档案信息、也不能和别人重号;
- 团体项目:姓名列留空,队员写进
member_names,多人用/隔开;- 拿不准的列留空,不要写「无」「/」「—」这类符号;
- 表里不要合并单元格、不要加标题行、不要插图;
- 填完先对着第五节的清单自查一遍,再发给收表人;
- **批次(
heat)**可以不填;要分批比赛就填 1–999 的整数,它只影响录入时怎么分组找人,不影响成绩与名次;- 存成什么格式:Excel →「另存为」→「CSV UTF-8 (逗号分隔) (*.csv)」最稳;中文 Excel 默认的「CSV (逗号分隔)」也能用。别用「Unicode 文本」(UTF-16),别手工改名或把两个文件拼起来,也别在格子里手写双引号(让 Excel 自己加)。
一句话:下载模板 → 只往下面粘数据 → 另存为 CSV UTF-8 → 上传。中间任何一个"顺手改一下"都可能让整份表被拦下。