五条均 frontend_status verified、owner mmg、verified_at 2026-09-08;批次A 四项 frontend_ref=2eb27845,#7291 frontend_ref=41f0bacc(均 hl-admin v2.1 可达)。
15 KiB
schema, ticket, title, consumer, author, change_type, backend_status, gateway_status, frontend_status, frontend_owner, frontend_ref, target_release, verified_at, status_note, updated_at, base
| schema | ticket | title | consumer | author | change_type | backend_status | gateway_status | frontend_status | frontend_owner | frontend_ref | target_release | verified_at | status_note | updated_at | base |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| hl-changelog/v2 | 7250 | 团期看板分页芯片透出 chipStats 计数(done/total/error),让「一户打回整格红」可解释 | admin | jw(GIT) | 修改接口 | deployed | verified | verified | mmg | 2eb27845 | 2026-09-08 | 前端已交付并验证(commit 2eb27845, 汇总工单项5):新增纯函数 chipStatsTip,六芯片 tooltip 透出「已完成 {done}/{total}」,error>0 按房/车「N 户已打回」、约「N 户合同异常」、保「N 户保险异常」追加,导/摄恒不追加,chipStats 缺失回落旧文案;颜色仍只由 chips.X 聚合态决定,spec 锁 error>0 但 chips DONE 仍 done 色。 | 2026-09-08 | dev-v3 |
团期: 看板芯片透出 chipStats 计数
服务: hl-order-service-v3 PR: #7254 Issue: #7250 日期: 2026-09-07 影响范围: 管理后台团期看板列表的六个配置芯片(房/车/导/摄/约/保)
⚠️ 关键变化
只增字段,chips 一字未改。 同一请求的行集、排序、chips 六项取值全部不变,老前端不改不报错。
新增 records[].chipStats.{hotel|vehicle|guide|photo|contract|insurance} = {total, done, error}。
颜色一律以 chips.X 为准,chipStats 只解释「红成什么程度」——现场 55 户里 1 户被打回,
芯片就整格红,运营看不出是 1 户还是 55 户出问题。
一、背景
wx 2026-09-07 在测试服看团期看板,产品「冻干粉发短信给」10-01 期的「房」芯片整格红。 排查结论:该团期 55 户活跃子订单里有 1 户处于「驳回给定制师」,而聚合规则是 「任一户落在失败值集合即整格 ERROR」,且该判定优先于「进行中」。
规则本身是对的——被打回的户需要人工介入,必须显眼——但一个红块表达不出「1/55」还是「55/55」。
wx 拍板:口径不改,透出计数。
| 改前 | 改后 | |
|---|---|---|
chips.hotel |
ERROR |
ERROR(不变) |
| 能看出几户出问题 | 不能 | chipStats.hotel = {total:55, done:0, error:1} |
二、变更接口清单
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|---|---|---|---|---|
| 1 | 团期看板分页 | GET | /v3/admin/order/group-batch |
响应新增字段 | 每行新增 chipStats 六芯片计数;chips 与其余字段不变 |
三、接口详情
1. 团期看板分页 GET /v3/admin/order/group-batch
VO: GroupBatchPageItemRespVO
使用场景
管理后台「团期订单」看板列表(GB-ADM-001)。前端在六个芯片上加悬停提示,用本次新增的三个数
说清「红成什么程度」。调用方 hl-ui src/stores/orderV2Batch.js 的 fetchBatchPage。
入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| productId | Query | Long | ❌ | — | 入参一个都没变。传值时走产品全班期合并基底 |
| scope | Query | String | ❌ | ONGOING / FINISHED / ALL | 不变(#7189) |
| opsStage | Query | String | ❌ | 八桶之一 | 不变 |
| batchStatus | Query | String | ❌ | 团期九态 | 不变 |
| month | Query | String | ❌ | yyyy-MM | 不变 |
| keyword | Query | String | ❌ | — | 不变 |
| deadlineFrom / deadlineTo | Query | String(date) | ❌ | — | 不变 |
| pageNo / pageSize | Query | Integer | ❌ | 缺省 1 / 20 | 不变 |
出参 Result<PageResult<GroupBatchPageItemRespVO>>
| 字段 | 类型 | 说明 |
|---|---|---|
| records[].chipStats | Object | 新增:六芯片计数,键与 chips 一一对应,固定返回全部 6 个键 |
| records[].chipStats.{芯片}.total | Integer | 计入统计的户数(免闸户不计);零户行为 0 |
| records[].chipStats.{芯片}.done | Integer | 已完成户数(房车导摄 DONE / 约 SIGNED / 保 INSURED) |
| records[].chipStats.{芯片}.error | Integer | 失败户数(房/车:驳回给定制师、驳回给管理员;约:作废中、已作废;保:已取消、投保失败;导/摄无失败态恒 0) |
| records[].chips 及其余全部字段 | — | 完全不变 |
请求示例
GET /v3/admin/order/group-batch?productId=2044306857534636034&scope=ALL&pageSize=50 HTTP/1.1
Authorization: Bearer <admin-token>
响应示例
{
"code": 200,
"message": "成功",
"success": true,
"data": {
"records": [
{
"groupBatchId": "2096412454643802114",
"batchLabel": "7",
"batchName": "没,那你",
"orderCount": 55,
"chips": { "hotel": "ERROR", "vehicle": "TODO", "guide": "TODO", "photo": "TODO", "contract": "TODO", "insurance": "TODO" },
"chipStats": {
"hotel": { "total": 55, "done": 0, "error": 1 },
"vehicle": { "total": 55, "done": 0, "error": 0 },
"guide": { "total": 55, "done": 0, "error": 0 },
"photo": { "total": 55, "done": 0, "error": 0 },
"contract": { "total": 55, "done": 0, "error": 0 },
"insurance": { "total": 55, "done": 0, "error": 0 }
}
}
],
"total": 2, "page": 1, "pageSize": 20
}
}
空数据 / 降级响应
零子订单行(含未建团行 groupBatchId=null):三个计数全 0,chips 取值沿用既有规则不变。
{
"groupBatchId": null,
"orderCount": 0,
"chips": { "hotel": "TODO", "vehicle": "TODO", "guide": "TODO", "photo": "TODO", "contract": "TODO", "insurance": "TODO" },
"chipStats": {
"hotel": { "total": 0, "done": 0, "error": 0 },
"vehicle": { "total": 0, "done": 0, "error": 0 },
"guide": { "total": 0, "done": 0, "error": 0 },
"photo": { "total": 0, "done": 0, "error": 0 },
"contract": { "total": 0, "done": 0, "error": 0 },
"insurance": { "total": 0, "done": 0, "error": 0 }
}
}
注意:零户行的
chips不是恒TODO——团期处于TRIP_FINISHED/REVIEWING/SETTLED时, 房车导摄走硬规则 2 得DONE(对空单列表同样生效)。本次只统一零户的三个计数,不动状态。
错误响应
{
"code": 589507,
"message": "无操作权限(非团期管理员 / 非本定制师名下)",
"success": false,
"data": null
}
无新增错误码。既有:589507 无权限、589515 传 productId 时产品域不可用。
业务边界
- 只读接口,无写操作、无新失败分支。
- 性能不退化:失败计数并入既有
countByChip的同一次遍历,芯片相关查询次数与改前一致; 顺带收敛了改前「aggregateByChip调完countByChip后resolveAggregateStatus又算一遍」的重复计算, 总遍历次数不增反减。 chips与chipStats同源:一次aggregateAll同时产出,不存在两者打架的窗口。- 覆盖场景:见「四、契约约束」的例外矩阵——
error > 0不等于芯片一定红。
四、契约约束与正确调用方式
✅ 正确 / ❌ 错误消费方式
| 场景 | 做法 |
|---|---|
| ✅ 芯片颜色 | 一律读 chips.X,chipStats 只用于 tooltip |
| ✅ 完成度文案 | 「已完成 {done}/{total}」 |
| ✅ 异常文案 | 房/车「{error} 户已打回」、约「{error} 户合同异常」、保「{error} 户保险异常」(或统一「{error} 户异常」)。约/保刻意只写「异常」:合同异常含「作废中 / 已作废」两态,保险异常含「已取消 / 投保失败」两态,要精确原因请点进对应芯片明细(约 = GB-ADM-094、保 = GB-ADM-095) |
| ❌ 把 done/total 说成「待配」 | done 是已完成户数,不是待办户数 |
| ❌ 把合同异常、保险异常统称「打回」 | 三类失败语义不同,措辞按芯片区分:只有房/车的两个失败态才是「打回」 |
| ❌ 把约的 error 写成「合同已作废」、保的 error 写成「投保失败」 | 以偏概全:约含「作废中 / 已作废」,正在作废会被说成已作废;保含「已取消 / 投保失败」,主动退保会被说成投保失败。统一写「合同异常」「保险异常」,精确原因走明细接口 |
❌ 用 total − done − error 当「待配户数」 |
里面混着未开始、进行中、待审核三种;现场 55 户里 48 户 PENDING、1 户 PROCESSING、2 户待审核、3 户未开始、1 户打回,仅凭 done=0/total=55/error=1 推不出 48。要精确分布请点进该芯片对应的逐户明细(GB-ADM-090~095,房 090 / 车 091 / 导 092 / 摄 093 / 约 094 / 保 095) |
❌ 用 error > 0 推断颜色 |
见下方例外矩阵 |
例外矩阵:error 与 chips.X 何时合法背离
后端有三条状态覆盖规则,它们都保留真实计数、只改状态:
| 场景 | 触发规则 | 该芯片 error |
chips.X |
|---|---|---|---|
| 团期已流团(CANCELLED),仍有户处于失败态 | 硬规则 1:六芯片恒 TODO |
> 0 | TODO |
| 团期已出行完毕 / 核团中 / 已结算,房务仍有打回户 | 硬规则 2:房车导摄恒 DONE | > 0 | DONE |
| 房车导摄未全部完成,合同或保险有异常户(约:作废中 / 已作废;保:已取消 / 投保失败) | 硬规则 3:约/保恒 TODO |
> 0 | TODO |
| 以上都未触发(普通分支) | — | > 0 | ERROR(严格等价) |
服务端只在普通分支做「error > 0 当且仅当 ERROR」的自校验,不一致记 ERROR 日志并以 chips.X 为准;
覆盖分支不校验、不记日志。
五、数据库行为
无表变更、无 Flyway、无 H2 schema 变更。 本次只是把内存里已经算出来的数往外给。
六、边界行为
- 未登录 → 401(网关拦截)
- 无权限 → 589507
- 传
productId时产品域不可用 → 589515 - 零子订单行 / 未建团行 →
chipStats六项{0,0,0},不为 null,前端不必判空 - 免闸户(
needs_hotel等为 false)→ 既不计total也不计error
六.5、枚举 / 数据字典
各芯片的失败值集合(决定 error 计数)
所属字段: chipStats.{芯片}.error | 类型: Integer(下表是被计入的状态值)
| 芯片 | 计入 error 的状态值 | 来源列 |
|---|---|---|
| hotel / vehicle | REJECTED_TO_CONSULTANT、REJECTED_TO_ADMIN |
order_main.room_control_status / vehicle_control_status |
| contract | VOIDING、VOIDED |
order_main.contract_status |
| insurance | CANCELLED、FAILED |
order_main.insurance_status |
| guide / photo | 无失败态,error 恒 0 |
order_main.guide_status / photographer_status |
各芯片的完成值(决定 done 计数)
| 芯片 | 计入 done 的状态值 |
|---|---|
| hotel / vehicle / guide / photo | DONE |
| contract | SIGNED |
| insurance | INSURED |
六.6、修改前后对比
字段级对比
| 字段 | 改前 | 改后 |
|---|---|---|
records[].chips |
六个 String | 完全不变 |
records[].chipStats |
不存在 | 六芯片 {total, done, error} |
| 其余全部字段 | — | 不变 |
行为级对比
| 行为 | 改前 | 改后 |
|---|---|---|
| 芯片红色可解释性 | 只有一个 ERROR | 附带 total/done/error 三个数 |
| 芯片相关查询次数 | N | N(不变) |
| 单次聚合的订单遍历次数 | countByChip 一趟 + resolveAggregateStatus 内部又一趟 |
一趟(顺带收敛) |
六.7、影响评估
- 是否破坏向后兼容: 否。纯增字段,
chips与其余键的值逐项一致。 - 前端是否必须同步上线: 否。不消费
chipStats则表现与改前完全相同。 - 前端 workaround 清理点: 无(此前前端没有可清理的兼容逻辑,只是显示不出细节)。
七、不影响范围
- 仅影响:
GET /v3/admin/order/group-batch的响应新增一个键 - 零影响:
GET /v3/admin/order/group-batch/board(board 不含chipStats)GET /v3/admin/order/group-batch/{id}团期详情GET /v3/admin/order/group-batch/export导出(CSV 列未动)GET /v3/admin/order/group-batch/{id}/chips/{chip}芯片明细 GB-ADM-090~095(本就逐户给状态)- 聚合口径本身(
chips的判定规则一字未改) - 小程序、H5 全部接口
八、测试环境已验证
✅ 已验证。 2026-09-07 部署 dev-v3 到测试服并过网关实测,AC-1 ~ AC-9 全部通过
(实测执行与回写见提交 16e0133;AC-6d 缺失用例由 PR #7258 补齐 6d3b38de7)。
网关实测要点:
| # | 用例 | 结果 |
|---|---|---|
| 1 | chipStats 六项与 chips/{chip} 明细端点的 totalCount / doneCount 逐一相等 |
✅ |
| 2 | error 计数与明细 items 里失败态户数相等——vehicle 芯片 55 户中 1 户 REJECTED_TO_CONSULTANT,chipStats.vehicle.error=1 |
✅ |
| 3 | 跨 6 个产品 55 行普通聚合分支满足「error > 0 当且仅当 chips.X = ERROR」,违例 0 |
✅ |
单测证据:JAVA_TOOL_OPTIONS=-Xmx3g mvn -o -pl hl-order-service-v3 -am test
全量 8734 例 Failures: 0(7 例 Testcontainers 因无 Docker 报错,与基线一致);
GroupBatchChipResolverTest 47 例(新增 16:AC-6 七例 + AC-6b 四例 + AC-6c 五例)、
GroupBatchQueryServiceTest 41 例(新增 2,含「芯片投影只查一次」断言)、
GroupBatchConverterTest 50 例;ArchTest 六道门禁全绿。
九、相关历史 PR
| PR | Issue | 说明 | 是否仍有效 |
|---|---|---|---|
| #7207 | #7204 | 导/摄零指派落 TODO |
✅ 有效 |
| #7192 | #7189 | 看板产品全班期基底与 scope;零户行 chips 口径统一 | ✅ 有效 |
| 本 PR #7254 | #7250 | 芯片透出 chipStats 计数,口径不改 | ✅ 最新 |
十、相关文档
- 关联 Issue: wx/HL#7250
- 关联 PR: wx/HL#7254
- 前端待办:
changelogs-v2/2026-09/07_frontend_团期看板对齐后端契约待办汇总-前端优化-管理后台.md第 5 条(归 mmg,本篇发布后再动手) - 接口文档:
docs/group/团期模块接口文档-v2.0.htmlGB-ADM-001、docs/order-v3/api/API-SPEC.html已同步
关联 / 联系人
链接
联系人
- 后端负责人: @jw
- 前端负责人: @mmg(tooltip,见前端汇总 changelog 第 5 条)