hl-api-changelog/changelogs-v2/2026-07/27_5292_车务逐日逐车派车与价格-修改接口-管理后台.md
wx 756bc172b4
所有检测均成功
changelog-filename-gate / validate (pull_request) Successful in 1s
fix(changelog): 回退不可达前端提交状态
2026-07-28 11:53:32 +08:00

17 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 5292 车务按服务日逐车配置用车、接机与价格 admin 修改接口 deployed verified claimed hl-ui-pi mmg/hl-ui@7b99fe7d35 2026-07-28 远端仅可达初始实现 7b99fe7d;此前回填的 bb266c0e 在 Gitea 不存在。默认全行程用车和 ARRIVAL 参与复选框仍有页面阻断,故从 implemented 回退 claimed,等待修复、复验并回填最终可达提交 2026-07-28 dev-v3

Fleet按服务日逐车配置用车、接机与价格

服务hl-fleet-service 后端 PRwx/HL#5296 Issue#5292 日期2026-07-27 影响范围:管理后台车务看板派车弹窗和订单派车详情


⚠️ 关键变化

新派车页面不再提交“收取车费日期”。派车保存改为提交完整的“服务日期 × 稳定车辆槽位”矩阵,每个单元格独立说明是否用车、车辆、司机、ARRIVAL 接机参与和当天实际价格。

items 输入暂时保留用于滚动发布兼容;旧收费日期字段只能随旧 items 使用,dailyPlan 模式提交这些字段会被拒绝。

2026-07-28 产品口径补充:默认全部行程用车

新建派车草稿进入“排车”步骤时,当前需求的全部可编辑服务日、全部新建稳定车辆槽位均默认勾选“当天用车”。车务只需要选择车辆、司机和逐日价格;只有主动取消某日勾选或点击“明确不用车”,才表示该日明确不用车。

初始化规则

  1. 后端 planState=UNPLANNED 表示尚未形成最终方案,不等于 NOT_USED。前端首次把可编辑 UNPLANNED 日格转换为草稿时应初始化 used=true,复选框默认选中,并显示“待选车辆/司机”或等价规划中状态。
  2. 新增车辆槽位时,该槽位覆盖的全部可编辑服务日同样默认 used=true,不得全部初始化为未勾选。
  3. 已有 planFinalized=trueUSED/NOT_USED、只读日格、已关账日格和已有有效派车必须按服务端事实保留;已经明确保存为 NOT_USED 的日期重新打开时仍保持未选中,不得重新默认用车。
  4. 默认选中只是前端草稿口径,不代表已经完成派车。未选择车辆、司机或逐日价格时仍不得提交,也不得伪造 planFinalized=true
  5. 用户主动取消“当天用车”时才写入草稿 used=false/planState=NOT_USED;某日所有槽位均不用车时继续执行 confirmNoVehicleServiceDates=true 二次确认。

当前前端偏差

前端提交 7b99fe7d35530073176af1a0376cba7b33503319 中,createDailyVehiclePlan() 在详情提供 dailyVehiclePlan 时把所有未最终确认日格按 UNPLANNED + used=false 直接用于草稿;appendDailyVehiclePlanSlot() 也把新槽位日格初始化为 used=false。因此页面出现整段行程“尚未规划”、所有“当天用车”均未选中的状态,与本次明确口径不符。

前端应区分“服务端基线状态”和“当前编辑草稿默认值”,不能通过把 UNPLANNED 改成服务端 USED 来伪造最终事实;仅在可编辑的新草稿层默认选中。

前端验收清单

  • 4 天行程首次进入排车步骤时,4 个可编辑日格的“当天用车”全部默认选中。
  • 候选尚未选定时显示待选车辆/司机而非“明确不用车”,且下一步仍因车辆、司机或价格缺失而受阻。
  • 新增车辆槽位后,该槽位全部可编辑服务日也默认选中。
  • 车务取消其中一天后,仅该日变为明确不用车,其余日期保持选中和已编辑草稿。
  • 已保存的 NOT_USED、已有有效派车及只读日期重新打开后保持服务端事实,不被默认逻辑覆盖。
  • 补充 createDailyVehiclePlan()appendDailyVehiclePlanSlot() 和真实挂载 FleetAssignModal 的回归测试,覆盖首次进入、增加槽位、重新打开以及主动取消用车。
  • 提交请求仍满足:每个 used=true 日格具备车辆、司机和价格;全天不用车时带明确二次确认。

2026-07-28 页面阻断ARRIVAL 接机参与无法选中

真实页面复验中,服务日 2026-08-04 已标记“要求接机”,该日格已勾选“当天用车”、已选车辆和司机、无只读或锁定提示,但点击“参与 ARRIVAL 接机 / 接站”后复选框无法保持选中。该操作发生在派车草稿提交前,属于前端日格交互与状态同步阻断,不是后端保存接口拒绝。

当前 origin/v2.1@e744c909 中:

  • DailyVehiclePlanMatrix.vue 的复选框仅发出 update:pickup(key, checked)
  • AssignModal.vuehandleDailyPlanPickupUpdate() 只将结果写入本地 dailyPlan
  • 现有 daily-vehicle-plan-matrix.spec.js 只断言子组件已发出事件,没有挂载 FleetAssignModal 验证父层接收后、候选状态 watcher 运行后以及切换日格后的值是否仍为 true

因此,子组件事件测试通过不能作为页面可用证据。前端需要从浏览器事件开始逐段核对 NCheckbox → update:pickup → handleDailyPlanPickupUpdate → dailyPlan → 提交 payload,找出勾选值被丢弃或覆盖的位置;不得通过跳过逐日方案校验或伪造后端字段规避。

前端验收清单

  • pickupRequired=trueused=true 且可编辑的日格,点击后复选框立即选中,并在多轮 nextTick、候选状态刷新以及价格编辑后保持选中。
  • 切换到其他服务日再返回,接机参与状态仍保留;再次点击可以明确取消。
  • 更新只作用于当前 serviceDate + fleetItemIndex,不得串改同日其他车辆或其他服务日。
  • 将该日改为不用车时自动清除 pickupParticipant;重新用车后由车务再次明确选择,不沿用陈旧值。
  • 提交前的 dailyPlan 以及最终请求体均包含该日格 pickupParticipant=true;后端返回成功后详情回显一致。
  • 要求接机的服务日至少一辆实际用车标记参与接机;未选择时继续显示既有校验提示,选择后提示收敛。
  • 新增 FleetAssignModal 父子联动回归测试,覆盖事件接收、watcher 稳定、日格切换和 payload;不能只断言 DailyVehiclePlanMatrix 发出了事件。
  • 页面 Console 无 Maximum recursive updates exceededunhandledrejection,复选框操作不得重新触发无界候选请求。

在该页面交互修复并完成真实浏览器复验前,frontend_status 保持 claimed,不得流转为 implemented/released/verified

变更接口

# 接口 方法 路径 变更类型 说明
1 原子提交最终派车方案 POST /admin/fleet/assignments/batch 请求体扩展与校验调整 新增完整 dailyPlan,保留旧 items 兼容
2 车务看板订单详情 GET /admin/fleet/board/orders/<orderId> 响应字段新增 返回逐日逐车计划、每车小计和订单车辆总计

二、原子提交最终派车方案

POST /admin/fleet/assignments/batch

请求 VOBatchCreateAssignmentReqVO

新增顶层字段

字段 类型 必填 约束 说明
dailyPlan DailyPlanItem[] 新页面必填 与旧 items 二选一;最多 4000 项 完整“服务日期 × 稳定车辆槽位”矩阵
confirmNoVehicleServiceDates Boolean 条件必填 某日全部槽位 used=false 时必须为 true 全天无需用车二次确认

orderIdrequirementId 和所有 Long ID 继续按 JSON 字符串传输。

DailyPlanItem

字段 类型 必填 约束 说明
fleetItemIndex Integer >= 0 稳定车辆槽位序号
serviceDate String(date) yyyy-MM-dd,必须属于当前需求服务日 服务日期
used Boolean - 当天是否实际用车
vehicleId String(Long) 条件必填 used=true 必填;不用车必须为空 当天车辆
driverId String(Long) 条件必填 used=true 必填;不用车必须为空 当天司机
pickupParticipant Boolean 仅表示 ARRIVAL 接机/接站;不用车不得为 true 当天是否参与接机
assignmentPrice String(decimal) 条件必填 used=true 必填;非负、整数最多 10 位、小数最多 2 位 本车当天实际价格,可为 0.00
priceAdjustmentReason String 条件必填 最多 256 字;实际价偏离价格日历时必填 改价原因
confirmCrossResident Boolean 跨常驻车时按既有规则确认 跨常驻车确认

正确请求示例

{
  "orderId": "789",
  "orderNo": "26-4165",
  "requirementId": "790",
  "startDate": "2026-08-04",
  "endDate": "2026-08-05",
  "headcount": 3,
  "holdMode": 0,
  "fromEntry": "from-board",
  "requestId": "daily-plan-26-4165-v1",
  "confirmNoVehicleServiceDates": false,
  "dailyPlan": [
    {
      "fleetItemIndex": 0,
      "serviceDate": "2026-08-04",
      "used": true,
      "vehicleId": "701",
      "driverId": "801",
      "pickupParticipant": true,
      "assignmentPrice": "800.00",
      "priceAdjustmentReason": "首日短途优惠"
    },
    {
      "fleetItemIndex": 1,
      "serviceDate": "2026-08-04",
      "used": true,
      "vehicleId": "702",
      "driverId": "802",
      "pickupParticipant": false,
      "assignmentPrice": "900.00",
      "priceAdjustmentReason": null
    },
    {
      "fleetItemIndex": 0,
      "serviceDate": "2026-08-05",
      "used": false,
      "vehicleId": null,
      "driverId": null,
      "pickupParticipant": false,
      "assignmentPrice": null,
      "priceAdjustmentReason": null
    },
    {
      "fleetItemIndex": 1,
      "serviceDate": "2026-08-05",
      "used": true,
      "vehicleId": "702",
      "driverId": "802",
      "pickupParticipant": false,
      "assignmentPrice": "900.00",
      "priceAdjustmentReason": null
    }
  ]
}

提交规则

  • 每个保留槽位必须覆盖当前需求的全部服务日;同一 fleetItemIndex + serviceDate 不能重复。
  • 同一服务日不能重复使用同一车辆或同一司机。
  • used=false 不占用车辆/司机、不投保、不计费;车辆、司机、接机和价格必须为空或 false。
  • 某日所有槽位均不用车时允许提交,但必须设置 confirmNoVehicleServiceDates=true
  • 大交通 ARRIVAL 要求平台接机时,当日至少一辆 used=true 的车辆必须 pickupParticipant=true
  • 大交通未要求接机时,仍允许人工标记一辆或多辆使用中的车辆参与接机。
  • 连续日期使用相同车辆和司机时后端自动合并派车组;逐日价格仍分别冻结。
  • 过去日期、已完结日期或已关账对账期不能修改。
  • dailyPlan 不得提交 chargeableServiceDatesvehicleFeeWaiverReasonconfirmAllServiceDatesFree

参数错误响应

本项目参数校验失败沿用 HTTP 200 + 业务 code=400

{
  "code": 400,
  "message": "dailyPlan 与旧 items 必须二选一,dailyPlan 不得提交旧收费日期字段",
  "data": null,
  "success": false
}

三、车务看板订单详情

GET /admin/fleet/board/orders/<orderId>

响应 VOResult<BoardOrderDetailVO>

新增响应字段

字段 类型 空值规则 说明
dailyVehiclePlan DailyVehiclePlanVO[] 无记录返回 [] 按服务日期、槽位序号稳定排序
vehicleFeeSummaries VehicleFeeSummaryVO[] 无实际用车返回 [] 按实际车辆汇总小计
vehicleFeeTotal String(decimal) 无费用返回 "0.00" 当前需求全部实际用车日总计

DailyVehiclePlanVO

字段 类型 说明
serviceDate String(date) 服务日期
fleetItemIndex Integer 稳定槽位序号
assignmentSlotId String(Long) 稳定槽位 ID
assignmentId String(Long) 每日切片 ID;显式不用车也返回占位 ID
assignmentGroupId String(Long) 当前连续派车组 ID
planFinalized Boolean 该日格是否已经业务最终确认
planState String UNPLANNED(建议占位)/ NOT_USED(明确不用车)/ USED(实际用车)
used Boolean 当天是否实际用车;必须结合 planFinalized/planState 区分未规划与明确不用车
pickupParticipant Boolean 当天车辆是否参与 ARRIVAL 接机
pickupRequired Boolean 大交通当天是否要求接机
vehicleId / driverId String(Long) 不用车时为 null
vehiclePlate / vehicleModel / driverName String 不用车时为 null
driverPhone String 脱敏手机号;不用车时为 null
calendarPrice String(decimal) 价格日历参考价;缺价或不用车时为 null
assignmentPrice String(decimal) 本车当天实际价;不用车时为 null
priceSource String CALENDAR / OVERRIDE / MISSING / NOT_USED
priceAdjustmentReason String 改价原因,无则 null
assignmentStatus String 基础派单状态;显式不用车为 unassigned
readOnly Boolean 过去、已完结或已关账日期为 true
readOnlyReason String 服务日期已过去 / 派单已完结 / 对账期已关账,可编辑时为 null

VehicleFeeSummaryVO

字段 类型 说明
vehicleId String(Long) 实际车辆 ID
vehiclePlate String 车牌
vehicleModel String 车型
amount String(decimal) 该车辆全部实际用车日小计

金额守恒:vehicleFeeTotal = sum(vehicleFeeSummaries[].amount) = sum(dailyVehiclePlan[used=true].assignmentPrice)

四、前端改造清单

  1. 删除派车弹窗中的“收取车费日期”和免费日期提交逻辑。
  2. 按服务日渲染稳定车辆槽位矩阵;每格维护 used、车辆、司机、ARRIVAL 接机参与和当天实际价格。
  3. 某日全不用车时显示二次确认,并提交 confirmNoVehicleServiceDates=true
  4. 默认价格使用详情/报价返回的日历价;修改价格时强制填写原因,允许 0.00
  5. 详情展示每辆车小计和订单车辆总计;金额以字符串解析,不能用浮点累计。
  6. readOnly=true 的日格禁止编辑,并展示 readOnlyReason
  7. 新页面只提交 dailyPlan,不得同时提交旧 items 或收费日期字段。

五、数据库和历史数据

  • fleet_assignment.daily_vehicle_used1 表示当天实际用车,0 表示明确不用车;滚动发布期间允许 NULL,读取侧按车辆/司机事实回退,避免旧节点新写入被误判。
  • fleet_assignment.pickup_participant1 表示当天该车参与 ARRIVAL 接机/接站;滚动发布期间允许 NULL 并按 false 兼容。
  • 历史已派日迁移为实际用车;原免费日实际价格迁为 0.00;未派占位迁为不用车;历史接机参与默认 false
  • 全程明确不用车可由 Fleet 以 vehicleCount=0 完成需求;Order 端车辆和司机快照均为空。

六、不影响范围

  • 不修改 hl-ui 仓库,由本 changelog 交接前端。
  • 不改变单派接口及旧 items 滚动兼容输入。
  • 不把 DEPARTURE 送机/送站映射到 pickupParticipant
  • 不改变订单或产品价格日历接口。

验证证据

  • 后端 PR #5296 已 squash 合并至 dev-v3hl-order-service-v3hl-fleet-service 已滚动部署测试环境,双实例健康检查通过。
  • Fleet 最新 dev-v3 reactor verify2452 项测试,0 failures,0 errors,1 skipped;Spotless、Jar、JaCoCo 均成功。
  • Order 全量6759 项测试,0 failures,0 errors,29 skipped;零车辆回调生产者/消费者及迁移定向回归通过。
  • 真实测试网关 GET /admin/fleet/board/orders/<orderId>HTTP 200、业务 code 200;返回 3 条 dailyVehiclePlan,包含 planFinalizedplanStateused、接机、价格和只读字段;逐车汇总数组及字符串总计存在。
  • 真实测试网关 POST /admin/fleet/assignments/batch 安全负例:dailyPlan 携带旧收费日期字段时 HTTP 200、业务 code 400,确认新旧模式互斥;该探针不产生业务写入。
  • OpenAPI diff 与 Spring Cloud Contract 未配置;已通过源码字段对比、Controller/Service 及 Fleet → Order 双端普通测试提供人工回退证据,未冒充工具通过。

当前状态:

  • backend_status: deployed
  • gateway_status: verified
  • frontend_status: claimed

关联 Issuewx/HL#5292