---
date: 2026-05-15
type: frontend-feature
module: admin-product-v2-itinerary-picker
priority: medium
backend_pr: "#2335"
backend_issue: "#2334"
supersedes:
  - "14_frontend_feature_admin_scenic-season-filter-and-tags.md"
  - "14_frontend_feature_admin_activity-season-filter-and-tags.md"
notify: ["@mmg"]
status: tested
---

# 资源 picker 去掉按产品线季节过滤,VO.seasons 改为产品/资源交集

## 业务变更

产品设计选节点(从资源库添加活动)弹窗,**不再按当前产品线的 seasons 过滤资源列表**。改为:

1. **列表全量** — 景区(scenic)、游玩项目(activity)两个 tab 返回全部资源,不因 productLineId 减少
2. **季节标签 = 交集** — 资源 VO 的 `seasons` 字段从 "资源全部支持季节" 改为 "产品线季节 ∩ 资源季节"
3. **封面/亮点保留** — `coverUrl` 与 `seasonHighlights` 仍按产品线 seasons[0] 切换

## 后端已就位 (PR #2335 已合并 dev,已部署测试服并真测)

### 行为变更对照

| 项 | 旧 (PR #2278) | 新 (PR #2335) |
|----|---------------|---------------|
| `GET /admin/scenic/spots?productLineId=X` 列表 total | 按产品线 seasons 过滤后的子集 | **全量**(与不传 productLineId 一致) |
| `GET /admin/activity/items?productLineId=X` 列表 total | 按产品线 seasons 过滤后的子集 | **全量**(与不传 productLineId 一致) |
| VO.`seasons` 字段 | 资源全部支持的季节(如 `["spring","summer","autumn"]`) | 产品线 ∩ 资源(如产品线=`[summer]` ∩ 资源=`[spring,summer,autumn]` → `["summer"]`) |
| VO.`coverUrl` 季节封面切换 | 同新版 | **保留**:仍按产品线 seasons[0] 切换 |
| VO.`seasonHighlights` 季节亮点 | 同新版 | **保留**:仍按产品线 seasons[0] 切换 |

### 测试服真测结果

| 场景 | 现象 |
|------|------|
| 不传 productLineId,scenic 列表 | total=66 |
| 传 productLineId(seasons=[summer]),scenic 列表 | total=**66**(未减少),VO.seasons=`["summer"]` |
| 不传 productLineId,activity 列表 | total=56 |
| 传 productLineId(seasons=[summer]),activity 列表 | total=**56**(未减少),VO.seasons=`[]`(资源未配 summer) |
| 传不存在的 productLineId(Feign 反查失败) | total=56,VO.seasons 回落资源全集(如 `["spring","autumn"]`) |

### 降级路径

- Feign 调 product-v2 失败 → `query.seasons` 不被注入 → VO.seasons 回落资源全集
- 产品线 seasons 为空 → 同上

## 前端实现要点

### 列表渲染

**透传 `productLineId` 的请求保持不变**(前端无需调整接口调用):

```js
await api.get(`/admin/scenic/spots?productLineId=${productLineId}&pageSize=20`)
await api.get(`/admin/activity/items?productLineId=${productLineId}&pageSize=20`)
```

### 季节标签渲染

VO `seasons` 字段**就是交集**,前端**直接渲染**即可,不需要在前端再做过滤:

```js
// VO.seasons 已经是后端算好的产品线 ∩ 资源,不要再做客户端过滤
const visibleSeasons = vo.seasons || []

// 4 色保持不变:
// spring → #67C23A / summer → #409EFF / autumn → #E6A23C / winter → #909399
```

> 如资源不支持任何产品线季节,`vo.seasons = []`,**不渲染任何季节标签**。

### 封面/亮点

`coverUrl` 与 `seasonHighlights` 行为**不变**,继续按现有方式渲染。

### 行程节点卡片(已选节点)

`InternalProductDetailVO.NodeItem.seasons` 字段保留;**节点卡片渲染同样规则** — 用后端透传的 seasons(已是交集)直接渲染。

## 涉及前端文件 (仅供参考定位)

- 弹窗组件: `D:\work2\hl-ui\src\views\product-v2\` 行程编辑器子组件
- 季节标签组件: 14_ 的实现可复用,无需调整(VO 字段含义虽变,但前端只是"渲染 vo.seasons",不感知)

## 关联

- 推翻 (supersedes): 05-14 的两份 changelog
  - `14_frontend_feature_admin_scenic-season-filter-and-tags.md`(后端 #2229)
  - `14_frontend_feature_admin_activity-season-filter-and-tags.md`(后端 #2234)
- 后端 PR #2229 / #2234 / #2278 **不回滚**,新增的 `scenic_season` / `activity_season` 子表 / VO 字段 / Feign 反查 全部保留
- 本次反转: backend issue #2334 / PR #2335

## 测试服环境

- 接口:`https://api.test.1814.love:9443/admin/scenic/spots`、`/admin/activity/items`
- admin token:测试服 admin / Admin@123456 登录 `/admin/auth/login`
- 测试用产品线 ID(seasons=[summer]):`2053279457388494849`
