diff --git a/changelogs-v2/2026-07/45_4837_车务每日派车切片与车型大类需求契约-管理后台.md b/changelogs-v2/2026-07/45_4837_车务每日派车切片与车型大类需求契约-管理后台.md new file mode 100644 index 0000000..93bc4de --- /dev/null +++ b/changelogs-v2/2026-07/45_4837_车务每日派车切片与车型大类需求契约-管理后台.md @@ -0,0 +1,396 @@ +# 【前端对接·管理后台】车务每日派车切片与车型大类需求契约 + +> Issue: [wx/HL#4837](https://git.1814.love:8443/wx/HL/issues/4837) +> PR: [#4840](https://git.1814.love:8443/wx/HL/pulls/4840)、[#4841](https://git.1814.love:8443/wx/HL/pulls/4841) +> 服务: `hl-order-service-v3` + `hl-fleet-service` +> 日期: 2026-07-08 +> 影响范围: 订单调整/用车需求、车务派单、矩阵派单、派单看板、车队对账 + +## 1. 结论 + +- 用车需求只选“车型大类”,不要选具体车型型号。前端应从 `GET /admin/fleet/vehicle-types/list` 或树接口的大类节点取 `typeKey`,提交到 `fleet[].vehicleType`。 +- 当前测试库 SUV 大类 `typeKey` 是 `suv2`;后端提交后会归一保存为规范 key `suv`。前端不要自己把 `suv2` 改成具体车型 ID,也不要提交 `modelId/modelName`。 +- `fleet_assignment` 已改为“每日切片”:7 天行程同一辆车会落 7 条记录,每条 `startDate=endDate=serviceDate`。 +- 读接口仍按派车组展示,前端不要把每日切片渲染成 7 张卡。以 `assignmentGroupId` 作为同一连续派车段的稳定分组 key。 +- 历史跨天单条派车记录已通过迁移拆分;新派单创建前也会兜底拆分历史占位,再按派车组消费。 + +## 2. 用车需求车型大类 + +### 2.1 车型大类列表 + +```http +GET /admin/fleet/vehicle-types/list +Authorization: Bearer +``` + +响应示例: + +```json +{ + "code": 200, + "message": "成功", + "success": true, + "data": [ + { + "id": "2057378611889180674", + "typeKey": "suv2", + "typeName": "SUV系列", + "icon": "Car", + "description": null, + "sortOrder": 1, + "modelCount": 5, + "inUseCount": 4 + }, + { + "id": "2057378611889180675", + "typeKey": "mpv", + "typeName": "商务车", + "modelCount": 5, + "inUseCount": 10 + } + ] +} +``` + +前端取值规则: + +| 用途 | 使用字段 | +|------|----------| +| 下拉展示 | `typeName` | +| 提交用车需求 | `typeKey` | +| 不可用于需求提交 | `models[].id`、`models[].modelName`、`vehicleTypeId` | + +### 2.2 车型大类树 + +```http +GET /admin/fleet/vehicle-types +Authorization: Bearer +``` + +响应中会带 `models[]`,这是给车型管理/价格日历/车辆档案使用的型号列表。订单用车需求仍只提交大类节点的 `typeKey`。 + +```json +{ + "code": 200, + "data": [ + { + "id": "2057378611889180674", + "typeKey": "suv2", + "typeName": "SUV系列", + "models": [ + { + "id": "2057378611889180701", + "modelName": "丰田普拉多", + "seats": 7 + } + ] + } + ] +} +``` + +## 3. 提交用车需求 + +```http +PUT /v3/admin/order/2074724409473458177/vehicle-requirement +Authorization: Bearer +Content-Type: application/json + +{ + "fleet": [ + { + "vehicleType": "suv2", + "seats": 7, + "count": 1 + } + ], + "specialTags": ["中文司机", "需要接送机"], + "remark": "司机会蒙语,第 3 天需要儿童安全座椅" +} +``` + +响应示例: + +```json +{ + "code": 200, + "message": "成功", + "success": true, + "data": { + "id": "2074724419590119426", + "version": 1, + "isActive": true, + "status": "PENDING", + "submittedAt": "2026-07-08T13:17:03", + "claimerId": null, + "claimerName": null, + "claimedAt": null, + "branchTaken": "INIT_SUBMIT", + "previousVersion": null, + "assignmentDeletedCount": null + } +} +``` + +后端落库口径: + +```json +[ + { + "vehicleType": "suv", + "seats": 7, + "count": 1 + } +] +``` + +说明: + +- `suv2` 是当前测试库 SUV 大类真实 `typeKey`,后端会归一为 `suv` 参与车务过滤、矩阵、对账。 +- `seats/count` 仍按组提交;每组默认覆盖整个行程,不支持“前几天/后几天车型不同”的 UI。 +- 多车场景仍用多组或 `count>1` 表达,后端会展开为多个 `fleetItemIndex`。 + +## 4. 创建派单与每日切片 + +```http +POST /admin/fleet/assignments +Authorization: Bearer +Content-Type: application/json + +{ + "orderId": "2074724409473458177", + "orderNo": "HL20260708131700144", + "requirementId": "2074724419590119426", + "fleetItemIndex": 0, + "vehicleId": "2065329516292513793", + "driverId": "2074724495473479681", + "startDate": "2026-07-13", + "endDate": "2026-07-18", + "pickupAt": "海拉尔东山机场", + "dropoffAt": "海拉尔站", + "headcount": 2, + "protocolPrice": "700.00", + "holdMode": 0, + "fromEntry": "from-board", + "skipCityJunctionException": false, + "strictSeats": false, + "requestId": "fleet-assign-20260708-001" +} +``` + +响应示例: + +```json +{ + "code": 200, + "message": "成功", + "success": true, + "data": { + "id": "2074724499256741890", + "assignmentGroupId": "333114315542499328", + "assignmentStatus": "assigned", + "protocolPrice": "700.00", + "holdSentAt": null, + "confirmedAt": "2026-07-08T13:17:22", + "sideEffects": { + "vehicleStatusUpdated": true, + "driverStatusUpdated": true + } + } +} +``` + +落库不变量: + +| 字段 | 口径 | +|------|------| +| `assignment_id` | 每日切片自己的 ID | +| `assignment_group_id` | 同一连续派车段共用,前端展示/操作分组 key | +| `start_date` / `end_date` | 每条切片都等于当天服务日 | +| `service_date` | 该条切片服务日 | +| `required_vehicle_type` | 规范车型大类 key,例如 `suv` | +| `protocol_price` | 派车时冻结的协议价日单价 | + +示例:2026-07-13 至 2026-07-18 会落 6 条: + +```json +[ + {"assignmentGroupId": "333114315542499328", "serviceDate": "2026-07-13", "startDate": "2026-07-13", "endDate": "2026-07-13"}, + {"assignmentGroupId": "333114315542499328", "serviceDate": "2026-07-14", "startDate": "2026-07-14", "endDate": "2026-07-14"}, + {"assignmentGroupId": "333114315542499328", "serviceDate": "2026-07-15", "startDate": "2026-07-15", "endDate": "2026-07-15"}, + {"assignmentGroupId": "333114315542499328", "serviceDate": "2026-07-16", "startDate": "2026-07-16", "endDate": "2026-07-16"}, + {"assignmentGroupId": "333114315542499328", "serviceDate": "2026-07-17", "startDate": "2026-07-17", "endDate": "2026-07-17"}, + {"assignmentGroupId": "333114315542499328", "serviceDate": "2026-07-18", "startDate": "2026-07-18", "endDate": "2026-07-18"} +] +``` + +## 5. 矩阵/看板读取口径 + +### 5.1 矩阵月视图 + +```http +GET /admin/fleet/matrix/grid?year=2026&month=7&status=all +``` + +响应片段: + +```json +{ + "code": 200, + "data": { + "year": 2026, + "month": 7, + "daysInMonth": 31, + "vehicles": [ + { + "id": "2065329516292513793", + "plate": "蒙C06E06", + "assignments": [ + { + "id": "2074724499256741890", + "assignmentGroupId": "333114315542499328", + "orderNumericId": "2074724409473458177", + "orderNo": "HL20260708131700144", + "startDay": 13, + "endDay": 18, + "startDate": "2026-07-13", + "endDate": "2026-07-18", + "vehicleCategory": "suv", + "categoryLabel": "SUV", + "assignmentStatus": "assigned", + "protocolPrice": "700.00" + } + ] + } + ] + } +} +``` + +前端处理: + +- 月视图应按 `vehicles[].assignments[]` 渲染,一个 `assignmentGroupId` 只是一条甘特段。 +- 不要再按 DB 每日切片数量重复生成条。 +- 拖拽/操作时优先保留 `assignmentGroupId`;旧接口仍以 `assignmentId` 作为 path var 时,传该组任一 `id` 即可,后端会按组处理已接通的分组操作。 + +### 5.2 矩阵日视图 + +```http +GET /admin/fleet/matrix/day-orders?date=2026-07-13 +``` + +响应片段: + +```json +{ + "code": 200, + "data": [ + { + "orderNumericId": "2074724409473458177", + "orderNo": "HL20260708131700144", + "startDate": "2026-07-13", + "endDate": "2026-07-18", + "dayInTrip": 1, + "totalDays": 6, + "orderAssignStatus": "assigned", + "assignments": [ + { + "assignmentId": "2074724499256741890", + "assignmentGroupId": "333114315542499328", + "fleetItemIndex": 0, + "vehicleCategory": "suv", + "categoryLabel": "SUV", + "vehiclePlate": "蒙C06E06", + "driverName": "API按单险司机4792", + "assignmentStatus": "assigned", + "protocolPrice": "700.00" + } + ] + } + ] +} +``` + +### 5.3 看板详情 + +```http +GET /admin/fleet/board/orders/2074724409473458177 +``` + +响应关注点: + +```json +{ + "code": 200, + "data": { + "transport": { + "batches": [ + { + "travelerNames": "张测试, 李测试", + "transportNo": "CA4792", + "time": "2026-07-13 10:45:00", + "station": "海拉尔东山机场" + }, + { + "travelerNames": "张测试, 李测试", + "transportNo": "K4792", + "time": "2026-07-18 16:30:00", + "station": "海拉尔站" + } + ], + "pickupRequired": true + }, + "operationLog": { + "records": [ + { + "opType": "CONFIRMED", + "detail": { + "assignmentId": "2074724499256741890", + "assignmentGroupId": "333114315542499328", + "requiredVehicleType": "SUV", + "requiredSeats": 7, + "tripRange": "2026-07-13 至 2026-07-18" + } + } + ] + }, + "currentAssignment": { + "id": "2074724499256741890", + "assignmentGroupId": "333114315542499328", + "vehiclePlate": "蒙C06E06", + "driverName": "API按单险司机4792", + "assignmentStatus": "assigned", + "protocolPrice": "700.00" + } + } +} +``` + +说明: + +- 终态 `completed/canceled` 时 `currentAssignment` 可能为 `null`,但操作日志仍保留 `assignmentGroupId`。 +- 大交通接送数据在 `transport.batches[]`;没有接送机/站时间时,调整订单快照接口使用 `vehicleTransportSummary.emptyText = "暂无接送机时间"`,见 44_4829 文档。 + +## 6. 车队对账影响 + +车队对账仍按每日服务日聚合。前端不用直接消费 `fleet_assignment` 每日切片,但要理解金额来源: + +- `GET /admin/fleet/reconciliation/cars` 的车天数来自每日切片/对账 prep。 +- 一个 6 天派车组会贡献 6 个车天。 +- `protocolPrice` 是元/车天快照,估算金额 = 日单价 × 车天。 + +## 7. 本次验证证据 + +已在测试环境验证: + +- 部署:`hl-fleet-service` deploy task `bcac32b8` 成功。 +- 全链路 API:`.tmp/4792_fleet_full_api_report.md`,115/115 passed。 +- 专项契约验证:`.tmp/4837_daily_slice_contract_verify.md`,9/9 passed。 +- 验证订单:`HL20260708131700144` / `2074724409473458177`。 +- 专项断言: + - `fleet_assignment` 未删除记录中 `start_date < end_date` 数量为 0。 + - 主订单 2026-07-13 至 2026-07-18 生成 6 条每日切片。 + - 同一组 `assignmentGroupId=333114315542499328` 在矩阵月视图只出现 1 次。 + - 矩阵日视图 2026-07-13 能查到该派车组。 + - 用车需求提交 `suv2` 后,订单侧保存为规范 `suv`。 +