From 14d84237e7583f1149d06542812f563107a67fce Mon Sep 17 00:00:00 2001 From: API Changelog Bot Date: Wed, 30 Sep 2026 02:22:05 +0800 Subject: [PATCH] =?UTF-8?q?docs(changelog):=20=E6=B4=BE=E5=8D=95=E7=9C=8B?= =?UTF-8?q?=E6=9D=BF=E7=9F=A9=E9=98=B5=E5=B9=B4=E6=9C=88=E6=A0=A1=E9=AA=8C?= =?UTF-8?q?=E4=B8=8E=E5=9B=A2=E6=9C=9F=E9=85=8D=E8=BD=A6=E8=AF=A6=E6=83=85?= =?UTF-8?q?=E4=B8=89=E6=9D=A1=E4=BA=A4=E6=8E=A5=E4=BB=B6=EF=BC=88#8561=20#?= =?UTF-8?q?8571=20#8556=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - #8561 派单矩阵三入口补年份区间校验,越界返新错误码 605076 - #8571 未派订单清单月份越界改由 Service 判定,与 matrix 另两个入口同构返 605010 - #8556 派单看板订单详情识别团期配车,排车步与实派车数不再只认逐户派车行 Co-Authored-By: Claude Opus 5 (1M context) --- ...›¢期配车排车节点与实派车数变更-修改接口-管理后台.md | 262 +++++++++++++ ...¥口补年份区间校验新增605076-修改接口-管理后台.md | 350 ++++++++++++++++++ ...越界改由Service判与matrix同构-修改接口-管理后台.md | 236 ++++++++++++ 3 files changed, 848 insertions(+) create mode 100644 changelogs-v2/2026-09/30_8556_派单看板详情识别团期配车排车节点与实派车数变更-修改接口-管理后台.md create mode 100644 changelogs-v2/2026-09/30_8561_派单矩阵三入口补年份区间校验新增605076-修改接口-管理后台.md create mode 100644 changelogs-v2/2026-09/30_8571_未派订单清单月份越界改由Service判与matrix同构-修改接口-管理后台.md diff --git a/changelogs-v2/2026-09/30_8556_派单看板详情识别团期配车排车节点与实派车数变更-修改接口-管理后台.md b/changelogs-v2/2026-09/30_8556_派单看板详情识别团期配车排车节点与实派车数变更-修改接口-管理后台.md new file mode 100644 index 00000000..49e909c9 --- /dev/null +++ b/changelogs-v2/2026-09/30_8556_派单看板详情识别团期配车排车节点与实派车数变更-修改接口-管理后台.md @@ -0,0 +1,262 @@ +--- +schema: "hl-changelog/v2" +ticket: "8556" +title: "派单看板订单详情识别团期配车,排车节点与实派车辆数不再只认逐户派车行" +consumer: "admin" +author: "wx(GIT)" +change_type: "修改接口" +backend_status: "deployed" +gateway_status: "verified" +frontend_status: "pending" +frontend_owner: "" +frontend_ref: "" +target_release: "" +verified_at: "" +status_note: "PR #8583 合并 dev-v3(9c7ac93829);hl-fleet-service dev-v3 分支部署测试网关 @ 9c7ac9382 并实测:团期订单详情下发 groupBatchId/groupDispatchManaged/groupDispatchReady/groupDispatchPlan,排车节点由 WAITING 改为 SKIPPED,actualVehicleCount 由团期子订单实测的 0 变为与团期配车总览一致的实派车数;同一订单可同时存在团期配车与个人派车两组数据且互不覆盖。" +updated_at: "2026-09-30" +base: "dev-v3" +--- + +# hl-fleet-service: 派单看板订单详情识别团期配车,排车节点与实派车辆数不再只认逐户派车行 + +> **存放目录**: `changelogs-v2/2026-09/` +> **服务**: hl-fleet-service (端口 8087) +> **PR**: #8583 +> **Issue**: #8556 +> **日期**: 2026-09-30 +> **影响范围**: 管理后台派单看板订单详情端点 `GET /admin/fleet/board/orders/{orderId}` + +--- + +## ⚠️ 关键变化 + +- 🔴 **破坏性变更**:`actualVehicleCount` 字段的响应类型声明一直是 `Integer`(可空),但改动前的实现从未真正下发过 `null`——本次改动起,**团期子订单在团期配车事实暂不可用时会真实下发 `null`**(触发条件:`groupDispatchManaged=true` 且 `groupDispatchReady=false`)。前端若曾经把该字段当作恒为数字直接做算术或比较,现在必须先判空。 +- 新增 4 个字段:`groupBatchId`(当前归属运营团期 ID,非团期订单为 `null`)、`groupDispatchManaged`(用车是否由团期统一编排)、`groupDispatchReady`(团期配车事实是否已取到,`false` 含义是"未知"不是"没有车")、`groupDispatchPlan`(本单所在乘车分组的团级配车行只读列表)。 +- 团期子订单(`groupDispatchManaged=true`)且本地没有任何逐户派车行时,第 2 步"排车"(`code=DISPATCH`)的状态由 `WAITING` 改为 **`SKIPPED`**(`SKIPPED` 是该字段既有的合法取值,非新增枚举值);语义是"本步不由本单单独执行",不是"未排车"。 +- `actualVehicleCount` 的计算口径变化:团期子订单现在统计"本单逐户派车 ∪ 本单所在乘车分组的团级配车"去重后的车辆并集,不再只数逐户派车行。 +- 团期配车(团级统一编排)与逐户接送机派车可以**同时存在于同一张订单**,二者互不覆盖:`dailyVehiclePlan`(逐户派车)与 `groupDispatchPlan`(团级配车)各自独立返回,`currentAssignment` 仍然只指向逐户派车行。 +- 本次**只改了** `assignment == null`(本地无任何逐户派车行)这一分支的排车节点状态;订单若同时存在逐户派车行,排车节点继续如实反映那条真实派车行的状态,不受团期标记影响。 + +--- + +## 二、变更接口清单 + +| # | 接口 | 方法 | 路径 | 变更类型 | 说明 | +|---|------|------|------|----------|------| +| 1 | 派单看板订单详情 | GET | `/admin/fleet/board/orders/{orderId}` | 🔴 破坏性变更 + 字段新增 | 新增团期配车相关 4 字段,`actualVehicleCount` 可为 `null`,排车节点新增 `SKIPPED` 用法 | + +--- + +## 三、接口详情 + +### 1. 派单看板订单详情 `GET /admin/fleet/board/orders/{orderId}` + +**VO**: `(无请求体,仅路径参数)` → `BoardOrderDetailVO` + +#### 使用场景 + +车务打开派单弹窗 Step1 查看当前订单详情时调用。本次改动解决团期子订单在本端点与团期配车总览端点给出相反结论的问题:团期已排车的订单此前在本端点被画成"未排车 / 0 辆"。 + +#### 入参字段表 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| orderId | Path | Long | ✅ | - | 订单 ID | + +#### 出参字段表 + +以下是本次新增/变化的字段;其余既有字段(`dailyVehiclePlan`、`currentAssignment`、`progressSteps` 等)结构未变,此处不重复列出。 + +| 字段 | 类型 | 说明 | +|------|------|------| +| groupBatchId | Long→String,可空 | 当前归属运营团期 ID(非团期订单为 `null`);活体优先、order-v3 降级时回退派车行建行快照 | +| groupDispatchManaged | Boolean,可空 | 用车是否由团期统一编排;`true`=排车节点为 `SKIPPED`,车辆事实见 `groupDispatchPlan` | +| groupDispatchReady | Boolean,可空 | 团期配车事实是否已取到;`false`=未知(非团期基线不可达或该团尚无活跃用车需求),**不是**"没有车";非团期订单为 `null` | +| actualVehicleCount | Integer,🔴 可空 | 车务当前实派车辆数(团期子订单含团级配车去重并集);`null`=团期配车事实暂不可用,前端不得按 `0` 渲染 | +| groupDispatchPlan | `List` | 本单所在乘车分组的团级配车(只读展示,按服务日、配车行 ID 升序) | +| ├─ dispatchId | Long→String | 团级配车行 ID(排障定位用,不作为任何写口入参) | +| ├─ tripDate | LocalDate | 服务日 | +| ├─ groupCode | String | 本单当日所在乘车分组键(`order_group_vehicle_group.group_code`) | +| ├─ vehicleId | Long→String,可空 | 车辆 ID(团级配车允许未落车,此时为 `null`) | +| ├─ vehiclePlate | String | 车牌 | +| ├─ vehicleModel | String | 车型名 | +| ├─ driverId | Long→String,可空 | 司机 ID(团级配车允许未落司机,此时为 `null`) | +| ├─ driverName | String | 司机姓名 | +| ├─ driverPhone | String | 司机手机(已脱敏) | +| └─ status | String | 团级配车行状态(原样透出 `fleet_group_dispatch.status`,如 `ASSIGNED`/`CONFIRMED`) | + +#### 请求示例 + +```http +GET /admin/fleet/board/orders/2104840641597030402 +``` + +#### 响应示例 + +真实实测(团期订单 A,团号 26-3682,仅团期配车、无个人派车行)关键字段: + +```json +{"code":200,"data":{"id":"HL20260929154809598","teamNo":"26-3682","groupBatchId":"2104840641651556353","groupDispatchManaged":true,"groupDispatchReady":true,"actualVehicleCount":1},"success":true} +``` + +对照:非团期订单(团号 26-0013): + +```json +{"code":200,"data":{"id":"HL20260924152729671","teamNo":"26-0013","groupBatchId":null,"groupDispatchManaged":false,"groupDispatchReady":null},"success":true} +``` + +#### 空数据 / 降级响应 + +- 非团期订单:`groupBatchId`/`groupDispatchManaged`/`groupDispatchReady` 均为 `null`/`false`,`groupDispatchPlan` 为空列表,`actualVehicleCount` 按逐户派车行正常计数(不受本次改动影响,不会是 `null`)。 +- 团期订单但团期配车事实取不到(`groupDispatchReady=false`,如 order-v3 团期基线不可达、或该团尚无活跃正式用车需求):`groupDispatchPlan=[]`,`actualVehicleCount=null`——前端应渲染为"团期配车信息暂不可用"这一类提示,不得退化显示为"未排车 / 0 辆"。 +- 团期分组已铺开但本单不在任何乘车分组(整团免车 / 本单自理):`groupDispatchReady=true` 且 `groupDispatchPlan=[]`,这是已验证的业务结论(本单不占团期用车),与上一条"未知"态不同,不要混为一谈。 + +#### 错误响应 + +本端点既有错误码未变: + +```json +{"code":605311,"message":"当前需求存在多个不透明派车方案代际","data":null,"success":false} +``` + +#### 业务边界 + +- 🔴 `actualVehicleCount` 从本次起可以真实为 `null`:判定条件是 `groupDispatchManaged=true && groupDispatchReady=false`。非团期订单、以及团期配车已就绪的订单,该字段仍是非空整数。 +- 排车节点 `SKIPPED` 只出现在"本地无任何逐户派车行 + 团期统一编排"这一种情况;订单若同时有逐户派车行,排车节点继续如实反映那条派车行的真实状态(`WAITING`/`PROCESSING`/`DONE`/`CANCELED`),团期标记不覆盖它。 +- `groupDispatchReady=false` 的含义是"未知",不是"没有车";只有 `groupDispatchReady=true` 且 `groupDispatchPlan=[]` 才是"本单确实不占团期用车"这个已验证的业务结论。 +- `groupDispatchPlan` 是只读展示,团期用车的修改入口在团期配车总览页,不在本端点。 + +--- + +## 四、契约约束与正确调用方式 + +> 本节只写后端接受/拒绝 payload 的规则,不写 UI 渲染建议。 + +### ✅ 正确 / ❌ 错误 payload 对照 + +| 场景 | payload / 响应 | +|------|-----------------| +| ✅ 渲染 `actualVehicleCount` 前先判空 | `null` 时渲染为"暂不可用",非 `null` 时按数字展示 | +| ✅ 判断"本单是否不占团期用车" | 必须同时看 `groupDispatchReady===true && groupDispatchPlan.length===0`,不能只看 `groupDispatchPlan` 是否为空数组 | +| ❌ 继续把 `actualVehicleCount` 当作恒不为空的数字直接参与计算 | 团期未就绪场景会拿到 `null`,直接参与算术会产生运行时异常 | +| ❌ 把排车节点 `SKIPPED` 当作未知枚举值兜底处理 | `SKIPPED` 是 `AssignmentProgressStatusEnum` 既有取值,前端 `allowableValues` 已包含,无需新增分支兜底逻辑,但需要有对应的展示文案 | + +### 切换状态时的必要动作 + +前端渲染 `actualVehicleCount` 与排车进度节点前,必须先读 `groupDispatchManaged`/`groupDispatchReady` 两个标记决定展示分支;直接复用非团期订单的展示逻辑会在团期订单上产生误导性的"0 辆 / 未排车"提示。 + +--- + +## 五、数据库行为 + +本端点为只读查询,无数据库写操作。新增的团期配车事实来自跨服务只读查询:`groupDispatchManaged=true` 时才会额外发起一次到 order-v3 的 Feign 调用取团期基线,非团期订单不受影响、不多打这次调用。查询失败或该团无活跃需求时返回"未知"态(`groupDispatchReady=false`),不抛异常、不影响本端点其余字段的正常返回。 + +--- + +## 六、边界行为 + +- 非团期订单 → `groupBatchId`/`groupDispatchReady` 为 `null`,`groupDispatchManaged=false`,`groupDispatchPlan=[]`,`actualVehicleCount` 按逐户派车行正常计数 +- 团期订单、团期配车基线不可达或该团无活跃需求 → `groupDispatchReady=false`,`groupDispatchPlan=[]`,`actualVehicleCount=null` +- 团期订单、团期分组已铺开但本单不在任何分组 → `groupDispatchReady=true`,`groupDispatchPlan=[]`,`actualVehicleCount` 按逐户派车行计数(可能为 0,这是已验证结论不是未知态) +- 团期订单、团期配车已就绪且本单在某分组 → `groupDispatchReady=true`,`groupDispatchPlan` 非空,`actualVehicleCount` 为逐户 ∪ 团级去重后的并集大小 +- 本地无逐户派车行 + 团期统一编排 → 排车节点 `SKIPPED` +- 本地有逐户派车行(不论是否团期订单)→ 排车节点如实反映该派车行状态,不受团期标记影响 +- 存量 `group_id` 为 `NULL` 的团级配车行(`V20260916_002` 迁移前落库、明确不回填)不进入本单的 `groupDispatchPlan`,但不报错、不影响其它行 + +--- + +## 六.5、枚举 / 数据字典 + +### 排车进度节点状态(`AssignmentProgressStatusEnum`,`progressSteps[].status`,`code=DISPATCH` 这一步) + +**所属字段**: `progressSteps[].status`(当 `progressSteps[].code=DISPATCH`) | **类型**: `String` + +| 值 | 中文 | 本次是否新增 | 说明 | +|----|------|------|------| +| `WAITING` | 等待中 | 既有值 | 非团期订单本地无派车行时的状态,本次未变 | +| `PROCESSING` | 进行中 | 既有值 | 本次未变 | +| `DONE` | 已完成 | 既有值 | 本次未变 | +| `CANCELED` | 已取消 | 既有值 | 本次未变 | +| `SKIPPED` | 已跳过 | 本次起用于排车节点 | 团期统一编排且本地无逐户派车行时的新用法;该取值本身已在 VO `allowableValues` 中存在(此前用于其它步骤),本次是新增了"排车"这一步会用到它 | + +## 六.6、修改前后对比 + +### 字段级对比 + +| 字段 | 改前 | 改后 | +|------|------|------| +| `groupBatchId` | 不存在 | 新增,`Long→String`,可空 | +| `groupDispatchManaged` | 不存在 | 新增,`Boolean`,可空 | +| `groupDispatchReady` | 不存在 | 新增,`Boolean`,可空 | +| `groupDispatchPlan` | 不存在 | 新增,`List`(10 个子字段,见出参字段表) | +| `actualVehicleCount` | 字段声明类型一直是 `Integer`,但实现从未真正下发过 `null`(内部局部变量此前是不可空计算) | 团期子订单在配车事实未就绪时,Service 层真实计算出 `null` 并下发 | + +### 行为级对比 + +| 场景 | 改前 | 改后 | +|------|------|------| +| 团期子订单、本地无逐户派车行 | 排车节点 `WAITING`,`actualVehicleCount=0` | 排车节点 `SKIPPED`,`actualVehicleCount` 取团期配车去重实派车数(就绪时)或 `null`(未就绪时) | +| 团期子订单、同时有逐户派车行 | 排车节点按该派车行真实状态 | 不变,仍按该派车行真实状态 | +| `actualVehicleCount` 统计口径(团期子订单) | 只数本单逐户派车行 | 本单逐户派车 ∪ 本单所在乘车分组的团级配车,去重后的并集 | +| 非团期订单 | 无本次描述的任何字段/行为 | 无变化(新增字段均为 `null`/`false`,`actualVehicleCount` 计算口径不变) | + +## 六.7、影响评估 + +- **是否破坏向后兼容**: 是——`actualVehicleCount` 的字面类型虽然一直是 `Integer`,但运行时从未观测到过 `null`;前端若曾经把它当作恒为数字的字段直接做算术/比较,现在会在团期未就绪场景下遇到真实的 `null`。 +- **前端是否必须同步上线**: 是(仅对涉及团期订单展示的场景)——非团期订单的响应字段与行为完全不变,可以不改;但只要页面会展示团期订单,就必须先对 `actualVehicleCount` 判空,并依据 `groupDispatchManaged`/`groupDispatchReady` 决定排车节点与实派车数的展示分支。 +- **前端 workaround 清理点**: 若此前为"团期订单详情显示未排车/0 辆,但团期配车总览显示已排车"这类矛盾现象写过特殊兼容或屏蔽逻辑,现在两端点结论已一致,可以确认不再需要。 + +--- + +## 七、不影响范围 + +- **仅影响**: 派单看板订单详情端点 `GET /admin/fleet/board/orders/{orderId}` 的响应字段与团期子订单的排车节点/实派车数展示逻辑。 +- **零影响**: + - 派单看板列表端点 `GET /admin/fleet/board/orders`(`BoardOrderRecordVO`)未受本次改动波及 + - 非团期订单的响应字段与行为 + - 接送机步骤(`PICKUP_DROPOFF`)与确认执行步骤(`CONFIRM_EXECUTE`)的判定逻辑 + - `dailyVehiclePlan`(逐户派车方案)的既有字段结构与计算口径 + - 团期配车总览/就绪判定等团期配车域自身的写口与其余读口 + +--- + +## 八、测试环境已验证 + +服务:`hl-fleet-service`,dev-v3 分支部署测试网关 @ `9c7ac9382`(含 #8556 所在提交),测试网关 `https://api.test.1814.love`;样本均为测试服现存真实业务数据: + +``` +✓ 团期订单 A(orderId=2104840641597030402,团号 26-3682,团期批次 2104840641651556353,仅团期配车无个人派车): + groupBatchId="2104840641651556353" groupDispatchManaged=true groupDispatchReady=true + progressSteps[DISPATCH].status=SKIPPED statusLabel=已跳过 active=false + actualVehicleCount=1;groupDispatchPlan 共 7 条(2026-11-11~2026-11-17) + 与同批次团期配车总览 GET /admin/fleet/group-dispatch/batches/2104840641651556353/overview 对照: + vehicleReady=true,7 天 dispatched=true,结论一致(改前两端点结论相反) +✓ 非团期订单 C(orderId=2103023501973848066,团号 26-0013): + groupBatchId=null groupDispatchManaged=false groupDispatchReady=null +✓ 团期订单 B(orderId=2104839654652121090,同时有团期配车与个人派车): + groupDispatchManaged=true groupDispatchReady=true actualVehicleCount=2 + dailyVehiclePlan:1 条,车辆蒙C10E10/司机铁木尔(个人派车) + groupDispatchPlan:多条,首条车辆蒙A-K1999/司机巴特尔(团期配车) + 两组数据同时非空、互不顶替;currentAssignment 仍指向个人派车行(蒙C10E10/铁木尔) +``` + +注:`actualVehicleCount=null` 这一具体取值未在本轮实测中被真实触发(测试服 order-v3 全程可达,两个团期样本 `groupDispatchReady` 均为 `true`);该分支的契约(字段类型可空、触发条件 `groupDispatchManaged=true && groupDispatchReady=false`)已在源码逐一核实(`BoardOrderService.java`、`BoardOrderDetailVO.java`),前端应按此契约做防御性判空,不依赖本轮是否观测到该取值。 + +--- + +## 十、相关文档 + +- 关联 Issue: [wx/HL#8556](https://git.1814.love/wx/HL/issues/8556) +- 关联 PR: [wx/HL#8583](https://git.1814.love/wx/HL/pulls/8583) + +## 关联 / 联系人 + +### 链接 + +- **Issue**: [#8556](https://git.1814.love/wx/HL/issues/8556) +- **PR**: [#8583](https://git.1814.love/wx/HL/pulls/8583) +- **Merge commit**: [9c7ac93829](https://git.1814.love/wx/HL/commit/9c7ac93829) + +### 联系人 + +- **后端负责人**: @wx diff --git a/changelogs-v2/2026-09/30_8561_派单矩阵三入口补年份区间校验新增605076-修改接口-管理后台.md b/changelogs-v2/2026-09/30_8561_派单矩阵三入口补年份区间校验新增605076-修改接口-管理后台.md new file mode 100644 index 00000000..1f1d6f5c --- /dev/null +++ b/changelogs-v2/2026-09/30_8561_派单矩阵三入口补年份区间校验新增605076-修改接口-管理后台.md @@ -0,0 +1,350 @@ +--- +schema: "hl-changelog/v2" +ticket: "8561" +title: "派单矩阵三个入口补年份区间校验,新增错误码 605076" +consumer: "admin" +author: "wx(GIT)" +change_type: "修改接口" +backend_status: "deployed" +gateway_status: "verified" +frontend_status: "pending" +frontend_owner: "" +frontend_ref: "" +target_release: "" +verified_at: "" +status_note: "PR #8565 合并 dev-v3(ad3c6e4305);hl-fleet-service dev-v3 分支部署测试网关 @ 9c7ac9382 并实测:grid/month-counts/unassigned-orders 三入口越界年份(1800/9999/1990)均返回 605076,区间内年份(含 2020/2100 两端边界,已在 grid 入口实测)行为不变。" +updated_at: "2026-09-30" +base: "dev-v3" +--- + +# hl-fleet-service: 派单矩阵三个入口补年份区间校验,新增错误码 605076 + +> **存放目录**: `changelogs-v2/2026-09/` +> **服务**: hl-fleet-service (端口 8087) +> **PR**: #8565 +> **Issue**: #8561 +> **日期**: 2026-09-30 +> **影响范围**: 管理后台派单矩阵三个查询入口(grid / month-counts / unassigned-orders)的年份校验 + +--- + +## ⚠️ 关键变化 + +- 派单矩阵三个查询入口(`grid`/`month-counts`/`unassigned-orders`)此前只校月份是否在 1-12,**不校年份**——`year=1800`、`year=9999` 这类明显异常值会被当成合法年份继续查询。现在统一在 Service 层加了年份区间校验 `[2020, 2100]`,越界抛**新增错误码 605076**。 +- 605076 的错误文案是 `年份超出范围(仅支持 2020-2100 年)`(`AssignmentErrorCode.MATRIX_YEAR_OUT_OF_RANGE`,文案里的年份区间已按当前常量渲染为 2020/2100)。 +- 校验顺序是**先年后月**:`year` 越界时直接抛 605076,不会先看 `month`。 +- 区间内年份(含边界 2020、2100)行为完全不变,仍按原逻辑正常查询并返回 200。 +- 三入口的 `year` 字段本身仍是**必填**(`@NotNull`),缺失依旧是既有的参数校验码 `100001`,本次未改动这一路径。 + +--- + +## 二、变更接口清单 + +| # | 接口 | 方法 | 路径 | 变更类型 | 说明 | +|---|------|------|------|----------|------| +| 1 | 矩阵主数据 | GET | `/admin/fleet/matrix/grid` | 校验补充 | 新增年份区间校验,越界返 605076 | +| 2 | 矩阵年度月度统计 | GET | `/admin/fleet/matrix/month-counts` | 校验补充 | 新增年份区间校验,越界返 605076 | +| 3 | 矩阵未派订单清单 | GET | `/admin/fleet/matrix/unassigned-orders` | 校验补充 | 新增年份区间校验,越界返 605076 | + +--- + +## 三、接口详情 + +### 1. 矩阵主数据 `GET /admin/fleet/matrix/grid` + +**VO**: `MatrixGridReqVO` → `MatrixGridRespVO` + +#### 使用场景 + +车务打开派单矩阵页查看某年某月逐日车辆占用/待派情况时调用。本次改动只影响 `year` 越界场景的响应,区间内查询字段结构与既有行为未变。 + +#### 入参字段表 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| year | Query | Integer | ✅ | 🔴 新增:2020-2100(越界返 605076) | 年份 | +| month | Query | Integer | ✅ | 1-12(越界返 605010) | 月份 | +| season | Query | String | - | active/pending/archived/blacklist | 司机赛季筛选,默认 active | +| fleetTeamIds | Query | Long[] | - | - | 车队 ID 多选,空=全部 | +| fleets | Query | String[] | - | 已废弃,仅客户端迁移兼容 | 旧版车队稳定编码多选 | +| typeKeys | Query | String[] | - | 规范小写,空=全部 | 车型大类多选 | +| status | Query | String | - | all/unassigned/assigned | 兼容矩阵筛选 | +| statuses | Query | String[] | - | 非空时优先于 status | 有效状态精确筛选 | + +#### 出参字段表 + +响应结构本次未改动,以下仅列出与本次校验相关、已实测确认的顶层字段: + +| 字段 | 类型 | 说明 | +|------|------|------| +| year | Integer | 年份(回显) | +| month | Integer | 月份(回显) | +| daysInMonth | Integer | 该月天数 | +| vehicles | List | 车辆逐日占用数据 | + +#### 请求示例 + +```http +GET /admin/fleet/matrix/grid?year=2020&month=6&season=active +``` + +#### 响应示例 + +区间下边界(year=2020)实测: + +```json +{"code":200,"message":"成功","data":{"year":2020,"month":6,"daysInMonth":30},"traceId":null,"success":true} +``` + +区间上边界(year=2100)实测: + +```json +{"code":200,"message":"成功","data":{"year":2100,"month":6},"traceId":null,"success":true} +``` + +#### 空数据 / 降级响应 + +区间内查询若当月无任何车辆/派车数据,`vehicles` 为空数组,属正常业务结果,不是错误;本次改动不影响此形态。 + +#### 错误响应 + +```json +{"code":605076,"message":"年份超出范围(仅支持 2020-2100 年)","data":null,"traceId":null,"success":false} +``` + +(实测 `year=1800` 与 `year=9999` 均返回上述响应体,仅请求参数不同。) + +#### 业务边界 + +- `year` 越界(不在 [2020, 2100])→ 605076,`month` 是否越界不影响判定结果(先年后月)。 +- `year` 合法、`month` 越界(如 13)→ 仍按既有 605010 路径处理,本次未改动。 +- `year`/`month` 缺失仍是既有的 100001(参数非法),未受本次改动影响。 + +### 2. 矩阵年度月度统计 `GET /admin/fleet/matrix/month-counts` + +**VO**: `MatrixMonthCountsReqVO` → `MatrixMonthCountsRespVO` + +#### 使用场景 + +车务查看某年 12 个月各状态计数概览时调用(矩阵页顶部年度视图)。本次改动只影响 `year` 越界场景。 + +#### 入参字段表 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| year | Query | Integer | ✅ | 🔴 新增:2020-2100(越界返 605076) | 年份 | +| season | Query | String | - | active/pending/archived/blacklist | 司机赛季筛选,默认 active | +| fleetTeamIds | Query | Long[] | - | - | 车队 ID 多选,空=全部 | +| typeKeys | Query | String[] | - | 规范小写,空=全部 | 车型大类多选 | + +注:本端点没有 `month` 入参,年份越界统一走 605076,不会把调用方指去改一个不存在的字段。 + +#### 出参字段表 + +| 字段 | 类型 | 说明 | +|------|------|------| +| year | Integer | 年份(回显) | +| months | List | 12 个月各状态计数 | + +#### 请求示例 + +```http +GET /admin/fleet/matrix/month-counts?year=2026&season=active +``` + +#### 响应示例 + +```json +{"code":200,"message":"成功","data":{"year":2026},"traceId":null,"success":true} +``` + +(实测该年 12 个月 `statusCounts` 均为 0,字段结构本次未改动,示例只截取顶层字段。) + +#### 空数据 / 降级响应 + +区间内年份若全年无任何数据,`months` 中每个月的计数均为 0,属正常业务结果;本次改动不影响此形态。 + +#### 错误响应 + +```json +{"code":605076,"message":"年份超出范围(仅支持 2020-2100 年)","data":null,"traceId":null,"success":false} +``` + +(实测 `year=1800` 返回上述响应体。) + +#### 业务边界 + +- `year` 越界(不在 [2020, 2100])→ 605076。 +- `year` 缺失仍是既有的 100001(参数非法),未受本次改动影响。 + +### 3. 矩阵未派订单清单 `GET /admin/fleet/matrix/unassigned-orders` + +**VO**: `MatrixUnassignedReqVO` → `List` + +#### 使用场景 + +车务查看某年某月未派车订单清单(含虚拟待派条目)时调用。本次改动只影响 `year` 越界场景;`month` 越界的同构收敛见工单 #8571 的 changelog。 + +#### 入参字段表 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| year | Query | Integer | ✅ | 🔴 新增:2020-2100(越界返 605076),本次前摘掉了原 `@Min(1970)/@Max(9999)` | 年份 | +| month | Query | Integer | ✅ | 1-12(越界返 605010,见 #8571) | 月份 | +| typeKeys | Query | String[] | - | 规范小写,空=全部 | 车型大类多选 | + +#### 出参字段表 + +响应结构本次未改动。 + +| 字段 | 类型 | 说明 | +|------|------|------| +| virtualPending | Boolean | 是否虚拟待派条目(库里无对应行,由 order-v3 当前需求投射) | +| headcountLabel | String | 人数展示文案 | + +#### 请求示例 + +```http +GET /admin/fleet/matrix/unassigned-orders?year=1990&month=6&season=active +``` + +#### 响应示例 + +```json +{"code":200,"message":"成功","data":[],"traceId":null,"success":true} +``` + +(对照:`year=2026&month=6`(区间内)实测返回上述形态,`data` 为空数组属正常业务结果,与越界错误可区分。) + +#### 空数据 / 降级响应 + +区间内年份若当月无未派订单,`data` 为空数组,属正常业务结果,与越界返回的错误响应(`success:false`)可明确区分。 + +#### 错误响应 + +```json +{"code":605076,"message":"年份超出范围(仅支持 2020-2100 年)","data":null,"traceId":null,"success":false} +``` + +(实测 `year=1990` 返回上述响应体;本次改动前该场景返回的是框架码 100001,见"六.6、修改前后对比"。) + +#### 业务边界 + +- 🔴 **契约收窄**:本端点 `year` 原有的校验区间是 `[1970, 9999]`(`@Min/@Max` 注解),本次收窄为 `[2020, 2100]` 且改走业务码 605076。`year=1990` 这类此前能通过框架校验、现在会被拒绝的取值,前端如果曾经允许用户选择这类年份,需要同步收紧可选范围。 +- `year` 越界 → 605076;`month` 越界 → 605010(#8571),二者不互相覆盖,先年后月。 +- `year`/`month` 缺失仍是既有的 100001(`@NotNull` 保留,未随本次摘除区间注解一并摘掉)。 + +--- + +## 四、契约约束与正确调用方式 + +> 本节只写后端接受/拒绝 payload 的规则,不写 UI 渲染建议。 + +### ✅ 正确 / ❌ 错误 payload 对照 + +| 场景 | payload / 响应 | +|------|-----------------| +| ✅ `year` 在 [2020, 2100] 区间内(含边界) | 三入口均正常返回 `code=200` | +| ❌ `year` 不在 [2020, 2100] 区间(如 1800/1990/9999) | 三入口均返回 `code=605076` | +| ❌ 继续沿用 `unassigned-orders` 此前 `[1970, 9999]` 的可选年份范围 | `year=1990` 等取值现在会被 605076 拒绝,不再是 100001 | +| ❌ 把 605076 当作可重试错误自动重试 | 605076 是入参永久性非法,重试同一 `year` 不会成功,需要用户重新选择年份 | + +### 切换状态时的必要动作 + +前端拦到 `code=605076` 时应提示"年份超出范围,仅支持 2020-2100 年"类文案,并将年份选择控件的可选范围收紧到该区间,不要自动重试。 + +--- + +## 五、数据库行为 + +本次涉及的三个接口均为只读查询,无任何数据库写操作。改动只在 Service 层新增一段入参校验逻辑,不涉及任何表结构或存量数据变化。 + +--- + +## 六、边界行为 + +- `year` 不在 [2020, 2100] → 605076(三入口统一,本次新增) +- `year` 缺失 → 100001(既有行为,未改动) +- `year` 合法、`month` 越界 → 605010(grid 既有行为;unassigned-orders 同构收敛见 #8571) +- `year`/`month` 均合法 → 按既有逻辑正常查询,字段结构未变 + +--- + +## 六.5、枚举 / 数据字典 + +### 矩阵年份越界错误码(`AssignmentErrorCode.MATRIX_YEAR_OUT_OF_RANGE`) + +**所属字段**: 无(HTTP 响应顶层 `code`) | **类型**: `Integer` + +| 值 | 中文 | 说明 | +|----|------|------| +| `605076` | 年份超出范围(仅支持 2020-2100 年) | 🔴 本次新增;三个矩阵查询入口的 `year` 不在 [2020, 2100] 时统一返回;入参永久性非法,不应自动重试 | + +## 六.6、修改前后对比 + +### 字段级对比 + +本次无请求/响应字段新增或删除;`unassigned-orders` 的 `year` 字段摘掉了 `@Min(1970)/@Max(9999)` 注解(见入参字段表标注),字段本身仍是必填 `Integer`。 + +### 行为级对比 + +| 场景 | 改前 | 改后 | +|------|------|------| +| grid / month-counts,`year` 越界(不在 [2020,2100],如 1800/9999) | 未校验,当作合法年份继续查询 | 返回 `code=605076`(新增拦截) | +| unassigned-orders,`year` 不在 [2020, 2100](含此前 `@Min(1970)/@Max(9999)` 认为合法的 [1970,2019]∪[2101,9999] 区间) | 该子区间内视为合法继续查询,落在 [1970,9999] 之外才返回框架码 100001 | 统一返回业务码 605076,不再区分是否曾落在 [1970,9999] 内 | +| 三入口,`year` 在 [2020, 2100] | 正常返回 200 | 不变,仍正常返回 200 | + +## 六.7、影响评估 + +- **是否破坏向后兼容**: 是(仅 `unassigned-orders`)——`year` 的可接受范围从 `[1970, 9999]` 收窄到 `[2020, 2100]`,且越界时的错误码从 100001 变为 605076;`grid`/`month-counts` 此前对越界年份没有任何拦截,本次是新增拦截而非收窄既有契约。 +- **前端是否必须同步上线**: 是——年份选择控件若允许超出 `[2020, 2100]` 的取值,现在会收到新的 605076 错误码,前端需要新增该码的处理分支(提示文案 + 阻断当前查询),并建议同步收紧可选年份范围以减少用户触发该错误的机会。 +- **前端 workaround 清理点**: 若此前为"年份异常导致矩阵页面空白/报错"写过特殊兼容逻辑,可以确认不再需要,因为现在有明确的 605076 信号可用。 + +--- + +## 七、不影响范围 + +- **仅影响**: 派单矩阵三个查询入口(`grid`/`month-counts`/`unassigned-orders`)在 `year` 入参越界时的响应。 +- **零影响**: + - 三入口在 `year` 合法时的成功路径字段结构 + - `month` 越界的既有校验 605010(`unassigned-orders` 的同构收敛见 #8571 单独的 changelog) + - `season`/`fleetTeamIds`/`typeKeys`/`status`/`statuses` 等其余入参的校验逻辑 + - `day-orders` 等矩阵模块下其余未涉及本次改动的端点 + +--- + +## 八、测试环境已验证 + +服务:`hl-fleet-service`,dev-v3 分支部署测试网关 @ `9c7ac9382`(含 #8561 所在提交),测试网关 `https://api.test.1814.love`: + +``` +✓ GET grid?year=1800&month=6 → code=605076, message="年份超出范围(仅支持 2020-2100 年)" +✓ GET grid?year=9999&month=6 → code=605076 +✓ GET month-counts?year=1800 → code=605076 +✓ GET unassigned-orders?year=1990&month=6 → code=605076(此前为 100001,见六.6) +✓ GET grid?year=2020&month=6(下边界)→ code=200,正常返回 +✓ GET grid?year=2100&month=6(上边界)→ code=200,正常返回 +✓ GET month-counts?year=2026(区间中段)→ code=200,正常返回 +✓ GET unassigned-orders?year=2026&month=6(区间中段)→ code=200, data=[] +``` + +注:2020/2100 两端边界值仅在 `grid` 入口做了直接边界实测;`month-counts`/`unassigned-orders` 在区间中段(year=2026)验证了正常放行。三入口共用同一段 `requireValidYearMonth` 校验逻辑(`MatrixService.java`),边界判定不因入口而异,越界拦截已在三入口分别实测(见上)。 + +--- + +## 十、相关文档 + +- 关联 Issue: [wx/HL#8561](https://git.1814.love/wx/HL/issues/8561) +- 关联 PR: [wx/HL#8565](https://git.1814.love/wx/HL/pulls/8565) + +## 关联 / 联系人 + +### 链接 + +- **Issue**: [#8561](https://git.1814.love/wx/HL/issues/8561) +- **PR**: [#8565](https://git.1814.love/wx/HL/pulls/8565) +- **Merge commit**: [ad3c6e4305](https://git.1814.love/wx/HL/commit/ad3c6e4305) + +### 联系人 + +- **后端负责人**: @wx diff --git a/changelogs-v2/2026-09/30_8571_未派订单清单月份越界改由Service判与matrix同构-修改接口-管理后台.md b/changelogs-v2/2026-09/30_8571_未派订单清单月份越界改由Service判与matrix同构-修改接口-管理后台.md new file mode 100644 index 00000000..2f78779e --- /dev/null +++ b/changelogs-v2/2026-09/30_8571_未派订单清单月份越界改由Service判与matrix同构-修改接口-管理后台.md @@ -0,0 +1,236 @@ +--- +schema: "hl-changelog/v2" +ticket: "8571" +title: "矩阵未派订单清单月份越界改由 Service 判,与另两个入口同构" +consumer: "admin" +author: "wx(GIT)" +change_type: "修改接口" +backend_status: "deployed" +gateway_status: "verified" +frontend_status: "pending" +frontend_owner: "" +frontend_ref: "" +target_release: "" +verified_at: "" +status_note: "PR #8582 合并 dev-v3(6634d0588d);hl-fleet-service dev-v3 分支部署测试网关 @ 9c7ac9382 并实测:unassigned-orders 月份越界(如 13、0)统一返回 605010,月份缺失仍返 100001,grid 入口的既有 605010 行为未回归。" +updated_at: "2026-09-30" +base: "dev-v3" +--- + +# hl-fleet-service: 矩阵未派订单清单月份越界改由 Service 判,与另两个入口同构 + +> **存放目录**: `changelogs-v2/2026-09/` +> **服务**: hl-fleet-service (端口 8087) +> **PR**: #8582 +> **Issue**: #8571 +> **日期**: 2026-09-30 +> **影响范围**: 管理后台派单矩阵未派订单清单端点 `unassigned-orders` 的月份越界校验 + +--- + +## ⚠️ 关键变化 + +- `unassigned-orders` 的 `month` 越界校验此前是框架层 `@Min(1)/@Max(12)` 注解,越界返回**框架码 100001**;`grid` 端点的 `month` 越界则一直是 Service 层 `requireValidYearMonth` 判定,返回**业务码 605010**。同一类"月份填错了",两个端点走两套码、两套错误文案,前端得按端点分别写处理分支。 +- 本次摘掉 `unassigned-orders` 的 `@Min/@Max` 注解,越界统一改由 Service 层 `requireValidYearMonth` 判定,**现在与 `grid` 完全同构:越界一律返回 605010**(`月份超出范围`)。 +- 🔴 **`@NotNull` 被保留**:`month` 字段缺失(不传该参数)仍然返回既有的 100001(`参数非法: 月份不能为空`),这条路径没有变化——只有"传了值但越界"这一种场景的错误码变了。 +- `year` 字段的年份越界校验(605076)是另一张工单 #8561 引入的独立改动,与本次 `month` 校验改动在同一个 `requireValidYearMonth` 方法里但各自独立生效,请分别查阅两份 changelog。 + +--- + +## 二、变更接口清单 + +| # | 接口 | 方法 | 路径 | 变更类型 | 说明 | +|---|------|------|------|----------|------| +| 1 | 矩阵未派订单清单 | GET | `/admin/fleet/matrix/unassigned-orders` | 校验口径收敛 | `month` 越界改由 Service 判,与 grid 统一返回 605010 | + +--- + +## 三、接口详情 + +### 1. 矩阵未派订单清单 `GET /admin/fleet/matrix/unassigned-orders` + +**VO**: `MatrixUnassignedReqVO` → `List` + +#### 使用场景 + +车务查看某年某月未派车订单清单(含虚拟待派条目)时调用。本次改动只影响 `month` 越界场景的错误码;`year` 越界的新增校验(605076)见工单 #8561 的 changelog。 + +#### 入参字段表 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| year | Query | Integer | ✅ | 2020-2100(越界返 605076,见 #8561) | 年份 | +| month | Query | Integer | ✅ | 🔴 1-12,越界改为返 605010(此前是框架码 100001),本次摘掉了原 `@Min(1)/@Max(12)` | 月份 | +| typeKeys | Query | String[] | - | 规范小写,空=全部 | 车型大类多选 | + +#### 出参字段表 + +响应结构本次未改动。 + +| 字段 | 类型 | 说明 | +|------|------|------| +| virtualPending | Boolean | 是否虚拟待派条目 | +| headcountLabel | String | 人数展示文案 | + +#### 请求示例 + +```http +GET /admin/fleet/matrix/unassigned-orders?year=2026&month=13&season=active +``` + +#### 响应示例 + +区间边界内实测(`month=1`): + +```json +{"code":200,"message":"成功","data":[],"traceId":null,"success":true} +``` + +区间边界内实测(`month=12`): + +```json +{"code":200,"message":"成功","data":[],"traceId":null,"success":true} +``` + +#### 空数据 / 降级响应 + +`month` 合法时若当月无未派订单,`data` 为空数组,属正常业务结果,与越界返回的错误响应(`success:false`)可明确区分。 + +#### 错误响应 + +`month=13`(越界)实测: + +```json +{"code":605010,"message":"月份超出范围","data":null,"traceId":null,"success":false} +``` + +`month=0`(越界)实测: + +```json +{"code":605010,"message":"月份超出范围","data":null,"traceId":null,"success":false} +``` + +`month` 缺失(未传该参数)实测,**未受本次改动影响**: + +```json +{"code":100001,"message":"参数非法: 月份不能为空","data":null,"traceId":null,"success":false} +``` + +#### 业务边界 + +- 🔴 `month` 越界(不在 1-12,如 0、13)从此前的框架码 100001 改为业务码 605010,与 `grid` 端点完全同构;前端若曾经按 100001 识别"月份越界"这一具体场景,需要改成识别 605010。 +- `month` 缺失(不传参数)仍是 100001,`@NotNull` 判定发生在 `requireValidYearMonth` 之前,未被本次改动波及,无需新增分支。 +- `year` 越界返回 605076(#8561 引入),与本次 `month` 越界的 605010 是两个独立判定,`requireValidYearMonth` 先判年后判月。 + +--- + +## 四、契约约束与正确调用方式 + +> 本节只写后端接受/拒绝 payload 的规则,不写 UI 渲染建议。 + +### ✅ 正确 / ❌ 错误 payload 对照 + +| 场景 | payload / 响应 | +|------|-----------------| +| ✅ `month` 在 1-12 区间内(含边界 1、12) | 正常返回 `code=200` | +| ❌ `month` 不在 1-12 区间(如 0、13) | 返回 `code=605010` | +| ❌ 不传 `month` 参数 | 返回 `code=100001`(未受本次改动影响) | +| ❌ 继续按 `code=100001` 识别"月份越界"这一具体场景 | 本端点越界场景已改为 605010,100001 现在只对应"缺参" | + +### 切换状态时的必要动作 + +前端若此前对本端点单独写过"`code=100001` → 月份超出范围"的文案分支,需要改成识别 `605010`(文案为"月份超出范围"),并与 `grid` 端点共用同一套 605010 处理逻辑;100001 的处理分支需要改为对应"参数缺失"。 + +--- + +## 五、数据库行为 + +本次涉及的接口为只读查询,无任何数据库写操作。改动只是把一段入参校验从框架注解移到 Service 层方法内,不涉及任何表结构或存量数据变化。 + +--- + +## 六、边界行为 + +- `month` 不在 1-12 → 605010(本次改动后的新行为,此前是 100001) +- `month` 缺失(未传参数)→ 100001(既有行为,未改动) +- `year` 越界 → 605076(#8561 引入的独立判定,先于 `month` 判定执行) +- `month` 在 1-12 且 `year` 合法 → 正常返回,字段结构未变 + +--- + +## 六.5、枚举 / 数据字典 + +### 月份越界错误码(`AssignmentErrorCode.MATRIX_MONTH_OUT_OF_RANGE`) + +**所属字段**: 无(HTTP 响应顶层 `code`) | **类型**: `Integer` + +| 值 | 中文 | 本次是否新增 | 说明 | +|----|------|------|------| +| `605010` | 月份超出范围 | 端点内是新用法(既有码,`grid` 端点此前已在用) | `unassigned-orders` 本次起对 `month` 越界统一返回该码,与 `grid` 同构 | +| `100001` | 参数非法 | 未变 | `month` 缺失(未传参数)时仍返回,文案为"参数非法: 月份不能为空" | + +## 六.6、修改前后对比 + +### 字段级对比 + +本次无请求/响应字段新增或删除;`month` 字段摘掉了 `@Min(1)/@Max(12)` 注解,`@NotNull` 保留,字段本身仍是必填 `Integer`。 + +### 行为级对比 + +| 场景 | 改前 | 改后 | +|------|------|------| +| `unassigned-orders`,`month` 越界(如 0、13) | 返回框架码 `100001`(`@Min/@Max` 拦截) | 返回业务码 `605010` | +| `unassigned-orders`,`month` 缺失 | 返回 `100001` | 不变,仍返回 `100001` | +| `grid`,`month` 越界 | 返回 `605010` | 不变,仍返回 `605010`(本次未改动 grid,仅用于对照验证未回归) | +| `unassigned-orders`,`month` 在 1-12 | 正常返回 200 | 不变,仍正常返回 200 | + +## 六.7、影响评估 + +- **是否破坏向后兼容**: 是——`month` 越界时的错误码从 `100001` 变为 `605010`,前端若按具体码值做过分支判断,命中该场景的分支需要更新。 +- **前端是否必须同步上线**: 是(仅针对本端点单独维护过 100001 越界分支的场景)——若前端此前对 `unassigned-orders` 单独写过"`code=100001` 即月份越界"的判断,现在需要改为识别 `605010`;若前端此前是把 100001 统一当作"参数错误"泛化处理且未细分场景,则不受影响。 +- **前端 workaround 清理点**: 若此前为"同一类月份错误在 grid 和 unassigned-orders 上分别处理"写过两套逻辑,现在两端点已统一为 605010,可以合并成一套。 + +--- + +## 七、不影响范围 + +- **仅影响**: `unassigned-orders` 端点在 `month` 入参越界(不在 1-12)时的错误码。 +- **零影响**: + - `month` 缺失时的错误码(仍是 100001) + - `year` 校验逻辑(605076,属 #8561 独立改动) + - `grid`/`month-counts` 两个端点的既有行为 + - `unassigned-orders` 在 `month` 合法时的成功路径字段结构 + +--- + +## 八、测试环境已验证 + +服务:`hl-fleet-service`,dev-v3 分支部署测试网关 @ `9c7ac9382`(含 #8571 所在提交),测试网关 `https://api.test.1814.love`: + +``` +✓ GET unassigned-orders?year=2026&month=13 → code=605010, message="月份超出范围"(此前应为 100001) +✓ GET unassigned-orders?year=2026&month=0 → code=605010 +✓ GET unassigned-orders?year=2026&month=1(下边界)→ code=200, data=[] +✓ GET unassigned-orders?year=2026&month=12(上边界)→ code=200, data=[] +✓ GET unassigned-orders?year=2026(不传 month)→ code=100001, message="参数非法: 月份不能为空"(@NotNull 未被误摘) +✓ GET grid?year=2026&month=13 → code=605010(grid 既有行为,未回归) +``` + +--- + +## 十、相关文档 + +- 关联 Issue: [wx/HL#8571](https://git.1814.love/wx/HL/issues/8571) +- 关联 PR: [wx/HL#8582](https://git.1814.love/wx/HL/pulls/8582) + +## 关联 / 联系人 + +### 链接 + +- **Issue**: [#8571](https://git.1814.love/wx/HL/issues/8571) +- **PR**: [#8582](https://git.1814.love/wx/HL/pulls/8582) +- **Merge commit**: [6634d0588d](https://git.1814.love/wx/HL/commit/6634d0588d) + +### 联系人 + +- **后端负责人**: @wx