Files
Environment-Monitoring-System/Design/frontend_Design/PersonnelManagementPage_Design.md
ChuXun 4ce487588a 1
2025-10-19 20:31:01 +08:00

8.4 KiB
Raw Blame History

人员管理页面设计文档

1. 页面概述

人员管理页面是提供给系统管理员ADMIN用于管理所有用户账户的界面。其核心功能包括展示用户列表、添加新用户、编辑现有用户信息、更改用户角色与状态以及搜索和筛选用户。

2. 页面布局

人员管理页面布局示意图

2.1 布局结构

页面采用经典的后台管理布局,与任务管理、反馈管理页面保持一致:

  • 顶部: 操作区域,包含"添加用户"按钮。
  • 中部: 筛选和搜索区域,支持按用户名、角色或状态进行搜索。
  • 下部: 用户数据表格,展示所有用户及其关键信息,并提供行内操作。
  • 底部: 分页组件。

3. 组件结构

<template>
  <div class="personnel-management-page">
    <el-page-header title="人员管理" content="系统用户列表" />

    <el-card class="page-container">
      <!-- 搜索与操作区域 -->
      <div class="table-toolbar">
        <el-form :model="filters" inline class="filter-form">
          <el-form-item>
            <el-input v-model="filters.name" placeholder="按姓名或用户名搜索" clearable />
          </el-form-item>
          <el-form-item>
            <el-select v-model="filters.role" placeholder="按角色筛选" clearable>
              <el-option label="管理员" value="ADMIN" />
              <el-option label="主管" value="SUPERVISOR" />
              <el-option label="网格员" value="GRID_WORKER" />
              <el-option label="决策者" value="DECISION_MAKER" />
            </el-select>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" icon="Search" @click="handleSearch">搜索</el-button>
          </el-form-item>
        </el-form>
        <div class="action-buttons">
          <el-button type="primary" icon="Plus" @click="handleCreateUser">添加用户</el-button>
        </div>
      </div>

      <!-- 用户表格 -->
      <el-table :data="users" v-loading="loading" stripe>
        <el-table-column prop="username" label="用户名" />
        <el-table-column prop="name" label="姓名" />
        <el-table-column prop="role" label="角色">
           <template #default="{ row }">
            <span>{{ formatRole(row.role) }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="email" label="邮箱" />
        <el-table-column prop="status" label="状态">
          <template #default="{ row }">
            <el-switch
              v-model="row.isActive"
              @change="handleStatusChange(row)"
              :loading="row.statusChanging"
              active-text="启用"
              inactive-text="禁用"
            />
          </template>
        </el-table-column>
        <el-table-column label="操作" width="200" fixed="right">
          <template #default="{ row }">
            <el-button link type="primary" @click="handleEdit(row)">编辑</el-button>
            <el-popconfirm title="确定要删除该用户吗?" @confirm="handleDelete(row)">
              <template #reference>
                <el-button link type="danger">删除</el-button>
              </template>
            </el-popconfirm>
          </template>
        </el-table-column>
      </el-table>

      <!-- 分页 -->
      <el-pagination
        v-if="total > 0"
        class="pagination-container"
        :current-page="pagination.page"
        :page-size="pagination.pageSize"
        :total="total"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      />
    </el-card>

    <!-- 用户表单对话框 -->
    <UserFormDialog 
      v-model="dialogVisible" 
      :user-id="selectedUserId"
      @success="onFormSuccess" 
    />
  </div>
</template>

4. 数据结构

// 用户筛选条件
interface UserFilters {
  name?: string;
  role?: 'ADMIN' | 'SUPERVISOR' | 'GRID_WORKER' | 'DECISION_MAKER';
}

// 用户列表项
interface UserListItem {
  id: number;
  username: string;
  name: string;
  email: string;
  role: string;
  isActive: boolean;
  statusChanging?: boolean; // 用于控制 Switch 的 loading 状态
}

// 用户表单数据 (用于对话框)
interface UserFormData {
  id?: number;
  username: string;
  name: string;
  email: string;
  role: string;
  password?: string; // 创建时需要,编辑时可选
}

5. 状态管理

// 组件内状态
const filters = ref<UserFilters>({});
const pagination = ref({ page: 1, pageSize: 10 });
const dialogVisible = ref(false);
const selectedUserId = ref<number | null>(null);

// 全局状态 (Pinia Store)
const personnelStore = usePersonnelStore();
const { users, total, loading } = storeToRefs(personnelStore);

6. 交互逻辑

6.1 CRUD 操作

const fetchUsers = () => {
  personnelStore.fetchUsers({ ...filters.value, ...pagination.value });
};

onMounted(fetchUsers);

const handleSearch = () => {
  pagination.value.page = 1;
  fetchUsers();
};

const handleCreateUser = () => {
  selectedUserId.value = null;
  dialogVisible.value = true;
};

const handleEdit = (user: UserListItem) => {
  selectedUserId.value = user.id;
  dialogVisible.value = true;
};

const handleDelete = async (user: UserListItem) => {
  await personnelStore.deleteUser(user.id);
  ElMessage.success('用户删除成功');
  fetchUsers(); // 刷新列表
};

const handleStatusChange = async (user: UserListItem) => {
  user.statusChanging = true;
  try {
    await personnelStore.updateUserStatus(user.id, user.isActive);
    ElMessage.success('状态更新成功');
  } catch {
    // 失败时将开关拨回原位
    user.isActive = !user.isActive;
  } finally {
    user.statusChanging = false;
  }
};

const onFormSuccess = () => {
  dialogVisible.value = false;
  fetchUsers();
};

6.2 辅助函数

const formatRole = (role: string) => {
  const roleMap = {
    ADMIN: '管理员',
    SUPERVISOR: '主管',
    GRID_WORKER: '网格员',
    DECISION_MAKER: '决策者'
  };
  return roleMap[role] || '未知角色';
};

7. API 调用

// api/personnel.ts
export const personnelApi = {
  getUsers: (params) => apiClient.get('/personnel', { params }),
  getUserById: (id: number) => apiClient.get(`/personnel/${id}`),
  createUser: (data: UserFormData) => apiClient.post('/personnel', data),
  updateUser: (id: number, data: UserFormData) => apiClient.put(`/personnel/${id}`, data),
  deleteUser: (id: number) => apiClient.delete(`/personnel/${id}`),
};

// stores/personnel.ts
export const usePersonnelStore = defineStore('personnel', {
  state: () => ({
    users: [] as UserListItem[],
    total: 0,
    loading: false,
  }),
  actions: {
    async fetchUsers(params) {
      this.loading = true;
      try {
        const { data } = await personnelApi.getUsers(params);
        this.users = data.items.map(u => ({ ...u, statusChanging: false }));
        this.total = data.total;
      } finally {
        this.loading = false;
      }
    },
    // ...其他 createUser, updateUser, deleteUser 等 actions
  }
});

8. 样式设计

.personnel-management-page {
  padding: 24px;

  .page-container {
    margin-top: 24px;
  }
  
  .table-toolbar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 20px;
  }

  .pagination-container {
    margin-top: 24px;
    display: flex;
    justify-content: flex-end;
  }
}

9. 关联组件

UserFormDialog.vue

用于创建和编辑用户的对话框组件。

  • Props: modelValue, userId
  • 功能:
    • 如果 userId 存在,则为编辑模式,对话框打开时会根据 ID 加载用户信息。
    • 如果 userId 为空,则为创建模式。
    • 包含用户名、姓名、邮箱、角色和密码的表单字段。
    • 密码字段在编辑模式下为可选,并提示"留空则不修改密码"。
    • 表单提交时进行验证,并调用 store 中对应的 createUserupdateUser action。
    • 操作成功后,发出 success 事件。

10. 测试用例

  • 集成测试:
    • 测试能否成功添加一个新用户。
    • 测试能否成功编辑一个现有用户的信息(包括修改密码和不修改密码两种情况)。
    • 测试能否成功删除一个用户。
    • 测试启用/禁用开关是否能正确更新用户状态。
    • 测试搜索和筛选功能是否能正确过滤用户列表。