32 KiB
schema, ticket, title, consumer, 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 | change_type | backend_status | gateway_status | frontend_status | frontend_owner | frontend_ref | target_release | verified_at | status_note | updated_at | base |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| hl-changelog/v2 | 5325 | 核单人员费用分 Tab | admin | 修改接口 | deployed | verified | pending | 2026-07-29 | dev-v3 |
⚠️【修改接口·管理后台】核单人员费用分 Tab(#5325)
PR:#5332 | 服务:hl-order-service-v3 | 更新时间:2026-07-29
1. 接口背景
核单页面的领队、司机、导游、摄影师、其他人员是五个独立 Tab,需要分别加载、分别保存。原 /settlement/step3 把所有人员类型聚合在同一请求中,还要求调用方提交人员类型;车辆费用也曾通过 Order 管理端接口直接暴露。
本次将人员费用改为五组独立 GET/PUT。人员类型由接口路径唯一确定,保存请求不再接收人员类型;每次 PUT 只全量替换当前 Tab,成功响应只表达成功,不返回新增、修改或删除的数据 ID。旧 Step3 和两个 Order 管理端车辆费用接口直接删除,不保留兼容路由。
变更接口
本次对外契约由五组独立 GET/PUT 和四个删除路由组成,完整清单如下。
2. 变更清单
| # | 接口名 | 方法 | 路径 | 变更类型 | 说明 |
|---|---|---|---|---|---|
| 1 | 查询领队人员费用 | GET | /v3/admin/order/:orderId/settlement/staff-fees/leaders |
新增接口 | 仅返回领队 Tab |
| 2 | 保存领队人员费用 | PUT | /v3/admin/order/:orderId/settlement/staff-fees/leaders |
新增接口 | 路径固定为领队,全量替换领队 Tab |
| 3 | 查询司机人员费用 | GET | /v3/admin/order/:orderId/settlement/staff-fees/drivers |
新增接口 | 仅返回司机 Tab |
| 4 | 保存司机人员费用 | PUT | /v3/admin/order/:orderId/settlement/staff-fees/drivers |
新增接口 | 路径固定为司机,全量替换司机 Tab |
| 5 | 查询导游人员费用 | GET | /v3/admin/order/:orderId/settlement/staff-fees/guides |
新增接口 | 仅返回导游 Tab |
| 6 | 保存导游人员费用 | PUT | /v3/admin/order/:orderId/settlement/staff-fees/guides |
新增接口 | 路径固定为导游,全量替换导游 Tab |
| 7 | 查询摄影师人员费用 | GET | /v3/admin/order/:orderId/settlement/staff-fees/photographers |
新增接口 | 仅返回摄影师 Tab |
| 8 | 保存摄影师人员费用 | PUT | /v3/admin/order/:orderId/settlement/staff-fees/photographers |
新增接口 | 路径固定为摄影师,全量替换摄影师 Tab |
| 9 | 查询其他人员费用 | GET | /v3/admin/order/:orderId/settlement/staff-fees/others |
新增接口 | 仅返回其他人员 Tab |
| 10 | 保存其他人员费用 | PUT | /v3/admin/order/:orderId/settlement/staff-fees/others |
新增接口 | 路径固定为其他人员,全量替换其他人员 Tab |
| 11 | Step3 聚合查询 | GET | /v3/admin/order/:orderId/settlement/step3 |
删除接口 | 不保留兼容 |
| 12 | Step3 聚合保存 | PUT | /v3/admin/order/:orderId/settlement/step3 |
删除接口 | 不保留兼容 |
| 13 | 查询核单车辆总车费 | GET | /v3/admin/order/:orderId/settlement/vehicle-fees |
删除接口 | 管理后台不再直接调用 |
| 14 | 确认并冻结核单车辆总车费 | POST | /v3/admin/order/:orderId/settlement/vehicle-fees/confirm |
删除接口 | 管理后台不再直接调用 |
3. 接口详情
五组接口均使用管理后台登录态,orderId 必须大于 0。GET 只返回路径所代表的人员类型;PUT 只替换路径所代表的 Tab,不影响另外四个 Tab。
3.1 领队 Tab
- 查询:
GET /v3/admin/order/:orderId/settlement/staff-fees/leaders - 保存:
PUT /v3/admin/order/:orderId/settlement/staff-fees/leaders - 人员类型:路径固定为领队,PUT 不传
staffRole - 保存语义:全量替换领队 Tab;
items: []表示清空领队 Tab - 人员引用:每行
staffId必填,必须属于当前订单的领队 - 费用明细:
detail 字段 |
类型 | 必填 | 说明 | 校验 |
|---|---|---|---|---|
days |
Integer | 是 | 服务天数 | >= 0 |
per_day |
Decimal | 是 | 每天费用 | >= 0 |
- 费用口径:计划成本为
days × per_day;实际成本为days × per_day + reimburse
3.2 司机 Tab
- 查询:
GET /v3/admin/order/:orderId/settlement/staff-fees/drivers - 保存:
PUT /v3/admin/order/:orderId/settlement/staff-fees/drivers - 人员类型:路径固定为司机,PUT 不传
staffRole - 保存语义:全量替换司机 Tab;
items: []表示清空司机 Tab - 人员引用:每行
staffId必填,必须属于当前订单的司机 - 费用明细:
detail 字段 |
类型 | 必填 | 说明 | 校验 |
|---|---|---|---|---|
days |
Array | 是 | 服务日明细 | 可为空数组 |
days[].service_date |
String(date) | 是 | 服务日期 | YYYY-MM-DD |
days[].vehicle_brief |
String | 否 | 车辆摘要 | 可空 |
days[].daily_fee |
Decimal | 是 | 日费,仅回显,不计入人员费用 | >= 0 |
days[].is_used |
Boolean | 否 | 是否使用 | 可空 |
days[].note |
String | 否 | 服务日备注 | 可空 |
extra_cost |
Decimal | 否 | 司机额外费用 | 空按 0,且 >= 0 |
extra_breakdown |
Array | 否 | 额外费用说明 | 各项金额合计必须等于 extra_cost |
extra_breakdown[].name |
String | 是 | 费用名称 | 非空 |
extra_breakdown[].amount |
Decimal | 是 | 金额 | >= 0 |
extra_breakdown[].note |
String | 否 | 备注 | 可空 |
- 费用口径:司机基础服务费不在人员费用中重复计算;计划成本为 0,实际成本为
extra_cost + reimburse
3.3 导游 Tab
- 查询:
GET /v3/admin/order/:orderId/settlement/staff-fees/guides - 保存:
PUT /v3/admin/order/:orderId/settlement/staff-fees/guides - 人员类型:路径固定为导游,PUT 不传
staffRole - 保存语义:全量替换导游 Tab;
items: []表示清空导游 Tab - 人员引用:
staffId可空;非空时必须属于当前订单的导游,空值表示按persons[]保存聚合行 - 费用明细:
detail 字段 |
类型 | 必填 | 说明 | 校验 |
|---|---|---|---|---|
persons |
Array | 是 | 导游计费明细 | 可为空数组 |
persons[].name |
String | 是 | 姓名 | 非空 |
persons[].days |
Integer | 是 | 天数 | >= 0 |
persons[].per_day |
Decimal | 是 | 每天费用 | >= 0 |
persons[].note |
String | 否 | 备注 | 可空 |
- 费用口径:计划成本为
Σ(persons[].days × persons[].per_day);实际成本为计划成本加reimburse
3.4 摄影师 Tab
- 查询:
GET /v3/admin/order/:orderId/settlement/staff-fees/photographers - 保存:
PUT /v3/admin/order/:orderId/settlement/staff-fees/photographers - 人员类型:路径固定为摄影师,PUT 不传
staffRole - 保存语义:全量替换摄影师 Tab;
items: []表示清空摄影师 Tab - 人员引用:
staffId可空;非空时必须属于当前订单的摄影师,空值表示按persons[]保存聚合行 - 费用明细:
detail 字段 |
类型 | 必填 | 说明 | 校验 |
|---|---|---|---|---|
persons |
Array | 是 | 摄影师计费明细 | 可为空数组 |
persons[].name |
String | 是 | 姓名 | 非空 |
persons[].days |
Integer | 是 | 天数 | >= 0 |
persons[].per_day |
Decimal | 是 | 每天费用 | >= 0 |
persons[].note |
String | 否 | 备注 | 可空 |
- 费用口径:计划成本为
Σ(persons[].days × persons[].per_day);实际成本为计划成本加reimburse
3.5 其他人员 Tab
- 查询:
GET /v3/admin/order/:orderId/settlement/staff-fees/others - 保存:
PUT /v3/admin/order/:orderId/settlement/staff-fees/others - 人员类型:路径固定为其他人员,PUT 不传
staffRole - 保存语义:全量替换其他人员 Tab;
items: []表示清空其他人员 Tab - 人员引用:
staffId可空;非空时必须属于当前订单的其他人员,空值表示按detail.items[]保存聚合行 - 费用明细:
detail 字段 |
类型 | 必填 | 说明 | 校验 |
|---|---|---|---|---|
items |
Array | 是 | 其他人员费用项 | 可为空数组 |
items[].name |
String | 是 | 费用名称 | 非空 |
items[].amount |
Decimal | 是 | 金额 | >= 0 |
items[].note |
String | 否 | 备注 | 可空 |
- 费用口径:计划成本为
Σ(detail.items[].amount);实际成本为计划成本加reimburse
4. 接口入参
4.1 GET 路径参数
五个 GET 的路径参数相同。
| 字段 | 类型 | 必填 | 说明 | 校验 |
|---|---|---|---|---|
orderId |
String | 是 | 订单 ID | 正整数 |
GET 无 Query 参数、无请求体。
4.2 PUT 路径参数
五个 PUT 的路径参数相同。
| 字段 | 类型 | 必填 | 说明 | 校验 |
|---|---|---|---|---|
orderId |
String | 是 | 订单 ID | 正整数 |
4.3 PUT 请求体
| 字段 | 类型 | 必填 | 说明 | 校验 |
|---|---|---|---|---|
items |
Array | 是 | 当前 Tab 的完整人员费用行 | 空数组表示清空当前 Tab |
4.4 PUT items[] 通用字段
| 字段 | 类型 | 必填 | 说明 | 校验/默认值 |
|---|---|---|---|---|
staffId |
String | 条件必填 | 当前订单人员分配 ID | 领队、司机必填;其他三个 Tab 可空;非空时必须属于当前订单且角色与路径一致 |
detail |
Object | 是 | 当前 Tab 对应的角色明细 | 结构见 §3 |
reimburse |
Decimal | 否 | 小额报销 | 空按 0,且 >= 0 |
paymentMethod |
String | 否 | 付款方式 | 空按 COMPANY_PAID |
voucherUrls |
String[] | 否 | 凭证 URL | 最多 9 个;每个非空、最长 1024 字符,仅支持 HTTP/HTTPS |
settleStatus |
String | 否 | 辅助人员结算状态 | 空按 PENDING;主报账人行不使用该字段 |
settledDate |
String(date) | 否 | 辅助人员结算日期 | YYYY-MM-DD;主报账人行不使用该字段 |
transferRef |
String | 条件必填 | 辅助人员结算转账流水号 | 最长 128 字符;辅助人员 settleStatus=COMPLETED 时必填;主报账人行不使用该字段 |
remark |
String | 否 | 备注 | 最长 500 字符 |
4.5 PUT 禁止提交的字段
请求体采用严格字段校验。以下字段属于路径确定项、服务端状态或查询回显,不得提交:
| 禁止字段 | 原因 |
|---|---|
staffRole |
人员类型由 leaders/drivers/guides/photographers/others 路径唯一确定 |
id |
保存为全量替换,不按数据行 ID 执行新增或修改 |
staffName |
查询回显字段 |
totalPlannedCost |
查询回显字段 |
totalActualCost |
查询回显字段 |
settlementConfirmStatus |
核单确认状态不由 Tab 保存请求指定 |
isPrimaryReporter |
查询回显字段 |
出现未知字段时请求失败,不会静默忽略。
5. 出参(响应)
5.1 统一响应外层
| 字段 | 类型 | 说明 |
|---|---|---|
code |
Integer | 业务码;成功为 200 |
message |
String | 结果说明 |
data |
Object/null | GET 为当前 Tab 数据;PUT 成功固定为 null |
traceId |
String/null | 链路追踪 ID |
success |
Boolean | code=200 时为 true,否则为 false |
5.2 五个 GET 的 data
| 字段 | 类型 | 说明 |
|---|---|---|
totalActualCost |
Decimal | 当前 Tab 实际费用合计 |
items |
Array | 当前 Tab 已保存行;没有已保存行时返回该角色候选草稿 |
5.3 GET data.items[]
| 字段 | 类型 | 可空 | 说明 |
|---|---|---|---|
id |
String | 是 | 已保存行 ID;候选草稿为 null |
staffId |
String | 是 | 人员分配 ID;聚合行可为 null |
staffName |
String | 是 | 人员姓名或聚合姓名摘要 |
detail |
Object | 否 | 当前 Tab 对应的角色明细,结构见 §3 |
totalPlannedCost |
Decimal | 否 | 计划成本 |
totalActualCost |
Decimal | 否 | 实际成本,已包含 reimburse |
reimburse |
Decimal | 否 | 小额报销 |
paymentMethod |
String | 否 | 付款方式 |
voucherUrls |
String[] | 否 | 凭证 URL;无凭证为 [] |
settlementConfirmStatus |
String | 否 | 人员费用核单确认状态 |
settleStatus |
String | 是 | 辅助人员结算状态;主报账人行返回 null |
settledDate |
String(date) | 是 | 辅助人员结算日期 |
transferRef |
String | 是 | 辅助人员结算转账流水号 |
isPrimaryReporter |
Boolean | 否 | 是否主报账人 |
remark |
String | 是 | 备注 |
ID 字段按字符串返回。
5.4 PUT 成功响应
五个 PUT 均为统一成功响应,不返回操作数据 ID:
{
"code": 200,
"message": "成功",
"data": null,
"traceId": null,
"success": true
}
6. 枚举 / 数据字典
6.1 paymentMethod
所属字段:PUT items[].paymentMethod、GET data.items[].paymentMethod | 类型:String | 必填:否
| 值 | 中文 | 说明 |
|---|---|---|
CASH_PAID |
现金已付 | 现金支付 |
COMPANY_PAID |
公司支付 | 请求不传时的默认值 |
SIGNED |
签单 | 按签单方式结算 |
6.2 settleStatus
所属字段:PUT items[].settleStatus、GET data.items[].settleStatus | 类型:String | 必填:否
| 值 | 中文 | 说明 |
|---|---|---|
PENDING |
待结算 | 辅助人员默认值 |
COMPLETED |
已结算 | 辅助人员使用时必须同时填写 transferRef |
主报账人行的 settleStatus 为 null。
6.3 settlementConfirmStatus
所属字段:GET data.items[].settlementConfirmStatus | 类型:String | 入参:禁止提交
| 值 | 中文 | 说明 |
|---|---|---|
UNCONFIRMED |
未确认 | Tab 保存后为未确认 |
CONFIRMED |
已确认 | 人员费用已完成核单确认 |
6.4 人员类型与路径映射
人员类型不是请求字段,仅用于说明路径含义。
| 路径尾段 | 人员类型 | 中文 |
|---|---|---|
leaders |
LEADER |
领队 |
drivers |
DRIVER |
司机 |
guides |
GUIDE |
导游 |
photographers |
PHOTOGRAPHER |
摄影师 |
others |
OTHER |
其他人员 |
7. 错误码
| code | 含义 | 触发场景 |
|---|---|---|
400 |
请求参数错误 | 提交 staffRole、id、settlementConfirmStatus 等未知/禁止字段,或字段格式、长度、枚举校验失败 |
404 |
接口不存在 | 继续调用已删除的 Step3 或 Order 管理端车辆费用接口 |
584020 |
订单不存在 | orderId 对应订单不存在 |
584021 |
当前核单状态不允许录人员费用 | PUT 时订单不是待核单或核单中 |
584023 |
司机明细非法 | days[] 缺失、服务日期/日费非法,或额外费用明细合计不等于 extra_cost |
584024 |
导游/摄影师明细非法 | persons[] 缺失,或姓名、天数、每天费用非法 |
584025 |
领队明细非法 | 缺少 days 或 per_day,或值小于 0 |
584026 |
人员实际费用非法 | 报销或折算后的实际费用小于 0 |
584027 |
人员引用无效 | staffId 不属于当前订单、角色与路径不一致,或领队/司机未传 staffId |
584028 |
其他人员明细非法 | detail.items[] 缺失,或名称、金额非法 |
584038 |
已结算但缺转账流水号 | 辅助人员 settleStatus=COMPLETED 且 transferRef 为空 |
584039 |
结算状态非法 | settleStatus 不是 PENDING 或 COMPLETED |
584080 |
团期共享科目不可在子订单录入 | 团期子订单保存非空领队或摄影师费用 |
8. 示例
以下示例中的订单 ID、人员 ID、行 ID 均为格式示例。
8.1 领队 Tab:典型 GET
请求:
GET /v3/admin/order/2080000000000000001/settlement/staff-fees/leaders
Authorization: Bearer <token>
无请求体。
响应:
{
"code": 200,
"message": "成功",
"data": {
"totalActualCost": 2450.00,
"items": [
{
"id": "2081000000000000001",
"staffId": "2082000000000000001",
"staffName": "领队甲",
"detail": {
"days": 3,
"per_day": 800.00
},
"totalPlannedCost": 2400.00,
"totalActualCost": 2450.00,
"reimburse": 50.00,
"paymentMethod": "COMPANY_PAID",
"voucherUrls": [],
"settlementConfirmStatus": "UNCONFIRMED",
"settleStatus": null,
"settledDate": null,
"transferRef": null,
"isPrimaryReporter": true,
"remark": "主报账人"
}
]
},
"traceId": null,
"success": true
}
8.2 领队 Tab:典型 PUT
请求:
PUT /v3/admin/order/2080000000000000001/settlement/staff-fees/leaders
Authorization: Bearer <token>
Content-Type: application/json
{
"items": [
{
"staffId": "2082000000000000001",
"detail": {
"days": 3,
"per_day": 800.00
},
"reimburse": 50.00,
"paymentMethod": "COMPANY_PAID",
"voucherUrls": [],
"remark": "主报账人"
}
]
}
响应:
{
"code": 200,
"message": "成功",
"data": null,
"traceId": null,
"success": true
}
8.3 司机 Tab:典型 GET
请求:
GET /v3/admin/order/2080000000000000001/settlement/staff-fees/drivers
Authorization: Bearer <token>
无请求体。
响应:
{
"code": 200,
"message": "成功",
"data": {
"totalActualCost": 120.00,
"items": [
{
"id": "2081000000000000002",
"staffId": "2082000000000000002",
"staffName": "司机甲",
"detail": {
"days": [
{
"service_date": "2026-07-29",
"vehicle_brief": "示例车辆",
"daily_fee": 700.00,
"is_used": true,
"note": ""
}
],
"extra_cost": 100.00,
"extra_breakdown": [
{
"name": "临时停车",
"amount": 100.00,
"note": ""
}
]
},
"totalPlannedCost": 0,
"totalActualCost": 120.00,
"reimburse": 20.00,
"paymentMethod": "COMPANY_PAID",
"voucherUrls": [],
"settlementConfirmStatus": "UNCONFIRMED",
"settleStatus": "PENDING",
"settledDate": null,
"transferRef": null,
"isPrimaryReporter": false,
"remark": ""
}
]
},
"traceId": null,
"success": true
}
8.4 司机 Tab:典型 PUT
请求:
PUT /v3/admin/order/2080000000000000001/settlement/staff-fees/drivers
Authorization: Bearer <token>
Content-Type: application/json
{
"items": [
{
"staffId": "2082000000000000002",
"detail": {
"days": [
{
"service_date": "2026-07-29",
"vehicle_brief": "示例车辆",
"daily_fee": 700.00,
"is_used": true,
"note": ""
}
],
"extra_cost": 100.00,
"extra_breakdown": [
{
"name": "临时停车",
"amount": 100.00,
"note": ""
}
]
},
"reimburse": 20.00,
"paymentMethod": "COMPANY_PAID",
"voucherUrls": [],
"settleStatus": "PENDING",
"settledDate": null,
"transferRef": null,
"remark": ""
}
]
}
响应:
{
"code": 200,
"message": "成功",
"data": null,
"traceId": null,
"success": true
}
8.5 导游 Tab:典型 GET
请求:
GET /v3/admin/order/2080000000000000001/settlement/staff-fees/guides
Authorization: Bearer <token>
无请求体。
响应:
{
"code": 200,
"message": "成功",
"data": {
"totalActualCost": 1800.00,
"items": [
{
"id": "2081000000000000003",
"staffId": null,
"staffName": "导游甲、导游乙",
"detail": {
"persons": [
{
"name": "导游甲",
"days": 2,
"per_day": 500.00,
"note": ""
},
{
"name": "导游乙",
"days": 2,
"per_day": 400.00,
"note": ""
}
]
},
"totalPlannedCost": 1800.00,
"totalActualCost": 1800.00,
"reimburse": 0,
"paymentMethod": "SIGNED",
"voucherUrls": [],
"settlementConfirmStatus": "UNCONFIRMED",
"settleStatus": "COMPLETED",
"settledDate": "2026-07-29",
"transferRef": "TRANSFER-20260729-001",
"isPrimaryReporter": false,
"remark": ""
}
]
},
"traceId": null,
"success": true
}
8.6 导游 Tab:典型 PUT
请求:
PUT /v3/admin/order/2080000000000000001/settlement/staff-fees/guides
Authorization: Bearer <token>
Content-Type: application/json
{
"items": [
{
"staffId": null,
"detail": {
"persons": [
{
"name": "导游甲",
"days": 2,
"per_day": 500.00,
"note": ""
},
{
"name": "导游乙",
"days": 2,
"per_day": 400.00,
"note": ""
}
]
},
"reimburse": 0,
"paymentMethod": "SIGNED",
"voucherUrls": [],
"settleStatus": "COMPLETED",
"settledDate": "2026-07-29",
"transferRef": "TRANSFER-20260729-001",
"remark": ""
}
]
}
响应:
{
"code": 200,
"message": "成功",
"data": null,
"traceId": null,
"success": true
}
8.7 摄影师 Tab:典型 GET
请求:
GET /v3/admin/order/2080000000000000001/settlement/staff-fees/photographers
Authorization: Bearer <token>
无请求体。
响应:
{
"code": 200,
"message": "成功",
"data": {
"totalActualCost": 1500.00,
"items": [
{
"id": "2081000000000000004",
"staffId": "2082000000000000004",
"staffName": "摄影师甲",
"detail": {
"persons": [
{
"name": "摄影师甲",
"days": 3,
"per_day": 500.00,
"note": ""
}
]
},
"totalPlannedCost": 1500.00,
"totalActualCost": 1500.00,
"reimburse": 0,
"paymentMethod": "COMPANY_PAID",
"voucherUrls": [],
"settlementConfirmStatus": "UNCONFIRMED",
"settleStatus": "PENDING",
"settledDate": null,
"transferRef": null,
"isPrimaryReporter": false,
"remark": ""
}
]
},
"traceId": null,
"success": true
}
8.8 摄影师 Tab:典型 PUT
请求:
PUT /v3/admin/order/2080000000000000001/settlement/staff-fees/photographers
Authorization: Bearer <token>
Content-Type: application/json
{
"items": [
{
"staffId": "2082000000000000004",
"detail": {
"persons": [
{
"name": "摄影师甲",
"days": 3,
"per_day": 500.00,
"note": ""
}
]
},
"reimburse": 0,
"paymentMethod": "COMPANY_PAID",
"voucherUrls": [],
"settleStatus": "PENDING",
"settledDate": null,
"transferRef": null,
"remark": ""
}
]
}
响应:
{
"code": 200,
"message": "成功",
"data": null,
"traceId": null,
"success": true
}
8.9 其他人员 Tab:典型 GET
请求:
GET /v3/admin/order/2080000000000000001/settlement/staff-fees/others
Authorization: Bearer <token>
无请求体。
响应:
{
"code": 200,
"message": "成功",
"data": {
"totalActualCost": 350.00,
"items": [
{
"id": "2081000000000000005",
"staffId": null,
"staffName": "临时协助",
"detail": {
"items": [
{
"name": "临时协助",
"amount": 300.00,
"note": ""
}
]
},
"totalPlannedCost": 300.00,
"totalActualCost": 350.00,
"reimburse": 50.00,
"paymentMethod": "CASH_PAID",
"voucherUrls": [
"https://example.com/vouchers/other-001.jpg"
],
"settlementConfirmStatus": "UNCONFIRMED",
"settleStatus": "COMPLETED",
"settledDate": "2026-07-29",
"transferRef": "TRANSFER-20260729-002",
"isPrimaryReporter": false,
"remark": ""
}
]
},
"traceId": null,
"success": true
}
8.10 其他人员 Tab:典型 PUT
请求:
PUT /v3/admin/order/2080000000000000001/settlement/staff-fees/others
Authorization: Bearer <token>
Content-Type: application/json
{
"items": [
{
"staffId": null,
"detail": {
"items": [
{
"name": "临时协助",
"amount": 300.00,
"note": ""
}
]
},
"reimburse": 50.00,
"paymentMethod": "CASH_PAID",
"voucherUrls": [
"https://example.com/vouchers/other-001.jpg"
],
"settleStatus": "COMPLETED",
"settledDate": "2026-07-29",
"transferRef": "TRANSFER-20260729-002",
"remark": ""
}
]
}
响应:
{
"code": 200,
"message": "成功",
"data": null,
"traceId": null,
"success": true
}
8.11 边界:清空单个 Tab
以下请求只清空导游 Tab,不影响领队、司机、摄影师和其他人员。
请求:
PUT /v3/admin/order/2080000000000000001/settlement/staff-fees/guides
Authorization: Bearer <token>
Content-Type: application/json
{
"items": []
}
响应:
{
"code": 200,
"message": "成功",
"data": null,
"traceId": null,
"success": true
}
8.12 异常:提交人员类型或服务端字段
请求:
PUT /v3/admin/order/2080000000000000001/settlement/staff-fees/drivers
Authorization: Bearer <token>
Content-Type: application/json
{
"staffRole": "GUIDE",
"items": []
}
响应:
{
"code": 400,
"message": "请求数据格式错误:人员费用 Tab 请求不支持字段: staffRole",
"data": null,
"traceId": null,
"success": false
}
id、settlementConfirmStatus 等禁止字段同样会被拒绝。
8.13 异常:辅助人员已结算但未填流水号
请求:
PUT /v3/admin/order/2080000000000000001/settlement/staff-fees/guides
Authorization: Bearer <token>
Content-Type: application/json
{
"items": [
{
"staffId": null,
"detail": {
"persons": [
{
"name": "导游甲",
"days": 1,
"per_day": 500.00
}
]
},
"settleStatus": "COMPLETED",
"transferRef": null
}
]
}
响应:
{
"code": 584038,
"message": "结算状态为 COMPLETED 时转账流水号不能为空",
"data": null,
"traceId": null,
"success": false
}
8.14 异常:调用已删除接口
请求:
GET /v3/admin/order/2080000000000000001/settlement/step3
Authorization: Bearer <token>
无请求体。
响应:
{
"code": 404,
"message": "接口不存在",
"data": null,
"traceId": null,
"success": false
}
PUT /settlement/step3、GET /settlement/vehicle-fees、POST /settlement/vehicle-fees/confirm 同样不可用。
验证证据
- 五个 Tab 的 GET 均已通过管理后台网关返回 HTTP 200、业务码 200。
staffRole、id、settlementConfirmStatus禁止字段探针均返回业务码 400。- 旧 Step3 GET/PUT、旧车辆费用 GET/confirm 路由均已返回业务码 404。
- Merge commit 已核对五组 GET/PUT 路由、严格请求字段和
Result<Void>保存响应契约。
9. 业务边界
- 每个 GET 只返回路径对应的人员类型,调用方不需要也不应再按
staffRole过滤。 - 每个 PUT 是当前 Tab 的全量替换;遗漏的当前 Tab 行会被删除,另外四个 Tab 不受影响。
items: []是合法请求,表示清空当前 Tab;items: null或缺少items会失败。- 领队、司机必须引用当前订单对应角色的
staffId。 - 导游、摄影师、其他人员允许
staffId=null的聚合行;如果传了staffId,仍必须与订单和路径角色匹配。 settlementConfirmStatus是查询状态,PUT 不接收;Tab 保存后该 Tab 行为未确认状态。settleStatus、settledDate、transferRef仅用于辅助人员的结算记录;主报账人行这三个字段不参与保存并在查询时为空。- 辅助人员
settleStatus=COMPLETED时必须填写transferRef。 - 司机
daily_fee仅回显,不计入人员费用;司机实际人员费用只计算extra_cost + reimburse。 - 团期子订单不能录入非空的领队、摄影师共享费用。
- 旧 Step3 与两个 Order 管理端车辆费用接口没有兼容期,继续调用会失败。
10. 修改前后对比
10.1 路径与调用方式
| 项目 | 修改前 | 修改后 |
|---|---|---|
| 人员费用查询 | 一个 GET /settlement/step3 返回全部人员类型 |
五个 Tab 各自 GET,只返回路径对应类型 |
| 人员费用保存 | 一个 PUT /settlement/step3 保存全部人员类型 |
五个 Tab 各自 PUT,只替换当前 Tab |
| 人员类型 | 请求行提交 staffRole |
由 URL 路径唯一确定,禁止提交 staffRole |
| 保存数据行标识 | 响应可包含新增/更新/删除 ID | PUT 成功固定 data=null |
| 保存入参 ID | 可按旧聚合结构提交 id |
全量替换,不提交 id |
| 核单确认状态 | 可在旧聚合行中携带相关状态 | settlementConfirmStatus 只查询回显,PUT 禁止提交 |
| Order 管理端车辆费用 | 前端可调用查询/确认接口 | 两个接口删除,前端不再调用 |
10.2 旧路径到新路径
| 旧调用 | 新调用 |
|---|---|
GET /settlement/step3 后按 staffRole=LEADER 过滤 |
GET /settlement/staff-fees/leaders |
GET /settlement/step3 后按 staffRole=DRIVER 过滤 |
GET /settlement/staff-fees/drivers |
GET /settlement/step3 后按 staffRole=GUIDE 过滤 |
GET /settlement/staff-fees/guides |
GET /settlement/step3 后按 staffRole=PHOTOGRAPHER 过滤 |
GET /settlement/staff-fees/photographers |
GET /settlement/step3 后按 staffRole=OTHER 过滤 |
GET /settlement/staff-fees/others |
PUT /settlement/step3 提交全部人员 |
按 Tab 调用对应 PUT |
GET /settlement/vehicle-fees |
删除,无前端替代调用 |
POST /settlement/vehicle-fees/confirm |
删除,无前端替代调用 |
11. 影响评估 / 回滚
11.1 影响评估
- 是否破坏向后兼容:是。四个旧路由直接删除,旧 Step3 请求结构不再接受。
- 前端是否必须同步调整:是。五个 Tab 必须切换到各自 GET/PUT,并删除
staffRole、id、settlementConfirmStatus等保存字段。 - 保存响应处理:PUT 只判断统一成功/失败结果,不再读取操作数据 ID。
11.2 回滚边界
- 当前接口不提供旧 Step3 和 Order 管理端车辆费用兼容路由。
- 前端若回滚到仍调用旧路由的版本,将无法完成查询或保存;回滚版本必须仍使用本文五组接口。
12. 注意事项
- 不要在五个 PUT 的根对象或行对象中发送
staffRole。 - 不要把 GET 返回的完整行对象原样回传;至少移除
id、staffName、totalPlannedCost、totalActualCost、settlementConfirmStatus、isPrimaryReporter。 - 五个 Tab 应分别维护请求状态和保存动作;保存某个 Tab 时不要拼入其他类型的行。
- PUT 成功后的
data为null,不再解析新增、修改、删除 ID。 - 删除前端对
/settlement/step3、/settlement/vehicle-fees、/settlement/vehicle-fees/confirm的调用。 - 金额字段按 Decimal 处理;ID 字段按 String 处理。
13. 关联 / 联系人
13.1 链接
- Issue:#5325
- PR:#5332
- Merge commit:10996166df493ee4237fdfdbaece611cb6c0cb52
13.2 联系人
- 后端负责人:@yst