hl-api-changelog/changelogs-v2/2026-08/07_5655_核单导游摄影族B接口下线-删除接口-管理后台.md
Mimingguang 20255492d0
一些检查失败了
changelog-filename-gate / validate (push) Failing after 1s
chore(v2): 标记 #5655 admin 前端已实现 (hl-admin@ee7a5d58)
族B→族A 切换已上线:直连 guide-fees/photographer-fees + 类别级指纹乐观锁
+ 并入 CategoryTable + 人员下拉仅预填姓名 + 不接 confirm + 候选最小实现。
如实标注待确认项:人员指纹冲突错误码按车辆域 584108 复用,待后端确认。
2026-08-08 09:42:52 +08:00

433 行
18 KiB
Markdown

此文件含有模棱两可的 Unicode 字符

此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。

---
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: "implemented"
frontend_owner: "mmg"
frontend_ref: "ee7a5d58"
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-08"
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 正常返回业务数据。
## 前端交付2026-08-08 mmg,hl-admin@ee7a5d58
族B→族A 切换已上线 v2.1。导游/摄影师页签查询/保存直连族A `guide-fees`/`photographer-fees`,废弃按人嵌套 StaffFeeTable、并入通用 CategoryTable与住宿/餐食/车辆页签同形态;PUT 携带 `expectedSourceFingerprint` 类别级指纹乐观锁(照车辆 version 模式 GET attach / 保存后 re-GET 写回 / 冲突刷新)。导游 `name`/`serviceType` 与摄影 `photographerName`/`feeType` 分别映射未复用;人员下拉保留仅预填姓名族A 无 staffId 落点);未接 confirm 端点(确认语义行级随 PUT;候选最小实现 excludedCandidateKeys 恒 []。
**待后端确认**:人员费用指纹冲突的错误码 changelog 未给出,前端按车辆域既有 `584108` 复用做冲突刷新分支;若人员域实际返回别的码,请告之以对齐(不阻塞,缺省时错误照常透传提示,仅无自动刷新)。