feat: admin 列表加 productLineId 参数自动 resolve seasons (PR #2281 / Issue #2278)

紧接 #2229/#2232/#2269 admin 列表季节系列。前端从产品上下文只有 productLineId,
让后端 Feign resolve productLine.seasons[0] 自动注入 query.seasons, 走现有 #2229
切换链路。前端只需多传 productLineId, 不必再算 seasons[0]。

5 场景兼容: 只传 seasons/只传 productLineId/两个都传(seasons 优先)/都不传(向前兼容)/
Feign 异常 fail-open 降级走本体不 500。

测试服三态对比 PASS:
- 无参 → oss 本体
- productLineId=autumn 产品线 → unsplash 秋色 + 秋色画廊
- productLineId=summer 产品线 → unsplash 夏景 + 自驾天堂

notify @mmg (前端只需多传 productLineId)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
这个提交包含在:
API Changelog Bot 2026-05-14 17:14:39 +08:00
父节点 f2bcc3a5e4
当前提交 e79c5dee2b

查看文件

@ -0,0 +1,119 @@
# resource: admin 列表加 productLineId 参数自动 resolve seasons (前端少做一步)
> **服务**: hl-product-service-v2 (端口 8083) + hl-resource-service (端口 8082)
> **PR**: #2281
> **Issue**: #2278
> **日期**: 2026-05-14
> **影响范围**: 管理端 产品设计「补充信息 → 产品卖点」节点弹窗(景区/游玩项目列表)
---
## ⚠️ 关键变化
紧接 #2229/#2232/#2269 admin 列表季节系列。
**之前**: 前端调 /admin/scenic/spots /admin/activity/items 必须传 seasons 参数才能切换 cover/seasonHighlights, 但产品上下文只有 productLineId, 前端要先 GET 产品线接口拿 seasons 再传, **多一步**
**现在**: 后端接受 productLineId, 自动 Feign resolve productLine.seasons 注入 query.seasons → 走现有 #2229 切换链路。**前端只多传一个 ID, 不必再算 seasons[0]**。
---
## 链路
```
/admin/scenic/spots?productLineId=X (无 seasons)
→ ScenicSpotService.listSpots 开头 Feign 调 hl-product-v2 GET /internal/product-line/X/seasons
→ 拿到 List<String> → 注入 query.setSeasons(...)
→ 走 PR #2229 现有 seasons[0] 切换 cover/seasonHighlights 路径
```
同款给 /admin/activity/items。
---
## 接口变化
### admin 列表加 productLineId 参数
| 接口 | 方法 | 路径 | 变更 |
|---|---|---|---|
| 景区列表 | GET | `/admin/scenic/spots` | 入参加 `productLineId: Long` |
| 游玩项目列表 | GET | `/admin/activity/items` | 入参加 `productLineId: Long` |
### internal 新加
| 接口 | 方法 | 路径 | 说明 |
|---|---|---|---|
| 产品线 seasons | GET | `/internal/product-line/{lineId}/seasons` | 供 resource-service Feign 调用, 返 `Result<List<String>>` |
---
## 入参 5 场景兼容性
| 场景 | 行为 |
|------|------|
| 只传 seasons | 旧路径不调 Feign (PR #2229 原行为) |
| 只传 productLineId | Feign 注入 seasons → 走 PR #2229 路径 |
| 两个都传 | seasons 显式优先 (不调 Feign) |
| 都不传 | 走本体 cover + seasonHighlights=null (向前兼容) |
| productLineId 不存在 / Feign 异常 | 静默降级走本体 (fail-open, 不 500) |
---
## 前端推荐用法 (@mmg)
```ts
// 弹窗 fetch 时多传 productLineId 即可, 不必再算 seasons:
const productLineId = currentProduct.lineId; // 编辑产品上下文已有
fetch(`/admin/scenic/spots?keyword=${kw}&pageSize=20&productLineId=${productLineId}`);
fetch(`/admin/activity/items?keyword=${kw}&pageSize=20&productLineId=${productLineId}`);
```
不必再调产品线接口拿 seasons 数组。
---
## 测试服三态对比已验证 (中俄边境公路 scenicId=3001000000000000019)
| 场景 | total | coverUrl | seasonHighlights |
|---|---|---|---|
| 无参 | 66 | `oss.aliyuncs.com/...62943d9b.jpg` (本体) | null |
| productLineId=2045004175602868226 (autumn 产品线) | 18 | `unsplash.com/photo-1508739773434-c26b3d09e071` | "秋色画廊·边境公路,稻穗收割,亲子自驾季" |
| productLineId=2047215799055118338 (summer 产品线) | 18 | `unsplash.com/photo-1472214103451-9374bd1c798e` | "中国最美边境公路,草原绿浪铺天,自驾天堂" |
| productLineId=9999999... (不存在) | 66 | 本体 (Feign fallback) | null |
✓ 三态切换符合预期, fail-open 降级正常。
---
## 不影响范围
- **仅影响**: admin 景区/游玩项目列表入参 + 后端装配
- **零影响**: 小程序 C 端、订单、价格、admin 详情、其他列表
- **向前兼容**: 前端没改之前(只传 seasons 或都不传)行为不变
---
## 风险评估
- 双向 Feign 已确认非循环: resource → product-v2 (本 PR) + product-v2 → resource (#2263 batchDetails) 都是单向
- product-v2 internal endpoint 只 SELECT product_line.seasons 单字段, 不会反向调 resource
- Feign fail-open: productLineId 不存在 / Feign 异常时静默降级, 列表不 500
---
## 相关历史 PR
| PR | Issue | 说明 |
|----|-------|------|
| #2229 | #2227 | 景区列表加 seasons 字段 + 封面切换 |
| #2234 | #2232 | 游玩项目同款 |
| #2269 | #2267 | 列表加 seasonHighlights 字段 |
| **#2281** | **#2278** | **本 PR**: 加 productLineId 自动 resolve seasons |
---
## 相关文档
- Issue: [wx/HL#2278](https://git.1814.love:8443/wx/HL/issues/2278)
- PR: [wx/HL#2281](https://git.1814.love:8443/wx/HL/pulls/2281)