fix(entry): 补报名弹窗的搜索框支持「号码布」;版本 dev_0.5.7

## 现场问题(主人原话)
> 成绩录入界面的补报名按钮窗口里面的搜索框只能查姓名和工号,不能查号码布,加一下。

号码布是本系统里**运动员的唯一标识**(定稿口径),现场拿号码布找人是常态,所以这条是刚需。

## 改了什么
- 抽出纯函数 `athleteMatchesKeyword(athlete, keyword)` 作为**选人搜索的唯一口径**:姓名、工号、**号码布** 三维并列;
  关键字归一(`trim()` + `toLowerCase()`)与仓库既有写法逐字一致,空搜索仍不筛人。
- `EntryPicker.vue` **两处**搜索都改成走它:
  - `filteredAthletes`(个人报名名单)
  - `membersByTeam`(团体队员名单)
- 两个搜索框的提示文字从「搜索姓名 / 工号」改成「**搜索姓名 / 工号 / 号码布**」。
- ⚠️ 收口成一个函数的意义:两个框**不会再各走各的** —— 这次就是因为两处各写了一份过滤条件,改一处漏一处。

## 验证
- **先红后绿**:新增 `web/src/admin/tests/athlete-search-bib.test.ts`(号码布能搜到、姓名/工号不回归、大小写与空格处理、空搜索不筛人)。
- 全量自检两轮**全绿、`EXIT=0`**:服务端 14 包 / 前端 929 例 0 fail / Console 68 例 0 fail。

## 顺带
`debug/使用说明/` 里落后的 4 份(使用手册 / 升级说明 / 报名名单导入规范 / 使用说明.txt)已补刷,与 `docs/` 逐份一致;
`docs/升级说明.md` 新增 `dev_0.5.7` 一节。

## 版本
`dev_0.5.6` → **`dev_0.5.7`**(无数据迁移);安装器素材同步重生成(照例只动 `brand.bmp` 两张)。
This commit is contained in:
AskaEth committed 2026-09-14 21:54:05 +08:00
1 parent 99c91f99f7
commit d11cab31db
9 files changed
+134 -24

No files matched your search

@@ -217,6 +217,31 @@ export function selectionAllowsSubmit(mode: SelectionMode, chosenCount: number):
return mode === 'team' || chosenCount > 0
}
/**
* 选人搜索框的匹配口径:**姓名 / 工号 / 号码布**任一命中即算(大小写不敏感、首尾空格忽略)。
*
* 号码布必须在内:它是本系统里人员的唯一标识(先认证件号,没有证件号就看号码布),
* 现场拿着号码布找人是常态,只能按姓名 / 工号搜等于搜不到人。
*
* 工号与号码布都可能为空(老数据两个都没填、老服务端也不下发),一律当空串处理。
* 关键字全为空白 = 没在搜,返回 true(不能把名单筛空)。
*
* 搜索框是文本框,这里只做字符串比较;**不要**把它的取值喂给 `type="number"` 的输入框
* (那种框的 v-model 会被 Vue 转成 number,清空才留 '',字符串方法会在渲染期抛错)。
*/
export function athleteMatchesKeyword(
athlete: { name: string; employeeNo?: string | null; bib?: string | null },
keyword: string,
): boolean {
const needle = keyword.trim().toLowerCase()
if (needle === '') return true
return (
athlete.name.toLowerCase().includes(needle) ||
(athlete.employeeNo ?? '').toLowerCase().includes(needle) ||
(athlete.bib ?? '').toLowerCase().includes(needle)
)
}
/**
* 报名行的展示文案:运动员姓名 → 团体队员首人 → 单位简称 / 全称。
*