diff --git a/changelogs-v2/2026-08/02_5374_保险任务与派单候选补齐团号契约-修改接口-管理后台.md b/changelogs-v2/2026-08/02_5374_保险任务与派单候选补齐团号契约-修改接口-管理后台.md new file mode 100644 index 0000000..ede9925 --- /dev/null +++ b/changelogs-v2/2026-08/02_5374_保险任务与派单候选补齐团号契约-修改接口-管理后台.md @@ -0,0 +1,211 @@ +--- +schema: "hl-changelog/v2" +ticket: "5374" +title: "保险任务与派单候选补齐真实团号契约" +consumer: "admin" +change_type: "修改接口" +backend_status: "deployed" +gateway_status: "verified" +frontend_status: "pending" +frontend_owner: "" +frontend_ref: "" +target_release: "" +verified_at: "2026-08-03T03:10:15+08:00" +status_note: "后端 PR #5415 已合并为 dev-v3@ee7ad816b;测试部署任务 23928056 双实例健康,保险任务与派单候选经网关真登录验证,Flyway 001/002、nullable VARCHAR(32)、回填收敛和普通 EXPLAIN 均通过;前端仍待领取。" +updated_at: "2026-08-03" +base: "dev-v3" +--- + +# Fleet:保险任务与派单候选补齐真实团号契约 + +> **服务**: hl-fleet-service (端口 8087) +> **PR**: [wx/HL#5415](https://git.1814.love:8443/wx/HL/pulls/5415) +> **Issue**: [wx/HL#5374](https://git.1814.love:8443/wx/HL/issues/5374) +> **日期**: 2026-08-02 +> **影响范围**: 管理后台车务保险任务列表与派单候选冲突提示 + +--- + +## 一、关键变化 + +- 保险任务列表新增独立 `teamNo` 团号 contains 查询,并在任务项返回真实 `teamNo`。 +- 派单候选的车辆、司机冲突快照新增真实 `teamNo`。 +- 无团号统一返回 `null`,**禁止回退或伪装为 `orderNo`**;现有订单号和雪花 ID 字符串序列化契约不变。 + +--- + +## 变更接口 + +| # | 接口 | 方法 | 路径 | 变更类型 | 说明 | +|---|---|---|---|---|---| +| 1 | 司机险任务/流水分页 | GET | `/admin/fleet/insurance/tasks` | 请求与响应字段新增 | 新增 `teamNo` 查询及任务团号 | +| 2 | 派单车辆/司机候选 | POST | `/admin/fleet/assignments/candidates` | 嵌套响应字段新增 | 两类 `conflicts[]` 新增真实团号 | + +--- + +## 三、接口详情 + +### 1. 司机险任务/流水分页 `GET /admin/fleet/insurance/tasks` + +**请求 VO**: `FleetInsuranceTaskPageReqVO` + +#### 新增入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|---|---|---|---|---|---| +| `teamNo` | Query | String | 否 | contains 模糊匹配 | 只搜索团号;不会 OR 匹配订单号;过滤在分页前完成 | + +#### 新增出参 `Result>` + +| 字段 | 类型 | 说明 | +|---|---|---| +| `data.records[].teamNo` | `String|null` | 保险任务冻结的真实团号快照;无团号返回 `null` | + +请求示例: + +```http +GET /admin/fleet/insurance/tasks?teamNo=2607&page=1&pageSize=20 +``` + +响应字段示例: + +```json +{ + "code": 200, + "data": { + "records": [ + { + "taskId": "9007199254740993", + "orderId": "9007199254740995", + "orderNo": "26-0701", + "teamNo": "HL-2607-001" + } + ], + "total": 1, + "page": 1, + "pageSize": 20 + }, + "success": true +} +``` + +### 2. 派单车辆/司机候选 `POST /admin/fleet/assignments/candidates` + +**响应 VO**: `AssignmentCandidateRespVO.ConflictVO` + +#### 新增出参 + +| 字段 | 类型 | 说明 | +|---|---|---| +| `data.vehicles.records[].conflicts[].teamNo` | `String|null` | 冲突派单的 Fleet 本地真实团号快照 | +| `data.vehicles.list[].conflicts[].teamNo` | `String|null` | `records` 的兼容序列化别名,字段一致 | +| `data.drivers.records[].conflicts[].teamNo` | `String|null` | 冲突派单的 Fleet 本地真实团号快照 | +| `data.drivers.list[].conflicts[].teamNo` | `String|null` | `records` 的兼容序列化别名,字段一致 | + +响应片段: + +```json +{ + "vehicles": { + "records": [ + { + "vehicleId": "101", + "conflicts": [ + { + "assignmentId": "9001", + "assignmentGroupId": "9101", + "orderNo": "26-0701", + "teamNo": "HL-2607-001", + "blocking": true, + "reasonCode": "ASSIGNMENT_CONFLICT" + } + ] + } + ] + }, + "drivers": { + "records": [ + { + "driverId": "201", + "conflicts": [ + { + "assignmentId": "9001", + "assignmentGroupId": "9101", + "orderNo": "26-0701", + "teamNo": null, + "blocking": true, + "reasonCode": "ASSIGNMENT_CONFLICT" + } + ] + } + ] + } +} +``` + +--- + +## 四、契约约束与正确调用方式 + +- 前端展示团号必须读取 `teamNo`;值为 `null` 时展示 `-`。 +- 不得把 `orderNo` 当作团号回退值。 +- `orderNo`、`orderId`、`assignmentId`、`assignmentGroupId` 继续保留;雪花 ID 继续按 JSON String 返回,用于路由和动作。 +- `teamNo` 只增加展示与查询能力,不改变候选 `available`、`blocking`、同城首尾衔接、可用窗口或派单写侧锁内复核。 +- 保险任务查询的 `teamNo` 是独立参数,不沿用派车看板兼容匹配订单号的既有语义。 + +--- + +## 五、数据库行为 + +- `fleet_insurance_task.team_no VARCHAR(32) NULL` 与 `fleet_assignment.team_no` 对齐。 +- nullable DDL 与历史回填 DML 使用两个独立 Flyway 版本。 +- 历史数据仅按 `assignment_id` 从 `fleet_assignment.team_no` 回填。 +- 无匹配派单、来源团号为空或任务已有非空团号时保持原值;不跨服务查询、不按订单号猜测。 + +### 生产两阶段迁移门禁(本单未授权、未执行生产) + +1. 第一阶段必须设置 `SPRING_FLYWAY_TARGET=20260802.001`,只允许 nullable DDL 落库;禁止携带默认 `latest` 直接滚动发布。 +2. 完成 Fleet Java 全量滚动并确认所有旧实例退出;此时新写入已冻结 `teamNo`,不会再产生旧代码造成的新增空快照。 +3. 重新只读统计待回填数、可匹配数并执行普通 `EXPLAIN`;影响行数 ≤ 50k、扫描行数 ≤ 200k、staging 单事务 ≤ 5s、锁等待 ≤ 1s、复制延迟增量 ≤ 2s 才可继续。 +4. 第二阶段才移除 target 或设置 `SPRING_FLYWAY_TARGET=20260802.002`,由受控单实例执行幂等 DML,再核验 Flyway history 与剩余空值。 +5. 任一阈值超限或证据缺失即停止第二阶段,改用 1k–5k 行受控分批;生产禁止 `EXPLAIN ANALYZE UPDATE`。 + +--- + +## 六、边界行为 + +- `teamNo` 完整或部分关键词均按 contains 命中。 +- 只有 `orderNo` 含关键词而 `teamNo` 不含时,不命中保险任务列表。 +- 历史任务或冲突派单没有团号时,响应字段为 `null`,接口不异常。 +- 空 `teamNo` 等同不启用该筛选;其他现有筛选条件与其按 AND 组合。 + +--- + +## 七、不影响范围 + +- 不修改派车矩阵、甘特、车务工作台或派车看板字段与搜索语义。 +- 不修改司机档案 `relatedOrders`。 +- 不新增 order-v3 Feign,不修改 `hl-common-feign`、内部接口或共享 Java DTO。 +- 不修改 `hl-ui`。 + +--- + +## 验证证据 + +- 定向测试:226 项通过,0 failures、0 errors、0 skipped。 +- Fleet Spotless:通过。 +- JaCoCo changed executable lines:9/9(100%)。 +- 独立 Reviewer(max):无 P0–P2。 +- oasdiff:项目缺少可复现 Swagger 2 → OAS3 转换链,标记 `not_configured`;已完成源码级手工契约对比。 +- MySQL 8.0.33 隔离实例:`FleetInsuranceTaskTeamNoMysqlTest` 3/3 通过,0 skipped;H2 全迁移回归 `FleetInsuranceTaskMigrationTest` 8/8 通过。 +- Fleet 全模块 `verify` 已执行 2764 项;接入本单隔离 Redis 后相关 4 项通过且无 key 残留,当前仅余 3 项基线失败(Release E Windows 时序 2 项、保险并发夹具 1 项,后者已在未含本单改动的 `dev-v3@a999a3df7` 同样复现),未将该次命令记为通过。 +- 测试部署及网关真实 round-trip 结果将在后端完成后更新本文件元数据与本节。 + +--- + +## 九、前端消费动作 + +1. 保险任务列表筛选增加 `teamNo` 参数,并按 `data.records[].teamNo` 展示团号。 +2. 派单候选的车辆/司机冲突提示改用各自 `conflicts[].teamNo` 展示团号。 +3. `teamNo === null` 时展示 `-`,不得显示 `orderNo` 作为替代团号。 +4. 保留现有 ID 与订单号用于路由、动作及兼容逻辑。