diff --git a/.tmp-user-62_4938.md b/.tmp-user-62_4938.md deleted file mode 100644 index 8943ee5..0000000 --- a/.tmp-user-62_4938.md +++ /dev/null @@ -1,507 +0,0 @@ -# 【#4938 前端对接·管理后台】车务创建、修改与最终确认返回订单调整基线差异 - -> Issue: [wx/HL#4938](https://git.1814.love:8443/wx/HL/issues/4938) -> -> PR: 待补充 -> -> 服务: `hl-fleet-service` -> -> 日期: 2026-07-19 -> -> 影响范围: 车务直接派车、直接改派、`holding → assigned` 最终确认,以及订单调整后的日期、人数、车辆容量差异处理 -> -> 状态: 源码静态契约已核对,待代码评审、合并、部署与测试环境验收 - -## 一、前端对接结论 - -以下三个既有管理后台接口现在共用业务码 `605041` 返回结构化逐日差异: - -| 操作 | 接口 | 触发 605041 的条件 | -|---|---|---| -| 创建派单 | `POST /admin/fleet/assignments` | `holdMode=0` 直接派车时最终基线不一致 | -| 修改派单 | `POST /admin/fleet/assignments/{assignmentId}/change` | `holdMode=0` 直接改派时最终基线不一致 | -| 最终确认 | `POST /admin/fleet/assignments/{assignmentId}/confirm` | 订单、需求、行程、逐日派单、人数或容量基线不一致 | - -前端必须遵守以下判断: - -1. 三个接口的 `605041` 当前均返回 HTTP 200,但统一响应体为 `code=605041`、`success=false`,不能只判断 HTTP 状态。 -2. `605041` 的 `data` 不为空: - - create 返回 `AssignmentWriteRespVO`,保证 `data.dailyDifferences` 可读; - - change 返回 `ChangeAssignmentRespVO`,保证 `data.dailyDifferences` 可读; - - confirm 返回 `ConfirmRespVO`,保证 `data.confirmed=false` 和 `data.dailyDifferences` 可读。 -3. `605041` 不会提交派单及其关联业务状态写入: - - create 不会新增或激活派单; - - change 不会取消旧派单,也不会生成可用的新派车版本; - - confirm 不会推进派单状态或确认时间; - - 三者都不会触发车辆/司机占用、保险、对账或订单派定结果变化。 -4. 收到 `605041` 后保持操作前页面状态,展示逐日差异,并重新拉取最新订单和车务详情。 -5. 所有派单、车辆槽位、派车组、订单、车辆和司机雪花 ID 均按 JSON String 发送和读取,禁止转为 JavaScript `Number`。金额字段也按 String 读取。 - -## 二、605041 公共响应契约 - -### 2.1 统一响应外层 - -```json -{ - "code": 605041, - "message": "订单行程或用车派单已变化,请按逐日差异处理后重试", - "data": { - "dailyDifferences": [ - { - "serviceDate": "2026-07-22", - "differenceType": "CAPACITY_INSUFFICIENT", - "assignmentId": null, - "assignmentSlotId": null, - "passengerCount": 8, - "passengerCapacity": 5, - "capacityGap": 3, - "message": "车辆载客量不足,已按每车司机占一座计算" - } - ] - }, - "traceId": "7db459fd-0b8e-4f29-9c46-4938f09a001", - "success": false -} -``` - -注意: - -- `data` 的完整类型取决于调用的是 create、change 还是 confirm,不能跨接口复用成功响应模型。 -- 除本文件明确保证的失败字段外,其余成功态字段在 `605041` 时为空,前端不得用它们推断写入结果。 -- `traceId` 用于反馈和日志定位,不参与业务判断。 - -### 2.2 `dailyDifferences[]` - -| 字段 | 类型 | 说明 | -|---|---|---| -| `serviceDate` | String/null | 发生差异的服务日,格式 `yyyy-MM-dd`;无法定位到单日时为空 | -| `differenceType` | String | 差异类型,取值见下表 | -| `assignmentId` | String/null | 可定位到具体派单时返回;仅用于定位差异,不代表本次写入成功 | -| `assignmentSlotId` | String/null | 可定位到稳定车辆槽位时返回 | -| `passengerCount` | Integer/null | 当前比对使用的乘客人数,不含司机 | -| `passengerCapacity` | Integer/null | 当日车辆合计可载客人数,每辆车已扣除司机一座 | -| `capacityGap` | Integer/null | 缺少座位数,等于 `passengerCount - passengerCapacity` | -| `message` | String | 后端生成的差异说明,可直接辅助展示 | - -差异类型: - -| `differenceType` | 含义 | -|---|---| -| `REQUIREMENT_VERSION_MISMATCH` | 当前生效用车需求已变化,或订单/需求已不可继续派单 | -| `ORDER_DATE_MISMATCH` | 订单当前日期与用车需求冻结日期不一致 | -| `ITINERARY_DATE_MISMATCH` | 逐日行程日期与用车需求冻结日期不一致,或缺少逐日行程 | -| `ASSIGNMENT_DATE_MISSING` | 某服务日缺少有效派单或车辆槽位 | -| `ASSIGNMENT_DATE_EXTRA` | 派单仍包含已不属于当前需求的服务日 | -| `HEADCOUNT_BASELINE_MISMATCH` | 订单当前人数、需求冻结人数或派单人数快照不一致 | -| `CAPACITY_INSUFFICIENT` | 当日所有车辆合计载客量不足 | - -`dailyDifferences` 可能同时包含多种类型、多条服务日记录。前端应遍历数组展示,不得只取第一条,也不得自行重算人数或车辆容量。 - -## 三、创建派单 create - -### 3.1 请求 - -```http -POST /admin/fleet/assignments -Authorization: Bearer -Content-Type: application/json -``` - -```json -{ - "orderId": "2078001000000000101", - "orderNo": "26-0719", - "requirementId": "2078001000000000201", - "fleetItemIndex": 1, - "vehicleId": "2078001000000000301", - "driverId": "2078001000000000401", - "startDate": "2026-07-21", - "endDate": "2026-07-23", - "pickupAt": "海拉尔", - "dropoffAt": "满洲里", - "headcount": 8, - "protocolPrice": "1300.00", - "holdMode": 0, - "fromEntry": "from-board", - "skipCityJunctionException": false, - "strictSeats": true, - "confirmCrossResident": false, - "requestId": "fleet-create-4938-20260719-001" -} -``` - -`605041` 只适用于 `holdMode=0`。原有 `holdMode=1` 排车锁定流程不执行本次最终基线门禁。 - -### 3.2 holdMode=0 成功响应 - -```json -{ - "code": 200, - "message": "成功", - "data": { - "id": "2078001000000000501", - "assignmentGroupId": "2078001000000000601", - "assignmentSlotId": "2078001000000000701", - "assignmentStatus": "assigned", - "stageCode": "assigned", - "stageLabel": "已派车", - "currentStep": 4, - "skippedStepCodes": [ - "DRIVER_CONFIRMATION", - "DRIVER_CONFIRMATION_EVIDENCE" - ], - "protocolPrice": "1300.00", - "holdSentAt": null, - "confirmedAt": "2026-07-19 14:20:00", - "sideEffects": { - "vehicleStatusUpdated": "busy", - "driverStatusUpdated": "busy", - "reconPrepRowsCreated": 0, - "reconPrepMarkedCanceled": null - }, - "dailyDifferences": null - }, - "traceId": "7db459fd-0b8e-4f29-9c46-4938c200001", - "success": true -} -``` - -仅在 `code=200` 时把新派单加入页面;`id`、`assignmentGroupId`、`assignmentSlotId` 均按 String 保存。 - -### 3.3 605041 失败响应 - -```json -{ - "code": 605041, - "message": "订单行程或用车派单已变化,请按逐日差异处理后重试", - "data": { - "id": null, - "assignmentGroupId": null, - "assignmentSlotId": null, - "assignmentStatus": null, - "stageCode": null, - "stageLabel": null, - "currentStep": null, - "skippedStepCodes": null, - "protocolPrice": null, - "holdSentAt": null, - "confirmedAt": null, - "sideEffects": null, - "dailyDifferences": [ - { - "serviceDate": "2026-07-22", - "differenceType": "CAPACITY_INSUFFICIENT", - "assignmentId": null, - "assignmentSlotId": null, - "passengerCount": 8, - "passengerCapacity": 5, - "capacityGap": 3, - "message": "车辆载客量不足,已按每车司机占一座计算" - } - ] - }, - "traceId": "7db459fd-0b8e-4f29-9c46-4938c605041", - "success": false -} -``` - -此时不得把临时响应内容加入派单列表,不得本地占用车辆/司机;刷新后仍以服务端最新详情为准。 - -## 四、修改派单 change - -### 4.1 请求 - -```http -POST /admin/fleet/assignments/2078001000000000501/change -Authorization: Bearer -Content-Type: application/json -``` - -```json -{ - "effectiveDate": "2026-07-22", - "newVehicleId": "2078001000000000302", - "newDriverId": "2078001000000000402", - "holdMode": 0, - "protocolPrice": "1688.00", - "confirmCrossResident": false, - "reason": "订单调整后更换车辆和司机", - "requestId": "fleet-change-4938-20260719-001" -} -``` - -`newVehicleId`、`newDriverId` 至少传一个。`605041` 只适用于 `holdMode=0`;`holdMode=1` 仍按排车待司机确认流程处理。 - -### 4.2 holdMode=0 成功响应 - -```json -{ - "code": 200, - "message": "成功", - "data": { - "assignmentId": "2078001000000000502", - "assignmentSlotId": "2078001000000000701", - "previousAssignmentGroupId": "2078001000000000601", - "newAssignmentGroupId": "2078001000000000602", - "assignmentStatus": "assigned", - "effectiveDate": "2026-07-22", - "affectedDays": 2, - "protocolPrice": "1688.00", - "otherVehicleCount": 1, - "warningCode": "ORDER_HAS_OTHER_VEHICLES", - "warningMessage": "该订单另有1个车辆槽位,当前仅修改本车辆,请核对其它车辆安排", - "otherVehicles": [ - { - "assignmentSlotId": "2078001000000000702", - "vehiclePlate": "蒙B-66666", - "driverName": "李师傅", - "startDate": "2026-07-21", - "endDate": "2026-07-23" - } - ], - "dailyDifferences": null - }, - "traceId": "7db459fd-0b8e-4f29-9c46-4938a200001", - "success": true -} -``` - -change 成功响应没有 `confirmed` 和 `sideEffects` 字段。只有 `code=200` 时才能用新派车组替换页面中的旧版本;`warningCode=ORDER_HAS_OTHER_VEHICLES` 时继续保留既有强提示。 - -### 4.3 605041 失败响应 - -```json -{ - "code": 605041, - "message": "订单行程或用车派单已变化,请按逐日差异处理后重试", - "data": { - "assignmentId": null, - "assignmentSlotId": null, - "previousAssignmentGroupId": null, - "newAssignmentGroupId": null, - "assignmentStatus": null, - "effectiveDate": null, - "affectedDays": null, - "protocolPrice": null, - "otherVehicleCount": null, - "warningCode": null, - "warningMessage": null, - "otherVehicles": null, - "dailyDifferences": [ - { - "serviceDate": null, - "differenceType": "HEADCOUNT_BASELINE_MISMATCH", - "assignmentId": null, - "assignmentSlotId": null, - "passengerCount": 8, - "passengerCapacity": null, - "capacityGap": null, - "message": "订单当前人数与用车需求冻结人数不一致" - }, - { - "serviceDate": "2026-07-22", - "differenceType": "CAPACITY_INSUFFICIENT", - "assignmentId": null, - "assignmentSlotId": null, - "passengerCount": 8, - "passengerCapacity": 5, - "capacityGap": 3, - "message": "车辆载客量不足,已按每车司机占一座计算" - } - ] - }, - "traceId": "7db459fd-0b8e-4f29-9c46-4938a605041", - "success": false -} -``` - -此时旧派单和原派车组仍是有效业务状态。不得用 `dailyDifferences[].assignmentId` 替换页面主键,也不得本地切换车辆、司机或状态。 - -## 五、最终确认 confirm - -### 5.1 请求 - -```http -POST /admin/fleet/assignments/2078001000000000501/confirm -Authorization: Bearer -Content-Type: application/json -``` - -```json -{ - "requestId": "fleet-final-confirm-4938-20260719-001" -} -``` - -| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | -|---|---|---|---|---|---| -| `assignmentId` | Path | String | 是 | 有效派单 ID | 当前派车组中的任一派单 ID | -| `requestId` | Body | String | 是 | 非空,最长 64 | 最终确认幂等标识 | - -### 5.2 成功响应 - -```json -{ - "code": 200, - "message": "成功", - "data": { - "confirmed": true, - "assignmentStatus": "assigned", - "stageCode": "assigned", - "stageLabel": "已派车", - "currentStep": 4, - "assignmentGroupId": "2078001000000000601", - "confirmedAt": "2026-07-19 14:30:00", - "itineraryUrl": "https://h5.example.com/#/itinerary/", - "sideEffects": { - "vehicleStatusUpdated": "busy", - "driverStatusUpdated": "busy", - "reconPrepRowsCreated": 0, - "reconPrepMarkedCanceled": null - }, - "dailyDifferences": null - }, - "traceId": "7db459fd-0b8e-4f29-9c46-4938f200001", - "success": true -} -``` - -`itineraryUrl` 签发配置不可用时允许为空,不影响确认成功。前端只有在 `code=200 && data.confirmed===true` 时展示最终确认成功,并刷新派单详情、看板列表和汇总。 - -### 5.3 日期、人数与容量同时存在差异 - -```json -{ - "code": 605041, - "message": "订单行程或用车派单已变化,请按逐日差异处理后重试", - "data": { - "confirmed": false, - "assignmentStatus": null, - "stageCode": null, - "stageLabel": null, - "currentStep": null, - "assignmentGroupId": null, - "confirmedAt": null, - "itineraryUrl": null, - "sideEffects": null, - "dailyDifferences": [ - { - "serviceDate": "2026-07-21", - "differenceType": "ORDER_DATE_MISMATCH", - "assignmentId": null, - "assignmentSlotId": null, - "passengerCount": null, - "passengerCapacity": null, - "capacityGap": null, - "message": "订单当前日期与用车需求冻结日期不一致" - }, - { - "serviceDate": null, - "differenceType": "HEADCOUNT_BASELINE_MISMATCH", - "assignmentId": null, - "assignmentSlotId": null, - "passengerCount": 8, - "passengerCapacity": null, - "capacityGap": null, - "message": "订单当前人数与用车需求冻结人数不一致" - }, - { - "serviceDate": "2026-07-22", - "differenceType": "CAPACITY_INSUFFICIENT", - "assignmentId": null, - "assignmentSlotId": null, - "passengerCount": 8, - "passengerCapacity": 5, - "capacityGap": 3, - "message": "车辆载客量不足,已按每车司机占一座计算" - } - ] - }, - "traceId": "7db459fd-0b8e-4f29-9c46-4938f605041", - "success": false -} -``` - -### 5.4 缺少某日车辆槽位 - -```json -{ - "code": 605041, - "message": "订单行程或用车派单已变化,请按逐日差异处理后重试", - "data": { - "confirmed": false, - "assignmentStatus": null, - "stageCode": null, - "stageLabel": null, - "currentStep": null, - "assignmentGroupId": null, - "confirmedAt": null, - "itineraryUrl": null, - "sideEffects": null, - "dailyDifferences": [ - { - "serviceDate": "2026-07-23", - "differenceType": "ASSIGNMENT_DATE_MISSING", - "assignmentId": null, - "assignmentSlotId": null, - "passengerCount": null, - "passengerCapacity": null, - "capacityGap": null, - "message": "该服务日缺少第2个车辆槽位派单" - } - ] - }, - "traceId": "7db459fd-0b8e-4f29-9c46-4938f605042", - "success": false -} -``` - -## 六、前端统一处理顺序 - -1. 先判断业务 `code`,再读取端点自己的 `data`: - - `code=200`:按对应成功模型处理; - - `code=605041`:按对应失败模型读取 `dailyDifferences`; - - 其他业务码:继续走既有错误处理。 -2. `605041` 时不要乐观更新: - - create 不新增本地派单; - - change 不替换旧派单; - - confirm 不改为 `assigned` 或“已确认”。 -3. 展示顶层 `message`,并按 `dailyDifferences` 列出服务日、差异类型、人数、容量和缺口;字段为空时隐藏对应展示项。 -4. 重新请求最新订单和车务详情,避免继续使用操作前缓存。 -5. 用户修正订单日期、行程、人数或派单后,生成新的 `requestId` 再提交新动作;仅在同一次动作网络结果不确定时复用原 `requestId`。 - -## 七、其他直接错误分支 - -| 业务码 | 常见场景 | 前端处理 | -|---|---|---| -| `605009` | 派单不存在 | 刷新详情和看板,停止操作旧记录 | -| `605020` | 当前状态不允许操作 | 刷新最新生命周期与操作能力 | -| `605025` | 最终确认前缺少司机确认或有效凭证 | 引导先完成司机确认与凭证登记 | -| `605001` / `605003` | 车辆或司机档期冲突 | 展示后端错误并重新选车/司机 | -| `605036` | 跨常驻车未显式确认 | 二次提示后携带 `confirmCrossResident=true` 重试 | -| `605041` | 订单、需求、行程、逐日派单、人数或容量基线不一致 | 使用当前端点的 `data.dailyDifferences` 展示并处理 | - -请求字段为空、格式不正确或超过长度限制时走统一参数校验错误,前端应在发请求前完成同样约束。 - -## 八、不影响范围 - -- 不新增管理后台接口,三个接口的请求字段结构保持不变。 -- `holdMode=1` 的排车锁定、司机确认与凭证登记流程保持不变。 -- 不改变取消、司机拒接、驳回需求、撤销取消和提前完结的前端调用契约。 -- 不要求前端计算订单人数、逐日服务日期或车辆载客量,这些均由后端权威校验并返回差异。 -- 本文件只描述管理后台直接消费的 HTTP 契约,不包含服务间调用或发布实现细节。 - -## 九、验收状态与待补证据 - -已完成: - -- 当前 worktree 中 create、change、confirm Controller 的 `605041` 强类型 `data` 静态核对。 -- `AssignmentWriteRespVO`、`ChangeAssignmentRespVO`、`ConfirmRespVO` 与 `dailyDifferences` 字段静态核对。 -- 三条失败路径不提交派单及其关联业务状态变化的源码顺序核对。 - -合并和部署后仍需补充: - -- 三个接口在测试环境 OpenAPI 中的请求/响应模型截图或导出差异。 -- 经网关分别取得 create、change、confirm 的成功响应和 `605041` 真实响应,记录 HTTP 状态、业务码、`traceId` 与完整 `data`。 -- 对 `605041` 前后做测试业务数据对照,确认派单版本/状态、车辆司机占用、保险、对账和订单派定结果未发生变化。 -- 管理后台页面联调证据:差异列表展示、空字段处理、刷新行为、禁止乐观更新,以及修正后重新提交成功。