# 装备建议条目 EquipmentItem 补 icon + color 字段

**日期**: 2026-04-23
**PR**: #1273 (Closes #1272)
**服务**: hl-product-service-v2 / hl-order-service-v2 / hl-mp-service
**类型**: feat（新增字段，向后兼容）

---

## 背景

PR #1259 上线后前端实现装备建议条目 UI，发现需要后端结构化传图标标识和颜色，不希望纯靠前端按 text 关键词猜图标。本次补字段。

---

## 字段扩展

### EquipmentItem 结构

```typescript
interface EquipmentItem {
  text:   string;   // 必填，1-50 字
  icon?:  string;   // 可选，图标 key，≤64 字
  color?: string;   // 可选，颜色值，≤16 字（建议 #RRGGBB）
}
```

### 约束总表（JSR-303 现已生效）

| 字段 | 必填 | 长度 | 错误消息 |
|------|------|------|----------|
| text | ✅ | 1-50 字 | `equipmentList[N].text: 装备文案不能为空` / `装备文案长度需在 1-50 字符之间` |
| icon | ❌ | ≤64 字 | `equipmentList[N].icon: 图标标识长度不能超过 64 字符` |
| color | ❌ | ≤16 字 | `equipmentList[N].color: 颜色值长度不能超过 16 字符` |

**color 格式**：后端不硬校验 `#RRGGBB` 格式，前端可传任意 ≤16 字符串（如 `red` / `#FFA726` / `rgb(255,167,38)`）。推荐 `#RRGGBB` 以便 admin/mp 渲染一致。

---

## 影响接口（5 处响应 + 1 处请求）

| 接口 | 变化 |
|------|------|
| `PUT /admin/product/item/{id}/supplement` | 请求 `equipmentList[].icon` / `[].color` 可选 |
| `GET /admin/product/item/{id}` | 响应 `supplement.equipmentList[].icon/color` 新增 |
| `GET /mp/product/{id}` | 响应 `equipmentList[].icon/color` 新增 |
| `GET /mp/order/{id}` | 响应 `equipmentList[].icon/color` 新增（订单快照固化） |
| `GET /mp/order/{orderId}/supplies-checklist` | 响应 `equipmentList[].icon/color` 新增 |

---

## 示例

### 保存（带图标和颜色）

```http
PUT /admin/product/item/123/supplement
{
  "equipmentList": [
    {"text": "防晒霜 SPF50+", "icon": "sunscreen", "color": "#FFA726"},
    {"text": "长袖防晒衣", "icon": "shirt"},
    {"text": "运动鞋"}
  ]
}
→ 200 {"code":200, "success":true}
```

### MP 详情回显

```json
{
  "equipmentList": [
    {"text":"防晒霜 SPF50+", "icon":"sunscreen", "color":"#FFA726"},
    {"text":"长袖防晒衣", "icon":"shirt", "color":null},
    {"text":"运动鞋",      "icon":null,      "color":null}
  ]
}
```

### 超限 400

```http
PUT .../supplement
{"equipmentList":[{"text":"x","icon":"aaaa...(65字)"}]}
→ 400 {"code":400, "message":"equipmentList[0].icon: 图标标识长度不能超过 64 字符"}
```

---

## 前端适配建议

### 1. icon 字段
**推荐约定**：前后端商量一份 iconKey 表（如 `sunscreen/shirt/jacket/shoe/bug/hat/sunglasses/water-bottle/umbrella/camera/headlamp/...`），前端内置图标库按 iconKey 查表渲染。

**降级逻辑**：
- icon 有值 → 前端按 key 查图标库渲染
- icon 为 null → 前端按 text 关键词硬匹配图标（PR #1259 方案）
- 都没匹配上 → 显示默认占位图标

### 2. color 字段
- color 有值 → 应用到图标颜色/文字颜色/背景色等
- color 为 null → 使用主题默认色

### 3. admin 编辑器
- 图标选择：内置 iconKey 下拉选择器（下拉源是前端约定的图标库）
- 颜色选择：内置色板选择器（el-color-picker 等）
- 两字段都可留空（提交时对应字段不传或传 null）

---

## 向后兼容

- 现有调用方不传 icon/color：后端接受，DB 存 JSON 不含这两个键
- 老订单快照：JSON 内条目没有 icon/color 键 → 反序列化后 EquipmentItem.icon/color = null
- **前端可直接升级，旧数据 null 兼容性零风险**

---

## 验证

测试服网关已 curl 6 场景全过：
- 混合保存（含 icon+color+只 text）→ 200
- Admin 详情回显 → 3 条字段精确
- MP 详情 icon/color 透传 → 正确
- icon 超 64 字 → 400
- color 超 16 字 → 400
- 老数据 null → 自然降级，无回归

---

## 部署

测试服已部署完毕:
- product-v2 task `f7952e0c` success
- order-v2 task `e94c50cd` success
- mp-service task `5b005209` success

**正式环境部署**：无需 DDL（equipment_list 列已在 PR #1259 DDL 时加，新字段存在同一 JSON 列内）。
