--- schema: "hl-changelog/v2" ticket: "7274" title: "景区首次设置供应商免变更原因" consumer: "admin" author: "lc(GIT)" change_type: "修改接口" backend_status: "deployed" gateway_status: "verified" frontend_status: "verified" frontend_owner: "mmg" frontend_ref: "b8ed1234" target_release: "" verified_at: "2026-09-07" status_note: "前端已交付并验证(commit b8ed1234):SupplierRelationModal 新增 isScenicFirstSet(module==='SCENIC' 且无现有关系),命中时选完供应商跳过原因弹框直提 049、body 不带 changeReason 键(additionalProperties:false 不多传);submitBind/runSubmit 抽公共逻辑复用,rebind/unbind/非 SCENIC 仍走原因弹框必填校验零改动。modal 定向 Vitest 5 绿 + checkpoint 全绿(含 Vitest 全量+生产构建)。" updated_at: "2026-09-07" base: "dev-v3" --- # 景区管理:首次设置供应商免变更原因 ## 一、关键变化 景区尚未绑定供应商时,用户选择供应商并点击“确定选择”后应直接调用设置接口;不再打开“设置供应商”变更原因弹框,也不需要提交 `changeReason`。 ## 二、变更接口清单 | # | 接口 | 方法 | 路径 | 变更类型 | 说明 | |---|---|---|---|---|---| | 1 | 设置或改绑资源供应商 | PUT | `/admin/supplier/resource-relations/{resourceModule}/{resourceId}/update` | 请求必填性调整 | 仅 `SCENIC` 首次设置允许省略 `changeReason` | ## 三、接口详情 ### 1. 设置或改绑资源供应商 `PUT /admin/supplier/resource-relations/{resourceModule}/{resourceId}/update` **VO**: `SupplierResourceReassignReqVO / SupplierResourceRelationRespVO` #### 使用场景 景区管理选择候选供应商后,首次设置直接提交;同一路径继续兼容原有改绑流程。 #### 入参 | 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | |---|---|---|---|---|---| | `resourceModule` | Path | String | 是 | 景区固定为 `SCENIC` | 当前资源模块 | | `resourceId` | Path | String | 是 | 正整数 | 景区 ID | | `supplierId` | Body | String | 是 | 正整数 | 选中的供应商 ID | | `changeReason` | Body | String | 条件必填 | 最长 500 字 | `SCENIC` 首次设置可省略;景区改绑及其他资源设置/改绑仍必填 | | `expectedCurrentSupplierId` | Body | String | 改绑必填 | 与版本时间同传 | 当前关系供应商 ID | | `expectedRelationUpdateTime` | Body | String | 改绑必填 | `yyyy-MM-dd HH:mm:ss` | 当前关系的 `updateTime` | | `requiredTypeCode` | Body | String | 否 | 最长 64 字 | 景区沿用既有规则,可省略 | | `remark` | Body | String | 否 | 最长 500 字 | 关系备注 | #### 出参 | 字段 | 类型 | 说明 | |---|---|---| | `data.relationId` | String | 当前关系 ID | | `data.supplierId` / `supplierName` | String | 生效供应商 ID / 全称 | | `data.resourceModule` / `resourceId` | String | 资源模块 / 资源 ID | | `data.requiredTypeCode` | String | 景区为 `SCENIC` | | `data.available` / `unavailableReasons` | Boolean / Array | 当前可用性及原因 | | `data.updateTime` | String | 后续改绑或解绑使用的关系版本 | | 其他既有字段 | - | 响应字段和语义均未变化 | #### 请求示例 ```http PUT /admin/supplier/resource-relations/SCENIC/3001000000000000015/update Authorization: Bearer <当前有效凭证> Content-Type: application/json {"supplierId":"2094247871271350274"} ``` #### 响应示例 ```json { "code": 200, "message": "成功", "data": { "relationId": "2096882924480589826", "supplierId": "2094247871271350274", "supplierNo": "SUP2094247871271350274", "supplierName": "示例景区供应商", "resourceModule": "SCENIC", "moduleName": "景区管理", "resourceId": "3001000000000000015", "resourceName": "示例景区", "requiredTypeCode": "SCENIC", "requiredTypeName": "景区管理", "remark": null, "available": true, "unavailableReasons": [], "createTime": "2026-09-07 16:47:02", "updateTime": "2026-09-07 16:47:02" }, "success": true } ``` #### 空数据 / 降级响应 没有空成功数据;校验或依赖失败时返回业务错误和 `data: null`,不会降级为成功,也不会创建或改写关系。 #### 错误响应 ```json {"code":400,"message":"changeReason不能为空","data":null,"success":false} ``` #### 业务边界 - 只有 `SCENIC` 且当前无供应商关系的首次设置可省略 `changeReason`。 - 景区改绑仍须提交两个并发版本字段和非空原因;其他资源设置/改绑与所有解绑行为不变。 - 权限、资源数据范围、供应商状态与资格门禁不变。 ## 四、契约约束与正确调用方式 - 当前资源模块为 `SCENIC` 且没有现有关系时,供应商选择器点击“确定选择”后立即提交上述 PUT,请求体不要补默认原因或空原因。 - 提交成功后结束设置流程,不再打开 `SupplierRelationModal` 中的“设置供应商”原因弹框。 - 景区已有关系时仍按改绑流程提交两个并发版本字段和非空 `changeReason`。 - 非景区资源的首次设置、改绑,以及所有资源的解绑流程均保持原原因校验和弹框行为。 ## 五、数据库行为 首次设置成功后可立即查询到当前关系,并追加一条原因为空的关系变更审计;后端不会生成默认或伪造原因。校验失败时关系与审计均不变化。本次没有表结构或存量数据迁移。 ## 六、边界行为 - 景区显式改绑省略 `changeReason`:`code=400`、`success=false`,消息为 `changeReason不能为空`。 - 未登录:应用响应 `code=401`、`success=false`。 - 业务错误可能仍使用 HTTP 200,调用方必须同时判断响应体 `code` 和 `success`。 - 无新增响应字段、错误码、枚举或接口路径。 ## 六.6、修改前后对比 | 场景 | 修改前 | 修改后 | |---|---|---| | `SCENIC` 首次设置 | 原因必填,确定选择后打开原因弹框 | 原因可省略,确定选择后直接完成设置 | | `SCENIC` 改绑 | 原因与并发版本必填 | 不变 | | 其他资源设置/改绑、解绑 | 原因必填 | 不变 | ## 六.7、影响评估 - **是否破坏向后兼容**: 否;原有携带原因的请求仍可用。 - **前端是否必须同步上线**: 是;后端无法移除前端主动打开的弹框。 - **前端 workaround 清理点**: 景区无现有关系时,删除“确定选择后打开原因弹框”的步骤并直接提交。 ## 七、不影响范围 - **仅影响**: 管理后台景区首次设置供应商。 - **零影响**: 景区改绑、其他资源设置/改绑、所有解绑、响应字段、错误码和小程序接口。 ## 八、测试环境已验证 - 首次设置请求完全省略 `changeReason`,返回 `code=200`,关系查询与空原因审计一致。 - 匿名设置返回 `401`;景区显式改绑省略原因返回 `400`,失败路径零写入。 - 测试关系已解绑并回读恢复为未绑定状态。 **当前状态:后端已部署并验证;待前端处理。** ## 十、相关文档 - [Issue #7274](https://git.1814.love:8443/wx/HL/issues/7274) - [PR #7282](https://git.1814.love:8443/wx/HL/pulls/7282) ## 关联 / 联系人 - **Issue**: [#7274](https://git.1814.love:8443/wx/HL/issues/7274) - **PR**: [#7282](https://git.1814.love:8443/wx/HL/pulls/7282) - **Merge commit**: [86286f5fdfac0b5e097bf36ab0ac4be757aeaac0](https://git.1814.love:8443/wx/HL/commit/86286f5fdfac0b5e097bf36ab0ac4be757aeaac0) - **后端负责人**: @lc