文件
hl-api-changelog/changelogs-v2/2026-09/28_8469_团期导摄芯片状态改按团期名册计算-修改接口-管理后台.md
T

48 KiB
原始文件 Blame 文件历史

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 8469 团期看板导/摄芯片状态改按团期名册计算,合同/保险芯片门控随之变化 admin jw(GIT) 修改接口 deployed verified implemented mmg 17afce4236ba8157f66f0aa0ffb181e9da60ae35 v2.1 2026-09-29 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。前端已交付(导/摄汇总行随 #8468 已删;chipStatsTip total=0 改显「无需」),详见 hl-admin v2.1 提交 17afce42。 2026-09-28 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<PageResult<GroupBatchPageItemRespVO>>

字段 类型 说明
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 - 不变

请求示例

GET /v3/admin/order/group-batch?scope=ALL&pageNo=1&pageSize=100
Authorization: Bearer <admin token>

无请求体。按产品看板:GET /v3/admin/order/group-batch?productId=2101499109901778946&scope=ALL&pageNo=1&pageSize=100。

响应示例

2026-09-28 18:34 测试服实测(不带 productId;本页共 13 行,这里只保留实例团期一行,字段均为原值):

{
  "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 实测)这一行的芯片部分:

{
  "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。实测片段(同一产品另一期):
{
  "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:

{
  "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<GroupBatchChipDetailVO>

字段 类型 说明
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 起)

请求示例

GET /v3/admin/order/group-batch/2101506167098511362/chips/guide
Authorization: Bearer <admin token>

无请求体。

响应示例

2026-09-28 18:34 测试服实测,实例团期(12 户都无需配导游,名册导游位 2 名领队)。改前同一请求 aggregateStatus 为 TODO「待开始」、totalCount=0、doneCount=0,其余字段相同。

{
  "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:

{
  "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 部分):

{
  "batchId": "2104511888882868226",
  "groupBatchId": "2104511888882868226",
  "chipLabel": "配导游",
  "aggregateStatus": "TODO",
  "aggregateStatusName": "待开始",
  "totalCount": 1,
  "doneCount": 0,
  "staffList": [],
  "items": []
}

流团后名册仍有人(同一团期 H 流团后)→ 恒 TODO,计数照实 totalCount=1、doneCount=1(data 部分):

{
  "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):

{
  "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<GroupBatchChipDetailVO>

字段 类型 说明
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 起)

请求示例

GET /v3/admin/order/group-batch/2101506167098511362/chips/photo
Authorization: Bearer <admin token>

无请求体。

响应示例

2026-09-28 18:34 测试服实测,实例团期(12 户都无需配摄影,名册摄影位 1 人)。改前同一请求 aggregateStatus 为 TODO「待开始」、totalCount=0、doneCount=0,其余字段相同。

{
  "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:

{
  "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。

{
  "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<GroupBatchChipDetailVO>

字段 类型 说明
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)

请求示例

GET /v3/admin/order/group-batch/2101506167098511362/chips/contract
Authorization: Bearer <admin token>

无请求体。

响应示例

2026-09-28 18:34 测试服实测,实例团期(房 / 车 12/12 已完成,导 / 摄按名册已完成,四项齐;10/12 已签署)。items 共 12 户,这里只保留前 2 户,其余字段原值。改前同一请求 aggregateStatus 为 TODO「待开始」(被按户的导 / 摄卡住),计数与 items 相同。

{
  "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:
{
  "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。

{
  "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<GroupBatchChipDetailVO>

字段 类型 说明
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

请求示例

GET /v3/admin/order/group-batch/2101506167098511362/chips/insurance
Authorization: Bearer <admin token>

无请求体。

响应示例

2026-09-28 18:34 测试服实测,实例团期(四项齐,12/12 已出单)。items 共 12 户,这里只保留前 2 户,其余字段原值。改前同一请求 aggregateStatus 为 TODO「待开始」,计数与 items 相同。

{
  "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。

{
  "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 本单:导 / 摄芯片改按团期名册,合同 / 保险门控随之变化 ✅ 最新

十、相关文档


关联 / 联系人

链接

联系人

  • 后端负责人: @jw