diff --git a/changelogs-v2/2026-08/08_5674_核单导游摄影费用保存接口字段白名单-修改接口-管理后台.md b/changelogs-v2/2026-08/08_5674_核单导游摄影费用保存接口字段白名单-修改接口-管理后台.md index e43d079..8c2fae6 100644 --- a/changelogs-v2/2026-08/08_5674_核单导游摄影费用保存接口字段白名单-修改接口-管理后台.md +++ b/changelogs-v2/2026-08/08_5674_核单导游摄影费用保存接口字段白名单-修改接口-管理后台.md @@ -7,9 +7,9 @@ change_type: "修改接口" author: "yaosutu(GIT)" backend_status: "deployed" gateway_status: "verified" -frontend_status: "required" -frontend_owner: "" -frontend_ref: "" +frontend_status: "implemented" +frontend_owner: "mmg" +frontend_ref: "9694bb68" target_release: "" verified_at: "" status_note: "契约零变更的澄清说明:#5674 后保存请求 VO 对未声明字段显式拒绝(@JsonAnySetter),前端若把 GET 响应 item 原样回传会带出只读派生字段(如 sourceType)被 400 拦截。本文档给出保存入参字段白名单与必须剥掉的只读字段清单。" @@ -264,3 +264,17 @@ toSaveItem(respItem) => 只保留白名单 12 个字段,其余丢弃 ### 13.2 联系人 - **后端负责人**: @yaosutu (yst) + +## 前端实证确认(2026-08-08 mmg,hl-admin@9694bb68) + +前端保存**非原样回传响应对象**,而是 `returnDetailAdapter.js buildStaffFeeTabSaveRequest` 逐项显式构造——但与 §4.2 白名单有真实出入,已按白名单重建修复: + +| 字段 | 前端改动前 | 改动后 | +|---|---|---| +| `sourceType` | 传 `source.sourceType \|\| 'MANUAL'` | **删除**(只读派生,传了 400) | +| `settlementConfirmStatus` | 传 UNCONFIRMED/CONFIRMED | **删除**(确认状态后端算) | +| `expectedSourceFingerprint` | 导游+摄影**都传** | **仅导游传**,摄影省略(摄影不收,传了被当未知字段拒) | +| 手工/候选来源区分 | 靠 sourceType=MANUAL | 改由 `candidateKey`/`staffAssignmentId` 是否为 null 区分(changelog §4.3 口径) | +| 姓名/类型字段 | name+serviceType(导游)/photographerName+feeType(摄影) | 不变(本就不混用) | + +修复前导游保存必带 sourceType+settlementConfirmStatus → 必触发 584128 400;摄影另多传 expectedSourceFingerprint → 同样 400。修复后严格白名单。改动文件:`returnDetailAdapter.js` + 两个 spec 同步断言(新增 `not.toHaveProperty('sourceType'/'settlementConfirmStatus')`、摄影 `not.objectContaining expectedSourceFingerprint` 守卫)。step1/step2/meal/vehicle/otherIncome/otherExpense 的 settlementConfirmStatus 不在本白名单范围、契约未变,保持不动。验证:settlement 全量定向 vitest 92/92 通过;checkpoint 全绿。