docs(v2): 房务+定制师提房需求+站内信聊天 前端对接总览(管理后台)
这个提交包含在:
父节点
43d69d38d1
当前提交
a2866a89cf
@ -0,0 +1,361 @@
|
||||
# 房务模块 + 定制师提房需求 + 站内信聊天 — 前端对接总览(管理后台)
|
||||
|
||||
> 变更类型:📘 对接总览(三域接口契约汇总,供前端排期对接)
|
||||
> 端类型:管理后台(房务管家工作台 / 订单·定制师提房需求 / 站内信聊天)
|
||||
> 日期: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.token`。`X-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_requirement`(INSERT-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 且 `PENDING` → `PENDING_EDIT`(编辑草稿,不增版本号)
|
||||
- active 且 `DONE` → `DONE_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_category`:STANDARD/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 | — | 抢单房务信息(已被抢时有值) |
|
||||
|
||||
**请求示例**
|
||||
|
||||
```bash
|
||||
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`
|
||||
|
||||
**Query**:`keyword`(≤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`
|
||||
|
||||
**Query**:`orderId`(必填) / `dayNumber` / `stayDate` / `city` / `keyword`(非空时跨城搜) / `limit`(默认10上限50) / `roomCategory` / `roomCount` / `preferredHotelId` / `requirementId`。
|
||||
|
||||
**响应 HotelCandidateRespVO**:`stayDate/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 | 是 | 酒店/房型 ID(resource) |
|
||||
| roomCategory | String | 是 | 房型字典 code |
|
||||
| roomCount | Integer | 是 | 间数(≥1) |
|
||||
| sellPrice | BigDecimal | 是 | 售价(元/间·晚,≥0) |
|
||||
| remark | String | 否 | 备注 |
|
||||
|
||||
**响应 `{successCount,failCount,items[]}`**,item:`dayNumber/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/send`**:`requirementId/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}/reply`**:`replyBody(必填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/commit`(`assignmentId/newHotelId/newRoomTypeId?/newRoomCategory?/newSellPrice/nights/diffOverride?/swapReason(4-256)`,响应回 `newAssignmentId/totalDiff/diffDirection`,正数=需补差)。
|
||||
|
||||
## 2.8 日历 `GET /admin/house/calendar`
|
||||
|
||||
**Query**:`month`(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[]}`:
|
||||
|
||||
- `overview`:`hotelCount/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`
|
||||
|
||||
**Query**:`bizModule?` / `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}/messages`**:`beforeId?`(游标,首屏不传=拉最新一页) / `pageSize`(1-50)。响应 `{conversationKey,hasMore,nextCursor,list[]}`,向上翻页用 `nextCursor` 当下次 `beforeId`。消息项:`messageId(串)/senderAdminId(串)/senderName/senderRole/msgType/priority/content/isMine/sentAt`。
|
||||
- **发 `POST /{conversationKey}/messages`**:`content`(必填,≤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`。
|
||||
- **bizModule**:HOUSE(房务·bizId=orderId) / FLEET(车务·bizId=派车单) / DIRECT(纯私聊·bizId=0) / SYSTEM(系统通知专用)。
|
||||
- **msgType**:TEXT(默认) / 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. 聊天:列表卡片 `consultantId` → `open(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 由前端实现**。
|
||||
正在加载...
x
在新工单中引用
屏蔽一个用户