新增: 产品标签改单选 + 字典值替换为 热内/新品/限定/硬核/治愈(Issue #1001)
这个提交包含在:
父节点
f0863e0267
当前提交
ddd7a53dbb
@ -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<String>`**(JSON 数组,DB 列类型 JSON,不动)
|
||||||
|
- `ProductBasicSaveReqVO.tags` **仍然是 `List<String>`**,**没加 `@Size(max=1)` 校验**
|
||||||
|
- 原因:老产品 tags 已有多值(图示摄影/露营/亲子),加硬校验会直接卡死这些产品的保存
|
||||||
|
- `MpProduct*RespVO.tags` **仍然是 `List<String>`**
|
||||||
|
- 没有 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<String> 字段
|
||||||
|
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(后端不出包,不走部署)
|
||||||
正在加载...
x
在新工单中引用
屏蔽一个用户