diff --git a/changelogs-v2/2026-10/23_9193_团期确认超限改为先计数拒绝-修改接口-管理后台.md b/changelogs-v2/2026-10/23_9193_团期确认超限改为先计数拒绝-修改接口-管理后台.md new file mode 100644 index 00000000..d0990c83 --- /dev/null +++ b/changelogs-v2/2026-10/23_9193_团期确认超限改为先计数拒绝-修改接口-管理后台.md @@ -0,0 +1,210 @@ +--- +schema: "hl-changelog/v2" +ticket: "9193" +title: "团期确认超限改为先计数拒绝:602010 触发时机提前、文案改为整团重配并警示解除" +consumer: "admin" +author: "chewu2(GIT)" +change_type: "修改接口" +backend_status: "deployed" +gateway_status: "verified" +frontend_status: "not_required" +frontend_owner: "" +frontend_ref: "" +target_release: "" +verified_at: "" +status_note: "已合并 dev-v3(PR #9214,squash b50acf55e),已部署测试服 task 67120fc5,双实例 8187/8087 均 is UP(各 7s),health 均 200,部署日志 ERROR 0;ha_r1_vm 经网关 GET /admin/fleet/dispatch-groups/page 返回 HTTP 200 / code 200(39 团)。接口入参/出参结构零变化,仅 602010 的触发时机与文案变化:超限团不再先做全量 FOR UPDATE 读取。hl-ui 无需改代码。" +updated_at: "2026-10-23" +base: "dev-v3" +--- + +# hl-fleet-service: 团期确认超限改为先计数拒绝 + +> **服务**: hl-fleet-service(管理后台) +> **PR**: #9214(已合入 dev-v3,合并提交 b50acf55e) +> **Issue**: #9193 +> **日期**: 2026-10-23 +> **影响范围**: 管理后台团期确认(超限存量团的 602010 触发时机与文案) + +--- + +## ⚠️ 关键变化 + +🟢 团级确认在存活配车行超过 500 时,改为**先计数、再拒绝**:不再先把全量存活行 `FOR UPDATE` 读进内存。 + +🟢 `602010` 的触发时机提前,文案改为: + +```text +单团存活配车行 N 超过单次确认上限 500,本次确认已拒绝且未读取明细。请联系管理员,用整团重配把排车项降到 500 以内——注意重配是整团全量覆盖,未在新计划中列出的排车项会被解除。 +``` + +🔴 接口路径、请求体、响应体结构、错误码数值均未变。前端不需要改字段或解析逻辑;若页面直接展示 `message`,会自动显示新文案。 + +--- + +## 一、背景 + +#9179 给团级确认加了 500 行上限,但守卫在 `selectAliveByGroupBatchForUpdate` 之后:超限团仍要先全量锁定读,再被拒绝。#9193 修读取侧:先计数守卫、再决定是否读明细。 + +超限存量的现实来源:一是 #9179 上线前的历史数据;二是 `batchCreate` 允许 4000 项而确认侧只允许 500 项(独立缺陷,另单处理)。 + +## 二、变更接口清单 + +| # | 接口 | 方法 | 路径 | 变更类型 | 说明 | +|---|------|------|------|----------|------| +| 1 | 团期确认 | POST | `/admin/fleet/group-dispatch/batches/{groupBatchId}/confirm` | 错误码触发时机 + 文案 | 超限时先计数拒绝,不读明细;入参/出参结构不变 | + +## 三、接口详情 + +### 1. 团期确认 `POST /admin/fleet/group-dispatch/batches/{groupBatchId}/confirm` + +**VO**: `GroupDispatchConfirmReqVO` / `Result` + +#### 使用场景 + +管理后台团期配车页点击「确认配车」时调用。服务端锁定团期、校验覆盖率与资源可派性,并把本团「已派车」行推进为「已确认」。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| groupBatchId | Path | Long | ✅ | - | 团期主订单 ID | +| requirementId | Body | Long | 否 | - | 需求 ID;不传则取当前有效需求 | +| requirementVersion | Body | Integer | 否 | - | 需求版本,用于并发校验 | +| remark | Body | String | 否 | 长度上限见 VO | 确认备注 | + +#### 出参 `Result` + +| 字段 | 类型 | 说明 | +|------|------|------| +| groupBatchId | Long | 团期主订单 ID | +| confirmedCount | Integer | 本次确认行数 | +| alreadyConfirmedCount | Integer | 原本已确认行数 | +| requirementId / requirementVersion | Long / Integer | 本次使用的需求与版本 | +| planVersion | Long | 配车计划版本 | +| requirementAdvanceIntent | String | 需求推进意图 | +| coverage | Object | 覆盖率明细 | +| legacyGroupRowCount | Integer | 旧团行数 | +| specWarnings | Array | 规格告警 | + +#### 请求示例 + +```json +{ "requirementId": 2112275846201069569, "requirementVersion": 3, "remark": "确认配车" } +``` + +#### 响应示例 + +```json +{ "code": 200, "message": "成功", "data": { "groupBatchId": 2112275846201069569, "confirmedCount": 12 }, "success": true } +``` + +#### 空数据 / 降级响应 + +本接口无空数据降级:无法确认时返回业务错误码,不返回部分成功。 + +#### 错误响应 + +```json +{ + "code": 602010, + "message": "单团存活配车行 2000 超过单次确认上限 500,本次确认已拒绝且未读取明细。请联系管理员,用整团重配把排车项降到 500 以内——注意重配是整团全量覆盖,未在新计划中列出的排车项会被解除。", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 存活行 ≤ 500:正常确认;恰好 500 行成功。 +- 存活行 > 500:先计数拒绝,不读明细;返回 602010。 +- 并发窗口:计数与全量锁定读之间若有人插行,读后二次复核仍会按 602010 拒绝。 +- 鉴权、错误码 602005/602006/602007/602008/602009 等原有语义不变。 + +## 四、契约约束与正确调用方式 + +### ✅ 正确 / ❌ 错误调用对照 + +| 场景 | 调用 | +|------|------| +| ✅ 存活行 ≤ 500 | 正常 POST,按原逻辑确认 | +| ❌ 存活行 > 500 仍反复重试 | 每次都会 602010;应先整团重配降到 500 行以内 | +| ❌ 把 602010 当成可重试的并发错误 | 不是并发错误;重试不会改变存活行数 | + +### 超限后的必要动作 + +由管理员执行一次请求项 ≤ 500 的整团重配(`POST /admin/fleet/group-dispatch/batches/{groupBatchId}/reconfigure`),把存活行压回 500 以内。**重配是整团全量覆盖**:未在新计划中列出的排车项会被解除,不是增量补充。 + +## 五、数据库行为 + +无表结构变更、无 Flyway。确认成功时仍按原逻辑把 `fleet_group_dispatch.status` 从 `ASSIGNED` CAS 为 `CONFIRMED`;超限拒绝时零写入。 + +## 六、边界行为 + +- 未登录 / 无车务权限 → 网关或权限守卫拒绝(403),与本次改动无关。 +- 团期不存在 → 原错误码。 +- 存活行恰好 500 → 成功(判据是 `> 500` 才拒)。 +- 存活行 501 → 602010,且不执行全量明细读取。 +- 存量 2000/5000 → 只读 1 行计数,明细零读取;实测全量读耗时 140/168ms(远小于 30s 租约)。 + +## 六.6、修改前后对比 + +### 行为级对比 + +| 场景 | 改前 | 改后 | +|------|------|------| +| 存活行 ≤ 500 | 正常确认 | 正常确认(不变) | +| 存活行 = 501 | 先全量 FOR UPDATE 读取,再 602010 拒绝 | 先计数,直接 602010 拒绝,不读明细 | +| 存活行 = 2000/5000 | 读取成本随存量线性增长 | 只读 1 行计数,明细零读取 | + +### 字段级对比 + +无字段变化。 + +## 六.7、影响评估 + +- **是否破坏向后兼容**: 否。请求/响应结构、错误码数值均未变;只有 602010 的触发时机提前、文案变化。 +- **前端是否必须同步上线**: 否。前端无需改代码;若自定义了 602010 提示语,建议同步为新文案。 +- **前端 workaround 清理点**: 无。 + +## 七、不影响范围 + +- **仅影响**: 管理后台团期确认的 602010 触发时机与文案。 +- **零影响**: + - 团期重配 `reconfigure` 的请求/响应结构与 500 项上限(未改)。 + - 团期分享确认 `share/confirm`(走独立事务路径,未改)。 + - 配车计划查询、覆盖率查询、派车工作台读取。 + - 数据库表结构与 Flyway。 + - 网关路由 `/admin/fleet/**`。 + +## 八、测试环境已验证 + +**环境**: TEST **验证时间**: 2026-10-23 11:08~11:10 +**构建身份**: hl-fleet-service `dev-v3 @ b50acf55e`,部署 task `67120fc5`;双实例 `8187/8087 is UP after 7s`;部署状态回读 `dev-v3 b50acf55e 0/N ok`。 + +```text +POST https://api.test.1814.love/admin/auth/login (ha_r1_vm) → HTTP 200 / code 200 +GET https://api.test.1814.love/admin/fleet/dispatch-groups/page?pageNo=1&pageSize=1 → HTTP 200 / code 200 / total=39 +GET http://127.0.0.1:8087/actuator/health → 200 +GET http://127.0.0.1:8187/actuator/health → 200 +部署窗口 ERROR 计数: 8087=0 / 8187=0 +``` + +真库用例:JDBC 预置存活 2000 行的团,确认被 602010 拒绝且 `selectAliveByGroupBatchForUpdate` 零调用;500 行成功、501 行拒绝;2000/5000 行全量读耗时 140/168ms。 + +## 十、相关文档 + +- 关联 Issue: [wx/HL#9193](https://git.1814.love/wx/HL/issues/9193) +- 关联 PR: [wx/HL#9214](https://git.1814.love/wx/HL/pulls/9214) +- 前置工单: [wx/HL#9179](https://git.1814.love/wx/HL/issues/9179) + +## 关联 / 联系人 + +### 链接 + +- **Issue**: [#9193](https://git.1814.love/wx/HL/issues/9193) +- **PR**: [#9214](https://git.1814.love/wx/HL/pulls/9214) +- **Merge commit**: [b50acf55e](https://git.1814.love/wx/HL/commit/b50acf55ecdb08b2c28f20cfeaf5344e16cafd53) + +### 联系人 + +- **后端负责人**: @chewu2