135 行
13 KiB
Markdown
135 行
13 KiB
Markdown
---
|
||
schema: "hl-changelog/v2"
|
||
ticket: "5788"
|
||
title: "换版保留派单可改派:候选排除放行 superseded 行 + vehicleSlots 新增标旧字段"
|
||
consumer: "admin"
|
||
author: "wx(GIT)"
|
||
change_type: "修改接口"
|
||
backend_status: "deployed"
|
||
gateway_status: "not_required"
|
||
frontend_status: "implemented"
|
||
frontend_owner: "mmg"
|
||
frontend_ref: "064d0be2"
|
||
target_release: ""
|
||
verified_at: "2026-08-10"
|
||
status_note: "【§2.8 重做完成 064d0be2】旧数据从窄条推翻重做为完整槽位卡。A.删 a75efc05 引入的窄条 am-superseded-slots 提示条;B/C.新建 SupersededSlotCard.vue:卡头「旧数据·需求已改版」+车型徽标 requiredVehicleTypeLabel+车 vehiclePlate vehicleModel+司机 driverName+「已派车·待人工核对」,整卡灰底弱化,排当前槽位后;展开只显区间行(serviceStartDate~serviceEndDate+车+司机+状态,后端无逐日切片 #5787,不渲染逐日价);D.操作留「更换车辆/司机(改派)」+「取消」,不提供删除槽位;F.分组/去重一律按 superseded 标志(严禁 fleetItemIndex 撞号);G.改期场景 serviceStart/End≠订单 startDate/endDate 时提示「旧派车日期与当前需求不符,请先取消后重新派车」。改派复用 change 链:changeTargetAssignment 按 assignmentId 命中 superseded 行直返(不走 merge/切片),assignmentOrder 顶部拦截给候选口径(requirementId 锚详情顶层当前需求 2086700635972915201、fleetItemIndex 省略、excludeAssignmentId=该行 assignmentId、日期该行);buildAssignmentCandidateRequest 支持显式 undefined 省略 fleetItemIndex。取消新链:DELETE cancelReason+driverNotified+requestId 幂等,605026 无凭证二次确认携 confirmWithoutEvidence=true 同一 requestId 重试,成功 refreshAssignmentBaseline 让卡/黄条消失、pendingCount 归 0。实证 26-9313 保留行扁平字段形态。AssignModal 59/59、picker 47/47、fleet/board 全量 444/444、checkpoint 含生产构建全过。H 实测验收(candidates 200 自排除/取消后徽章归 0)交 wx 测试服复测。"
|
||
updated_at: "2026-08-10"
|
||
base: "dev-v3"
|
||
---
|
||
|
||
# 车务: 需求换版保留派单可改派 + 槽位视图标旧(#5788)
|
||
|
||
> **服务**: hl-fleet-service (8087/8187)
|
||
> **PR**: #5796
|
||
> **Issue**: #5788
|
||
> **日期**: 2026-08-10
|
||
> **影响范围**: 派单看板订单详情 vehicleSlots 结构(新增 3 字段)、派单候选查询排除校验语义
|
||
> **背景**: #5784 换版保留行此前点「重新配置车辆」必报「参数非法: 排除派单不属于当前订单、当前用车需求或当前车型项」(26-9313 实测),改派通路被拦死;且槽位视图无法区分新旧行。
|
||
|
||
---
|
||
|
||
## 变更接口
|
||
|
||
### 1. 详情接口 vehicleSlots 新增 3 字段
|
||
|
||
`GET /admin/fleet/board/orders/{orderId}` 的 `vehicleSlots[]` 每行新增:
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `requirementId` | string(Long) | 槽位行所属用车需求ID;与顶层 requirementId 不等且 superseded=true 时为换版保留的旧需求行 |
|
||
| `superseded` | boolean | **是否换版保留的旧派单行**。true=旧数据,仅供人工核对后改派/取消,不参与当前方案日格进度与车费计数 |
|
||
| `supersededByRequirementId` | string(Long) | 取代该行的新需求ID;superseded=true 时非空 |
|
||
|
||
**排序约定**: 当前需求槽位行在前(顺序不变),换版保留行追加在尾部。保留行固定 `canDelete=false`,`deleteBlockReason="需求已改版保留行,请改派或取消,不支持直接删除槽位"`。
|
||
|
||
**前端要做**: 保留行渲染「旧数据/需求已改版」标识(区别于当前槽位),操作只留「改派 / 取消」;顶部黄条(supersededAssignments)保持现状作提醒入口。注意保留行的 `fleetItemIndex` 是旧版展开序,可能与当前需求槽位撞号,**渲染分组请以 superseded 标志区分,勿再单靠 fleetItemIndex**。
|
||
|
||
### 2. 候选查询排除校验放宽(保留行改派入口打通)
|
||
|
||
`POST /admin/fleet/assignments/candidates`:
|
||
|
||
- `excludeAssignmentId` 现在允许两类:①当前需求本身的派单(原口径,仍须 requirementId+fleetItemIndex 精确匹配);②**换版保留派单**(supersededByRequirementId 非空,属当前订单即可)。
|
||
- **排除保留行时 `fleetItemIndex` 可不传**(旧版序号在新需求下无语义,后端不再校验);座位匹配自动锚保留行自身座位快照(requiredSeats),不再按新需求车型项定位。
|
||
- 保留行自身占用会被正确排除:实测 exclude 后原车 available=true、conflicts=[](可改回原车或换车)。
|
||
- 防护不回归:非本订单/不存在的 assignmentId、普通行 fleetItemIndex 不匹配 → 仍报「参数非法」。
|
||
|
||
### 2.5 跟进(PR #5798,2026-08-10):排除未派车占位行也不校验序号
|
||
|
||
现版前端槽位上下文缺 `fleetItemIndex` 时回退 0(`useAssignFlow.js:294`),排除 SUV 占位行(实际序号 1)时被后端精确匹配拒绝(26-9313 复现)。后端已放宽:**排除当前需求的 unassigned 占位行时不校验 fleetItemIndex**(需求归属仍校验),座位按占位行自身 requiredSeats 快照。现版前端不改也能选车,但仍建议槽位上下文与 `vehicleSlots[].fleetItemIndex`/`assignmentId` 同源取值,消除序号错位。
|
||
|
||
### 2.6 展示布局建议(wx 2026-08-10 口径)
|
||
|
||
场景:原需求商务车×2(两辆均已派),改为商务×1+SUV×1。期望车务再派车时看到:
|
||
|
||
1. **商务槽(当前)**: 沿用原车回显(换版时签名匹配自动沿用,如 26-9313 的蒙A-E5555)——可加「沿用」小徽标(判定见 #5784 changelog);
|
||
2. **SUV 槽(当前)**: 待选车,点选车走候选接口(本次已修通);
|
||
3. **旧数据行**: 被取代的原商务车(蒙A-S6666)从 `vehicleSlots` 里 `superseded=true` 的行渲染,标「旧数据/需求已改版」。**操作能力与普通行一致(可改派/取消),不要禁用**——旧数据与新数据无本质区别,只要日期对得上;仅改出发日期场景下旧车/司机日期不符时,车务需先取消旧行再进行下一步(此时给出引导提示)。
|
||
|
||
即"原来的两辆商务车都可见(一辆沿用在新槽、一辆标旧),新需求两个槽位齐全"。
|
||
|
||
### 2.7 ⚠️ a75efc05 复测未过·前端需返工(wx 2026-08-10 现场实测 26-9313,浏览器抓包实证)
|
||
|
||
标旧行没渲染、选车仍报错、槽位误显锁定,根因共 4 项(前 2 项同一根因):
|
||
|
||
1. **数据源遮蔽(根因)**: `explicitAssignmentSlots`(batchAssignmentSlots.js)只要 `order.assignmentSlots` 是数组就直接返回,**永远读不到 detail 的 `vehicleSlots`**。实测本单列表行 `assignmentSlots` 有 2 个普通槽(不含 superseded 行、无 superseded/canDelete 字段)→ ①supersededSlots 恒空,「旧数据·需求已改版」行一次都没渲染过;②槽位对象丢失 `canDelete=true`(detail 有、列表无)→ 误显"当前槽位不可删除,请刷新详情后重试"。**修法**: superseded 标旧行与 canDelete/deleteBlockReason 必须以 detail `vehicleSlots` 为源(合并或优先)。
|
||
2. **candidates 排除同源缺陷阻塞实锤**: 槽位2 选车请求实抓 `fleetItemIndex=1, excludeAssignmentId=2086270154022285313`(=槽位1 E5555 已派行)——picker 上下文的 excludeAssignmentId 取了订单级行而非本槽位行,被后端精确匹配拒绝报"参数非法"。后端已再兜底(PR #5802:同订单上下文不一致的排除改为**忽略**并 WARN,不再报错),**现版前端已可正常选车**,但同源修正仍需落地:excludeAssignmentId/fleetItemIndex 一律取本槽位行(vehicleSlots 同行的 assignmentId+fleetItemIndex),否则被误传行会在候选里如实显示冲突(略影响体验不阻塞)。
|
||
3. **去除"已锁定"(wx 2026-08-10 口径)**: `isExistingAssignment` 槽位的「统一选择车辆/司机」按钮禁用+显示"已锁定"——去除该锁定;已有槽位同样允许统一选车(走候选接口,后端排除口径已放开)。
|
||
4. **任何槽位车务都可删除(wx 2026-08-10 口径)**: 删除按钮不再因 canDelete 缺失/false 隐藏或拦截——后端 #5572 本就允许删除一切未完结槽位(已派/待确认删除时联动取消释放),仅已完结/已关账行后端会拒并给原因,前端直接放开按钮、失败时展示后端 message 即可(换版保留旧行例外:仍走改派/取消不走删除)。
|
||
|
||
**⚖️ 形态重定(wx 2026-08-10 最终口径,推翻上一段"形态定稿")**: 「旧数据·需求已改版」**不接受窄条单列**。旧数据必须作为**槽位条目**渲染进「排车方案」槽位列表,与「车辆槽位 N」同构。按下方 2.8 规格实现。
|
||
|
||
**⏸️ 暂停施工(wx 2026-08-10 晚,最高优先)**: 2.8 的"旧数据槽位卡"形态**不要做了**。wx 最终口径已升级为后端换版策略简化(工单 #5810:换版不自动增减槽位、全部行平移绑定新需求、superseded 形态退役、需求转语句字段 requirementFleetText、出发日期唯一门禁)。后端落地后本 changelog 会出全新前端契约(预告:槽位头去"建议{车型}"标签、改版横幅显示需求语句、槽位统一原样渲染)。在那之前 #5788 前端侧**保持现状即可**,勿再按 2.8 施工。
|
||
|
||
### 2.8 🎯 旧数据槽位·实现规格(最终版,给前端按此落地,逐条执行不要自行简化)
|
||
|
||
**A. 移除**: AssignModal 中 a75efc05 引入的 `am-superseded-slots` 窄条区块(含"该行属上一版用车需求的保留派单…请在订单详情核对后改派或取消"提示条)整体删除。
|
||
|
||
**B. 渲染位置与结构**: `supersededSlots`(来源见 F)的每一行,渲染为一张**槽位卡片**,复用当前槽位(`am-slot-collapse__item`)的同构结构,排在全部当前需求槽位之后。卡片头从左到右:
|
||
1. 标题位(替代"车辆槽位 N"):**「旧数据 · 需求已改版」**;
|
||
2. 车型徽标位:该行 `requiredVehicleTypeLabel`(如"商务车");
|
||
3. 车辆位:`vehiclePlate + vehicleModel`(如 蒙A-S6666 丰田赛那);
|
||
4. 司机位:`driverName`;
|
||
5. 状态位:**「已派车 · 待人工核对」**;
|
||
6. 视觉:整卡灰底/弱化以区分当前槽位(可沿用现有 superseded 样式类)。
|
||
|
||
**C. 展开内容**: 后端**刻意不提供**保留行的逐日切片(dailyVehiclePlan 排除保留行防双重计数,#5787),所以展开区渲染**一条区间行**即可:服务日期=`serviceStartDate ~ serviceEndDate`(26-9313 即 08/22~08/24)、车、司机、状态;**不渲染逐日价格编辑**。
|
||
|
||
**D. 操作(与普通槽位一致,均直接可用,不引导跳订单详情)**:
|
||
1. **「更换车辆/司机(改派)」**: 打开统一选择器,candidates 请求参数——`orderId`=当前订单、`requirementId`=**详情顶层当前需求 id**(不是保留行的 requirementId!)、`excludeAssignmentId`=**该保留行自身 assignmentId**、`fleetItemIndex` **不传**(后端口径 2 已支持,传了也不校验)、`startDate/endDate`=保留行自身日期。选定车/司机后走既有改派提交链路。
|
||
2. **「取消」**: `DELETE /admin/fleet/assignments/{assignmentId}`,body: `cancelReason` 必填、`driverNotified` 必填(true/false)、`requestId` 幂等;无凭证时后端返回 605026「未上传取消凭证,请二次确认」→ 弹确认后携 `confirmWithoutEvidence=true` 重试。
|
||
3. **不提供「删除槽位」按钮**(该行 `canDelete=false`,`deleteBlockReason` 已给文案;删除≠取消,保留行只走改派/取消)。
|
||
|
||
**E. 处置后的刷新预期**: 改派或取消成功后重拉详情——该旧数据槽位卡消失、顶部黄条(supersededAssignments)消失、`requirementChangePendingCount` 归 0。
|
||
|
||
**F. 数据源(不许再走列表 assignmentSlots)**: 旧数据槽位只认 detail `GET /admin/fleet/board/orders/{orderId}` 的 `vehicleSlots[]` 中 `superseded===true` 的行(b31ac7c3 已修数据源合并,沿用);**分组/去重一律用 superseded 标志,严禁用 fleetItemIndex**(旧版序号与当前槽位撞号,26-9313 实测旧行 index=1 与 SUV 槽撞)。
|
||
|
||
**G. 改期场景提示**: 保留行 `serviceStartDate/serviceEndDate` 与订单当前出行日期不一致时,卡内加一行提示:「旧派车日期与当前需求不符,请先取消后重新派车」(改期时旧车/司机占用的是旧日期,车务须先取消)。
|
||
|
||
**H. 验收(测试服 26-9313 实测,全过才算完)**:
|
||
- [ ] 排车方案列表内可见"旧数据·需求已改版"槽位卡(S6666/巴雅尔/08/22~08/24/已派车·待人工核对),位于当前槽位之后,窄条已删;
|
||
- [ ] 该卡「更换车辆/司机」→ candidates 业务码 200,原车 S6666 在候选中 available=true(自排除生效);
|
||
- [ ] 该卡「取消」(走二次确认)→ 徽章计数归 0、卡与黄条消失;
|
||
- [ ] 当前需求槽位的选车/删除/统一选择功能不回归。
|
||
|
||
## 验证证据:实测数据样例(测试服 26-9313)
|
||
|
||
```json
|
||
// vehicleSlots 尾部保留行
|
||
{"fleetItemIndex":1, "requiredVehicleType":"mpv", "slotStatus":"assigned",
|
||
"vehiclePlate":"蒙A-S6666", "superseded":true,
|
||
"requirementId":"2086270153913225218",
|
||
"supersededByRequirementId":"2086700635972915201",
|
||
"canDelete":false, "deleteBlockReason":"需求已改版保留行,请改派或取消,不支持直接删除槽位"}
|
||
```
|
||
|
||
## 关联 / 联系人
|
||
|
||
### 链接
|
||
|
||
- **相关工单**: [#5788](https://git.1814.love:8443/wx/HL/issues/5788)、[#5784](https://git.1814.love:8443/wx/HL/issues/5784)(换版保留规则)
|
||
|
||
### 联系人
|
||
|
||
- **后端负责人**: @wx
|
||
- **前端负责人**: @mmg
|