16 KiB
16 KiB
【修改接口 · 管理后台】确认订单预览与提交接口契约补齐(#4853)
PR: #4839 / #4846 / #4860 / #4868 服务: hl-order-service-v3 更新时间: 2026-07-13 适用端: 管理后台订单详情页
1. 接口背景
管理后台订单详情页点击“确认订单/确认行程”时,前端需要先调用预览接口取得 5 项前置校验结果;只有 allPassed=true 时才展示确认弹窗,并在用户确认后调用专用提交接口。
本次补齐前端实际需要的两个接口契约:
GET /v3/admin/order/{orderId}/confirm-checklistPOST /v3/admin/order/{orderId}/confirm-itinerary
前端不要再接入或暴露通用状态机接口 /v3/admin/order/{orderId}/transition 来做确认订单动作。
2. 变更清单
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|---|---|---|---|---|
| 1 | 确认订单前置校验与弹窗预览 | GET | /v3/admin/order/{orderId}/confirm-checklist |
修改接口 | 返回成功/失败互斥结构;失败返回 items,成功返回 preview;补齐 items[].checkName、preview.staffs,删除 notifications |
| 2 | 确认订单/确认行程提交 | POST | /v3/admin/order/{orderId}/confirm-itinerary |
新增专用接口 | 前端只传可选 reporterAssignmentId;服务端固定确认事件和审计原因;成功后推进到待出行并触发合同/投保异步事件 |
3. 接口详情
3.1 确认订单前置校验与弹窗预览
- 路径:
GET /v3/admin/order/{orderId}/confirm-checklist - 认证: 管理后台登录态,Header 携带
Authorization: Bearer <token> - 用途: 点击确认按钮后先调用,用于决定弹窗展示内容或阻断原因。
- 核心语义:
allPassed=true:items=null,preview有值,前端展示确认弹窗。allPassed=false:items有值,preview=null,前端展示失败项并引导补齐。
3.2 确认订单/确认行程提交
- 路径:
POST /v3/admin/order/{orderId}/confirm-itinerary - 认证: 管理后台登录态,Header 携带
Authorization: Bearer <token> - 用途: 用户在确认弹窗里最终点击确认后调用。
- 请求体: 可传
{};只有用户在弹窗里切换主报账人时才传reporterAssignmentId。 - 副作用: 成功后订单从定制中/待确认推进为待出行,并可能触发合同生成、保险投保异步事件。
4. 入参
4.1 路径参数
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
orderId |
String | 是 | 订单 ID。雪花 ID 建议按字符串处理,避免前端数字精度丢失。 |
4.2 GET /confirm-checklist 查询参数
无。
4.3 POST /confirm-itinerary 请求体
| 字段 | 类型 | 必填 | 说明 | 校验规则 |
|---|---|---|---|---|
reporterAssignmentId |
String | 否 | 新的主报账人 staff assignmentId;不传则沿用当前主报账人。 | 传入时必须是当前订单下有效的 staff assignment;不能指向团期共享 staff;建议前端按字符串传。 |
空请求体示例:
{}
切换主报账人示例:
{
"reporterAssignmentId": "2072930844657283074"
}
5. 出参
5.1 通用响应包装
| 字段 | 类型 | 说明 |
|---|---|---|
code |
Number | 业务状态码,200 表示成功。 |
message |
String | 业务提示,成功时通常为 成功。 |
data |
Object | 接口业务数据;失败时通常为 null。 |
5.2 GET /confirm-checklist 的 data
| 字段 | 类型 | 说明 |
|---|---|---|
allPassed |
Boolean | 是否全部通过。唯一开关字段。 |
items |
Array | 5 项校验明细;仅 allPassed=false 时返回数组,全部通过时为 null。 |
preview |
Object / null | 确认弹窗预览数据;仅 allPassed=true 时返回对象,未通过时为 null。 |
items[] 字段:
| 字段 | 类型 | 说明 |
|---|---|---|
code |
String | 检查项代码。 |
checkName |
String | 检查项中文名称,用于前端直接展示。 |
passed |
Boolean | 当前检查项是否通过。 |
failReason |
String / null | 未通过原因;通过时为 null。 |
actionPath |
String / null | 建议跳转路径;通过时为 null。 |
preview 字段:
| 字段 | 类型 | 说明 |
|---|---|---|
departureDate |
String | 出发日期,格式 yyyy-MM-dd。 |
totalPeopleCount |
Number | 总出行人数。 |
driverName |
String / null | 司机姓名。 |
driverPhoneMasked |
String / null | 司机手机号脱敏值。 |
hotels |
Array | 酒店摘要列表,按城市/酒店去重。 |
staffs |
Array | 本单配置人员列表,主报账人优先展示。 |
contractAutoAction |
Object / null | 确认后合同自动处理预告。 |
insuranceAutoAction |
Object / null | 确认后保险自动处理预告。 |
preview.hotels[] 字段:
| 字段 | 类型 | 说明 |
|---|---|---|
cityName |
String / null | 城市名称。 |
hotelName |
String / null | 酒店名称。 |
preview.staffs[] 字段:
| 字段 | 类型 | 说明 |
|---|---|---|
assignmentId |
String | staff 分配记录 ID。 |
staffId |
String | 员工 ID。 |
staffName |
String | 员工姓名。 |
staffPhone |
String / null | 员工手机号脱敏值。 |
staffRole |
String | 员工角色代码。 |
staffRoleName |
String | 员工角色中文名称。 |
isPrimaryReporter |
Boolean | 是否主报账人。 |
preview.contractAutoAction 字段:
| 字段 | 类型 | 说明 |
|---|---|---|
planName |
String / null | 确认后将使用的合同方案名称。 |
autoSign |
Boolean | 是否自动发送给客户线上签署。 |
preview.insuranceAutoAction 字段:
| 字段 | 类型 | 说明 |
|---|---|---|
planName |
String / null | 确认后将使用的保险方案名称。 |
peopleCount |
Number | 预计投保人数,通常等于 totalPeopleCount。 |
effectiveDescription |
String / null | 生效时间描述。 |
5.3 POST /confirm-itinerary 的 data
| 字段 | 类型 | 说明 |
|---|---|---|
success |
Boolean | 是否确认成功。 |
oldStatus |
String | 变更前订单主状态。 |
newStatus |
String | 变更后订单主状态。 |
oldFlowStatus |
String | 变更前订单流程状态。 |
newFlowStatus |
String | 变更后订单流程状态。 |
triggeredEvents |
Array | 确认成功后触发的异步事件标识。 |
6. 枚举 / 数据字典
6.1 items[].code
| 值 | 中文 | 说明 |
|---|---|---|
PAYMENT_OK |
支付状态 | 订单需满足确认前支付要求。 |
TRAVELER_COMPLETE |
出行人信息 | 出行人信息需完整。 |
HOTEL_DONE |
配房状态 | 需要配房的订单必须已完成配房。 |
VEHICLE_DONE |
配车状态 | 需要配车的订单必须已完成配车。 |
CONTRACT_TEMPLATE_OK |
合同模板 | 产品需存在可用合同方案/模板。 |
6.2 preview.staffs[].staffRole
| 值 | 中文 | 说明 |
|---|---|---|
DRIVER |
司机 | 车辆执行人员。 |
LEADER |
领队 | 团队领队。 |
GUIDE |
导游 | 导游人员。 |
PHOTOGRAPHER |
摄影师 | 摄影人员。 |
OTHER |
其他 | 其他配置人员。 |
6.3 状态字段
| 字段 | 常见成功前 | 常见成功后 | 说明 |
|---|---|---|---|
oldStatus / newStatus |
CUSTOMIZING |
PENDING_DEPARTURE |
订单主状态从定制中推进到待出行。 |
oldFlowStatus / newFlowStatus |
PENDING_CONFIRM |
PENDING_DEPARTURE |
流程状态从待确认推进到待出行。 |
6.4 triggeredEvents
| 值 | 中文 | 说明 |
|---|---|---|
ASYNC_CONTRACT_GENERATE |
异步生成合同 | 确认成功后可能触发合同生成/发送。 |
ASYNC_INSURANCE_ISSUE |
异步投保 | 确认成功后可能触发保险投保。 |
7. 错误码
| code | 含义 | 触发场景 | 前端建议 |
|---|---|---|---|
401 |
未登录或登录态无效 | 未携带有效 Authorization。 |
跳登录或刷新登录态。 |
581007 |
订单不存在 | orderId 不存在或已删除。 |
提示订单不存在并返回列表。 |
581016 |
当前订单状态不允许该操作 | 订单不处于可确认状态,或重复确认。 | 刷新详情和按钮状态。 |
581036 |
确认订单前置校验未通过 | 直接提交确认,但 checklist 未全部通过。 | 重新调用 confirm-checklist 展示失败项。 |
581046 |
reporterAssignmentId 格式非法 |
主报账人 assignmentId 不是有效数字 ID。 | 清空选择或提示重新选择报账人。 |
582102 |
员工分配记录不存在 | reporterAssignmentId 不存在或不属于当前订单。 |
重新拉取 preview.staffs 后再选。 |
582109 |
团期共享 staff 不可在订单侧增删改 | reporterAssignmentId 指向团期共享 staff。 |
禁止选择该人员作为订单侧改动目标。 |
8. 示例
8.1 典型成功:先预览,再确认
请求:
GET /v3/admin/order/2076236236812345346/confirm-checklist
Authorization: Bearer <token>
响应:
{
"code": 200,
"message": "成功",
"data": {
"allPassed": true,
"items": null,
"preview": {
"departureDate": "2026-07-19",
"totalPeopleCount": 3,
"driverName": "测试司机",
"driverPhoneMasked": "1390000****",
"hotels": [
{
"cityName": "拉萨",
"hotelName": "测试酒店"
}
],
"staffs": [
{
"assignmentId": "2076236240000000001",
"staffId": "2076236240000000002",
"staffName": "张三",
"staffPhone": "1380000****",
"staffRole": "DRIVER",
"staffRoleName": "司机",
"isPrimaryReporter": true
}
],
"contractAutoAction": {
"planName": "标准国内电子签约方案",
"autoSign": true
},
"insuranceAutoAction": {
"planName": "测试境内意外险方案",
"peopleCount": 3,
"effectiveDescription": "出发前 24h 内生效"
}
}
}
}
提交确认:
POST /v3/admin/order/2076236236812345346/confirm-itinerary
Authorization: Bearer <token>
Content-Type: application/json
{}
响应:
{
"code": 200,
"message": "成功",
"data": {
"success": true,
"oldStatus": "CUSTOMIZING",
"newStatus": "PENDING_DEPARTURE",
"oldFlowStatus": "PENDING_CONFIRM",
"newFlowStatus": "PENDING_DEPARTURE",
"triggeredEvents": [
"ASYNC_CONTRACT_GENERATE",
"ASYNC_INSURANCE_ISSUE"
]
}
}
8.2 边界成功:确认时切换主报账人
请求:
POST /v3/admin/order/2072930323661811714/confirm-itinerary
Authorization: Bearer <token>
Content-Type: application/json
{
"reporterAssignmentId": "2072930358709415938"
}
响应:
{
"code": 200,
"message": "成功",
"data": {
"success": true,
"oldStatus": "CUSTOMIZING",
"newStatus": "PENDING_DEPARTURE",
"oldFlowStatus": "PENDING_CONFIRM",
"newFlowStatus": "PENDING_DEPARTURE",
"triggeredEvents": [
"ASYNC_CONTRACT_GENERATE",
"ASYNC_INSURANCE_ISSUE"
]
}
}
8.3 异常:预览未通过
请求:
GET /v3/admin/order/2072930000000000000/confirm-checklist
Authorization: Bearer <token>
响应:
{
"code": 200,
"message": "成功",
"data": {
"allPassed": false,
"items": [
{
"code": "TRAVELER_COMPLETE",
"checkName": "出行人信息",
"passed": false,
"failReason": "出行人信息未完善",
"actionPath": "/admin/order/orders/2072930000000000000?tab=travelers"
},
{
"code": "HOTEL_DONE",
"checkName": "配房状态",
"passed": false,
"failReason": "配房未完成",
"actionPath": "/admin/order/orders/2072930000000000000?tab=hotel"
}
],
"preview": null
}
}
如果此时仍直接提交确认:
{
"code": 581036,
"message": "确认订单前置校验未通过,请先补全所有必填项",
"data": null
}
9. 业务边界
- 前端确认按钮流程固定为:先调
GET /confirm-checklist,allPassed=true后再调POST /confirm-itinerary。 allPassed=true和allPassed=false的结构互斥,前端不要同时依赖items和preview。preview.contractAutoAction和preview.insuranceAutoAction是“确认后将要执行的方案预告”,不是确认后的最终合同/保单详情。- 确认成功后可能异步生成合同和保险,前端需要以订单详情、合同保险 tab 的回读为最终状态展示依据。
- 重复提交确认不是幂等成功,会返回状态不允许类错误;前端提交后应禁用按钮或防重复点击。
- 房务角色不可访问订单确认接口;前端应按菜单/角色控制入口展示。
10. 修改前后对比
| 项 | 修改前 | 修改后 |
|---|---|---|
| 确认提交接口 | 前端可能误接 POST /v3/admin/order/{orderId}/transition 并传 eventCode=CONFIRM |
使用专用 POST /v3/admin/order/{orderId}/confirm-itinerary |
| 预览成功结构 | items 可能仍被前端当作数组处理 |
allPassed=true 时 items=null、preview 有值 |
| 预览失败结构 | 前端可能仍渲染空预览 | allPassed=false 时 items 有值、preview=null |
| 失败项展示 | 缺少稳定中文展示字段 | items[].checkName 可直接展示 |
| 酒店预览 | 可能为空或不可靠 | preview.hotels[] 返回真实配房酒店摘要 |
| 人员预览 | 缺少弹窗人员列表 | preview.staffs[] 返回本单配置人员,可用于主报账人选择 |
| 通知预览 | 曾短暂存在 notifications |
notifications 已删除,前端不要读取 |
| 合同/保险预告 | 容易理解成已生成记录回读 | 明确是确认后将使用的 ACTIVE 方案预告 |
11. 影响评估 / 回滚
| 维度 | 影响 |
|---|---|
| 前端调用 | 订单详情确认按钮需要接入 confirm-checklist + confirm-itinerary 两步流程。 |
| 旧接口兼容 | 不建议前端继续使用通用 /transition 完成确认动作。 |
| 展示兼容 | 前端要处理 items=null 和 preview=null 两种互斥结构。 |
| 回滚方式 | 如前端未接入,可先隐藏确认按钮或保留旧入口;但不要同时调用新旧确认提交接口。 |
12. 注意事项
orderId、assignmentId、staffId均建议按字符串处理。- 确认提交成功会真实改变订单状态,并触发合同/保险异步动作,不要把
POST /confirm-itinerary用作普通预检。 - 2026-07-13 测试服实测订单
2076236236812345346:GET /confirm-checklist返回code=200、allPassed=true、preview有值。POST /confirm-itinerary返回code=200、success=true。- 回读订单详情为
PENDING_DEPARTURE / PENDING_DEPARTURE,合同状态SIGNED,保险状态INSURED。 - 状态日志包含
CONFIRM事件。
13. 关联 / 联系人
- Issue #4838: wx/HL#4838
- Issue #4844: wx/HL#4844
- Issue #4853: wx/HL#4853
- Issue #4867: wx/HL#4867
- PR #4839: wx/HL#4839
- PR #4846: wx/HL#4846
- PR #4860: wx/HL#4860
- PR #4868: wx/HL#4868
- Commit: https://git.1814.love:8443/wx/HL/commit/b8abce7e2
- Commit: https://git.1814.love:8443/wx/HL/commit/711850177
- Commit: https://git.1814.love:8443/wx/HL/commit/89cbf9cdf
- Commit: https://git.1814.love:8443/wx/HL/commit/c772d83e7
- 负责人: 腰苏图