docs(changelog-v2): 配房需求面板前端接入 — 房型 roomTypeId 模型 + 酒店/备注渲染 (#4209/#4216/#4221)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
这个提交包含在:
API Changelog Bot 2026-06-22 15:26:38 +08:00
父节点 efa63eca69
当前提交 38960ac9d3

查看文件

@ -0,0 +1,91 @@
# 配房需求面板(定制师侧)前端接入 —— 真实房型 roomTypeId 模型 + 酒店/备注渲染(#4209 / #4216 / #4221,关联 #4220
> 变更类型:🔧 后端契约已就绪(部署 + 实测验证)→ 前端接入
> 端类型:管理后台(订单详情·定制师侧「行程安排 → 住宿安排」+「调整订单 → 配房需求」面板)
> 日期2026-06-22
> 工单:#4209 / #4216 / #4221(关联另一会话 #4220 服务hl-order-service-v3 + hl-resource-service
---
## TL;DR前端这轮要做的
1. **住宿安排结构化语句补「酒店名 + 候选备注」**(后端已就绪 + 实测,可立即接)。
2. **房型:先选酒店 → 选该酒店真实房型**,候选提交 `roomTypeId`(不再把房型名塞段级)。
3. **段级 `roomCategory` 传字典大类码**,别塞房型名。
4. **`hotelId` 可空** = 无酒店候选。
5. **预算只读**,编辑态显示候选最高协议价。
6. **删「城市/区域」输入框**
---
## 1. 住宿安排:补酒店名 + 候选备注(✅ 已就绪 + 实测,可立即接)
行程 Tab「住宿安排」当前结构化语句「第 N 晚 · X 间 · 房型 · ¥价/晚」**漏了酒店和候选备注**。后端 #4220 已补全段 × 候选结构并部署测试服,实测确认数据齐全:
`GET /v3/admin/order/{id}/itinerary``hotelGroup.requirement.days[]`
```json
{
"dayNumber": 1,
"segments": [{
"roomCategory": "...", "roomCount": 1, "budget": "380.00", "remark": "段备注",
"candidates": [
{ "hotelId": "...", "hotelName": "呼伦贝尔香格里拉大酒店", "remark": "候选备注 777555" },
{ "hotelId": "...", "hotelName": "海拉尔嘉世豪酒店", "remark": "候选备注 77777222" }
]
}]
}
```
**前端**:每段渲染 `房型 · X 间 · ¥budget/晚`,并把 `candidates[]` 的**酒店名 + 候选备注**展示出来(多候选平铺),段备注 `segments[].remark` 单列。完整结构见 #4220 changelog。
## 2. 房型模型:先选酒店 → 真实房型roomTypeId
⚠️ **实测发现当前前端把房型名("普通标间" / "俄式标准房")塞进了段级 `roomCategory`** —— 这不对:`roomCategory` 是房型**大类字典码**,具体房型名属于候选的真实房型。新模型:
- 候选选定酒店后,调**候选源**拿该酒店的**真实房型列表**(每项含 `roomTypeId` + `roomCategory` 大类 + 房型名 + 协议价)。
- 定制师选具体房型 → 候选提交 `roomTypeId` / `roomTypeName` / `protocolPrice`(候选级)。
- 段级 `roomCategory` 传**字典大类码**room_categorySTANDARD / SINGLE / TWIN / QUEEN / KING / SUITE / FAMILY / YURT / SPECIAL,**勿传房型名**;**选填**#4221 放开),无酒店候选时可空。
> 候选源端点返回真实房型的详细字段契约,以「后端验证后的更新版 changelog」为准,本节先给方向、勿提前联调。
## 3. 提交契约放开(✅ #4221 已实测)
`PUT /v3/admin/order/{id}/hotel-requirement`
- `segments[].roomCategory`**选填**(原必填)。
- `segments[].candidates[].hotelId`**选填**(原必填)= **无酒店候选**(定制师只提房数 X 间,酒店留房控统筹)。
- 仅 `segments[].roomCount` 必填。
实测:无酒店候选 / 缺 roomCategory 的提交体均通过校验(不再 400
## 4. 预算(只读)
- 预算后端按酒店协议价强制覆盖,**前端只读**、传值不作数。
- 一段多候选时段预算 = 候选中**最高**协议价(成本上限,房控择一不论选哪家都不超)。编辑态实时显示读候选 `protocolPrice`,多候选取最高。
## 5. 删「城市/区域」输入框(✅ #4216
候选面板的「城市/区域」字段后端已下线,提交体不再接收 → **删除该输入框**
---
## 字段速查
| 字段 | 位置 | 状态 | 说明 |
|---|---|---|---|
| `candidates[].hotelName` | 回显 itinerary | ✅ 已就绪 | 候选酒店名 |
| `candidates[].remark` | 回显 itinerary | ✅ 已就绪 | 候选备注 |
| `segments[].remark` | 回显 itinerary | ✅ 已就绪 | 段备注 |
| `candidates[].roomTypeId` | 提交 | 待前端接 | 候选真实房型 ID候选级 |
| `candidates[].roomTypeName` | 提交 | 待前端接 | 候选真实房型名快照 |
| `segments[].roomCategory` | 提交 | 待前端改 | 房型大类字典码,选填,**勿塞房型名** |
| `candidates[].hotelId` | 提交 | ✅ 已放开 | 选填 = 无酒店候选 |
| `segments[].budget` | 提交 | 只读 | 后端协议价覆盖 |
---
## 节奏
- **第 1 / 3 / 4 / 5 项**:后端已合并 + 部署测试服 + 实测验证,可立即接。
- **第 2 项(房型 roomTypeId 模型)**:方向已定,候选源真实房型详细字段待后端验证后更新版给全,属较大 reflow,建议与第 1 项分批。