--- schema: "hl-changelog/v2" ticket: "6266" title: "供应商审批记录业务展示字段调整" consumer: "admin" author: "lc(GIT)" change_type: "修改接口" backend_status: "deployed" gateway_status: "verified" frontend_status: "verified" frontend_owner: "mmg" frontend_ref: "cd7fd4c4" target_release: "" verified_at: "" status_note: "PR #6270 已合并 dev-v3,合并提交 f14544fe0 已随 Resource 双实例滚动部署到 TEST。审批记录新增供应商名称、供应商类型、操作人姓名和审批角色,隐藏四个技术字段,并把变更前后值、状态和历史原因转换为中文脱敏业务展示。管理端需同步调整表格列和字段绑定。" updated_at: "2026-08-24" base: "dev-v3" --- # 供应商审批记录业务展示字段调整 ## ⚠️ 破坏性变更 供应商详情的审批记录响应改为面向业务展示:新增供应商名称、供应商类型、操作人姓名和审批角色;不再返回变更记录 ID、字段名、审批日志 ID 和操作人 ID。管理端必须按本契约调整表格列,不能继续依赖已移除字段。 ## 变更接口 | 方法 | 路径 | 权限 | 行为变化 | |---|---|---|---| | GET | `/admin/supplier/items/{supplierId}/approval-records/page` | `supplier:approval:read` | 调整分页记录的响应字段和展示语义;请求参数、分页结构及权限不变 | ### 请求 ```http GET /admin/supplier/items/2091715622923657217/approval-records/page?page=1&pageSize=10 HTTP/1.1 Host: api.test.1814.love:9443 Authorization: Bearer ``` GET 请求无请求体。 #### 路径参数 | 参数 | 类型 | 必填 | 说明 | |---|---|---:|---| | `supplierId` | String | 是 | 供应商 ID | #### 查询参数 | 参数 | 类型 | 必填 | 默认值 | 说明 | |---|---|---:|---|---| | `page` | Integer | 否 | `1` | 页码,最小为 1;兼容别名 `pageNo` | | `pageSize` | Integer | 否 | `20` | 每页条数,范围 1–100 | | `approvalLogId` | String | 否 | — | 按关联审批日志 ID 精确筛选;仅为请求筛选条件,响应不再回传该字段 | | `operationType` | String | 否 | — | `CREATE`、`UPDATE`、`ENABLE`、`DISABLE`、`DELETE` | | `targetType` | String | 否 | — | 当前仅支持 `SUPPLIER` | | `fieldName` | String | 否 | — | 按历史变更字段精确筛选;仅为请求筛选条件,响应不再回传该字段 | | `status` | String | 否 | — | 以生命周期编码筛选:`DRAFT`、`VETTING`、`ACTIVE`、`SUSPENDED`、`FROZEN`、`BLACKLIST`、`ARCHIVED` | | `from` | String | 否 | — | 开始时间,格式 `yyyy-MM-dd HH:mm:ss`;必须与 `to` 同时传入 | | `to` | String | 否 | — | 结束时间,格式 `yyyy-MM-dd HH:mm:ss`;不得早于 `from` | | `sortBy` | String | 否 | `createTime` | `createTime` 或 `changeLogId` | | `sortDirection` | String | 否 | `DESC` | `ASC` 或 `DESC`,大小写均可 | ## 响应字段变化 ### 新增字段 | 字段 | 类型 | 空值语义 | 说明 | |---|---|---|---| | `supplierName` | String | 供应商存在时非空 | 当前供应商法定全称 | | `supplierTypes` | Array | 无类型时 `[]` | 当前供应商全部类型,主类型优先;`typeCode` 为字典值,`typeName` 为运行时中文名称 | | `operatorName` | String | 不返回 `null` | 优先返回操作人的企微姓名,其次为用户名;系统记录显示 `系统`,人员信息暂不可用时显示 `管理员#` | | `operatorRole` | String | 不返回 `null` | 审计发生时的角色快照中文名;空角色显示 `系统`,未知历史角色显示 `其他角色()` | `supplierTypes[]` 元素结构: | 字段 | 类型 | 说明 | |---|---|---| | `typeCode` | String | 供应商类型字典值 | | `typeName` | String | 供应商类型中文名称 | ### 移除字段 | 原字段 | 前端处理 | |---|---| | `changeLogId` | 删除“变更 ID”列及所有字段读取 | | `fieldName` | 删除“字段”列及所有字段读取;变更内容已经合并到中文摘要 | | `approvalLogId` | 删除“审批日志 ID”列及所有字段读取 | | `operatorId` | 改为展示 `operatorName`,不要再直接展示管理员 ID | 上述字段仅从响应记录中移除;`approvalLogId`、`fieldName` 和 `sortBy=changeLogId` 作为既有查询能力继续兼容。 ### 保留字段与新语义 | 字段 | 类型 | 新语义 | |---|---|---| | `supplierId` | String | 供应商 ID | | `operationType` | String | 操作类型编码保持不变 | | `targetType` | String | 当前固定为 `SUPPLIER` | | `targetId` | String / null | 主体变更记录为 `null` | | `oldValueMasked` | String | 变更前的中文脱敏业务摘要,不再直接返回生命周期等原始编码 | | `newValueMasked` | String | 变更后的中文脱敏业务摘要,不再直接返回生命周期等原始编码 | | `changeReason` | String | 业务原因;已识别的历史注册记录同步校正为正确原因 | | `status` | String / null | 变更后生命周期中文名,不再返回原始状态编码 | | `createTime` | String | `yyyy-MM-dd HH:mm:ss` | 生命周期展示值如下: | 原编码 | 响应中文值 | |---|---| | `DRAFT` | `草稿` | | `VETTING` | `注册审核中` | | `ACTIVE` | `合作中` | | `SUSPENDED` | `暂停合作` | | `FROZEN` | `已冻结` | | `BLACKLIST` | `黑名单` | | `ARCHIVED` | `已归档` | 审批角色常用展示值如下: | 角色快照 | `operatorRole` | |---|---| | `SUPER_ADMIN` | `超级管理员` | | `ADMIN` | `管理员` | | `FINANCE` | `财务` | | `OPERATOR` | `运营人员` | | `CUSTOMIZER` | `定制师` | | `HOUSEKEEPING_ADMIN` | `房务管理员` | | `LOGISTICS_ADMIN` | `车务管理员` | | `VEHICLE_MANAGER` | `车辆管理员` | 历史注册链路中可明确识别的原因统一为: | 场景 | `changeReason` | |---|---| | 创建供应商草稿 | `创建供应商注册草稿` | | 草稿提交注册审核 | `提交供应商注册审批` | | 注册审批通过并启用 | `供应商注册审批通过并启用合作` | ## 典型成功响应 ```json { "code": 200, "message": "成功", "traceId": "6266-success-example", "success": true, "data": { "records": [ { "supplierId": "2091715622923657217", "supplierName": "内蒙古示例景区有限公司", "supplierTypes": [ { "typeCode": "SCENIC", "typeName": "景区管理" } ], "operationType": "ENABLE", "targetType": "SUPPLIER", "targetId": null, "oldValueMasked": "供应商状态:注册审核中;供应商编号:无", "newValueMasked": "供应商状态:合作中;供应商编号:SUP2091715622923657217", "changeReason": "供应商注册审批通过并启用合作", "status": "合作中", "operatorName": "示例管理员", "operatorRole": "超级管理员", "createTime": "2026-08-24 10:34:34" } ], "total": 1, "page": 1, "pageSize": 10 } } ``` 前端不能从示例中的名称、类型或状态推导固定值;供应商名称和类型取当前档案,状态、角色和变更内容由服务端提供中文展示。 ## 边界响应 供应商存在但筛选条件下没有审批记录时返回空分页,不返回 `null`: ```json { "code": 200, "message": "成功", "traceId": "6266-empty-example", "success": true, "data": { "records": [], "total": 0, "page": 1, "pageSize": 10 } } ``` ## 错误语义 | 场景 | HTTP | 业务码 | 说明 | |---|---:|---:|---| | 缺少或无效认证 | 可能为 200 | `401` | `success=false`;不能只判断 HTTP 状态 | | 无可信管理员身份、角色或 `supplier:approval:read` 权限 | 403 | `403` | 拒绝查询,不返回审批记录 | | 供应商不存在或已删除 | 200 | `395001` | `供应商不存在` | | 查询枚举、分页或时间范围非法 | 200 | `400` | 返回对应参数校验消息 | 未认证示例: ```json { "code": 401, "message": "缺少有效的 Authorization 头", "data": null, "traceId": "6266-auth-example", "success": false } ``` ## 脱敏与兼容约束 - 税号、联系电话、证件号和银行账号等敏感内容始终按字段语义重新脱敏;历史摘要也不会因旧数据格式而返回完整敏感值。 - 集合型资料只返回有界中文摘要;未知历史资料显示为安全的“其他资料:已变更”,客户端不要解析摘要反推结构化表单。 - 无变更值统一显示 `—`;前端直接展示服务端摘要,不再对 `oldValueMasked`、`newValueMasked` 或 `status` 做生命周期编码翻译。 - `supplierName` 和 `supplierTypes` 是当前供应商档案信息,不是每次审批发生时的历史快照。 - 本次不修改请求参数、分页外壳、认证方式、权限码、Gateway 路由或操作类型编码。 ## 管理端改造清单 1. 隐藏“变更 ID”“字段”“审批日志 ID”列。 2. 新增“供应商名称”“供应商类型”“操作人”“审批角色”列,分别绑定 `supplierName`、`supplierTypes`、`operatorName`、`operatorRole`。 3. “变更前(脱敏)”“变更后(脱敏)”直接展示 `oldValueMasked`、`newValueMasked`,不再显示原始状态编码。 4. “状态快照”直接展示中文 `status`;操作类型筛选仍提交既有英文编码。 5. 删除对 `changeLogId`、`fieldName`、`approvalLogId`、`operatorId` 的响应依赖。 ## 验证证据 - 自动化:审批记录投影与契约定向测试 22 项零失败;Supplier 聚焦回归 196 项零失败(1 项条件跳过);Resource 全量 1953 项零失败(38 项仓库既有条件跳过)。 - 部署:TEST 部署任务 `73bfe0aa` 成功、退出码 0;`hl-resource-service` 的 8182、8082 双实例依次启动并健康。部署服务器 HEAD `4de8e1703` 包含目标合并提交 `f14544fe0` 和功能提交 `bdcb48d78`。 - 真实 Gateway:管理端开发代理明确指向 `https://api.test.1814.love:9443`;有效超级管理员查询得到 `code=200`、`success=true` 和 4 条真实审批记录。 - 响应断言:四个新增字段在每条记录中均存在,四个移除字段均不存在;变更前后摘要和状态未出现 `DRAFT`、`VETTING`、`ACTIVE` 等原始生命周期编码;操作人返回姓名、审批角色返回中文。 - 原因断言:同一供应商的创建、提交、审批通过记录分别返回正确中文业务原因。 - 认证门禁:直接经 TEST Gateway 不携带 Authorization 查询,返回 HTTP 200、业务码 `401`、`success=false`。 - 清理:本次 TEST 验收仅执行只读查询,未创建、修改或删除业务数据,无需数据清理。 ## 撤回 1. 从最新 `dev-v3` 创建回退分支,执行 `git revert -m 1 --no-edit f14544fe0430ccafb7b74bca1ef43c080eabf491`,经独立 PR 合入。 2. 重新构建并滚动部署 `hl-resource-service`;无需恢复数据库、配置、Redis 或 MQ,也没有不可逆数据影响。 3. 回退后审批记录会恢复旧响应字段和旧展示语义;管理端若已接入新字段,必须同步回退字段绑定,避免空列。 4. 经 Gateway 复测成功分页、空分页、未认证、无权限、中文/旧编码展示、敏感字段脱敏和历史原因。 5. 撤回本 Changelog 时,以新的文档提交删除本文件并通知管理端停止消费新契约;不要重写已发布提交历史。 ## 关联 / 联系人 - **Issue**: [#6266](https://git.1814.love:8443/wx/HL/issues/6266) - **PR**: [#6270](https://git.1814.love:8443/wx/HL/pulls/6270) - **合并提交**: [f14544fe0](https://git.1814.love:8443/wx/HL/commit/f14544fe0430ccafb7b74bca1ef43c080eabf491) - **后端负责人**: @lc