文件
hl-api-changelog/changelogs-v2/2026-10/02_8662_询房预览补权限-修改接口-管理后台.md
T
API Changelog Bot和Claude Opus 5.5 cdcd07d8e5
changelog-filename-gate / validate (push) Failing after 1s
docs(changelog): #8659 房务价格日历与库存口径统一 / #8662 删除旧住宿需求提交口与询房预览补权限
- #8659:候选页 inventoryStatus 按日历状态取值;控房表新增 calendarStatus / calendarStatusName(前端加一列展示);扣减拒绝分 808906 / 808907 / 808901。
- #8662:删除 PUT /v3/admin/order/{id}/hotel-requirement;询房预览补房务读守卫,非房务角色返回 808090。

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 01:15:08 +08:00

239 行
9.6 KiB
Markdown
原始文件 Blame 文件历史

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
---
schema: "hl-changelog/v2"
ticket: "8662"
title: "询房预览接口补房务读守卫"
consumer: "admin"
author: "wx(GIT)"
change_type: "修改接口"
backend_status: "deployed"
gateway_status: "not_required"
frontend_status: "not_required"
frontend_owner: ""
frontend_ref: ""
target_release: ""
verified_at: ""
status_note: ""
updated_at: "2026-10-02"
base: "dev-v3"
---
# 询房预览接口补房务读守卫
> **存放目录**: 二期 → `changelogs-v2/2026-10/`
>
> **服务**: hl-order-service-v3
> **Issue**: #8662
> **日期**: 2026-10-02
> **影响范围**: 管理后台房务询房话术预览功能
---
## ⚠️ 关键变化
- 接口 `POST /v3/admin/order/inquiry/preview` 新增房务读守卫。
- **非房务角色**(定制师、管理员、其他后台角色)调用返回 **808090**「未登录或非房务角色,无权操作」。
- **房务角色**(房务管理员、超管)放行,功能无改动。
---
## 一、背景
二期房务功能收口中,#8390 统一给 16 个旧只读端点(日历 / 房务详情 / 酒店视图 / 转单候选 / 待办 / 月度对账 / 旧抢单池 / 订单房间)挂上房务读守卫,唯独询房话术预览这一个接口漏过,导致定制师、运营等非房务角色能调通,拿到酒店联系人与微信(源码:`HouseReadGuard.java` 类 javadoc)。本次补上后,受此守卫覆盖的端点共 17 个。
---
## 二、变更接口清单
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|------|------|------|----------|------|
| 1 | 询房话术预览 | POST | `/v3/admin/order/inquiry/preview` | 修改 | 新增房务读守卫,非房务角色返回 808090 |
---
## 三、接口详情
### 1. 询房话术预览 `POST /v3/admin/order/inquiry/preview`
**VO**: `InquiryPreviewReqVO → InquiryPreviewRespVO`
#### 使用场景
房务在配房弹窗点击「询房」时预览即将发往酒店的话术(所见即所发),确认无误后复制到企业微信。本次修改:非房务角色被拒。
#### 入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|------|------|------|------|------|------|
| hotelId | Body | Long | ✅ | - | 酒店 ID;按此取 resource 联系人渲染文案 |
| orderId | Body | Long | ❌ | - | 订单 ID(取团号);`assignmentId` 有效时以其所属订单为准 |
| assignmentId | Body | Long | ❌ | - | 配房 ID;存在且与 `hotelId` 匹配时,日期/房型/间数/支付方式优先取该配房快照 |
| stayDate | Body | LocalDate | ❌ | - | 入住日期;`assignmentId` 命中时被快照值覆盖 |
| roomCount | Body | Integer | ❌ | ≥1 | 房间数;`assignmentId` 命中时被快照值覆盖;都缺省时按 1 间渲染 |
| roomCategory | Body | String | ❌ | 字典 room_category | 房型类别;`assignmentId` 未命中时用于查房型中文名,查不到则原样回退为传入的 code |
#### 出参 `Result<InquiryPreviewRespVO>`
| 字段 | 类型 | 说明 |
|------|------|------|
| messageBody | String | 渲染后的固定格式订房确认话术(模板见下) |
| contactName | String | 联系人姓名,resource 按 hotelId 带出,前端只读回显 |
| contactWechat | String | 联系人微信号,resource 按 hotelId 带出,前端只读回显 |
话术固定模板(`InquiryMessageTemplate.SEND_BASE`,占位符按 `Map` 渲染,缺失值替换为空串):
```
呼籁旅行 - 订房确认书:
团号:${teamNo}
日期:${stayDate}
房型:${roomTypeName}${roomCount}间
备注:${tags}
1.${paymentText},价格保密。
2.${breakfastText}${invoiceText}
3.核房电话:${phone}
辛苦确认后回复 @${replyContacts}
```
#### 请求示例
```json
{
"hotelId": 1900000001,
"orderId": 1900000000,
"stayDate": "2026-04-28",
"roomCount": 1
}
```
#### 响应示例
```json
{
"code": 200,
"message": "成功",
"data": {
"messageBody": "呼籁旅行 - 订房确认书:\n团号:HL20261001A\n日期:4.28\n房型:待补充1间\n备注:协议酒店\n1.领队前台现付,价格保密。\n2.含早含发票\n3.核房电话:0470-8888888\n辛苦确认后回复 @王前台",
"contactName": "王前台",
"contactWechat": "hailar_holiday"
},
"success": true
}
```
上例未传 `roomCategory`、也未传 `assignmentId`,`roomTypeName` 按规则取不到任何来源,渲染为空缺省文案(源码常量 `EMPTY_VALUE_TEXT`)——`${roomTypeName}${roomCount}间` 模板不插空格,故渲染结果是该空缺省文案与 `1间` 的无分隔拼接(见上方 JSON 示例的 `messageBody`),前端如需展示分隔需自行处理,后端不改模板。日期按 `M.d` 格式渲染(无补零),`2026-04-28` → `4.28`。ID、团号、酒店联系人等取值均为说明用的构造值。
#### 空数据 / 降级响应
- 酒店联系信息查询抛异常(`loadHotelExtended` 捕获全部 `RuntimeException`):静默降级,`contactName`/`contactWechat` 返回**空字符串 `""`(不是 NULL)**,`messageBody` 仍正常渲染,缺省字段分别落空值常量(`EMPTY_VALUE_TEXT`)/空标签常量(`EMPTY_TAG_TEXT`)/现付默认文案。
- `assignmentId` 传了但查不到记录、或与 `hotelId` 不匹配:静默降级为按请求参数 + 资源数据重新生成(不报错,仅记一条 `log.warn`),不是 assignment 快照。
- `assignmentId` 命中但与请求里的 `orderId` 不一致:忽略请求 `orderId`,改用该配房记录的真实 `orderId`(同样静默降级,仅记日志)。
- 不落库,房务可反复调用,无状态。
#### 错误响应
```json
{
"code": 808090,
"message": "未登录或非房务角色,无权操作",
"data": null,
"success": false
}
```
其他错误:
| code | message | 触发 |
|------|---------|------|
| 400 | hotelId 不能为空 | hotelId 未传 |
| 400 | 房间数最小为 1 | roomCount 传了但 < 1 |
#### 业务边界
- 只校验角色(房务管理员/超管放行),**不校验订单归属**:房务可预览任意订单的询房话术,与 #8390 覆盖的其余 16 个只读端点行为一致。
- 该守卫只拦「有角色但非房务」;零角色账号(网关未透传 `X-Admin-Role`)按既有口径仍放行,不受本次改动影响(`HouseReadGuard.java` 类 javadoc,#7609 G-2 定案)。
- 预览不落库,无副作用,可反复调用。
- `contactWechat` 仅供复制,前端不做交互(不拨电话、不主动跳转)。
---
## 四、契约约束与正确调用方式
### 权限对照
| 角色 | 改前 | 改后 | 说明 |
|------|------|------|------|
| 房务管理员 | 200 放行 | 200 放行 | 无改动 |
| 超管 | 200 放行 | 200 放行 | 无改动 |
| 定制师(CUSTOMIZER) | 200 放行(缺陷) | 808090 拒绝 | **新增限制** |
| 其他后台角色(如 ADMIN) | 200 放行(缺陷) | 808090 拒绝 | **新增限制** |
| 零角色账号(网关未透传 `X-Admin-Role`) | 放行 | 放行 | 无改动(#7609 G-2 口径,本次刻意不收) |
---
## 五、数据库行为
不落库,本接口无数据写入。
---
## 六、边界行为
- 错误码 808090 与所有同域房务读端点保持一致,可统一处理。
- 权限守卫受 Nacos 开关 `group-batch.acl.enforce.house-read-role` 控制。测试服 2026-09-30~10-02 期间该开关为开启状态(实测 ADMIN/CUSTOMIZER 均返回 808090,见「八、测试环境已验证」);生产环境以当时的配置为准,前端按本文档的错误码契约接即可,无需关心开关本身的开关状态。
---
## 六.5 枚举
不适用(接口无新增枚举)。
---
## 六.6、修改前后对比
| 项 | 改前 | 改后 |
|----|------|------|
| 权限校验 | ❌ 无房务守卫,任何角色可调 | ✅ 新增房务读守卫,非房务返回 808090 |
| 功能逻辑 | 预览话术、返回联系人 | 不变(仅权限改动) |
---
## 六.7、影响评估
- **前端无需改动**:经 hl-ui v2.1 核实,该接口的封装函数(`src/api/housekeeper/inquiry.js` 的 `previewInquiry`)仅有一处调用——`src/views/housekeeper/components/useHousekeeperInquiryCopy.js`,位于房务专属视图目录下,本就只在房务角色登录后的界面里被触达。非房务角色(定制师等)侧没有调用这个接口的代码,本次收紧权限不会让任何现有页面报错。
---
## 七、不影响范围
- 房务配房流程(使用此接口的场景)功能不变。
- 小程序端、H5 端接口无改动。
- #8390 已覆盖的其余 16 个旧只读端点本身无行为变化,本次只是把本端点补入同一套守卫。
---
## 八、测试环境已验证
测试服环境,2026-09-30~10-02,经网关实测,与修前基线逐字段比对(基线快照:`p50_ac3_room_manager.json`/`p50_ac3_super_admin.json`;本轮:`p6_ac3_roommanager.json`/`p6_ac3_superadmin.json`/`p6_ac3_admin.json`/`p6_ac3_consultant.json`)。
```
POST /v3/admin/order/inquiry/preview
房务管理员(ROOM_MANAGER):200,messageBody/contactName/contactWechat 与修前基线逐字节相同 ✓
超管(SUPER_ADMIN):200,messageBody/contactName/contactWechat 与修前基线逐字节相同 ✓
管理员(ADMIN):808090 未登录或非房务角色,无权操作 ✓
定制师(CUSTOMIZER):808090 未登录或非房务角色,无权操作 ✓
```
---
## 十、相关文档
- **Issue**: [#8662](https://git.1814.love:8443/wx/HL/issues/8662)
- **PR**: [#8705](https://git.1814.love:8443/wx/HL/pulls/8705)
- **背景工单**: [#8390](https://git.1814.love:8443/wx/HL/issues/8390)(原覆盖 16 个读端点统一守卫,本次 #8662 补上第 17 个——即本端点)
## 关联 / 联系人
**关联工单**: #8662
**同批删除**: 旧住宿需求提交接口
**后端负责人**: @wx