Files
rui-docs/superpowers/specs/2026-06-07-user-management-api-adaptation-design.md
T

6.3 KiB
Raw Blame History

用户管理接口适配设计规范

工单: #2 - 用户管理接口变更通知
日期: 2026-06-07
方案: 方案 B(完整适配)


1. 背景

后端已完成用户管理模块接口重构(提交 dbd04d8),支持部门、角色联表查询和聚合信息返回。前端需要适配以:

  • 减少请求次数(从 3 个请求合并为 1 个)
  • 支持部门/角色筛选
  • 在列表和详情中展示部门、角色信息

2. 后端变更摘要

2.1 用户实体扩展字段

{
  "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 - 自动返回 deptsroles
  • GET /user/admin/user/list - 自动返回 deptsroles
  • 支持筛选参数:deptIdroleId

3. 前端适配范围

3.1 用户列表页 (views/user/info/Index.vue)

新增列:

  • 部门列:显示用户所属部门名称(多个部门用逗号分隔,主部门加粗)
  • 角色列:显示用户角色名称(多个角色用标签展示)

新增筛选条件:

  • 部门筛选:树形选择器(el-tree-select),支持多选
  • 角色筛选:树形选择器(el-tree-select),支持多选

数据流:

  • 列表接口自动返回 deptsroles,无需额外请求
  • 筛选参数通过 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.assignDeptsuserPostService.assignPosts 用于保存

3.4 Service 层扩展 (service/user/userService.ts)

新增方法:

  • aggregate(userId) - 调用聚合查询接口

4. 组件设计

4.1 部门/角色展示组件

无需新增组件,直接在表格列中使用 slot 渲染:

<!-- 部门列 -->
<template #column-depts="{ row }">
  <el-tag 
    v-for="dept in row.depts" 
    :key="dept.deptId"
    :type="dept.main ? 'primary' : 'info'"
    size="small"
    class="mr-1"
  >
    {{ dept.deptName }}
  </el-tag>
</template>

<!-- 角色列 -->
<template #column-roles="{ row }">
  <el-tag 
    v-for="role in row.roles" 
    :key="role.roleId"
    type="success"
    size="small"
    class="mr-1"
  >
    {{ role.roleName }}
  </el-tag>
</template>

4.2 筛选区域

<template #search="{ query: q, search, reset }">
  <!-- 现有筛选条件... -->
  
  <!-- 新增部门筛选 -->
  <el-form-item label="所属部门">
    <el-tree-select
      v-model="q.deptId"
      :data="deptTree"
      check-strictly
      node-key="id"
      :props="{ label: 'deptName', children: 'children' }"
      placeholder="请选择部门"
      clearable
      style="width: 200px"
    />
  </el-form-item>
  
  <!-- 新增角色筛选 -->
  <el-form-item label="角色">
    <el-tree-select
      v-model="q.roleId"
      :data="roleTree"
      check-strictly
      node-key="id"
      :props="{ label: 'roleName', children: 'children' }"
      placeholder="请选择角色"
      clearable
      style="width: 200px"
    />
  </el-form-item>
</template>

5. 数据类型定义

// 部门信息(嵌套在用户中)
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) - 自动包含 deptsroles
  • 支持 deptIdroleId 筛选参数

6.2 详情弹窗

变更前:

  • 直接使用 props.row 数据

变更后:

  • 打开时调用 userService.aggregate(props.row.id)
  • 使用返回的完整数据渲染

6.3 编辑表单

变更前:

// 需要额外请求获取部门和角色
const deptIds = await userDeptService.listDeptIdsByUserId(userId)
const roleIds = await userService.getRoles(userId)

变更后:

// 直接从 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) 添加,不影响旧逻辑
  • 保留 userDeptServiceuserPostService 用于分配功能

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 方法

设计评审状态: 待评审
下一步: 用户评审通过后,编写实施计划