# 用户管理接口适配设计规范
**工单**: #2 - 用户管理接口变更通知
**日期**: 2026-06-07
**方案**: 方案 B(完整适配)
---
## 1. 背景
后端已完成用户管理模块接口重构(提交 `dbd04d8`),支持部门、角色联表查询和聚合信息返回。前端需要适配以:
- 减少请求次数(从 3 个请求合并为 1 个)
- 支持部门/角色筛选
- 在列表和详情中展示部门、角色信息
## 2. 后端变更摘要
### 2.1 用户实体扩展字段
```json
{
"id": 1,
"username": "admin",
"phone": "13800138000",
"depts": [
{
"deptId": 1,
"deptCode": "TECH",
"deptName": "技术部",
"main": true
}
],
"roles": [
{
"roleId": 1,
"roleCode": "admin",
"roleName": "管理员",
"dataScope": 1
}
]
}
```
### 2.2 新增接口
- `GET /user/admin/user/{id}/aggregate` - 聚合查询(基础信息 + 部门列表 + 角色列表)
### 2.3 增强接口
- `GET /user/admin/user/page` - 自动返回 `depts` 和 `roles`
- `GET /user/admin/user/list` - 自动返回 `depts` 和 `roles`
- 支持筛选参数:`deptId`、`roleId`
## 3. 前端适配范围
### 3.1 用户列表页 (`views/user/info/Index.vue`)
**新增列:**
- 部门列:显示用户所属部门名称(多个部门用逗号分隔,主部门加粗)
- 角色列:显示用户角色名称(多个角色用标签展示)
**新增筛选条件:**
- 部门筛选:树形选择器(`el-tree-select`),支持多选
- 角色筛选:树形选择器(`el-tree-select`),支持多选
**数据流:**
- 列表接口自动返回 `depts` 和 `roles`,无需额外请求
- 筛选参数通过 `queryParams` 传递给 `userService.page()`
### 3.2 用户详情弹窗 (`views/user/info/UserDetailDialog.vue`)
**改造:**
- 使用新的聚合接口 `GET /user/admin/user/{id}/aggregate`
- 展示部门列表(部门名称 + 是否主部门标记)
- 展示角色列表(角色名称 + 数据范围)
**数据流:**
```
打开弹窗 → 调用 aggregate 接口 → 展示完整信息
```
### 3.3 用户表单 (`views/user/info/UserFormDialog.vue`)
**优化:**
- 编辑时从 `row.depts` 解析 `deptIds`(替代调用 `userDeptService.listDeptIdsByUserId`)
- 编辑时从 `row.roles` 解析 `roleIds`(替代调用 `userService.getRoles`)
- 保留 `userDeptService.assignDepts` 和 `userPostService.assignPosts` 用于保存
### 3.4 Service 层扩展 (`service/user/userService.ts`)
**新增方法:**
- `aggregate(userId)` - 调用聚合查询接口
## 4. 组件设计
### 4.1 部门/角色展示组件
无需新增组件,直接在表格列中使用 `slot` 渲染:
```vue
{{ dept.deptName }}
{{ role.roleName }}
```
### 4.2 筛选区域
```vue
```
## 5. 数据类型定义
```typescript
// 部门信息(嵌套在用户中)
interface UserDept {
deptId: number
deptCode: string
deptName: string
main: boolean
}
// 角色信息(嵌套在用户中)
interface UserRole {
roleId: number
roleCode: string
roleName: string
dataScope: number
}
// 扩展用户类型
interface User {
id: number
username: string
// ... 其他字段
depts?: UserDept[]
roles?: UserRole[]
}
```
## 6. 接口调用变更
### 6.1 列表页
**变更前:**
- 调用 `userService.page(params)` - 仅返回基础信息
**变更后:**
- 调用 `userService.page(params)` - 自动包含 `depts` 和 `roles`
- 支持 `deptId` 和 `roleId` 筛选参数
### 6.2 详情弹窗
**变更前:**
- 直接使用 `props.row` 数据
**变更后:**
- 打开时调用 `userService.aggregate(props.row.id)`
- 使用返回的完整数据渲染
### 6.3 编辑表单
**变更前:**
```typescript
// 需要额外请求获取部门和角色
const deptIds = await userDeptService.listDeptIdsByUserId(userId)
const roleIds = await userService.getRoles(userId)
```
**变更后:**
```typescript
// 直接从 row 中解析
const deptIds = props.row.depts?.map((d: any) => d.deptId) || []
const roleIds = props.row.roles?.map((r: any) => r.roleId) || []
```
## 7. 错误处理
- 聚合接口失败时,回退到使用 `props.row` 基础信息
- 部门/角色数据缺失时,显示 "-" 或空标签
- 筛选条件不影响现有查询逻辑
## 8. 兼容性
- 原有接口保持不变
- 新增字段通过 `@TableField(exist = false)` 添加,不影响旧逻辑
- 保留 `userDeptService` 和 `userPostService` 用于分配功能
## 9. 测试要点
1. 列表页是否正确显示部门和角色信息
2. 部门/角色筛选是否生效
3. 详情弹窗是否正确展示聚合数据
4. 编辑表单是否正确解析已选部门/角色
5. 保存后数据是否正确刷新
## 10. 文件变更清单
| 文件 | 变更类型 | 说明 |
|------|---------|------|
| `views/user/info/Index.vue` | 修改 | 添加部门/角色列和筛选条件 |
| `views/user/info/UserDetailDialog.vue` | 修改 | 使用聚合接口,展示部门/角色详情 |
| `views/user/info/UserFormDialog.vue` | 修改 | 从 row 解析 deptIds/roleIds |
| `service/user/userService.ts` | 修改 | 添加 aggregate 方法 |
---
**设计评审状态**: 待评审
**下一步**: 用户评审通过后,编写实施计划