diff --git a/changelogs-v2/2026-07/27_4760_hl-ui-v2.1车务矩阵对账模板真实接口对接告知-管理后台.md b/changelogs-v2/2026-07/27_4760_hl-ui-v2.1车务矩阵对账模板真实接口对接告知-管理后台.md new file mode 100644 index 0000000..7aca791 --- /dev/null +++ b/changelogs-v2/2026-07/27_4760_hl-ui-v2.1车务矩阵对账模板真实接口对接告知-管理后台.md @@ -0,0 +1,397 @@ +# 【前端告知·管理后台】hl-ui v2.1 车务矩阵/对账/模板需切真实接口 + +> **关联**: wx/HL#4760、wx/HL#4756 +> **前端基线**: `D:\work2\hl-ui`,分支 `v2.1`,本地服务 `http://localhost:9527/` +> **日期**: 2026-07-06 +> **结论**: 本告知只说明前端对接问题,不要求后端修改,也不要求扩大公共分页上限。 + +--- + +## 1. 当前 v2.1 源码确认 + +`hl-ui` 本地业务代码已恢复,当前 `git status` 只有未跟踪 `.serena/`,没有业务文件改动。 + +当前矩阵页仍不是完整真实接口数据,证据如下: + +| 文件 | 当前问题 | +|------|----------| +| `src/stores/fleet.js` | 仍从 `@/mock/fleet` 初始化 `vehicles/drivers/vehicleTypes/orders`。 | +| `src/views/fleet/matrix/index.vue` | 主矩阵读取 `useFleetStore()` 的 `fleet.orders`、`fleet.vehicles`,没有调用 `/admin/fleet/matrix/grid`。 | +| `src/views/fleet/_shared/gantt/composables/useGanttContext.js` | `year=2026`、`currentMonth=5`、`monthToday=4` 是硬编码。 | +| `src/views/fleet/matrix/components/MonthDropdown.vue` | `monthOrders = { 3:6, 4:11, 5:18, 6:14, 7:1000, 8:520 }` 是演示数字;所以 7 月显示 `1000` 不是接口返回。 | +| `src/views/fleet/matrix/components/MatrixFilterBar.vue`、`MatrixLegend.vue`、`DayListModal.vue` | 仍 import `@/mock/fleet`。 | +| `src/views/fleet/matrix/SoloUnassignedView.vue`、`solo/SoloByOrderView.vue`、`solo/SoloByVehicleView.vue` | 分窗仍读取 `useFleetStore()`,也会跟着 mock。 | + +因此页面截图里 `2026-05`、`5月4日`、`21/10/11`、7 月 `1000` 等都不能作为真实接口验收结果。 + +--- + +## 2. 矩阵派单必须接的真实接口 + +### 2.1 主矩阵 + +```http +GET /admin/fleet/matrix/grid?year=2026&month=7&season=active&status=all&fleets=own&fleets=coopA&typeKeys=suv&typeKeys=mpv +``` + +参数说明: + +| 参数 | 说明 | +|------|------| +| `year` / `month` | 必填。默认应取浏览器当前年月,不要硬编码 2026-05。 | +| `season` | 默认 `active`。 | +| `status` | `all` / `unassigned` / `assigned`。 | +| `fleets` | 多选,重复 query key:`fleets=own&fleets=coopA`。 | +| `typeKeys` | 多选,重复 query key:`typeKeys=suv&typeKeys=mpv`。 | + +真实响应例子: + +```json +{ + "code": 200, + "message": "成功", + "success": true, + "data": { + "year": 2026, + "month": 7, + "daysInMonth": 31, + "todayDay": 6, + "weekendDays": [4, 5, 11, 12, 18, 19, 25, 26], + "unassignedWindowCount": 81, + "fleetCount": { "own": 8, "coopA": 5, "coopB": 3 }, + "statusCounts": { + "totalAssignments": 83, + "unassignedAssignments": 82, + "assignedAssignments": 1, + "totalOrders": 82, + "unassignedOrders": 81, + "partialOrders": 0, + "assignedOrders": 1 + }, + "vehicles": [ + { + "id": "2064995255698010113", + "plate": "蒙A-T7777", + "modelName": "丰田普拉多", + "seats": 7, + "fleet": "own", + "primaryDriverName": "宝音德力格尔", + "primaryDriverPhone": "135****5009", + "assignments": [ + { + "id": "2072896404014952450", + "orderId": "HL20260703121250376", + "orderNumericId": "2072896322494492673", + "orderNo": "HL20260703121250376", + "customerName": "客户姓名", + "headcountLabel": "1人", + "startDay": 4, + "endDay": 5, + "startDate": "2026-07-04", + "endDate": "2026-07-05", + "assignmentStatus": "completed", + "isHailarPickup": false, + "isHailarDropoff": false, + "productName": "测试核心产品-单档-固定订金" + } + ] + } + ] + } +} +``` + +前端处理要求: + +- 车辆行来自 `data.vehicles`,订单条来自每辆车的 `assignments`。 +- 月份列数用 `daysInMonth`,今日线用 `todayDay`,不要再用 `5月4日`。 +- 顶部全部/未派/已派计数用 `statusCounts`;未派窗口按钮数量用 `unassignedWindowCount`。 +- 订单条主键优先用 `assignment.id`;打开订单详情或后续写接口时保留 `orderNumericId` 字符串。 +- `headcountLabel`、`isHailarPickup`、`isHailarDropoff` 后端已给,不需要从 mock helper 反推。 + +### 2.2 未派订单窗口 + +```http +GET /admin/fleet/matrix/unassigned-orders?year=2026&month=7&typeKeys=suv&typeKeys=mpv +``` + +真实响应例子: + +```json +{ + "code": 200, + "message": "成功", + "success": true, + "data": [ + { + "orderId": "HL20260627143804674", + "orderNumericId": "2070758545334145025", + "orderNo": "HL20260627143804674", + "assignmentId": "2071040277102952450", + "fleetItemIndex": 0, + "vehicleCategory": "suv", + "categoryLabel": "SUV", + "customerName": "钱曌", + "productName": "测试核心产品-多档-固定比例", + "headcount": 3, + "headcountLabel": "3人", + "startDay": 2, + "endDay": 4, + "startDate": "2026-07-02", + "endDate": "2026-07-04", + "assignmentStatus": "unassigned_urgent", + "urgentBadge": "T-0", + "isHailarPickup": false, + "isHailarDropoff": false + } + ] +} +``` + +前端处理要求: + +- 未派窗口、分窗未派页、订单甘特未派行都应使用这个接口数据。 +- 一单多车会返回多条,行唯一键用 `assignmentId + fleetItemIndex`,不要只按 `orderId` 去重。 +- 拖拽派单时写接口需要带 `orderId=orderNumericId`、`orderNo`、`fleetItemIndex`、`startDate`、`endDate`、`headcount`。 + +### 2.3 点击某天订单清单 + +```http +GET /admin/fleet/matrix/day-orders?date=2026-07-06 +``` + +真实响应例子: + +```json +{ + "code": 200, + "message": "成功", + "success": true, + "data": [ + { + "orderId": "HL20260627113631667", + "orderNumericId": "2070712856860418050", + "orderNo": "HL20260627113631667", + "customerName": "房车冒烟2", + "headcount": 1, + "headcountLabel": "1人", + "startDate": "2026-07-04", + "endDate": "2026-07-06", + "dayInTrip": 3, + "totalDays": 3, + "orderAssignStatus": "unassigned", + "assignments": [ + { + "assignmentId": "2070712882764423170", + "fleetItemIndex": 0, + "vehicleCategory": "mpv", + "categoryLabel": "商务车", + "vehiclePlate": "", + "driverName": "", + "assignmentStatus": "unassigned_urgent" + } + ] + } + ] +} +``` + +前端处理要求: + +- 点击日期列头时调用本接口,不能只从当前本地 `filteredOrders` 过滤。 +- 这个接口按订单聚合,`assignments[]` 展开一单多车明细;适合当天弹窗完整展示。 + +--- + +## 3. 分窗页同步要求 + +矩阵主窗和分窗现在都在用 `useFleetStore()`,所以即使主窗改了 API,分窗仍可能显示 mock。 + +分窗页也必须改成同一个真实数据源: + +| 分窗 | 正确数据源 | +|------|------------| +| `matrix-solo?solo=byVehicle` | `GET /admin/fleet/matrix/grid` 的 `vehicles[].assignments`。 | +| `matrix-solo?solo=byOrder` | `grid` 已派订单 + `unassigned-orders` 未派订单合并展示。 | +| `matrix-solo?solo=unassigned` | `GET /admin/fleet/matrix/unassigned-orders`。 | + +分窗 URL 需要带上当前 `year/month/fleets/typeKeys/status`,否则会和主窗月份/筛选不一致。 + +--- + +## 4. 车队对账不是分页不够,是不分页主数据接口没接 + +车队对账页不要从车辆分页、司机分页或本地 mock 拼数据;后端已提供按周期聚合的不分页主数据接口。 + +### 4.1 车费对账 + +```http +GET /admin/fleet/reconciliation/cars?periodStart=2026-07-01&periodEnd=2026-07-31 +``` + +响应例子: + +```json +{ + "code": 200, + "message": "成功", + "success": true, + "data": { + "periodLabel": "2026-07", + "periodStart": "2026-07-01", + "periodEnd": "2026-07-31", + "fleets": [ + { + "fleet": "own", + "fleetName": "自有", + "orderCount": 16, + "estimatedTotal": "12879.90", + "payableTotal": "12879.90", + "actualTotal": null, + "settleMode": "OWN_COST", + "diff": null, + "closed": false, + "vehicles": [ + { + "vehicleId": "2073712142359445506", + "plate": "蒙A-74638", + "modelName": "别克GL8", + "orderCount": 1, + "days": 1, + "avgPerDay": "1080.00", + "amount": "1080.00", + "payableAmount": "1080.00" + } + ] + } + ], + "grandTotal": { + "estimated": "12879.90", + "payable": "12879.90", + "actual": "0.00", + "diff": "-12879.90", + "totalDays": 16, + "totalOrderCount": 16 + } + } +} +``` + +### 4.2 保险对账 + +```http +GET /admin/fleet/reconciliation/insurance?periodStart=2026-07-01&periodEnd=2026-07-31 +``` + +响应例子: + +```json +{ + "code": 200, + "message": "成功", + "success": true, + "data": { + "periodLabel": "2026-07", + "fleets": [ + { + "fleet": "own", + "sourceSubtotals": { "manual": "0.00", "baoyou": "0.00" }, + "typeCounts": { "annual": 0, "perTrip": 0, "none": 16 }, + "drivers": [ + { + "driverId": "2073712140971089921", + "name": "API师傅74638", + "insuranceType": "none", + "insuranceSource": "NONE", + "billingMethod": "无保险", + "orderCount": 1, + "days": 1, + "insuranceAmount": "0.00" + } + ] + } + ], + "grandTotal": "0.00" + } +} +``` + +前端处理要求: + +- 对账期默认取当前月;今天是 2026-07-06,默认应显示 `2026年7月`,不是 `2026年5月`。 +- 顶部月份按钮可以用本地月份范围生成,也可以调用: + +```http +GET /admin/fleet/reconciliation/periods?fromMonth=2026-01 +``` + +- 录入实付金额、关账、重开账使用已有写接口;不要在前端本地保存。 +- 公共分页上限仍是 100。对账主数据本身不分页,不需要 `pageSize=1000`。 + +--- + +## 5. 车管模板页没数据时优先检查是否调用真实接口 + +车管模板列表是非分页接口: + +```http +GET /admin/fleet/message-templates +``` + +响应例子: + +```json +{ + "code": 200, + "message": "成功", + "success": true, + "data": [ + { + "id": "2073978002412105729", + "templateName": "排车待确认 - 标准", + "templateType": "hold_notify", + "bodyTemplate": "师傅您好,{{order.no}} {{order.startDate}}-{{order.endDate}} 用车待确认,客户 {{order.customer}},人数 {{order.headcount}},车辆 {{vehicle.plate}} {{vehicle.model}},请确认是否接单。", + "variablesHelp": "[{\"key\":\"order.no\",\"label\":\"订单号\"}]", + "isDefault": true, + "sortOrder": 10, + "createTime": "2026-07-06 11:51:03" + } + ] +} +``` + +前端处理要求: + +- 不要拼 `page/pageSize`。 +- 如果页面仍然空,先看浏览器 Network 是否真的请求了 `/admin/fleet/message-templates`,以及当前账号是否为车务角色。 + +--- + +## 6. 分页上限口径 + +这次不要把 VO 改成 fleet 私有 `page/pageSize=1000`,也不要绕过公共分页上限。 + +正确口径: + +| 场景 | 接口类型 | 说明 | +|------|----------|------| +| 车辆列表、司机列表、待审核列表 | 分页接口 | `pageSize <= 100`。 | +| 派单弹窗车辆/司机选择 | 分页或轻量 options | 车辆分页按 10/20 翻页,司机远程搜索用 `/drivers/options?limit<=20`。 | +| 矩阵派单月视图 | 专用不分页聚合 | `/matrix/grid`、`/matrix/unassigned-orders`、`/matrix/day-orders`。 | +| 车队对账 | 专用不分页聚合 | `/reconciliation/cars`、`/reconciliation/insurance`。 | +| 车管模板 | 专用不分页列表 | `/message-templates`。 | +| 车型大类/树 | 专用不分页选项 | `/vehicle-types`、`/vehicle-types/list`。 | + +--- + +## 7. 前端验收 checklist + +- 打开 `http://localhost:9527/fleet/matrix`,Network 必须看到 `/admin/fleet/matrix/grid?year=2026&month=7...`。 +- 矩阵默认月份必须是 `2026-07`,今日线应是 `7月6日`;不得再显示 `2026-05 / 5月4日`。 +- 不得再出现 `MonthDropdown.vue` 的演示 `7月 1000 单`。 +- 打开未派订单窗口,Network 必须看到 `/admin/fleet/matrix/unassigned-orders`。 +- 点击日期列头,Network 必须看到 `/admin/fleet/matrix/day-orders?date=YYYY-MM-DD`。 +- 分窗页不能再使用 `useFleetStore()` 的 mock 数据。 +- 车队对账页 Network 必须看到 `/admin/fleet/reconciliation/cars` 和 `/insurance`,默认周期是当前月 `2026-07-01 ~ 2026-07-31`。 +- 车管模板页 Network 必须看到 `/admin/fleet/message-templates`。 +- 车务菜单测试账号必须是车务角色;不要用 `admin`、`adminle`、`wx`、定制师账号验证车务菜单。