# hl-ui v2.1 车务接口复核差异告知 - 日期:2026-07-07 - 复核对象:`D:/work2/hl-ui`,分支 `v2.1`,最新提交 `fd7f4392` - 复核依据:`HL-v3 dev-v3` 当前代码与 `docs/order-v3/api/API-SPEC-FLEET-V1.5.html` - 结论:车务部分 API 文件已接入真实接口,但仍有若干页面/动作没有完全按真实契约走。请前端优先修下面 P0/P1 项。 ## P0 · 必须修 ### 1. 车队对账录入实付方法错了 前端文件:`src/api/fleet/reconciliation.js` 当前: ```js export function updateFleetReconciliationActual(data, config = {}) { return http.post(`${BASE}/actual`, data, config) } ``` 后端真实接口: ```http PUT /admin/fleet/reconciliation/actual Content-Type: application/json { "periodStart": "2026-07-01", "periodEnd": "2026-07-31", "fleet": "own", "actualAmount": "58000.00", "note": "线下结算单号/备注" } ``` 响应示例: ```json { "code": 200, "data": { "fleet": "own", "actualAmount": "58000.00", "payableEstimated": "58500.00", "diff": "-500.00", "closed": false } } ``` 前端需要改成 `http.put(`${BASE}/actual`, data, config)`。 ### 2. 车队对账期不能继续用本地月份预设 前端文件: - `src/views/fleet/recon/index.vue` - `src/views/fleet/recon/components/PeriodBar.vue` - `src/views/fleet/recon/composables/useReconCompute.js` 当前页面月份来自 `MONTH_PRESETS` 本地生成,未使用已封装的 `getFleetReconciliationPeriods`。这会导致当前 2026-07 仍可能停留在历史月份/本地缓存月份,且拿不到后端关账态。 后端真实接口: ```http GET /admin/fleet/reconciliation/periods?fromMonth=2026-01 ``` 响应示例: ```json [ { "label": "2026-07", "periodStart": "2026-07-01", "periodEnd": "2026-07-31", "closed": false, "reopened": false }, { "label": "2026-06", "periodStart": "2026-06-01", "periodEnd": "2026-06-30", "closed": true, "reopened": false } ] ``` 前端应以 `GET /fleet/reconciliation/periods` 为对账期下拉数据源;本地月份只能作为接口失败兜底,不应作为主数据源。 ### 3. 派单看板列表字段映射错了,已派车信息会读不到 前端文件:`src/views/fleet/board/index.vue` 后端 `GET /admin/fleet/board/orders` 列表行不是 `currentAssignment` 结构,而是平铺字段: ```json { "id": "HL202607010001", "orderId": "2074000000000000001", "assignmentId": "2074000000000000002", "fleetItemIndex": 0, "assignmentStatus": "assigned", "currentVehiclePlate": "蒙A-88888", "currentVehicleModel": "丰田普拉多", "currentVehicleSeats": 7, "currentVehicleFleet": "own", "currentDriverName": "王师傅", "currentDriverPhone": "138****1234", "protocolPrice": null } ``` 当前 `normalizeBoardOrder()` 主要读 `assignment.plate / row.vehiclePlate / row.driverName`,会漏掉真实字段。应补齐: ```js vehicle: assignment.vehiclePlate || row.currentVehiclePlate || row.vehiclePlate || '', driverName: assignment.driverName || row.currentDriverName || row.driverName || '', driverPhone: assignment.driverPhone || row.currentDriverPhone || row.driverPhone || '', vehicleModel: row.currentVehicleModel, vehicleSeats: row.currentVehicleSeats, vehicleFleet: row.currentVehicleFleet, assignmentId: assignment.id || row.assignmentId, protocolPrice: assignment.protocolPrice ?? row.protocolPrice ?? null ``` 注意:列表行没有 `vehicleId/driverId`,不要用 mock store 二次 join 假数据。 ### 4. 看板详情当前派单字段也映射错了 前端文件: - `src/views/fleet/board/index.vue` - `src/views/fleet/board/components/OrderDrawer.vue` 后端 `GET /admin/fleet/board/orders/{orderId}` 的 `currentAssignment` 示例: ```json { "currentAssignment": { "id": "2074000000000000002", "vehiclePlate": "蒙A-88888", "driverName": "王师傅", "assignmentStatus": "holding", "protocolPrice": "1300.00", "holdSentAt": "2026-07-07T10:00:00", "itineraryUrl": null } } ``` 当前前端读 `assignment.plate`,应改读 `assignment.vehiclePlate`。详情接口没有返回 `driverId/vehicleId`,抽屉展示不要从 `useFleetStore` mock 反查司机和车辆。 ### 5. 取消派单请求体不满足后端门禁 前端文件:`src/views/fleet/board/index.vue` 当前取消动作传: ```js await cancelAssignment(o.assignmentId, { cancelReason: '车务后台取消', driverNotified: false, }) ``` 后端真实要求:`driverNotified` 必须为 `true`,否则返回参数错误。 正确请求: ```http DELETE /admin/fleet/assignments/{assignmentId} Content-Type: application/json { "cancelReason": "司机拒接,重新派车", "driverNotified": true, "notifyNote": "已电话告知王师傅", "cutoffDate": "2026-07-07" } ``` 同时前端按钮文案不要写“取消订单”。该接口是“取消派单”,不是客户订单退单。客户退单/取消订单不在车务模块处理。 ### 6. 司机拒接/请求换车等抽屉动作仍是 mock 本地状态 前端文件: - `src/views/fleet/board/index.vue` - `src/stores/fleet.js` 当前: - `司机拒接` 调 `fleet.rejectAssign(o.id)`,只改前端 mock store。 - `请求更换车辆 / 撤销请求` 调 `fleet.requestChange/cancelChange`,只改前端 mock store。 这些不会落后端,不会触发占用释放、保险、对账 prep、操作日志。前端应先隐藏或改接真实车务接口: - 司机拒接后退回待派:走 `DELETE /admin/fleet/assignments/{assignmentId}`,且 `driverNotified=true`。 - 已派单不可直接驳回用车需求;要先取消派单并完成司机告知存证。 - 换车请求当前后端文档标为未落地完整闭环,不要用 mock 状态制造假成功。 ### 7. 车辆/司机档案里的“派活”订单选择仍从 mock store 取单 前端文件: - `src/views/fleet/components/OrderPickerDrawer.vue` - `src/views/fleet/vehicles/index.vue` - `src/views/fleet/drivers/index.vue` - `src/stores/fleet.js` 当前 `OrderPickerDrawer` 从 `fleetStore.orders` 取 mock 订单。真实入口应使用后端未派数据: ```http GET /admin/fleet/matrix/unassigned-orders?year=2026&month=7&typeKeys=suv&typeKeys=mpv ``` 或使用看板分页: ```http GET /admin/fleet/board/orders?page=1&pageSize=20&statuses=unassigned ``` 返回行里关键字段: ```json { "assignmentId": "2074000000000000002", "orderNumericId": "2074000000000000001", "orderNo": "HL202607010001", "fleetItemIndex": 0, "vehicleCategory": "suv", "categoryLabel": "SUV", "startDate": "2026-07-10", "endDate": "2026-07-12", "headcountLabel": "3人" } ``` 派单弹窗必须拿真实 `orderNumericId/assignmentId/fleetItemIndex/requirementId`,不能拿 mock 订单 ID。 ### 8. 派单弹窗预选车辆不能传车牌当 vehicleId 前端文件: - `src/views/fleet/_shared/gantt/composables/useAssignAction.js` - `src/views/fleet/board/components/AssignModal.vue` - `src/views/fleet/board/composables/useVehicleDriverPicker.js` 后端创建派单要求: ```json { "vehicleId": "2074000000000000101", "driverId": "2074000000000000102", "orderId": "2074000000000000001", "startDate": "2026-07-10", "endDate": "2026-07-12", "holdMode": 1, "protocolPrice": "1300.00" } ``` 当前从矩阵/车辆档案预选时常传 `vehicle.plate`,但 `useVehicleDriverPicker` 内部选项 `valueKey` 优先是车辆 `id`。应统一: - 选择值使用 `vehicleId`。 - 展示字段使用 `plate`。 - 如果入口只能拿到车牌,必须先从 `/fleet/vehicles/page` 结果中找到对应 `id`,否则不要预选。 ## P1 · 需要尽快对齐 ### 9. 车务工作台数据入口对了,但“配车”按钮仍打开旧订单配车组件 前端文件: - `src/views/dashboard/components/VehicleDashboard.vue` - `src/views/order/components/VehicleInfoModal.vue` 工作台数据源 `GET /admin/profile/dashboard?period=today` 是对的;但“配车”按钮打开的是旧 `VehicleInfoModal`,里面调用旧订单接口 `assignVehicle/checkVehicleInfoDiff`,不是车务派单闭环。 建议:点击工作台“配车”应跳转/打开车务看板详情或复用 `FleetAssignModal`,走: - `GET /admin/fleet/board/orders/{orderId}` - `POST /admin/fleet/assignments` - `POST /admin/fleet/assignments/{assignmentId}/confirm` ### 10. 矩阵订单详情抽屉 action 事件参数不匹配 前端文件:`src/views/fleet/matrix/index.vue` `OrderDrawer` 发的是字符串: ```js emit('action', 'assign') ``` 矩阵页接收写成: ```js function onDrawerAction({ type }) { if (type === 'assign') ... } ``` 这会导致矩阵详情抽屉内派车/重派动作不触发。应改成接字符串,或统一事件对象格式。 ### 11. 消息模板 delete 的 config 传参位置不一致 前端文件:`src/api/fleet/message-template.js` 当前: ```js return http.delete(`${BASE}/${String(templateId)}`, config) ``` `http.delete(url, data, config)` 签名下,这会把 config 当请求 body。建议统一为: ```js return http.delete(`${BASE}/${String(templateId)}`, null, config) ``` 无 config 时影响不大;需要 `silentError/cancelDuplicate` 时会出问题。 ### 12. 车队对账导出目前是前端本地 CSV,不是后端文件流 前端文件:`src/views/fleet/recon/index.vue` 后端已有: ```http GET /admin/fleet/reconciliation/export/cars?periodStart=2026-07-01&periodEnd=2026-07-31 ``` 如果前端要保证和后端对账口径、BOM、文件名完全一致,车费对账导出建议改用后端文件流。本地 CSV 可保留作兜底。 ## 可以保留的部分 - `src/api/fleet/board.js` 路径整体正确:summary/orders/detail/timeline/precheck/create/confirm/cancel/reject/restore/early-complete 都能对上后端。 - `src/api/fleet/matrix.js` 三个接口路径正确:grid/unassigned-orders/day-orders。 - `src/api/fleet/vehicles.js`、`vehicle-types.js`、`drivers.js`、`pricing.js`、`insurance.js` 主路径基本正确。 - `@/mock/fleet` 中仅作为展示常量/文案 helper 使用可以暂留;但不能作为车务真实数据源,尤其不能作为订单、车辆、司机、派单状态的写入源。 ## 前端自测建议 1. 用车务角色登录,不用 admin/wx。 2. 打开车务工作台,确认数据来自 `GET /admin/profile/dashboard?period=today`,点击“配车”不要进入旧 `VehicleInfoModal`。 3. 车务看板列表检查已派行:车牌、司机、协议价、派单状态都来自 `current*` 或 `currentAssignment` 真实字段。 4. 打开订单详情后再派单,确认 `POST /admin/fleet/assignments` 请求体里 `vehicleId/driverId/orderId` 都是雪花字符串,不是车牌/订单号。 5. 取消派单必须先勾选/确认“已告知司机”,请求体 `driverNotified=true`。 6. 车队对账切到当前月份 2026-07,月份来源应为 `/fleet/reconciliation/periods`;录入实付必须发 `PUT /fleet/reconciliation/actual`。