hl-api-changelog/changelogs-v2/2026-06/20_房务+定制师提房需求+站内信聊天_前端对接总览-管理后台.md

24 KiB

房务模块 + 定制师提房需求 + 站内信聊天 — 前端对接总览(管理后台)

变更类型:📘 对接总览(三域接口契约汇总,供前端排期对接) 端类型:管理后台(房务管家工作台 / 订单·定制师提房需求 / 站内信聊天) 日期2026-06-20 服务hl-order-service-v3房务 + 定制师提房需求、hl-user-service站内信聊天 关联工单:#2728 房务工作台、#4013 房务侧 6 态、#4029/#4039/#4047/#4052/#4066/#4070~#4074/#4101 等


⚠️ 关键说明(务必先读)

  1. 统一网关 + 鉴权:所有 admin 接口走网关 https://api.test.1814.love:9443,请求头 Authorization: Bearer <token>。登录 POST /admin/auth/login {username,password}data.tokenX-Admin-Id 由网关从 token 注入,前端不要自己设"当前操作人/归属/未读"全部据此判定)。
  2. 雪花 ID 一律是字符串:所有 id/orderId/requirementId/assignmentId/hotelId/consultantId/... 等雪花 Long 在 JSON 里都是字符串(全局 ToStringSerializer)。前端按 string 接收、原样回传,禁止 parseInt/Number() 否则丢精度。
  3. 金额一律是字符串:所有 BigDecimal 金额(totalAmount/sellPrice/protoPrice/budget/replyPrice/...)在 JSON 里是字符串(如 "600.00")。前端按 string 展示/计算(用 decimal 库),不要当 number。
  4. 统一响应包{ "code": 200, "msg": "success", "data": {...} }。HTTP 始终 200,业务错误用 code + 6 位错误码区分(见各域错误码表)。分页统一 PageResult{ list/total }(部分接口为 {list,total,stats})。
  5. 错误码段位:房务 order-v3 = 808xxx;定制师提房需求 = 582xxx;站内信 user-service = 281xxx
  6. 本总览=导航 + 核心契约:高频建屏接口给到字段级 + 示例;其余给端点 + 用途 + 关键参数,完整字段以 Knife4j/Swagger 在线文档为准(每个 VO 都有 @ApiModelProperty 中文)。

模块一 · 定制师提房需求hl-order-service-v3

定制师在订单里提交/修改住宿需求 → 生成 order_hotel_requirementINSERT-only 版本化)→ 进抢单池给房务抢。控制器 HotelRequirementAdminController,全部 /v3/admin/order/**(网关已覆盖)。

1.1 端点总览

方法 路径 用途 调用角色
PUT /v3/admin/order/{id}/hotel-requirement 提交/修改/调整房型需求(核心入口·三分支自动判断) 定制师
GET /v3/admin/order/{id}/room 查询房间分配列表(家庭维度) 定制师
POST /v3/admin/order/{id}/room 新增房间分配(家庭维度) 定制师
PUT /v3/admin/order/{id}/room/{roomAssignmentId} 编辑房间分配 定制师
POST /v3/admin/order/{id}/hotel-requirement/dispatch 团期管理员提交房务PENDING_REVIEW→PENDING 团期管理员
POST /v3/admin/order/{id}/hotel-requirement/reject 团期管理员打回定制师 团期管理员

另有 POST /v3/admin/order/hotel-requirement/{requirementId}/assign(房控老式单次配房)属房务侧,建议房务工作台统一走【模块二 · 2.4 批量配房】。

1.2 核心接口:提交/修改/调整房型需求

PUT /v3/admin/order/{id}/hotel-requirement —— 定制师提房需求唯一入口。后端按订单当前是否有 active 需求 + 状态自动判断三分支,前端无需区分:

  • 无 active 行 → INIT_SUBMIT(首次提交)
  • active 且 PENDINGPENDING_EDIT(编辑草稿,不增版本号)
  • active 且 DONEDONE_ADJUST(已配房后调整,自动回 PENDING/PENDING_REVIEW 并软删旧配房)

请求体

字段 类型 必填 说明
days List<DayHotelReq> 每晚用房安排,长度必须 = 订单 tripNights
specialTags List<String> 特殊诉求标签(高楼层/景观房/无烟房…,前端自定义多选,后端不做枚举校验)
remark String(≤500) 需求备注

DayHotelReq

字段 类型 必填 说明
dayNumber Integer 第几晚1..tripNights,不重复
hotels List<HotelDetailReq> 同晚酒店列表≥1
remark String(≤200) 当晚备注

HotelDetailReq

字段 类型 必填 说明
hotelId Long 资源域酒店 ID须存在且已发布
roomCategory String 房型分类字典 room_categorySTANDARD/SINGLE/TWIN/QUEEN/KING/SUITE/FAMILY/YURT/SPECIAL
roomCount Integer 房间数(>0
budget BigDecimal 条件 预算/晚。自由行必填、跟团传 null⚠️ 工单 #4047后端按协议价独算覆盖、定制师不可改预算锁,前端可展示协议价做建议值但提交后端会以协议价为准
hotelName String 酒店名快照(前端传,供回显,后端不自动查资源)
source String 来源标记,默认 MANUAL

stayDate(每晚入住日)前端不传,后端按 departDate + (dayNumber-1) 反推。

响应体HotelRequirementRespVO

字段 类型 说明
requirementId Long(字符串) 需求行 ID
version Integer 版本号INSERT-only 单调递增;PENDING 反复改不增)
isActive Boolean 是否当前生效版本
status String 需求状态(见 1.3 状态机)
branchTaken String 实际走的分支INIT_SUBMIT / PENDING_EDIT / DONE_ADJUST
submittedAt LocalDateTime 首提时间PENDING 改不变,保抢单公平)
previousVersion Integer DONE_ADJUST 分支:上一版本号
assignmentDeletedCount Integer DONE_ADJUST 分支:软删旧配房行数
claimerId/claimerName/claimedAt 抢单房务信息(已被抢时有值)

请求示例

curl -k -X PUT "https://api.test.1814.love:9443/v3/admin/order/60001/hotel-requirement" \
  -H "Authorization: Bearer <token>" -H "Content-Type: application/json" -d '{
  "days": [
    {"dayNumber":1,"remark":"靠近景点","hotels":[
      {"hotelId":80001001,"roomCategory":"TWIN","roomCount":2,"budget":600.00,"hotelName":"拉萨西藏宾馆"}
    ]}
  ],
  "specialTags": ["高楼层","景观房"],
  "remark": "夫妻房,要求安静"
}'

1.3 需求状态机RequirementStatus

枚举 中文 说明
PENDING 待房务配 已提交进抢单池(核心订单提交后直达此态)
PROCESSING 配房中 已被抢,处理中
DONE 配房完成 配房完成
PENDING_REVIEW 待审核 仅团期:定制师提交后等团期管理员审核
REJECTED_TO_CONSULTANT 已打回定制师 房务/管理员打回,定制师改后重提
REJECTED_TO_ADMIN 已打回团期管理员 仅团期:房务打回回到管理员重审
  • 核心订单:提交 → PENDING →DONE / 打回 REJECTED_TO_CONSULTANT
  • 团期订单:提交 → PENDING_REVIEW →(管理员 dispatch → PENDING / 管理员 reject → REJECTED_TO_CONSULTANT

1.4 错误码582xxx

说明
582001 订单不存在
582011 days 长度与订单 tripNights 不一致
582012 dayNumber 越界或重复
582013 hotelId 不存在或已下架
582014 跟团模式 budget 必须为空
582015 自由行模式 budget 必填
582016 roomCount 必须 > 0
582017 订单状态不允许提交需求(已结算/已取消)
582018 roomCategory 不在字典中
582030 当前需求状态不可修改PROCESSING
582042 已签合同需走调整订单工作流

模块二 · 房务管家工作台hl-order-service-v3

房务工作台全功能。/v3/admin/order/**/v3/admin/house/**/admin/house/**/v3/admin/hotel-candidates 网关均已覆盖。

2.1 端点总览

分组 方法 路径 用途
抢单池 GET /v3/admin/order/grab-pool/hotel-requirements 抢单池列表(分页+多维筛选)
POST /v3/admin/order/hotel-requirements/{requirementId}/claim 抢单(乐观锁先到先得)
POST /v3/admin/order/hotel-requirements/{requirementId}/transfer 转单 / 超管强制指派
POST /v3/admin/order/hotel-requirements/{requirementId}/release 释放回抢单池
GET /v3/admin/order/grab-pool/my-claims/hotel 我的接单(分页+stats
GET /v3/admin/house/staff 转单可选房务员工
候选酒店 GET /v3/admin/hotel-candidates 候选酒店统一查询4 场景)
配房 POST /v3/admin/order/hotel-requirements/{requirementId}/assignments 批量提交配房方案
PUT /v3/admin/order/assignments/{id} 修改单条配房(含改协议价 #4072
DELETE /v3/admin/order/assignments/{id} 删除配房(软删)
GET /v3/admin/order/orders/{orderId}/rooms 房间分配查询(按家庭分组)
POST /v3/admin/order/assignments/{assignmentId}/rooms 家庭维度房间分配(整批覆盖)
订单详情 GET /admin/house/orders/{orderId} 房务侧订单详情聚合
GET /admin/house/orders/{orderId}/requirement-history 需求历史(含 diff/退回)
最终确认 POST /admin/house/assignments/requirements/{requirementId}/finalize 房务点最终确认
POST /admin/house/assignments/requirements/{requirementId}/receipts 上传确认回执multipart
GET /admin/house/assignments/requirements/{requirementId}/receipts 查询回执列表
询房 POST /v3/admin/order/inquiry/send 发起询房
POST /v3/admin/order/inquiry/{inquiryId}/reply 回填酒店回复(可同步建配房)
GET /v3/admin/order/inquiry 询房历史(分页)
POST /v3/admin/order/inquiry/{originalInquiryId}/resend 重发询房
POST /v3/admin/order/inquiry/{inquiryId}/escalate 加急/催办
换酒店 GET /v3/admin/order/swap-hotel/candidates 换酒店候选(同城可用)
POST /v3/admin/order/swap-hotel/preview 换酒店预览差价
POST /v3/admin/order/swap-hotel/commit 换酒店提交(触发联动)
待办 GET /v3/admin/order/todos 房务待办列表(多筛选+分类stats
日历 GET /admin/house/calendar 房务日历(月历+状态点)
酒店视图 GET /v3/admin/house/hotels 房务酒店列表
GET /v3/admin/house/hotels/{hotelId} 酒店详情 4Tab 聚合
POST /v3/admin/house/hotels/{hotelId}/check-log 新增核房记录
GET /v3/admin/house/hotels/{hotelId}/check-log 核房历史
GET /v3/admin/house/hotels/{hotelId}/operation-log 酒店维度操作日志
GET /admin/house/orders/{orderId}/operation-log 订单维度操作日志
月度对账 GET /v3/admin/house/reconciliation/monthly 月度对账(按酒店现结汇总)
GET /v3/admin/house/reconciliation/monthly/export 月度对账 Excel 导出

2.2 抢单池列表 GET /v3/admin/order/grab-pool/hotel-requirements

Querykeyword(≤32) / productType(CORE/GROUP/CUSTOM) / productName / consultantId / guestName / departDateFrom / departDateTo / page(默认1) / pageSize(1-100,默认20) / sortBy(默认 createTime,desc,可 departDate,asc)。

响应 PageResult<HouseGrabPageItemRespVO>(行卡片,挑关键):

字段 类型 说明
id Long(串) 房型需求 ID抢单用
orderId / orderNo Long(串)/String 订单 ID/订单号
guestName / personsDesc String 客人姓名 / 人数描述(如 2大1小
productType / productName / productNo String 产品类型/名/编号
route / departDate / nights String/Date/Int 档位·夜数 / 出行日 / 夜数
cities List<String> 行程城市(去重中文)
totalAmount BigDecimal(串) 订单总额
consultantName / consultantId String/Long(串) 定制师姓名 / adminId#4101 新增,开聊天用,见模块三)
requirementNote / special String/List<String> 需求备注 / 特殊诉求标签
requirementVersion Integer 需求版本(>1 时 UI 标"已修订"
createTime LocalDateTime 创建时间

我的接单 GET .../my-claims/hotel 响应为 {list, total, stats}stats={inProgress,pendingConfirm,confirmed,exception};行 VO 同样含 consultantId + unreadMessageCount(聊天未读红点,见模块三)。

2.3 候选酒店 GET /v3/admin/hotel-candidates

QueryorderId(必填) / dayNumber / stayDate / city / keyword(非空时跨城搜) / limit(默认10上限50) / roomCategory / roomCount / preferredHotelId / requirementId

响应 HotelCandidateRespVOstayDate/city/productType/candidates[],每个候选含酒店信息、协议价/售价、可用房、运营标签 tags#4070 复用酒店标签库:响应快/常合作等)、推荐理由等。

2.4 批量提交配房 POST /v3/admin/order/hotel-requirements/{requirementId}/assignments

幂等:同 requirementId 3 秒窗口去重 + 30 秒分布式锁。

请求 { items: List<AssignmentItemReqVO> },每项:

字段 类型 必填 说明
dayNumber Integer 第几天≥1
familyIndex Integer 家庭序号多家庭团区分,默认1
hotelId / roomTypeId Long 酒店/房型 IDresource
roomCategory String 房型字典 code
roomCount Integer 间数≥1
sellPrice BigDecimal 售价(元/间·晚,≥0
remark String 备注

响应 {successCount,failCount,items[]},itemdayNumber/familyIndex/assignmentId(串)/arrange(pending/waiting/confirmed/problem)

2.5 修改配房 PUT /v3/admin/order/assignments/{id}(含改协议价 #4072

字段 类型 必填 说明
protoPrice BigDecimal 新协议价(#4072 房务改协议价)。后端 afterCommit 自动写回 resource 价格日历(协议价单源真相)
sellPrice BigDecimal 新售价
remark String 备注
syncHotelSnapshot Boolean 重新拉酒店主数据覆盖快照

改价口径:房务侧只改协议价(本接口 protoPrice);定制师改结算价不在房务、也不在"提需求"那步,另在"确认订单"环节处理,前端房务工作台无需提供改结算价入口。

2.6 询房(核心两个)

发起 POST /v3/admin/order/inquiry/sendrequirementId/hotelId/dayNumber/stayDate/nights(1-30)/roomCount(1-99)/roomCategory?/messageBody?(≤1000,留空用模板)/isPriority?/timeoutOverride?(默认240min)/contactName?/contactWechat?。响应含 id/status(PENDING)/timeoutAt/wechatTemplate(微信复制粘贴模板)

回填 POST /v3/admin/order/inquiry/{inquiryId}/replyreplyBody(必填1-2000)/replyPrice?/replyAvailable?(REJECTED 时必须 0)/replyStatus(REPLIED/REJECTED/CONFIRMED)/convertToAssignment?(true 同步建配房)/isPartialReply?convertToAssignment=true 时响应回 convertedAssignmentId

询房=线下微信沟通的记录/状态机载体,不是即时通讯;房务↔定制师的实时沟通走站内信聊天(模块三),两者不同。

2.7 换酒店(三步)

GET /swap-hotel/candidates?assignmentId=&level=POST /swap-hotel/preview(算差价 autoDiff/appliedDiff/totalDiff/diffDirection 升级·降级·持平)→ POST /swap-hotel/commitassignmentId/newHotelId/newRoomTypeId?/newRoomCategory?/newSellPrice/nights/diffOverride?/swapReason(4-256),响应回 newAssignmentId/totalDiff/diffDirection,正数=需补差)。

2.8 日历 GET /admin/house/calendar

Querymonth(YYYY-MM 必填) / scope(mine默认/all) / status(inProgress/inquiry/pending/exception,逗号多选)。响应 {month,summary,days[]},days 为完整周排版28-42 天,含上下月补位 isCurrentMonth=false),每天 tourCount + statusDots[]status/label/count/color

2.9 月度对账 GET /v3/admin/house/reconciliation/monthly?month=YYYY-MM#4074

仅统计现结settlement paymentMethod=CASH_PAID。响应 {month,overview,hotels[]}

  • overviewhotelCount/orderCount/roomNights/totalAmount/paidAmount/unpaidAmount(金额均字符串)。
  • hotels[]hotelId(串)/hotelName/orderCount/roomNights/totalAmount/avgPrice/paidAmount/unpaidAmount,应付降序。

导出 GET .../monthly/export?month=YYYY-MM.xlsx 文件流(Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,文件名 house-reconciliation-{month}.xlsx)。空月返空列表 + 全 0 概览。

2.10 房务错误码808xxx

码 → 说明(节选高频)
抢单 0080xx 808001 已被他人抢 / 808003 达30单上限 / 808010 非本人需求 / 808013 转单达3次 / 808021 已有confirmed无法释放 / 808090 未登录或非房务
配房 0081xx 808100 需求不存在 / 808101 需求未抢 / 808102 dayNumber越界 / 808110 非本人需求 / 808120 配房不存在 / 808130 房间数超配 / 808131 床型不在字典 / 808140 订单不存在 / 808141 订单非房务可见 / 808150 month格式错 / 808170 对账month格式错 / 808180 未全部配房 / 808181 有未完结询房 / 808182 状态不允许最终确认 / 808186 状态不允许上传回执
询房 0082xx 808200 非本人需求 / 808201 酒店ID无效 / 808202 该酒店该晚已有PENDING询房 / 808210 询问不存在 / 808211 询问已结束 / 808220 orderId与requirementId至少传一
换酒店 0084xx 808400 原配房不存在 / 808401 新酒店今日无可用房 / 808402 无权操作 / 808403 库存冲突 / 808404 新旧酒店相同 / 808405 配房已被换过
酒店视图 0085xx 808500 酒店不存在 / 808501 totalAvailable与byRoomType不一致 / 808502 该日已有核房记录 / 808503 byRoomType为空

模块三 · 站内信聊天hl-user-service

站内信已升级为双向 1:1 会话 + SSE 实时 + 敏感词过滤。房务↔定制师围绕订单的实时沟通走这里(区别于询房的线下记录)。控制器 ChatMessageController/admin/message/chat/**只做聊天,不推业务通知

3.1 端点总览

方法 路径 用途
POST /admin/message/chat/open 打开/找回 1:1 会话(幂等)
GET /admin/message/chat/conversations 我的会话列表(含订单摘要/待回复 tab
GET /admin/message/chat/{conversationKey}/messages 拉线程消息(游标分页)
POST /admin/message/chat/{conversationKey}/messages 发一条消息
POST /admin/message/chat/{conversationKey}/read 标记已读到最新
GET /admin/message/chat/unread-total 我的聊天未读总数(聊天 Tab 专用)
GET /ws/admin-msg/stream SSE 实时推送长连接
GET /admin/message/unread-count 顶部合并角标(聊天+通知,已有,不在本次范围但前端会用)

3.2 打开会话 POST /admin/message/chat/open

请求bizModule(HOUSE/FLEET/DIRECT) / bizId(HOUSE=orderId;DIRECT 留空) / peerAdminId(对方 adminId)。 响应conversationKey / peerAdminId / peerName / peerRole / unreadCount / isNew

房务从订单卡片开会话{bizModule:"HOUSE", bizId:<orderId>, peerAdminId:<consultantId>}consultantId 取自抢单池/我的接单列表行(#4101 已补到列表 VO,无需进详情。同业务对象同两人重复 open 返 isNew=false,前端可缓存 conversationKey 避免重复调。

3.3 会话列表 GET /admin/message/chat/conversations

QuerybizModule? / bizId?(配合实现"围绕某订单的会话"/ onlyPending?(true=只看待回复) / pageNo(默认1) / pageSize(1-50,默认20)。

响应 PageResult<ChatConversationRespVO>conversationKey / bizModule / bizId(串) / peerAdminId(串) / peerName / peerRole / unreadCount / lastMessagePreview / lastMessageAt / status(ACTIVE/ARCHIVED) / peerAvatar + HOUSE 会话专属orderNo / customerName / destination / tripDays / bizStatusLabel(中文如"待配房") / progressDesc(如"已配 2/4 间") / pendingReply。按最后活跃倒序。

3.4 拉消息 / 发消息 / 已读

  • GET /{conversationKey}/messagesbeforeId?(游标,首屏不传=拉最新一页) / pageSize(1-50)。响应 {conversationKey,hasMore,nextCursor,list[]},向上翻页用 nextCursor 当下次 beforeId。消息项:messageId(串)/senderAdminId(串)/senderName/senderRole/msgType/priority/content/isMine/sentAt
  • POST /{conversationKey}/messagescontent(必填,≤1000) / priority?(NORMAL默认/URGENT) / msgType?(TEXT默认/IMAGE/SYSTEM)。响应 {messageId,conversationKey,sentAt}限流 20 条/60 秒/会话
  • 已读 POST /{conversationKey}/read:把会话标记已读到最新,unreadCount 归 0。响应 {conversationKey,unreadCount:0,lastReadMessageId}建议发消息后/进入会话时自动调一次
  • 未读总数 GET /admin/message/chat/unread-total{chatUnreadTotal}(仅 CHAT,聊天 Tab 红点)。

3.5 SSE 实时推送 GET /ws/admin-msg/stream

前端用 EventSource 连接,token 走 query/ws/admin-msg/stream?token=<token>(网关已放行 /ws/ 前缀、注入 X-Admin-Id;SSE 路由 response-timeout 已加大到 1h 防掐断)。事件:

事件名 触发 载荷关键字段
connected 建连即发 "ok"
im-chat 新聊天消息type=CHAT adminId / unreadCount / conversationKey / senderName / preview / priority
message 通知类type=NOTIFY 或老信令) adminId / unreadCount / title
ping 每 25s 心跳(注释行,不触发 onmessage

前端按事件名分发:im-chat 刷新聊天会话/红点,message 走原通知逻辑。

3.6 会话 key 规则 + 枚举

  • 会话 key{bizModule}:{bizId}:{minAdminId}:{maxAdminId},两人 adminId 强制小者在前,保证双向命中同一会话不分叉。DIRECT 纯私聊 bizId 用 0 占位。示例 HOUSE:70123:101:205
  • bizModuleHOUSE(房务·bizId=orderId) / FLEET(车务·bizId=派车单) / DIRECT(纯私聊·bizId=0) / SYSTEM(系统通知专用)。
  • msgTypeTEXT(默认) / IMAGE(图片URL) / SYSTEM(系统提示,senderAdminId 空)。
  • 敏感词:后端发送时本地 DFA 命中替换为等长 *不报错。前端无需自己过滤,直接展示返回的 content

3.7 站内信错误码281xxx

HTTP语义 说明
281001 404 会话不存在(对未 open 的 key 操作)
281002 403 无权访问该会话(非成员)
281003 409 会话正在创建,请稍后重试open 并发)
281004 429 发送过于频繁(限流 20/60s
281005 400 不能与自己创建会话
281010 400 目标员工不存在或已离职
281011 400 消息内容不合法(空/超 1000 字)

前端联调 Checklist

  1. 登录拿 token → 所有请求带 Authorization: Bearer,不要手设 X-Admin-Id
  2. 所有 id/金额按字符串处理(雪花精度 + 金额精度)。
  3. 定制师提房:PUT /v3/admin/order/{id}/hotel-requirement,days 长度=tripNights;budget 自由行必填/跟团 null,别在前端锁死预算值(后端按协议价覆盖)。
  4. 房务工作台:抢单池列表 → claim → 候选 /v3/admin/hotel-candidates → 批量配房 /assignments → (改协议价走 PUT /assignments/{id}protoPrice)→ finalize + 上传回执。
  5. 聊天:列表卡片 consultantIdopen(HOUSE,orderId,consultantId) → messages/send/read;并发起一条 EventSource('/ws/admin-msg/stream?token=') 监听 im-chat/message
  6. 完整字段以测试服 Knife4j/Swagger 为准(每 VO 有中文 @ApiModelProperty),本总览覆盖端点+核心契约+错误码+枚举。

备注

  • 本总览三域接口均已部署测试服并通过 9443 实测;网关路由全覆盖,无需新增。
  • 站内信"接入房务"= 房务↔定制师 1:1 聊天(已完备);不做房务事件→站内信通知(配房完成/待配房等 NOTIFY 推送暂不做)。
  • 月度对账/酒店富表单等后端 schema+API 已就位,对应表单/列表 UI 由前端实现