From e9e28563eff01bc69dead6f230cb42076c2d66b9 Mon Sep 17 00:00:00 2001 From: jw Date: Thu, 24 Sep 2026 18:02:46 +0800 Subject: [PATCH] =?UTF-8?q?docs(changelog):=20#8354=20=E5=9B=A2=E6=9C=9F?= =?UTF-8?q?=E4=BA=BA=E5=91=98=E5=90=8D=E5=86=8C=E5=AE=9E=E6=97=B6=E5=A7=93?= =?UTF-8?q?=E5=90=8D=E6=89=8B=E6=9C=BA=EF=BC=88staffStatus/liveInfoDegrade?= =?UTF-8?q?d=EF=BC=89+=20=E5=8D=95=E4=BA=BA=E5=88=A0=E9=99=A4/=E6=9B=B4?= =?UTF-8?q?=E6=8D=A2=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 (1M context) --- ...时姓名手机与单人删除更换接口-修改接口-管理后台.md | 433 ++++++++++++++++++ 1 file changed, 433 insertions(+) create mode 100644 changelogs-v2/2026-09/24_8354_团期人员名册实时姓名手机与单人删除更换接口-修改接口-管理后台.md diff --git a/changelogs-v2/2026-09/24_8354_团期人员名册实时姓名手机与单人删除更换接口-修改接口-管理后台.md b/changelogs-v2/2026-09/24_8354_团期人员名册实时姓名手机与单人删除更换接口-修改接口-管理后台.md new file mode 100644 index 00000000..1481bd95 --- /dev/null +++ b/changelogs-v2/2026-09/24_8354_团期人员名册实时姓名手机与单人删除更换接口-修改接口-管理后台.md @@ -0,0 +1,433 @@ +--- +schema: "hl-changelog/v2" +ticket: "8354" +title: "团期配导游 / 配摄影已配置人员列表化:名册姓名手机按人员 ID 实时查询(新增 staffStatus / liveInfoDegraded)+ 新增单人删除、单人更换接口" +consumer: "admin" +author: "jw(GIT)" +change_type: "修改接口" +backend_status: "deployed" +gateway_status: "verified" +frontend_status: "pending" +frontend_owner: "mmg" +frontend_ref: "" +target_release: "" +verified_at: "" +status_note: "jw 2026-09-24 定:已配置人员改为列表展示(角色、姓名、手机号三列),做单人接口,姓名手机按人员 ID 实时查询,不动二期 #8258。PR #8357 已合 dev-v3(f457074ba)并部署 TEST,2026-09-24 17:54~18:00 经真实网关实测:名册接口把团期快照名「旧快照名」覆盖为资源库实时姓名;资源库已删除 / 已下架的人照常列出并分别标 NOT_FOUND / OFF_SHELF;对 order-v3 单个 Feign 客户端 staffBriefFeignClient 注入 1ms 超时(17:55:59~17:59:41,还原后 nacos 原文 SHA-256 逐字节一致)期间名册接口仍 200、全部行 liveInfoDegraded=true、值为快照;单人删除只删目标人,其他人的团期行与子订单副本 ID 不变;单人更换主报账人后报账人等级随行转移、预支候选变为新人;删除主报账人后 primaryReporterRemoved=true、预支候选为空;删光导游 / 摄影且有子订单需要该项时就绪位回落 0;不在本团 589508、新旧相同 100001、新人已在本团 589582、类型不符 582114、新人已下架 582118、缺 newStaffId 400、已确认团期 589598,均零写入;不带 token 401。前端需把「已配置人员」改为表格并接两个新接口,且须先修 24_frontend 配置弹窗误传团期 ID 的缺陷,故 frontend_status 记 pending。" +updated_at: "2026-09-24" +base: "dev-v3" +--- + +# 团期人员配置:名册实时姓名手机 + 单人删除 / 更换(管理后台) + +> **服务**: hl-order-service-v3(端口 8086/8186) +> **PR**: #8357 +> **Issue**: #8354 +> **日期**: 2026-09-24 +> **影响范围**: 管理后台团期详情页「配导游」「配摄影」两个页签的「已配置人员」区域 + +--- + +## ⚠️ 关键变化 + +1. **名册接口的姓名、手机号改为实时值**。以前是保存配置时存下的快照,资源库改了名或换了手机也不会变;现在每次查询都按人员 ID 实时取资源库。新增两个字段:`staffStatus`(人员在资源库的状态)和 `liveInfoDegraded`(资源服务不可用时回落快照)。原有字段不变。 +2. **新增单人删除**:`DELETE /v3/admin/group-batch/{productBatchId}/staff/{staffId}`,只删这一个人,其他人不动,同步从各子订单上移除。 +3. **新增单人更换**:`PUT /v3/admin/group-batch/{productBatchId}/staff/{staffId}/replace`,新人接替原人的角色位、排序、备注和报账人等级,同步替换到各子订单。 +4. 以上三个接口的路径变量都是**产品侧排期 ID**(`detail.productBatchId`),**不是**路由上的团期 ID。传错会拿到空名册或 589553,见 `24_frontend_团期详情配导游配摄影保存报589553弹窗误传团期ID-前端缺陷-管理后台.md`。 + +--- + +## 一、背景 + +「已配置人员」原来是一行文字(`领队 · 巴特尔 · 139****1011 领队 · 萨仁高娃 · 139****1008`),人多了看不清,也不能对单个人操作。jw 2026-09-24 定:改为表格,列为角色、姓名、手机号;做单人删除 / 更换接口;姓名手机按人员 ID 实时查询;继续使用 `order_batch_staff`,不动二期 #8258。 + +--- + +## 二、变更接口清单 + +| # | 接口 | 方法 | 路径 | 变更类型 | 说明 | +|---|---|---|---|---|---| +| 1 | 查询团期人员名册 | GET | `/v3/admin/group-batch/{productBatchId}/staff` | 修改 | 姓名 / 手机改为实时值;新增 `staffStatus` / `liveInfoDegraded` | +| 2 | 团期单人删除 | DELETE | `/v3/admin/group-batch/{productBatchId}/staff/{staffId}` | 新增 | 只删一人并同步子订单 | +| 3 | 团期单人更换 | PUT | `/v3/admin/group-batch/{productBatchId}/staff/{staffId}/replace` | 新增 | 一人换一人并同步子订单 | + +--- + +## 三、接口详情 + +### 1. 查询团期人员名册 `GET /v3/admin/group-batch/{productBatchId}/staff` + +**VO**: `List` + +#### 使用场景 + +「配导游」「配摄影」页签打开时拉取已配置人员,前端按 `staffRole` 分到导游位(`GUIDE` / `LEADER`)和摄影位(`PHOTOGRAPHER`)两张表,展示角色、姓名、手机号。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|---|---|---|---|---|---| +| productBatchId | path | Long | 是 | 产品侧排期 ID | 取 `detail.productBatchId`,不是团期 ID | + +#### 出参 + +| 字段 | 类型 | 说明 | +|---|---|---| +| id | Long(String) | 团期人员记录 ID(整位保存后会变,单人操作请用 `staffId`) | +| staffId | Long | 人员 ID,单人删除 / 更换的路径参数 | +| staffRole / staffRoleName | String | 角色及中文(领队 / 导游 / 摄影) | +| staffName | String | **实时姓名**;`staffStatus` 不是 `ON_SHELF` 时为配置时快照 | +| staffPhone | String | **实时手机号**,脱敏前 3 后 4;非 `ON_SHELF` 时为快照(可能为 null) | +| avatarUrl | String | 头像(快照) | +| sortOrder | Integer | 排序 | +| remark | String | 备注 | +| reporterRank / reporterRankName | String | 报账人等级及中文 | +| staffStatus | String | **新增**。`ON_SHELF` 上架(实时值)/ `OFF_SHELF` 已下架 / `NOT_FOUND` 资源库查不到(已删除)/ `UNKNOWN` 资源服务不可用 | +| liveInfoDegraded | Boolean | **新增**。`true` = 资源服务不可用,本行姓名手机为快照 | + +#### 请求示例 + +```http +GET /v3/admin/group-batch/2101502082564407299/staff +Authorization: Bearer +``` + +#### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": [ + { + "id": "2103044654230642690", + "staffId": 1011, + "staffRole": "LEADER", + "staffRoleName": "领队", + "staffName": "巴特尔", + "staffPhone": "139****1011", + "sortOrder": 1, + "reporterRank": "NONE", + "reporterRankName": "非报账人", + "staffStatus": "ON_SHELF", + "liveInfoDegraded": false + }, + { + "id": "8354000000001006", + "staffId": 1006, + "staffRole": "GUIDE", + "staffRoleName": "导游", + "staffName": "赵丽娜", + "staffPhone": null, + "sortOrder": 9, + "reporterRank": "NONE", + "reporterRankName": "非报账人", + "staffStatus": "OFF_SHELF", + "liveInfoDegraded": false + } + ], + "success": true +} +``` + +#### 空数据 / 降级响应 + +未配置人员返回 `[]`。资源服务不可用时仍返回 200,姓名手机为快照: + +```json +{ + "code": 200, + "message": "成功", + "data": [ + { + "staffId": 1011, + "staffRole": "LEADER", + "staffName": "巴特尔", + "staffPhone": "139****1011", + "staffStatus": "UNKNOWN", + "liveInfoDegraded": true + } + ], + "success": true +} +``` + +#### 错误响应 + +判权未改动(`group-batch:view`)。 + +```json +{ + "code": 589507, + "message": "无操作权限(当前角色未授予团期权限,或该团期不在您名下)", + "data": null, + "success": false +} +``` + +#### 业务边界 + +- 整团只调一次资源服务批量接口;资源服务异常、超时、返回失败时整体降级为快照。 +- 已下架、已删除的人**照常列出**,不会从名册里消失,前端可按 `staffStatus` 加提示(如「已下架」)。 +- 保存接口(`PUT .../staff`)的响应里这两个新字段为 `null`,只有本查询接口会填。 + +### 2. 团期单人删除 `DELETE /v3/admin/group-batch/{productBatchId}/staff/{staffId}` + +**VO**: `BatchStaffRemoveRespVO` + +#### 使用场景 + +名册表格某一行点「删除」,只移除这一个人。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|---|---|---|---|---|---| +| productBatchId | path | Long | 是 | 产品侧排期 ID | 同名册接口 | +| staffId | path | Long | 是 | 须在本团名册中 | 取名册行的 `staffId` | + +#### 出参 + +| 字段 | 类型 | 说明 | +|---|---|---| +| productBatchId | Long(String) | 回显 | +| groupBatchId | Long(String) | 运营团期 ID | +| removedStaffId | Long | 被删除的人员 ID | +| removedStaffRole | String | 被删除人员的角色 | +| primaryReporterRemoved | Boolean | 被删的是否是主报账人;`true` 时本团已无主报账人 | +| affectedOrderCount | Integer | 同步删除副本的活跃子订单数 | +| staffList | Array | 删除后的名册(快照值,需要实时值请重新调名册接口) | + +#### 请求示例 + +```http +DELETE /v3/admin/group-batch/2103060031777988611/staff/1008 +Authorization: Bearer +``` + +#### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": { + "productBatchId": "2103060031777988611", + "groupBatchId": "2103060033518661633", + "removedStaffId": 1008, + "removedStaffRole": "LEADER", + "primaryReporterRemoved": false, + "affectedOrderCount": 2, + "staffList": [] + }, + "success": true +} +``` + +#### 空数据 / 降级响应 + +写接口,无空数据形态;校验失败零写入,返回下方错误码。 + +#### 错误响应 + +| code | 触发条件 | +|---|---| +| `589508` | 此人不在本团(文案为「报账人不是该团期已派员工」,前端建议按码值自定义为「该人员不在本团」) | +| `589598` | 团期已确认(物料准备中及以后)或已取消 | +| `589553` | 团期未建团(通常是路径传成了团期 ID) | + +```json +{ + "code": 589508, + "message": "报账人不是该团期已派员工", + "data": null, + "success": false +} +``` + +#### 业务边界 + +- 只删目标人,本团其他人的记录一行不动。 +- 同步删除团内各活跃子订单上此人的副本,并同步子订单导游 / 摄影状态。 +- 删光导游位或摄影位、且团内有子订单需要该项时,对应就绪位回落为未就绪。 +- `primaryReporterRemoved=true` 时建议提示「主报账人已移除,团期预支需重新设置主报账人」。 + +### 3. 团期单人更换 `PUT /v3/admin/group-batch/{productBatchId}/staff/{staffId}/replace` + +**VO**: `BatchStaffReplaceReqVO` → `BatchStaffReplaceRespVO` + +#### 使用场景 + +名册表格某一行点「更换」,从候选里选一个新人替换原人。候选用既有的 `GET .../staff/candidates/page?role=GUIDE|PHOTOGRAPHER`。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|---|---|---|---|---|---| +| productBatchId | path | Long | 是 | 产品侧排期 ID | 同名册接口 | +| staffId | path | Long | 是 | 须在本团名册中 | 被换下的人 | +| newStaffId | body | Long | 是 | 上架、类型符合原配置位、不在本团、不等于 staffId | 换上的人 | + +#### 出参 + +| 字段 | 类型 | 说明 | +|---|---|---| +| productBatchId / groupBatchId | Long(String) | 回显 / 运营团期 ID | +| oldStaffId / newStaffId | Long | 被换下 / 换上的人员 ID | +| staffRole | String | 新人落库角色(导游位按新人真实类型存 `GUIDE` 或 `LEADER`) | +| reporterRank | String | 新人继承的报账人等级 | +| primaryReporterTransferred | Boolean | 被换下的是否是主报账人;`true` 时主报账人已转给新人 | +| affectedOrderCount | Integer | 同步替换副本的活跃子订单数 | +| staffList | Array | 更换后的名册(快照值) | + +#### 请求示例 + +```json +{ + "newStaffId": 1010 +} +``` + +#### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": { + "productBatchId": "2103060031777988611", + "groupBatchId": "2103060033518661633", + "oldStaffId": 1011, + "newStaffId": 1010, + "staffRole": "LEADER", + "reporterRank": "PRIMARY", + "primaryReporterTransferred": true, + "affectedOrderCount": 2, + "staffList": [] + }, + "success": true +} +``` + +#### 空数据 / 降级响应 + +写接口,无空数据形态;校验失败零写入。 + +#### 错误响应 + +| code | 触发条件 | +|---|---| +| `400` | 缺 `newStaffId` | +| `100001` | 新旧相同 | +| `589508` | 原人不在本团 | +| `589582` | 新人已在本团 | +| `582114` | 新人类型不符合该配置位(如把摄影换进导游位) | +| `582118` | **新增**。新人在资源库已下架 | +| `582103` | 资源库取不到新人(文案为「请稍后重试」,可能是新人不存在) | +| `589598` / `589553` | 团期已确认或已取消 / 未建团 | + +```json +{ + "code": 582118, + "message": "所选人员已下架,不能配置到团期,请重新选择", + "data": null, + "success": false +} +``` + +#### 业务边界 + +- 配置位不变:导游位只能换成导游或领队,摄影位只能换成摄影。 +- 新人继承原人的排序、备注、报账人等级;本团其他人一行不动。 +- 各活跃子订单上原人的副本换成新人,并同步子订单状态。 + +--- + +## 四、契约约束与正确调用方式 + +- 三个接口的 `productBatchId` 一律取 `detail.productBatchId`。 +- 单人操作用名册行的 `staffId`,不要用 `id`(`id` 在整位保存后会变)。 +- 删除或更换成功后重新调名册接口刷新表格(响应里的 `staffList` 是快照值)。 +- 删除 / 更换主报账人后,团期预支的领款人候选会随之变化(删除后为空、更换后为新人)。 + +--- + +## 五、数据库行为 + +- 零表结构变更、零迁移脚本,继续读写 `order_batch_staff`。 +- 单人删除:软删此人团期行 + 软删本团活跃子订单上此人的 `order_staff_assignment`(`source=GROUP_BATCH`)副本。 +- 单人更换:软删原人团期行并插入新人一行;子订单上软删原人副本、插入新人副本。 +- 名册查询只读。 +- 所有校验失败零写入(TEST 实测写前写后比对一致)。 + +--- + +## 六、边界行为 + +- 两个写接口与整位保存共用同一把团期锁,同一团期的写操作串行。 +- 已知窗口:若刚做过整位保存、其异步同步尚未完成就执行单人删除,被删的人可能在个别子订单上被那一轮同步写回;设置报账人等级有同类窗口。实际操作间隔秒级以上时不会出现。 + +--- + +## 六.6、修改前后对比 + +| 项 | 改前 | 改后 | +|---|---|---| +| 名册姓名 / 手机 | 保存配置时的快照 | 资源库实时值;不可用时回落快照 | +| 名册新增字段 | 无 | `staffStatus`、`liveInfoDegraded` | +| 删除一个人 | 把整个配置位的名单去掉此人后重新整体保存 | `DELETE .../staff/{staffId}` | +| 换一个人 | 同上,整体保存 | `PUT .../staff/{staffId}/replace` | +| 其他人的记录 | 每次整体保存都会重建 | 单人操作不动其他人 | + +--- + +## 六.7、影响评估 + +- 前端:名册改表格、接两个新接口、按 `staffStatus` / `liveInfoDegraded` 加提示;原有字段不变,不改也不会报错。 +- 性能:名册查询多一次资源服务批量调用。 +- 出团通知书等内部读取名册的地方仍用快照,不受影响。 + +--- + +## 七、不影响范围 + +- 整位保存 `PUT /v3/admin/group-batch/{productBatchId}/staff`、候选分页、设置报账人等级三个接口的契约。 +- 订单侧人员接口(`/v3/admin/order/{orderId}/staff*`)。 +- 二期 #8258 团期人员改表。 + +--- + +## 八、测试环境已验证 + +部署 dev-v3 @ `f457074ba` 后,2026-09-24 17:54~18:00 经真实网关 `https://api.test.1814.love` 实测(自造团期 `2103060033518661633`,一户需要导游和摄影): + +| 用例 | 期望 | 实测 | +|---|---|---| +| 构建身份:名册接口带 `staffStatus` | 新字段出现 | 4 次均带 | +| 团期快照名改成「旧快照名」后查名册 | 返回资源库实时姓名 | 返回「萨仁高娃」 | +| 资源库已删除 / 已下架的人 | 照常列出,`NOT_FOUND` / `OFF_SHELF` | 通过 | +| 注入资源服务客户端 1ms 超时 | 200,`liveInfoDegraded=true`,快照值 | 通过;还原后 nacos 原文 SHA-256 一致,复核恢复 `ON_SHELF` | +| 删除萨仁高娃 | 只删目标,其他人团期行 / 子订单副本 ID 不变 | 通过 | +| 删除不在本团的人 | 589508 零写入 | 通过 | +| 更换:新旧相同 / 原人不在本团 / 新人已在本团 / 类型不符 / 新人已下架 / 缺参 | 100001 / 589508 / 589582 / 582114 / 582118 / 400,零写入 | 通过 | +| 更换主报账人 巴特尔 → 乌日娜 | 等级转移,预支候选变为乌日娜 | 通过 | +| 删除主报账人 | `primaryReporterRemoved=true`,预支候选为空 | 通过 | +| 删光摄影 / 导游(有户需要) | 对应就绪位回落 0 | 通过 | +| 已确认团期删除 / 更换 | 589598 零写入 | 通过 | +| 不带 token | 401 | 通过 | + +造数已清理:订单取消、成团取消、产品侧班期取消。 + +--- + +## 十、相关文档 + +- Issue #8354、PR #8357 +- 前端缺陷:`24_frontend_团期详情配导游配摄影保存报589553弹窗误传团期ID-前端缺陷-管理后台.md` +- 预支领款人限定主报账人:`24_8322_团期预支核单前均可发起与领款人限定主报账人-修改接口-管理后台.md` + +--- + +## 关联 / 联系人 + +- 后端:jw +- 前端:mmg