文件
hl-api-changelog/changelogs-v2/2026-09/09_7304_团期时间线只读端点status-logs-新增接口-管理后台.md
T
2026-09-09 13:55:49 +08:00

212 行
9.6 KiB
Markdown
原始文件 Blame 文件历史

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
---
schema: "hl-changelog/v2"
ticket: "7304"
title: "新增团期状态流水(时间线)只读端点 GB-ADM-096:GET /v3/admin/order/group-batch/:groupBatchId/status-logs"
consumer: "admin"
author: "jw(GIT)"
change_type: "新增接口"
backend_status: "deployed"
gateway_status: "verified"
frontend_status: "verified"
frontend_owner: "mmg"
frontend_ref: "51ca6946"
target_release: ""
verified_at: "2026-09-09"
status_note: "新增一个只读端点,把此前只写不可读的 group_batch_status_log 暴露给管理端。后端已部署 TEST 并经真实网关实测 AC-1~AC-6(含读回 #7283 的 BATCH_PRODUCT_CANCEL_FAILED 兜底留痕)。前端待接:团期详情加一个「操作记录/时间线」区块——STATUS 类画 fromStatusName→toStatusName 箭头,DATA 类只渲染 content;中文名一律用后端给的 eventTypeName/fromStatusName/toStatusName,不要自建映射表(枚举会继续新增);operatorType 可能是 SYSTEM/MQ,此时 operatorId 为 null、operatorName 是「系统」之类固定文案。权限与团期看板/芯片同码 group-batch:view。"
updated_at: "2026-09-09"
base: "dev-v3"
---
# 团期状态流水(时间线)只读端点
## 一、给前端的一句话
团期的「操作记录 / 时间线」现在有接口了。**一次 GET 拿到该团期从建团到当前的全部事件**,按时间升序,中文名后端已经拼好,前端直接渲染即可。这是个纯新增端点,不动任何既有接口。
## 二、变更接口清单
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|---|---|---|---|---|
| 1 | 团期状态流水(时间线) | GET | `/v3/admin/order/group-batch/:groupBatchId/status-logs` | 新增 | 一次返回该团期全部状态流水,按时间升序;此前该表只写不可读 |
## 三、接口详情
### 1. 团期状态流水(时间线) `GET /v3/admin/order/group-batch/:groupBatchId/status-logs`
**VO**: `GroupBatchStatusLogItemVO`
#### 使用场景
团期详情页的「操作记录 / 时间线」区块。此前这张表只写不读——建团、成团、取消成团、流团、退单审批、转期、导出、合同保险十余条链路都往里写,但页面上一条也看不到。
#### 入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| `groupBatchId` | path | Long | 是 | 雪花 ID,按字符串传 | 团期 ID |
无 query、无 body。**不分页**——单团期的流水条数由其生命周期事件数决定(量级几十条),不是无界列表。
#### 出参
`Result<List<GroupBatchStatusLogItemVO>>`,按 `changedAt` **升序**。
| 字段 | 类型 | 说明 |
|---|---|---|
| `logId` | String | 流水 ID(雪花) |
| `groupBatchId` | String | 团期 ID(雪花) |
| `changeType` | String | `STATUS`=状态流转 / `DATA`=状态内数据变更 |
| `eventType` | String | 事件类型值,如 `BATCH_GROUP` |
| `eventTypeName` | String | 事件类型中文名,如「成团」;枚举外的历史值为 `null` |
| `fromStatus` | String | 变更前团期状态;首次建团为 `null` |
| `fromStatusName` | String | 变更前状态中文名,如「招募中」 |
| `toStatus` | String | 变更后团期状态 |
| `toStatusName` | String | 变更后状态中文名,如「资源准备中」 |
| `content` | String | 展示文本,后端已拼好,前端直接渲染 |
| `reason` | String | 理由 / 备注,可为 `null` |
| `operatorType` | String | `USER` / `ADMIN` / `SYSTEM` / `MQ` |
| `operatorId` | String | 操作人 ID(雪花);`SYSTEM` / `MQ` 场景为 `null` |
| `operatorName` | String | 操作人姓名快照;系统场景为「系统」之类固定文案 |
| `extra` | Object | 附加快照,**已解析成对象**(不是转义 JSON 字符串);无附加数据时为 `null` |
| `changedAt` | String | `yyyy-MM-dd HH:mm:ss` |
#### 请求示例
```http
GET /v3/admin/order/group-batch/2097500233511362561/status-logs
Authorization: Bearer <admin token>
```
#### 响应示例
```json
{
"code": 200,
"message": "成功",
"data": [
{
"logId": "2097500233519751171",
"groupBatchId": "2097500233511362561",
"changeType": "STATUS",
"eventType": "BATCH_CREATE",
"eventTypeName": "建团",
"fromStatus": null,
"fromStatusName": null,
"toStatus": "RECRUITING",
"toStatusName": "招募中",
"content": "建团:秋日川西小环线",
"reason": null,
"operatorType": "ADMIN",
"operatorId": "1001",
"operatorName": "admin",
"extra": null,
"changedAt": "2026-09-09 09:40:00"
},
{
"logId": "2097501083860418561",
"groupBatchId": "2097500233511362561",
"changeType": "DATA",
"eventType": "BATCH_CONTRACT_ISSUE",
"eventTypeName": "手动开合同/保险",
"fromStatus": "RESOURCE_PREPARING",
"fromStatusName": "资源准备中",
"toStatus": "RESOURCE_PREPARING",
"toStatusName": "资源准备中",
"content": "手动开合同 · 张三(HL20260909094000073)",
"reason": null,
"operatorType": "ADMIN",
"operatorId": "1001",
"operatorName": "admin",
"extra": {
"orderId": "2097500234186702849",
"orderNo": "HL20260909094000073",
"kind": "合同",
"schemeName": "标准国内电子签约方案"
},
"changedAt": "2026-09-09 09:43:23"
}
]
}
```
#### 空数据 / 降级响应
团期不存在、或该团期尚无任何流水,一律返回空列表,**不报错**:
```json
{ "code": 200, "message": "成功", "data": [] }
```
> 注意这一点与团期详情不同:`GET /v3/admin/order/group-batch/:groupBatchId` 对不存在的团期抛 `589500`,本端点回空数组。原因是这张表是 append-only 存证表,「查不到」在读语义上就等于「空时间线」。
单条记录的降级:`extra` 为空 / 空串 / 非法 JSON 时该条 `extra` 回 `null`,其余字段正常;事件类型或状态是枚举外的历史值时对应 `*Name` 回 `null`、code 原样返回。**一条脏数据不会让整条时间线查不出来。**
#### 错误响应
当前角色没有 `group-batch:view` 权限(失败关闭,与团期看板 / 芯片明细同码):
```json
{ "code": 589507, "message": "无操作权限(非团期管理员 / 非本定制师名下)", "data": null, "success": false }
```
缺少或无效的 token 由网关拦截,返回 `401`。本端点不产生其它业务错误码。
#### 业务边界
- 只读端点,不改任何数据。
- 返回全量,不分页、不截断。
- 中文名由后端给:`eventTypeName` / `fromStatusName` / `toStatusName`;枚举外的历史值为 `null`。
- 团期不存在与无流水不区分,都回空数组。
- 权限码 `group-batch:view`,与团期看板、芯片逐户明细一致。
## 四、契约约束与正确调用方式
1. **中文名一律用后端返回的字段渲染,不要在前端自建 code→中文 映射表。** 团期事件类型会持续新增(#7283 刚加过 `BATCH_PRODUCT_CANCEL_FAILED`),后端给名字前端就零改动;自建映射表会漏。
2. **按 `changeType` 分叉渲染**:`STATUS` 画 `fromStatusName → toStatusName` 箭头;`DATA` 的 `fromStatus === toStatus`,只渲染 `content`。
3. **`operatorType` 可能是 `SYSTEM` / `MQ`**(AFTER_COMMIT 或异步链路写入),此时 `operatorId` 为 `null`,`operatorName` 是「系统」之类的固定文案,照常渲染即可,别按「一定有操作人」写死。
4. **`extra` 是对象或 `null`**,不是字符串,不要再 `JSON.parse`。不同事件的 `extra` 结构不同,按需取键、缺键要兜住。
5. **雪花 ID 一律按字符串处理**(`logId` / `groupBatchId` / `operatorId` 都以字符串下发)。
6. 名字字段可能为 `null`(库里存的是当前枚举外的历史值),此时前端兜底显示对应的 code。
## 六、边界行为
| 场景 | 行为 |
|---|---|
| 团期不存在 | `code=200`,`data=[]` |
| 团期存在但无流水 | `code=200`,`data=[]` |
| `extra` 为空 / 空串 / 非法 JSON | 该条 `extra` 回 `null`,其余字段正常,不影响整条时间线 |
| 事件类型 / 状态是枚举外的历史值 | 对应 `*Name` 回 `null`,`eventType` / `fromStatus` / `toStatus` 原样返回 |
| 无 `group-batch:view` 权限 | `589507` |
## 七、不影响范围
- 不改任何既有接口的路径、入参、出参、错误码。
- 不改团期状态流水的**写入**侧:十余条写入链路一行未动。
- 无表变更、无 Flyway、无数据迁移。
- 网关路由不新增(`/v3/admin/**` 已覆盖)。
- 只滚 `hl-order-service-v3` 一个服务。
## 八、测试环境已验证
TEST(`api.test.1814.love`)真实网关逐条取证:
| 验收项 | 实测 |
|---|---|
| 全量返回、按 `changedAt` 升序、条数与 `SELECT COUNT(*)` 一致 | ✅ |
| `STATUS` 与 `DATA` 两类各有实例,`DATA` 类 `fromStatus == toStatus` | ✅ |
| 能读回 #7283 的 `BATCH_PRODUCT_CANCEL_FAILED`,content 为「班期置不可售失败,请到产品后台手动取消该班期(班期 ID:…)」 | ✅ 本端点存在的直接理由 |
| `extra` 为结构化对象;空值 / 脏值回 `null` 不报错 | ✅ |
| 团期不存在 → `code=200, data=[]`(对照:团期详情同 id 抛 589500) | ✅ |
| `CUSTOMIZER` 角色 → `589507`,与 `chips/contract` 逐角色一致 | ✅ |
## 十、相关文档
- 实施单编号:GB-ADM-096(新增)
- 前序 #7283:本端点是它「同步失败只记时间线让运营看见」那条兜底的读回出口,解开其 AC-9 的阻塞
## 关联 / 联系人
- 工单:https://git.1814.love:8443/wx/HL/issues/7304
- PR:https://git.1814.love:8443/wx/HL/pulls/7359
- 后端:jw;前端:mmg