From b224d430a46216e173cba15ef7a814426c94f868 Mon Sep 17 00:00:00 2001 From: jw Date: Mon, 28 Sep 2026 18:54:00 +0800 Subject: [PATCH] =?UTF-8?q?docs(order-v3):=20=E5=9B=A2=E6=9C=9F=E5=AF=BC/?= =?UTF-8?q?=E6=91=84=E8=8A=AF=E7=89=87=E7=8A=B6=E6=80=81=E6=94=B9=E6=8C=89?= =?UTF-8?q?=E5=9B=A2=E6=9C=9F=E5=90=8D=E5=86=8C=E8=AE=A1=E7=AE=97=E4=BA=A4?= =?UTF-8?q?=E6=8E=A5=E4=BB=B6=EF=BC=88#8469=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- ...„芯片状态改按团期名册计算-修改接口-管理后台.md | 1123 +++++++++++++++++ 1 file changed, 1123 insertions(+) create mode 100644 changelogs-v2/2026-09/28_8469_团期导摄芯片状态改按团期名册计算-修改接口-管理后台.md diff --git a/changelogs-v2/2026-09/28_8469_团期导摄芯片状态改按团期名册计算-修改接口-管理后台.md b/changelogs-v2/2026-09/28_8469_团期导摄芯片状态改按团期名册计算-修改接口-管理后台.md new file mode 100644 index 00000000..2056a770 --- /dev/null +++ b/changelogs-v2/2026-09/28_8469_团期导摄芯片状态改按团期名册计算-修改接口-管理后台.md @@ -0,0 +1,1123 @@ +--- +schema: "hl-changelog/v2" +ticket: "8469" +title: "团期看板导/摄芯片状态改按团期名册计算,合同/保险芯片门控随之变化" +consumer: "admin" +author: "jw(GIT)" +change_type: "修改接口" +backend_status: "deployed" +gateway_status: "verified" +frontend_status: "pending" +frontend_owner: "" +frontend_ref: "" +target_release: "" +verified_at: "" +status_note: "PR #8489 已合入 dev-v3(2c87b0618),TEST 的 hl-order-service-v3 运行 dev-v3 2c87b0618;经网关 api.test.1814.love 用真实 admin token 实测 AC-1~AC-6、AC-9 通过(验收脚本 22/22)。5 个接口结构、字段名、枚举值集不变,颜色渲染逻辑不用改;导/摄计数单位由户变为名册位,看板悬停 0/0 与导/摄页签、芯片弹层的按户文案需前端核对(见第四节交接清单),故 frontend_status 记 pending。" +updated_at: "2026-09-28" +base: "dev-v3" +--- + +# 团期看板:导/摄芯片状态改按团期名册计算(管理后台) + +> **服务**: hl-order-service-v3(团期看板列表、团期芯片明细) +> **PR**: #8489(合入 dev-v3 为 `2c87b0618`) +> **Issue**: #8469 +> **日期**: 2026-09-28 +> **影响范围**: 团期看板每行「导 / 摄」芯片颜色与悬停计数、「合同 / 保险」芯片颜色;团期详情「配导游」「配摄影」页签的状态标签与计数;看板点导 / 摄 / 合同 / 保险芯片弹出的明细 + +--- + +## ⚠️ 关键变化 + +1. **导 / 摄芯片改按团期名册算,不再按户**:看板列表的 `records[].chips.guide` / `chips.photo` 与芯片明细 `GET .../chips/guide`、`GET .../chips/photo` 的 `aggregateStatus` 同一口径——团期名册里这一位有人就是 `DONE`;名册没人时,只有「团期已成团、未返团、且团期标记为整团不需要」才是 `DONE`,其余都是 `TODO`。流团恒 `TODO`、已返团恒 `DONE` 两条硬规则不变。完整判定表见六.5。 +2. **导 / 摄不再出现 `DOING`**(改前「部分户已指派」是 `DOING`),也不会出现 `ERROR`;`chipStats.guide.error` / `chipStats.photo.error` 恒为 0。 +3. **导 / 摄计数单位变了:从「户」变成「名册的这一位」**。`chipStats.guide/photo` 的 `total/done` 与明细的 `totalCount/doneCount` 只有三种取值:名册有人 `total=1, done=1`;成团后整团不需要且名册没人 `total=0, done=0`;其余 `total=1, done=0`。不要再按户数展示,也不要与 `orderCount` 比较。 +4. **合同 / 保险芯片的起点随之变化**:「房 / 车 / 导 / 摄四项全部 `DONE` 前,合同 / 保险恒 `TODO`」这条规则现在吃新的导 / 摄结果。整团不需要导摄、或名册已配齐的团不再被导 / 摄卡住;合同 / 保险自身的 `totalCount`、`doneCount`、`chipStats` 与逐户 `items` 不变。 +5. **接口结构、字段名、枚举值集全部不变**,颜色映射(`TODO` 灰 / `DOING` 橙 / `DONE` 绿 / `ERROR` 红)照旧。前端要核对的只有按户文案与 0/0 悬停(见第四节「前端交接清单」)。 + +--- + +## 一、背景 + +团期详情导游 / 摄影页签的状态标签、看板导 / 摄芯片颜色和悬停「已完成 done/total」原来都按户算:只统计需要导游 / 摄影的子订单(户),再看每户有没有指派。子订单都「无需」时计入户数为 0,状态就一直是「待开始」,即使团期名册里已经派了人;合同、保险芯片又要等房车导摄四项齐了才开始,于是一起卡住。 + +测试服实例:团期 `2101506167098511362`(jw测试1期,物料准备中,12 户都无需配导游,名册导游位 2 名领队、摄影位 1 人),改前导游页签显示「待开始 · 共 0 户计入 · 已完成 0 户」,合同芯片 `TODO`(10/12 已签署)、保险芯片 `TODO`(12/12 已出单)。 + +jw 2026-09-28 定案口径(出自工单 D1~D8,按源码最终实现表述): + +| # | 口径 | +|---|---| +| D1 | 团期名册本位(导游位 / 摄影位)有人 → 完成;没人 → 待开始(成团前后的细分见 D5、D6) | +| D2 | 两条硬规则不变:团期已流团 → 待开始;已返团(出行完毕 / 核单中 / 已结算)→ 完成 | +| D3 | 看板列表、团期详情页签、芯片明细接口三处同一口径、同一取值 | +| D4 | 合同 / 保险「房车导摄四项全部完成前恒待开始」,导 / 摄两项改吃 D1 的结果 | +| D5 | 招募中只看名册:有人 → 完成,没人 → 待开始;团期上的「需要导游 / 需要摄影」标记在招募中还没写入(成团时才由子订单汇总写入),不参与判断 | +| D6 | 已成团未返团(资源准备中 / 物料准备中 / 待出发 / 出行中):名册有人 → 完成;名册没人时,团期标记为「不需要」→ 完成,「需要」→ 待开始 | +| D7 | 计数:名册有人 1/1,没人 0/1(done/total);成团后整团不需要且名册没人 → 0/0 | +| D8 | 导游位默认 = 导游 `GUIDE` + 领队 `LEADER`,摄影位 = 摄影 `PHOTOGRAPHER`(与团期人员配置、芯片明细 `staffList` 同一口径);导 / 摄不再有「进行中」,失败数恒 0 | + +--- + +## 二、变更接口清单 + +| # | 接口 | 方法 | 路径 | 变更类型 | 说明 | +|---|------|------|------|----------|------| +| 1 | 团期分页列表(看板,GB-ADM-001) | GET | `/v3/admin/order/group-batch` | 修改:出参取值语义变化 | `records[].chips.guide/photo`、`records[].chipStats.guide/photo` 改按团期名册;`chips.contract/insurance` 门控随之变化;带与不带 `productId` 两条路一致 | +| 2 | 配导游芯片明细(GB-ADM-092) | GET | `/v3/admin/order/group-batch/{groupBatchId}/chips/guide` | 修改:出参取值语义变化 | `aggregateStatus`、`totalCount`、`doneCount` 改按团期名册;`items` 仍恒 `[]`,`staffList` 不变 | +| 3 | 配摄影芯片明细(GB-ADM-093) | GET | `/v3/admin/order/group-batch/{groupBatchId}/chips/photo` | 修改:出参取值语义变化 | 同 2 | +| 4 | 合同芯片明细(GB-ADM-094) | GET | `/v3/admin/order/group-batch/{groupBatchId}/chips/contract` | 修改:出参取值语义变化 | `aggregateStatus` 受新导 / 摄结果门控;`totalCount`、`doneCount`、`items` 不变 | +| 5 | 保险芯片明细(GB-ADM-095) | GET | `/v3/admin/order/group-batch/{groupBatchId}/chips/insurance` | 修改:出参取值语义变化 | 同 4 | + +--- + +## 三、接口详情 + +### 1. 团期分页列表(看板) `GET /v3/admin/order/group-batch` + +**VO**: `GroupBatchPageItemRespVO`(`records[]` 元素;芯片字段在内嵌的 `Chips` 与 `ChipStatsMap` / `ChipStats`) + +#### 使用场景 + +团期看板每行的六芯片:颜色取 `records[].chips.X`,悬停「已完成 done/total」取 `records[].chipStats.X`。本单只改其中 `guide`、`photo` 两项的取值,以及 `contract`、`insurance` 两项何时离开 `TODO`。不带 `productId`(全部团期,按建团时间分页)与带 `productId`(产品全班期基底,含未建团的班期行)两条路同一口径。 + +#### 入参 + +全部为既有参数,本单未改。 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| productId | Query | Long | 否 | - | 按产品筛选;有值时以产品全班期为基底,含未建团的班期行(`groupBatchId` 为 `null`) | +| batchStatus | Query | String | 否 | 团期九态之一(见六.5) | 团期状态精确筛选 | +| opsStage | Query | String | 否 | `RECRUIT` / `CONFIGURE` / `CONFIRM` / `TRIP` / `REVIEW` / `SETTLE` / `DISBANDED`;非法值忽略 | 看板桶筛选 | +| scope | Query | String | 否 | `ONGOING` / `FINISHED` / `ALL`;非法值忽略 | 班期范围;带 `productId` 时缺省 `ONGOING`,不带时缺省 `ALL` | +| month | Query | String | 否 | `yyyy-MM` | 出发月份 | +| departFrom / departTo | Query | String | 否 | `yyyy-MM-dd`,含当日;非法值忽略 | 出团日期区间 | +| deadlineFrom / deadlineTo | Query | String | 否 | `yyyy-MM-dd` | 报名截止日区间 | +| keyword | Query | String | 否 | - | 班期编号 / 班期名称模糊匹配 | +| sortBy / sortOrder | Query | String | 否 | `departDate` / `enrollDeadline` / `createTime`;`asc` / `desc` | 排序;非白名单值回落默认排序,不报错 | +| pageNo | Query | Integer | 否 | 缺省或小于 1 时按 1 | 页码 | +| pageSize | Query | Integer | 否 | 缺省 20,最大 100(超出截断) | 每页条数 | + +#### 出参 `Result>` + +| 字段 | 类型 | 说明 | +|------|------|------| +| data.records[].chips.guide / chips.photo | String | **取值变化**:只会是 `TODO` 或 `DONE`,按团期名册判定(判定表见六.5);不再出现 `DOING`、`ERROR` | +| data.records[].chipStats.guide / chipStats.photo | Object | **取值变化**:`{ total, done, error }`,单位是「名册的这一位」:名册有人 `total=1, done=1`;成团后整团不需要且名册没人 `total=0, done=0`;其余 `total=1, done=0`;`error` 恒 0 | +| data.records[].chips.contract / chips.insurance | String | **门控变化**:房 / 车 / 导 / 摄四项全部 `DONE` 前恒 `TODO`,其中导 / 摄取上面的新结果;四项齐后按逐户合同 / 保险状态汇总,汇总规则不变 | +| data.records[].chipStats.contract / chipStats.insurance | Object | 不变:户数,按真实数据统计,不受门控影响 | +| data.records[].chips.hotel / vehicle、chipStats.hotel / vehicle | - | 不变 | +| data.records[] 其余字段、data.total / page / pageSize | - | 不变 | + +#### 请求示例 + +```http +GET /v3/admin/order/group-batch?scope=ALL&pageNo=1&pageSize=100 +Authorization: Bearer +``` + +无请求体。按产品看板:`GET /v3/admin/order/group-batch?productId=2101499109901778946&scope=ALL&pageNo=1&pageSize=100`。 + +#### 响应示例 + +2026-09-28 18:34 测试服实测(不带 `productId`;本页共 13 行,这里只保留实例团期一行,字段均为原值): + +```json +{ + "code": 200, + "message": "成功", + "data": { + "records": [ + { + "groupBatchId": "2101506167098511362", + "productBatchId": "2101502082564407299", + "productId": "2101499109901778946", + "productName": "jw测试产品", + "batchNo": "Q202609272101502082564407298", + "batchName": "jw测试1期", + "batchLabel": "1", + "batchStatus": "MATERIAL_PREPARING", + "batchStatusName": "物料准备中", + "stage": "CONFIRM", + "stageName": "确认", + "tripSubStatus": null, + "tripSubStatusName": null, + "opsStage": "CONFIRM", + "opsStageName": "确认", + "minGroupPeople": 6, + "minToForm": 6, + "maxRooms": 12, + "maxParticipants": 24, + "enrolledPeople": 24, + "enrolledRooms": 12, + "remainRooms": 0, + "remainParticipants": 0, + "orderCount": 12, + "enrollDeadline": "2026-09-26", + "departDate": "2026-09-27", + "endDate": "2026-10-03", + "daysToDepart": -1, + "receivableAmount": "156760.00", + "receivedAmount": "47940.00", + "unpaidAmount": "108820.00", + "chips": { + "hotel": "DONE", + "vehicle": "DONE", + "guide": "DONE", + "photo": "DONE", + "contract": "DOING", + "insurance": "DONE" + }, + "chipStats": { + "hotel": { + "total": 12, + "done": 12, + "error": 0 + }, + "vehicle": { + "total": 12, + "done": 12, + "error": 0 + }, + "guide": { + "total": 1, + "done": 1, + "error": 0 + }, + "photo": { + "total": 1, + "done": 1, + "error": 0 + }, + "contract": { + "total": 12, + "done": 10, + "error": 0 + }, + "insurance": { + "total": 12, + "done": 12, + "error": 0 + } + }, + "productBatchStatus": null, + "productBatchStatusLabel": null, + "productBatchStatusName": null, + "productBatchRemoved": null + } + ], + "total": 13, + "page": 1, + "pageSize": 100 + }, + "traceId": null, + "success": true +} +``` + +改前(同一请求,18:00 实测)这一行的芯片部分: + +```json +{ + "groupBatchId": "2101506167098511362", + "batchStatus": "MATERIAL_PREPARING", + "chips": { + "hotel": "DONE", + "vehicle": "DONE", + "guide": "TODO", + "photo": "TODO", + "contract": "TODO", + "insurance": "TODO" + }, + "chipStats": { + "hotel": { + "total": 12, + "done": 12, + "error": 0 + }, + "vehicle": { + "total": 12, + "done": 12, + "error": 0 + }, + "guide": { + "total": 0, + "done": 0, + "error": 0 + }, + "photo": { + "total": 0, + "done": 0, + "error": 0 + }, + "contract": { + "total": 12, + "done": 10, + "error": 0 + }, + "insurance": { + "total": 12, + "done": 12, + "error": 0 + } + } +} +``` + +#### 空数据 / 降级响应 + +- 本页没有团期时 `records: []`,不做芯片计算。 +- 带 `productId` 时,未建团的班期行(`groupBatchId` 为 `null`)导 / 摄恒 `TODO`、`total=1, done=0`(改前为 `total=0, done=0`);房 / 车 / 合同 / 保险计数仍为 0。实测片段(同一产品另一期): + +```json +{ + "groupBatchId": null, + "productBatchId": "2101502082795143171", + "batchName": "jw测试2期", + "batchStatus": "RECRUITING", + "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": 1, + "done": 0, + "error": 0 + }, + "photo": { + "total": 1, + "done": 0, + "error": 0 + }, + "contract": { + "total": 0, + "done": 0, + "error": 0 + }, + "insurance": { + "total": 0, + "done": 0, + "error": 0 + } + } +} +``` + +- 团期里没有活跃子订单时:房 / 车 / 合同 / 保险计数为 0(不变);导 / 摄仍按名册与团期标记判定,例如成团后整团不需要且名册没人为 `DONE`、`total=0, done=0`。 + +#### 错误响应 + +错误码未改动。角色未授予 `group-batch:list`: + +```json +{ + "code": 589507, + "message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)", + "data": null, + "success": false +} +``` + +未登录由网关拦截,HTTP 200、业务码 401(测试服实测文案「缺少有效的 Authorization 头」)。 + +#### 业务边界 + +- 判权未改:`group-batch:list`,无权限 589507。 +- 导 / 摄只看团期名册、团期状态与团期「需要导游 / 需要摄影」标记,不看任何一户子订单的需要标记或指派情况。 +- 流团(`batchStatus=CANCELLED`):六芯片恒 `TODO`;导 / 摄计数照实,名册有人时会出现 `chips.guide=TODO` 而 `chipStats.guide` 为 `total=1, done=1`,属正常。 +- 已返团(`TRIP_FINISHED` / `REVIEWING` / `SETTLED`):导 / 摄恒 `DONE`;名册没人且团期需要时计数为 `total=1, done=0`,属正常。 +- 颜色一律以 `chips.X` 为准,`chipStats` 只用来解释(与 #7250 口径相同)。 +- 名册增删人员后,下一次请求即按新名册计算。 +- 本接口只读。 + +### 2. 配导游芯片明细 `GET /v3/admin/order/group-batch/{groupBatchId}/chips/guide` + +**VO**: `GroupBatchChipDetailVO` + +#### 使用场景 + +团期详情「配导游」页签的状态标签与计数、看板点导游芯片弹出的明细。本接口 `aggregateStatus` 与看板同一行 `chips.guide` 同值,`doneCount` / `totalCount` 与 `chipStats.guide.done` / `chipStats.guide.total` 同值。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| groupBatchId | Path | Long | 是 | 运营团期 ID | 路由上的团期 ID(既有,未改) | + +#### 出参 `Result` + +| 字段 | 类型 | 说明 | +|------|------|------| +| batchId / groupBatchId | String | 团期 ID(`batchId` 已废弃,同值;不变) | +| chipLabel | String | 「配导游」(不变) | +| aggregateStatus / aggregateStatusName | String | **取值变化**:只会是 `TODO`「待开始」或 `DONE`「已完成」,按团期名册判定(判定表见六.5);改前按户,可为 `DOING`「进行中」 | +| totalCount | Integer | **取值变化**:名册导游位有人为 1;没人时,成团后整团不需要为 0,其余为 1。改前是需要导游的户数 | +| doneCount | Integer | **取值变化**:名册导游位有人为 1,否则 0。改前是已指派导游的户数 | +| staffList | Object[] | 不变:本团导游位已配置人员;元素字段 `staffId`、`staffRole`、`staffRoleName`、`staffName`、`staffPhone`(脱敏)、`reporterRank`、`reporterRankName`、`source`、`sourceName`;未配置为 `[]` | +| items | Object[] | 不变:恒为 `[]`(#8468 起) | + +#### 请求示例 + +```http +GET /v3/admin/order/group-batch/2101506167098511362/chips/guide +Authorization: Bearer +``` + +无请求体。 + +#### 响应示例 + +2026-09-28 18:34 测试服实测,实例团期(12 户都无需配导游,名册导游位 2 名领队)。改前同一请求 `aggregateStatus` 为 `TODO`「待开始」、`totalCount=0`、`doneCount=0`,其余字段相同。 + +```json +{ + "code": 200, + "message": "成功", + "data": { + "batchId": "2101506167098511362", + "groupBatchId": "2101506167098511362", + "chipLabel": "配导游", + "aggregateStatus": "DONE", + "aggregateStatusName": "已完成", + "totalCount": 1, + "doneCount": 1, + "staffList": [ + { + "staffId": "1011", + "staffRole": "LEADER", + "staffRoleName": "领队", + "staffName": "巴特尔", + "staffPhone": "139****1011", + "reporterRank": "PRIMARY", + "reporterRankName": "主报账人", + "source": null, + "sourceName": null + }, + { + "staffId": "1008", + "staffRole": "LEADER", + "staffRoleName": "领队", + "staffName": "萨仁高娃", + "staffPhone": "139****1008", + "reporterRank": "NONE", + "reporterRankName": "非报账人", + "source": null, + "sourceName": null + } + ], + "items": [] + }, + "traceId": null, + "success": true +} +``` + +#### 空数据 / 降级响应 + +名册导游位没人时 `staffList: []`、`items: []`,状态与计数看团期状态和团期标记。三种实测: + +成团后整团不需要、名册没人(团期 `2100856430494973953`,资源准备中)→ `DONE`,`totalCount=0`、`doneCount=0`: + +```json +{ + "code": 200, + "message": "成功", + "data": { + "batchId": "2100856430494973953", + "groupBatchId": "2100856430494973953", + "chipLabel": "配导游", + "aggregateStatus": "DONE", + "aggregateStatusName": "已完成", + "totalCount": 0, + "doneCount": 0, + "staffList": [], + "items": [] + }, + "traceId": null, + "success": true +} +``` + +成团后团期需要导游、名册没人(造数团期 H,资源准备中)→ `TODO`,`totalCount=1`、`doneCount=0`(`data` 部分): + +```json +{ + "batchId": "2104511888882868226", + "groupBatchId": "2104511888882868226", + "chipLabel": "配导游", + "aggregateStatus": "TODO", + "aggregateStatusName": "待开始", + "totalCount": 1, + "doneCount": 0, + "staffList": [], + "items": [] +} +``` + +流团后名册仍有人(同一团期 H 流团后)→ 恒 `TODO`,计数照实 `totalCount=1`、`doneCount=1`(`data` 部分): + +```json +{ + "batchId": "2104511888882868226", + "groupBatchId": "2104511888882868226", + "chipLabel": "配导游", + "aggregateStatus": "TODO", + "aggregateStatusName": "待开始", + "totalCount": 1, + "doneCount": 1, + "staffList": [ + { + "staffId": "1002", + "staffRole": "GUIDE", + "staffRoleName": "导游", + "staffName": "李雪梅", + "staffPhone": "138****1002", + "reporterRank": "NONE", + "reporterRankName": "非报账人", + "source": null, + "sourceName": null + } + ], + "items": [] +} +``` + +#### 错误响应 + +错误码未改动:团期不存在 589500,无权限 589507。未登录(测试服实测,网关返回 HTTP 200、业务码 401): + +```json +{ + "code": 401, + "message": "缺少有效的 Authorization 头", + "data": null, + "traceId": "8f16889e7bc64740", + "success": false +} +``` + +#### 业务边界 + +- 判权未改:`group-batch:view`,无权限 589507;团期不存在 589500。 +- 导游位收哪些角色以配置位字典为准,默认导游 `GUIDE` + 领队 `LEADER`;与 `staffList` 同一口径,所以 `staffList` 非空 ⇔ `doneCount=1`。 +- 招募中不看团期标记:名册没人一律 `TODO`、`totalCount=1`、`doneCount=0`。 +- 流团恒 `TODO`(计数照实,可能 1/1);已返团恒 `DONE`(计数照实,可能 0/1 或 0/0);成团后才流团的团期名册没人时计数为 `totalCount=1`、`doneCount=0`,不是 0/0。 +- `items` 恒 `[]`,不要用逐户数据推导本芯片状态。 +- 本接口只读。 + +### 3. 配摄影芯片明细 `GET /v3/admin/order/group-batch/{groupBatchId}/chips/photo` + +**VO**: `GroupBatchChipDetailVO` + +#### 使用场景 + +团期详情「配摄影」页签的状态标签与计数、看板点摄影芯片弹出的明细。本接口 `aggregateStatus` 与看板同一行 `chips.photo` 同值,`doneCount` / `totalCount` 与 `chipStats.photo.done` / `chipStats.photo.total` 同值。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| groupBatchId | Path | Long | 是 | 运营团期 ID | 路由上的团期 ID(既有,未改) | + +#### 出参 `Result` + +| 字段 | 类型 | 说明 | +|------|------|------| +| batchId / groupBatchId | String | 团期 ID(`batchId` 已废弃,同值;不变) | +| chipLabel | String | 「配摄影」(不变) | +| aggregateStatus / aggregateStatusName | String | **取值变化**:只会是 `TODO`「待开始」或 `DONE`「已完成」,按团期名册判定(判定表见六.5);改前按户,可为 `DOING`「进行中」 | +| totalCount | Integer | **取值变化**:名册摄影位有人为 1;没人时,成团后整团不需要为 0,其余为 1。改前是需要摄影的户数 | +| doneCount | Integer | **取值变化**:名册摄影位有人为 1,否则 0。改前是已指派摄影的户数 | +| staffList | Object[] | 不变:本团摄影位已配置人员;元素字段同接口 2(`staffId`、`staffRole`、`staffRoleName`、`staffName`、`staffPhone`(脱敏)、`reporterRank`、`reporterRankName`、`source`、`sourceName`);未配置为 `[]` | +| items | Object[] | 不变:恒为 `[]`(#8468 起) | + +#### 请求示例 + +```http +GET /v3/admin/order/group-batch/2101506167098511362/chips/photo +Authorization: Bearer +``` + +无请求体。 + +#### 响应示例 + +2026-09-28 18:34 测试服实测,实例团期(12 户都无需配摄影,名册摄影位 1 人)。改前同一请求 `aggregateStatus` 为 `TODO`「待开始」、`totalCount=0`、`doneCount=0`,其余字段相同。 + +```json +{ + "code": 200, + "message": "成功", + "data": { + "batchId": "2101506167098511362", + "groupBatchId": "2101506167098511362", + "chipLabel": "配摄影", + "aggregateStatus": "DONE", + "aggregateStatusName": "已完成", + "totalCount": 1, + "doneCount": 1, + "staffList": [ + { + "staffId": "1003", + "staffRole": "PHOTOGRAPHER", + "staffRoleName": "摄影", + "staffName": "王强", + "staffPhone": "138****1003", + "reporterRank": "NONE", + "reporterRankName": "非报账人", + "source": null, + "sourceName": null + } + ], + "items": [] + }, + "traceId": null, + "success": true +} +``` + +#### 空数据 / 降级响应 + +名册摄影位没人时 `staffList: []`、`items: []`。招募中团期摄影位没人(团期 `2104491315645538305`,团期标记在招募中为 0,也不算「不需要」)→ `TODO`,`totalCount=1`、`doneCount=0`: + +```json +{ + "code": 200, + "message": "成功", + "data": { + "batchId": "2104491315645538305", + "groupBatchId": "2104491315645538305", + "chipLabel": "配摄影", + "aggregateStatus": "TODO", + "aggregateStatusName": "待开始", + "totalCount": 1, + "doneCount": 0, + "staffList": [], + "items": [] + }, + "traceId": null, + "success": true +} +``` + +成团后整团不需要且名册没人时为 `DONE`、`totalCount=0`、`doneCount=0`(与接口 2 同形)。 + +#### 错误响应 + +错误码未改动:团期不存在 589500,无权限 589507。 + +```json +{ + "code": 589500, + "message": "团期不存在", + "data": null, + "success": false +} +``` + +#### 业务边界 + +- 判权未改:`group-batch:view`,无权限 589507;未登录由网关返回业务码 401。 +- 摄影位收哪些角色以配置位字典为准,默认只收摄影 `PHOTOGRAPHER`;与 `staffList` 同一口径,所以 `staffList` 非空 ⇔ `doneCount=1`。 +- 招募中不看团期标记:名册没人一律 `TODO`、`totalCount=1`、`doneCount=0`。 +- 流团恒 `TODO`(计数照实);已返团恒 `DONE`(计数照实)。 +- `items` 恒 `[]`,不要用逐户数据推导本芯片状态。 +- 本接口只读。 + +### 4. 合同芯片明细 `GET /v3/admin/order/group-batch/{groupBatchId}/chips/contract` + +**VO**: `GroupBatchChipDetailVO`(逐户项 `GroupBatchChipItemRespVO`) + +#### 使用场景 + +看板点合同芯片弹出的逐户合同明细,以及团期详情里的合同芯片面板。本接口 `aggregateStatus` 与看板同一行 `chips.contract` 同值。本单只改「何时离开 `TODO`」,逐户内容与计数不变。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| groupBatchId | Path | Long | 是 | 运营团期 ID | 路由上的团期 ID(既有,未改) | + +#### 出参 `Result` + +| 字段 | 类型 | 说明 | +|------|------|------| +| batchId / groupBatchId | String | 团期 ID(`batchId` 已废弃,同值;不变) | +| chipLabel | String | 「合同」(不变) | +| aggregateStatus / aggregateStatusName | String | **门控变化**:房 / 车 / 导 / 摄四项未全部 `DONE` 时恒 `TODO`「待开始」,其中导 / 摄改用团期名册结果;四项齐后按逐户合同状态汇总(汇总规则不变):有作废中 / 已作废 → `ERROR`;全部已签署 → `DONE`;有待出具 / 已生成 / 已上报 / 已上传 / 签署中 → `DOING`;否则 `TODO` | +| totalCount | Integer | 不变:活跃子订单数(合同每户都计入) | +| doneCount | Integer | 不变:已签署户数 | +| staffList | - | 不变:恒 `null` | +| items | Object[] | 不变:逐户合同状态;元素字段 `orderId`、`orderNo`、`teamNo`、`contactName`(已废弃)/ `customerName`、`peopleCount`、`status`、`statusText`(已废弃)/ `statusName`、`needsIt`(恒 true)、`updateTime`、`claimerId`、`claimerName`、`claimerSource`、`staffs`(恒 `null`) | + +#### 请求示例 + +```http +GET /v3/admin/order/group-batch/2101506167098511362/chips/contract +Authorization: Bearer +``` + +无请求体。 + +#### 响应示例 + +2026-09-28 18:34 测试服实测,实例团期(房 / 车 12/12 已完成,导 / 摄按名册已完成,四项齐;10/12 已签署)。`items` 共 12 户,这里只保留前 2 户,其余字段原值。改前同一请求 `aggregateStatus` 为 `TODO`「待开始」(被按户的导 / 摄卡住),计数与 `items` 相同。 + +```json +{ + "code": 200, + "message": "成功", + "data": { + "batchId": "2101506167098511362", + "groupBatchId": "2101506167098511362", + "chipLabel": "合同", + "aggregateStatus": "DOING", + "aggregateStatusName": "进行中", + "totalCount": 12, + "doneCount": 10, + "staffList": null, + "items": [ + { + "orderId": "2101506167043985410", + "orderNo": "HL20260920105808925", + "teamNo": "26-3627", + "contactName": "张建国", + "customerName": "张建国", + "peopleCount": 6, + "status": "SIGNED", + "statusText": "已签署", + "statusName": "已签署", + "needsIt": true, + "updateTime": null, + "claimerId": "1001", + "claimerName": "admin", + "claimerSource": "BATCH", + "staffs": null + }, + { + "orderId": "2101507276118626306", + "orderNo": "HL20260920110233355", + "teamNo": "26-0750", + "contactName": "王志强", + "customerName": "王志强", + "peopleCount": 2, + "status": "SIGNED", + "statusText": "已签署", + "statusName": "已签署", + "needsIt": true, + "updateTime": null, + "claimerId": "1001", + "claimerName": "admin", + "claimerSource": "BATCH", + "staffs": null + } + ] + }, + "traceId": null, + "success": true +} +``` + +#### 空数据 / 降级响应 + +- 团期没有活跃子订单:`totalCount=0`、`doneCount=0`、`items: []`、`aggregateStatus` 为 `TODO`(不变)。 +- 导 / 摄仍未齐时恒 `TODO`。实测:造数团期 H 已配导游、未配摄影,合同芯片 `TODO`: + +```json +{ + "code": 200, + "message": "成功", + "data": { + "batchId": "2104511888882868226", + "groupBatchId": "2104511888882868226", + "chipLabel": "合同", + "aggregateStatus": "TODO", + "aggregateStatusName": "待开始", + "totalCount": 1, + "doneCount": 0, + "staffList": null, + "items": [ + { + "orderId": "2104511888652181506", + "orderNo": "HL20260928180148673", + "teamNo": null, + "contactName": "巴图孟和", + "customerName": "巴图孟和", + "peopleCount": 2, + "status": null, + "statusText": "无合同", + "statusName": "无合同", + "needsIt": true, + "updateTime": null, + "claimerId": null, + "claimerName": null, + "claimerSource": null, + "staffs": null + } + ] + }, + "traceId": null, + "success": true +} +``` + +#### 错误响应 + +错误码未改动:团期不存在 589500,无权限 589507。 + +```json +{ + "code": 589507, + "message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)", + "data": null, + "success": false +} +``` + +#### 业务边界 + +- 判权未改:`group-batch:view`,无权限 589507;团期不存在 589500;未登录由网关返回业务码 401。 +- 门控只影响 `aggregateStatus`:门控期间 `totalCount`、`doneCount`、`items` 照实,可能出现 `doneCount=totalCount` 而 `aggregateStatus=TODO`,属正常。 +- 流团恒 `TODO`;已返团时房 / 车 / 导 / 摄恒 `DONE`,合同按逐户汇总(不变)。 +- 整团不需要导摄的团(成团后、名册没人、团期标记为不需要)不再因导 / 摄卡在 `TODO`,只要房 / 车也已 `DONE` 即按逐户合同状态显示。 +- 本接口只读。 + +### 5. 保险芯片明细 `GET /v3/admin/order/group-batch/{groupBatchId}/chips/insurance` + +**VO**: `GroupBatchChipDetailVO`(逐户项 `GroupBatchChipItemRespVO`) + +#### 使用场景 + +看板点保险芯片弹出的逐户保险明细,以及团期详情里的保险芯片面板。本接口 `aggregateStatus` 与看板同一行 `chips.insurance` 同值。本单只改「何时离开 `TODO`」,逐户内容与计数不变。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| groupBatchId | Path | Long | 是 | 运营团期 ID | 路由上的团期 ID(既有,未改) | + +#### 出参 `Result` + +| 字段 | 类型 | 说明 | +|------|------|------| +| batchId / groupBatchId | String | 团期 ID(`batchId` 已废弃,同值;不变) | +| chipLabel | String | 「保险」(不变) | +| aggregateStatus / aggregateStatusName | String | **门控变化**:房 / 车 / 导 / 摄四项未全部 `DONE` 时恒 `TODO`「待开始」,其中导 / 摄改用团期名册结果;四项齐后按逐户保险状态汇总(汇总规则不变):有已取消 / 出单失败 → `ERROR`;全部已出单 → `DONE`;有出单中 → `DOING`;否则 `TODO` | +| totalCount | Integer | 不变:活跃子订单数(保险每户都计入) | +| doneCount | Integer | 不变:已出单户数 | +| staffList | - | 不变:恒 `null` | +| items | Object[] | 不变:逐户保险状态;元素字段同接口 4 | + +#### 请求示例 + +```http +GET /v3/admin/order/group-batch/2101506167098511362/chips/insurance +Authorization: Bearer +``` + +无请求体。 + +#### 响应示例 + +2026-09-28 18:34 测试服实测,实例团期(四项齐,12/12 已出单)。`items` 共 12 户,这里只保留前 2 户,其余字段原值。改前同一请求 `aggregateStatus` 为 `TODO`「待开始」,计数与 `items` 相同。 + +```json +{ + "code": 200, + "message": "成功", + "data": { + "batchId": "2101506167098511362", + "groupBatchId": "2101506167098511362", + "chipLabel": "保险", + "aggregateStatus": "DONE", + "aggregateStatusName": "已完成", + "totalCount": 12, + "doneCount": 12, + "staffList": null, + "items": [ + { + "orderId": "2101506167043985410", + "orderNo": "HL20260920105808925", + "teamNo": "26-3627", + "contactName": "张建国", + "customerName": "张建国", + "peopleCount": 6, + "status": "INSURED", + "statusText": "已出单", + "statusName": "已出单", + "needsIt": true, + "updateTime": null, + "claimerId": "1001", + "claimerName": "admin", + "claimerSource": "BATCH", + "staffs": null + }, + { + "orderId": "2101507276118626306", + "orderNo": "HL20260920110233355", + "teamNo": "26-0750", + "contactName": "王志强", + "customerName": "王志强", + "peopleCount": 2, + "status": "INSURED", + "statusText": "已出单", + "statusName": "已出单", + "needsIt": true, + "updateTime": null, + "claimerId": "1001", + "claimerName": "admin", + "claimerSource": "BATCH", + "staffs": null + } + ] + }, + "traceId": null, + "success": true +} +``` + +#### 空数据 / 降级响应 + +- 团期没有活跃子订单:`totalCount=0`、`doneCount=0`、`items: []`、`aggregateStatus` 为 `TODO`(不变)。 +- 房 / 车 / 导 / 摄未齐时恒 `TODO`,计数照实(与接口 4 同形)。 + +#### 错误响应 + +错误码未改动:团期不存在 589500,无权限 589507。 + +```json +{ + "code": 589500, + "message": "团期不存在", + "data": null, + "success": false +} +``` + +#### 业务边界 + +- 判权未改:`group-batch:view`,无权限 589507;团期不存在 589500;未登录由网关返回业务码 401。 +- 门控只影响 `aggregateStatus`:门控期间计数与 `items` 照实,可能出现 `doneCount=totalCount` 而 `aggregateStatus=TODO`,属正常(实例团期改前即 12/12 却 `TODO`)。 +- 流团恒 `TODO`;已返团时按逐户汇总(不变)。 +- 本接口只读。 + +--- + +## 四、契约约束与正确调用方式 + +> 5 个接口均为 GET、入参未改;本节写取值的正确读法。 + +### ✅ 正确 / ❌ 错误读法对照 + +| 场景 | 读法 | +|------|------| +| ✅ 芯片颜色 | 列表取 `chips.X`,明细取 `aggregateStatus`;四值映射不变 | +| ✅ 导 / 摄「名册有没有人」 | 明细 `staffList` 是否非空,或 `doneCount=1` / `chipStats.X.done=1`(三者恒一致) | +| ✅ 识别「整团不需要」 | 导 / 摄 `total=0`(明细 `totalCount=0`):此时状态必为 `DONE`,含义是已成团(含已返团)、团期标记为不需要、名册没人 | +| ❌ 把导 / 摄计数当户数 | 「共 N 户计入 · 已完成 N 户」对导 / 摄不成立,两个数只会是 0 或 1 | +| ❌ 用逐户数据推导导 / 摄状态 | 导 / 摄 `items` 恒 `[]`;子订单上的需要导游 / 摄影标记不参与判定 | +| ❌ 用 `chipStats` 推颜色 | 流团时 `TODO` 可与 1/1 并存,已返团时 `DONE` 可与 0/1 并存,合同 / 保险门控期间 `TODO` 可与 12/12 并存 | + +### 前端交接清单 + +1. **颜色**:不用改。`chips.guide/photo` 只会出现 `TODO` / `DONE`,合同 / 保险仍是四值。 +2. **看板悬停**(hl-ui `src/views/order-v2/batch/_shared/batchLifecycle.js` 的 `chipStatsTip`):导 / 摄会显示「已完成 1/1」「已完成 0/1」「已完成 0/0」,数字是名册这一位,不是户数。0/0 时芯片为绿色(整团不需要),当前会原样显示「已完成 0/0」——这是本契约的正常取值;若要更直观,可对导 / 摄 `total=0`(此时必为 `DONE`)改显示「无需」。 +3. **导 / 摄页签与芯片弹层汇总行**(hl-ui `src/views/order-v2/batch/detail/components/ChipItemsPanel.vue`、`src/views/order-v2/batch/components/ChipDetailModal.vue` 的「共 {totalCount} 户计入 · 已完成 {doneCount} 户」):对导 / 摄这两个数不再是户数。若按 #8468 交接清单第 6 项已对导 / 摄去掉该行,无需再动;若仍在,请对导 / 摄隐藏该行或改为按名册展示(如「已配置 N 人」取 `staffList.length`,`totalCount=0` 显示「无需」)。状态标签照用 `aggregateStatus`。房 / 车 / 合同 / 保险的汇总行不变。 +4. **合同 / 保险**:不用改。整团不需要导摄或名册已配齐的团,合同 / 保险芯片会比改前更早离开 `TODO`,属预期。 +5. 不需要新增请求或字段。 + +--- + +## 五、数据库行为 + +本单 5 个接口均为只读查询,零写入;不含数据迁移,不改存量数据。 + +--- + +## 六、边界行为 + +- 未登录 → 网关拦截,HTTP 200、业务码 401(既有,测试服实测)。 +- 无权限 → 589507(列表 `group-batch:list`,明细 `group-batch:view`,既有)。 +- 团期不存在 → 589500(芯片明细,既有)。 +- 未建团的班期行(仅带 `productId` 的列表)→ 导 / 摄 `TODO`、`total=1, done=0`;该行没有 `groupBatchId`,调不到芯片明细。 +- 团期状态缺失(历史脏数据)→ 导 / 摄名册有人 `DONE`(1/1),否则 `TODO`(0/1)。 +- 成团后才流团 → 恒 `TODO`;名册没人时计数 0/1,不是 0/0。 +- 导 / 摄从不出现 `DOING`、`ERROR`;`chipStats.guide/photo.error` 恒 0。 +- 向后兼容:结构不变,旧前端不改也能按新值正确着色;只是导 / 摄的按户文案不再准确(见第四节)。 + +--- + +## 六.5、枚举 / 数据字典 + +### 芯片聚合态(常量定义于 `com.hulalv.order.groupbatch.helper.GroupBatchChipResolver`) + +**所属字段**: `GroupBatchPageItemRespVO.Chips.*`、`GroupBatchChipDetailVO.aggregateStatus` | **类型**: `String` + +| 值 | 中文 | 说明 | +|----|------|------| +| `TODO` | 待开始 | 导 / 摄:见下方判定表;合同 / 保险:四项未齐时恒为此值 | +| `DOING` | 进行中 | 导 / 摄本单起不再出现;房 / 车 / 合同 / 保险规则不变 | +| `DONE` | 已完成 | 导 / 摄:见下方判定表 | +| `ERROR` | 异常 | 导 / 摄从不出现;房 / 车 / 合同 / 保险规则不变 | + +### 导 / 摄判定表(按优先级从上往下,命中即止;计数写作 done/total) + +| 团期状态 | 名册本位 | 团期「需要」标记 | 状态 | 计数 | +|----------|----------|------------------|------|------| +| 流团 `CANCELLED` | 有人 | 不看 | `TODO` | 1/1 | +| 流团 `CANCELLED` | 没人 | 不看 | `TODO` | 0/1 | +| 已返团 `TRIP_FINISHED` / `REVIEWING` / `SETTLED` | 有人 | 不看 | `DONE` | 1/1 | +| 已返团 | 没人 | 需要 | `DONE` | 0/1 | +| 已返团 | 没人 | 不需要 | `DONE` | 0/0 | +| 任意其他状态(含招募中) | 有人 | 不看 | `DONE` | 1/1 | +| 已成团未返团 `RESOURCE_PREPARING` / `MATERIAL_PREPARING` / `PENDING_DEPARTURE` / `TRAVELLING` | 没人 | 不需要 | `DONE` | 0/0 | +| 已成团未返团 | 没人 | 需要 | `TODO` | 0/1 | +| 招募中 `RECRUITING` | 没人 | 不看 | `TODO` | 0/1 | +| 未建团的班期行(仅带 `productId` 的列表) | 没人 | 无 | `TODO` | 0/1 | + +### batchStatus(`com.hulalv.order.groupbatch.enums.GroupBatchStatus`) + +**所属字段**: `GroupBatchPageItemRespVO.batchStatus` | **类型**: `String` + +| 值 | 中文 | 导 / 摄判定分组 | +|----|------|------| +| `RECRUITING` | 招募中 | 招募中:只看名册 | +| `RESOURCE_PREPARING` | 资源准备中 | 已成团未返团 | +| `MATERIAL_PREPARING` | 物料准备中 | 已成团未返团 | +| `PENDING_DEPARTURE` | 待出发 | 已成团未返团 | +| `TRAVELLING` | 出行中 | 已成团未返团 | +| `TRIP_FINISHED` | 出行完毕 | 已返团 | +| `REVIEWING` | 核单中 | 已返团 | +| `SETTLED` | 已结算 | 已返团 | +| `CANCELLED` | 已取消(流团) | 流团 | + +### 配置位成员(`com.hulalv.order.assignment.constants.GroupBatchStaffSlot`) + +**所属字段**: 决定 `staffList` 与导 / 摄「名册本位有没有人」 | **类型**: `String`(`staffRole`) + +| 配置位 | 默认成员 | 说明 | +|--------|----------|------| +| 导游位 | `GUIDE` 导游、`LEADER` 领队 | 以配置位字典为准,字典读不到时用默认成员 | +| 摄影位 | `PHOTOGRAPHER` 摄影 | 同上 | +| - | 司机、其他 | 不属于任何配置位,不算导 / 摄有人 | + +--- + +## 六.6、修改前后对比 + +### 字段级对比 + +| 字段 | 改前 | 改后 | +|------|------|------| +| `chips.guide` / `chips.photo`,导 / 摄明细 `aggregateStatus` | 按户(#7204):无计入户 `TODO`;计入户零指派 `TODO`;部分指派 `DOING`;全部指派 `DONE` | 按团期名册:只有 `TODO` / `DONE`,判定见六.5 | +| `chipStats.guide/photo.total`,导 / 摄明细 `totalCount` | 需要导游 / 摄影的户数 | 名册这一位:1;成团后整团不需要且名册没人时为 0 | +| `chipStats.guide/photo.done`,导 / 摄明细 `doneCount` | 已指派的户数 | 名册有人 1,否则 0 | +| `chipStats.guide/photo.error` | 恒 0 | 恒 0(不变) | +| `chips.contract/insurance`,合同 / 保险明细 `aggregateStatus` | 四项齐判定用按户的导 / 摄结果 | 用按名册的导 / 摄结果 | + +### 行为级对比(测试服部署前后同一批只读请求;计数写作 done/total) + +| 场景 | 改前 | 改后 | +|------|------|------| +| 实例团期 `2101506167098511362`(物料准备中,12 户都无需导摄,名册导游位 2 人、摄影位 1 人)导 / 摄 | `TODO` 0/0 | `DONE` 1/1 | +| 同上 · 合同 | `TODO` 10/12 | `DOING` 10/12 | +| 同上 · 保险 | `TODO` 12/12 | `DONE` 12/12 | +| 招募中团期 `2104491315645538305`(导游位有人、摄影位没人) | 导 / 摄 `TODO` 0/0 | 导游 `DONE` 1/1,摄影 `TODO` 0/1 | +| 成团后整团不需要、名册空的团期(部署前后都在列表里的 8 个) | 导 / 摄 `TODO` 0/0 | 导 / 摄 `DONE` 0/0 | +| 带 `productId` 的未建团班期行(实例产品下 15 行) | 导 / 摄 `TODO` 0/0 | 导 / 摄 `TODO` 0/1 | +| 团期 `2104490621953794050`(2 户都需要导摄且已指派,名册导游位、摄影位各 1 人) | 导 / 摄 `DONE` 2/2(户) | 导 / 摄 `DONE` 1/1(名册位) | +| 部分户已指派 | 导 / 摄 `DOING` | 不再出现;名册有人即 `DONE` | +| 房 / 车芯片(看板 11 行) | - | 部署前后逐字段一致 | + +--- + +## 六.7、影响评估 + +- **是否破坏向后兼容**: 否。结构、字段名、枚举值集不变;但导 / 摄计数的含义由户数变为名册位,按户展示的文案会不准确(见第四节交接清单第 2、3 项)。 +- **前端是否必须同步上线**: 否。颜色随新值自然变化;文案核对不影响功能。 +- **前端 workaround 清理点**: 若前端为导 / 摄 `DOING`「部分户已指派」写过专门的图例或提示,可删;导 / 摄汇总行里的「户」字样可删。 + +--- + +## 七、不影响范围 + +- **仅影响**: 看板列表 `chips` / `chipStats` 的导、摄两项取值与合同、保险两项的门控;导、摄、合同、保险四个芯片明细的 `aggregateStatus` 与导 / 摄计数。 +- **零影响**: + - 配房、配车芯片明细 `GET /v3/admin/order/group-batch/{groupBatchId}/chips/hotel`、`GET /v3/admin/order/group-batch/{groupBatchId}/chips/vehicle`,以及看板 `chips.hotel/vehicle`、`chipStats.hotel/vehicle`(测试服部署前后逐字段一致) + - 合同 / 保险芯片的 `totalCount`、`doneCount`、`chipStats`、逐户 `items` + - 团期详情 `GET /v3/admin/order/group-batch/{groupBatchId}` 的进度条 `progressStepper`(#8478,按确认门就绪标记计算)及其余字段 + - 合并层看板 `GET /v3/admin/order/group-batch/board` + - 团期人员配置(保存 / 名册 / 更换 / 删除 / 候选)接口 + - 子订单上的需要导游 / 摄影标记与订单侧人员指派数据(不再参与芯片判定,数据本身不变) + +--- + +## 八、测试环境已验证 + +- **环境**:TEST,`hl-order-service-v3` 运行 dev-v3 `2c87b0618`(PR #8489 合入,2026-09-28 18:33 双实例滚动完成)。 +- **方式**:经网关 `https://api.test.1814.love`,真实 admin token;构建身份探针命中(实例团期导游芯片由 `TODO` 0/0 变为 `DONE` 1/1)。手机号均为接口脱敏值。 +- **部署前后对照**:同一批只读请求,证据为会话证据 accept8469/PROBE-before.json 与 accept8469/PROBE-after.json,结果见六.6 行为级对比。 +- **造数**:团期 H「11月20日海拉尔-满洲里3日团」(团期 ID `2104511888882868226`,1 张订单,成团前只对这张单置需要导游 / 摄影),验收后已流团、订单已取消;其余团期只读。 + +| AC | 检验点 | 结果 | 证据 | +|----|--------|------|------| +| 1 | 实例团期导 / 摄:明细 `DONE` 1/1;看板不带 `productId`、带 `productId` 两条路同为 `DONE` 1/1,三处一致 | ✅ | 会话证据 accept8469/AC-1.json | +| 2 | 招募中团期:导游位有人 `DONE` 1/1、摄影位没人 `TODO` 0/1(团期标记为 0 也不算不需要),看板与明细一致;实例产品下 15 个未建团行导 / 摄均 `TODO` 0/1 | ✅ | 会话证据 accept8469/AC-2.json、accept8469/PROBE-after.json | +| 3 | 成团后整团不需要、名册空的 9 个团期看板导 / 摄均 `DONE` 0/0,抽样明细一致;团期 H(资源准备中,团期需要导摄、名册空)导 / 摄 `TODO` 0/1,看板与明细一致 | ✅ | 会话证据 accept8469/AC-3.json | +| 4 | 团期 H 流团后名册仍有 2 人,导 / 摄恒 `TODO`(计数 1/1 照实);测试服没有已返团团期可取证,已返团三态由单测矩阵覆盖(出行完毕 / 核单中 / 已结算 × 有人 / 没人需要 / 没人不需要) | ✅ | 会话证据 accept8469/AC-4.json | +| 5 | 团期 H 配导游后导游 `DONE` 1/1、摄影仍 `TODO` 0/1、合同 `TODO`;再配摄影后摄影 `DONE` 1/1;实例团期四项齐后合同 `TODO` → `DOING` 10/12、保险 `TODO` → `DONE` 12/12 | ✅ | 会话证据 accept8469/AC-5.json | +| 6 | 看板 11 行房 / 车 `chips` 与 `chipStats` 部署前后逐字段一致 | ✅ | 会话证据 accept8469/PROBE-before.json、accept8469/PROBE-after.json | +| 9 | 无 token 调导游芯片明细 → HTTP 200、业务码 401 | ✅ | 会话证据 accept8469/AC-9.json | + +验收脚本 22/22 通过(会话证据 accept8469/VERIFY-summary.json)。 + +--- + +## 九、相关历史 PR + +| PR | Issue | 说明 | 是否仍有效 | +|----|-------|------|------------| +| #7207 | #7204 | 导 / 摄芯片按户:零指派 `TODO`、部分指派 `DOING`、全部指派 `DONE` | ❌ 已被本单取代 | +| #7254 | #7250 | 六芯片透出 `chipStats` 计数 | ✅ 字段有效;导 / 摄计数单位本单改为名册位 | +| #7856 | #7853 | 导 / 摄芯片明细带出 `staffList` | ✅ 有效(内容不变) | +| #8475 | #8468 | 导 / 摄明细 `items` 恒 `[]`;该文所写「导 / 摄聚合态与计数仍按户」一句已被本单取代 | ⚠️ `items` 口径有效,聚合口径以本文为准 | +| #8480 | #8478 | 团期详情进度条 `progressStepper` | ✅ 有效,本单不改 | +| **#8489** | **#8469** | 本单:导 / 摄芯片改按团期名册,合同 / 保险门控随之变化 | ✅ 最新 | + +--- + +## 十、相关文档 + +- 工单 #8469: https://git.1814.love/wx/HL/issues/8469 +- 拆出本单的 #8468(导 / 摄明细去掉逐户人员): https://git.1814.love/wx/HL/issues/8468 +- 改前口径 #7204: https://git.1814.love/wx/HL/issues/7204 + +--- + +## 关联 / 联系人 + +### 链接 + +- **Issue**: [#8469](https://git.1814.love/wx/HL/issues/8469) +- **PR**: [#8489](https://git.1814.love/wx/HL/pulls/8489) +- **Merge commit**: [2c87b0618](https://git.1814.love/wx/HL/commit/2c87b0618) + +### 联系人 + +- **后端负责人**: @jw