156 行
5.8 KiB
Markdown
156 行
5.8 KiB
Markdown
# 前端 Bug 通知 — Step2 行程编排「住宿安排」档位显示错乱
|
||
|
||
- **日期**: 2026-04-17
|
||
- **类型**: 前端 Bug 修复指南(**不涉及后端代码改动,后端无需重启**)
|
||
- **涉及端**: 管理后台 hl-ui(产品编辑页 Step2)
|
||
- **后端服务**: hl-product-service-v2(**仅作接口说明,代码不变**)
|
||
|
||
---
|
||
|
||
## 一、问题描述
|
||
|
||
在产品编辑页 Step2「行程编排」→「住宿安排」tab 中:
|
||
|
||
- **预期**:显示 5 个档位 tab,名称依次为 `经济 / 舒适 / 轻奢 / 高端 / 豪华`(与 Step1 基础信息配置的 5 档一致)
|
||
- **实际**:只显示 **2 个档位 tab**,且名称为 `经奢 / 高端` —— 其中 **"经奢" 这个词在后端任何地方都不存在**
|
||
|
||
**复现路径**:
|
||
- 环境:测试服 `192.168.100.236`
|
||
- 产品 ID:`2045018534152478721`
|
||
- 页面:产品编辑 → Step2 行程编排 → 住宿安排
|
||
|
||
---
|
||
|
||
## 二、根因分析(后端已核实)
|
||
|
||
### 1. 后端返回的数据是完整正确的
|
||
|
||
调用 `GET /admin/product/item/{id}` 返回 `data.tiers` **完整包含 5 档**,每档都有 `tierSeq` / `tierName` / `tierDescription` 字段,数据无问题。
|
||
|
||
### 2. "经奢" 不是后端字典
|
||
|
||
在整个后端项目(包括 schema.sql、字典表、常量、VO、代码注释)`grep "经奢"` **零匹配**。该字符串**必然是前端代码内写死的**。
|
||
|
||
### 3. itinerary 内 hotels 只有部分档位是业务正常
|
||
|
||
后端 `data.itinerary[*].hotels` 里 `tierSeq` 只出现 `1` 和 `2`,是**用户在 Step2 只给档位 1、2 录入了酒店**的真实业务状态(业务允许不录满全部档位,不是 bug)。
|
||
|
||
前端**不应该**从 `itinerary[*].hotels` 反推档位 tab 列表 —— 这会导致:未录入酒店的档位 tab 直接消失;而一旦索引/字段错位,还会出现 "经奢" 这种幻觉档位名。
|
||
|
||
---
|
||
|
||
## 三、后端接口数据结构(示例)
|
||
|
||
接口:`GET /admin/product/item/{id}`
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"data": {
|
||
"id": 2045018534152478721,
|
||
"name": "示例产品",
|
||
|
||
"tiers": [
|
||
{"tierSeq": 1, "tierName": "经济", "tierDescription": "快捷酒店/双床标间"},
|
||
{"tierSeq": 2, "tierName": "舒适", "tierDescription": "四星酒店/河景房"},
|
||
{"tierSeq": 3, "tierName": "轻奢", "tierDescription": "五星酒店/高级套房"},
|
||
{"tierSeq": 4, "tierName": "高端", "tierDescription": "精品度假酒店/江景套房"},
|
||
{"tierSeq": 5, "tierName": "豪华", "tierDescription": "奢华度假庄园/别墅"}
|
||
],
|
||
|
||
"itinerary": [
|
||
{
|
||
"dayNumber": 1,
|
||
"hotels": [
|
||
{"tierSeq": 1, "hotelId": 111, "hotelName": "某快捷酒店"},
|
||
{"tierSeq": 2, "hotelId": 222, "hotelName": "某四星酒店"}
|
||
]
|
||
},
|
||
{
|
||
"dayNumber": 2,
|
||
"hotels": []
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
字段说明:
|
||
|
||
| 字段 | 含义 | 说明 |
|
||
|------|------|------|
|
||
| `data.tiers` | **档位定义列表**(权威来源) | Step1 基础信息配置,**档位 tab 列表必须用它** |
|
||
| `data.tiers[*].tierSeq` | 档位序号 | 1/2/3/4/5 |
|
||
| `data.tiers[*].tierName` | 档位中文名 | 经济/舒适/轻奢/高端/豪华 |
|
||
| `data.tiers[*].tierDescription` | 档位描述 | 档位下方的说明文字 |
|
||
| `data.itinerary[*].hotels` | 某一天的酒店安排 | 按档位可能部分录入,**允许为空数组** |
|
||
| `data.itinerary[*].hotels[*].tierSeq` | 该酒店归属的档位 | 用于过滤到对应档位 tab 下展示 |
|
||
|
||
---
|
||
|
||
## 四、前端正确渲染逻辑
|
||
|
||
### 1. 档位 tab 列表
|
||
|
||
**严格使用 `data.tiers`**:
|
||
|
||
```js
|
||
// 正确
|
||
const tierTabs = data.tiers; // 5 档齐全,顺序按 tierSeq
|
||
|
||
// 错误 —— 会导致未录酒店的档位消失
|
||
const tierTabs = uniqBy(flatMap(data.itinerary, d => d.hotels), 'tierSeq');
|
||
```
|
||
|
||
### 2. 档位名称
|
||
|
||
**一律用 `tier.tierName` 字段**,禁止前端写死档位名数组:
|
||
|
||
```js
|
||
// 正确
|
||
<Tab label={tier.tierName} />
|
||
|
||
// 错误 —— 极易出现 "经奢" 这种幻觉
|
||
const TIER_NAMES = ['经济', '经奢', '轻奢', '高端', '豪华']; // 第 2 项就是错的
|
||
<Tab label={TIER_NAMES[tier.tierSeq - 1]} />
|
||
```
|
||
|
||
### 3. 每档下的酒店
|
||
|
||
按当前选中档位的 `tierSeq` 过滤:
|
||
|
||
```js
|
||
const hotelsOfCurrentTier = day.hotels.filter(h => h.tierSeq === currentTierSeq);
|
||
```
|
||
|
||
### 4. 空档位保留 tab,内容区显示空状态
|
||
|
||
即使某档位下 `hotels` 全部为空,**tab 仍然要显示**,内容区渲染空状态提示(如"该档位暂未配置酒店,点击添加"),**禁止隐藏 tab**。
|
||
|
||
---
|
||
|
||
## 五、排查步骤建议
|
||
|
||
1. **全前端代码 grep `经奢`** → 应能定位到写死的字符串来源,删除或修正为从 `tiers` 取值
|
||
2. **定位 Step2 住宿 tab 的数据源**:检查是否从 `itinerary[*].hotels` 聚合 `tierSeq` 推导档位 —— 如是,改为从 `data.tiers` 取
|
||
3. **检查档位名枚举数组**:搜 `['经济'` / `['经济','` 等关键词,排查是否有写死的档位名数组写反
|
||
4. **检查字典调用**:Step2 档位名是否误用了其他字典(如把酒店星级字典当档位用)
|
||
|
||
---
|
||
|
||
## 六、验收标准(前端修完后自测)
|
||
|
||
- [ ] 产品 `2045018534152478721` Step2「住宿安排」tab **严格显示 5 个档位**,名称依次等于 Step1:`经济 / 舒适 / 轻奢 / 高端 / 豪华`
|
||
- [ ] 档位 3(轻奢)、4(高端)、5(豪华)下未录酒店时,**tab 仍然显示**,内容区呈现空状态而非 tab 消失
|
||
- [ ] 档位 1(经济)、2(舒适)下能正确看到已录入的酒店
|
||
- [ ] **全前端代码 grep 不到「经奢」这个字符串**
|
||
- [ ] 其他已发布产品随机抽查 2 个,Step2 住宿 tab 档位数与 Step1 配置完全一致
|
||
|
||
---
|
||
|
||
## 七、影响范围
|
||
|
||
- **后端**:无变更,不需要重启服务
|
||
- **前端**:仅 Step2「住宿安排」tab 的档位渲染逻辑修复
|
||
- **数据**:无需订正,线上数据是正确的,仅前端展示错误
|