# feat(mp/user/product-v2): /mp/banner/active 主题 (PRODUCT_LINE) 补 description + tags 字段

> **仓库**: HL (后端 hl-mp-service + hl-user-service + hl-product-service-v2 + hl-common-feign)
> **关联 PR/Issue**: PR #2938 + PR #2941, Closes #2936
> **日期**: 2026-05-23
> **影响范围**: `/mp/banner/active` 响应新增 `linkTarget` 嵌套对象,内含 description / tags
> **接收方**: mmg (前端)
> **前端**: **需要消费新字段** — banner.linkTarget.description / banner.linkTarget.tags 渲染主题轮播卡片

---

## 🎯 业务背景

呼籁 admin 字典里 `banner_link_type=PRODUCT_LINE` 标签是「主题」,product_line 表面向 C 端就是"主题"概念。

之前 banner 绑定主题 (link_type=PRODUCT_LINE) 时 mp 端拿不到主题的 description 和 tags,前端无法在轮播图卡片展示。

## 改动 (2 个 PR)

### PR #2938 — user-service + product-v2 字段贯通

- `InternalProductLineSimpleVO` (product-v2 + user-service 镜像) 加 `tags: List<String>` 字段
- `BannerLinkTargetVO` 加 `description + tags`
- `ProductLineMapper.selectSimpleInfoByIds` `.select()` 列表补 tags 列
- `ProductLineService.selectSimpleByIds` builder 补 `.tags(line.getTags())`
- `BannerService.enrichLinkTarget` PRODUCT_LINE 分支补 `.description(...).tags(...)`

### PR #2941 — mp 端 VO 补 linkTarget 嵌套

- `MpBannerVO` 新增 `linkTarget` 字段(此前精简 VO 没这字段,Feign 反序列化时下游 BannerVO 的 linkTarget 被 Jackson 自动丢弃)
- `MpHomeBannerLinkTargetVO` 加 `description + tags` 字段,跟 user-service `BannerLinkTargetVO` 对齐

## API 行为变化

### `GET /mp/banner/active`

每个 banner 现在多一个 `linkTarget` 嵌套对象:

**PRODUCT_LINE (主题) 场景**:

```json
{
  "id": 5,
  "title": "额吉的故乡",
  "linkType": "PRODUCT_LINE",
  "linkId": "2045622604613529601",
  "linkTarget": {
    "type": "PRODUCT_LINE",
    "id": "2045622604613529601",
    "name": "额吉的故乡v11",
    "subtitle": null,
    "coverImageUrl": "https://...",
    "productType": "CORE",
    "seasons": ["winter"],
    "lineId": null,
    "description": "公司的风格的",   // 新字段
    "tags": ["限定"]                 // 新字段
  },
  ...
}
```

**PRODUCT 场景**:

```json
{
  "linkType": "PRODUCT",
  "linkTarget": {
    "type": "PRODUCT",
    "name": "...",
    "subtitle": "...",
    "coverImageUrl": "...",
    "productType": "CORE",
    "seasons": [...],
    "lineId": ...,
    "description": null,   // PRODUCT 不返,前端可忽略
    "tags": null
  }
}
```

**其他 linkType / linkId 无效**: `linkTarget = null`

---

## 🚨 前端需要做的事

### 1. 读取新字段

```ts
const banner = response.data[0];
if (banner.linkType === 'PRODUCT_LINE' && banner.linkTarget) {
  const desc = banner.linkTarget.description;  // 主题描述
  const tags = banner.linkTarget.tags;          // 主题标签数组
  const seasons = banner.linkTarget.seasons;    // 季节数组 (本来就有)
}
```

### 2. 兼容性

- 旧前端代码不读 linkTarget 的不受影响 (顶层字段 id/title/imageUrl/linkType 等保持不变)
- linkTarget 可能为 null (其他 linkType 或目标已删除/下架),需做 null 守护
- description 和 tags 仅 PRODUCT_LINE 场景有值,PRODUCT 场景为 null

### 3. 自查

```bash
grep -rE "banner.linkTarget|banner\\.description|banner\\.tags" hl-ui/src
```

---

## 数据流

```
product_line (DB)
  ↓ ProductLineMapper.selectSimpleInfoByIds (含 tags)
  ↓ ProductLineService.selectSimpleByIds (含 description + tags)
  ↓ InternalProductLineSimpleVO (含 description + tags)
  ↓ user-service BannerService.enrichLinkTarget (PRODUCT_LINE 分支)
  ↓ user-service BannerLinkTargetVO (含 description + tags)
  ↓ Feign /internal/mp/banner/active 返回 BannerVO
  ↓ Jackson 反序列化到 mp MpBannerVO (PR #2941 新增 linkTarget 字段)
  ↓ MpBannerVO.linkTarget 类型 MpHomeBannerLinkTargetVO (PR #2941 新增 description + tags)
  ↓ /mp/banner/active 响应给前端
```

---

## 测试服真测记录

部署 user + product-v2 + mp (rolling-deploy 2026-05-23 10:38) 后真测:

```bash
curl https://api.test.1814.love:9443/mp/banner/active
```

| banner | linkType | description | tags |
|---|---|---|---|
| #2033821591988748290 | PRODUCT | null ✅ | null ✅ |
| #5 (额吉的故乡) | PRODUCT_LINE | '公司的风格的' ✅ | ['限定'] ✅ |

单测:
- BannerServiceTest 32 全绿
- ProductLine*Test 80 全绿
- mp Banner + Home 20 全绿

---

## 联系人

后端: wx (呼籁旅行)
前端: mmg

如有疑问可在 [#2936](https://git.1814.love:8443/wx/HL/issues/2936) 评论区留言。
