fix(goods): 商品展示名统一「品名 SKU」——剥 ASCII 型号限定词、纯款号补描述

左栏商品名显示成光款号(如 PLTK016)的根因是双层解析不一致:api 写路径按
首括号对解析产出「童装…(DTG180) PLTK016」,admin 展示解析按末括号取品名
误显示成 PLTK016。

- admin parseLinkName 对齐 api 首括号对解析 + 无 SKU 段中文品名守卫,
  cleanLinkName 剥离 ASCII 型号限定词(中文括号内容保留)
- api 新增 cleanGoodDisplayName/describePureSkuGoodName,接入 create/update/
  batchCreate(batchCreate 补上缺失的 normalize);纯款号按 SDS 分类名补描述
- 新增幂等存量修复脚本 fix:good-names(默认 dry-run,--apply 写库)
- 已执行:V2 栈 34 条限定词名、V1 栈 213 条原始链接名规范化,复跑幂等 0

Tests: api 22 suites/199 passed, admin 27 passed, tsc clean
This commit is contained in:
yeuimu
2026-09-03 01:04:22 +08:00
parent ae9901e6cc
commit c3be8ab979
10 changed files with 598 additions and 16 deletions
+77
View File
@@ -0,0 +1,77 @@
# 修复左栏商品名显示成光款号(PLTK016 → 童装纯色插肩短袖T恤 PLTK016)
- 分支:`bugfix/pure-sku-good-name-yeuimu`(自 `develop`
- 日期:2026-09-02
- 类型:Bug 修复 / 数据修复
## 问题
后台商品配置页(GoodsView)左栏部分商品只显示纯款号(如 `PLTK016`),期望显示
「描述名 款号」(如 `童装纯色插肩短袖T恤 PLTK016`)。
## 根因(两层)
1. **展示解析误判(主因,V2 栈 34 条)**:部分 SDS 品名自带 ASCII 型号限定词,
写路径 `normalizeGoodName`api `splitSegment1` 首括号对解析)产出的展示名为
`童装纯色插肩短袖T恤(DTG180 PLTK016`;而 admin 展示解析器
`parseLinkName` 用**最后一个** `` 之后的文本当品名 → 显示成光秃秃 `PLTK016`
2. **纯款号名(防御路径,当期两库 0 条)**:SDS 部分链接名只有款号,解析不出
品名时 `normalizeGoodName` 原样入库,左栏显示裸款号;且 `batchCreate` 完全
未过 normalize。
描述名权威来源:SDS 分类名 `categories.category_name``PLTK016 童装纯色插肩短袖T恤`
`auto-group` 族名同源),去首 token 款号即得。
## 边界与约束
- `origin_goods.good_name` 是 SDS 纯镜像、每小时被同步覆盖 —— **不动镜像**
只修 `goods.good_name`(官网展示名,前台官网直接透传,同步受益)。
- 中文括号内容(如 `(女款)`)不是型号限定词,保留。
- CUSTOM 商品(createCustom/updateCustomContent)人工命名不受影响。
## 实现
### adminapps/admin/src/utils/origin-name.ts
- `parseLinkName` 对齐 api 端:首括号对解析 + 半/全角归一;无 SKU 段时仅当
括号后品名含中文才视为链接名(防「品名(限定词) SKU」误解析)。
- 新增 `stripAsciiParenQualifiers``cleanLinkName` 展示统一剥离 ASCII 型号限定词。
### apiapps/api/src/goods/goods.service.ts
- 导出 `stripAsciiParenQualifiers` / `cleanGoodDisplayName`(规范化 + 剥限定词)/
`isPureSkuGoodName` / `describePureSkuGoodName`(纯款号按 SDS 分类名补描述,
分类名中的限定词一并剥离)。
- `resolveGoodName` 私有助手接入 `create` / `update` / `batchCreate`batchCreate
顺带补上缺失的 normalize);`sdsCategoryIdForGood` 取(可切换后的)主链接分类。
- `backfillPureSkuGoodNames({ dryRun, goodId? })`:存量修复,幂等,支持 goodId
限定(测试隔离用)。
### 脚本
- `apps/api/prisma/fix-pure-sku-good-names.ts`(薄壳,手动构造依赖),
npm script `fix:good-names`;默认 dry-run`-- --apply` 写库。
## 测试(TDD
- admin `origin-name.spec.ts`:+5(误解析防护、限定词剥离、中文括号保留、
首括号单段解析),共 23 绿。
- api `goods.service.spec.ts`+9(纯函数边界、create/update/batchCreate 补描述、
无映射保留、backfill dry-run/apply/幂等/限定词剥离),共 30 绿。
- 全量:api 22 套件 199 测试绿(临时 docker postgres + `prisma migrate deploy`
共享开发库 192.168.124.92 当期不可达);admin vitest 2 文件 27 测试绿;
两端 `tsc --noEmit` 零错误。
## 落库结果(2026-09-02 执行)
- V2 栈(deploy-v2-postgres-1):34 条 `品名(限定词) SKU``品名 SKU`
(含 #263 `童装纯色插肩短袖T恤 PLTK016`)。
- V1 栈(deploy-postgres-1):213 条原始链接名 → 规范化「品名 SKU」(后台展示
等价,官网卡片由原始链接名变为干净品名)。
- 两库复跑 dry-run `renamed=0 unmapped=0`,幂等验证通过;数据已干净,线上旧
前端镜像无需等重部署即正确显示;代码修复防新增。
## 权限评估
无新增端点/操作,全部复用既有已控权限路径(PATCH /goods/:id 等);CLI 脚本为
运维通道 —— 无需新增权限项。