五条均 frontend_status verified、owner mmg、verified_at 2026-09-08;批次A 四项 frontend_ref=2eb27845,#7291 frontend_ref=41f0bacc(均 hl-admin v2.1 可达)。
20 KiB
schema, ticket, title, consumer, author, change_type, backend_status, gateway_status, frontend_status, frontend_owner, frontend_ref, target_release, verified_at, updated_at, base, status_note
| schema | ticket | title | consumer | author | change_type | backend_status | gateway_status | frontend_status | frontend_owner | frontend_ref | target_release | verified_at | updated_at | base | status_note |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| hl-changelog/v2 | 7190 | 团期状态新增「出行完毕」TRIP_FINISHED,看板七桶扩八桶 | admin | wx(GIT) | 修改接口 | deployed | verified | verified | mmg | 2eb27845 | 2026-09-08 | 2026-09-08 | dev-v3 | 前端已交付并验证(commit 2eb27845, 汇总工单项3):batchLifecycle OPS_STAGES/OPS_STAT_TABS/BATCH_STATUS_TO_OPS 三处插 TRIP_FINISHED「出行完毕」单射,位置在出行中与待审核之间,统计条按键名读 buckets.TRIP_FINISHED;batchLifecycle.spec 硬断言扩八键顺序+TRIP_FINISHED 单射。 |
团期模块:状态九态(新增「出行完毕」)与看板八桶
⚠️ 关键变化
- 团期状态 8 → 9 态:新增
TRIP_FINISHED「出行完毕」,位于TRAVELLING「出行中」之后、REVIEWING「核单中」之前。九态与中文名:RECRUITING招募中 /RESOURCE_PREPARING资源准备中 /MATERIAL_PREPARING物料准备中 /PENDING_DEPARTURE待出发 /TRAVELLING出行中 /TRIP_FINISHED出行完毕 /REVIEWING核单中 /SETTLED已结算 /CANCELLED已取消。 - 看板运营阶段 7 桶 → 8 桶:新增桶
TRIP_FINISHED「出行完毕」,位于TRAVELLING之后、AUDITING之前。八桶顺序:RECRUIT, FORMED, PENDING_TRIP, TRAVELLING, TRIP_FINISHED, AUDITING, CHECKED, DISBANDED。GB-ADM-009 统计条buckets固定键由 7 个变 8 个;GB-ADM-001 / GB-ADM-008 的opsStage多一个可选值。 - 推进由两个定时任务按日自动完成(出发日 ≤ 今天:待出发 → 出行中;返团日 < 今天:出行中 → 出行完毕;日期取 product 侧实时班期日期,不取团期快照)。上线时两个 sys_job 为 PAUSED,「出行完毕 → 核单中」发起核单入口落地前不会 resume,所以近期页面上不会自然出现该态,但契约已变,前端要先把桶/页签/映射补齐,否则出现时页签少一个、桶键被忽略。
- 联动:出行完毕团期的房/车/导/摄芯片恒
DONE(与已返团同硬规则);对其子订单退团被拒589501;预支入口在该态仍开放;转期/调容量/需求提报按既有规则在该态均拒。
一、背景
现象
wx 2026-09-06 要求看板状态页签在「出行中」后增加「出行完毕」。排查发现团期八态的后半段(待出发 → 出行中 → 核单中 → 已结算)此前没有任何代码推进(订单级有按日期推进的 job,团期级没有),测试库全部团期都停在已成团。本单新增正式状态并补齐团期级按日推进。
调用链
- hl-user-service sys_job(Quartz)
groupBatchLifecycleJob.processDepartures() / processTripFinishes()→ 桥接 bean 经 Feign → order-v3POST /v3/internal/jobs/group-batch-departure/run、/group-batch-trip-finish/run(内部端点,网关不开放) - order-v3
GroupBatchLifecycleJobService:取候选(PENDING_DEPARTURE/TRAVELLING)→ 按产品经 Feign 取 product 实时班期日期 →GroupBatchLifecycleTxService.advanceOne同一事务 CAS 改状态 + 写时间线(BATCH_DEPART「系统自动发团」/ 新事件BATCH_TRIP_FINISH「系统自动出行完毕」) - 看板读侧:
GroupBatchStageBuckets九态折叠八桶 → GB-ADM-001records[].batchStatus / batchStatusName、GB-ADM-009buckets、GB-ADM-008 导出opsStage
地面真相(测试服 dev-v3,2026-09-06 21:38-21:42,团期房务会话临时造数)
| 团期 | 造数 | 触发 job 后 | 说明 |
|---|---|---|---|
A 2096495107078328322(#7158验收班期) |
状态 → PENDING_DEPARTURE;product 侧出发日 12-20 → 09-05;order 快照出发日仍 12-20 | 第一轮(出发日 12-20,未来)不动;第二轮(09-05)→ TRAVELLING | 读 product 实时日期,快照未动 |
B 2096510069465088002(#7178验收班期) |
状态 → TRAVELLING;product 侧返团日 12-28 → 09-05;order 快照返团日仍 12-27 | 第一轮不动;第二轮 → TRIP_FINISHED「出行完毕」 | 同上 |
两轮 sys_job 1041 / 1042 执行日志均 SUCCESS(毫秒级)。造数已由团期房务会话复原。
二、变更接口清单
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|---|---|---|---|---|
| 1 | 团期看板分页(GB-ADM-001) | GET | /v3/admin/order/group-batch |
入参枚举扩展 + 响应取值扩展 | opsStage / batchStatus 新增 TRIP_FINISHED;records[].batchStatus 可为 TRIP_FINISHED、batchStatusName="出行完毕" |
| 2 | 团期看板统计条(GB-ADM-009) | GET | /v3/admin/order/group-batch/summary |
响应结构扩展 | buckets 固定键 7 → 8,新增 TRIP_FINISHED,total = 八桶之和 |
| 3 | 团期看板导出(GB-ADM-008) | GET | /v3/admin/order/group-batch/export |
入参枚举扩展 | opsStage 新增 TRIP_FINISHED |
三、接口详情
1. 团期看板分页 GET /v3/admin/order/group-batch
VO: GroupBatchListReqVO → Result<PageResult<GroupBatchPageItemRespVO>>
使用场景
团期看板列表(hl-ui src/stores/orderV2Batch.js:93-97 getGroupBatchPage());点「出行完毕」页签时传 opsStage=TRIP_FINISHED。
入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| productId | query | Long(字符串) | 否 | 雪花 ID | 按产品筛选 |
| opsStage | query | String | 否 | RECRUIT / FORMED / PENDING_TRIP / TRAVELLING / TRIP_FINISHED / AUDITING / CHECKED / DISBANDED |
新增 TRIP_FINISHED;非法值忽略不报错 |
| batchStatus | query | String | 否 | 九态之一 | 可传 TRIP_FINISHED |
| month | query | String | 否 | yyyy-MM | 出发月份 |
| keyword | query | String | 否 | 已转义 | 班期编号 / 名称模糊 |
| deadlineFrom / deadlineTo | query | String | 否 | yyyy-MM-dd | 报名截止日区间 |
| pageNo | query | Integer | 否 | 默认 1 | 页码 |
| pageSize | query | Integer | 否 | 默认 20,最大 100 | 每页条数 |
出参 Result<PageResult<GroupBatchPageItemRespVO>>
| 字段 | 类型 | 说明 |
|---|---|---|
| data.records[] | Array | 团期行(分页容器 records / total / page / pageSize) |
| data.records[].groupBatchId | String(Long) | 团期主订单 ID |
| data.records[].batchStatus | String | 九态之一,可为 TRIP_FINISHED |
| data.records[].batchStatusName | String | 中文名,TRIP_FINISHED 对应「出行完毕」 |
| data.records[].chips | Object | 六芯片;TRIP_FINISHED 团期房/车/导/摄恒 DONE(硬规则,与已返团同) |
| 其余字段 | — | 不变(productBatchId / productId / productName / batchNo / batchName / batchLabel / maxRooms / maxParticipants / enrolledPeople / enrolledRooms / remainRooms / remainParticipants / orderCount / enrollDeadline / departDate / endDate / receivableAmount / receivedAmount) |
请求示例
GET /v3/admin/order/group-batch?productId=2056947670512971778&opsStage=TRIP_FINISHED&pageSize=10 HTTP/1.1
Host: api.test.1814.love:9443
Authorization: Bearer <token>
响应示例
第二轮造数后实测(2026-09-06 21:42):
{
"code": 200,
"message": "成功",
"data": {
"records": [
{
"groupBatchId": "2096510069465088002",
"productId": "2056947670512971778",
"productName": "测试小蒙马-多档-固定金额",
"batchName": "#7178验收班期",
"batchStatus": "TRIP_FINISHED",
"batchStatusName": "出行完毕",
"orderCount": 1,
"departDate": "2026-12-27",
"endDate": "2026-12-28"
}
],
"total": 1,
"page": 1,
"pageSize": 10
},
"success": true
}
空数据 / 降级响应
opsStage=TRIP_FINISHED 在 sys_job 未 resume 期间通常无命中:records 为空数组、total=0,不是错误。
{
"code": 200,
"message": "成功",
"data": { "records": [], "total": 0, "page": 1, "pageSize": 20 },
"success": true
}
错误响应
{
"code": 589507,
"message": "无操作权限(非团期管理员 / 非本定制师名下)",
"data": null,
"success": false
}
业务边界
opsStage与batchStatus的映射:TRIP_FINISHED桶 =TRIP_FINISHED态(单射,不是复合桶;FORMED仍是 RESOURCE_PREPARING + MATERIAL_PREPARING 复合桶)- #7189 合入后有「班期范围」筛选,默认「未结束」按返团日过滤;出行完毕/待审核/已审核的团期返团日必然已过,前端点这三个页签时应自动把范围切到「全部」
2. 团期看板统计条 GET /v3/admin/order/group-batch/summary
VO: Result<GroupBatchSummaryVO>(查询参数 productId / month / keyword,无请求 VO)
使用场景
看板页签计数(hl-ui orderV2Batch.js:74 getGroupBatchSummary()),与 GB-ADM-001 同筛选、不含 opsStage。
入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| productId | query | Long(字符串) | 否 | 雪花 ID | 按产品 |
| month | query | String | 否 | yyyy-MM | 出发月份 |
| keyword | query | String | 否 | 已转义 | 班期编号 / 名称模糊 |
出参 Result<GroupBatchSummaryVO>
| 字段 | 类型 | 说明 |
|---|---|---|
| data.total | Integer | 命中团期总数 = 八桶之和 |
| data.buckets | Object | 固定 8 键,顺序 RECRUIT, FORMED, PENDING_TRIP, TRAVELLING, TRIP_FINISHED, AUDITING, CHECKED, DISBANDED,无命中为 0(改前 7 键,无 TRIP_FINISHED) |
| data.subOrderCount | Integer | 命中团期活跃子订单合计(不变) |
请求示例
GET /v3/admin/order/group-batch/summary?productId=2056947670512971778 HTTP/1.1
Host: api.test.1814.love:9443
Authorization: Bearer <token>
响应示例
第二轮造数后实测(21:42):
{
"code": 200,
"message": "成功",
"data": {
"total": 6,
"buckets": {
"RECRUIT": 0,
"FORMED": 2,
"PENDING_TRIP": 0,
"TRAVELLING": 1,
"TRIP_FINISHED": 1,
"AUDITING": 0,
"CHECKED": 0,
"DISBANDED": 2
},
"subOrderCount": 4
},
"success": true
}
空数据 / 降级响应
无命中团期时 total=0、subOrderCount=0,buckets 仍固定返回 8 键全 0。
{
"code": 200,
"message": "成功",
"data": { "total": 0, "buckets": { "RECRUIT": 0, "FORMED": 0, "PENDING_TRIP": 0, "TRAVELLING": 0, "TRIP_FINISHED": 0, "AUDITING": 0, "CHECKED": 0, "DISBANDED": 0 }, "subOrderCount": 0 },
"success": true
}
错误响应
{
"code": 589507,
"message": "无操作权限(非团期管理员 / 非本定制师名下)",
"data": null,
"success": false
}
业务边界
- 桶键由后端枚举顺序生成,前端按对象键顺序或按自己的页签表读取都可以,但不要按索引位置取第 5 个当「待审核」(改前第 5 个是 AUDITING,改后是 TRIP_FINISHED)
- 老前端未加新键时:多出的
TRIP_FINISHED键被忽略,total与页签计数之和会差出该桶的数量
3. 团期看板导出 GET /v3/admin/order/group-batch/export
VO: 无请求 VO(查询参数) → CSV 文件流 text/csv
使用场景
看板「导出」按钮(hl-ui exportGroupBatch()),筛选参数与 GB-ADM-001 同义、不含分页。
入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| productId | query | Long(字符串) | 否 | 雪花 ID | 按产品 |
| month | query | String | 否 | yyyy-MM | 出发月份 |
| keyword | query | String | 否 | 已转义 | 班期编号 / 名称模糊 |
| opsStage | query | String | 否 | 八桶之一 | 新增 TRIP_FINISHED |
出参 CSV 文件流
| 字段 | 类型 | 说明 |
|---|---|---|
| (响应体) | text/csv | 列与改前一致;状态列可出现「出行完毕」 |
请求示例
GET /v3/admin/order/group-batch/export?productId=2056947670512971778&opsStage=TRIP_FINISHED HTTP/1.1
Host: api.test.1814.love:9443
Authorization: Bearer <token>
响应示例
{
"code": 200,
"message": "文件流(Content-Type: text/csv; Content-Disposition: attachment),此处仅示意,实际响应体为 CSV"
}
空数据 / 降级响应
无命中时返回只有表头的 CSV;命中 > 2000 行返回 589517。
{
"code": 589517,
"message": "导出行数超过上限,请缩小筛选范围",
"data": null,
"success": false
}
错误响应
{
"code": 589507,
"message": "无操作权限(非团期管理员 / 非本定制师名下)",
"data": null,
"success": false
}
业务边界
- 权限
group-batch:export opsStage非法值忽略(与 GB-ADM-001 一致)
四、契约约束与正确调用方式
三个接口均为只读 GET,无请求体;本节写的是前端消费九态/八桶的规则。
✅ 正确 / ❌ 错误 payload 对照
| 场景 | payload / 处理 |
|---|---|
| ✅ 页签 → 筛选 | 点「出行完毕」页签传 opsStage=TRIP_FINISHED(与其它页签同一套 opsStage) |
| ✅ 状态 → 桶 | 八态映射表加 TRIP_FINISHED: 'TRIP_FINISHED';未知状态值按灰/默认样式,不抛错 |
| ✅ 统计条 | 按键名读 buckets.TRIP_FINISHED,不按索引 |
| ❌ 硬编码七桶数组 | 少一个页签、total 对不上 |
❌ 把 TRIP_FINISHED 当「已完成」终态 |
它之后还有核单中 / 已结算;核单入口在后续单 |
切换状态时的必要动作
无写接口。团期进入 TRIP_FINISHED 只由 sys_job 1042 完成(当前 PAUSED);前端不需要也不能手动推进。
五、数据库行为
order_group_batch.batch_status 为 VARCHAR(32),直接存新值 TRIP_FINISHED,无表变更、无 Flyway(order-v3)。hl-user-service Flyway V20260906_005__register_group_batch_lifecycle_jobs.sql 种子两行 sys_job(1041 团期出发推进 0 10 0 * * ?、1042 团期出行完毕推进 0 20 0 * * ?,job_group=ORDER,status=PAUSED)。
| job | 扫描条件 | 推进 | 时间线事件 |
|---|---|---|---|
| 1041 | PENDING_DEPARTURE 且 product 侧出发日 ≤ 今天 |
→ TRAVELLING |
BATCH_DEPART 系统自动发团 |
| 1042 | TRAVELLING 且 product 侧返团日 < 今天 |
→ TRIP_FINISHED |
BATCH_TRIP_FINISH 系统自动出行完毕 |
状态 CAS 与时间线在同一事务内原子提交;日期取不到 product 实时值时回退团期快照并记 WARN。
六、边界行为
- 未登录 → 网关 401;无权限 →
589507 opsStage/batchStatus传未知值 → 忽略该筛选,不报错- 返团日当天仍算出行中(
< 今天才推进);出发日当天即算出行中(≤ 今天) - 出行完毕团期:退团 →
589501;转期 / 调满团名额 / 需求提报按既有阶段门拒绝;预支仍可发起 - HTTP 始终 200,按
code判断
六.5、枚举 / 数据字典
batchStatus(com.hulalv.order.groupbatch.enums.GroupBatchStatus)
| 值 | 中文名 | 桶(GroupBatchStageBuckets.Bucket) |
|---|---|---|
RECRUITING |
招募中 | RECRUIT |
RESOURCE_PREPARING |
资源准备中 | FORMED |
MATERIAL_PREPARING |
物料准备中 | FORMED |
PENDING_DEPARTURE |
待出发 | PENDING_TRIP |
TRAVELLING |
出行中 | TRAVELLING |
TRIP_FINISHED |
出行完毕(新增) | TRIP_FINISHED(新增) |
REVIEWING |
核单中 | AUDITING |
SETTLED |
已结算 | CHECKED |
CANCELLED |
已取消 | DISBANDED |
opsStage / buckets 键(GroupBatchStageBuckets.Bucket)
RECRUIT 招募中 / FORMED 已成团 / PENDING_TRIP 待出行 / TRAVELLING 出行中 / TRIP_FINISHED 出行完毕 / AUDITING 待审核 / CHECKED 已审核 / DISBANDED 流团(前端页签文案沿用现有)。
六.6、修改前后对比
字段级对比
| 字段 | 修改前 | 修改后 |
|---|---|---|
GB-ADM-001 / 008 opsStage 取值 |
7 值 | 8 值(+ TRIP_FINISHED) |
GB-ADM-001 records[].batchStatus 取值 |
8 值 | 9 值(+ TRIP_FINISHED,中文名「出行完毕」) |
GB-ADM-009 buckets 键 |
7 键 | 8 键,TRIP_FINISHED 插在 TRAVELLING 与 AUDITING 之间 |
行为级对比
| 场景 | 修改前 | 修改后 |
|---|---|---|
| 待出发团期到出发日 | 无人推进,永远待出发 | sys_job 1041(resume 后)每日 00:10 → 出行中 |
| 出行中团期过返团日 | 无人推进,永远出行中 | sys_job 1042(resume 后)每日 00:20 → 出行完毕 |
| 出行完毕团期芯片 | 不存在该态 | 房/车/导/摄恒 DONE(与已返团同) |
| 出行完毕团期退团 | 不存在该态 | 589501 |
| 原七桶各自口径 | — | 不变 |
六.7、影响评估
- 向后兼容:只增枚举值/键,不改字段名;老前端不改代码不报错,但页签少「出行完毕」、统计条多出的键被忽略
- 前端是否必须同步上线:否(job PAUSED 期间不会出现该态数据);但应在 job resume 前补齐
- 数据:order-v3 无表变更;user-service 只有 sys_job 种子
七、不影响范围
- 仅影响: 团期看板页签/统计条/导出的桶集合,团期状态取值
- 零影响:
- #7204 导/摄芯片零指派口径、房/车/约/保芯片
- 订单(子订单)状态机与订单接口
- 团期成团 / 取消成团 / 流团 / 物资确认 / 结算守卫(仍要求核单中)
- 小程序
八、测试环境已验证
真实接口输出(测试服 api.test.1814.love,2026-09-06 21:38-21:42,登录后切 ADMIN / 触发 job 切 SUPER_ADMIN):
GET /v3/admin/order/group-batch/summary?productId=2044306857534636034 → 200, buckets 键序 RECRUIT,FORMED,PENDING_TRIP,TRAVELLING,TRIP_FINISHED,AUDITING,CHECKED,DISBANDED ✓
POST /admin/job/1041/trigger、/admin/job/1042/trigger(第一轮,造数期均为未来日期) → sys_job_log SUCCESS,A/B 状态不动 ✓
POST /admin/job/1041/trigger、/admin/job/1042/trigger(第二轮,product 侧日期改到 09-05) → SUCCESS,A→TRAVELLING、B→TRIP_FINISHED,order 快照日期未动 ✓
GET /v3/admin/order/group-batch?productId=2056947670512971778&opsStage=TRIP_FINISHED → 200, 1 行 B「出行完毕」 ✓
GET /v3/admin/order/group-batch/summary?productId=2056947670512971778 → TRAVELLING=1, TRIP_FINISHED=1 ✓
GET /v3/admin/order/group-batch/2096510069465088002/chips/hotel → aggregateStatus=DONE(硬规则) ✓
POST /v3/admin/order/group-batch/2096510069465088002/sub-order/2096510069234401282/withdraw → 589501 ✓
验证团期: A 2096495107078328322、B 2096510069465088002(产品 2056947670512971778「测试小蒙马-多档-固定金额」),造数已复原。单测:GroupBatchStageBucketsTest 12/0、GroupBatchSummaryVOTest 2/0、GroupBatchStatusTest 6/0、GroupBatchLifecycleJobServiceTest 11/0、GroupBatchLifecycleTxServiceTest 4/0、GroupBatchLifecycleJobTest 3/0、GroupBatchMapperIT 13/0;合入后 dev-v3 HEAD 全量 order-v3 8726/0、hl-user-service QuartzJobExecutorTest 16/0。部署:Deploy Panel 21:20-21:22 双实例滚动完成(order-v3 + user-service),分支 dev-v3。
十、相关文档
- 关联 Issue: wx/HL#7190
- 关联 PR: wx/HL#7212
- 同现场: #7188(「第N期」序号)、#7189(看板以产品全班期为基底 + 班期范围筛选)、#7204(导/摄芯片零指派口径)
- 后续单: 「出行完毕 → 核单中」发起核单入口(落地前两个 sys_job 保持 PAUSED)
关联 / 联系人
链接
联系人
- 后端负责人: @wx