文件
hl-api-changelog/changelogs-v2/2026-09/20_7987_团期时间线新增开窗与重配两类事件-修改接口-管理后台.md
T
API Changelog Bot和Claude Opus 5 ba87a9b611
changelog-filename-gate / validate (push) Failing after 1s
docs(changelog): #7987 订正被 mmg 实证推翻的「前端必须新增渲染分支」,并清空 not_required 上的认领字段
正文第 38 行说「前端必须新增这两个 event_type 的渲染分支」,而 mmg 在
frontmatter 里已用实证翻成 not_required(StatusLogsPanel 渲染
eventTypeName || eventType || '事件',后端直供中文名+原码兜底,前端无自建
映射表,零改动)。订正了状态位却没回头改正文,那句话会让下一个读的人以为
前端还有活。原句划掉保留接 grep,并注明这条结论依赖「后端继续直供
eventTypeName」——该字段哪天返 null,渲染缺口会重新成立。

frontend_owner/frontend_ref 清空:交付指南写死 not_required 条目任何人
(含前端)不得回写这 4 个认领字段,填了会被 E_FRONTEND 残留校验拦下
(2026-08-19 #6077 先例)。本文件能推上去是因为门禁只扫新增路径,
不是因为合规。mmg 的实证本身原样保留。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-21 09:02:10 +08:00

499 行
25 KiB
Markdown
原始文件 Blame 文件历史

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
---
schema: "hl-changelog/v2"
ticket: "7987"
title: "团期时间线新增开窗与重配两类事件,事件类型枚举扩展"
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: "⚠️ 2026-09-21 清空 frontend_owner/frontend_ref:按 BACKEND_CHANGELOG_DELIVERY_GUIDE,not_required 条目**任何人(含前端)不得回写** frontend_owner / frontend_ref / target_release / verified_at——这 4 个是「前端需要动作」的认领标记,填了会被发布门禁 E_FRONTEND 残留校验拦下(2026-08-19 #6077 就是这么被拦的)。前端表达「已知悉」用评论/口头即可,不动 frontmatter。本文件能推上去是因为门禁**只扫新增路径**,不是因为合规。mmg 的实证本身保留在下文。 gateway_status=verified 的依据:2026-09-20 18:22-18:46 经网关 https://api.test.1814.love:9443 实测(账号 cw_test_7444)。GET /v3/admin/order/group-batch/{id}/status-logs 在两个批次上分别取到 BATCH_VEHICLE_REQUIREMENT_REOPENED(开窗,extra 含 windowMinutes/blockedStage/expiresAt/scopeGroupCodes/scopeDates 五项齐全)与 BATCH_VEHICLE_DISPATCH_RECONFIGURED(重配),eventType/eventTypeName/changeType=DATA/extra 各字段逐一对照一致。⚠️ 本次实测发现并已订正一处契约偏差:重配事件的 operatorId 原写字符串 SYSTEM,实测为 null(与库里其它 SYSTEM 类事件惯例一致),判为文档写错而非实现错,已在字段表/字段值/JSON 示例/注意事项共 5 处改完。前端若按原文档判空会得到相反预期,故这条订正与发布同一批。 前端实证翻 not_required(mmg 2026-09-20):前端无自建 eventType 映射表,StatusLogsPanel 渲染 `eventTypeName || eventType || '事件'`(后端直供中文名+原码兜底),operatorType=SYSTEM 时 operatorId=null/operatorName「系统」是该面板注释钉住的既有口径,两类新事件与 operatorId 订正均自动正常显示,零改动。 【上一轮原注】backend_status=deployed 的判据(2026-09-20 18:35 复核):hl-order-service-v3 测试服部署点 e179e09bd(2026-09-20 17:55:02 发布),`git merge-base --is-ancestor ab92377c7 e179e09bd` = true,故本篇端点的代码确已在测试服运行的字节里。⚠️ 这是一次**时点读数**:测试服由多会话共用,随时可能被滚到别的提交;origin/dev-v3 在本次复核时已前进到 f56692a51,落后的是部署点不是本篇。 gateway_status 保持 pending——本会话未对本篇端点做任何真实网关调用,正文示例值的来源已在各小节逐处标注(单元测试字面量 / @ApiModelProperty example 声明),不是抓包。待网关复验后再置 verified,**不得为了让门禁变绿改这个位**。"
updated_at: "2026-09-20"
base: "dev-v3"
---
# order-v3: 团期时间线新增开窗与重配两类事件
> **存放目录**: 二期(v3) → `changelogs-v2/{YYYY-MM}/`
>
> **服务**: hl-order-v3 (端口 8021)
> **PR**: #8039
> **Issue**: #7987
> **日期**: 2026-09-20
> **影响范围**: 管理后台 - 团期详情页 - 状态流水/时间线
---
## ⚠️ 关键变化
后端在团期时间线(`group_batch_status_log` 表)新增两种事件记录:
- **BATCH_VEHICLE_REQUIREMENT_REOPENED**(开窗事件)—— 管理员显式开启受控重配窗口时写入
- **BATCH_VEHICLE_DISPATCH_RECONFIGURED**(重配事件)—— fleet 回调确认重配生效时写入
~~**前端必须新增这两个 event_type 值的渲染分支**,否则这两类事件在管理后台团期时间线上将无法正常显示其标签名(见下文「③ 前端渲染缺口」)。~~
✅ **2026-09-20 mmg 实证推翻了上面这句,前端零改动**(原句划掉保留接 grep):`StatusLogsPanel` 渲染的是 `eventTypeName || eventType || '事件'`,**后端直供中文名 + 原码兜底**,前端**没有**自建 eventType 映射表 ⇒ 两类新事件与 `operatorId` 那处订正都会自动正常显示。
📌 下文「③ 前端渲染缺口」一节同样按这条实证作废——**它描述的缺口在当前前端实现里不存在**。⚠️ 但这个结论依赖「后端继续直供 `eventTypeName`」:哪天后端让该字段返回 null(正文「注意事项」里写的历史脏值场景就是一例),前端会退化成显示原始 code,那时这条渲染缺口会重新成立。
---
## 一、背景
#7987 实施"受控重配窗口"机制:管理员可在团期进入待出发后仍显式开一个时间限制的窗口,允许车务在此期间重新排车。此前这两件事的事实只落在需求行的三个字段(`reconfigure_reason` / `reconfigure_opened_by` / `reconfigure_opened_at`),但运营打开团期详情页时看不到这些列,无法追溯窗口何时开过。
本次变更补上团期时间线的留痕,让管理员在团期详情页就能看到「谁在何时以什么原因开了重配窗口」与「窗口内换车是否生效」。
---
## 二、变更接口清单
既存接口(#7304 落地)返回值扩展:
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|------|------|------|----------|------|
| 1 | 团期状态流水查询 | GET | `/v3/admin/order/group-batch/{id}/status-logs` | 响应新增 event_type 值 | 新增两种事件类型 |
---
## 三、接口详情
### 1. 团期状态流水查询 `GET /v3/admin/order/group-batch/{id}/status-logs`
**VO**: `GroupBatchStatusLogItemVO` (既存响应 VO,新增 eventTypeName 映射值)
#### 使用场景
管理后台团期详情页的状态流水/时间线面板,用于向运营展示该团期的历史状态变化与重要操作记录。本次变更使该时间线新增两类事件的可见性。
#### 入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|------|------|------|------|------|------|
| id | Path | Long | ✅ | - | 团期主订单 ID |
#### 出参 `Result<List<GroupBatchStatusLogItemVO>>`
| 字段 | 类型 | 说明 |
|------|------|------|
| logId | String | 流水记录 ID |
| groupBatchId | Long | 团期主订单 ID |
| changeType | String | 变更类型:STATUS(状态流转) / DATA(数据变更) |
| eventType | String | 事件类型代码(如 BATCH_VEHICLE_REQUIREMENT_REOPENED) |
| eventTypeName | String | 事件类型中文名(**新增两种**:团车受控重开·已开配车窗口 / 团车受控重配·车辆安排已变更) |
| fromStatus | String | 状态前值代码(如 PENDING_DEPARTURE) |
| fromStatusName | String | 状态前值中文名 |
| toStatus | String | 状态后值代码 |
| toStatusName | String | 状态后值中文名 |
| content | String | 事件文本内容(前端直接渲染) |
| reason | String | 事件原因/备注(可为 null) |
| operatorType | String | 操作人类型:ADMIN / SYSTEM / MQ |
| operatorId | String | 操作人 ID。⚠️ **2026-09-20 网关实测订正**:**`operatorType=SYSTEM` 时本字段是 `null`,不是字符串 `"SYSTEM"`**(与库里其它 SYSTEM 类事件如 `BATCH_VEHICLE_REQUIREMENT_DONE` 的惯例一致)。前端判空请按 `null` 处理 |
| operatorName | String | 操作人名称 |
| extra | Map<String, Object> | 结构化附加数据,字段随事件类型变化(见下文"新增事件详解") |
| changedAt | String | 事件发生时刻(ISO 8601) |
#### 新增事件类型详解
**BATCH_VEHICLE_REQUIREMENT_REOPENED 事件**
- `eventType`: `"BATCH_VEHICLE_REQUIREMENT_REOPENED"`
- `eventTypeName`: `"团车受控重开·已开配车窗口"`
- `changeType`: `"DATA"` (状态内数据变更,fromStatus = toStatus)
- `operatorType`: `"ADMIN"`
- `operatorId`: 开窗管理员 ID
- `operatorName`: 开窗管理员真名
- `content`: "开启受控重配窗口:允许车务在 X 分钟内重新安排本团车辆(授权 N 个乘车分组 / M 个行程日,2026-09-20 10:30:00 前有效)。此前团期已进入「待出发」,正常不可再配车。"
- `reason`: 管理员必填的开窗原因(如"团期特殊变更")
- `extra`: 结构化数据
```json
{
"requirementId": "需求行主键(字符串)",
"requirementVersion": 需求行版本号(整数),
"blockedStage": "PENDING_DEPARTURE",
"windowMinutes": 120,
"expiresAt": "2026-09-20T12:30:00",
"scopeGroupCodes": ["乘车分组编号数组"],
"scopeDates": ["2026-09-21", "2026-09-22"]
}
```
**BATCH_VEHICLE_DISPATCH_RECONFIGURED 事件**
- `eventType`: `"BATCH_VEHICLE_DISPATCH_RECONFIGURED"`
- `eventTypeName`: `"团车受控重配·车辆安排已变更"`
- `changeType`: `"DATA"` (状态内数据变更,fromStatus = toStatus)
- `operatorType`: `"SYSTEM"`
- `operatorId`: **`null`**(⚠️ **2026-09-20 网关实测订正**:原写 `"SYSTEM"`,实测为 `null`)
- `operatorName`: `"系统"`
- `content`: "本团车辆安排已被重新排定:车务在受控重配窗口内完成换车,新的配车计划(版本 20260920_v1)已生效,原计划作废。开窗授权人:张三;具体经办人见车务配车记录。"
- `reason`: 开窗时管理员填写的原因(沿用窗口的 reason,非重配操作人的备注)
- `extra`: 结构化数据
```json
{
"requirementId": "需求行主键(字符串)",
"requirementVersion": 需求行版本号(整数),
"planVersion": "fleet 配车计划版本号(字符串)",
"reconfigureOpenedBy": "开窗管理员 ID(与前一条事件的 operatorId 对应)",
"reconfigureOpenedAt": "2026-09-20T10:15:30"
}
```
#### 请求示例
```json
GET /v3/admin/order/group-batch/8000001/status-logs
```
#### 响应示例
```json
{
"code": 200,
"message": "成功",
"data": [
{
"logId": "12345",
"groupBatchId": "8000001",
"changeType": "DATA",
"eventType": "BATCH_VEHICLE_REQUIREMENT_REOPENED",
"eventTypeName": "团车受控重开·已开配车窗口",
"fromStatus": "PENDING_DEPARTURE",
"fromStatusName": "待出发",
"toStatus": "PENDING_DEPARTURE",
"toStatusName": "待出发",
"content": "开启受控重配窗口:允许车务在 120 分钟内重新安排本团车辆(授权 2 个乘车分组 / 3 个行程日,2026-09-20T12:30:00 前有效)。此前团期已进入「待出发」,正常不可再配车。",
"reason": "临时增加3人,需调整座位分组与用车方案",
"operatorType": "ADMIN",
"operatorId": "1001",
"operatorName": "李四",
"extra": {
"requirementId": "7000001",
"requirementVersion": 2,
"blockedStage": "PENDING_DEPARTURE",
"windowMinutes": 120,
"expiresAt": "2026-09-20T12:30:00",
"scopeGroupCodes": ["GRP001", "GRP002"],
"scopeDates": ["2026-09-21", "2026-09-22", "2026-09-23"]
},
"changedAt": "2026-09-20T10:30:00"
},
{
"logId": "12346",
"groupBatchId": "8000001",
"changeType": "DATA",
"eventType": "BATCH_VEHICLE_DISPATCH_RECONFIGURED",
"eventTypeName": "团车受控重配·车辆安排已变更",
"fromStatus": "PENDING_DEPARTURE",
"fromStatusName": "待出发",
"toStatus": "PENDING_DEPARTURE",
"toStatusName": "待出发",
"content": "本团车辆安排已被重新排定:车务在受控重配窗口内完成换车,新的配车计划(版本 20260920_v1)已生效,原计划作废。开窗授权人:李四;具体经办人见车务配车记录。",
"reason": "临时增加3人,需调整座位分组与用车方案",
"operatorType": "SYSTEM",
"operatorId": null,
"operatorName": "系统",
"extra": {
"requirementId": "7000001",
"requirementVersion": 2,
"planVersion": "20260920_v1",
"reconfigureOpenedBy": "1001",
"reconfigureOpenedAt": "2026-09-20T10:30:00"
},
"changedAt": "2026-09-20T11:45:00"
}
],
"success": true
}
```
#### 空数据 / 降级响应
```json
{
"code": 200,
"data": [],
"success": true
}
```
#### 错误响应
```json
{
"code": 589500,
"message": "团期不存在",
"success": false,
"data": null
}
```
#### 业务边界
- 接口返回的时间线按 `changedAt` 升序排列(从最早到最新)
- 两个新事件都属于 `DATA` 类(状态内数据变更),不涉及团期主状态 `batch_status` 变化
- 库里若有历史脏值或未知 event_type,后端 eventTypeLabel 返回 null,前端需兜底显示原始 code 值
---
## 四、契约约束与正确调用方式
> 本节说明后端接受请求、返回响应的规则。
### ✅ 正确 / ❌ 错误请求对照
| 场景 | 请求示例 | 结果 |
|------|---------|------|
| ✅ 查询既存团期的时间线 | `GET /v3/admin/order/group-batch/8000001/status-logs` | 200 + 时间线列表 |
| ✅ 无流水时返回空列表 | `GET /v3/admin/order/group-batch/9999999/status-logs`(不存在团期) | 200 + `data: []` |
| ❌ 团期 ID 非数字 | `GET /v3/admin/order/group-batch/abc/status-logs` | 400 |
### 字段约束与兼容性规则
- **eventType 兼容性**:库里可能存在本版本未定义的历史 event_type 值 → 后端 eventTypeLabel 返回 null → 前端应兜底显示原始 code 值,而不是报错
- **extra 字段**:根据 eventType 不同而变化(见下文详解);前端需根据 eventType 判断应读取哪些 extra 字段,勿假设所有事件的 extra 结构相同
- **operatorType 非 ADMIN 时**:⚠️ **2026-09-20 网关实测订正**:**`operatorId` 是 `null`、`operatorName` 是 `"系统"`——两个字段形态不同,不要当成同一回事**(原文把它们合并描述成「可能不是真实人名」,会让前端以为 `operatorId` 也有值) → 前端应按类型判断如何渲染,勿硬编码为"管理员"
- **reason 字段**:可为 null(仅新增事件强制填写,既有历史事件可能无此字段) → 前端应做 null check
---
## 六.5、枚举:新增事件类型
### eventType(GroupBatchLogEventType)
**所属字段**: `GroupBatchStatusLogItemVO.eventType` | **类型**: `String` | **枚举类**: `com.hulalv.order.groupbatch.enums.GroupBatchLogEventType`
新增两个枚举值(共有 N+2 个值):
| 值 | 中文名 | 说明 | changeType | 何时写入 |
|----|------|------|-----------|---------|
| `BATCH_VEHICLE_REQUIREMENT_REOPENED` | 团车受控重开·已开配车窗口 | 管理员显式开启受控重配窗口,允许车务在时间限制内重新排车 | DATA | 调用 POST `/v3/admin/order/group-batch/{id}/vehicle-requirement/reopen` 时 |
| `BATCH_VEHICLE_DISPATCH_RECONFIGURED` | 团车受控重配·车辆安排已变更 | fleet 就绪回调确认重配生效,新车辆计划已应用,原计划作废 | DATA | fleet Outbox 回调解除受控重开阻断时 |
### operatorType(操作人类型)
**所属字段**: `GroupBatchStatusLogItemVO.operatorType` | **类型**: `String`
既有三种值,新增事件涉及的分别是:
| 值 | 中文名 | 说明 | 示例事件 |
|----|------|------|---------|
| `ADMIN` | 管理员 | 真实的管理后台登录用户 | BATCH_VEHICLE_REQUIREMENT_REOPENED |
| `SYSTEM` | 系统 | 无 HTTP 请求上下文的自动操作(MQ / 定时任务 / 回调) | BATCH_VEHICLE_DISPATCH_RECONFIGURED |
| `MQ` | MQ 事件 | MQ 消费触发(如支付/退款回调) | 既有其他事件 |
---
## 四、前端需求与缺口说明
### ① eventTypeLabel 映射(前端渲染分支)
**后端实现**(`GroupBatchStatusLogService.java:237-248`):
```java
private String eventTypeLabel(String value) {
if (value == null) {
return null;
}
for (GroupBatchLogEventType type : GroupBatchLogEventType.values()) {
if (type.getValue().equals(value)) {
return type.getLabel();
}
}
return null; // 未知值返回 null
}
```
**当前状况**:
- 后端遍历枚举查找 event_type,找到则返回 label,否则返回 null
- 前端收到的 eventTypeName 字段值为 null 时,该行事件在时间线上**显示为空白**(既不报错、也不显示原始值,这是现状)
**前端必须新增的映射**:
```typescript
// 示例伪码
const eventTypeLabels = {
"BATCH_VEHICLE_REQUIREMENT_REOPENED": "团车受控重开·已开配车窗口",
"BATCH_VEHICLE_DISPATCH_RECONFIGURED": "团车受控重配·车辆安排已变更",
// ... 既有其他 event_type ...
};
```
**不加分支的后果**:这两类事件在管理后台团期时间线上无法显示其事件名称,运营只看得到时刻/操作人/备注,但看不出"这是什么事件",影响运营追溯。
### ② 重配事件的操作人恒为 SYSTEM(不能拿 extra 字段顶替)
**源码事实**(`GroupBatchService.java:1089-1118`,recordReconfigureTrail 方法):
```java
// 就绪回调中,无 HTTP 请求上下文,operatorResolver.resolve() 返回 SYSTEM
Operator operator = operatorResolver.resolve(); // → Operator.system()
groupBatchStatusLogService.recordDataChange(groupBatchId,
GroupBatchLogEventType.BATCH_VEHICLE_DISPATCH_RECONFIGURED,
batch == null ? null : GroupBatchStatus.fromCode(batch.getBatchStatus()),
content, window.reason(), extra);
```
**重配事件的字段值**:
- `operatorType`: `"SYSTEM"`
- `operatorId`: **`null`**(⚠️ **2026-09-20 网关实测订正**:原写 `"SYSTEM"`,实测为 `null`)
- `operatorName`: `"系统"`
- `extra.reconfigureOpenedBy`: 开窗管理员 ID(**不是**重配操作人)
- `extra.reconfigureOpenedAt`: 开窗时刻(**不是**重配时刻,重配时刻在 changedAt)
**这不是 bug,是设计**:
- 重配的真实经办人(谁在车务后台点的"重配"按钮)只存在于 fleet 侧的 `fleet_group_dispatch.updated_by`
- order-v3 是接收者,fleet 回调进来时没有经办人载荷
- `extra.reconfigureOpenedBy` 答的是"**谁授权开的窗**"(过去的管理动作),与"**谁换的车**"(当前的车务动作)是两个不同的人、不同的时刻
**前端若把 `extra.reconfigureOpenedBy` 显示成"经办人",就是把一个错误的责任人写到审计页面上**。
- ✅ 正确做法:operatorName 显示"系统",content 或 extra.reconfigureOpenedBy 里可补充说明"开窗人是谁"
- ❌ 错误做法:拿 extra.reconfigureOpenedBy 冒充 operatorId/operatorName 展示成经办人
### ③ 开窗事件的操作人是真实人(与重配事件不同)
**源码事实**(`GroupVehicleRequirementService.java:2305-2347`,recordReopenTrail 方法):
```java
public GroupVehicleReopenRespVO doReopen(Long groupBatchId,
GroupVehicleRequirementReopenReqVO req,
String operatorId) {
// ... 业务逻辑 ...
recordReopenTrail(groupBatchId, batch, active, req, windowMinutes, expiresAt);
}
private void recordReopenTrail(...) {
// recordDataChange 内部调 operatorResolver.resolve(),因为这是 HTTP 请求上下文
// 会从 AdminAuthInterceptor 注入的 AdminContext 里取当前登录管理员
groupBatchStatusLogService.recordDataChange(groupBatchId,
GroupBatchLogEventType.BATCH_VEHICLE_REQUIREMENT_REOPENED,
GroupBatchStatus.fromCode(batch.getBatchStatus()), content, req.getReason(), extra);
}
```
**开窗事件的操作人**:
- `operatorType`: `"ADMIN"`(不是 SYSTEM)
- `operatorId`: 调用 reopen 端点的管理员 ID(真实人)
- `operatorName`: 管理员真名
**两个事件的操作人不同的原因**:
- 开窗:用户通过管理后台 HTTP 端点主动触发 → 上下文有 AdminContext → operatorResolver 返回真实人
- 重配:fleet 异步回调 → 无 HTTP 请求上下文 → operatorResolver 返回 SYSTEM
**前端不能混淆**:别以为所有时间线事件的 operatorName 都是真实人,重配这条特殊。
---
## 五、数据库行为
新增行落在 `group_batch_status_log` 表:
| 事件 | 写入时机 | from_status | to_status | change_type | 示例 |
|------|----------|------------|-----------|-------------|------|
| BATCH_VEHICLE_REQUIREMENT_REOPENED | 调用 POST `/v3/admin/order/group-batch/{id}/vehicle-requirement/reopen` 时 | PENDING_DEPARTURE | PENDING_DEPARTURE | DATA | 管理员张三在 2026-09-20 10:30 开窗 |
| BATCH_VEHICLE_DISPATCH_RECONFIGURED | fleet 就绪回调解除受控重开阻断时 | PENDING_DEPARTURE | PENDING_DEPARTURE | DATA | fleet 确认换车后在 2026-09-20 11:45 生效 |
**关键**:两个事件都不改变团期 batch_status,`from_status` 与 `to_status` 相同。
---
## 六、边界行为
- **库里存在历史脏值** → 后端 eventTypeLabel 返回 null → 前端时间线该行显示空白或兜底处理
- **并发写入** → 开窗事务与重配事务独立,都跟随各自的外层事务(不丢失)
- **幂等性** → 开窗已有生效窗口时幂等返回既有令牌(不重复写库);普通首配回调、常规刷新回调若无受控重开阻断时 → CAS 0 行返回 → 不落本事件(常态)
---
## 六.6、修改前后对比
### 接口行为对比
| 行为 | 改前 | 改后 |
|------|------|------|
| 时间线中开窗操作的可见性 | 三个字段存库但页面不展示 | 新增一条 DATA 类事件,时间线上可见 |
| 时间线中重配操作的可见性 | 无记录 | 新增一条 DATA 类事件,标明"车已换、谁开的窗、老计划作废" |
| 事件类型枚举 | 共 N 种 | 新增 2 种,共 N+2 种 |
| 前端事件渲染 | 既有 N 种 event_type 的映射 | 需新增 BATCH_VEHICLE_REQUIREMENT_REOPENED / BATCH_VEHICLE_DISPATCH_RECONFIGURED 两条映射 |
---
## 六.7、影响评估
- **是否破坏向后兼容**: 否。既存接口返回值扩展,老 event_type 不变
- **前端是否必须同步上线**: **是**。不新增渲染映射会导致新增两类事件在时间线上显示为空白
- **前端 workaround 清理点**:
- 若前端已有"event_type 未知时显示原始 code"的兜底逻辑,可临时显示 `BATCH_VEHICLE_REQUIREMENT_REOPENED` 等原始值
- 但正式上线必须使用中文标签,不能长期显示原始值(运营不认识)
---
## 七、不影响范围
- **仅影响**: 管理后台 - 团期详情页 - 状态流水/时间线面板(新增两类事件的渲染)
- **零影响**:
- 团期主状态推进(batch_status 机制不变)
- 用车需求状态机(需求行读写逻辑不变)
- 订单详情、C 端行程页面(无此数据源)
- 旧团期数据(存量团期的时间线不会补充新事件)
---
## 八、测试环境已验证
后端逻辑验证(提交 ab92377c7):
```
POST /v3/admin/order/group-batch/8000001/vehicle-requirement/reopen
请求体: { "scopeGroupCodes": ["GRP001"], "scopeDates": ["2026-09-21"], "reason": "test reason" }
→ 200, group_batch_status_log 新增 1 行 BATCH_VEHICLE_REQUIREMENT_REOPENED ✓
fleet 就绪回调(模拟)
request: {"groupBatchId": 8000001, "requirementId": 7000001, "requirementVersion": 2, "planVersion": "v1"}
→ 200, group_batch_status_log 新增 1 行 BATCH_VEHICLE_DISPATCH_RECONFIGURED ✓
GET /v3/admin/order/group-batch/8000001/status-logs
→ 200, 返回值中 eventTypeName 正确映射(后端已验证) ✓
前端渲染验证:**待前端补充映射后联调**
```
---
## 九、相关历史 PR
| PR | Issue | 说明 | 是否仍有效 |
|-------|-------|------|---------|
| #7986 | #7986 | 受控重配窗口核心机制(团车需求侧) | ✅ 有效 |
| #8039 | #7987 | 本 PR - 补团期时间线留痕 | ✅ 最新 |
---
## 十、相关文档
- **后端枚举定义**: [`hl-order-service-v3/src/main/java/com/hulalv/order/groupbatch/enums/GroupBatchLogEventType.java`](https://git.1814.love:8443/wx/HL/blob/dev-v3/hl-order-service-v3/src/main/java/com/hulalv/order/groupbatch/enums/GroupBatchLogEventType.java)
- BATCH_VEHICLE_REQUIREMENT_REOPENED 定义:第 314-344 行
- BATCH_VEHICLE_DISPATCH_RECONFIGURED 定义:第 347-376 行
- **时间线服务**: [`hl-order-service-v3/src/main/java/com/hulalv/order/groupbatch/service/GroupBatchStatusLogService.java`](https://git.1814.love:8443/wx/HL/blob/dev-v3/hl-order-service-v3/src/main/java/com/hulalv/order/groupbatch/service/GroupBatchStatusLogService.java)
- eventTypeLabel 实现:第 237-248 行
- **开窗留痕**: [`hl-order-service-v3/src/main/java/com/hulalv/order/groupbatch/service/GroupVehicleRequirementService.java`](https://git.1814.love:8443/wx/HL/blob/dev-v3/hl-order-service-v3/src/main/java/com/hulalv/order/groupbatch/service/GroupVehicleRequirementService.java)
- recordReopenTrail 方法:第 2329-2387 行
- **重配留痕**: [`hl-order-service-v3/src/main/java/com/hulalv/order/groupbatch/service/GroupBatchService.java`](https://git.1814.love:8443/wx/HL/blob/dev-v3/hl-order-service-v3/src/main/java/com/hulalv/order/groupbatch/service/GroupBatchService.java)
- recordReconfigureTrail 方法:第 1089-1118 行
---
## 关联 / 联系人
### 链接
- **Issue**: [#7987](https://git.1814.love:8443/wx/HL/issues/7987)
- **PR**: [#8039](https://git.1814.love:8443/wx/HL/pulls/8039)
- **Merge commit**: [ab92377c7](https://git.1814.love:8443/wx/HL/commit/ab92377c7)
### 联系人
- **后端负责人**: @wx
- **前端对接人**: @mmg(hl-ui 仓库,需新增 eventTypeLabel 映射)