diff --git a/changelogs-v2/2026-08/27_6474_供应商详情分离变更记录与审批流水-新增接口-管理后台.md b/changelogs-v2/2026-08/27_6474_供应商详情分离变更记录与审批流水-新增接口-管理后台.md new file mode 100644 index 00000000..a2b16039 --- /dev/null +++ b/changelogs-v2/2026-08/27_6474_供应商详情分离变更记录与审批流水-新增接口-管理后台.md @@ -0,0 +1,499 @@ +--- +schema: "hl-changelog/v2" +ticket: "6474" +title: "供应商详情分离变更记录与审批流水" +consumer: "admin" +author: "lc(GIT)" +change_type: "新增接口" +backend_status: "deployed" +gateway_status: "verified" +frontend_status: "pending" +frontend_owner: "" +frontend_ref: "" +target_release: "" +verified_at: "" +status_note: "PR #6519 已合并 dev-v3;补充缺陷 PR #6534 已恢复旧兼容查询。hl-resource-service 已由 Deploy Panel 任务 9e69fd2c 精确发布提交 aec1de2d 至 TEST,并以真实 SUPER_ADMIN、ADMIN 和受限 CUSTOMIZER 身份完成 Gateway 只读验收。" +updated_at: "2026-08-27" +base: "dev-v3" +--- + +# 供应商管理:详情分离变更记录与审批流水 + +供应商详情新增两个相互独立的只读分页接口:“变更记录”只返回供应商主体发生过的业务变化,“审批记录”只返回供应商主体审批事实。两个列表独立计数、独立筛选、独立排序,收款账户记录不会混入。 + +旧 `/admin/supplier/items/{supplierId}/approval-records/page` 继续保留,用于仍需主体与账户变更混合列表的兼容场景;本次不删除、不改名,也不要求现有调用方同步切换。 + +## 一、背景 + +旧审批记录接口承载的是主体与收款账户变更的兼容混合列表,不能同时满足详情页“业务变更”和“审批过程”两种独立展示语义。若管理端在本地拆分或二次计数,会出现分页总数不准确、账户记录混入主体历史、审批技术字段误展示等问题。 + +本次由后端直接提供两个稳定的业务白名单视图: + +- “变更记录”展示操作类型、变更前后业务摘要、原因、生命周期状态、操作人、历史角色和发生时间。 +- “审批记录”展示审批业务、申请人、状态、动作、审批人安全展示值、意见、提交时间和完成时间。 +- 两个接口都在查询前校验可信管理身份、角色和 `supplier:approval:read` 权限。 + +## 二、变更接口清单 + +| # | 接口 | 方法 | 路径 | 变更类型 | 说明 | +|---:|---|---|---|---|---| +| 1 | 查询供应商主体变更记录 | GET | `/admin/supplier/items/{supplierId}/change-records/page` | 新增只读接口 | 独立分页返回主体变更业务摘要 | +| 2 | 查询供应商主体审批流水 | GET | `/admin/supplier/items/{supplierId}/approval-history/page` | 新增只读接口 | 独立分页返回主体审批过程与结果 | + +## 三、接口详情 + +### 1. 查询供应商主体变更记录 `GET /admin/supplier/items/{supplierId}/change-records/page` + +**VO**: `SupplierChangeRecordPageReqVO` / `SupplierChangeRecordRespVO` + +#### 使用场景 + +管理端进入供应商详情的“变更记录”页签时调用。服务端完成主体记录筛选、分页和业务摘要投影;前端不要从旧混合列表中再次筛选主体记录,也不要自行拼接前后值摘要。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|---|---|---|---:|---|---| +| `supplierId` | Path | String | 是 | 正整数 ID 字符串 | 目标供应商;不得转为 JavaScript Number | +| `page` | Query | Integer | 否 | 默认 `1`,最小 `1` | 当前页;兼容别名 `pageNo` | +| `pageSize` | Query | Integer | 否 | 默认 `20`,范围 `1..100` | 每页条数 | +| `operationType` | Query | String | 否 | `CREATE`、`UPDATE`、`ENABLE`、`DISABLE`、`DELETE` | 操作类型精确筛选 | +| `fieldName` | Query | String | 否 | 非空白,最长 64 字符 | 发生变化的业务字段精确筛选 | +| `status` | Query | String | 否 | 生命周期编码 | 按变更后的供应商状态筛选 | +| `from` | Query | String | 条件必填 | `yyyy-MM-dd HH:mm:ss` | 与 `to` 成对传入,按发生时间筛选,含边界 | +| `to` | Query | String | 条件必填 | `yyyy-MM-dd HH:mm:ss`,不得早于 `from` | 与 `from` 成对传入,含边界 | +| `sortBy` | Query | String | 否 | `occurredAt` 或 `changeLogId`,默认 `occurredAt` | 服务端白名单排序字段 | +| `sortDirection` | Query | String | 否 | `ASC` 或 `DESC`,不区分大小写,默认 `DESC` | 排序方向 | + +#### 出参 `Result>` + +分页对象固定包含 `records`、`total`、`page`、`pageSize`。 + +| 字段 | 类型 | 说明 | +|---|---|---| +| `records` | Array | 当前页主体变更记录;无数据时为 `[]` | +| `total` | Integer | 符合筛选条件的主体变更总数,不包含账户记录 | +| `page` | Integer | 当前页码 | +| `pageSize` | Integer | 当前页容量 | +| `records[].operationType` | String | 操作类型编码 | +| `records[].oldValue` | String | 变更前中文业务摘要;空值使用明确占位 | +| `records[].newValue` | String | 变更后中文业务摘要;空值使用明确占位 | +| `records[].valueAvailability` | String | `FULL` 或 `LEGACY_MASKED_UNRECOVERABLE` | +| `records[].changeReason` | String | 业务变更原因或稳定占位 | +| `records[].status` | String/null | 变更后的供应商生命周期中文名 | +| `records[].operatorName` | String | 操作人展示名;系统操作为“系统”,依赖降级为“未知管理员” | +| `records[].operatorRole` | String | 操作发生时的角色快照中文名 | +| `records[].occurredAt` | String | 变更发生时间,格式 `yyyy-MM-dd HH:mm:ss` | + +响应不会返回变更日志 ID、管理员内部 ID、原始审计 JSON、TraceId、账户 ID、证明附件或其他主体敏感快照字段。 + +#### 请求示例 + +```http +GET /admin/supplier/items/2092800000000000001/change-records/page?page=1&pageSize=20&operationType=UPDATE&sortBy=occurredAt&sortDirection=DESC +Authorization: Bearer +``` + +GET 请求无请求体。 + +#### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "success": true, + "data": { + "records": [ + { + "operationType": "UPDATE", + "oldValue": "供应商全称:示例旅行服务公司", + "newValue": "供应商全称:示例旅行服务有限公司", + "valueAvailability": "FULL", + "changeReason": "修正供应商主体名称", + "status": "合作中", + "operatorName": "示例管理员", + "operatorRole": "超级管理员", + "occurredAt": "2026-08-27 15:20:00" + } + ], + "total": 1, + "page": 1, + "pageSize": 20 + } +} +``` + +#### 空数据 / 降级响应 + +筛选结果为空仍返回成功分页,不回退到旧混合列表: + +```json +{ + "code": 200, + "message": "成功", + "success": true, + "data": { + "records": [], + "total": 0, + "page": 1, + "pageSize": 20 + } +} +``` + +历史记录无法恢复完整原值时,仍返回已有安全摘要,并明确标记: + +```json +{ + "operationType": "UPDATE", + "oldValue": "138****8000", + "newValue": "139****9000", + "valueAvailability": "LEGACY_MASKED_UNRECOVERABLE", + "changeReason": "历史记录", + "status": "合作中", + "operatorName": "未知管理员", + "operatorRole": "管理员", + "occurredAt": "2026-07-01 10:00:00" +} +``` + +#### 错误响应 + +非法筛选、分页、排序或时间范围返回参数错误,例如只传 `from`: + +```json +{ + "code": 400, + "message": "from和to必须同时传入", + "success": false, + "data": null +} +``` + +供应商不存在或已删除: + +```json +{ + "code": 395001, + "message": "供应商不存在", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 要求 Gateway 登录态、可信管理员身份、允许的读角色以及 `supplier:approval:read` 平台权限;任一门禁失败时不查询历史数据。 +- 代码角色矩阵沿用 `ADMIN`、`FINANCE`、`SUPER_ADMIN`;角色允许不等于拥有平台权限,两项必须同时满足。 +- 只读取供应商主体变更,不包含收款账户变更或审批流水。 +- `oldValue`、`newValue` 是后端形成的中文业务摘要,不是可回填编辑表单的结构化快照。 +- User 姓名依赖异常只影响 `operatorName`,分页仍成功且不会以管理员内部 ID 降级。 +- 接口只读,成功、空数据和失败场景均不修改供应商、审批、缓存或消息状态。 + +### 2. 查询供应商主体审批流水 `GET /admin/supplier/items/{supplierId}/approval-history/page` + +**VO**: `SupplierApprovalHistoryPageReqVO` / `SupplierApprovalHistoryRespVO` + +#### 使用场景 + +管理端进入供应商详情的“审批记录”页签时调用。该列表只表达主体审批申请、过程和结果,不包含主体字段变更摘要,也不包含收款账户审批。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|---|---|---|---:|---|---| +| `supplierId` | Path | String | 是 | 正整数 ID 字符串 | 目标供应商;不得转为 JavaScript Number | +| `page` | Query | Integer | 否 | 默认 `1`,最小 `1` | 当前页;兼容别名 `pageNo` | +| `pageSize` | Query | Integer | 否 | 默认 `20`,范围 `1..100` | 每页条数 | +| `bizType` | Query | String | 否 | 大写字母开头,仅大写字母、数字、下划线,最长 32 字符 | 审批业务类型精确筛选 | +| `approvalStatus` | Query | String | 否 | 大写字母开头,仅大写字母、数字、下划线,最长 20 字符 | 审批状态精确筛选 | +| `action` | Query | String | 否 | 大写字母开头,仅大写字母、数字、下划线,最长 32 字符 | 审批动作或结果精确筛选 | +| `from` | Query | String | 条件必填 | `yyyy-MM-dd HH:mm:ss` | 与 `to` 成对传入,按提交时间筛选,含边界 | +| `to` | Query | String | 条件必填 | `yyyy-MM-dd HH:mm:ss`,不得早于 `from` | 与 `from` 成对传入,含边界 | +| `sortBy` | Query | String | 否 | `submittedAt` 或 `finishedAt`,默认 `submittedAt` | 服务端白名单排序字段 | +| `sortDirection` | Query | String | 否 | `ASC` 或 `DESC`,不区分大小写,默认 `DESC` | 排序方向 | + +#### 出参 `Result>` + +分页对象固定包含 `records`、`total`、`page`、`pageSize`。 + +| 字段 | 类型 | 说明 | +|---|---|---| +| `records` | Array | 当前页主体审批记录;无数据时为 `[]` | +| `total` | Integer | 符合筛选条件的主体审批总数,不包含账户审批 | +| `page` | Integer | 当前页码 | +| `pageSize` | Integer | 当前页容量 | +| `records[].bizType` | String | 审批业务类型编码 | +| `records[].bizTypeName` | String | 审批业务类型中文名;未知编码显示“其他供应商审批” | +| `records[].applicantName` | String | 申请人展示名;系统申请为“系统”,依赖降级为“未知申请人” | +| `records[].approvalStatus` | String | 审批状态编码 | +| `records[].approvalStatusName` | String | 审批状态中文名;未知编码显示“未知状态” | +| `records[].action` | String/null | 审批动作或结果编码 | +| `records[].actionName` | String | 审批动作中文名;未知编码显示“其他动作” | +| `records[].approverName` | String | 安全展示值:“系统”“待审批”或“外部审批人” | +| `records[].opinion` | String | 审批意见;无意见时为 `—` | +| `records[].submittedAt` | String | 提交时间;历史缺失时使用该审批事实的创建时间,格式 `yyyy-MM-dd HH:mm:ss` | +| `records[].finishedAt` | String/null | 完成时间;审批中为 `null`,格式 `yyyy-MM-dd HH:mm:ss` | + +响应不会返回审批日志 ID、申请人内部 ID、requestNo、spNo、审批模板 ID、企微用户 ID、候选或详情摘要、候选或详情 JSON/密文、apply/sync 技术状态。 + +#### 请求示例 + +```http +GET /admin/supplier/items/2092800000000000001/approval-history/page?page=1&pageSize=20&approvalStatus=APPROVED&sortBy=submittedAt&sortDirection=DESC +Authorization: Bearer +``` + +GET 请求无请求体。 + +#### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "success": true, + "data": { + "records": [ + { + "bizType": "PROFILE_CREATE", + "bizTypeName": "供应商建档审批", + "applicantName": "示例管理员", + "approvalStatus": "APPROVED", + "approvalStatusName": "已通过", + "action": "SYSTEM_AUTO_APPROVE", + "actionName": "系统自动通过", + "approverName": "系统", + "opinion": "—", + "submittedAt": "2026-08-27 14:00:00", + "finishedAt": "2026-08-27 14:00:01" + } + ], + "total": 1, + "page": 1, + "pageSize": 20 + } +} +``` + +#### 空数据 / 降级响应 + +不存在符合条件的审批事实时返回成功空分页: + +```json +{ + "code": 200, + "message": "成功", + "success": true, + "data": { + "records": [], + "total": 0, + "page": 1, + "pageSize": 20 + } +} +``` + +申请人姓名依赖不可用时,该记录仍正常返回,`applicantName` 为 `未知申请人`;不会回退为内部管理员 ID。 + +#### 错误响应 + +非法枚举、分页、排序或反向时间范围返回参数错误,例如: + +```json +{ + "code": 400, + "message": "from不能晚于to", + "success": false, + "data": null +} +``` + +无业务读取权限时返回拒绝结果,且不查询审批历史: + +```json +{ + "code": 403, + "message": "无权访问供应商数据", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 权限条件与变更记录接口相同:可信管理身份、`ADMIN`/`FINANCE`/`SUPER_ADMIN` 读角色和 `supplier:approval:read` 平台权限缺一不可。 +- 只读取供应商主体审批,不包含收款账户审批或主体字段变更记录。 +- 时间筛选基于提交时间;历史提交时间为空时使用该审批事实的创建时间。 +- 申请人名称每页最多批量补全一次;User 服务异常、空响应或缺失用户时安全降级,整页不返回 500。 +- 审批人只返回业务安全展示值,不暴露企微或外部审批系统标识。 +- 接口只读,不推进审批状态,不触发审批回调,也不产生缓存、消息或配置副作用。 + +## 四、契约约束与正确调用方式 + +### 详情页接入映射 + +| 页面区域 | 正确接口 | 数据范围 | +|---|---|---| +| 变更记录 | `GET /admin/supplier/items/{supplierId}/change-records/page` | 仅主体变更 | +| 审批记录 | `GET /admin/supplier/items/{supplierId}/approval-history/page` | 仅主体审批 | +| 旧兼容混合列表 | `GET /admin/supplier/items/{supplierId}/approval-records/page` | 主体与账户变更,契约不变 | + +### ✅ 正确 / ❌ 错误调用对照 + +| 场景 | 调用 / 结果 | +|---|---| +| ✅ 分别加载两个页签 | 两条新接口分别维护自己的 `page`、`pageSize`、筛选和 `total` | +| ✅ 查询完整时间区间 | 同时传 `from=2026-08-01 00:00:00` 与 `to=2026-08-31 23:59:59` | +| ✅ 兼容旧页面 | 继续调用旧 `approval-records/page`,无需因本次新增接口修改 | +| ❌ 在前端拆旧混合列表 | 分页后再过滤会得到错误总数,也不能生成审批流水 | +| ❌ 只传一侧时间 | 返回 `400`,不执行历史查询 | +| ❌ 把 `supplierId` 转为 Number | 可能丢失精度;ID 必须始终按 String 传输和比较 | + +调用方必须同时检查 `code`、`message`、`success` 和 `data`,不能只用 HTTP 状态判断业务成功。 + +## 六、边界行为 + +- 未登录或登录态失效:统一结果业务码 `401`,不进入供应商查询。 +- 已登录但角色或平台权限不满足:业务码 `403`,不读取历史。 +- `supplierId<=0`、`page<1`、`pageSize` 不在 `1..100`、非法筛选或排序:业务码 `400`。 +- 供应商不存在或已软删除:业务码 `395001`。 +- `from`、`to` 必须同时传入,且 `from<=to`;时间边界包含起止时刻。 +- 请求超过最后一页:返回原请求页码、空 `records` 和真实 `total`,不自动改页。 +- 两个新接口的 `total` 分别统计自己的数据集,互不借用;账户变更和账户审批都不进入。 +- 旧 `approval-records/page` 的路径、请求、响应及主体/账户混合语义保持兼容。 + +## 六.5、枚举 / 数据字典 + +### `operationType`(变更记录操作类型) + +**所属字段**: `SupplierChangeRecordPageReqVO.operationType` / `SupplierChangeRecordRespVO.operationType` | **类型**: `String` + +| 值 | 中文 | 说明 | +|---|---|---| +| `CREATE` | 创建 | 创建供应商主体 | +| `UPDATE` | 更新 | 更新主体业务字段 | +| `ENABLE` | 启用 | 恢复可用状态 | +| `DISABLE` | 停用 | 暂停或禁用合作 | +| `DELETE` | 删除 | 软删除业务事实 | + +### `status`(变更后的供应商生命周期) + +**所属字段**: `SupplierChangeRecordPageReqVO.status` | **类型**: `String` + +| 值 | 中文展示 | +|---|---| +| `DRAFT` | 草稿 | +| `VETTING` | 注册审核中 | +| `ACTIVE` | 合作中 | +| `SUSPENDED` | 暂停合作 | +| `FROZEN` | 已冻结 | +| `BLACKLIST` | 黑名单 | +| `ARCHIVED` | 已归档 | + +### `valueAvailability`(变更摘要可用性) + +**所属字段**: `SupplierChangeRecordRespVO.valueAvailability` | **类型**: `String` + +| 值 | 中文 | 调用方处理 | +|---|---|---| +| `FULL` | 完整业务摘要可用 | 正常展示 `oldValue` / `newValue` | +| `LEGACY_MASKED_UNRECOVERABLE` | 历史原值不可恢复 | 展示现有摘要,并标注其为历史脱敏值;不要提示用户重试 | + +### `bizType`(主体审批业务类型) + +**所属字段**: `SupplierApprovalHistoryPageReqVO.bizType` / `SupplierApprovalHistoryRespVO.bizType` | **类型**: `String` + +| 值 | 中文展示 | 说明 | +|---|---|---| +| `PROFILE_CREATE` | 供应商建档审批 | 注册或建档审批 | +| `STATUS_CHANGE` | 供应商状态变更审批 | 生命周期状态变更审批 | +| 其他合法大写编码 | 其他供应商审批 | 为历史及后续业务保留兼容 | + +### `approvalStatus`(主体审批状态) + +**所属字段**: `SupplierApprovalHistoryPageReqVO.approvalStatus` / `SupplierApprovalHistoryRespVO.approvalStatus` | **类型**: `String` + +| 值 | 中文展示 | +|---|---| +| `PENDING` | 审批中 | +| `APPROVED` | 已通过 | +| `REJECTED` | 已驳回 | +| `CANCELED` / `CANCELLED` | 已撤销 | +| `FAILED` | 失败 | +| 其他合法大写编码 | 未知状态 | + +### `action`(主体审批动作或结果) + +**所属字段**: `SupplierApprovalHistoryPageReqVO.action` / `SupplierApprovalHistoryRespVO.action` | **类型**: `String` + +| 值 | 中文展示 | +|---|---| +| `SUBMIT` | 已提交 | +| `SYSTEM_AUTO_APPROVE` | 系统自动通过 | +| `APPLY_FAIL` | 结果应用失败 | +| `APPROVE` | 通过 | +| `REJECT` | 驳回 | +| `REVOKE` | 撤销 | +| `CANCEL` | 取消 | +| 其他合法大写编码 | 其他动作 | + +## 七、不影响范围 + +- **仅新增**:供应商详情的两个管理端只读分页契约。 +- **保持兼容**:旧 `approval-records/page` 继续返回主体与账户变更混合列表。 +- **零影响**:供应商详情、创建、更新、提交、归档、暂停合作、拉黑、删除及收款账户管理接口。 +- **零影响**:供应商写权限、数据范围、状态机、审批提交/结果应用、事务、锁、幂等、审计与软删除语义。 +- **零影响**:数据库结构与历史数据;本次无 migration、数据回填或破坏性数据操作。 +- **零影响**:Gateway 顶级路由、Nacos 配置、Redis、MQ 和跨服务写链路。 +- 后端仓库未修改任何管理端前端源码;管理端接入状态保持 `pending`。 + +## 八、测试环境已验证 + +- 本地自动化:主功能定向测试 79 项零失败;补充空上下文兼容测试套件 51 项零失败;最终 `hl-resource-service` 全量 2158 项零失败、零错误(38 项条件跳过);`GatewayRouteAuditTest` 4 项零失败。 +- 合并:主 PR #6519 合并提交 `3dc80ad69630127d91fa973a682051b2ef5c41d8`;验收发现旧兼容接口空上下文缺陷后,补充工单 #6532 / PR #6534 以最小修复合入,最新合并提交为 `aec1de2db2b4ed07d78877c1ccd4e532919bdaf3`。 +- TEST 精确部署:Deploy Panel 任务 `9e69fd2c` 成功发布 `aec1de2db2b4ed07d78877c1ccd4e532919bdaf3`;构建退出码 0,任务期 10 次有效采样均至少 2 个运行进程、2 个健康启用 Nacos 实例,零不可用采样,部署窗日志无失败标记。 +- 真实 Gateway:使用现有真实 `SUPER_ADMIN` 与同账号可切换的 `ADMIN` 身份,两条新接口的成功分页、字段白名单、独立总数、筛选、排序、边界参数和旧接口兼容均通过;`CUSTOMIZER` 返回 `403`,未认证返回 `401`。 +- TEST 数据覆盖:目标供应商存在 18 条主体变更事实和 1 条主体审批事实;对应账户变更、账户审批均为 0,验证两个新接口没有跨域混页。审批样本为 `APPROVED` / `SYSTEM_AUTO_APPROVE`;环境没有外部审批人样本,未伪造业务数据。 +- 身份说明:代码角色矩阵仍包含 `ADMIN`、`FINANCE`、`SUPER_ADMIN`。TEST 角色目录存在 `FINANCE`,但当前获批真实账号不能切换到该角色;按工单确认使用现有 `SUPER_ADMIN`(并覆盖 `ADMIN`)替代 FINANCE 实测,不创建、不修改、不伪造财务账号。 +- 清理:验收全程只读,供应商数据指纹前后一致,业务测试数据创建数为 0;真实会话均已失效处理,无数据库、Redis、MQ 或临时配置需要清理。 + +## 九、相关历史 PR + +| PR | Issue | 说明 | 是否仍有效 | +|---|---|---|---| +| #6486 | #6436 | 冻结供应商授权完整值与历史摘要语义 | ✅ 有效,本次沿用 | +| #6519 | #6474 | 新增主体变更记录与主体审批流水独立分页 | ✅ 本次主功能 | +| #6534 | #6532 | 修复旧兼容接口投影空上下文时的空指针 | ✅ 有效,保障历史兼容 | + +## 十、相关文档 + +- 关联 Issue:[#6474](https://git.1814.love:8443/wx/HL/issues/6474) +- 关联 PR:[#6519](https://git.1814.love:8443/wx/HL/pulls/6519) +- 补充缺陷 Issue:[#6532](https://git.1814.love:8443/wx/HL/issues/6532) +- 补充缺陷 PR:[#6534](https://git.1814.love:8443/wx/HL/pulls/6534) +- 管理端接入:将“变更记录”“审批记录”分别切换到两条新接口;前端引用待回填。 + +## 撤回 + +1. 管理端先停止请求两个新路径,并恢复使用旧 `approval-records/page`,避免代码回退窗口产生请求失败。 +2. 从最新 `dev-v3` 创建独立回退分支,对主功能合并执行 `git revert -m 1 --no-edit 3dc80ad69630127d91fa973a682051b2ef5c41d8`,验证后经独立 PR 合入。 +3. #6532 的空上下文修复可独立保留,它修复的是旧兼容接口且不依赖两个新路径。若明确要求连同该修复一起撤回,再按从新到旧顺序执行 `git revert -m 1 --no-edit aec1de2db2b4ed07d78877c1ccd4e532919bdaf3`;这样会重新引入旧兼容接口在特定记录上的 500 风险,不作为推荐方案。 +4. 使用 Deploy Panel 两阶段客户端,仅滚动部署 `hl-resource-service`;本次无数据库、配置、Redis 或 MQ 恢复步骤,也无不可逆数据影响。 +5. 撤回后经 Gateway 验证两个新路径不可用、旧兼容接口按选定回退范围正常,复测未认证和越权,并确认 Resource 双实例、Nacos、日志及零写入。 +6. 同步发布本 Changelog 的撤回说明;不得仅改文件名表达状态。 + +## 关联 / 联系人 + +### 链接 + +- **Issue**: [#6474](https://git.1814.love:8443/wx/HL/issues/6474) +- **PR**: [#6519](https://git.1814.love:8443/wx/HL/pulls/6519) +- **Merge commit**: [`3dc80ad6`](https://git.1814.love:8443/wx/HL/commit/3dc80ad69630127d91fa973a682051b2ef5c41d8) +- **补充 PR**: [#6534](https://git.1814.love:8443/wx/HL/pulls/6534) +- **TEST 目标提交**: [`aec1de2d`](https://git.1814.love:8443/wx/HL/commit/aec1de2db2b4ed07d78877c1ccd4e532919bdaf3) + +### 联系人 + +- **后端负责人**: @lc