# 装备建议字段改造 — 条目列表结构化 **日期**: 2026-04-23 **PR**: #1259 (Closes #1244) **服务**: hl-product-service-v2 / hl-order-service-v2 / hl-mp-service **类型**: feat(新增字段,向后兼容) --- ## 背景 管理后台「产品编辑 → 补充信息 → 预订须知 → 装备建议」从纯文本 textarea 改为**条目列表**形式。小程序端目标视觉:左图标 + 右文案,一行一条。 **图标责任**:后端只存文本,图标由前端自行实现(硬编码关键词匹配 / 内置图标库 / 顺序样式),后端不提供图标字段。 --- ## 字段新增契约 ### 数据结构 ```typescript interface EquipmentItem { text: string; // 文案,必填,1-50 字 } ``` - **条目数上限**: 20 - **单条 text 长度**: 1-50 字(非空非空白) - **text 必填非空** - 超限后端返 `code=400 message="装备建议不合法:..."` ### 旧字段(保留,降级兜底) `equipmentAdvice: string`(富文本 HTML 字符串)继续返回,**不删**。 ### 降级三态(前端必须实现) | equipmentList | equipmentAdvice | 前端行为 | |---------------|-----------------|---------| | 非空数组 | 任意 | 渲染条目列表(图标前端自行匹配) | | null / 空数组 | 非空字符串 | 渲染纯文本(可能含 HTML) | | null / 空数组 | null / 空 | 不渲染"装备建议"模块 | --- ## 涉及接口(5 处响应体变化 + 1 处请求体) ### 1. Admin 保存 `POST /admin/product/supplement/save` **请求体新增**: ```json { "productId": 123, "equipmentList": [ {"text": "防晒霜 SPF50+"}, {"text": "长袖防晒衣"}, {"text": "薄外套(早晚温差15°C+)"} ] } ``` **请求体删除**:`equipmentAdvice` 字段从 `ProductSupplementSaveReqVO` 彻底移除(老 UI 已无入口)。 ### 2. Admin 详情 `GET /admin/product/{id}` → `SupplementVO` **响应新增**: ```json { "supplement": { "equipmentAdvice": "

老富文本旧字段

", "equipmentList": [{"text": "防晒霜 SPF50+"}] } } ``` ### 3. MP 产品详情 `GET /mp/product/{id}` **响应新增**: ```json { "equipmentAdvice": "

...

", "equipmentList": [{"text": "防晒霜 SPF50+"}] } ``` ### 4. 订单详情 `GET /mp/order/{id}` **响应新增** `OrderDetailVO.equipmentList`(下单时固化自产品快照): ```json { "equipmentAdvice": "...", "equipmentList": [{"text": "..."}] } ``` ### 5. 供应清单 `GET /mp/order/{orderId}/supplies-checklist` **响应新增** `MpSuppliesChecklistRespVO.equipmentList`: ```json { "orderId": 1001, "categories": [...], "equipmentAdvice": "...", "equipmentList": [{"text": "..."}] } ``` --- ## 向后兼容说明 - **老订单快照**:2026-04-23 之前下单的订单,产品快照 JSON 中不含 `equipmentList` 键 → 后端 `path("equipmentList").isArray()` 返 false → `equipmentList` 返 null → 前端按三态降级兜底渲染 `equipmentAdvice` - **老产品**:未重新保存过的产品 DB 列 `equipment_list` 为 null → 接口返 null - **零破坏性**:所有响应字段只新增不删除,前端不升级也不会报错 --- ## 前端实现要点 1. **管理端**: - 移除原 `equipmentAdvice` 富文本输入框 - 新增"+ 新增装备"条目列表 UI(一行一条,单条文案输入 + 删除按钮) - 保存时只传 `equipmentList: List<{text}>`,不传 `equipmentAdvice` - 本地做条目数 ≤20 / 单条 1-50 字前置校验,避免 400 2. **小程序端**: - 实现三态降级逻辑(见上表) - 图标硬编码或按文案关键词匹配(例: "防晒" → 太阳图标, "外套" → 衣服图标, "鞋" → 鞋图标) - 一行一条布局:` ` 3. **订单详情/供应清单**:老订单自然走 `equipmentAdvice` 纯文本分支,新订单渲染 `equipmentList` --- ## 硬约束提醒 - **不要传空字符串 text**:后端会 400(`@NotBlank`) - **不要传 >20 条**:后端会 400(`@Size(max=20)`) - **不要传 >50 字 text**:后端会 400(`@Size(max=50)`) - **前端可以传空数组 `[]`** 表示"清空装备建议",这是合法意图 --- ## 代码位置参考(前端调试用) - Admin VO: `hl-product-service-v2/.../vo/admin/ProductSupplementSaveReqVO.java` - Admin 详情: `hl-product-service-v2/.../vo/admin/ProductDetailRespVO.SupplementVO` - MP VO: `hl-product-service-v2/.../vo/mp/MpProductDetailRespVO` - 订单详情: `hl-order-service-v2/.../controller/vo/OrderDetailVO` - 供应清单: `hl-order-service-v2/.../internal/vo/MpSuppliesChecklistRespVO` --- ## 部署说明 测试服已执行 DDL(本次部署前必须先跑): ```sql ALTER TABLE product_supplement ADD COLUMN equipment_list JSON DEFAULT NULL COMMENT '装备建议条目列表([{text}]),优先于 equipment_advice'; ``` 正式环境上线前同步 DDL。