用户列表-布局与组件结构描述.md 20 KB

用户列表 - 布局与组件结构描述

1️⃣ 页面概述

用户列表页面用于管理系统用户账号,包括本地用户和域用户的查看、创建、编辑、删除等操作。支持用户状态管理(启用/禁用)、密码重置等功能。

2️⃣ 布局结构(使用约定术语)

Page Layout

  • Layout Type: Vertical Stack Layout(垂直堆叠布局)
  • Direction: Vertical(垂直方向)
  • Spacing: 无间距(紧密堆叠)
  • Padding: 0(全屏布局)

Component Hierarchy(层级结构)

Page (页面)
└── Main Container (主容器)
    ├── Header Region (头部区域)
    │   └── Tabs Component (选项卡组件)
    │       ├── Tab Item: 用户列表
    │       ├── Tab Item: 角色列表
    │       ├── Tab Item: 域用户组
    │       └── Tab Item: LDAP
    │
    ├── Content Region (内容区域)
    │   └── Table Section (表格分区)
    │       ├── Table Component (表格组件)
    │       │   ├── Column: 用户名称
    │       │   ├── Column: 角色
    │       │   ├── Column: 用户类型
    │       │   ├── Column: 账号状态 (Switch)
    │       │   └── Column: 锁定状态
    │       │
    │       └── Pagination Component (分页组件)
    │           ├── Total Count Display
    │           ├── Page Size Selector
    │           ├── Page Navigation
    │           └── Page Jump Input
    │
    └── Footer Region (底部区域)
        └── Action Toolbar (操作工具栏)
            ├── Button: 重置密码
            ├── Button: 刷新
            ├── Button: 删除
            ├── Button: 编辑
            └── Button: 新建 (Primary)

Layout Properties(布局属性)

Main Container

  • Type: Flexbox Layout
  • Direction: Column
  • Height: 100vh
  • Overflow: Hidden
  • Background: Token.colorBgContainer

Header Region (Tabs)

  • Height: 48px
  • Background: Token.colorBgContainer
  • Border-bottom: 1px solid Token.colorBorderSecondary
  • Padding: 0 24px

Content Region

  • Type: Flex Layout
  • Flex: 1 (占据剩余空间)
  • Overflow: Auto
  • Padding: 24px 24px 0 24px

Table Section

  • Type: Flexbox Layout
  • Direction: Column
  • Gap: 16px
  • Height: 100%

Footer Region

  • Height: 72px
  • Background: Token.colorBgContainer
  • Border-top: 1px solid Token.colorBorderSecondary
  • Padding: 16px 24px
  • Alignment: Center
  • Justify: Center

Action Toolbar

  • Type: Horizontal Flex Layout
  • Gap: 12px
  • Justify: Center

3️⃣ Ant Design 组件选择

使用的组件及理由

组件 用途 选择理由
Tabs 顶部导航选项卡 - 提供标准的选项卡导航
- 自动处理选中状态
- 支持路由集成
- 清晰的视觉分隔
- 适合管理多个相关页面
Table 用户数据展示 - 强大的数据表格组件
- 内置排序、筛选功能
- 支持行选择
- 自动处理分页数据
- 列宽自适应
- 固定列支持
Switch 账号状态开关 - 直观的开关交互
- 即时生效反馈
- 支持加载状态
- 适合布尔值切换
- 占用空间小
Pagination 分页控制 - 完整的分页功能
- 支持页码跳转
- 每页条数选择
- 总数显示
- 国际化支持
Button 操作按钮 - 提供多种按钮样式
- 支持加载状态
- 图标支持
- 自动防重复点击
- 主题一致性
Space 按钮组间距 - 统一管理按钮间距
- 响应式布局
- 自动对齐
Modal 弹窗对话框 - 用于编辑/新建用户
- 模态交互
- 表单提交
- 确认删除操作
Popconfirm 操作确认 - 删除确认提示
- 轻量级确认
- 避免误操作

Tabs 组件选择理由

选择 Tabs 作为顶部导航的原因:

  • ✅ 将相关的用户管理功能组织在一起(用户列表、角色列表、域用户组、LDAP)
  • ✅ 清晰的视觉层级,用户可以快速切换不同的管理视图
  • ✅ 节省页面空间,避免多个独立页面
  • ✅ 符合用户管理系统的常见设计模式
  • ✅ 支持路由集成,可以通过 URL 直接访问特定标签页

Table 组件选择理由

选择 Ant Design Table 的原因:

  • ✅ 企业级表格组件,功能强大且稳定
  • ✅ 内置虚拟滚动,支持大数据量
  • ✅ 列配置灵活,支持自定义渲染
  • ✅ 内置排序、筛选、分页等功能
  • ✅ 支持行选择,便于批量操作
  • ✅ 响应式设计,适配不同屏幕

Switch 组件选择理由

使用 Switch 而不是按钮来控制账号状态的原因:

  • ✅ 直观展示当前状态(开/关)
  • ✅ 单击即可切换,操作效率高
  • ✅ 占用空间小,适合表格列
  • ✅ 即时反馈,用户体验好
  • ✅ 符合开关控制的通用设计模式

4️⃣ 功能清单

数据展示功能

  • [x] 用户列表展示

    • 显示用户名称
    • 显示用户角色
    • 显示用户类型(本地用户/域用户)
    • 显示账号状态(启用/禁用)
    • 显示锁定状态
    • 支持列排序
    • 支持列筛选
  • [x] 分页功能

    • 显示总条数
    • 每页条数选择(10/20/50/100)
    • 页码导航
    • 快速跳转到指定页
  • [x] 数据加载

    • 初始加载用户列表
    • 加载状态指示
    • 加载失败处理
    • 自动刷新(可选)

用户操作功能

  • [x] 新建用户

    • 打开新建用户表单
    • 输入用户基本信息
    • 选择用户角色
    • 设置初始密码
    • 表单验证
    • 提交创建请求
  • [x] 编辑用户

    • 选中用户
    • 打开编辑表单
    • 修改用户信息
    • 保存修改
  • [x] 删除用户

    • 单选删除
    • 批量删除(可选)
    • 删除确认提示
    • 删除操作
    • 删除结果反馈
  • [x] 重置密码

    • 选中用户
    • 打开重置密码对话框
    • 生成新密码或手动输入
    • 密码强度验证
    • 提交重置请求
    • 显示新密码(一次性)
  • [x] 账号状态管理

    • 启用账号
    • 禁用账号
    • 状态切换确认
    • 即时生效反馈
  • [x] 刷新列表

    • 重新加载用户列表
    • 保持当前页码和筛选条件
    • 刷新状态提示

选择与批量操作

  • [x] 行选择

    • 单选用户
    • 多选用户(复选框)
    • 全选/取消全选
    • 显示已选数量
  • [x] 批量操作

    • 批量删除
    • 批量启用/禁用(可选)
    • 批量导出(可选)

搜索与筛选

  • 搜索功能
    • 按用户名搜索
    • 按角色筛选
    • 按用户类型筛选
    • 按账号状态筛选
    • 实时搜索/延迟搜索

标签页切换

  • Tab 导航
    • 切换到角色列表
    • 切换到域用户组
    • 切换到 LDAP 配置
    • 保持当前页面状态

5️⃣ 功能需求与思考

功能1:用户列表展示与加载

需求描述

  • 页面加载时自动获取用户列表数据
  • 支持分页加载,每页显示 20 条(可配置)
  • 显示用户的关键信息:用户名、角色、类型、状态

交互流程

  1. 页面挂载时触发数据加载
  2. 显示 Table 加载状态(Skeleton 或 Spin)
  3. 数据加载成功后渲染表格
  4. 加载失败显示错误提示,提供重试按钮

数据结构

interface User {
  id: string;
  username: string;          // 用户名称
  role: string;              // 角色
  userType: 'local' | 'domain'; // 用户类型
  isEnabled: boolean;        // 账号状态
  isLocked: boolean;         // 锁定状态
  lastLoginTime?: string;    // 最后登录时间
  createdAt: string;         // 创建时间
  updatedAt: string;         // 更新时间
}

interface UserListResponse {
  data: User[];
  total: number;
  page: number;
  pageSize: number;
}

边界情况

  • 无数据(空状态展示)
  • 数据量大(虚拟滚动)
  • 网络慢(加载超时处理)
  • 并发请求(取消过期请求)

功能2:账号状态切换

需求描述

  • 通过 Switch 组件即时切换用户账号的启用/禁用状态
  • 提供即时反馈,显示操作结果

交互流程

  1. 用户点击 Switch 开关
  2. Switch 进入 loading 状态
  3. 发送状态更新请求到后端
  4. 请求成功:Switch 切换状态,显示成功提示
  5. 请求失败:Switch 恢复原状态,显示错误提示

验证规则

  • 不能禁用当前登录用户自己的账号
  • 不能禁用系统管理员账号(除非有多个管理员)
  • 需要相应权限才能操作

安全考虑

  • 禁用账号时,立即终止该用户的所有会话
  • 记录状态变更操作日志
  • 关键操作需要二次确认

边界情况

  • 网络中断时的状态同步
  • 并发修改冲突
  • 权限不足的提示
  • 当前登录用户的特殊处理

功能3:新建用户

需求描述

  • 通过 Modal 表单创建新用户
  • 输入用户基本信息并设置初始密码

交互流程

  1. 点击"新建"按钮
  2. 打开新建用户 Modal
  3. 填写用户信息表单:
    • 用户名(必填,唯一性校验)
    • 显示名称(可选)
    • 角色选择(必填)
    • 用户类型(本地/域)
    • 初始密码(必填,强度校验)
    • 确认密码(必填,一致性校验)
    • 邮箱(可选,格式校验)
    • 电话(可选)
  4. 点击"确定"提交
  5. 显示创建进度
  6. 成功:关闭 Modal,刷新列表,显示成功消息
  7. 失败:显示错误信息,保持 Modal 打开

表单字段

interface CreateUserForm {
  username: string;          // 3-20字符,字母数字下划线
  displayName?: string;      // 显示名称
  role: string;              // 角色ID
  userType: 'local' | 'domain';
  password: string;          // 8-20字符,包含大小写+数字
  confirmPassword: string;   // 与password一致
  email?: string;            // 邮箱格式
  phone?: string;            // 电话格式
}

验证规则

  • 用户名:3-20字符,只能包含字母、数字、下划线,不能以数字开头
  • 密码:8-20字符,必须包含大写字母、小写字母、数字
  • 邮箱:标准邮箱格式
  • 电话:11位手机号或固定电话格式

边界情况

  • 用户名已存在
  • 表单验证失败
  • 网络超时
  • 服务器错误

功能4:编辑用户

需求描述

  • 修改现有用户的信息(除用户名外)
  • 可以修改角色、显示名称、联系方式等

交互流程

  1. 选中用户(单选)
  2. 点击"编辑"按钮
  3. 打开编辑用户 Modal
  4. 表单预填充当前用户信息
  5. 修改可编辑字段
  6. 提交修改
  7. 成功:关闭 Modal,刷新列表
  8. 失败:显示错误信息

可编辑字段

  • 显示名称
  • 角色
  • 邮箱
  • 电话
  • 备注

不可编辑字段

  • 用户名(主键,不可修改)
  • 用户类型(创建后不可修改)
  • 创建时间

权限限制

  • 普通用户只能编辑自己的部分信息
  • 管理员可以编辑所有用户
  • 不能修改超级管理员的角色

边界情况

  • 未选中用户点击编辑
  • 选中多个用户(禁用编辑按钮)
  • 编辑过程中用户被删除
  • 并发编辑冲突

功能5:删除用户

需求描述

  • 删除选中的用户账号
  • 提供删除确认,防止误操作

交互流程

  1. 选中要删除的用户(单选或多选)
  2. 点击"删除"按钮
  3. 弹出 Popconfirm 确认对话框
  4. 用户确认删除
  5. 发送删除请求
  6. 成功:从列表移除,显示成功消息
  7. 失败:显示错误信息

确认对话框内容

  • 单个删除:确定要删除用户 "${username}" 吗?
  • 批量删除:确定要删除选中的 ${count} 个用户吗?
  • 警告提示:删除后将无法恢复,且该用户的所有会话将被终止。

删除限制

  • 不能删除当前登录用户
  • 不能删除系统内置用户(如 Administrator)
  • 需要相应权限
  • 用户有关联数据时需要特殊处理(如操作日志)

安全措施

  • 二次确认
  • 软删除(标记为已删除,保留数据)或硬删除
  • 记录删除操作日志
  • 立即终止被删除用户的所有会话

边界情况

  • 未选中用户点击删除(禁用按钮)
  • 删除过程中网络中断
  • 删除后分页处理(如删除最后一页的唯一记录)
  • 批量删除部分成功部分失败

功能6:重置密码

需求描述

  • 管理员为用户重置密码
  • 支持自动生成或手动输入新密码

交互流程

  1. 选中用户
  2. 点击"重置密码"按钮
  3. 打开重置密码 Modal
  4. 选择重置方式:
    • 自动生成随机密码
    • 手动输入新密码
  5. 如手动输入,需验证密码强度和确认密码
  6. 提交重置请求
  7. 成功:显示新密码(一次性),提示用户记录
  8. 失败:显示错误信息

密码生成规则

  • 长度:12-16位
  • 包含:大写字母、小写字母、数字、特殊字符
  • 易读性:避免易混淆字符(如 0/O, 1/l/I)

安全考虑

  • 新密码只显示一次
  • 重置后强制用户首次登录时修改密码
  • 记录密码重置操作日志
  • 立即终止该用户的所有会话

权限要求

  • 只有管理员可以重置他人密码
  • 用户可以自己修改密码(不是重置)

边界情况

  • 未选中用户
  • 选中多个用户(可以批量重置吗?)
  • 生成的密码不符合系统策略
  • 重置当前登录用户的密码

功能7:刷新列表

需求描述

  • 重新加载用户列表数据
  • 保持当前的筛选和分页状态

交互流程

  1. 点击"刷新"按钮
  2. 显示刷新状态(按钮 loading)
  3. 重新请求当前页数据
  4. 更新表格显示
  5. 显示刷新成功提示(可选)

保持状态

  • 当前页码
  • 每页条数
  • 搜索关键词
  • 筛选条件
  • 排序规则

使用场景

  • 怀疑数据有更新时
  • 操作完成后验证结果
  • 网络错误后重试
  • 定时自动刷新(可选)

功能8:行选择与批量操作

需求描述

  • 支持单选和多选用户
  • 根据选中状态启用/禁用操作按钮

交互流程

  1. 点击行首复选框选择用户
  2. 显示已选中数量
  3. 根据选中状态更新按钮可用性:
    • 未选中:禁用"编辑"、"删除"、"重置密码"
    • 选中1个:启用所有操作
    • 选中多个:禁用"编辑",启用"删除"、"重置密码"

选择状态管理

interface SelectionState {
  selectedRowKeys: string[];  // 选中的用户ID数组
  selectedRows: User[];       // 选中的用户对象数组
}

批量操作

  • 批量删除:删除所有选中用户
  • 批量重置密码:为所有选中用户生成新密码
  • 批量导出:导出选中用户信息(可选)

边界情况

  • 切换页面后清空选择
  • 删除选中用户后更新选择状态
  • 全选时排除不可操作的用户

功能9:Tab 切换

需求描述

  • 在用户列表、角色列表、域用户组、LDAP 之间切换
  • 保持各自的状态

交互流程

  1. 点击 Tab 标签
  2. 切换到对应的内容
  3. 加载对应的数据(如未加载)
  4. 保持当前 Tab 的状态

路由集成

  • URL 反映当前 Tab:/system/users?tab=user-list
  • 支持直接通过 URL 访问特定 Tab
  • 浏览器前进/后退支持

状态管理

  • 每个 Tab 独立管理自己的状态
  • 不同 Tab 之间不共享筛选条件
  • Tab 切换时保留未提交的表单数据(可选)

6️⃣ 后续实现建议

状态管理

Redux Slice 设计

// states/userManagementSlice.ts
interface UserManagementState {
  // 用户列表数据
  users: {
    data: User[];
    total: number;
    loading: boolean;
    error: string | null;
  };
  
  // 分页状态
  pagination: {
    current: number;
    pageSize: number;
  };
  
  // 搜索和筛选
  filters: {
    keyword: string;
    role: string | null;
    userType: 'all' | 'local' | 'domain';
    status: 'all' | 'enabled' | 'disabled';
  };
  
  // 排序
  sorter: {
    field: string | null;
    order: 'ascend' | 'descend' | null;
  };
  
  // 选择状态
  selection: {
    selectedRowKeys: string[];
    selectedRows: User[];
  };
  
  // 当前 Tab
  activeTab: 'user-list' | 'role-list' | 'domain-group' | 'ldap';
  
  // 模态框状态
  modals: {
    createUser: boolean;
    editUser: boolean;
    resetPassword: boolean;
  };
  
  // 当前编辑的用户
  currentUser: User | null;
}

// 异步 Thunks
export const fetchUsers = createAsyncThunk(
  'userManagement/fetchUsers',
  async (params: FetchUsersParams) => {
    const response = await getUserList(params);
    return response;
  }
);

export const createUser = createAsyncThunk(
  'userManagement/createUser',
  async (userData: CreateUserForm) => {
    const response = await createUserAPI(userData);
    return response;
  }
);

export const updateUser = createAsyncThunk(
  'userManagement/updateUser',
  async ({ id, data }: { id: string; data: UpdateUserForm }) => {
    const response = await updateUserAPI(id, data);
    return response;
  }
);

export const deleteUsers = createAsyncThunk(
  'userManagement/deleteUsers',
  async (userIds: string[]) => {
    await deleteUsersAPI(userIds);
    return userIds;
  }
);

export const toggleUserStatus = createAsyncThunk(
  'userManagement/toggleUserStatus',
  async ({ id, isEnabled }: { id: string; isEnabled: boolean }) => {
    await updateUserStatusAPI(id, isEnabled);
    return { id, isEnabled };
  }
);

export const resetPassword = createAsyncThunk(
  'userManagement/resetPassword',
  async ({ id, password }: { id: string; password?: string }) => {
    const response = await resetPasswordAPI(id, password);
    return response;
  }
);

API 接口设计

```typescript // API/user.ts

// 获取用户列表 export interface FetchUsersParams { page: number; pageSize: number; keyword?: string; role?: string; userType?: 'local' | 'domain'; status?: 'enabled' | 'disabled'; sortField?: string; sortOrder?: 'asc' | 'desc'; }

export const getUserList = (params: FetchUsersParams): Promise => { return request.get('/api/system/users', { params }); };

// 创建用户 export interface CreateUserForm { username: string; displayName?: string; role: string; userType: 'local' | 'domain'; password: string; email?: string; phone?: string; }

export const createUserAPI = (data: CreateUserForm): Promise => { return request.post('/api/system/users', data); };

// 更新用户 export interface UpdateUserForm { displayName?: string; role?: string; email?: string; phone?: string; remark?: string; }

export const updateUserAPI = (id: string, data: UpdateUserForm): Promise => { return request.put(/api/system/users/${id}, data); };

// 删除用户 export const deleteUsersAPI = (userIds: string[]): Promise => { return request.delete('/api/system/users', { data: { userIds } }); };

// 更新用户状态 export const updateUserStatusAPI = (id: string, isEnabled: boolean): Promise => { return request.patch(/api/system/users/${id}/status, { isEnabled }); };

// 重置密码 export interface ResetPasswordResponse { newPassword: string; // 新密码(仅一次性返回) }

export const resetPasswordAPI = ( id: string, password?: string ): Promise => { return request.post(/api/system/users/${id}/reset-password, { password }); };

// 检查用户名是否存在 export const checkUsernameExists = (username: string): Promise => {