18 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 | 5818 | 车务全量代码审计整改:保险错误码迁段(540033-540037→601200-601204)、新增多个业务码、对账/看板响应结构与数值变化、若干入参新增校验 | admin | wx(GIT) | 修改接口 | deployed | not_required | implemented | mmg | 46a57557 | 2026-08-11 | PR #5837 已合并 dev-v3 并部署测试服,全量 3485 用例 0 失败、ArchTest 12/12、Flyway 迁移实测通过(540033 残留 0 / 601200 恰好 7 行)。本条汇总一轮全量审计整改中**所有前端可见**的变化,按「必须改」「按需改」「只需知晓」三档排列,逐条给了触发条件与处置口径。前端已实现(46a57557):实证后 A1 保险错误码(前端零引用)/A2 dayPrice(仅展示经 formatPrice 内部 Number 安全)/A5 到期看板(前端固定白名单传值)/B3 opType(无下拉)/B4 priceSource(DAILY_FEE_SOURCES 已含 FREE)/B5(纯后端)零改动;实际落地子集——A6 模板编辑 isDefault 恒参与 diff 对比、submit 写接口前按编辑态裁剪(编辑未变省略避免 600804,顺带修复仅切换默认被无变化短路误拦);A3/A4 useAssignFlow 新增 605063(回执损坏禁自动重试)/605064(全程槽逐日部分免费)专用提示;B1 对账行标识改后端权威 fleet 字段(兜底行 fleetTeamId 可为 null,旧数据回退)并抽 reconAdapter 纯函数;B2 保险分来源金额优先读 manualAmount/baoyouAmount+sourceSubtotals(消除同司机跨来源矛盾行,兼容旧响应回退);B6 清 CAPACITY_INSUFFICIENT/passengerCapacity/capacityGap 死契约。测试:reconAdapter.spec 6+EditModal.spec 4+useAssignFlow final-confirm +2+baselineDifference 同步,fleet 全域 66 文件 618 用例全绿,checkpoint 10 文件含生产构建全过。 | 2026-08-11 | dev-v3 |
车务:全量代码审计整改的前端契约变化(#5818 / PR #5837)
服务: hl-fleet-service (8087/8187) PR: #5837 Issue: #5818 背景: 对 hl-fleet-service(740 文件约 10 万行)做了一轮规范/质量/逻辑三维全量审计并整改(确认 151 条缺陷,修复 127 条 + CR 整改)。绝大多数是后端内部修复,但有以下几类前端能看见的变化。
变更接口清单
| 接口 | 变化类型 | 见下文 |
|---|---|---|
GET /admin/fleet/insurance/tasks |
errorCode 值域迁段(存量数据一并改写) |
A1 |
GET /admin/fleet/vehicles/options |
dayPrice number → string |
A2 |
POST /admin/fleet/assignments/{assignmentId}/confirm |
新增错误码 605063 | A3 |
POST /admin/fleet/assignments/requirements/{requirementId}/confirm |
新增 605063、首次给出完整错误码表(605059/605062/605063);dailyDifferences[] 删 2 字段 |
A3 / B6 |
POST /admin/fleet/assignments |
新增错误码 605064 | A4 |
POST /admin/fleet/assignments/batch |
新增错误码 605064 | A4 |
POST /admin/fleet/assignments/{assignmentId}/change |
新增错误码 605064 | A4 |
GET /admin/fleet/board/expiry |
kinds/buckets 非法值由静默忽略改为 100001 |
A5 |
PUT /admin/fleet/message-templates/{id} |
isDefault 语义变化 + 新增 600804 |
A6 |
GET /admin/fleet/reconciliation/cars |
grandTotal.actual/diff 数值变化;fleets[] 可能出现兜底行 |
B1 |
GET /admin/fleet/reconciliation/insurance |
数值变化;drivers[] 新增分来源金额字段 |
B2 |
GET /admin/fleet/reconciliation/pending-compensations |
opType 白名单补 INSURANCE |
B3 |
GET /admin/fleet/board/orders/{orderId} |
priceSource 新增 FREE;混态派车组展示区间修正 |
B4 / B5 |
POST /admin/fleet/h5/tokens |
expireDays 新增 1-90 上限 |
C1 |
| 操作时间线查询 | page 新增 100000 上限 |
C1 |
POST / PUT /admin/fleet/vehicles |
primaryDriverId 新增存在性校验(600205) |
C2 |
POST /admin/fleet/insurance/tasks/{taskId}/retry |
补登记 601210-601215(原返 100500) | C3 |
POST /admin/fleet/drivers/{driverId}/insurance/purchase、/insure |
降级时由 100500 改返 605601 | C3 |
POST /admin/fleet/driver-pending/{pendingId}/approve |
删 605022,新增 600205 / 600210 | C3 |
🔴 A. 必须改(不改会踩坑)
A1. 保险任务 errorCode 值域迁段:540033-540037 → 601200-601204
接口:GET /admin/fleet/insurance/tasks(列表)响应 errorCode 字段。
原因:车务此前在 order 服务的 5xxxxx 段私铸错误码,其中 540033 / 540034 与 hl-order-service-v3 已注册的真码撞号且语义完全不同(order 侧 540033 是「被保人缺少出生日期」、540034 是「产品已下架/不可售」)。现已迁到 fleet 自有的 601200-601299 段。
| 旧码 | 新码 | 含义 |
|---|---|---|
| 540033 | 601200 | 司机年保未覆盖服务日 |
| 540034 | 601201 | 保险台账与司机年保档案不一致,需人工核对 |
| 540035 | 601202 | 退保后保障状态待复核 |
| 540036 | 601203 | 司机保险档案在处理期间已变更 |
| 540037 | 601204 | 历史取消事件缺少取消前状态 |
⚠️ 存量数据已随 Flyway 迁移一并改写(测试服实测:迁移后 540033-540037 残留 0)。所以发版当天所有历史待处理行的码会同时跳变。
前端处置:若在任何地方硬编码过 540033-540037 做分支、文案映射或埋点,必须同步改成 601200-601204。
⚠️ 注意 errorCode 这一列是两个来源合用:601200-601204 是车务自有的失败原因码,其余是保险服务上游业务码原样透传(如 540007 无匹配费率)。不能按段位反推服务归属,也不能把它当 HTTP 响应码用。
A2. 车辆下拉 dayPrice 由 JSON number 改为 string
接口:GET /admin/fleet/vehicles/options 的 dayPrice。
450.00(number)→ "450.00"(string),与 VehicleModelRespVO.basePrice 口径统一(金额统一字符串下发,避免 JS 浮点精度问题)。
前端处置:参与计算前必须 Number(dayPrice)。否则 dayPrice * days 会退化成字符串拼接("450.00450.00")、dayPrice.toFixed(2) 直接 TypeError、dayPrice > 0 变成字符串比较。
A3. 派车确认新增错误码 605063(不可自愈终态,禁止自动重试)
接口:POST /admin/fleet/assignments/{assignmentId}/confirm 与 POST /admin/fleet/assignments/requirements/{requirementId}/confirm。
{ "code": 605063, "msg": "原子确认回执已损坏,无法幂等重放,请联系管理员" }
原来这个场景走全局兜底返 100500 系统繁忙,前端会落 default 分支甚至无脑重试。
前端处置:这是不可自愈终态——同 requestId 重试永远返回同码。不得自动重试、不得静默轮询,直接提示用户联系管理员人工处理。
另:需求级确认端点 POST /admin/fleet/assignments/requirements/{requirementId}/confirm 首次给出完整错误码表,前端若之前只处理 605062,需补 605059(同 requestId 用于不同确认内容,需换新 requestId)与 605063。
A4. 全程槽「逐日部分免费」新增专用错误码 605064
接口:POST /admin/fleet/assignments(单派)、POST /admin/fleet/assignments/batch、POST /admin/fleet/assignments/{assignmentId}/change。
{ "code": 605064, "msg": "全程槽不支持逐日部分免费,请整程统一计费或改用逐日派车方案" }
触发条件:对一个全程槽(一条行覆盖整个服务期)提交的 chargeableServiceDates 既不是全部服务日、也不是空集合,而是真子集。
原因(重要):修复前这种输入会被静默算错——按首日单点判定后整行写入,首日免费就导致整程车费归零(资损)。现在明确拒绝。
前端处置:给该码专用提示,引导用户「整程统一计费」或「改用逐日派车方案」;该码不可自动重试(同参数必然同码)。若前端有按 code == 100001 的通用参数错误提示分支,此场景会不再命中它。
A5. 到期看板 kinds / buckets 非法值由静默忽略改为报错
接口:GET /admin/fleet/board/expiry。
传白名单外的值原来是「静默忽略、返四类全量」,现在直接返 100001。
kinds合法值:inspect/vehInsure/license/driverInsurebuckets合法值:expired/urgent/soon/watch/ok- 大小写敏感(传
LICENSE/Expired会报错)
为什么这么改:静默忽略会让「筛选不生效却返回全量」被误读成「该类目下真有这么多」。这是对齐 #5455 已定案口径——列表接口的 statuses / vehicleTypeKeys 本来就是拒绝非法值,到期接口是唯一例外。
A6. 消息模板编辑 isDefault 语义变化 + 新增 600804
接口:PUT /admin/fleet/message-templates/{id}。
isDefault语义由「不传 = 非默认」改为「编辑不传 = 保持原值」(新增仍是不传 = 非默认)。- 新增错误码 600804「默认模板不可取消默认」(与 delete 的 600803 对称)。
前端处置:若编辑表单里始终回传 isDefault: false,取消默认会从「静默成功」变为 600804 报错。请改为只在用户真的切换时才传该字段。
🟡 B. 按需改(数值/结构变化,看你怎么渲染)
B1. 对账「车队」Tab 数值与结构变化
接口:GET /admin/fleet/reconciliation/cars
grandTotal.actual与diff的数值会变:修复前从fleets[]累加,漏计了team_no为空的核单车费行与「本期已无 active prep 但有核单车费」的车队;现在对费用行全量求和。财务侧会看到历史月份合计变大、diff 由偏负回正——这是修 bug 不是回归。fleets[]可能出现「兜底车队行」:fleet="unknown"/fleetName="未归属车队"(team_no 缺失桶),或fleet=真实 teamCode(本期无 active prep 但有核单车费)。这类行vehicles=[]、estimatedTotal=payableTotal="0.00"、actualTotal/diff有值;能反查到车队的已补齐fleetTeamId/fleetType/settleType/settleMode,真无主数据的unknown桶fleetTeamId仍为 null。 前端处置:行 key 请用fleet字段,不要用fleetTeamId;按settleMode分列渲染时要容忍兜底行。 注:只在未传fleets/fleetTeamIds时出现;显式筛车队时行为不变(且此时grandTotal.actual只统计被选中车队,比修复前更严格)。
B2. 对账「保险」Tab 数值与结构变化
接口:GET /admin/fleet/reconciliation/insurance
- 数值会变:修复前用「该司机在区间内最早那一行」的 source 代表全月,导致逐日投保的司机整月被渲染成「无保险」且金额不入小计。现在逐行按
driver_insurance_source分组求和。fleets[].sourceSubtotals.manual/baoyou、grandTotal、typeCounts、drivers[]的多个字段数值与取值都会变。 drivers[]新增分来源金额字段(manualAmount/baoyouAmount),insuranceAmount保留为合计。这样「Σ drivers 按 source 分桶 == sourceSubtotals」可对账(修复前同司机跨来源会出现source=BAOYOU但金额含 MANUAL 的矛盾行)。
建议:部署后拉一个已有数据的月份做前后对比截图给财务确认。
B3. 待补偿列表 opType 接受 INSURANCE
接口:GET /admin/fleet/reconciliation/pending-compensations
opType 白名单补齐 INSURANCE(此前传 INSURANCE 返 400,而该值确实会被写入)。前端下拉可补该项:GENERATE / INVALIDATE / REACTIVATE / TRUNCATE / INSURANCE。
B4. 派车板逐日车费 priceSource 新增 FREE
接口:GET /admin/fleet/board/orders/{orderId} 的 dailyVehiclePlan[].priceSource
免费服务日此前被错标为 OVERRIDE(因为一个 @TableField(exist=false) 的字段恒为 null 导致整段判断是死分支),现在正确返回 FREE,且 priceAdjustmentReason 在 FREE 时返回免费豁免原因而非恒 null。金额不变(免费日仍 0.00)。
B5. 派车板混态派车组的展示区间修正
接口:GET /admin/fleet/board/orders/{orderId}(组视图 / 槽位卡)
多日派车组在行程进行中是天然混态(前几天已完结、后几天在途)。修复前展示区间只按「主状态行」收窄,却带着全程的逐日车费明细,自相矛盾(区间 1 天却有 5 条逐日车费)。现在区间与车费明细同源,逐日车费条数会变多(变正确),无字段结构变化。
B6. 派车确认差异契约删字段
接口:POST /admin/fleet/assignments/requirements/{requirementId}/confirm 的 data.dailyDifferences[]
删除 passengerCapacity / capacityGap 两字段,differenceType 的取值去掉 CAPACITY_INSUFFICIENT——三者自 #5810 起后端已永远不产出,属死契约。
🟢 C. 只需知晓(新增入参校验 / 错误码登记)
C1. 新增入参上限
| 接口 | 字段 | 新增校验 | 影响 |
|---|---|---|---|
POST /admin/fleet/h5/tokens |
expireDays |
@Min(1) @Max(90) |
传 0 或 365 原来能建 token,现在 400。若有「长期有效」按钮传大值会失败 |
| 操作时间线 | page |
@Max(100000) |
超限原来返空列表,现在 400。建议前端自行夹紧避免翻页越界 |
C2. 车辆绑定常驻司机新增存在性校验
接口:POST / PUT /admin/fleet/vehicles 与导入 UPDATE 分支。
primaryDriverId 指向不存在或已软删的司机,现在直接返 600205「司机不存在」(此前静默落库成悬挂引用)。前端下拉缓存过期会踩到,需要有兜底提示。
C3. 错误码清单补登记(行为零变化,只是 Swagger 补全)
POST /admin/fleet/insurance/tasks/{taskId}/retry:补登记 601210-601215(权威保单未通过复核 / 权威保单查询失败 / 权威年保快照查询失败 / 既有成功任务等待权威数据复核 / 冲突后权威查询失败 / 冲突后档案复核失败)。这些场景原先一律返 100500「系统繁忙」,现在返精确码。POST /admin/fleet/drivers/{driverId}/insurance/purchase与/insure:order-v3 保险服务降级时由 100500 改为按 Controller 承诺的 605601 返回。POST /admin/fleet/driver-pending/{pendingId}/approve:删除 605022(该码全服务已无抛出点,前端若有该分支应删或转为不可达兜底),新增 600205(自带车常驻司机不存在)与 600210(并发冲突,续签审核 CAS 失败,需刷新重试)。
C4. 已删除的请求字段
DriverSaveReqVO.blacklistReason 请求字段已删除(后端早已不消费)。不会 400(Jackson 忽略未知字段),但 Swagger 契约里没有了,前端可清理。
验证证据
门禁:全量 mvn -pl hl-fleet-service test(clean 后)3485 个用例 0 失败,仅剩 10 个 ReleaseEOccupancyMysql8033RecoveryTest 错误(该类设计上只能由 test/run-mysql833-provider.ps1 传冻结 SHA 系统属性运行,基线同款);FleetRedLineArchTest 12/12 绿;spotless:check clean。相比基线(3382 用例 / 1 失败 + 13 错误)新增约 100 个用例,红项只减不增。
测试服实测(部署 task 55207386,双实例 12:59 重启):
- 错误码迁段(A1):迁移前
SELECT error_code, LEFT(error_message,30), COUNT(*) FROM fleet_insurance_task WHERE error_code IN ('540033','540034') GROUP BY 1,2→ 7 行 540033、文案全部以「司机年保」开头(100% 命中迁移条件);迁移后 540033-540037 残留 0、601200 恰好 7 行。 - P0 终止截断(本次整改的最高优先级缺陷,前端不可见但影响车务可用性):订单 2086697883247022081 含两条全程行(08-26
28 与 08-2931),POST /internal/fleet/assignment/truncate-from-termination传 terminateDate=08-30 返回 200(修复前必抛 605907 且永久失败、车/司机占用永不释放)。落库形态:原全程行按天拆片 → 首日 08-29 保留 assigned 且车费按新边界从 4500 重算为 1500,08-30/08-31 两片 canceled;另一条 08-2628 的行完全未被触碰;对账 prep 精确反标(08-29 active、08-30/08-31 canceled、另一行 08-2628 全 active)——既不漏截也不多截。 - Flyway 全量迁移在 H2 与测试服 MySQL 均执行成功。
前端 checklist
- A1 保险
errorCode码表由 540033-540037 改为 601200-601204 - A2
/vehicles/options的dayPrice参与计算前Number()转换 - A3 confirm 两端点接住 605063(禁自动重试),需求级确认补 605059 分支
- A4 派单三端点接住 605064(禁自动重试),给专用引导文案
- A5 到期看板
kinds/buckets只传白名单值且大小写严格 - A6 模板编辑不再无条件回传
isDefault: false,接住 600804 - B1 对账车队行 key 改用
fleet字段,容忍兜底行(vehicles=[]、fleetTeamId可能为 null) - B2 对账保险 Tab 消费新增的
manualAmount/baoyouAmount - B3 待补偿
opType下拉补INSURANCE - B4 逐日车费
priceSource支持FREE - C1
expireDays≤90、page≤100000 前端夹紧 - C2 车辆保存接住 600205
做完请把 frontmatter 的 frontend_status 改为 implemented 并填 frontend_ref。