diff --git a/changelogs-v2/2026-08/07_5655_核单导游摄影族B接口下线-删除接口-管理后台.md b/changelogs-v2/2026-08/07_5655_核单导游摄影族B接口下线-删除接口-管理后台.md new file mode 100644 index 0000000..882f351 --- /dev/null +++ b/changelogs-v2/2026-08/07_5655_核单导游摄影族B接口下线-删除接口-管理后台.md @@ -0,0 +1,426 @@ +--- +author: "yst(GIT)" +schema: "hl-changelog/v2" +ticket: "5655" +title: "核单导游/摄影族B嵌套接口下线,统一走族A扁平接口" +consumer: "admin" +change_type: "删除接口" +backend_status: "deployed" +gateway_status: "not_required" +frontend_status: "pending" +frontend_owner: "" +frontend_ref: "" +target_release: "" +verified_at: "2026-08-07" +status_note: "后端已删除族B guides/photographers 嵌套 GET/PUT 共4个路由并部署测试服;已行为级验证族B 4端点返回404、族A guide-fees/photographer-fees 正常返回。等待前端将导游/摄影页签从族B路径切换到族A扁平接口,frontend_status=pending 表示等待前端真实领取。" +updated_at: "2026-08-07" +base: "dev-v3" +--- + + +# ⚠️【删除接口·管理后台】核单导游/摄影族B嵌套接口下线,统一走族A扁平接口 (#5655) + +> **PR**: #5658 | **服务**: order-v3 | **更新时间**: 2026-08-07 + +## 1. 接口背景 + +核单页面的导游、摄影师费用历史上存在两套接口: + +- **族 A(保留)**:`/settlement/guide-fees`、`/settlement/photographer-fees`,按天扁平行结构,与住宿、餐食等页签形态一致。 +- **族 B(本次删除)**:`/settlement/staff-fees/guides`、`/settlement/staff-fees/photographers`,按人嵌套 `persons[]` 结构。 + +一笔导游/摄影费用只对应一个人,族 B 的 `persons[]` 嵌套属于过度设计,且与其他核单页签的平铺形态不一致。本次将族 B 共 4 个路由整体删除,导游/摄影核单统一由族 A 扁平接口承载。 + +**旧路径已删,调用返回 HTTP 404「接口不存在」。** 前端必须把导游、摄影师页签的查询/保存调用从族 B 路径切换到族 A 路径。 + +## 2. 变更清单 + +| # | 接口名 | 方法 | 路径 | 变更类型 | 说明 | +|---|--------|------|------|----------|------| +| 1 | 查询导游人员费用(族B) | GET | `/v3/admin/order/:orderId/settlement/staff-fees/guides` | 删除 | 路由删除,调用返回 HTTP 404 | +| 2 | 全量替换导游人员费用(族B) | PUT | `/v3/admin/order/:orderId/settlement/staff-fees/guides` | 删除 | 路由删除,调用返回 HTTP 404 | +| 3 | 查询摄影师人员费用(族B) | GET | `/v3/admin/order/:orderId/settlement/staff-fees/photographers` | 删除 | 路由删除,调用返回 HTTP 404 | +| 4 | 全量替换摄影师人员费用(族B) | PUT | `/v3/admin/order/:orderId/settlement/staff-fees/photographers` | 删除 | 路由删除,调用返回 HTTP 404 | + +替代接口(族 A,**本次未改动,已在线**,前端切换目标): + +| Tab | 查询 | 全量保存 | 确认 | +|-----|------|----------|------| +| 导游 | `GET /v3/admin/order/:orderId/settlement/guide-fees` | `PUT /v3/admin/order/:orderId/settlement/guide-fees` | `POST /v3/admin/order/:orderId/settlement/guide-fees/confirm` | +| 摄影师 | `GET /v3/admin/order/:orderId/settlement/photographer-fees` | `PUT /v3/admin/order/:orderId/settlement/photographer-fees` | `POST /v3/admin/order/:orderId/settlement/photographer-fees/confirm` | + +## 3. 接口详情 + +### 3.1 已删除:族B 导游人员费用查询与保存 + +- **原方法与路径**: + - `GET /v3/admin/order/:orderId/settlement/staff-fees/guides` + - `PUT /v3/admin/order/:orderId/settlement/staff-fees/guides` +- **使用场景**:已删除。导游核单查询/保存改用 `/settlement/guide-fees`(见 §3.3)。 +- **认证**:原接口要求管理后台登录态;接口删除后,即使登录态有效也返回 HTTP 404。 +- **幂等性**:不适用。 +- **限流**:无。 + +### 3.2 已删除:族B 摄影师人员费用查询与保存 + +- **原方法与路径**: + - `GET /v3/admin/order/:orderId/settlement/staff-fees/photographers` + - `PUT /v3/admin/order/:orderId/settlement/staff-fees/photographers` +- **使用场景**:已删除。摄影师核单查询/保存改用 `/settlement/photographer-fees`(见 §3.4)。 +- **认证**:原接口要求管理后台登录态;接口删除后,即使登录态有效也返回 HTTP 404。 +- **幂等性**:不适用。 +- **限流**:无。 + +### 3.3 替代:导游费用(族A) + +- **接口名**:查询导游费用 / 全量保存导游费用 / 确认导游费用 +- **方法与路径**: + - `GET /v3/admin/order/:orderId/settlement/guide-fees` + - `PUT /v3/admin/order/:orderId/settlement/guide-fees` + - `POST /v3/admin/order/:orderId/settlement/guide-fees/confirm` +- **使用场景**:核单页面导游页签的查询、全量保存、确认。 +- **认证**:管理后台登录态 + 订单访问权限。 +- **幂等性**:GET 只读;PUT 为全量替换语义,需携带 `expectedSourceFingerprint` 乐观锁指纹(取值为最近一次 GET 返回的 `sourceFingerprint`),指纹不匹配拒绝写入;POST confirm 重复确认不产生副作用。 +- **限流**:无接口级特殊限流。 + +### 3.4 替代:摄影师费用(族A) + +- **接口名**:查询摄影师费用 / 全量保存摄影师费用 / 确认摄影师费用 +- **方法与路径**: + - `GET /v3/admin/order/:orderId/settlement/photographer-fees` + - `PUT /v3/admin/order/:orderId/settlement/photographer-fees` + - `POST /v3/admin/order/:orderId/settlement/photographer-fees/confirm` +- **使用场景**:核单页面摄影师页签的查询、全量保存、确认。 +- **认证 / 幂等性 / 限流**:与 §3.3 导游一致。 + +## 4. 接口入参 + +### 4.1 路径参数(族A GET / PUT / POST 通用) + +| 字段 | 类型 | 必填 | 说明 | 校验 | +|------|------|------|------|------| +| `orderId` | String(Long) | 是 | 订单 ID | 正整数 | + +GET 无 Query 参数、无请求体。POST confirm 无请求体。 + +### 4.2 PUT 请求体(全量保存) + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| `expectedSourceFingerprint` | String | 是 | 乐观锁指纹,取最近一次 GET 返回的 `sourceFingerprint`;不匹配则拒绝写入 | +| `items` | Array | 是 | 全量费用行(扁平按天,无嵌套);传 `[]` 表示清空 | +| `excludedCandidateKeys` | String[] | 否 | 被排除的候选 `candidateKey` 列表;无排除传 `[]` | + +`items[]` 行字段与 GET 出参行字段一致(见 §5.2),其中 `id` 已有行需回传、新增行不传。 + +## 5. 出参字段 + +### 5.1 顶层字段(GET `data`) + +| 字段 | 类型 | 可空 | 说明 | +|------|------|------|------| +| `category` | String | 否 | 类别;导游固定 `GUIDE`,摄影师固定 `PHOTOGRAPHER` | +| `sourceFingerprint` | String | 否 | 乐观锁指纹;PUT 必须通过 `expectedSourceFingerprint` 回传 | +| `totalAmount` | String(Decimal) | 否 | 费用合计金额,字符串格式如 `"590.00"` | +| `cashPaidAmount` | String(Decimal) | 否 | 现付金额合计 | +| `unconfirmedCount` | Integer | 否 | 未确认行数 | +| `pendingCandidateCount` | Integer | 否 | 待处理候选数 | +| `settlementReady` | Boolean | 否 | 是否已具备核单条件 | +| `blockReasonCode` | String | 是 | 不具备核单条件时的机器可读原因;可核单时为 `null`,如 `ITEMS_UNCONFIRMED` | +| `editable` | Boolean | 否 | 当前是否可编辑 | +| `readOnlyReasonCode` | String | 是 | 只读原因;可编辑时为 `null` | +| `items` | Array | 否 | 费用行,扁平按天,无嵌套;无明细为 `[]` | + +### 5.2 `items[]` 行字段 + +导游(guide-fees): + +| 字段 | 类型 | 可空 | 说明 | +|------|------|------|------| +| `id` | String(Long) | 是 | 费用行 ID(雪花,字符串);候选未落库行为 `null` | +| `candidateKey` | String | 是 | 候选键;手工补录行为 `null` | +| `staffAssignmentId` | String(Long) | 是 | 人员派单 ID;无关联为 `null` | +| `serviceDate` | String(date) | 否 | 服务日期(单天),格式 `YYYY-MM-DD` | +| `name` | String | 否 | 导游姓名 | +| `serviceType` | String | 否 | 服务类型编码,见 §6.1 | +| `serviceTypeName` | String | 否 | 服务类型名称,如 `全陪导游` | +| `paymentMethod` | String | 否 | 付款方式编码,见 §6.3 | +| `paymentMethodName` | String | 否 | 付款方式名称 | +| `amount` | String(Decimal) | 否 | 金额,字符串格式如 `"295.00"` | +| `settlementConfirmStatus` | String | 否 | 核单确认状态编码,见 §6.4 | +| `settlementConfirmStatusName` | String | 否 | 核单确认状态名称 | +| `remark` | String | 是 | 备注 | +| `sourceType` | String | 否 | 来源编码,见 §6.5 | +| `sourceTypeName` | String | 否 | 来源名称,如 `手工补录` | +| `sourceActive` | Boolean | 否 | 来源是否有效 | +| `voucherUrls` | String[] | 否 | 凭证 URL;无凭证为 `[]` | +| `completionState` | String | 否 | 行完备状态,如 `COMPLETE` | +| `candidateResolution` | String | 否 | 候选处理结果,如 `INCLUDED` | + +摄影师(photographer-fees)与导游**同构**,仅两个字段名不同: + +| 语义 | 导游字段名 | 摄影师字段名 | +|------|-----------|--------------| +| 姓名 | `name` | `photographerName` | +| 类型编码/名称 | `serviceType` / `serviceTypeName` | `feeType` / `feeTypeName` | + +摄影师类型枚举见 §6.2。 + +## 6. 枚举 / 数据字典 + +### 6.1 导游 `serviceType` + +**所属字段**:guide-fees `items[].serviceType` | **类型**:String + +| 值 | 中文 | +|----|------| +| `FULL_COURSE_GUIDE` | 全陪导游 | +| `LOCAL_GUIDE` | 地接导游 | +| `COMMENTARY_SERVICE` | 讲解服务 | +| `TEMPORARY_SUPPLEMENT` | 临时补录 | + +### 6.2 摄影师 `feeType` + +**所属字段**:photographer-fees `items[].feeType` | **类型**:String + +| 值 | 中文 | +|----|------| +| `FOLLOW_SHOOT` | 跟拍 | +| `PORTRAIT` | 写真 | +| `AERIAL_SHOOT` | 航拍 | +| `EDITING_DELIVERY` | 剪辑出片 | +| `CAMERA_DRONE` | 相机/无人机 | +| `OTHER` | 其他 | + +### 6.3 `paymentMethod` + +**所属字段**:`items[].paymentMethod` | **类型**:String + +| 值 | 中文 | +|----|------| +| `COMPANY_PAID` | 公司付款 | +| `CASH_PAID` | 现付 | + +### 6.4 `settlementConfirmStatus` + +**所属字段**:`items[].settlementConfirmStatus` | **类型**:String + +| 值 | 中文 | +|----|------| +| `UNCONFIRMED` | 未确认 | +| `CONFIRMED` | 已确认 | + +### 6.5 `sourceType` + +**所属字段**:`items[].sourceType` | **类型**:String + +| 值 | 中文 | 说明 | +|----|------|------| +| `MANUAL` | 手工补录 | 核单页手工新增的费用行 | +| 其他来源编码 | — | 由派单/候选自动带入,以实际返回为准 | + +## 7. 错误码 + +### 7.1 已删除的族B专属错误码(不再返回) + +| code | 原含义 | 变更 | +|------|--------|------| +| `584023` | DRIVER detail 缺 days[] 数组 / 元素缺 service_date 或 daily_fee 字段 | 删除,不再返回 | +| `584024` | GUIDE / PHOTOGRAPHER detail 缺 persons[] / 元素缺 name / days / per_day | 删除,不再返回 | +| `584025` | LEADER detail 缺 days 或 per_day 字段 | 删除,不再返回 | +| `584028` | OTHER detail 缺 items[] / 元素缺 name / amount | 删除,不再返回 | + +前端若存在针对这 4 个错误码的分支处理,可一并清理。 + +### 7.2 本次相关错误码 + +| code | 含义 | 触发场景 | +|------|------|----------| +| `404` | 请求地址不存在 | 调用任一已删除的族B路由(staff-fees/guides、staff-fees/photographers) | +| `400` | 请求参数错误 | `orderId` 不是正整数;PUT 请求体字段缺失或非法 | +| `403` | 无访问权限 | 登录态或角色无权访问 | +| `581007` | 订单不存在 | `orderId` 对应订单不存在 | + +## 8. 示例 + +### 8.1 典型成功:GET 导游费用(族A) + +请求: + +```http +GET /v3/admin/order/2085641684778958848/settlement/guide-fees +Authorization: Bearer JWT_TOKEN +``` + +无请求体。 + +响应(测试单真实打样): + +```json +{ + "code": 200, + "message": "成功", + "data": { + "category": "GUIDE", + "sourceFingerprint": "a02c66c6...", + "totalAmount": "590.00", + "cashPaidAmount": "0.00", + "unconfirmedCount": 2, + "pendingCandidateCount": 0, + "settlementReady": false, + "blockReasonCode": "ITEMS_UNCONFIRMED", + "editable": true, + "readOnlyReasonCode": null, + "items": [ + { + "id": "2085641684778958849", + "candidateKey": null, + "staffAssignmentId": null, + "serviceDate": "2026-08-10", + "name": "王强", + "serviceType": "FULL_COURSE_GUIDE", + "serviceTypeName": "全陪导游", + "paymentMethod": "COMPANY_PAID", + "paymentMethodName": "公司付款", + "amount": "295.00", + "settlementConfirmStatus": "UNCONFIRMED", + "settlementConfirmStatusName": "未确认", + "remark": "打样导游", + "sourceType": "MANUAL", + "sourceTypeName": "手工补录", + "sourceActive": true, + "voucherUrls": [], + "completionState": "COMPLETE", + "candidateResolution": "INCLUDED" + } + ] + }, + "success": true +} +``` + +### 8.2 边界:PUT 全量保存空 items(清空导游费用) + +请求: + +```http +PUT /v3/admin/order/2085641684778958848/settlement/guide-fees +Authorization: Bearer JWT_TOKEN +Content-Type: application/json +``` + +```json +{ + "expectedSourceFingerprint": "a02c66c6...", + "items": [], + "excludedCandidateKeys": [] +} +``` + +响应: + +```json +{ + "code": 200, + "message": "成功", + "data": null, + "success": true +} +``` + +保存后重新 GET 拉取最新 `sourceFingerprint` 再渲染。 + +### 8.3 业务失败:调用已删除的族B旧路径返回 404 + +请求: + +```http +GET /v3/admin/order/2085641684778958848/settlement/staff-fees/guides +Authorization: Bearer JWT_TOKEN +``` + +无请求体。 + +响应: + +```json +{ + "code": 404, + "message": "请求地址不存在", + "data": null, + "success": false +} +``` + +PUT `/settlement/staff-fees/guides`、GET/PUT `/settlement/staff-fees/photographers` 行为一致,均为 HTTP 404。 + +## 9. 业务边界 + +**适用**: +- 核单页面导游、摄影师页签的查询、保存、确认全部走族 A 扁平接口。 +- 一笔费用一行(按人×天扁平铺开),不存在一人多行嵌套。 + +**不适用**: +- 族 B 的 `persons[]` 嵌套请求体不再有任何承载路径,不得把嵌套 body 改发到族 A(族 A 只接受扁平 `items[]`)。 +- 领队、司机、其他人员费用早在 #5380 已删除,本次不涉及。 + +**特殊边界**: +- PUT 必须携带最新 `expectedSourceFingerprint`;并发编辑或保存后未刷新指纹再保存会被拒绝,需重新 GET。 +- `items=[]` 是合法输入,表示清空该类别费用。 + +## 10. 修改前后对比 + +### 10.1 接口级对比 + +| 能力 | 改前 | 改后 | +|------|------|------| +| 导游费用查询 | `GET /settlement/staff-fees/guides`(族B,persons[] 嵌套) | `GET /settlement/guide-fees`(族A,扁平 items[]) | +| 导游费用保存 | `PUT /settlement/staff-fees/guides`(族B) | `PUT /settlement/guide-fees`(族A,带 expectedSourceFingerprint) | +| 摄影师费用查询 | `GET /settlement/staff-fees/photographers`(族B) | `GET /settlement/photographer-fees`(族A) | +| 摄影师费用保存 | `PUT /settlement/staff-fees/photographers`(族B) | `PUT /settlement/photographer-fees`(族A) | +| 族B 4 个路由 | 可用 | **已删除,调用返回 HTTP 404** | + +### 10.2 错误码对比 + +| 错误码 | 改前 | 改后 | +|--------|------|------| +| `584023` / `584024` / `584025` / `584028` | 族B 请求体校验失败时返回 | 不再返回(族B 路由整体删除) | + +## 11. 影响评估 / 回滚 + +### 11.1 影响评估 + +- **是否破坏向后兼容**:是。族B 共 4 个路由已删除,未切换的前端版本调用固定 404。 +- **前端是否必须同步上线**:是。管理后台必须把导游、摄影师页签的查询/保存切换到族 A 路径,并改为扁平 `items[]` 请求体(携带 `expectedSourceFingerprint`)。 +- **后端数据**:导游/摄影费用底层存储不变,仅接口承载形态收口;历史数据在族 A 下正常可见。 + +### 11.2 回滚边界 + +- 前端版本不得回滚到仍调用 `staff-fees/guides`、`staff-fees/photographers` 的版本,否则对应页签固定 404。 +- 后端如需回滚需恢复 4 个路由与 4 个错误码,涉及 PR #5658 整体 revert,由后端评估。 + +## 12. 注意事项 + +- 切换目标路径是 `guide-fees` / `photographer-fees`(短横线、无 staff 前缀),不要拼成 `staff-fees/guide-fees` 等混合路径。 +- 族A PUT 是全量替换语义:保存时提交整页 `items[]`;只传改动行会丢失未传行。 +- 保存成功后必须重新 GET 获取最新 `sourceFingerprint`,否则下次 PUT 指纹不匹配被拒。 +- 摄影师行字段是 `photographerName` / `feeType` / `feeTypeName`,与导游的 `name` / `serviceType` / `serviceTypeName` 不同,不要复用同一套字段映射常量。 +- `orderId`、行 `id`、`staffAssignmentId` 均按字符串处理;金额字段(`amount` / `totalAmount` / `cashPaidAmount`)为字符串格式 Decimal。 +- 清理前端对 `584023` / `584024` / `584025` / `584028` 的错误码分支。 + +## 13. 关联 / 联系人 + +### 13.1 链接 + +- **Issue**: [#5655](https://git.1814.love:8443/wx/HL/issues/5655) +- **PR**: [#5658](https://git.1814.love:8443/wx/HL/pulls/5658) +- **Merge commit**: [7d29484da77e20a706ec611893545c419f6821b2](https://git.1814.love:8443/wx/HL/commit/7d29484da77e20a706ec611893545c419f6821b2) + +### 13.2 联系人 + +- **后端负责人**: @yst(腰苏图) + +## 验证证据 + +- PR #5658 已合并至 `dev-v3`,合并提交 `7d29484da77e20a706ec611893545c419f6821b2`。 +- 测试服已部署并行为级验证:族B 4 端点(GET/PUT staff-fees/guides、GET/PUT staff-fees/photographers)均返回 HTTP 404;族A guide-fees / photographer-fees 正常返回业务数据。