文件
hl-api-changelog/changelogs-v2/2026-09/04_7079_团期人员配置位成员改由字典决定-修改接口-管理后台.md
T
jw a611948477
changelog-filename-gate / validate (push) Successful in 3s
团期人员配置位成员改由字典决定,取值域三处对齐(#7079)
PR #7085 合入 dev-v3(合并提交 d1b724d59),2026-09-04 部署测试环境
并经真实网关鉴权实测 7 条用例。

核心证据:15:30:33 往 group_batch_staff_slot_guide 插一行 GUIDE_ASSISTANT,
15:35:44(301 秒后)导游位候选由 7 人变 8 人——未改代码、未重启、未重新部署。
随后连打 8 次全部返回 8 人,两个实例都已回源。演示行验证后已撤除。

2 个接口的候选池来源与落库取值变更,路径/入参/出参结构全部不变:
- GET /v3/admin/group-batch/:groupBatchId/staff/candidates  候选池成员由字典决定,582113 文案变更
- PUT /v3/admin/group-batch/:groupBatchId/staff             staffRole 落真实 staffType

含字典初始化脚本 sql/dict_group_batch_staff_slot.sql(幂等,需手工执行)。
dict_type_id 取 8071/8072——8021/8022 在本机与测试环境都已被
contract_status / contract_platform 占用。

staff_role 取值域测试环境实测三处一致(字典 = 枚举 = @Pattern,8 项)。

frontend_status=not_required:路径、入参、出参结构均未变,前端无需改动;
但不要再硬编码候选池成员,也不要沿用自己提交的 staffRole 回显。
2026-09-04 15:37:23 +08:00

14 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 7079 团期人员配置位成员改由字典决定,取值域三处对齐 admin jw(GIT) 修改接口 deployed verified not_required PR #7085 已合入 dev-v3(合并提交 d1b724d59);2026-09-04 部署测试环境并经网关实测。含字典初始化脚本 sql/dict_group_batch_staff_slot.sql,需手工执行 2026-09-04 dev-v3

团期人员配置: 配置位收哪些人员类型改由数据字典决定

服务: hl-order-service-v3 PR: #7085 | Issue: #7079 | 合并提交: d1b724d59 影响范围: 管理后台「团期详情 → 配置导游/摄影」弹窗的候选池


⚠️ 关键变化

「导游位收哪些人员类型」不再写死在代码里,改由数据字典决定。业务在字典管理页面加一行,最多 5 分钟后生效,不需要发版。

group_batch_staff_slot_guide         → GUIDE、LEADER
group_batch_staff_slot_photographer  → PHOTOGRAPHER

另有一处落库取值变化:导游位并收导游与领队,改前不论选的是谁,order_batch_staff.staff_role 落的都是前端传的配置位名(往往是 GUIDE),「这一位上站的到底是导游还是领队」在数据里就丢了。现在落该人员在资源域的真实 staffType。


一、背景

人员类型 staff_type 本来就是「服务人员管理」里维护的字典,实有 7 项。而团期人员配置位只认死了导游位与摄影位两个、成员也写死在 Java 字面量里,要让研学老师也能配进导游位就得改代码发版。本次把这件事交还给业务。


二、变更接口清单

# 接口 方法 路径 变更类型 说明
1 团期人员候选列表 GET /v3/admin/group-batch/:groupBatchId/staff/candidates 候选池来源变更 成员由字典决定;582113 文案变更
2 全量保存团期人员配置 PUT /v3/admin/group-batch/:groupBatchId/staff 落库取值变更 staffRole 落真实 staffType

三、接口详情

1. 团期人员候选列表 GET /v3/admin/group-batch/:groupBatchId/staff/candidates

VO: StaffCandidateRespVO

使用场景

「配置导游 / 配置摄影」弹窗打开时调用,渲染可选人员列表。

入参

字段 位置 类型 必填 约束 说明
groupBatchId Path Long ✅ — 产品侧团期 batchId
role Query String ✅ GUIDE / PHOTOGRAPHER,大小写敏感 配置位标识;未知值返回 582113

出参 Result<List<StaffCandidateRespVO>>

字段 类型 说明
staffId Long 人员 ID,未变
staffName String 姓名,未变
staffType String 资源域人员类型,未变
staffPhone String 脱敏手机号,未变
assigned Boolean 是否已选,未变

出参结构完全没有变化,变的是这个列表里会出现哪些人——由字典 group_batch_staff_slot_* 决定。

请求示例

GET /v3/admin/group-batch/990707900901/staff/candidates?role=GUIDE

响应示例

{
  "code": 200,
  "message": "成功",
  "success": true,
  "data": [
    {
      "staffId": 1002,
      "staffName": "李雪梅",
      "staffType": "GUIDE",
      "staffPhone": "138****1002",
      "assigned": false
    },
    {
      "staffId": 1005,
      "staffName": "刘大山",
      "staffType": "LEADER",
      "staffPhone": "138****1005",
      "assigned": false
    }
  ]
}

空数据 / 降级响应

字典读空或字典服务不可用时不报错,回落到内置默认值(导游位 GUIDE+LEADER,摄影位 PHOTOGRAPHER)并打 WARN,候选列表照常返回。资源域无可用人员时返回空数组:

{
  "code": 200,
  "message": "成功",
  "success": true,
  "data": []
}

错误响应

配置位标识未知(含小写 guide、DRIVER):

{
  "code": 582113,
  "message": "人员配置位不合法,请检查配置位标识",
  "success": false,
  "data": null
}

业务边界

  • 配置位成员来自字典,改字典后各实例最多 5 分钟内生效(本地缓存有界 TTL)
  • 字典里写了取值域外的人员类型会被忽略并 WARN,其余行照常生效
  • 字典整体读不到时回落内置默认值,行为与改前一致
  • role 大小写敏感,小写不认(沿用既有口径)
  • 司机不设配置位,由车务派车投影产生

2. 全量保存团期人员配置 PUT /v3/admin/group-batch/:groupBatchId/staff

VO: BatchStaffConfigReqVO

使用场景

「配置导游 / 配置摄影」弹窗点保存时调用,全量覆盖该团期人员配置。

入参

字段 位置 类型 必填 约束 说明
groupBatchId Path Long ✅ — 产品侧团期 batchId
staffList Body Array ❌ 传空则清空 全量覆盖
staffList[].staffId Body Long ✅ — 资源域人员 ID
staffList[].staffRole Body String ✅ 取值域本次扩至 8 项 见下方取值域说明
staffList[].sortOrder Body Integer ❌ 缺省 0 展示排序

出参 Result<BatchStaffConfigRespVO>

字段 类型 说明
staffList Array 落库后的人员快照;其中 staffRole 取值口径变更
affectedOrderCount Integer 扇出到的活跃子订单数,未变

请求示例

{
  "staffList": [
    {
      "staffId": 1005,
      "staffRole": "GUIDE",
      "sortOrder": 0
    }
  ]
}

响应示例

请求传的是配置位名 GUIDE,但 1005 在资源域是领队,出参与落库都归一为 LEADER:

{
  "code": 200,
  "message": "成功",
  "success": true,
  "data": {
    "staffList": [
      {
        "staffId": 1005,
        "staffRole": "LEADER",
        "staffName": "刘大山",
        "staffPhone": "138****1005",
        "sortOrder": 0
      }
    ],
    "affectedOrderCount": 1
  }
}

空数据 / 降级响应

staffList 传空数组即清空该团期全部人员配置:

{
  "code": 200,
  "message": "成功",
  "success": true,
  "data": {
    "staffList": [],
    "affectedOrderCount": 1
  }
}

错误响应

staffRole 不在取值域内:

{
  "code": 400,
  "message": "员工角色不在取值域内,取值域对齐 SettlementStaffRoleEnum 与 staff_role 字典",
  "success": false,
  "data": null
}

业务边界

  • 落库 staffRole 只在配置位内部归一:请求角色能解析到配置位、且该人员真实类型也在这个配置位成员里时才替换
  • 跨位不匹配(领队被配到摄影位)沿用入参,本次不做拒绝
  • DRIVER / OTHER 不属于任何配置位,沿用入参
  • 资源域反查不到人员类型时沿用入参
  • 导游位有人(GUIDE 或 LEADER)即置 guide_ready,与改前一致

四、契约约束与正确调用方式

  • 候选池成员不再由代码保证,前端不要硬编码「导游位只会出现导游和领队」;以接口返回为准。
  • staffRole 落库值可能与提交值不同:提交配置位名,落库是该人员的真实人员类型。前端若需回显角色,读出参里的 staffRole,不要沿用自己提交的值。
  • staffRole 取值域本次由 5 项扩至 8 项:新增 GUIDE_ASSISTANT / STUDY_TEACHER / LIFE_TEACHER。
  • 改字典不是立即全局生效:各实例本地缓存 5 分钟有界 TTL,期间不同实例口径可能不同,只影响候选池多列/少列一类人员。

五、数据库行为

无 DDL、无 Flyway 迁移。但需手工执行一个字典初始化脚本:

sql/dict_group_batch_staff_slot.sql   新增,幂等,可重复执行
表 变化
sys_dict_type 新增 2 行:group_batch_staff_slot_guide(8071) / group_batch_staff_slot_photographer(8072)
sys_dict_data 新增 3 行配置位成员;staff_role 补 STUDY_TEACHER / LIFE_TEACHER 两行
order_batch_staff.staff_role 结构未变;新写入的取值口径变了,存量行不动

dict_type_id 取 8071/8072 而非号段顺序的 8021/8022——后者在本机与测试环境都已被 contract_status / contract_platform 占用(两处实测确认)。


六、边界行为

  • 字典未初始化 → 回落内置默认值,行为与改前完全一致
  • 字典含非法人员类型 → 忽略该行 + WARN,其余生效
  • 字典全部非法 → 视同读空,回落默认值
  • 字典行 dictValue 为空或空白 → 直接跳过,不刷告警
  • Feign 返回 null / 失败 / 抛异常 → 三种都回落默认值,不把异常透给调用方
  • role 小写 / 未知 → 582113

六.5、枚举 / 数据字典

新增字典类型 2 个:group_batch_staff_slot_guide、group_batch_staff_slot_photographer。取值域 = 资源域 staff_type。

staff_role 字典扩至 8 项,与 SettlementStaffRoleEnum 和接口 @Pattern 三处对齐(测试环境实测三处完全一致)。

六.6、修改前后对比

项 变更前 变更后
配置位成员 写死在 3 处 Java 字面量 由字典决定,加一行即生效
扩一种人员类型 改代码 + 发版 改字典,最多 5 分钟生效
落库 staffRole 前端传的配置位名 该人员真实 staffType
staffRole 取值域 5 项 8 项
582113 文案 「只支持导游位与摄影位」 「请检查配置位标识」
字典不可用 — 回落内置默认值,不中断
路径 / 入参 / 出参结构 — 全部不变

六.7、影响评估

维度 评估
兼容性 字典未初始化时回落默认值,与改前完全一致,不会坏
前端 无需改动。路径、入参、出参结构均未变;但不要再硬编码候选池成员,也不要沿用自己提交的 staffRole 回显
数据 无 DDL;需手工执行一个幂等字典脚本;存量 staff_role 行不动
性能 每个配置位一次字典 Feign,5 分钟缓存;候选池按类型逐类拉取,类型多一种多一次资源域调用
回滚 git revert;字典行留着无害(回滚后代码不读它)
风险 中低。主要风险是下游若有按 staff_role == 'GUIDE' 硬比对处会受落库取值变化影响;order-v3 内已全部改为按配置位归组

七、不影响范围

  • 零影响:两个接口的路径、HTTP 方法、入参字段、出参结构
  • 零影响:摄影位口径,字典默认仍只收 PHOTOGRAPHER
  • 零影响:staff-fees 费用录入分流——只加枚举取值域,未动 SettlementStaffFeeDetailCodec 的 GUIDE/PHOTOGRAPHER 两族判定
  • 零影响:存量 order_batch_staff / order_staff_assignment 数据
  • 零影响:DRIVER / OTHER 角色的处理
  • 未新建端点

八、测试环境已验证

✅ 2026-09-04 于测试环境网关实测,真实鉴权(管理端 test_admin,角色定制师)。

  • 网关 https://api.test.1814.love:9443,分支 dev-v3,合并提交 d1b724d59
  • 部署方式:双实例滚动更新(8186 → 8086),各 10s 就绪,零停机
  • 部署内容经部署面板 /api/git/backend 交叉核对:构建时点 d1b724d59 已是 dev-v3 顶端
  • 字典初始化脚本已在测试环境执行,幂等
# 用例 期望 实测
1 导游位候选(字典 GUIDE+LEADER) 与改前一致 ✅ 7 人
2 摄影位候选 口径不变 ✅ 1 人
3 role=DRIVER 582113 新文案 ✅ 「请检查配置位标识」
4 导游位选领队(提交 GUIDE) 落库真实类型 ✅ 出参与落库均为 LEADER
5 同场景 guide_ready 仍置位 ✅ 1
6 staff_role 取值域三处对齐 字典 = 枚举 = @Pattern ✅ 8 项完全一致
7 字典加一行 GUIDE_ASSISTANT 无需发版即生效 ✅ 301 秒后候选 7 → 8 人,陈小燕出现;两个实例连打 8 次均为 8

观察:双实例持续 running,服务日志最近 200 行 ERROR / Exception 命中 0 条;配置位字典相关 WARN 0 条,说明字典读取正常、未走降级。

用例 7 是本单的核心证据:15:30:33 往字典插一行,15:35:44(301 秒后)候选列表由 7 人变 8 人——没有改代码、没有重启服务、没有重新部署。延迟符合 5 分钟有界 TTL 的设计;随后连打 8 次全部返回 8 人,两个实例都已回源。演示用的那一行验证后已撤除,出厂默认仍是 GUIDE + LEADER。

本地单测:431 例全过。新增 GroupBatchStaffSlotResolverTest 14 例(正常读取、加行即生效、去重、TTL 命中缓存、读空/Feign null/Feign 异常三种降级、降级后判定仍工作、非法值过滤、全非法回落、空白值跳过、未知角色无配置位、枚举大小写敏感);GroupBatchStaffConfigServiceTest 新增 3 例覆盖落库取值三个分支。

测试数据:一律 T7079- 前缀,验证后物理删除。test_admin 口令一次性置换,取到令牌后立即按备份还原,逐字节一致;共享库写入全程持 test-db 租约。


九、相关历史 PR

  • #7065(Refs #7063 第 1 波)本 PR 承接它,StaffSlotRoles 由事实源退化为兜底默认值
  • 裁决来源:#7063 的 D-1 / D-3 / D-4(jw 2026-09-04)

十、相关文档

  • 团期需求文档:docs/group/(dev-v3 分支)
  • 字典初始化脚本:sql/dict_group_batch_staff_slot.sql

关联 / 联系人

  • Issue: #7079
  • PR: #7085(合并提交 d1b724d59)