--- schema: "hl-changelog/v2" ticket: "8271" title: "团期看板与详情按六节点展示:分页 / 详情 / 看板行新增 stage 与出行子状态,统计条与 opsStage 改七桶(旧八桶过渡期兼容),核团 / 验团用语统一为核单 / 结算" consumer: "admin" author: "jw(GIT)" change_type: "修改接口" backend_status: "deployed" gateway_status: "verified" frontend_status: "pending" frontend_owner: "" frontend_ref: "" target_release: "" verified_at: "2026-09-24" status_note: "六节点定案(SRS §0.27.1 / §0.27.4):持久九态 batchStatus 不动,服务端派生节点 stage(RECRUIT 招募 / CONFIGURE 配置 / CONFIRM 确认 / TRIP 出行 / REVIEW 核单 / SETTLE 结算 / DISBANDED 已流团)与出行子状态 tripSubStatus(待出发 / 出行中 / 已返团),只供展示。团期分页、详情、看板行新增 stage / stageName / tripSubStatus / tripSubStatusName 四字段;既有字段 opsStage 的取值由八桶改为七桶(与 stage 逐字同值);统计条 buckets 固定 13 键 = 七桶 + 6 个旧八桶别名键(别名键不计入 total);opsStage 筛选接受七桶,旧八桶 code 过渡期按原口径兼容;导出 CSV「状态」列改为节点名。PR #8303 补充:面向用户的核团 / 验团用语统一为核单 / 结算(6 个错误码文案、时间线事件中文标签、核单状态 CHECKED 中文名),码值与存储值不变。前端需把看板页签与统计条切到七桶、详情页按 stage / tripSubStatus 展示节点;旧八桶别名在前端切换完成前保留。" updated_at: "2026-09-24" base: "dev-v3" --- # 团期看板: 按六节点展示,统计条与筛选改七桶(管理后台) > **服务**: hl-order-service-v3(端口 8086/8186) > **PR**: #8276(代码)、#8279(文档)、#8303(核单 / 结算用语) > **Issue**: #8271 > **日期**: 2026-09-24 > **影响范围**: 管理后台团期看板(页签、统计条、列表行、导出)、团期详情头部节点展示、团期时间线与核单 / 结算相关报错文案 --- ## ⚠️ 关键变化 1. **`opsStage` 响应取值变了**:以前是八桶(`FORMED` / `PENDING_TRIP` / `TRAVELLING` / `TRIP_FINISHED` / `AUDITING` / `CHECKED` …),现在只输出七桶(`CONFIGURE` / `CONFIRM` / `TRIP` / `REVIEW` / `SETTLE` …),且与新字段 `stage` 逐字同值。按旧值做过 `switch` 的前端代码会落到默认分支。 2. **原「已成团」一桶拆成两桶**:`RESOURCE_PREPARING` → 配置(`CONFIGURE`),`MATERIAL_PREPARING` → 确认(`CONFIRM`);原「待出行 / 出行中 / 出行完毕」三桶合成一个「出行」(`TRIP`),细分看 `tripSubStatus`。 3. **统计条 `buckets` 从 8 键变 13 键**:七桶在前、6 个旧别名键在后。`total` 只等于七桶之和,**不要再对 `buckets` 整体求和**(会重复计数)。 4. **旧入参仍然能用**:页签继续传旧八桶 code 给 `opsStage` 筛选,结果与改前逐条一致(按原口径展开);统计条的旧键名计数也照旧给。 5. **用语**:「核团中 / 已验团」改为「核单 / 结算」,涉及 6 个错误码文案、时间线事件中文名、核单状态 `CHECKED` 的中文名;码值与存储值一律不变。 --- ## 一、背景 团期六节点定案:看板与详情按「招募 → 配置 → 确认 → 出行 → 核单 → 结算」展示,另有分叉终态「已流团」。持久九态 `batchStatus` 不动、不新增持久列,节点与出行子状态由服务端唯一派生,**只供展示,不承担业务判断**——按钮可用性、权限仍以 `batchStatus` 与各就绪位为准。 | 节点 `stage` | `stageName` | 覆盖的 `batchStatus` | 说明 | |---|---|---|---| | `RECRUIT` | 招募 | `RECRUITING` | 未建团行(产品侧有班期、订单侧尚无团期)也恒为 `RECRUIT` | | `CONFIGURE` | 配置 | `RESOURCE_PREPARING` | 配房 / 车 / 导游领队 / 摄影与物资,确认前可改 | | `CONFIRM` | 确认 | `MATERIAL_PREPARING` | 人工确认后配置锁定,逐户出合同与保险 | | `TRIP` | 出行 | `PENDING_DEPARTURE`、`TRAVELLING`、`TRIP_FINISHED` | 复合节点,细分见 `tripSubStatus` | | `REVIEW` | 核单 | `REVIEWING` | 原「核团中」 | | `SETTLE` | 结算 | `SETTLED` | 原「已验团」 | | `DISBANDED` | 已流团 | `CANCELLED` | 分叉终态 | --- ## 二、变更接口清单 | # | 接口 | 方法 | 路径 | 变更类型 | 说明 | |---|------|------|------|----------|------| | 1 | 团期分页列表(GB-ADM-001) | GET | `/v3/admin/order/group-batch` | 出参新增字段 + 出参取值变化 + 入参取值扩展 | 新增四字段;`opsStage` 出参改七桶;`opsStage` 筛选接受七桶并兼容旧八桶 | | 2 | 团期详情(GB-ADM-002) | GET | `/v3/admin/order/group-batch/{groupBatchId}` | 出参新增字段 + 出参取值变化 | 新增四字段;`opsStage` 改七桶 | | 3 | 团期看板列表 | GET | `/v3/admin/order/group-batch/board` | 出参新增字段 + 出参取值变化 | 命中 / 未命中 / 孤儿三类行均带四字段;`opsStage` 改七桶 | | 4 | 团期看板统计条(GB-ADM-009) | GET | `/v3/admin/order/group-batch/summary` | 出参取值变化 | `buckets` 13 键;`total` = 七桶之和 | | 5 | 导出团期列表 CSV(GB-ADM-008) | GET | `/v3/admin/order/group-batch/export` | 入参取值扩展 + 导出内容变化 | `opsStage` 同分页口径;「状态」列改为节点名 | | 6 | 团期状态流水(GB-ADM-096) | GET | `/v3/admin/order/group-batch/{groupBatchId}/status-logs` | 出参取值变化(文案) | 5 个核团 / 验团事件的 `eventTypeName` 改为核单 / 结算用语 | 路径、HTTP 方法、权限码、信封结构均不变;网关无改动。 --- ## 三、接口详情 ### 1. 团期分页列表 `GET /v3/admin/order/group-batch` **VO**: `GroupBatchListReqVO` → `PageResult` #### 使用场景 团期看板主列表(按页签筛选)。页签既可以传七桶 code,也可以继续传旧八桶 code。 #### 入参 | 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | |------|------|------|------|------|------| | opsStage | Query | String | 否 | 七桶或旧八桶 code;空白 / 非法值忽略 | **本次改取值**:七桶 `RECRUIT` / `CONFIGURE` / `CONFIRM` / `TRIP` / `REVIEW` / `SETTLE` / `DISBANDED`;旧八桶 `FORMED` / `PENDING_TRIP` / `TRAVELLING` / `TRIP_FINISHED` / `AUDITING` / `CHECKED` 过渡期仍按原口径展开 | | scope | Query | String | 否 | `ONGOING` / `FINISHED` / `ALL` | 班期范围;与 `opsStage` 取交集(不变) | | productId | Query | Long | 否 | - | 按产品筛选(不变) | | batchStatus | Query | String | 否 | 九态 code | 精确九态筛选(不变) | | month | Query | String | 否 | `yyyy-MM` | 出发月份(不变) | | keyword | Query | String | 否 | - | 班期编号 / 名称模糊(不变) | | pageNo | Query | Integer | 否 | 默认 1 | 页码(不变) | | pageSize | Query | Integer | 否 | 默认 20,最大 100 | 每页条数(不变) | 其余既有筛选参数(`deadlineFrom` / `deadlineTo` / `departFrom` / `departTo` / `sortBy` / `sortOrder`)不变。 #### 出参 | 字段 | 类型 | 说明 | |------|------|------| | records[].batchStatus | String | 持久九态,**业务判断用这个**(不变) | | records[].batchStatusName | String | 九态中文名(不变,如「资源准备中」「出行完毕」) | | records[].stage | String | **新增**。节点 code,取值见「一、背景」七个 | | records[].stageName | String | **新增**。节点中文名,与 `stage` 同生同灭 | | records[].tripSubStatus | String | **新增**。出行子状态 `PENDING_DEPARTURE` / `TRAVELLING` / `TRIP_FINISHED`;仅 `stage = TRIP` 时有值,其余为 null | | records[].tripSubStatusName | String | **新增**。待出发 / 出行中 / 已返团;与 `tripSubStatus` 同生同灭 | | records[].opsStage | String | **取值改变**:与 `stage` 逐字同值(七桶),旧八桶值不再输出 | | records[].opsStageName | String | **取值改变**:与 `stageName` 同值 | | total | Long | 命中总数(不变) | 其余分页项字段不变。 #### 请求示例 ```http GET /v3/admin/order/group-batch?opsStage=TRIP&scope=ALL&pageNo=1&pageSize=20 HTTP/1.1 Host: api.test.1814.love:9443 Authorization: Bearer ``` 无请求体。 #### 响应示例 ```json { "code": 200, "message": "成功", "data": { "total": 1, "records": [ { "groupBatchId": "2099750660965584898", "batchNo": "GB26100101", "batchStatus": "PENDING_DEPARTURE", "batchStatusName": "待出发", "stage": "TRIP", "stageName": "出行", "tripSubStatus": "PENDING_DEPARTURE", "tripSubStatusName": "待出发", "opsStage": "TRIP", "opsStageName": "出行" } ] }, "success": true } ``` #### 空数据 / 降级响应 无命中返回空页;`batchStatus` 为 null 或不在九态内的历史脏数据行,四个新字段与 `opsStage` / `opsStageName` 同为 null,不抛错: ```json { "code": 200, "data": { "total": 0, "records": [] }, "success": true } ``` #### 错误响应 `opsStage` 传非法值不报错(忽略该筛选并记 warn);本接口错误形态沿用既有,如无列表权限: ```json { "code": 589507, "message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)", "success": false, "data": null } ``` #### 业务边界 - 七桶与旧别名 code 不相交,先按七桶解析、未命中再按别名解析。 - 旧别名按**原口径**展开,不放大为新节点:`PENDING_TRIP` 仍只筛待出发,`FORMED` = 配置 + 确认。 - 服务端严格取 `scope ∩ opsStage`:`REVIEW` / `SETTLE` 及 `TRIP` 里已返团的那部分返团日必然已过,默认 `ONGOING` 会过滤掉,点这些页签需把 `scope` 切到 `ALL`。 - 四个新字段是纯内存映射,整页无额外查询。 --- ### 2. 团期详情 `GET /v3/admin/order/group-batch/{groupBatchId}` **VO**: `GroupBatchDetailRespVO` #### 使用场景 团期详情页头部展示当前节点(如「出行 · 待出发」)。 #### 入参 | 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | |------|------|------|------|------|------| | groupBatchId | Path | Long | ✅ | 团期主键 | 不变 | #### 出参 | 字段 | 类型 | 说明 | |------|------|------| | batchStatus | String | 持久九态(不变) | | batchStatusName | String | 九态中文名(不变) | | stage | String | **新增**。节点 code | | stageName | String | **新增**。节点中文名 | | tripSubStatus | String | **新增**。仅 `stage = TRIP` 时有值 | | tripSubStatusName | String | **新增**。与 `tripSubStatus` 同生同灭 | | opsStage | String | **取值改变**:七桶,与 `stage` 同值 | | opsStageName | String | **取值改变**:与 `stageName` 同值 | 其余详情字段不变。 #### 请求示例 ```http GET /v3/admin/order/group-batch/2097250563497385985 HTTP/1.1 Host: api.test.1814.love:9443 Authorization: Bearer ``` 无请求体。 #### 响应示例 ```json { "code": 200, "message": "成功", "data": { "groupBatchId": "2097250563497385985", "batchStatus": "MATERIAL_PREPARING", "batchStatusName": "物料准备中", "stage": "CONFIRM", "stageName": "确认", "tripSubStatus": null, "tripSubStatusName": null, "opsStage": "CONFIRM", "opsStageName": "确认" }, "success": true } ``` #### 空数据 / 降级响应 非出行节点 `tripSubStatus` / `tripSubStatusName` 为 null;脏数据行四字段同为 null: ```json { "code": 200, "data": { "batchStatus": null, "stage": null, "stageName": null, "tripSubStatus": null, "tripSubStatusName": null, "opsStage": null, "opsStageName": null }, "success": true } ``` #### 错误响应 ```json { "code": 589500, "message": "团期不存在", "success": false, "data": null } ``` #### 业务边界 - 子状态中文名「已返团」与九态 `batchStatusName`「出行完毕」不同名,两套文案各自展示,不要互相替换。 - 前端不得用 `stage` / `tripSubStatus` 判断按钮可用性或权限。 --- ### 3. 团期看板列表 `GET /v3/admin/order/group-batch/board` **VO**: `List` #### 使用场景 按产品展示全部班期(含未建团行与孤儿行)的看板卡片列表。 #### 入参 | 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | |------|------|------|------|------|------| | productId | Query | Long | ✅ | - | 产品 ID(不变) | | scope | Query | String | 否 | `ONGOING` / `FINISHED` / `ALL`,缺省 `ALL` | 班期范围(不变) | #### 出参 | 字段 | 类型 | 说明 | |------|------|------| | [].batchStatus | String | 持久九态(不变);未建团行按 `RECRUITING` | | [].stage | String | **新增**。节点 code;未建团行恒 `RECRUIT` | | [].stageName | String | **新增**。节点中文名 | | [].tripSubStatus | String | **新增**。仅 `stage = TRIP` 时有值 | | [].tripSubStatusName | String | **新增** | | [].opsStage | String | **取值改变**:七桶,与 `stage` 同值 | | [].opsStageName | String | **取值改变**:与 `stageName` 同值 | #### 请求示例 ```http GET /v3/admin/order/group-batch/board?productId=100001&scope=ALL HTTP/1.1 Host: api.test.1814.love:9443 Authorization: Bearer ``` 无请求体。 #### 响应示例 ```json { "code": 200, "message": "成功", "data": [ { "groupBatchId": "2097250563497385985", "batchStatus": "TRAVELLING", "stage": "TRIP", "stageName": "出行", "tripSubStatus": "TRAVELLING", "tripSubStatusName": "出行中", "opsStage": "TRIP", "opsStageName": "出行" }, { "productBatchId": "2097250420299530242", "batchStatus": "RECRUITING", "stage": "RECRUIT", "stageName": "招募", "tripSubStatus": null, "tripSubStatusName": null, "opsStage": "RECRUIT", "opsStageName": "招募" } ], "success": true } ``` #### 空数据 / 降级响应 产品无班期时返回空数组: ```json { "code": 200, "data": [], "success": true } ``` #### 错误响应 ```json { "code": 589507, "message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)", "success": false, "data": null } ``` #### 业务边界 - 命中 / 未命中 / 孤儿三类行统一带四个新字段。 - 行集合、排序、其余字段均不变。 --- ### 4. 团期看板统计条 `GET /v3/admin/order/group-batch/summary` **VO**: `GroupBatchSummaryVO` #### 使用场景 看板顶部各页签的计数。 #### 入参 | 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | |------|------|------|------|------|------| | productId | Query | Long | 否 | - | 不变 | | month | Query | String | 否 | `yyyy-MM` | 不变 | | keyword | Query | String | 否 | - | 不变 | | scope | Query | String | 否 | `ONGOING` / `FINISHED` / `ALL` | 不变 | 本接口不接受 `opsStage`(它的作用正是给出各桶数量)。 #### 出参 | 字段 | 类型 | 说明 | |------|------|------| | total | Integer | **口径改变**:= 七桶之和(旧别名键不计入) | | buckets | Map<String, Integer> | **键集合改变**:固定 13 键,无命中为 0;前 7 键为七桶,后 6 键为旧八桶别名 | | subOrderCount | Integer | 命中团期的活跃子订单合计(不变) | | effectiveScope | String | 实际生效的班期范围(不变) | | filteredOutCount | Integer | 被范围过滤掉的团期数(不变) | `buckets` 13 键口径: | 键 | 计数口径 | 计入 `total` | |---|---|---| | `RECRUIT` / `CONFIGURE` / `CONFIRM` / `TRIP` / `REVIEW` / `SETTLE` / `DISBANDED` | 七桶;`TRIP` = 待出发 + 出行中 + 已返团 | ✅ | | `FORMED` | 旧别名 = `RESOURCE_PREPARING` + `MATERIAL_PREPARING` | ❌ | | `PENDING_TRIP` | 旧别名 = `PENDING_DEPARTURE` | ❌ | | `TRAVELLING` | 旧别名 = `TRAVELLING` | ❌ | | `TRIP_FINISHED` | 旧别名 = `TRIP_FINISHED` | ❌ | | `AUDITING` | 旧别名 = `REVIEWING` | ❌ | | `CHECKED` | 旧别名 = `SETTLED` | ❌ | #### 请求示例 ```http GET /v3/admin/order/group-batch/summary?scope=ALL HTTP/1.1 Host: api.test.1814.love:9443 Authorization: Bearer ``` 无请求体。 #### 响应示例 ```json { "code": 200, "message": "成功", "data": { "total": 12, "buckets": { "RECRUIT": 3, "CONFIGURE": 2, "CONFIRM": 1, "TRIP": 4, "REVIEW": 1, "SETTLE": 0, "DISBANDED": 1, "FORMED": 3, "PENDING_TRIP": 2, "TRAVELLING": 1, "TRIP_FINISHED": 1, "AUDITING": 1, "CHECKED": 0 }, "subOrderCount": 57, "effectiveScope": "ALL", "filteredOutCount": 0 }, "success": true } ``` #### 空数据 / 降级响应 无命中时 13 键全部为 0: ```json { "code": 200, "data": { "total": 0, "buckets": { "RECRUIT": 0, "CONFIGURE": 0, "CONFIRM": 0, "TRIP": 0, "REVIEW": 0, "SETTLE": 0, "DISBANDED": 0, "FORMED": 0, "PENDING_TRIP": 0, "TRAVELLING": 0, "TRIP_FINISHED": 0, "AUDITING": 0, "CHECKED": 0 }, "subOrderCount": 0 }, "success": true } ``` #### 错误响应 ```json { "code": 589507, "message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)", "success": false, "data": null } ``` #### 业务边界 - 按键名读取,不要依赖 Map 下标;也不要对 `buckets` 整体求和。 - `RECRUIT` / `DISBANDED` 新旧同名同义,不重复出现。 - 状态不在九态内的行被排除,不计入任何桶。 --- ### 5. 导出团期列表 CSV `GET /v3/admin/order/group-batch/export` **VO**: `text/csv` 附件(非 `Result` 信封) #### 使用场景 看板「导出」按钮,按当前筛选导出 CSV。 #### 入参 | 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | |------|------|------|------|------|------| | opsStage | Query | String | 否 | 同分页口径 | **本次改取值**:七桶或旧八桶 code | | productId | Query | Long | 否 | - | 不变 | | month | Query | String | 否 | `yyyy-MM` | 不变 | | keyword | Query | String | 否 | - | 不变 | | scope | Query | String | 否 | `ONGOING` / `FINISHED` / `ALL` | 不变 | #### 出参 | 字段 | 类型 | 说明 | |------|------|------| | 状态(CSV 第 8 列) | String | **内容改变**:由旧八桶中文名改为节点名;出行节点拼子状态,如「出行·待出发」「出行·出行中」「出行·已返团」 | 列名、列序(固定 10 列)与单次 2000 行上限不变。 #### 请求示例 ```http GET /v3/admin/order/group-batch/export?opsStage=CONFIGURE&scope=ALL HTTP/1.1 Host: api.test.1814.love:9443 Authorization: Bearer ``` 无请求体。 #### 响应示例 响应为 CSV 附件;「状态」列示例: ```json { "Content-Type": "text/csv; charset=utf-8", "header": "团期号,期号,日期,出团日,满团名额,已售,剩余,状态,子订单数,整团应收", "状态列取值示例": ["招募", "配置", "确认", "出行·待出发", "出行·出行中", "出行·已返团", "核单", "结算", "已流团"] } ``` #### 空数据 / 降级响应 无命中时只输出表头一行(不变): ```json { "header": "团期号,期号,日期,出团日,满团名额,已售,剩余,状态,子订单数,整团应收", "rows": 0 } ``` #### 错误响应 ```json { "code": 589507, "message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)", "success": false, "data": null } ``` #### 业务边界 - 按「状态」列中文做过解析的下游需同步:旧值「已成团 / 待出行 / 核团中 / 已验团」不再出现。 - 筛选口径与分页接口共用同一展开逻辑。 --- ### 6. 团期状态流水 `GET /v3/admin/order/group-batch/{groupBatchId}/status-logs` **VO**: `List` #### 使用场景 团期详情「操作记录 / 时间线」。本次只改 5 个事件的中文标签(PR #8303)。 #### 入参 | 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | |------|------|------|------|------|------| | groupBatchId | Path | Long | ✅ | 团期主键 | 不变 | #### 出参 | 字段 | 类型 | 说明 | |------|------|------| | [].eventType | String | 事件类型值(**不变**) | | [].eventTypeName | String | **取值改变**:见下表;标签在读取时渲染,存量行一并显示新标签 | | [].content | String | 展示文本;本次之后新写入的核单 / 结算相关流水改用新用语,存量行原样 | | eventType | 改前 eventTypeName | 改后 eventTypeName | |---|---|---| | `BATCH_TRIP_END` | 返团核团 | 发起核单 | | `BATCH_SETTLE` | 验团结算 | 结算 | | `BATCH_AUDIT_ALLOCATE` | 核团提交核算 | 核单提交核算 | | `BATCH_AUDIT_REALLOCATE` | 核团重新核算 | 核单重新核算 | | `BATCH_AUDIT_PRICE_OVERRIDE` | 核团改价 | 核单改价 | #### 请求示例 ```http GET /v3/admin/order/group-batch/2097250563497385985/status-logs HTTP/1.1 Host: api.test.1814.love:9443 Authorization: Bearer ``` 无请求体。 #### 响应示例 ```json { "code": 200, "message": "成功", "data": [ { "eventType": "BATCH_SETTLE", "eventTypeName": "结算", "fromStatus": "REVIEWING", "fromStatusName": "核单中", "toStatus": "SETTLED", "toStatusName": "已结算", "content": "结算归档,团期结束", "operatorType": "ADMIN" } ], "success": true } ``` #### 空数据 / 降级响应 无流水返回空数组;库里是枚举外历史值时 `eventTypeName` 为 null(不变): ```json { "code": 200, "data": [], "success": true } ``` #### 错误响应 ```json { "code": 589500, "message": "团期不存在", "success": false, "data": null } ``` #### 业务边界 - 按 `eventType` 做分支的前端不受影响;按中文标签匹配的需改。 - `fromStatusName` / `toStatusName`(九态中文名「核单中」「已结算」)不变。 --- ## 四、契约约束与正确调用方式 ### ✅ 正确 / ❌ 错误用法对照 | 场景 | 用法 | |------|------| | ✅ 看板页签筛选(新) | `opsStage=CONFIGURE` / `opsStage=TRIP` | | ✅ 看板页签筛选(过渡期旧值) | `opsStage=FORMED`,结果 = 配置 + 确认,与改前一致 | | ✅ 页签计数 | 读 `buckets.CONFIGURE`、`buckets.TRIP` 等七桶键;总数读 `total` | | ❌ 总数自己求和 | `Object.values(buckets).reduce(...)` → 七桶与别名重复,结果偏大 | | ❌ 用节点判按钮 | `if (stage === 'CONFIGURE') showConfirmButton()` → 应读 `batchStatus` 与就绪位 | | ❌ 按旧 `opsStage` 值分支 | `case 'FORMED':` → 响应已不再输出旧值 | ### 核单 / 结算用语:错误码文案变化(PR #8303,码值不变) | code | 改前 message | 改后 message | |---|---|---| | 589555 | 该团期已验团归档,不可重复验团 | 该团期已结算归档,不可重复结算 | | 589565 | 团期已验团归档,如需重新核单请先做验团反确认 | 团期已结算归档,如需重新核单请先做结算反确认 | | 589567 | 该团期尚未进入核团:{0} | 该团期尚未进入整团核单:{0} | | 589568 | 核团当前状态不允许该操作:{0} | 整团核单当前状态不允许该操作:{0} | | 589572 | 所选订单不属于本团期的核团范围 | 所选订单不属于本团期的整团核单范围 | | 589573 | 核团数据已被他人修改(当前版本 {0},提交版本 {1}),请刷新后重试 | 整团核单数据已被他人修改(当前版本 {0},提交版本 {1}),请刷新后重试 | 核单状态枚举 `CHECKED` 的中文名由「已验团」改为「已结算」(存储值不变);前端按 code 判断即可,按中文匹配的需改。 --- ## 六、边界行为 - 未登录 → 401(网关拦截)。 - `batchStatus` 为 null 或不在九态内的脏数据行:四个新字段与 `opsStage` / `opsStageName` 同为 null,不抛错。 - `opsStage` 空白或非法值:忽略该筛选并记 warn,不报错。 - 未建团行恒为 `RECRUIT` / 招募。 - 旧八桶别名(筛选入参 + 统计条 6 键)在前端切到七桶之前保留,删除时另发契约变更。 --- ## 六.5、枚举 / 数据字典 ### stage / opsStage(GroupBatchStageBuckets.Bucket) **所属字段**: `stage`、`opsStage`(响应)、`opsStage`(筛选入参)、`buckets` 前 7 键 | **类型**: `String` | 值 | 中文 | 说明 | |----|------|------| | `RECRUIT` | 招募 | ← `RECRUITING` | | `CONFIGURE` | 配置 | ← `RESOURCE_PREPARING` | | `CONFIRM` | 确认 | ← `MATERIAL_PREPARING` | | `TRIP` | 出行 | ← `PENDING_DEPARTURE` / `TRAVELLING` / `TRIP_FINISHED` | | `REVIEW` | 核单 | ← `REVIEWING` | | `SETTLE` | 结算 | ← `SETTLED` | | `DISBANDED` | 已流团 | ← `CANCELLED` | ### tripSubStatus(GroupBatchStageBuckets.TripSubStatus) **所属字段**: `tripSubStatus` | **类型**: `String` | 值 | 中文 | 说明 | |----|------|------| | `PENDING_DEPARTURE` | 待出发 | 仍可发起流团 | | `TRAVELLING` | 出行中 | 出发日起 | | `TRIP_FINISHED` | 已返团 | 返团日次日起;首次录共享成本即进入核单 | ### 旧八桶别名(GroupBatchStageBuckets.LegacyBucket,过渡期) **所属字段**: `opsStage`(筛选入参)、`buckets` 后 6 键 | **类型**: `String` | 值 | 中文 | 说明 | |----|------|------| | `FORMED` | 已成团 | = `RESOURCE_PREPARING` + `MATERIAL_PREPARING` | | `PENDING_TRIP` | 待出行 | = `PENDING_DEPARTURE` | | `TRAVELLING` | 出行中 | = `TRAVELLING` | | `TRIP_FINISHED` | 出行完毕 | = `TRIP_FINISHED` | | `AUDITING` | 核团中 | = `REVIEWING` | | `CHECKED` | 已验团 | = `SETTLED` | --- ## 六.6、修改前后对比 ### 字段级对比 | 字段 | 改前 | 改后 | |------|------|------| | `stage` / `stageName` | 无 | 新增,七个节点 | | `tripSubStatus` / `tripSubStatusName` | 无 | 新增,仅出行节点有值 | | `opsStage`(响应) | 八桶:`RECRUIT` / `FORMED` / `PENDING_TRIP` / `TRAVELLING` / `TRIP_FINISHED` / `AUDITING` / `CHECKED` / `DISBANDED` | 七桶,与 `stage` 同值 | | `opsStageName`(响应) | 招募中 / 已成团 / 待出行 / 出行中 / 出行完毕 / 核团中 / 已验团 / 已流团 | 招募 / 配置 / 确认 / 出行 / 核单 / 结算 / 已流团 | | `buckets`(统计条) | 8 键,`total` = 8 桶之和 | 13 键(七桶 + 6 别名),`total` = 七桶之和 | | 导出「状态」列 | 旧八桶中文名 | 节点名,出行节点拼子状态 | | `eventTypeName`(5 个核单 / 结算事件) | 核团 / 验团用语 | 核单 / 结算用语 | | 6 个错误码 message | 核团 / 验团用语 | 核单 / 结算用语(见「四」) | ### 行为级对比 | 行为 | 改前 | 改后 | |------|------|------| | `opsStage=FORMED` 筛选 | 配置 + 确认 | 不变(别名按原口径) | | `opsStage=TRIP` 筛选 | 非旧八桶 code,按非法值忽略(不筛) | 筛待出发 + 出行中 + 已返团 | | `opsStage=CONFIGURE` / `CONFIRM` / `REVIEW` / `SETTLE` | 非法值被忽略 | 按新节点筛选 | ⚠️ 注意 `TRIP` 与旧 `TRIP_FINISHED` 的区别:旧八桶里「出行完毕」的 code 是 `TRIP_FINISHED`,不是 `TRIP`;页签若传的是 `TRIP_FINISHED`,行为不变。 ## 六.7、影响评估 - **是否破坏向后兼容**: 部分。筛选入参与统计条旧键完全兼容;响应字段 `opsStage` / `opsStageName` 的取值改变,读这两个字段做分支或展示的代码会受影响。 - **前端是否必须同步上线**: 否。旧页签传旧 code、读旧键仍然工作;要展示六节点需改读 `stage` / `tripSubStatus` 与七桶键。 - **前端 workaround 清理点**: 若前端曾自己把九态折叠成阶段,可改为直接读 `stage`;切到七桶后告知后端删除旧八桶别名。 --- ## 七、不影响范围 - **仅影响**: 上述 6 个查询 / 导出接口的节点相关字段与文案,及 6 个核单 / 结算错误码的 message。 - **零影响**: - 持久九态 `batchStatus` 及其中文名 `batchStatusName`(「核单中」「已结算」原本就是这两个字) - 所有写接口的状态流转与业务闸(节点只供展示) - 错误码 code 值、枚举存储值、时间线 `eventType` 值 - 权限码、路径、信封结构、网关配置 - 小程序端 --- ## 八、测试环境已验证 部署 `dev-v3` @ `b212cb708`,2026-09-23 17:44–17:48,`api.test.1814.love:9443`。 | 验证项 | 结果 | |---|---| | 分页(`pageSize=100`)与看板行(187 行)字段 | 均带 `stage` / `stageName` / `tripSubStatus` / `tripSubStatusName` 四个新字段,且 `opsStage == stage` ✓ | | 九态 → 节点映射 | 全映射实测 ✓ | | 统计条 `summary`(`scope=ALL`) | 13 键逐键与 DB 一致;`total = 267` = 七桶之和(13 键合计 492) ✓ | | `opsStage` 筛选 15 个取值 | `total` 全部等于 DB 计数;`PENDING_TRIP` 只筛待出发 3 条,`FORMED = 215`,未知值忽略 ✓ | | 低权限角色 | `ROOM_MANAGER` / `VEHICLE_MANAGER` → 589507 ✓ | 核单 / 结算用语(PR #8303:6 个错误码文案、时间线标签): 补充(PR #8303,dev-v3 @ ade8ac292,2026-09-24 09:52–09:58):api-docs 中「已验团 / 团期核团 / 验团归档 / 验团反确认 / 核团面板」旧文案 0 次;589555「该团期已结算归档,不可重复结算」、589565「团期已结算归档,如需重新核单请先做结算反确认」实测触发;`status-logs` 对 09-18 旧记录返回新标签「发起核单 / 核单改价 / 核单提交核算 / 核单重新核算 / 结算」(`content` 为写入时原文,不随之变化)。工单 #8271 已验收关单。 --- ## 九、相关历史 PR | PR | Issue | 说明 | 是否仍有效 | |----|-------|------|------------| | #6917 / #6926 | #6904 | 统计条与导出、`opsStage` 筛选首版 | ⚠️ 桶取值被本次替换,旧 code 以别名保留 | | — | #7190 | 加「出行完毕」`TRIP_FINISHED` 成八桶 | ⚠️ 同上 | | — | #7535 | 详情 / 分页透出 `opsStage` | ⚠️ 字段保留,取值改七桶 | | **本 PR #8276 / #8279 / #8303** | **#8271** | 六节点派生 + 七桶 + 核单 / 结算用语 | ✅ 最新 | --- ## 十、相关文档 - 关联 Issue: [wx/HL#8271](https://git.1814.love/wx/HL/issues/8271) - 关联 PR: [wx/HL#8276](https://git.1814.love/wx/HL/pulls/8276)、[wx/HL#8279](https://git.1814.love/wx/HL/pulls/8279)、[wx/HL#8303](https://git.1814.love/wx/HL/pulls/8303) - 同批六节点条目:团期人工确认(#8268)、确认后锁定配置(#8269) ## 关联 / 联系人 ### 链接 - **Issue**: [#8271](https://git.1814.love/wx/HL/issues/8271) - **PR**: [#8276](https://git.1814.love/wx/HL/pulls/8276)、[#8279](https://git.1814.love/wx/HL/pulls/8279)、[#8303](https://git.1814.love/wx/HL/pulls/8303) - **Merge commit**: [678d47b58](https://git.1814.love/wx/HL/commit/678d47b584ac0237784c0bf728e86dfe6cbacb1d)、[bfbc0d337](https://git.1814.love/wx/HL/commit/bfbc0d337a92f3e2dec8b84aa54cbf1042f08698)、[ade8ac292](https://git.1814.love/wx/HL/commit/ade8ac292388354649c3e367e1171e6e55836280) ### 联系人 - **后端负责人**: @jw