changelog: refactor product-v2 餐饮选项 meal_option 字典化 (#2778)

这个提交包含在:
API Changelog Bot 2026-05-21 10:49:56 +08:00
父节点 9b1f59c96c
当前提交 376e28930f

查看文件

@ -0,0 +1,119 @@
# refactor(product-v2): 餐饮选项 meal_option 由硬编码改为系统字典 + 新增「含(正餐)」
**日期**2026-05-21
**PR**#2783(已合 dev → 已合 dev-v3 → 已部署测试服并验证)
**工单**#2778
**影响端**管理后台前端hl-ui
---
## 背景
原「餐饮安排」下拉框 4 个选项(含酒店 / 含营地 / 含特色餐 / 自理)在前端 `MealConfig.vue` 和后端 `ProductItineraryAggregateFacade` 都是**硬编码**。每次加一个选项都要前后端同时改代码、走 PR、上线。
本次改造:
- 后端 switch 硬编码 → 改为读 `meal_option` 字典
- 字典数据库里新加一条 `REGULAR` = 「含(正餐)」
- 以后再加选项只在字典管理后台点一下即可,**前后端代码无需任何改动**
---
## 字典数据meal_option
测试服已落库,可通过 `GET /admin/dict/data/meal_option` 拉到:
| sortOrder | dictValue | dictLabel | 说明 |
|-----------|-----------|-----------|------|
| 1 | `HOTEL` | 含(酒店) | 历史值 |
| 2 | `CAMP` | 含(营地) | 历史值 |
| 3 | `SPECIAL` | 含(特色餐) | 历史值 |
| 4 | `REGULAR` | **含(正餐)** | **本次新增** |
| 5 | `SELF` | 自理 | 历史值(默认值) |
---
## 🚨 前端需要做的事
### 1. 删除硬编码
文件:`hl-ui/src/views/product/edit/components/itinerary/MealConfig.vue`
把第 22-27 行的硬编码数组**删掉**
```js
// 删掉这段
const mealOptions = [
{ label: '含(酒店)', value: 'HOTEL' },
{ label: '含(营地)', value: 'CAMP' },
{ label: '含(特色餐)', value: 'SPECIAL' },
{ label: '自理', value: 'SELF' },
]
```
### 2. 改成调字典接口
调用:`GET /admin/dict/data/meal_option`(已存在的字典 API
**Header**:需要 admin token
**响应结构**
```json
{
"code": 200,
"message": "成功",
"data": [
{ "dictValue": "HOTEL", "dictLabel": "含(酒店)", "sortOrder": 1, "status": "ACTIVE" },
{ "dictValue": "CAMP", "dictLabel": "含(营地)", "sortOrder": 2, "status": "ACTIVE" },
{ "dictValue": "SPECIAL", "dictLabel": "含(特色餐)", "sortOrder": 3, "status": "ACTIVE" },
{ "dictValue": "REGULAR", "dictLabel": "含(正餐)", "sortOrder": 4, "status": "ACTIVE" },
{ "dictValue": "SELF", "dictLabel": "自理", "sortOrder": 5, "status": "ACTIVE" }
]
}
```
### 3. 下拉绑定动态数据
`n-popselect``:options` 改为从接口返回的数组映射(注意现有字典 store 可能已经封装好,可以复用):
```js
// 推荐:直接复用全局 dictStore如果已有
const mealOptions = computed(() =>
dictStore.getDictData('meal_option').map(d => ({
label: d.dictLabel,
value: d.dictValue
}))
)
```
如果暂时没全局字典 store,组件级别 `onMounted` 拉一次即可(字典本身后端有 5 分钟 Redis 缓存,不会打到 DB
### 4. 校验逻辑无变化
`isSelf(value)` 仍然按 `value === 'SELF' || !value` 判断 — `SELF` 是业务语义的「自理」,前端这层判断不动。
---
## 兼容性
- ✅ 历史数据HOTEL/CAMP/SPECIAL/SELF**全兼容**,已上线的产品数据无需迁移
- ✅ 字典服务挂掉时后端会 fallback 到 dictValue 字面值(订单详情不会显示空白)
- ✅ 字典本身有 Redis 5 分钟缓存,QPS 无压力
---
## 测试服验证记录
- 测试服 https://web.test.1814.love:9443 已部署 commit `b28cef1c7`dev-v3
- 字典查询接口返回 5 条数据 ✓
- 产品详情接口对 5 种 meal_optionHOTEL/CAMP/SPECIAL/REGULAR/SELF全部返回正确 dictLabel ✓
- 无 token 调用返 `code: 401`
---
## 联系人
后端wx呼籁旅行
前端mmg
如有疑问或字典接口路径需要确认,可在 [#2778](https://git.1814.love:8443/wx/HL/issues/2778) 评论区留言。