# 配房需求面板（定制师侧）前端接入 —— 真实房型 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_category：STANDARD / 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 项分批。
