From ddd7a53dbbab6fe196f9375066d481036b2396d3 Mon Sep 17 00:00:00 2001 From: wx <2636507191@qq.com> Date: Mon, 20 Apr 2026 17:22:24 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E:=20=E4=BA=A7=E5=93=81?= =?UTF-8?q?=E6=A0=87=E7=AD=BE=E6=94=B9=E5=8D=95=E9=80=89=20+=20=E5=AD=97?= =?UTF-8?q?=E5=85=B8=E5=80=BC=E6=9B=BF=E6=8D=A2=E4=B8=BA=20=E7=83=AD?= =?UTF-8?q?=E5=86=85/=E6=96=B0=E5=93=81/=E9=99=90=E5=AE=9A/=E7=A1=AC?= =?UTF-8?q?=E6=A0=B8/=E6=B2=BB=E6=84=88=EF=BC=88Issue=20#1001=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2026-04-20_product-tag-single-select.md | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 changelogs/2026-04/2026-04-20_product-tag-single-select.md diff --git a/changelogs/2026-04/2026-04-20_product-tag-single-select.md b/changelogs/2026-04/2026-04-20_product-tag-single-select.md new file mode 100644 index 0000000..9b6e0f1 --- /dev/null +++ b/changelogs/2026-04/2026-04-20_product-tag-single-select.md @@ -0,0 +1,101 @@ +# 产品标签改单选 + 字典值整体替换 + +**日期**:2026-04-20 +**PR**:无代码变更(纯字典数据迁移) +**Issue**:#1001 +**影响**:管理端产品编辑页 Step1 基础信息「产品标签」 + +--- + +## 为什么变 + +产品侧简化标签心智: +1. 每个产品只配 **1 个标签**(原来多选 chip,现在单选) +2. 字典 `product_tag` 整体换值: + - **旧**:亲子 / 城记 / 摄影 / 研学 / 露营 + - **新**:热内 / 新品 / 限定 / 硬核 / 治愈 + +--- + +## 后端改动 + +**只改字典,不动接口、不动字段类型**: + +- `product_tag` 字典:删除 5 个老项,新增 5 个新项(sortOrder 1→5) +- `ProductDO.tags` 字段**仍然是 `List`**(JSON 数组,DB 列类型 JSON,不动) +- `ProductBasicSaveReqVO.tags` **仍然是 `List`**,**没加 `@Size(max=1)` 校验** + - 原因:老产品 tags 已有多值(图示摄影/露营/亲子),加硬校验会直接卡死这些产品的保存 +- `MpProduct*RespVO.tags` **仍然是 `List`** +- 没有 DDL 变更 + +### 接口签名不变 + +| Method | Path | 说明 | +|---|---|---| +| POST | `/admin/product/item/basic` | `tags: string[]` 字段类型完全不变 | +| GET | `/admin/product/item/detail` | 同上 | +| GET | `/mp/product/list` / `/mp/product/detail` | 同上 | +| GET | `/admin/dict/data/product_tag` | 现在返回 5 个新字典项 | +| GET | `/dict/all`(公开)| 其中 `product_tag` 类目返回 5 个新字典项 | + +--- + +## 前端改造(要做) + +### 产品编辑页 Step1 —— 产品标签输入控件 + +- 从**多选 chip** 改为**单选下拉** (Select / Radio Group / 单选 chip 二选一,UI 同学定) +- 选项数据源:`/admin/dict/all` → `dictType === 'product_tag'` → `dataList` 5 项 +- **提交格式仍然是数组**: + ```js + // 保持兼容后端 List 字段 + saveReqVO.tags = selected ? [selected] : [] + ``` + 不要直接传字符串 —— 后端仍按数组接 +- **后端没加 max=1 硬校验**,所以就算前端误传 ≥2 个也不会报错,但业务上就按单选出 + +### 老数据兼容(关键) + +现有产品 tags 里可能存了老字典值(摄影/露营/亲子/研学/城记),编辑页打开时: + +- **不要把 `tags` 里不在新字典 5 项里的值过滤掉** —— 这会悄悄丢数据 +- **建议展示**:老 tag 值按字符串原样显示,加个灰色提示 "已下架标签,请重新选择" +- 用户保存时前端强制用户从 5 个新值中选一个(单选默认行为) + +### `/dict/all` 的 `product_tag` 新响应 + +```jsonc +{ + "dictType": "product_tag", + "dictName": "产品标签", + "dataList": [ + { "dictValue": "热内", "dictLabel": "热内", "icon": null, "sort": 1 }, + { "dictValue": "新品", "dictLabel": "新品", "icon": null, "sort": 2 }, + { "dictValue": "限定", "dictLabel": "限定", "icon": null, "sort": 3 }, + { "dictValue": "硬核", "dictLabel": "硬核", "icon": null, "sort": 4 }, + { "dictValue": "治愈", "dictLabel": "治愈", "icon": null, "sort": 5 } + ] +} +``` + +- 注意 `dictValue` 和 `dictLabel` 都是中文(和老字典保持一致,不是英文 code) +- `icon` 字段是昨天新加的(见 [2026-04-20_dict-icon-field.md](./2026-04-20_dict-icon-field.md)),暂时都是 null,产品侧后续可配图标 + +--- + +## 数据迁移 + +**不迁移**。 + +- 老产品 tags JSON 里存的老字典值字符串**保留**,编辑时按上面"老数据兼容"逻辑展示 +- 用户在下次编辑该产品时,按单选从新 5 项里选一个,保存后老值就被覆盖了 +- 小程序端列表/详情展示老 tag 时原样显示(即使字典里没这个值) + +--- + +## 验证 + +- ✅ 测试环境 `/admin/dict/data/product_tag` 返回 5 项(热内/新品/限定/硬核/治愈) +- ✅ `/dict/all` 公开接口 `product_tag` 也是 5 项新值 +- ✅ DB `sys_dict_data WHERE dict_type='product_tag'` 5 行无残留老值 +- ⏳ 生产环境字典同步:由 wx 手动在正式库执行相同的删 5 加 5(后端不出包,不走部署)