# 用户服务接口契约审计修复（错误码下移 Service + Map→VO + 角色守卫规范化）— 修改接口 — 管理后台

> 变更类型：⚠️ 部分行为收紧（错误码规范化 + 响应结构稳定化），无破坏性字段删除
> 端类型：管理后台（用户/系统管理）
> 日期：2026-06-17
> 服务：hl-user-service
> PR：https://git.1814.love:8443/wx/HL/pulls/3924

---

## ⚠️ 关键说明

用接口契约语义审计工作流全量扫描用户服务（hl-user-service）全部 Controller，逐端点比对「Swagger `@ApiOperation` 声明的契约 ⨯ 实际实现 ⨯ 业务规则」，对抗复核后修复一批「接口能跑但返回值/错误码/落库逻辑与契约不符」。已合并 dev-v3、部署测试服、网关 9443 + 真 admin token 实测（`/admin/role`、`/admin/menu/tree` 返回 VO 结构、双实例 totalCodes=282 健康）、本地全量 2793 单测零新增回归。

下面只列**与前端对接相关**的变更。最影响前端的是第 1 节（部分管理端接口的鉴权失败由裸 403/字符串改为业务错误码）。

---

## 1. 角色守卫规范化：非超管/非管理员失败改为业务错误码（前端按 Result.code 处理）

平台 HTTP 始终 200，业务码在 `Result.code`。系统管理类接口此前部分用裸 403 / 字符串提示拦截越权，本次统一下移 Service 层并改为业务错误码，行为与 notes 文档对齐。

| 接口 | 方法 | 变更错误码 | 触发场景 |
|---|---|---|---|
| 完整菜单树 | GET `/admin/menu/tree` | **200307** | 非 SUPER_ADMIN 调用（原行为允许 ADMIN，现严格仅 SUPER_ADMIN，与 notes「仅 SUPER_ADMIN」一致） |
| 角色列表 | GET `/admin/role` | **200313** | 非 SUPER_ADMIN/非 ADMIN 调用（原裸 403，现业务码「仅管理员或超级管理员可执行」） |
| 创建/编辑/删除角色、分配菜单 | POST/PUT/DELETE `/admin/role/**` | **200307** | 非 SUPER_ADMIN（原裸 403，现业务码） |
| 删除内置角色 | DELETE `/admin/role/{roleId}` | **210104** | 删除 SUPER_ADMIN 等系统预置角色（兑现「内置角色不可删除」契约） |

> 前端处理：以上接口鉴权/业务失败请按 `Result.code` 判断（200307=仅超管、200313=仅管理员或超管、210104=内置角色不可删除），不要再依赖 HTTP 403 或固定文案。

---

## 2. 系统字典/菜单：新增业务错误码（原 404/400 → 业务码）

| 接口 | 方法 | 变更错误码 | 触发场景 |
|---|---|---|---|
| 字典数据编辑/删除/查询 | `/admin/dict/data/**` | **210404** | 字典数据项不存在（原 404，现业务码「字典数据不存在」） |
| 菜单创建/编辑（类型校验） | POST/PUT `/admin/menu/**` | **210204** | menuType 不在白名单（D/M/B），原通用错误，现稳定业务码 |
| 菜单创建/编辑（状态校验） | POST/PUT `/admin/menu/**` | **210205** | status 不属于 common_status 字典（ACTIVE/INACTIVE） |

---

## 3. 响应结构稳定化：Map → 强类型 VO（字段名不变，类型更稳定）

以下接口此前返回 `Map<String,Object>`，本次改为强类型 VO，**字段名与层级不变**，前端无需改动，仅类型更稳定可预期：

| 接口 | 方法 | 响应类型 |
|---|---|---|
| 角色详情 | GET `/admin/role/{roleId}` | `Map` → `SysRoleDetailRespVO`（roleId/roleName/roleKey/sortOrder/status/menuIds 等） |
| 完整菜单树 / 角色菜单树 / 我的菜单 | GET `/admin/menu/tree`、`/tree/role/{id}`、`/my` | `List<SysMenu>` → `List<SysMenuRespVO>`（递归 children，含 menuType/path/component/icon/visible/isCache/status） |
| 角色列表 | GET `/admin/role` | 列表项统一为 `SysRoleRespVO` |

> 大雪花 ID（roleId/menuId 等超 JS 安全范围的 Long）按平台口径以**字符串**返回（如 `"2049331915839700993"`），小 ID 仍为数字；前端按字符串/数字皆可解析处理。

---

## 4. 其它对齐（前端基本无感）

- 部分响应 VO 字段名/null 语义/缺字段与 Swagger 契约对齐；金额类字段补 `@JsonSerialize(ToStringSerializer)` 输出字符串。
- 安全：创建管理员/重置密码/登录接口的 Swagger notes 不再明文写出默认密码（仅文档措辞，接口行为不变）。

---

## 暂缓项（本次未改，留作后续）

- 内部接口 `/internal/user/admin/info/{adminId}` 的错误码微调（404→业务码）暂缓，本期回退保持原行为。
- 前端配置 `SECRET` 类型脱敏策略待产品确认，本期保持原行为（管理端详情/列表仍返真值供编辑）。
