一些检查失败了
changelog-filename-gate / validate (push) Failing after 1s
修改原因:hl-ui changelog loop 需要把前端消费进度回写到契约源,避免领取、实现状态与实际交付脱节。 修改内容:将 frontend_status 与已有 legacy frontend 同步为 implemented,记录负责人 hl-ui-codex,并关联 mmg/hl-ui@594dfa44b497b40a1e75c81b3e60abba8deb6137;发布和验收字段保持不变。 实际验证:回写器已校验目标文件、状态单调性、提交范围和 Front Matter 内容,提交只包含当前 changelog。 Frontend-Status: tools/mcp-api-sync/.changelog-repo/changelogs-v2/2026-07/26_5257_车务看板按用车需求聚合多车型槽位-修改接口-管理后台.md
12 KiB
12 KiB
schema, ticket, title, consumer, change_type, backend_status, gateway_status, frontend_status, frontend_owner, frontend_ref, target_release, verified_at, status_note, updated_at, base
| schema | ticket | title | consumer | change_type | backend_status | gateway_status | frontend_status | frontend_owner | frontend_ref | target_release | verified_at | status_note | updated_at | base |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| hl-changelog/v2 | 5257 | 车务看板按用车需求聚合多车型槽位 | admin | 修改接口 | deployed | verified | implemented | hl-ui-codex | mmg/hl-ui@594dfa44b4 | 2026-07-26T11:13:51+08:00 | 后端 PR #5259 已合并为 dev-v3@01bf9c627,并重新部署测试环境及通过网关复验;本契约明确替代 #5216 的按槽位卡片维度。前端尚未认领,需按需求卡消费 assignmentSlots。 | 2026-07-26T03:40:29.152Z | dev-v3 |
车务看板按用车需求聚合多车型槽位
关联
- Issue: wx/HL#5257
- 服务:
hl-fleet-service - 前端仓库/分支:
mmg/hl-ui/v2.1 - 影响范围: 车务管理 → 派车看板列表、需求卡和需求详情
- 被本契约替代的旧口径: #5216 派车看板补充槽位接送路线与就绪摘要 中“每张卡对应一个稳定车辆槽位”的维度说明
关键变化
同一订单的一条当前有效用车需求可能同时需要多种车型、多个车辆槽位。例如
SUV×1 + 商务车×1 是 1 条用车需求、合计 2 辆车,不能显示成 2 条“用车需求”。
GET /admin/fleet/board/orders 的 data.records[] 从派车槽位粒度调整为当前
active requirementId 粒度:
- 同一
requirementId只返回一条 record。 requiredVehicles[]展示全部车型组及数量。assignmentProgress.totalSlots展示合计需要的车辆数。- 新增
assignmentSlots[],完整保留逐辆派车身份、状态、车辆和司机。 - 原顶层单槽位字段兼容保留,统一表示当前最需要处理的代表槽位。
- 状态、车型或司机筛选命中需求内任一槽位时,需求只返回一次。
- 后端先按需求聚合,再排序和分页;
total与汇总接口不再按槽位重复计数。
请求参数、路径、HTTP method、响应包络、错误码、数据库和派车执行语义均不变。
变更接口
GET /admin/fleet/board/orders
响应示例
{
"code": 200,
"message": "成功",
"data": {
"records": [
{
"id": "26-5256",
"orderId": "2080200000000000000",
"requirementId": "2080200000000000900",
"requiredVehicles": [
{
"vehicleType": "suv",
"categoryLabel": "SUV",
"seats": 5,
"count": 1
},
{
"vehicleType": "mpv",
"categoryLabel": "商务车",
"seats": 7,
"count": 1
}
],
"assignmentProgress": {
"totalSlots": 2,
"unassignedSlots": 2,
"holdingSlots": 0,
"assignedSlots": 0,
"completedSlots": 0,
"canceledSlots": 0
},
"assignmentStatus": "unassigned",
"assignmentId": "2080200000000000001",
"assignmentSlotId": "2080200000000000101",
"fleetItemIndex": 0,
"canAssign": true,
"canRejectRequirement": true,
"assignmentSlots": [
{
"assignmentId": "2080200000000000001",
"assignmentGroupId": "2080200000000000201",
"assignmentSlotId": "2080200000000000101",
"fleetItemIndex": 0,
"slotSummary": {
"requiredVehicleType": "suv",
"requiredVehicleTypeLabel": "SUV",
"requiredSeats": 5
},
"baseAssignmentStatus": "unassigned",
"assignmentStatus": "unassigned",
"assignmentStatusLabel": "待派车",
"availableActionCodes": ["ASSIGN"],
"vehiclePlate": null,
"vehicleModel": null,
"vehicleSeats": null,
"driverName": null,
"driverPhone": null,
"urgentBadge": null,
"canAssign": true
},
{
"assignmentId": "2080200000000000002",
"assignmentGroupId": "2080200000000000202",
"assignmentSlotId": "2080200000000000102",
"fleetItemIndex": 1,
"slotSummary": {
"requiredVehicleType": "mpv",
"requiredVehicleTypeLabel": "商务车",
"requiredSeats": 7
},
"baseAssignmentStatus": "unassigned",
"assignmentStatus": "unassigned",
"assignmentStatusLabel": "待派车",
"availableActionCodes": ["ASSIGN"],
"vehiclePlate": null,
"vehicleModel": null,
"vehicleSeats": null,
"driverName": null,
"driverPhone": null,
"urgentBadge": null,
"canAssign": true
}
]
}
],
"total": 1,
"page": 1,
"pageSize": 20
},
"success": true
}
新增字段 assignmentSlots[]
所有雪花 ID 必须按字符串消费。
| 字段 | 类型 | 空值 | 说明 |
|---|---|---|---|
assignmentId |
String |
否 | 逐槽位派车/改派操作使用的派单 ID |
assignmentGroupId |
String |
否 | 同一派车组 ID |
assignmentSlotId |
String |
否 | 跨逐日切片稳定的车辆槽位 ID |
fleetItemIndex |
Integer |
否 | 当前需求 fleet[] 展开后的槽位序号,0 起 |
slotSummary |
Object |
否 | 该槽位车型、座位、服务范围和整单槽位数 |
baseAssignmentStatus |
String |
否 | 基础落库态 |
assignmentStatus |
String |
否 | 当前有效状态,可含紧急派生态 |
assignmentStatusLabel |
String |
否 | 后端中文状态标签 |
lifecycleStageCode/lifecycleStageLabel |
String |
否 | 该槽位生命周期阶段 |
currentStep |
Integer |
否 | 该槽位当前步骤 |
availableActionCodes |
String[] |
否 | 该槽位可用动作;需求级驳回不在此数组 |
vehiclePlate/vehicleModel |
String |
是 | 已派车辆信息 |
vehicleSeats |
Integer |
是 | 已派车辆座位数 |
vehicleFleetTeamId |
String |
是 | 已派车辆所属车队 ID |
vehicleFleetTeamName/vehicleFleetTeamType/vehicleFleetTeamSettleType |
String |
是 | 已派车辆所属车队信息 |
driverName |
String |
是 | 已派司机姓名 |
driverPhone |
String |
是 | 已脱敏司机手机号 |
urgentBadge |
String |
是 | T-N 或 Nh;非紧急为 null |
canAssign |
Boolean |
否 | 该槽位是否可进入派车/改派流程 |
顶层兼容字段
以下既有字段没有删除,旧前端继续读取不会报错:
assignmentId/assignmentGroupId/assignmentSlotId/fleetItemIndexslotSummaryassignmentStatus/assignmentStatusLabellifecycleStageCode/lifecycleStageLabel/currentStep/availableActionCodescurrentVehicle*currentDriver*urgentBadge/canAssign/canRejectRequirement
它们统一指向代表槽位,选择优先级为:
未派 → 排车中 → 已派 → 已完成 → 已取消
同级按 fleetItemIndex/assignmentSlotId/assignmentId 稳定排序。部分已派时,顶层仍指向
未派槽位,保证原“派车派人”入口可继续派下一辆;所有槽位的真值以
assignmentSlots[] 和 assignmentProgress 为准。
canRejectRequirement 与需求级驳回动作只读外层 record。任一槽位已进入
holding/assigned 时,外层不会错误开放驳回;槽位级 availableActionCodes 不包含需求级驳回。
筛选、分页和汇总
- 状态多选:任一槽位命中即返回该需求一次。
- 车型多选:任一需求槽位命中即返回该需求一次,
requiredVehicles[]仍保留全部车型。 - 司机筛选/关键词:任一槽位司机命中即返回该需求一次。
- 混合状态:顶层状态取代表槽位状态;完整状态分布读取
assignmentProgress和assignmentSlots[]。 - 空态:无当前有效需求或无 fleet 看板候选时返回
records=[]/total=0,不按人数合成虚假槽位。 - 顺序:先聚合为唯一 requirement record,再确定性排序和分页。
data.total:查询范围内唯一 activerequirementId数,不是车辆槽位数。GET /admin/fleet/board/summary:状态和今日出团数使用相同需求粒度,不重复计数。
守恒关系:
assignmentProgress.totalSlots
== unassignedSlots
+ holdingSlots
+ assignedSlots
+ completedSlots
+ canceledSlots
assignmentProgress.totalSlots
== sum(requiredVehicles[].count)
前端处理清单
- 看板列表对每个
records[]只渲染一张需求卡,不再按fleetItemIndex/assignmentSlotId拆卡,也不得展开assignmentSlots[]生成额外卡片。 - 列表 row key 优先使用
requirementId;仅兼容历史空值时回退id/orderId。 - 需求卡展示
requiredVehicles[]的全部车型组,并显示assignmentProgress.totalSlots为“需要 N 辆车”。 - 需求详情遍历
assignmentSlots[]展示全部车辆槽位、各自状态和已派车辆/司机。 - 顶层按钮可继续使用代表槽位字段;逐辆操作必须使用所选
assignmentSlots[i].assignmentId/fleetItemIndex/assignmentSlotId,不得复用其他槽位 ID。 - 需求级驳回只使用外层
canRejectRequirement/availableActionCodes,不从槽位数组推断。 - 混合状态显示以
assignmentProgress为准,不用顶层单一状态覆盖所有槽位。 - 继续按既有稳定状态 token 映射颜色,不按中文文案判断色值。
- 覆盖单车型×1、多车型各×1、同车型×2、部分已派、全已派、完结/取消和空列表场景。
不影响范围
- 不修改用车需求
fleet[]的业务语义。 - 不合并、删除或改写真实
fleet_assignment;派车仍逐辆、逐槽位执行。 - 不修改派车、确认、取消、改派、需求驳回接口的请求结构。
- 不修改 §7 矩阵派单的车辆槽位维度。
- 不修改数据库、网关路由、错误码、车辆/司机占用、保险或费用。
- 本交接不代表已修改、发布或验证
mmg/hl-ui。
后端验证
- 精确复现测试:同一
requirementId下SUV×1 + 商务车×1返回total=1/records=1、requiredVehicles=2组、assignmentSlots=2、assignmentProgress.totalSlots=2。 - 同车型×2、部分已派、全已派、混合完结/取消、状态多选、聚合后分页和汇总去重均有自动化覆盖。
- 相关定向测试 64 项通过,0 failures/errors。
- OpenAPI diff 状态为
not_configured:当前环境没有oasdiff,仓库也没有可复现的 Swagger 2 → OpenAPI 3 导出链;契约审查保存了 Controller/VO 字段对比和自动化测试 作为人工 fallback 证据。
验证证据
- 后端 commit:
fd641651144ab429ec1b371e1902a70bf3e7f025 - 后端 PR:wx/HL#5259
- 合并 commit:
dev-v3@01bf9c6274d5c40e00e65b84c5224189b0fd06b8 - 合并后测试部署:现有部署 API 已滚动发布
dev-v3,hl-fleet-service:8087/8187均健康;构建、发布成功,部署日志尾部的ERROR/FATAL/Exception命中数为 0。 - 网关复现订单
26-5256:HTTP/业务码均为 200,records=1、total=1、requiredVehicles=SUV×1+MPV×1、assignmentSlots=2且逐槽位 ID 唯一、assignmentProgress.totalSlots=2、状态数量之和为 2;脱敏证据 SHA-256 为7ba2b05d8bdf335207771c59e089357dbe25d1fe0ac4aa0db1c91f910da563f5。 - fleet 定向测试 64 项通过;
mvn -pl hl-fleet-service spotless:check611 个文件通过;mvn -pl hl-fleet-service -am verify中 fleet 2386 项测试 0 failures/errors、skipped 1,完整 reactorBUILD SUCCESS。 - OpenAPI diff 为
not_configured,已保存 Controller/VO 字段对比、兼容语义、 自动化测试和脱敏网关结构作为人工 fallback 证据。 frontend_status=pending:本次未修改、部署或验证mmg/hl-ui; 页面仍需按“1 条需求卡 + 2 个槽位详情”的新契约完成消费。