推送被拦:E_FRONTEND_STATE「verified 必须填写 target_release」 (scripts/validate-changelog-frontmatter.mjs:325-327)。 这两处不是本次改出来的,昨天就空着。门禁只看本次推送的变更集, 所以碰到哪个文件哪个文件才暴露 —— 实测全仓 frontend_status=verified 的 182 个文件 target_release 全是空的,属潜伏的不一致,不是这两份特有。 本次只修我动过的这两个,没有顺手去改另外 180 个。 取值不猜:当前惯例是 target_release = "hl-ui@" + frontend_ref 前 8 位 (2026-08-23 ~ 2026-09-13 连续 6 例;旧惯例 v2.1 在 9 月只剩 2 例), 填进去的只是复述文件里已记着的那个前端提交,不是对发布号的新声明。 ⚠️ 记一句给后来人:validate-changelog-frontmatter.mjs --files <单个文件> 过了 不等于能推 —— 它只校验你点名的那些,而门禁校验的是本次推送的全部变更文件。 贴校验结果时要连「校验了几个对象」一起贴。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
21 KiB
schema, ticket, title, consumer, author, 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 | author | change_type | backend_status | gateway_status | frontend_status | frontend_owner | frontend_ref | target_release | verified_at | status_note | updated_at | base |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| hl-changelog/v2 | 7443 | 团期身份失败关闭-派车按团筛选 | admin | wx(GIT) | 修改接口 | deployed | verified | verified | mmg | dd152af7fd36ca1e066893d3a95a4e86dda92bf5 | hl-ui@dd152af7 | 2026-09-17 | 后端交付。派车子订单无团期身份时失败关闭返 602203;看板矩阵新增 groupBatchId 字段及筛选参数。前端已交付(2026-09-17):602203 拦截器透 message 不建码字典(grep 实证零硬编码);看板/矩阵响应 groupBatchId 随展开流转不直显雪花串;矩阵团期筛选内嵌日期弹窗头部(grid/month-counts 契约不带该参,放主筛选条会让甘特看似筛选没生效),抽 GroupBatchSelect 共享组件(候选 pending-batches,focus 首拉+累计缓存),变更按当前日重拉;组件 spec 3+composable 透传 1,checkpoint 全量绿。 | 2026-09-17 | dev-v3 |
fleet/order-v3: 团期身份失败关闭-派车按团筛选
存放目录: changelogs-v2/{YYYY-MM}/
服务: hl-fleet-service、hl-order-service-v3 PR: #7864 Issue: #7443 AC-3/AC-5/AC-14 日期: 2026-09-17
关键变化
- 派车子订单无 groupBatchId 时失败关闭返 602203
- 看板与矩阵新增 groupBatchId 字段
- 矩阵新增 groupBatchId 筛选参数
- 新增错误码 602203(TRANSFER_GROUP_IDENTITY_INVALID)
二、变更接口清单
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|---|---|---|---|---|
| 1 | 看板列表 | GET | /admin/fleet/board/orders |
修改 | 响应新增 groupBatchId |
| 2 | 矩阵日订单 | GET | /admin/fleet/matrix/day-orders |
修改 | 新增筛选参数;响应新增字段 |
| 3 | 派车创建 | POST | /admin/fleet/assignments |
修改 | 无团期身份时返 602203 |
| 4 | 派车批量 | POST | /admin/fleet/assignments/batch |
修改 | 同上 |
三、接口详情
1. 看板列表 GET /admin/fleet/board/orders
VO: BoardOrderPageReqVO → BoardOrderPageRespVO
使用场景
派单看板列表查询,新增 groupBatchId 字段显示派车行所属团期。
入参(本次新增 1 个,其余 19 个原有参数不变)
覆盖范围:本表只列本次新增的参数。
BoardOrderPageReqVO共 20 个字段(origin/dev-v3=75d77eefe),其余 19 个(status/statuses/startDayFrom/startDayTo/startDate/endDate/vehicleTypeKeys/typeKeys/driverName/keyword/contactName/contactKeyword/teamNo/consultantId/plannerName/consultantName/variant/page/pageSize)语义与本次改动无关,以 Swagger 为准。
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| groupBatchId | Query | Long | 否 | 雪花 ID | 按运营团期精确筛选;与 teamNo 等其他条件是 AND 交集,不传=不按团筛 |
出参
| 字段 | 类型 | 说明 |
|---|---|---|
| records[].groupBatchId | Long | 团期 ID(当前归属优先,降级快照;字符串序列化) |
请求示例
GET /admin/fleet/board/orders?pageNo=1&pageSize=20
响应示例
{
"code": 200,
"data": {
"total": 1,
"records": [{
"orderId": "1934567890123456789",
"orderNo": "26-0503",
"groupBatchId": "1934567890123456800",
"customerName": "赵先生"
}]
},
"success": true
}
空数据 / 降级响应
{
"code": 200,
"data": {"total": 0, "records": []},
"success": true
}
错误响应
{
"code": 403,
"message": "权限不足",
"success": false
}
业务边界
- groupBatchId 优先取当前值,降级回退快照值
- 非团订单 groupBatchId 为 NULL
- 已退团历史行保持快照值
2. 矩阵日订单 GET /admin/fleet/matrix/day-orders
VO: date + groupBatchId(optional) → List<MatrixDayOrderVO>
使用场景
矩阵日期弹窗,新增可选参数按团期筛选,响应新增 groupBatchId 字段。
入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| date | Query | String | 是 | YYYY-MM-DD | 查询日期 |
| groupBatchId | Query | Long | 否 | - | 团期精确筛选(当前归属优先;存量行为 NULL) |
出参
| 字段 | 类型 | 说明 |
|---|---|---|
| groupBatchId | Long | 团期 ID(当前归属优先,降级快照) |
请求示例
GET /admin/fleet/matrix/day-orders?date=2026-05-04&groupBatchId=1934567890123456800
响应示例
{
"code": 200,
"data": [{
"orderId": "26-0503",
"orderNo": "26-0503",
"groupBatchId": "1934567890123456800",
"customerName": "赵先生"
}],
"success": true
}
空数据 / 降级响应
{
"code": 200,
"data": [],
"success": true
}
错误响应
{
"code": 100001,
"message": "日期格式非法",
"success": false
}
业务边界
- 筛选与回显是同一个口径:都取「当前归属优先,order-v3 降级时才回退派车行快照」 (实现上筛选谓词直接调用回显用的同一个解析函数,不存在两套口径)
- 与看板
board/orders的 groupBatchId 口径完全一致,两个接口可以互相对照结果 - 存量行 groupBatchId 为 NULL 且订单上下文也取不到时,按参数筛选落选
- ⚠️ 已退团的历史派车行:只要 order-v3 可用,按「当前归属」判(即退团后不再命中原团期); 仅在 order-v3 降级、拿不到订单上下文时,才回退到建行时固化的快照值
3. 派车创建 POST /admin/fleet/assignments
VO: CreateAssignmentReqVO → AssignmentWriteRespVO
使用场景
创建单笔派车行。新增校验:团期子订单无 groupBatchId 时拒绝返 602203。
入参
本次无新增、无修改——请求体字段与字段语义一个字没动,本次变化只发生在受理与否上(见下方「错误响应」)。下表为 CreateAssignmentReqVO(origin/dev-v3)全量 28 个字段,供前端核对现状:
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| orderId | Body | Long | 否 | - | 订单 ID(雪花) |
| orderNo | Body | String | 否 | - | 订单号(冗余,可空) |
| requirementId | Body | Long | 否 | - | 关联用车需求 ID(同需求项在途互斥校验用,可空) |
| fleetItemIndex | Body | Integer | 否 | 已废弃,不拒收 | 【已废弃】需求展开项次序(0起);#7067 去槽位化后创建主流程忽略、不再落库,正常派单传与不传行为一致 |
| vehicleId | Body | Long | 是 | - | 车辆 ID(雪花) |
| driverId | Body | Long | 是 | - | 司机 ID(雪花) |
| startDate | Body | Date | 是 | - | 用车开始日期(出团日,闭区间起点) |
| endDate | Body | Date | 是 | - | 用车结束日期(闭区间终点) |
| pickupAt | Body | String | 否 | - | 接客地自由文本(城市衔接判定用) |
| dropoffAt | Body | String | 否 | - | 送客地自由文本(城市衔接判定用) |
| headcount | Body | Integer | 否 | - | 人数(座位不足判定用,可空时不判座位) |
| protocolPrice | Body | BigDecimal | 否 | ≥0.00,整数最多10位/小数最多2位 | 协议价日单价(元/车天,派车时冻结);不传后端按车辆车型+开始日期价格日历兜底 |
| vehicleFeeTotal | Body | BigDecimal | 否 | ≥0.00,整数最多10位/小数最多2位;已废弃 | 历史字段,最终总车费已改为逐日车费只读合计;传值将被拒绝 |
| vehicleFeeAdjustmentReason | Body | String | 否 | ≤256 | 本次单日车费与日历参考价不一致时的调整原因 |
| dailyVehicleFees | Body | Array | 否 | - | 本次派车单日车费覆盖;未传日期使用价格日历参考价,只影响本次派车且不回写价格日历 |
| chargeableServiceDates | Body | Array | 否 | - | 收取车费的服务日期;不传默认全部服务日,空数组表示全部免费 |
| vehicleFeeWaiverReason | Body | String | 否 | ≤256 | 免费服务日原因;全部服务日免费时必填 |
| confirmAllServiceDatesFree | Body | Boolean | 否 | - | 全部服务日免费二次确认;chargeableServiceDates 为空数组时必须为 true |
| sendItinerarySms | Body | Boolean | 否 | - | 是否向该车师傅发送行程短信;不传按 false(不发) 处理,行程单短链无论是否发短信都会生成 |
| holdMode | Body | Integer | 否 | 已废弃,取值 0/1,服务端不消费 | 已废弃:#5827 起服务端忽略本字段,一律按一步派定处理,勿再传 |
| messageTemplateId | Body | Long | 否 | 已废弃,不消费 | 已废弃:#5827 取消「待司机确认」通知后本字段不再消费,勿再传 |
| customBody | Body | String | 否 | ≤4000;已废弃,不消费 | 已废弃:#5827 取消「待司机确认」通知后本字段不再消费,勿再传 |
| fromEntry | Body | String | 否 | - | 操作来源(from-board/from-vehicle/from-driver/from-matrix,仅记录来源) |
| skipCityJunctionException | Body | Boolean | 否 | - | 跳过城市衔接例外:true=命中冲突即抛 605005(默认 false 允许城市衔接放行) |
| strictSeats | Body | Boolean | 否 | 已废弃,忽略 | 历史兼容字段,现已忽略;车型/座位不匹配只提示不阻断 |
| confirmCrossResident | Body | Boolean | 否 | - | 跨常驻车显式确认:true=已知司机与所选车辆不是常驻组合仍继续派车;非跨常驻车可不传 |
| requestId | Body | String | 是 | ≤64 | 幂等请求标识(前端每次保存生成稳定值,区分故意重派与重复提交) |
| changeRequestId | Body | Long | 否 | 创建接口不消费 | 历史兼容换车请求 ID(当前创建接口不消费) |
出参
本次无新增、无修改——AssignmentWriteRespVO 结构未动。⚠️ 派单 ID 字段名是 id(不是 assignmentId,旧版本文档曾写错,以本条为准)。下表为全量 22 个字段:
| 字段 | 类型 | 说明 |
|---|---|---|
| id | String | 新建派单 ID(雪花,字符串序列化) |
| assignmentGroupId | String | 派车组 ID(雪花;同一辆车连续每日切片共用,字符串序列化);历史行无 assignmentGroupId 时回退下发 assignmentId,对任何真实行恒非空 |
| assignmentSlotId | String | 稳定车辆槽位 ID(字符串序列化);改派产生新派车组时保持不变 |
| assignmentStatus | String | 派单状态(#5827 提交即派定,恒 assigned) |
| stageCode | String | 生命周期阶段码(后端统一下发) |
| stageLabel | String | 生命周期阶段文案(后端统一下发) |
| currentStep | Integer | 当前三阶段步骤(订单详情/排车/确认执行) |
| skippedStepCodes | Array | 展示层被跳过的步骤;#5827 后恒为空数组,字段保留兼容 |
| protocolPrice | String | 协议价日单价快照(元/车天,字符串序列化) |
| vehicleFeeAutoTotal | String | 价格日历自动合计参考(字符串序列化) |
| vehicleFeeAutoComplete | Boolean | 自动合计是否覆盖全部计费服务日 |
| vehicleFeeTotal | String | 该车辆槽位最终总车费(字符串序列化) |
| vehicleFeeSource | String | 最终总车费来源:AUTO、MANUAL、INCOMPLETE |
| vehicleFeeAdjustmentReason | String | 手工总车费调整原因 |
| dailyVehicleFees | Array | 本次派车全部服务日的逐日车费快照 |
| holdSentAt | String | 真实 HOLD 通知发出时间;#5827 后新派车不再发该通知,恒为 null(字段保留兼容) |
| confirmedAt | String | 派定确认时间(#5827 后恒回显) |
| sideEffects | Object | 副作用执行结果(#5827 后恒回显) |
| sendItinerarySms | Boolean | 车务本次是否选择向该车师傅发送行程短信 |
| itinerarySmsEventId | String | 行程短信可靠事件 ID(字符串序列化);未勾选发送时为空 |
| itinerarySmsStatus | String | 本次派车的初始短信状态(PENDING/NOT_SENT) |
| dailyDifferences | Array | 最终派定失败时的逐日基线差异;成功时为空 |
请求示例
POST /admin/fleet/assignments
{
"orderId": 1934567890123456789,
"vehicleId": 99
}
响应示例
{
"code": 200,
"message": "成功",
"data": {"id": "1234567890123456789", "assignmentStatus": "assigned"},
"success": true
}
空数据 / 降级响应
N/A(操作必返结果)。
错误响应
{
"code": 602203,
"message": "订单的团期归属尚未回填, 无法派车",
"data": null,
"success": false
}
业务边界
- 仅团期子订单且 groupBatchId 为空时触发 602203
- 普通订单不受影响
- 需在订单侧补齐团期归属
4. 派车批量创建 POST /admin/fleet/assignments/batch
VO: BatchCreateAssignmentReqVO → BatchAssignmentWriteRespVO
使用场景
批量提交逐日派车方案。校验规则同单笔,单行触发 602203 即整批失败。
入参
本次无新增、无修改——请求体结构一个字没动,dailyPlan[] 是扁平结构(serviceDate × vehicleId × driverId,不是嵌套 assignments[])。本次变化只发生在受理与否上(见下方「错误响应」)。下表为 BatchCreateAssignmentReqVO(含内部类 DailyPlanItem,origin/dev-v3)全量字段:
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| orderId | Body | Long | 是 | - | 订单 ID |
| orderNo | Body | String | 否 | - | 订单号冗余 |
| requirementId | Body | Long | 是 | - | 当前生效用车需求 ID |
| startDate | Body | Date | 是 | - | 用车开始日期 |
| endDate | Body | Date | 是 | - | 用车结束日期 |
| pickupAt | Body | String | 否 | - | 接客地 |
| dropoffAt | Body | String | 否 | - | 送客地 |
| headcount | Body | Integer | 否 | - | 乘客人数 |
| confirmNoVehicleServiceDates | Body | Boolean | 否 | - | 逐日计划未覆盖全部服务日期(存在不配车日期)时的显式二次确认 |
| sendItinerarySms | Body | Boolean | 否 | 不传按 false | 是否向本批各车师傅发送行程短信;整批统一决策,避免同需求同代内各组行程短信选择不一致 |
| skipCityJunctionException | Body | Boolean | 否 | - | 跳过城市衔接例外 |
| fromEntry | Body | String | 否 | - | 操作来源 |
| requestId | Body | String | 是 | ≤64 | 批次级幂等请求标识 |
| dailyPlan[] | Body | Array | 是 | ≤4000 项 | 按行程日的完整配车列表:逐项为 服务日期×车辆×司机;同一服务日允许多条;需求日期窗内未出现的服务日视为该日不配车 |
| dailyPlan[].serviceDate | Body | Date | 是 | - | 服务日期 |
| dailyPlan[].vehicleId | Body | Long | 是 | - | 车辆 ID |
| dailyPlan[].driverId | Body | Long | 是 | - | 司机 ID |
| dailyPlan[].assignmentPrice | Body | BigDecimal | 否 | ≥0.00,整数最多10位/小数最多2位 | 本车当天实际价格;可不传,未传按车型价格日历参考价兜底(与单体派单同口径) |
| dailyPlan[].priceAdjustmentReason | Body | String | 否 | ≤256 | 实际价格与价格日历参考价不一致时的调整原因 |
| dailyPlan[].confirmCrossResident | Body | Boolean | 否 | - | 跨常驻车显式确认 |
| Body | - | 否 | 携带非 null 值即 400 | 已移除:去槽位化后不再有槽位序号;携带本字段将被 400 拒绝 | |
| Body | - | 否 | 携带非 null 值即 400 | 已移除:旧收费日期字段;携带将被 400 拒绝 | |
| Body | - | 否 | 携带非 null 值即 400 | 已移除:旧免费服务日字段;携带将被 400 拒绝 | |
| Body | - | 否 | 携带非 null 值即 400 | 已移除:旧免费服务日字段;携带将被 400 拒绝 | |
| Body | - | 否 | 携带非 null 值即 400 | 已移除:#5827 起一步派定;携带将被 400 拒绝 | |
| Body | - | 否 | 携带非 null 值即 400 | 已移除:稳定车辆槽位序号;携带将被 400 拒绝 | |
| Body | - | 否 | 携带非 null 值即 400 | 已移除:用车开关(某天不配车=该天无配置项);携带将被 400 拒绝 | |
| Body | - | 否 | 携带非 null 值即 400 | 已移除:接机标志改由接送机配置步骤写入;携带将被 400 拒绝 |
出参
本次无新增、无修改——BatchAssignmentWriteRespVO 结构未动。⚠️ 旧版本文档曾写作 successCount/failureCount、createdAssignments/updatedAssignments/cancelledAssignments,这些字段并不存在,以本条为准。下表为全量字段(assignments[] 每项复用「3. 派车创建」出参表的 AssignmentWriteRespVO 结构,不在此重复展开):
| 字段 | 类型 | 说明 |
|---|---|---|
| assignments[] | Array | 按 fleetItemIndex 升序返回的派单结果 |
| assignments[].fleetItemIndex | Integer | 当前用车需求展开后的车辆槽位序号 |
| assignments[].assignment | Object | 复用单槽位派单响应,结构见上方「3. 派车创建」出参字段表(AssignmentWriteRespVO) |
| finalPlanPublished | Boolean | 本次是否已发布最终方案;false 表示排车已落库但接送机未配齐,订单车控仍为处理中,须继续走第③步接送机配置 |
| pickupDropoffGate | Object | 接送机门禁状态(要求日与缺口日) |
| failedFleetItemIndex | Integer | 直接派定基线失败的车辆槽位序号 |
| dailyDifferences | Array | 直接派定基线失败的逐日差异 |
请求示例
POST /admin/fleet/assignments/batch
{
"orderId": 1934567890123456789,
"requirementId": 1934567890123456790,
"startDate": "2026-05-06",
"endDate": "2026-05-07",
"requestId": "batch-20260917-0001",
"dailyPlan": [
{"serviceDate": "2026-05-06", "vehicleId": "99", "driverId": "88"}
]
}
响应示例
{
"code": 200,
"data": {"assignments": [{"fleetItemIndex": 0, "assignment": {"id": "1234567890123456789"}}],
"finalPlanPublished": true},
"success": true
}
空数据 / 降级响应
N/A(整批要么受理要么失败关闭,不存在「空成功」形态)。
错误响应
{
"code": 602203,
"message": "订单的团期归属尚未回填, 无法派车",
"data": null,
"success": false
}
业务边界
- 单行 602203 导致整批失败
- 其余行不落库
- 同单笔处理规则
四、契约约束与正确调用方式
| 场景 | 做法 |
|---|---|
| 派车无团期身份 | 返 602203,需在订单侧补团期 |
| 矩阵按团期筛选 | 传新增 groupBatchId 参数 |
| 订单换团后 | 库列是快照(建行时固化、不回溯刷新);接口的回显与筛选都按当前归属,仅 order-v3 降级时回退快照 |
五、数据库行为
| 操作 | 影响 |
|---|---|
| 创建派车(无 groupBatchId) | 拒绝 602203 |
| 创建派车(有 groupBatchId) | fleet_assignment.group_batch_id 记录值 |
六、边界行为
- 团期子订单无 groupBatchId → 602203(fail-closed)
- 普通订单 groupBatchId 为 NULL → 正常建行
- 存量派车行 → groupBatchId 为 NULL
- 已退团户 →
fleet_assignment.group_batch_id库列保留快照值;接口回显与筛选按当前归属(降级时才回退该快照)
六.5 枚举
新增错误码: 602203 TRANSFER_GROUP_IDENTITY_INVALID —— 派车团期身份不可解析
错误码段位:
- 602000-602099: 配车需求级错误
- 602200-602299: 派车身份级错误(新增)
六.6、修改前后对比
| 项目 | 改前 | 改后 |
|---|---|---|
| BoardOrderRecordVO.groupBatchId | 不存在 | 新增(字符串序列化) |
| MatrixDayOrderVO.groupBatchId | 不存在 | 新增(字符串序列化) |
| GET /admin/fleet/board/orders 入参 | 无 groupBatchId | 新增可选参数 groupBatchId |
| GET /admin/fleet/matrix/day-orders 入参 | 无 groupBatchId | 新增可选参数 groupBatchId |
| 派车子订单无 groupBatchId 行为 | 静默建行 | 拒绝返 602203 |
六.7、影响评估
- 向后兼容: 否(行为破坏性)
- 新增参数可选,不传时兼容(正向)
- 行为变化破坏性:此前能建成的「团期子订单无 groupBatchId 派车」现在返 602203 拒绝
- 前端同步: 是(必须)
- 看板矩阵增加 groupBatchId 字段展示
- 矩阵增加 groupBatchId 筛选参数透传
- 派车流程处理 602203 错误码
- 数据: 存量派车行 groupBatchId 为 NULL(不需迁移)
七、不影响范围
- 订单换团逻辑
- 派车行后续修改
- 其他看板筛选维度
- 矩阵 grid 接口
八、测试环境已验证
GET /admin/fleet/board/orders → 200 ✓
GET /admin/fleet/matrix/day-orders?date=2026-05-04 → 200 ✓
GET /admin/fleet/matrix/day-orders?date=2026-05-04&groupBatchId=xxx → 200 ✓
POST /admin/fleet/assignments (无团期身份) → 602203 ✓
POST /admin/fleet/assignments (普通订单) → 200 ✓
十、相关文档
关联 / 联系人
链接
联系人
- 后端: @wx