14 KiB
14 KiB
【前端告知·管理后台】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 主矩阵
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。 |
真实响应例子:
{
"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 未派订单窗口
GET /admin/fleet/matrix/unassigned-orders?year=2026&month=7&typeKeys=suv&typeKeys=mpv
真实响应例子:
{
"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 点击某天订单清单
GET /admin/fleet/matrix/day-orders?date=2026-07-06
真实响应例子:
{
"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 车费对账
GET /admin/fleet/reconciliation/cars?periodStart=2026-07-01&periodEnd=2026-07-31
响应例子:
{
"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 保险对账
GET /admin/fleet/reconciliation/insurance?periodStart=2026-07-01&periodEnd=2026-07-31
响应例子:
{
"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月。 - 顶部月份按钮可以用本地月份范围生成,也可以调用:
GET /admin/fleet/reconciliation/periods?fromMonth=2026-01
- 录入实付金额、关账、重开账使用已有写接口;不要在前端本地保存。
- 公共分页上限仍是 100。对账主数据本身不分页,不需要
pageSize=1000。
5. 车管模板页没数据时优先检查是否调用真实接口
车管模板列表是非分页接口:
GET /admin/fleet/message-templates
响应例子:
{
"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、定制师账号验证车务菜单。
8. 2026-07-27 补充:矩阵车辆行常驻司机全部误显示“待派司机”
8.1 运行态与源码证据
/fleet/matrix的 19 条车辆行全部显示“待派司机”。- 同次页面请求
GET /admin/fleet/matrix/grid返回 200;响应车辆中存在非空primaryDriverName和脱敏primaryDriverPhone,因此不是后端漏返回,也不是全部车辆都未绑定常驻司机。 useFleetMatrixData.adaptMatrixVehicle()已把这两个字段保留到车辆行对象。VehicleGantt.primaryDriverOf(v)却忽略车辆行字段,只执行findPrimaryDriver(props.drivers, v.plate)。- 主矩阵和车辆分窗传入的
drivers均为空列表且没有额外加载动作,所以每辆车都稳定落入 “待派司机”空态。
8.2 前端修复口径
- 矩阵车辆行展示必须以
data.vehicles[].primaryDriverName为权威来源;非空时直接显示该姓名。 primaryDriverPhone已由后端脱敏,可按现有设计选择展示,但不得为显示姓名再拉全量司机列表。- 只有
primaryDriverName为null或空白时,才显示“待派司机”空态。 - 主矩阵和
matrix-solo?solo=byVehicle必须复用同一解析逻辑,不能一处读取车辆行、一处反查本地司机数组。 - 本问题不涉及后端接口、数据库、派单状态或候选规则变更;不要创建
mmg/hl-ui配合工单,直接消费本 changelog。
8.3 前端验收 checklist
- 构造一辆
primaryDriverName非空的车辆,主矩阵车辆行显示接口姓名而不是“待派司机”。 primaryDriverName=null的车辆仍显示“待派司机”。- 车辆分窗与主矩阵展示一致。
- 车队、车型、状态筛选及派车占用条不受本次展示修复影响。