diff --git a/docs/superpowers/specs/2026-08-07-crm-name-pinyin-abbr-design.md b/docs/superpowers/specs/2026-08-07-crm-name-pinyin-abbr-design.md new file mode 100644 index 000000000..9c6822c0a --- /dev/null +++ b/docs/superpowers/specs/2026-08-07-crm-name-pinyin-abbr-design.md @@ -0,0 +1,143 @@ +# CRM 产品/客户名称拼音首字母检索 + +**日期:** 2026-08-07 +**状态:** 设计已确认 +**选定方案:** 表内冗余字段 `name_pinyin_abbr` + 后端 `pypinyin` 统一生成;列表与业务选择器 keyword 增加不区分大小写的拼音模糊匹配 +**相关模块:** 产品管理 `/#/crm/product`、客户管理 `/#/crm/customer`;合同/报价等产品选择器与客户选择器 + +## 1. 目标 + +1. 为产品名称、客户全称维护 **拼音首字母缩写**(库内存小写),支持多音字/特殊简称时人工纠正。 +2. 前台列表筛选、快速搜索,以及合同/报价等业务选择器的远程搜索,支持用拼音首字母 **模糊检索**,且输入大小写混合均可命中。 +3. 新增/保存时默认按名称自动生成;名称变更时 **仅当拼音字段为空才自动填**;已有值(含手改)不覆盖;表单提供「按名称重新生成」。 +4. 上线时对存量数据跑一次批量回填(仅填空字段)。 + +## 2. 非目标 + +- 不维护客户 `short_name` 的独立拼音字段(简称仍走现有中文 `LIKE`)。 +- 不存全拼、不做独立别名表、不做全文检索引擎。 +- 本期不改客户公海、小程序客户列表等其它入口的检索(可二期复用同一字段与工具函数)。 +- 不提供管理端「强制全量重算」入口(仅上线脚本一次回填)。 +- 不为 `LIKE '%xx%'` 强依赖新建索引(可按数据量后续评估)。 + +## 3. 背景与现状 + +- web-admin 已有 CRM **产品管理**(`crm_product`)与 **客户管理**(`crm_customer`)。 +- 当前检索均为名称/编号等字段的 `LIKE` 中文模糊匹配,无拼音相关列。 +- 业务痛点:打汉字检索偏慢,希望用拼音首字母快速定位。 + +## 4. 数据模型 + +| 表 | 新字段 | 类型 | 说明 | +|----|--------|------|------| +| `crm_product` | `name_pinyin_abbr` | `varchar(100)` DEFAULT NULL | 产品名称拼音首字母,存小写 | +| `crm_customer` | `name_pinyin_abbr` | `varchar(100)` DEFAULT NULL | 客户全称拼音首字母,存小写 | + +- 字段位置:业务字段区,紧挨 `product_name` / `customer_name` 之后;公共字段之前。 +- API / 前端驼峰:`namePinyinAbbr`。 +- DDL 同步维护:`docs/sql/` 基线及迁移脚本;符合 `database-conventions` 字段顺序约定。 +- `_row_to_dict`、Create/Update Body、前端 form **字段一致性** 必须包含该可写字段(见 `docs/dev-field-consistency.md`)。 + +## 5. 生成规则 + +后端统一工具函数(建议 `backend/app/utils/pinyin_abbr.py` 或同等位置),依赖 `pypinyin`(写入 `requirements.txt`)。 + +**算法:** + +1. 输入字符串 trim;空则返回空串。 +2. 逐字符: + - 汉字 → 取拼音首字母(`pypinyin` 默认读音),转小写; + - `a-zA-Z0-9` → 转小写后保留; + - 其余(空格、括号、%、中英文标点等)→ 丢弃。 +3. 拼接为连续小写串;若超过字段长度则截断至 100。 + +**示例(以实际 `pypinyin` 结果为准,下列为期望形态):** + +| 名称 | `name_pinyin_abbr` | +|------|-------------------| +| `55% 工业硫酸` | `55gylls` | +| `苯骈三氮唑BTA` | `bstnzbta` | +| `PAC` | `pac` | +| `安徽金浔新能源材料有限公司` | 按库结果连续小写首字母 | + +**写入时机:** + +| 场景 | 行为 | +|------|------| +| 新增且拼音为空 | 按名称自动生成 | +| 编辑改名称,拼音仍为空 | 自动生成 | +| 编辑改名称,拼音已有值 | **不覆盖** | +| 用户点「按名称重新生成」 | 前端用当前名称覆盖表单拼音字段;保存时提交 | +| 用户手改拼音 | 保存时 `strip` 后转小写入库 | +| 上线回填脚本 | 仅空 / NULL 字段按名称生成 | + +名称本身有必填校验;名称为空时不生成、不因拼音阻塞保存。 + +## 6. 检索语义 + +在现有 keyword / 名称类条件上 **OR** 拼音字段,大小写不敏感: + +```text +-- 伪代码;kw_lower = keyword.strip().lower() +(名称 LIKE %keyword%) +OR (编号等其它既有条件…) +OR (LOWER(name_pinyin_abbr) LIKE %kw_lower%) +``` + +- 中文检索行为保持不变。 +- 纯字母数字输入可命中拼音缩写(如 `GYlls` / `gylls` / `GYLLS` 等价)。 +- 客户列表既有 `customer_name` / `customer_no` / `short_name` / `mobile` 等条件保留,再 OR 拼音。 + +**本期必须改造的查询入口:** + +| 入口 | 说明 | +|------|------| +| 产品列表 keyword | 筛选区 + 快速搜索 | +| 产品 options / 选择器 | `fetchProductOptions`、`product-selector`、`DbCrmProductSelect` 等远程搜 | +| 客户列表 keyword / customerName | 筛选区客户名称、快速搜索 | +| 客户 options / 选择器 | `fetchCustomerOptions`、`DbCrmCustomerSelect` 等远程搜 | + +合同/报价等使用上述 options/list 的选择器 **不新增独立查询参数**。 + +## 7. API 与后端改动要点 + +- CRUD create/update:接受 `namePinyinAbbr`;服务端按第 5 节规则归一化/补全。 +- list / options:keyword 条件并入拼音 OR。 +- detail / `_row_to_dict`:返回 `namePinyinAbbr`。 +- 回填:一次性脚本(如 `backend/scripts/backfill_name_pinyin_abbr.py`),按租户或全表扫描,仅更新空字段;失败行记日志,按批提交避免长事务。 + +## 8. 前端 UI + +| 位置 | 改动 | +|------|------| +| 产品新增/编辑表单(含公共 `ProductFormDialog`) | 「拼音首字母」可编辑输入 + 「重新生成」按钮 | +| 客户新增/编辑表单 | 同上 | +| 产品/客户查看弹窗 | 只读展示拼音首字母,便于核对手改 | +| 列表筛选 / 快速搜索 | placeholder / hint 提示可搜名称、编号、拼音首字母 | +| 选择器搜索框 | 同步更新 placeholder(若有文案) | + +UI 遵守 Fresh Mint:`label-position="top"`、按钮带图标、「重新生成」为中性描边;表单注释用 `#label` + `.form-label-tip`(如有需要)。 + +## 9. 上线步骤 + +1. 执行 DDL:两表增加 `name_pinyin_abbr`。 +2. 部署后端(含 `pypinyin`)与前端。 +3. 运行回填脚本(仅空字段)。 +4. 抽检:列表与选择器用中文、小写拼音、大小写混合拼音检索若干已知样例。 + +## 10. 测试要点 + +- 新增产品/客户:不填拼音 → 自动生成小写缩写。 +- 手改拼音后改名称保存 → 拼音不被覆盖。 +- 「重新生成」→ 表单拼音被名称规则覆盖,保存后生效。 +- 列表 / options:`gylls`、`GYLLS`、`GYlls` 均可命中对应产品;中文名称检索仍可用。 +- 回填:已有手改值的行不被脚本覆盖;空行被填上。 +- 字段一致性脚本:`python scripts/check_field_consistency.py`(若覆盖 product/customer)通过。 + +## 11. 风险与缓解 + +| 风险 | 缓解 | +|------|------| +| 多音字默认读音不准 | 表单可手改 + 重新生成 | +| 化工名含括号、百分比、英文缩写 | 生成规则保留字母数字、丢弃符号(见第 5 节) | +| 存量未回填则拼音搜不到 | 上线必跑一次回填脚本 |