# 2026-07-21

## VIP 角色绑定改为动态查询（去硬编码）
- 问题：`src/pages/user/vip-review/index.tsx` 中 `VIP_ROLE_ID = 2032` 写死，跨租户不适用。
- 改动：
  - `src/api/system/role/model/index.ts`：给 `RoleParam` 增加 `tenantId?: number | string` 字段，支持按租户过滤角色。
  - `vip-review/index.tsx`：新增 `getCurrentTenantId()`（取自 `Taro.getStorageSync('TenantId') || TenantId`）与 `getVipRoleId()`（调用 `listRoles({ roleCode:'vip', tenantId })` 动态获取 roleId）；`assignVipRole` 改用动态 roleId，并在 `addUserRole` 时带上 `tenantId`。
  - 导入补充：`listRoles` (from `@/api/system/role`)、`TenantId` (from `@/config/app`)。
- 约定：VIP 角色以 `roleCode='vip'` 标识，不再依赖固定 roleId。

## 后端确认（com.gxwebsoft.core）
- `GET /api/system/role`：支持 `roleCode` 过滤（`RoleParam.roleCode` 带 `@QueryField(EQ)`）。✅
- 租户隔离由 MyBatis-Plus `TenantLineInnerInterceptor` 自动完成（`sys_role` 不在忽略表清单），租户取自请求头 `tenantId`。`PageParam.buildWrapper` 还会**显式跳过** `tenantId` 字段不拼 WHERE，所以前端的 `tenantId` 查询参数不参与过滤——真正隔离靠请求头。`RoleParam.tenantId` 无 `@QueryField`，传了也被忽略，但功能正确（按当前租户返回 VIP 角色）。
- ⚠️ 关键 bug：`POST /api/system/user-role`(save) 用 `getLoginUser().getUserId()` **无条件覆盖**请求体里的 `userId`。VIP 审核通过时，角色会被绑到当前登录的店员，而非申请人 `item.userId`。原硬编码版本也存在此问题。需与用户确认是否修复（建议：仅当请求体 userId 为空时才回退到登录用户）。
- 路径核对：前端 `SERVER_API_URL='.../api'`，`addUserRole` 命中 `/api/system/user-role`，一致。
