From b80f575fae25b2514a80ff6b9c85fb8a7da66f47 Mon Sep 17 00:00:00 2001 From: yaosutu <770858045@qq.com> Date: Fri, 22 May 2026 12:37:26 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=2022=5F2867-2868=5F=E8=AE=A2?= =?UTF-8?q?=E5=8D=95=E8=AF=A6=E6=83=85=E6=9E=9A=E4=B8=BE=E7=BB=9F=E4=B8=80?= =?UTF-8?q?+service-standard=E4=BF=AE=E5=A4=8D=20changelog?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...统一+service-standard修复-修改接口-管理后台.md | 298 ++++++++++++++++++ 1 file changed, 298 insertions(+) create mode 100644 changelogs-v2/2026-05/22_2867-2868_订单详情枚举统一+service-standard修复-修改接口-管理后台.md diff --git a/changelogs-v2/2026-05/22_2867-2868_订单详情枚举统一+service-standard修复-修改接口-管理后台.md b/changelogs-v2/2026-05/22_2867-2868_订单详情枚举统一+service-standard修复-修改接口-管理后台.md new file mode 100644 index 0000000..66e7aa5 --- /dev/null +++ b/changelogs-v2/2026-05/22_2867-2868_订单详情枚举统一+service-standard修复-修改接口-管理后台.md @@ -0,0 +1,298 @@ +# [修改接口·管理后台] 订单详情枚举统一 + service-standard 修复 (#2867 #2868) + +> **PR**: #2869 #2874 | **服务**: hl-order-service-v3 | **更新时间**: 2026-05-22 + +## 1. 接口背景 + +本次修复合并两个 PR,均针对订单详情页管理后台接口的静默 bug: + +- **PR #2869(Issue #2868)枚举统一 + null 兑底**:contractStatus / insuranceStatus 两个字段历史上枚举値定义不完整(少了中间过渡态和 NONE 初始态),且在订单还未进入合同/保险流程时后端直接返回 null,前端字典无法匹配导致显示空白或"未知"。本次统一枚举値集并将 null 兑底为 "NONE"。 + +- **PR #2874(Issue #2867)service-standard Tab 修复**:hasServiceStandard 字段原来只判断快照记录是否存在(行存在即返回 true),未校验反序列化是否成功、itinerary 是否非空,导致前端收到 hasServiceStandard=true 后调 GET /service-standard 接口却收到 data=null 的矛盾。根因是快照 itinerary 字段类型 List 与源头 List 不匹配,反序列化失败被静默吞掉。 + +## 2. 变更清单 + +| # | 接口 | 方法 | 路径 | 变更类型 | 说明 | +|---|------|------|------|----------|------| +| 1 | 订单详情 | GET | `/v3/admin/order/{id}` | 修改接口 | contractStatus/insuranceStatus 枚举统一;hasServiceStandard 判定逻辑修复 | +| 2 | 合同&保险 Tab | GET | `/v3/admin/order/{id}/contract-insurance` | 修改接口 | contractStatus/insuranceStatus 枚举统一,null 兑底为 NONE | +| 3 | 服务标准 Tab | GET | `/v3/admin/order/{id}/service-standard` | 修改接口(行为修复) | 原来 data 永远 null;现在能正常返回完整数据 | + +## 3. 接口详情 + +### 3.1 GET /v3/admin/order/{id} —— 订单详情 + +- **使用场景**:管理后台订单详情页首次加载,获取订单主信息 +- **认证**:需要管理后台 JWT(Bearer token),role=ADMIN +- **幂等性**:是(只读) +- **限流**:无 + +**本次变更字段**: +- `data.main.contractStatus`:枚举値扩展(4→6 値),null → `"NONE"` +- `data.main.insuranceStatus`:枚举値扩展(4→5 値),null → `"NONE"` +- `data.main.hasServiceStandard`:判定逻辑修复(见 §9) + +### 3.2 GET /v3/admin/order/{id}/contract-insurance —— 合同&保险 Tab + +- **使用场景**:管理后台订单详情页切换到 "合同&保险" Tab 时调用 +- **认证**:需要管理后台 JWT(Bearer token),role=ADMIN +- **幂等性**:是(只读) +- **限流**:无 + +**本次变更字段**: +- `data.contract.contractStatus`:枚举値扩展(4→6 値),null → `"NONE"` +- `data.insurance.insuranceStatus`:枚举値扩展(4→5 値),null → `"NONE"` + +### 3.3 GET /v3/admin/order/{id}/service-standard —— 服务标准 Tab + +- **使用场景**:管理后台订单详情页切换到 "服务标准" Tab 时调用;应在 `hasServiceStandard=true` 时才调此接口 +- **认证**:需要管理后台 JWT(Bearer token),role=ADMIN +- **幂等性**:是(只读) +- **限流**:无 + +**本次变更**:行为修复。修复前 data 永远为 null;修复后在有效快照时返回完整结构。 + +## 4. 接口入参 + +### 4.1 路径参数 + +三个接口入参相同,无变化。 + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| `id` | Long(String) | 是 | 订单 ID(snowflake,JSON 传 String 防精度丢失) | + +### 4.2 请求体字段 + +三个接口均为 GET,无请求体。 + +## 5. 出参(响应) + +### 5.1 GET /v3/admin/order/{id} —— 变更字段 + +| 字段路径 | 类型 | 说明 | +|----------|------|------| +| `data.main.contractStatus` | String(枚举) | 合同状态,见 §6.1。**本次扩展枚举値 + null 兑底** | +| `data.main.insuranceStatus` | String(枚举) | 保险状态,见 §6.2。**本次扩展枚举値 + null 兑底** | +| `data.main.hasServiceStandard` | Boolean | 是否有服务标准快照。**本次修复判定逻辑** | + +### 5.2 GET /v3/admin/order/{id}/contract-insurance —— 变更字段 + +| 字段路径 | 类型 | 说明 | +|----------|------|------| +| `data.contract.contractStatus` | String(枚举) | 合同状态,见 §6.1。**本次扩展枚举値 + null 兑底** | +| `data.insurance.insuranceStatus` | String(枚举) | 保险状态,见 §6.2。**本次扩展枚举値 + null 兑底** | + +### 5.3 GET /v3/admin/order/{id}/service-standard —— ServiceStandardVO(完整) + +| 字段 | 类型 | 说明 | +|------|------|------| +| `data.itinerary` | List | 行程列表,元素格式:"Day{n} {title}",如 "Day1 抵达成都"。**修复前恒为 null,修复后正常返回** | +| `data.notice` | String | 出行须知。可为 null | +| `data.refundPolicy` | String | 退款政策说明。可为 null | + +当订单无服务标准快照时(`hasServiceStandard=false`),整个 `data` 为 null。 + +## 6. 枚举 / 数据字典 + +### 6.1 contractStatus(合同状态) + +**所属字段**:`data.main.contractStatus`(OrderMainVO)、`data.contract.contractStatus`(ContractInsuranceVO)| **类型**:`String` + +| 値 | 中文 | 说明 | +|----|------|------| +| `NONE` | 无合同 | 订单尚未进入签约流程(修复前此状态返回 null) | +| `GENERATING` | 生成中 | 合同正在后台生成 | +| `GENERATED` | 已生成 | 合同已生成,待客户签署 | +| `SIGNED` | 已签署 | 客户已完成签署 | +| `VOIDED` | 已作废 | 合同已作废 | +| `RESIGNING` | 重签中 | 合同正在重新发起签署 | + +**修复前仅有4 値**:PENDING / GENERATED / SIGNED / VOIDED(PENDING 已废弃,NONE / GENERATING / RESIGNING 为本次新增枚举値) + +### 6.2 insuranceStatus(保险状态) + +**所属字段**:`data.main.insuranceStatus`(OrderMainVO)、`data.insurance.insuranceStatus`(ContractInsuranceVO)| **类型**:`String` + +| 値 | 中文 | 说明 | +|----|------|------| +| `NONE` | 无保险 | 订单尚未进入投保流程(修复前此状态返回 null) | +| `ISSUING` | 投保中 | 保险正在后台出单 | +| `ISSUED` | 已出单 | 保险已成功出单 | +| `CANCELLED` | 已取消 | 保险已取消 | +| `FAILED` | 出单失败 | 保险出单失败 | + +**修复前仅有4 値**:PENDING / ACTIVE / FAILED / CANCELLED(旧値已废弃重命名,全部替换为上表5 値) + +## 7. 错误码 + +本次修复无新增错误码。 + +| code | 含义 | 触发场景 | +|------|------|----------| +| `200` | 成功 | 正常响应 | +| `1000400` | 参数异常 | 路径参数 `id` 格式错误 | +| `1000404` | 订单不存在 | 指定 id 的订单不存在或已删除 | +| `1000403` | 无权限 | 非管理员 token 访问 | + +## 8. 示例 + +### 8.1 典型成功 —— 新建订单 contractStatus 返 NONE(修复前返 null) + +**请求**: + +``` +GET /v3/admin/order/1921234567890123456 +Authorization: Bearer +``` + +**响应**: + +```json +{ + "code": 200, + "data": { + "main": { + "orderId": "1921234567890123456", + "orderNo": "ORD20260522001", + "contractStatus": "NONE", + "insuranceStatus": "NONE", + "hasServiceStandard": false + } + }, + "message": "ok", + "success": true +} +``` + +> 修复前:contractStatus: null,insuranceStatus: null,前端字典无法匹配显示空白。 + +### 8.2 边界情况 —— service-standard 接口有快照时返完整数据(修复前永远 null) + +**请求**: + +``` +GET /v3/admin/order/1921234567890123456/service-standard +Authorization: Bearer +``` + +**响应(修复后)**: + +```json +{ + "code": 200, + "data": { + "itinerary": [ + "Day1 抵达成都,入住民宿", + "Day2 前往峨眉山景区", + "Day3 返程" + ], + "notice": "请携带身份证原件,到达后联系导游", + "refundPolicy": "出发7天以上全额退款,7天内收取50%手续费" + }, + "message": "ok", + "success": true +} +``` + +**响应(修复前)**: + +```json +{ + "code": 200, + "data": null, + "message": "ok", + "success": true +} +``` + +### 8.3 业务失败 —— hasServiceStandard=false 时 service-standard 返 data=null(正常行为) + +**场景说明**:订单未绑定产品行程快照,调 service-standard 接口返 data=null 是正常行为。 + +**请求**: + +``` +GET /v3/admin/order/1921111111111111111/service-standard +Authorization: Bearer +``` + +**响应**: + +```json +{ + "code": 200, + "data": null, + "message": "ok", + "success": true +} +``` + +## 9. 业务边界 + +**hasServiceStandard 判定逻辑(修复后)**: + +同时满足以下三个条件,`hasServiceStandard` 才返回 `true`: +1. 订单关联的产品行程快照记录存在 +2. 快照 JSON 反序列化成功(无类型错误) +3. 快照中 `itinerary` 字段非空(至少有1天行程) + +任意一个条件不满足,`hasServiceStandard` 返回 `false`,此时调 `GET /service-standard` 将返回 `data=null`。 + +**contractStatus / insuranceStatus 兑底规则**: +- 订单刚创建、尚未发起签约/投保时,两个字段返回 "NONE"(修复前返回 null) +- 字段値随后端状态机流转更新,不需要前端轮询,刷新页面即可获取最新値 + +## 10. 修改前后对比 + +### 10.1 字段级对比 + +| 字段 | 修复前 | 修复后 | +|------|--------|--------| +| `contractStatus`(初始态) | null | "NONE" | +| `contractStatus`(枚举集合) | PENDING / GENERATED / SIGNED / VOIDED(4 値,含PENDING已废弃) | NONE / GENERATING / GENERATED / SIGNED / VOIDED / RESIGNING(6 値) | +| `insuranceStatus`(初始态) | null | "NONE" | +| `insuranceStatus`(枚举集合) | PENDING / ACTIVE / FAILED / CANCELLED(4 値,均已废弃重命名) | NONE / ISSUING / ISSUED / CANCELLED / FAILED(5 値) | +| `hasServiceStandard` | 只判断快照行存在,partial 快照也返 true | 快照存在 + 反序列化成功 + itinerary 非空,三条件全满足才返 true | +| GET /service-standard data | 永远为 null(反序列化失败被吐) | 有效快照时返回完整 {itinerary, notice, refundPolicy} | + +### 10.2 行为级对比 + +| 行为 | 修复前 | 修复后 | +|------|--------|--------| +| 新建订单合同/保险状态 | 返回 null,前端字典无法匹配 | 返回 "NONE",字典正常匹配显示"无合同"/"无保险" | +| hasServiceStandard=true 但 Tab 内容空 | 会出现(快照反序列化失败时) | 不再出现;hasServiceStandard=true 一定能拿到有效数据 | +| insuranceStatus 枚举 ACTIVE / PENDING | 后端可能返回这两个値 | 后端不再返回,统一替换为新枚举値集合 | + +## 11. 影响评估 / 回滚 + +### 11.1 影响评估 + +- **是否破坏向后兼容**:是(枚举値重命名)。旧字典如只有 PENDING / ACTIVE(保险)或 PENDING(合同)等旧値,遇到新値会显示 "未知"。 +- **前端是否必须同步上线**:建议同步更新枚举字典(§6.1 和 §6.2 完整値表)再上线;若前端能容忍旧値显示 "未知" 可先不同步。 + +### 11.2 回滚方案 + +- **回滚方式**:revert PR #2869 / PR #2874,重新打包部署 hl-order-service-v3 +- **回滚后影响**:contractStatus / insuranceStatus 恢复返回 null 和旧枚举値;service-standard Tab 恢复返回 null + +## 12. 注意事项 + +- **枚举字典必须更新**:旧前端字典仅有4 値/4 値(含已废弃的 PENDING / ACTIVE),遇到新枚举値(如 NONE / GENERATING / RESIGNING / ISSUING / ISSUED)会显示 "未知"。请按 §6.1 和 §6.2 完整値表更新本地枚举字典。 +- **旧枚举値已废弃**:contractStatus 的 PENDING、insuranceStatus 的 PENDING 和 ACTIVE 后端不再返回,前端字典保留无害但不会再出现。 +- **service-standard workaround 清理**:如果前端之前针对 hasServiceStandard=true 但 data=null 的矛盾做过兑底处理(如显示固定占位文案、屏蔽Tab),修复后可以移除该 workaround。 + +## 13. 关联 / 联系人 + +### 13.1 链接 + +- **Issue(枚举统一)**: [#2868](https://git.1814.love:8443/wx/HL/issues/2868) +- **Issue(service-standard 修复)**: [#2867](https://git.1814.love:8443/wx/HL/issues/2867) +- **PR(枚举统一)**: [#2869](https://git.1814.love:8443/wx/HL/pulls/2869) +- **PR(service-standard 修复)**: [#2874](https://git.1814.love:8443/wx/HL/pulls/2874) +- **Merge commit(枚举统一)**: [bb4c41969](https://git.1814.love:8443/wx/HL/commit/bb4c41969) +- **Merge commit(service-standard 修复)**: [442fdf089](https://git.1814.love:8443/wx/HL/commit/442fdf089) + +### 13.2 联系人 + +- **后端负责人**: @yst