From e28c94c18b2ee3b56765b428d0f04e08cce540ef Mon Sep 17 00:00:00 2001 From: API Changelog Bot Date: Thu, 24 Sep 2026 10:56:50 +0800 Subject: [PATCH] =?UTF-8?q?docs(changelog):=20#8301=20=E8=BD=A6=E5=8A=A1?= =?UTF-8?q?=E7=9C=8B=E6=9D=BF=E5=B8=A6=E6=97=A5=E6=9C=9F=E7=AD=9B=E9=80=89?= =?UTF-8?q?=E6=97=B6=E5=8D=95=E6=9D=A1=20requirement=5Fid=20=E4=B8=BA?= =?UTF-8?q?=E7=A9=BA=E7=9A=84=E6=B4=BE=E8=BD=A6=E8=A1=8C=E4=B8=8D=E5=86=8D?= =?UTF-8?q?=E6=B8=85=E7=A9=BA=E6=95=B4=E4=B8=AA=E6=97=A5=E6=9C=9F=E7=AA=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...期筛选单条脏行不再整窗清零-修改接口-管理后台.md | 293 ++++++++++++++++++ 1 file changed, 293 insertions(+) create mode 100644 changelogs-v2/2026-09/24_8301_车务看板日期筛选单条脏行不再整窗清零-修改接口-管理后台.md diff --git a/changelogs-v2/2026-09/24_8301_车务看板日期筛选单条脏行不再整窗清零-修改接口-管理后台.md b/changelogs-v2/2026-09/24_8301_车务看板日期筛选单条脏行不再整窗清零-修改接口-管理后台.md new file mode 100644 index 00000000..2b66e440 --- /dev/null +++ b/changelogs-v2/2026-09/24_8301_车务看板日期筛选单条脏行不再整窗清零-修改接口-管理后台.md @@ -0,0 +1,293 @@ +--- +schema: "hl-changelog/v2" +ticket: "8301" +title: "车务看板带日期筛选时,单条 requirement_id 为空的派车行不再清空整个日期窗" +consumer: "admin" +author: "wx(GIT)" +change_type: "修改接口" +backend_status: "deployed" +gateway_status: "verified" +frontend_status: "not_required" +frontend_owner: "" +frontend_ref: "" +target_release: "" +verified_at: "" +status_note: "" +updated_at: "2026-09-24" +base: "dev-v3" +--- + +# fleet: 看板日期筛选分支的脏行失败关闭收窄为跳过单行 + +> **存放目录**: `changelogs-v2/2026-09/` +> +> **服务**: hl-fleet-service +> **PR**: #8310 +> **Issue**: #8301 +> **日期**: 2026-09-24 +> **影响范围**: 管理后台「车务看板」订单列表/网格视图(带日期筛选时) + +--- + +## ⚠️ 关键变化 + +**带日期筛选时,单条脏数据不再清空整个日期窗。** 此前只要日期窗里存在任意一条 `requirement_id` 为空的派车行,`GET /admin/fleet/board/orders`(带 `startDate/endDate` 或 `startDayFrom/startDayTo`)就整页返回 `records=[]`、`total=0`、`code=200`,**不报错**——页面上看到的是「这几天没有订单」而不是任何异常。现在这条行被**跳过并记 WARN**(WARN 里带 `orderId`/`assignmentId`/`assignmentGroupId`),同一日期窗内其余订单**照常返回**,与不带日期筛选时的既有口径一致。 + +**接口契约零变化**:路径、参数、字段、类型、必填性、枚举、错误码全部不变,只修正日期分支的行为。 + +--- + +## 一、背景 + +车务看板带日期筛选时走一条独立的「当前主单日期候选」扫描分支。该分支原本把四类候选行异常合并成一个失败关闭条件,其中一类是「派车行的 `requirement_id` 为空」——这是历史数据迁移、手工修数或未来写路径缺陷可能留下的占位行。这类行本身匹配不上任何用车需求,在不带日期的路径里只是被跳过并记一条汇总 WARN;但在日期分支里,它会让**同页全部订单**的候选一起作废,表现为整窗静默返回空。 + +本次把该条件按成因拆开:真正影响槽位聚合正确性的三类结构性畸形(行对象缺失、主单 ID 缺失、派车组 ID 与派车 ID 同时缺失)以及重复槽位键**仍然失败关闭**,只是各自补一条带定位信息的 WARN;`requirement_id` 为空的行改为逐行剔除并记 WARN。 + +--- + +## 二、变更接口清单 + +| # | 接口 | 方法 | 路径 | 变更类型 | 说明 | +|---|------|------|------|----------|------| +| 1 | 看板订单列表 | GET | `/admin/fleet/board/orders` | 行为变更(契约不变) | 带日期筛选时,`requirement_id` 为空的派车行由「整窗失败关闭」改为「跳过该行 + WARN」 | + +--- + +## 三、接口详情 + +### 1. 看板订单列表 `GET /admin/fleet/board/orders` + +**VO**: `BoardOrderPageReqVO → BoardOrderPageRespVO`(`records: BoardOrderRecordVO[]`) + +#### 使用场景 + +管理后台「车务看板」订单列表/网格视图(`variant=list|grid`)。车务人员按状态、日期、团号、车型等条件筛出待派/已派订单卡片,逐卡执行改派、派车、查看行程等操作。本次改动只影响**带日期筛选**时该列表返回的记录集合。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| startDate | Query | LocalDate | ❌ | `yyyy-MM-dd` | 行程日期窗起(`startDayFrom` 的兼容别名) | +| endDate | Query | LocalDate | ❌ | `yyyy-MM-dd` | 行程日期窗止(`startDayTo` 的兼容别名) | +| startDayFrom | Query | LocalDate | ❌ | `yyyy-MM-dd` | 行程日期窗起;为空时回落到 `startDate` | +| startDayTo | Query | LocalDate | ❌ | `yyyy-MM-dd` | 行程日期窗止;为空时回落到 `endDate` | +| statuses / status | Query | String[] / String | ❌ | 枚举:unassigned/unassigned_urgent/holding/holding_urgent/assigned/canceled/completed | 状态筛选,可多选;`status` 为单值兼容别名 | +| vehicleTypeKeys / typeKeys | Query | String[] | ❌ | 车型大类字典值 | 车型多选筛选 | +| keyword / driverName / contactName / teamNo / plannerName | Query | String | ❌ | - | 关键字、司机、联系人、团号、定制师等模糊搜索 | +| groupBatchId | Query | Long | ❌ | 等值匹配 | 运营团期 ID | +| consultantId | Query | Long | ❌ | - | 定制师 ID 精确筛选 | +| variant | Query | String | ❌ | `list`/`grid` | 视图口径 | +| page(或 pageNo) | Query | Integer | ❌ | ≥1,缺省 1 | 页码 | +| pageSize | Query | Integer | ❌ | 1-100 | 每页条数 | + +> 本单不新增、不删除、不改任何参数的类型与必填性;上表只为把「受影响的日期参数」放进完整上下文。 + +#### 出参 `Result` + +| 字段 | 类型 | 说明 | +|------|------|------| +| records | BoardOrderRecordVO[] | 本页看板卡片;本次改动只影响带日期筛选时该数组的内容 | +| total | Long | 命中总数;带日期筛选时不再被单条脏行清零 | +| page | Integer | 当前页码 | +| pageSize | Integer | 每页条数 | +| records[].id | Long | 派车行/虚拟条目主键 | +| records[].orderId / orderNo / teamNo | Long / String / String | 子订单 ID、订单编号、团号 | +| records[].assignmentId / assignmentGroupId / requirementId | Long | 派车行 ID、派车分组 ID、当前用车需求 ID | +| records[].assignmentStatus | String | 派单状态码 | +| records[].virtualPending | Boolean | 虚拟待派卡标记(真实记录恒为 `false`) | +| records[].groupVehicleCovered | Boolean | 团车整段接管标记(详见 #8235 交接件) | +| records[].urgentBadge / canAssign / dispatchReadOnly | String / Boolean / Boolean | 加急标签、可派车、只读 | +| records[].startDate / endDate | LocalDate | 行程起止日期 | +| records[].currentVehiclePlate / currentDriverName | String | 当前车辆车牌 / 司机姓名 | + +#### 请求示例 + +```http +GET /admin/fleet/board/orders?startDate=2026-11-01&endDate=2026-11-10&variant=list&pageNo=1&pageSize=20 +``` + +#### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": { + "records": [ + { + "id": 7330843067599549, + "orderId": 2101014943313670001, + "orderNo": "HL20261106000001", + "teamNo": null, + "assignmentId": 7330843067599549, + "assignmentGroupId": 7330843067599549, + "requirementId": 2101014943313670100, + "assignmentStatus": "holding", + "virtualPending": false, + "groupVehicleCovered": null, + "urgentBadge": null, + "canAssign": true, + "dispatchReadOnly": false, + "startDate": "2026-11-06", + "endDate": "2026-11-07", + "currentVehiclePlate": null, + "currentDriverName": null + } + ], + "total": 1, + "page": 1, + "pageSize": 20 + }, + "success": true +} +``` + +#### 空数据 / 降级响应 + +无匹配记录时返回空数组与 `total=0`,不报错: + +```json +{ + "code": 200, + "message": "成功", + "data": { "records": [], "total": 0, "page": 1, "pageSize": 20 }, + "success": true +} +``` + +带日期筛选时的空列表**仍不等同于**「该日期窗确实无单」:日期候选扫描取数失败、结果集缺失、候选行结构畸形(行对象缺失 / 主单 ID 缺失 / 派车组 ID 与派车 ID 同时为空)或槽位键重复时,本页仍按既有 fail-closed 口径整体返回空,但每一种成因现在都会在 `hl-fleet-service` 日志里留下一条可区分的 WARN。不带日期筛选的查询不走这条分支。 + +#### 错误响应 + +```json +{ + "code": 401, + "message": "未登录或登录已过期", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 只影响**带日期筛选**的分支。不带日期的查询、车辆矩阵接口、看板汇总接口的口径与本次改动前完全一致。 +- `requirement_id` 为空的派车行会被剔除:该行原本在不带日期的路径里也匹配不上任何用车需求、不可能出现在看板上,因此剔除它不会让**本该展示**的卡片消失。 +- 若某订单在日期窗内**只有**这一条脏行,该订单在带日期的视图里看不到——这与它不带日期时的既有表现一致;让它可见需要的是数据修复,不是看板放行。 +- 日期候选结果集本身取到空(无订单上下文)时不查派车行,正常返回空页。 +- 鉴权:管理后台登录态,未登录 401(网关拦截)。 + +--- + +## 四、契约约束与正确调用方式 + +### ✅ 正确 / ❌ 错误用法对照 + +| 场景 | 说明 | +|------|------| +| ✅ 直接使用 `total` 与 `records` | 结构与字段均未变,前端无需做任何解析适配 | +| ✅ 把带日期筛选返回的空列表理解为「结构性异常或确实无单」 | 本次改动后,单条 `requirement_id` 为空的脏行不再制造这种空结果;剩余会制造空结果的是结构性畸形(行缺失、主单 ID 缺失、槽位键缺失或重复),均会在服务端留 WARN | +| ❌ 为「带日期筛选可能返回空」保留前端兜底或本地缓存回填 | 本次改动后不再是必需;保留也不会出错,但会把真实的结构性畸形空结果一并掩盖 | +| ❌ 依赖后端 WARN 的具体文案做前端逻辑 | WARN 只面向排障,文案不是契约 | + +### 切换状态时的必要动作 + +无。本接口是只读 GET,跳过脏行的判定完全由后端在读取时完成,不接受前端传参覆盖,也不需要前端在请求前做任何字段准备。 + +--- + +## 六、边界行为 + +- 未登录 → 401(网关拦截) +- 无匹配记录 → 200 + 空数组、`total=0`,不报错 +- 日期候选行含 `requirement_id` 为空的行 → 200,该行被跳过并记 WARN,其余订单照常返回(本次改动) +- 日期候选行结构畸形(行对象缺失 / 主单 ID 缺失 / 派车组 ID 与派车 ID 同时缺失)或槽位键重复 → 200 + 整页空(既有 fail-closed 口径保留),并新增带定位信息的 WARN +- order-v3 日期候选页取数失败、超过单次一致性快照上限或上下文畸形 → 200 + 整页空(既有 fail-closed 口径保留) +- 虚拟待派候选层不可用(开关关闭或远端候选不可用)→ 只丢虚拟条目,真实派车行照常返回 + +--- + +## 六.6、修改前后对比 + +### 字段级对比 + +| 字段 | 改前 | 改后 | 变化说明 | +|------|------|------|----------| +| 请求 / 响应字段 | 无变化 | 无变化 | 本次为纯行为修正,不新增、不删除、不改类型 | + +### 行为级对比 + +| 行为 | 改前 | 改后 | 影响 | +|------|------|------|------| +| 日期窗内某订单存在一条 `requirement_id` 为空的派车行 | **整窗**返回 `records=[]`、`total=0`、`code=200`,服务端无日志 | 只**跳过该行**并记 WARN,同窗其余订单正常返回 | 带日期筛选的列表不再被单条脏数据清空 | +| 同一数据**不带日期**查询 | 该行被跳过 + 一条汇总 WARN | 不变 | 无 | +| 日期候选出现重复槽位键 | 整页失败关闭,无日志 | 整页失败关闭(不变),新增带重复键样本的 WARN | 排障可定位 | +| 日期候选行结构畸形(行缺失 / 主单 ID 缺失 / 槽位键全缺) | 整页失败关闭,无日志 | 整页失败关闭(不变),新增带成因与定位字段的 WARN | 排障可定位 | + +--- + +## 六.7、影响评估 + +- **是否破坏向后兼容**: 否。请求参数、响应结构、字段类型与错误码全部不变,仅带日期筛选时的记录集合与 `total` 不再被单条脏数据清零。 +- **前端是否必须同步上线**: 否。前端无需修改即可受益。 +- **前端 workaround 清理点**: 若前端此前针对「带日期筛选偶发返回空」做过兜底或本地回填,可以在确认后移除;保留不影响功能。 + +--- + +## 七、不影响范围 + +- **仅影响**:管理后台「车务看板」订单列表/网格视图(`/admin/fleet/board/orders`)在**带日期筛选**时的记录集合与 `total`。 +- **零影响**: + - 不带日期筛选的看板订单列表口径 + - 车辆矩阵未派清单、网格与月度统计(`/admin/fleet/matrix/**`,不走日期候选扫描分支) + - 看板汇总与统计接口 + - 派车、改派、确认等写接口 + - 用车需求与派车行的数据结构、状态机与任何表结构 + +--- + +## 八、测试环境已验证 + +测试服部署(`deploy:test` 单写租约):`hl-fleet-service` 2026-09-24 10:49:54 滚动部署到 `dev-v3 @ cc70c9ba3`(该提交是本次 squash 合并 `48c755fd1` 的后代),实例 8187 / 8087 均 UP 且健康检查通过。 + +网关实测(`https://api.test.1814.love`,管理后台登录态切到车务角色): + +| # | 请求 | 修复前 `total` | 修复后 `total` | +|---|------|----------------|----------------| +| 1 | `GET /admin/fleet/board/orders`(不带日期) | 243 | 243(对照组,未变)✓ | +| 2 | `...&startDate=2026-11-01&endDate=2026-11-10`(窗内含脏行) | **0** | **8** ✓ | +| 3 | `...&startDayFrom=2026-11-01&startDayTo=2026-11-10`(同窗别名参数) | **0** | **8** ✓ | +| 4 | `...&startDate=2026-09-24&endDate=2026-11-04`(窗内不含脏行) | 71 | 71(对照组,未变)✓ | +| 5 | `...&startDate=2026-11-06&endDate=2026-11-06`(脏行当天) | **0** | **6** ✓ | +| 6 | `...&startDate=2026-11-05&endDate=2026-11-07` | **0** | **6** ✓ | + +服务端逐行 WARN(两个实例各两条,与上表实测同刻,原始行): + +```text +2026-09-24 10:50:56.063 [http-nio-8087-exec-1] WARN c.h.f.b.service.BoardCandidateSource - 车务看板列表日期候选剔除无用车需求ID的派单行(本行不参与候选): orderId=2101014943313670146 assignmentId=7330843067599548 assignmentGroupId=7330843067599548 +2026-09-24 10:50:56.556 [http-nio-8187-exec-2] WARN c.h.f.b.service.BoardCandidateSource - 车务看板列表日期候选剔除无用车需求ID的派单行(本行不参与候选): orderId=2101014943313670146 assignmentId=7330843067599548 assignmentGroupId=7330843067599548 +``` + +那条脏行(`assignment_id=7330843067599548`,`order_id=2101014943313670146`,行程日期 2026-11-06)本身不再出现在任何日期窗结果里——它匹配不上任何用车需求,本就无法在看板渲染;关键变化是它不再让同窗其余订单一起消失。 + +本地验证:定向 42/42 绿、看板与矩阵影响面回归 379/379 绿、`spotless:check` 与 `mvn -o -pl hl-fleet-service -am verify` 均 BUILD SUCCESS(该模块 4766 个用例 0 失败 0 错误 6 跳过)。 + +--- + +## 十、相关文档 + +- 关联 Issue: [wx/HL#8301](https://git.1814.love/wx/HL/issues/8301) +- 关联 PR: [wx/HL#8310](https://git.1814.love/wx/HL/pulls/8310) +- 同一接口的上一份交接件(#8235,看板订单记录新增 `groupVehicleCovered`),其中「带日期筛选的既有 fail-closed 口径」一条由本文件取代 + +## 关联 / 联系人 + +### 链接 + +- **Issue**: [#8301](https://git.1814.love/wx/HL/issues/8301) +- **PR**: [#8310](https://git.1814.love/wx/HL/pulls/8310) +- **Merge commit**: [48c755fd1](https://git.1814.love/wx/HL/commit/48c755fd1feff715f9ec946b55f77207f23dc942) + +### 联系人 + +- **后端负责人**: @wx +- **前端负责人**: @mmg