父节点
546d22454a
当前提交
698a3f03ed
@ -0,0 +1,120 @@
|
||||
---
|
||||
date: 2026-05-14
|
||||
type: frontend-feature
|
||||
module: admin-product-v2-itinerary-activity-picker
|
||||
priority: medium
|
||||
backend_pr: "#2234"
|
||||
backend_issue: "#2232"
|
||||
related: "14_frontend_feature_admin_scenic-season-filter-and-tags.md"
|
||||
notify: ["@mmg"]
|
||||
status: pending
|
||||
---
|
||||
|
||||
# 游玩项目按产品线季节过滤 + 节点展示季节标签
|
||||
|
||||
## 需求
|
||||
|
||||
紧接景区 (#2227 / PR #2229),「从资源库添加活动」弹窗第二个 tab「**游玩项目**」也要按产品线 `seasons` 过滤 + 缩略图按季节切换 + 节点季节标签。**行为与景区完全对齐**。
|
||||
|
||||
## 后端已就位 (PR #2234 已合并并部署测试服)
|
||||
|
||||
### 数据基础
|
||||
|
||||
**新建** `activity_season` 子表(Flyway V20260514_001,字段对照 `scenic_season` 复刻)。运营进后台逐个游玩项目补配季节数据后生效;未配的游玩项目 `vo.seasons` 返 `[]`。
|
||||
|
||||
老 `activity.best_season` 自由文本字段保留不动(老 UI 兼容),**不**自动迁移到新结构化子表。
|
||||
|
||||
### 接口变更
|
||||
|
||||
#### `GET /admin/activity/items` — 游玩项目列表
|
||||
|
||||
**新增 query 参数**(与景区接口同款):
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `seasons` | `List<String>` | 否 | 多选 OR 过滤,枚举 `spring/summer/autumn/winter`。传任一交集即返回。空/不传 = 不过滤 |
|
||||
|
||||
请求格式(数组多参):
|
||||
```http
|
||||
GET /admin/activity/items?seasons=spring&seasons=autumn&pageSize=20
|
||||
```
|
||||
|
||||
**`ActivityListVO` 新增字段:**
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `seasons` | `List<String>` | 该游玩项目在 `activity_season` 配置的全部季节(distinct,枚举 `spring/summer/autumn/winter`)。**节点标签直接读这个**。 |
|
||||
|
||||
> ⚠️ **已有的 `coverUrl` 字段含义变更**:当 query 含 `seasons` 时,`coverUrl` 返回 **query.seasons[0] 对应的 `activity_season.cover_material_id`** 物化 URL;该季节未配/物化失败回落到主表 `coverMaterialId`。无 query.seasons 时维持主表 cover(行为不变)。
|
||||
|
||||
#### 真实响应示例
|
||||
|
||||
**请求**: `GET /admin/activity/items?pageSize=2`
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "成功",
|
||||
"data": {
|
||||
"total": 56,
|
||||
"records": [
|
||||
{
|
||||
"activityId": 3002000000000000000,
|
||||
"name": "满洲里草原篝火晚会",
|
||||
"subtitle": "...",
|
||||
"categoryCode": "...",
|
||||
"billingType": "...",
|
||||
"city": "...",
|
||||
"coverUrl": "https://hlgl-test.oss-cn-beijing.aliyuncs.com/test/...",
|
||||
"seasons": [],
|
||||
"tags": [...],
|
||||
"longitude": ...,
|
||||
"latitude": ...
|
||||
}
|
||||
]
|
||||
},
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
> 当前 `activity_season` 表是空的(刚建),所有游玩项目 `seasons` 都返 `[]`。**运营录数据后**,过滤会立即生效;封面切换也立即生效,行为与景区完全一致。
|
||||
|
||||
## 前端实现建议
|
||||
|
||||
### 弹窗「游玩项目」tab
|
||||
|
||||
参考景区 tab 的实现完全对照:
|
||||
|
||||
1. 弹窗打开时调列表接口透传产品线 `seasons`:
|
||||
```js
|
||||
const params = new URLSearchParams()
|
||||
productLineSeasons.forEach(s => params.append('seasons', s))
|
||||
await api.get(`/admin/activity/items?${params}&pageSize=20`)
|
||||
```
|
||||
2. 列表行的**缩略图**直接用 VO 返回的 `coverUrl`(后端已切换好)
|
||||
3. 列表行的**季节标签**渲染 `vo.seasons` 数组,**4 色与景区一致**:
|
||||
- `spring` → 春绿 `#67C23A`
|
||||
- `summer` → 夏蓝 `#409EFF`
|
||||
- `autumn` → 秋橙 `#E6A23C`
|
||||
- `winter` → 冬蓝灰 `#909399`
|
||||
|
||||
### 已选节点(行程卡片上)
|
||||
|
||||
行程节点 ACTIVITY 类型的 `InternalProductDetailVO.NodeItem.seasons` 已透传 — 在游玩项目节点卡片上渲染同款季节标签(可多个)。**与景区节点同款组件即可复用**。
|
||||
|
||||
### 兜底
|
||||
|
||||
- 老游玩项目没配 `activity_season` 的,`vo.seasons` 返 `[]`,前端不渲染标签即可
|
||||
- `coverUrl` 任何时候都不会因为新逻辑变 null(已做回落)
|
||||
|
||||
## 工单 & PR
|
||||
|
||||
- Backend Issue: #2232
|
||||
- Backend PR: #2234 (squash merged dev,已部署测试服)
|
||||
- 测试服真测通过: 基线 total=56 ✅ / VO seasons 字段 ✅ / seasons=autumn 过滤 total=0(数据空) / 反例 seasons=xxx 总=0 ✅ / coverUrl 物化 ✅
|
||||
|
||||
## 关联
|
||||
|
||||
景区同款实施: `14_frontend_feature_admin_scenic-season-filter-and-tags.md`(PR #2229 / Issue #2227)
|
||||
|
||||
弹窗的剩余两个 tab「餐厅」「服务」**暂未实施季节过滤** — 业务侧确认需要再开工单。
|
||||
正在加载...
x
在新工单中引用
屏蔽一个用户