changelog(#5810): 换版槽位人工制新契约——需求语句+605062日期门禁+槽位统一原样渲染(PR #5815)
所有检测均成功
changelog-filename-gate / validate (push) Successful in 2s

取代 #5788 前端契约:superseded 三字段语义已死,删除全部标旧渲染分支;
新增 requirementFleetText 需求语句展示;派车推进类接口接住 605062。
#5788 条目标 not_required 并指向本条。
这个提交包含在:
API Changelog Bot 2026-08-11 08:58:57 +08:00
父节点 71a0544914
当前提交 4ab1d52c8c
共有 2 个文件被更改,包括 183 次插入6 次删除

查看文件

@ -7,13 +7,13 @@ author: "wx(GIT)"
change_type: "修改接口"
backend_status: "deployed"
gateway_status: "not_required"
frontend_status: "pending"
frontend_owner: "mmg"
frontend_ref: "b31ac7c3"
frontend_status: "not_required"
frontend_owner: ""
frontend_ref: ""
target_release: ""
verified_at: "2026-08-10"
status_note: "【遵 17:54 暂停令回退,等 #5810 新契约】064d0be2 按 17:31 二次打回的 2.8 规格把旧数据重做为完整槽位卡(SupersededSlotCard+改派/取消链,AssignModal 59/59、picker 47/47、fleet/board 444/444、checkpoint 含生产构建全过),但交付先于 17:54「暂停 2.8 施工、保持现状」说明 push。遵暂停令已 revert(3441e69e),v2.1 回到 b31ac7c3 口径(superseded 撞号过滤+标旧窄条+返工4项:vehicleSlots 为源合并/exclude 同源/放开统一选择/放开删除 superseded 例外)。#5810 换版策略升级(槽位人工制+需求语句 requirementFleetText+出发日期门禁)后端落地、本 changelog 出全新前端契约后,再按新形态实现(预告:槽位头去「建议{车型}」标签、改版横幅显示需求语句、槽位统一原样渲染)。"
updated_at: "2026-08-10"
verified_at: ""
status_note: "【已被 #5810 取代,本条前端契约作废,勿再施工;前端历史实现引用 b31ac7c3 已随本条作废】新契约见 `changelogs-v2/2026-08/11_5810_换版槽位人工制-需求语句与派车日期门禁-修改接口-管理后台.md`:换版改为整槽平移,`superseded`/`supersededAssignments`/`requirementChangePendingCount` 三字段语义已死(恒 false/[]/0,本条要求的「标旧渲染」全部删除,改为槽位统一原样渲染 + 需求语句 requirementFleetText + 605062 日期门禁。以下为历史记录:【遵 17:54 暂停令回退,等 #5810 新契约】064d0be2 按 17:31 二次打回的 2.8 规格把旧数据重做为完整槽位卡(SupersededSlotCard+改派/取消链,AssignModal 59/59、picker 47/47、fleet/board 444/444、checkpoint 含生产构建全过),但交付先于 17:54「暂停 2.8 施工、保持现状」说明 push。遵暂停令已 revert(3441e69e),v2.1 回到 b31ac7c3 口径(superseded 撞号过滤+标旧窄条+返工4项:vehicleSlots 为源合并/exclude 同源/放开统一选择/放开删除 superseded 例外)。#5810 换版策略升级(槽位人工制+需求语句 requirementFleetText+出发日期门禁)后端落地、本 changelog 出全新前端契约后,再按新形态实现(预告:槽位头去「建议{车型}」标签、改版横幅显示需求语句、槽位统一原样渲染)。"
updated_at: "2026-08-11"
base: "dev-v3"
---

查看文件

@ -0,0 +1,177 @@
---
schema: "hl-changelog/v2"
ticket: "5810"
title: "换版槽位人工制:新增需求语句 requirementFleetText + 派车日期门禁 605062 + 槽位统一原样渲染(取代 #5788 全部旧数据形态)"
consumer: "admin"
author: "wx(GIT)"
change_type: "修改接口"
backend_status: "deployed"
gateway_status: "not_required"
frontend_status: "pending"
frontend_owner: "mmg"
frontend_ref: ""
target_release: ""
verified_at: "2026-08-10"
status_note: "后端 PR #5815 已合并 dev-v3 并部署测试服,三场景 API 实测通过(改车型/改日期/加天数 + 反例)。本条 **取代** 10_5788_换版保留派单可改派与槽位标旧 的前端契约:#5788 里「旧数据行/标旧窄条/SupersededSlotCard/单独列出旧数据」的全部形态一律作废,改为槽位统一原样渲染,详见下文 §2。"
updated_at: "2026-08-11"
base: "dev-v3"
---
# 车务:换版槽位人工制 —— 需求语句 + 派车日期门禁 + 槽位统一原样渲染(#5810
> **服务**: hl-fleet-service (8087/8187)
> **PR**: #5815
> **Issue**: #5810(取代 #5788 的前端契约)
> **日期**: 2026-08-10 后端部署完成
> **影响范围**: 派单看板订单详情 `GET /admin/fleet/board/orders/{orderId}`(新增 1 字段 + 3 个字段语义退化为恒空)、派车推进类接口新增错误码 605062
> **一句话**: 换版后端不再自动增删槽位、不再区分新旧行,前端也不要再区分——**槽位有什么就原样画什么**;需求变成一句提示语;唯一会拦住车务的是「派车日期不在需求日期窗内」。
---
## 0. 先读这段:为什么推翻 #5788 的做法
#5788(后端 #5784/#5796/#5798/#5802)的老机制是:定制师改用车需求 → 后端按「车型+座位」签名匹配,**匹配上的旧派车行沿用、匹配不上的标 `superseded`(旧数据)、缺的自动补未派占位、多的自动取消**。于是页面上出现了「新槽位 + 旧数据行」两类东西,前端为了表达它反复返工三轮(窄条 → 卡片 → 单独区块,wx 每一轮都不满意。
**2026-08-10 wx 最终口径(本单实现的就是这个)**
> 「槽位的数据配置啥就是啥,不自动清除数据,不自动增加/减少槽位。只在改出发日期的时候做日期判断,日期不对没法下一步。」
所以后端把整套「签名匹配 / 自动补位 / 自动取消 / superseded 标记」全部删掉,换成**整槽平移**:换版时把该订单下所有未删派车行(含已完成 completed,只排除 canceled原封不动地重新绑定到新需求 ID 上——槽位数、车辆、司机、日期、价格、状态全不动,只是"户口"迁到新需求名下。存量带 `superseded` 标记的历史行也已由 Flyway 一次性迁移重绑完毕。
**给前端的直接含义****再也没有"旧数据行"这个概念了。** 所有槽位都是当前需求下的普通槽位,一视同仁地渲染成普通槽位卡。
---
## 1. 新增字段:`requirementFleetText`(需求语句)
### 接口
`GET /admin/fleet/board/orders/{orderId}` —— **根级新增**(不在 `vehicleSlots` 里):
| 字段 | 类型 | 可空 | 说明 |
|------|------|------|------|
| `requirementFleetText` | string | 是(需求不可达时 `null` | 当前有效用车需求的车型语句 |
### 取值规则(后端已实现,前端直接展示即可,**不要自己再拼**
- 格式:车型项按 `{车型中文标签}×{数量}({座位数}座)` 生成,多项用中文顿号 `、` 连接
- 实例(测试服真实返回):
- 26-9313 改需求后 → `"商务车×1(7座)、SUV×1(5座)"`
- 单车型单辆 → `"商务车×1(7座)"`
- 车型标签走字典 normalize,字典查不到时回退车型原始编码;数量 ≤0 按 1 计;座位数缺失时省略 `(N座)` 后缀
### 前端怎么用
1. **改版提示横幅**:文案 `需求已改版,请对照新需求人工调整` + 紧跟这句 `requirementFleetText`
⚠️ 注意:横幅的**触发条件不再是** `requirementChangePendingCount > 0`(该字段现在恒 0,见 §2。是否显示横幅由前端自行决定例如本次进入派车页时对比上次看到的 `requirementVersion`,或干脆常驻显示"当前需求xxx")。**推荐做法**:不做横幅态,直接在派车页/订单概览常驻一行「当前需求商务车×1(7座)、SUV×1(5座)」,这样任何时候车务都能对照,不依赖任何"变更"状态。
2. **订单概览**:同一句展示,位置见 wx 截图指向的区域(需求信息块)。
3. `null` 时该行整体不渲染(不要显示"当前需求null"或空冒号)。
---
## 2. ⚠️ 必须删除的旧渲染分支(#5788 遗留)
以下三个字段**契约保留不删**(兼容期,避免前端 500,但**语义已死**,值恒为空:
| 字段 | 位置 | #5810 后的值 | 前端处理 |
|------|------|-------------|---------|
| `requirementChangePendingCount` | 根级 | **恒 `0`** | 删掉依赖它的徽章/横幅触发逻辑 |
| `supersededAssignments` | 根级 | **恒 `[]`** | 删掉整个"旧数据区块/列表"渲染 |
| `vehicleSlots[].superseded` | 槽位 | **恒 `false`** | 删掉 `superseded ? 旧数据卡 : 普通卡` 的三元分支 |
| `vehicleSlots[].supersededByRequirementId` | 槽位 | **恒 `null`** | 无用 |
| `vehicleSlots[].requirementId` | 槽位 | 恒 == 根级 `requirementId` | 无需比对 |
**具体到 mmg 已写的代码**(按 #5788 三轮返工的产物):
- `SupersededSlotCard`064d0be2 的旧数据槽位卡组件)→ **整个组件删除**
- "标旧窄条"a75efc05/b31ac7c3 的窄条渲染)→ **删除**
- 任何 `slot.superseded === true` 的判断、任何把 `supersededAssignments` 单独成区/成行的代码 → **删除**
- 槽位列表数据源:**只用 `vehicleSlots`**,按后端返回顺序原样渲染,每一项都是普通槽位卡(可派车/可换车/可取消/可删除,能力与普通槽位完全一致)
**验收标准**:改需求前后,页面槽位卡数量与内容**完全不变**(除非车务自己动手加/删/改。26-9313 实测返回 3 个槽位(原商务车 E5555 行、原商务车 S6666 行、新 SUV 空槽),三个都是普通卡,没有任何"旧"标记。
---
## 3. ⚠️ 槽位头去掉「建议 {车型}」标签
槽位头当前显示的「建议 商务车」「建议 SUV」这类标签 —— **去掉**
原因:槽位人工制下车务爱派什么车派什么车,后端不再按车型校验(车型/数量/人数不符**不拦截**,见 §4,"建议"标签只会让车务误以为必须匹配。车型诉求统一由 §1 的 `requirementFleetText` 在横幅/概览表达一次即可。
字段层面:`vehicleSlots[].requiredVehicleType` / `requiredVehicleTypeLabel` / `requiredSeats` **契约保留**(后端仍返回真实值,其它场景可能用到),但**不要再渲染成槽位头的"建议 xx"标签**。
---
## 4. 新增错误码 605062派车日期与需求不符唯一硬门禁
### 触发场景
定制师**改了出发日期/行程天数**后,需求的日期窗变了,但车务原来配的车还挂在旧日期上。此时车务想推进(发送给司机 / 确认执行 / 提交最终方案),后端拦截:
```json
{ "code": 605062, "msg": "存在派车日期与当前用车需求不符的槽位,请先调整或取消后再继续", "data": null }
```
### 哪些接口会返回
| 接口 | 说明 |
|------|------|
| `POST /admin/fleet/assignments/requirements/{requirementId}/confirm` | 需求级确认执行preflight + 锁内双重校验) |
| `POST /admin/fleet/assignments/batch` | 批量提交最终实派方案(提交入参日期 + 既有在途行双向校验) |
| 逐日方案提交(`batch``dailyPlan` 入参) | 同上 |
### 前端处理
1. `msg` 已是**完整可直接展示的中文**,直接弹给用户即可,不要自己另写文案。
2. 建议在提示后附操作引导:`请在槽位列表中删除或改期日期不符的槽位后重试`
3. **不需要**前端预先算日期做本地拦截(后端是权威,且前端算容易与后端口径不一致);如果想给视觉提示,可用 `vehicleSlots[].serviceStartDate/serviceEndDate` 与订单 `departDate/endDate` 比对给个黄色角标,但**不要**据此禁用按钮。
### 不拦截的情况(明确告知,避免前端"帮倒忙"加校验)
- **加天数**(需求日期窗**扩大**):旧派车行日期仍落在扩大后的窗内 → **完全放行**,且**不强制车务把新增的天派满**
- **车型/数量/人数与需求不符****不拦截**(降级为提示语句,即 §1 的 `requirementFleetText`
- 已完成(`completed`)的历史行日期越窗 → **不拦截**(终态行无法调整,不能卡死推进)
---
## 5. 行为变化速查(后端换版语义,供前端理解页面为什么这样)
| 场景 | #5788 老行为 | #5810 新行为 |
|------|-------------|-------------|
| 定制师改车型2商务 → 1商务+1SUV | 匹配上的沿用,匹配不上的标旧,缺的自动补占位 | **全部行原样平移**,槽位数不变;SUV 需求只体现在语句里 |
| 定制师改日期 | 同上 + 旧日期行标旧 | 全部行原样平移(日期不动);推进时 **605062** 拦截,车务手动改期/取消后放行 |
| 定制师加天数 | 自动补新天占位 | 不自动补;车务可自行补派新增天(不补也能推进) |
| 定制师减车辆数 | 自动取消多余未派占位 | **不自动取消**;多出来的槽位由车务自己删(删除能力 #5572 已全放开) |
| 旧存量 superseded 行 | 特殊形态 | Flyway 已一次性迁移重绑为普通行 |
---
## 6. 联调数据(测试服可直接复现)
| 场景 | 订单 | 说明 |
|------|------|------|
| 改车型后的三槽位原样 | 团号 `26-9313`orderId `2086270153414103041` | 详情返回 `requirementFleetText="商务车×1(7座)、SUV×1(5座)"``vehicleSlots` 3 项、`superseded` 全 false、`supersededAssignments=[]` |
| 605062 拦截 / 放行 | 订单 `2086697882311680002` | 已被本次实测改到 08-28~31 且已确认执行完毕;如需重现 605062,请改该单出发日期后再点确认执行 |
后端实测记录:改车型场景槽位零变动;改日期场景 confirm 返 605062、取消越窗行并窗内重派后 confirm 返 200;加天数场景不拦截,且新增天用他单占用车被 605001 正确拒绝、precheck 如实返回车+司机双 conflicts。
---
## 7. 不变的部分(无需改动)
- `vehicleSlots` 其余字段(`assignmentSlotId`/`fleetItemIndex`/`assignmentGroupId`/`slotStatus`/`canDelete` 等)语义全不变
- 候选查询 `POST /admin/fleet/assignments/candidates``excludeAssignmentId` 语义不变(#5802 宽容口径保留:同订单不命中的排除项后端忽略并记 WARN,不再报"参数非法"
- 派车/改派/取消/增删槽位所有既有接口契约不变
- 网关路由无新增
---
## 8. 前端 checklist做完请把 frontmatter 的 `frontend_status` 改为 `implemented` 并填 `frontend_ref`
- [ ] 详情响应新增消费 `requirementFleetText`,在派车页/订单概览展示为一行需求语句null 不渲染)
- [ ] 删除 `SupersededSlotCard` 组件及所有"旧数据"分支渲染(窄条/区块/角标)
- [ ] 删除对 `supersededAssignments``requirementChangePendingCount``slot.superseded` 的一切依赖
- [ ] 槽位列表数据源统一为 `vehicleSlots`,按序原样渲染为普通槽位卡,能力(派车/换车/取消/删除)不因来源不同而降级
- [ ] 槽位头去掉「建议 {车型}」标签
- [ ] 派车推进类接口confirm / batch接住 `605062`,直接展示后端 `msg` + 操作引导
- [ ] 不新增任何前端侧日期硬拦截(不 disable 按钮)