This commit is contained in:
ChuXun
2025-10-19 20:31:01 +08:00
parent cfd054f0d9
commit 4ce487588a
287 changed files with 59148 additions and 0 deletions

View File

@@ -0,0 +1,296 @@
# 人员管理页面设计文档
## 1. 页面概述
人员管理页面是提供给系统管理员ADMIN用于管理所有用户账户的界面。其核心功能包括展示用户列表、添加新用户、编辑现有用户信息、更改用户角色与状态以及搜索和筛选用户。
## 2. 页面布局
![人员管理页面布局示意图](https://placeholder-for-personnel-page-mockup.png)
### 2.1 布局结构
页面采用经典的后台管理布局,与任务管理、反馈管理页面保持一致:
- **顶部**: 操作区域,包含"添加用户"按钮。
- **中部**: 筛选和搜索区域,支持按用户名、角色或状态进行搜索。
- **下部**: 用户数据表格,展示所有用户及其关键信息,并提供行内操作。
- **底部**: 分页组件。
## 3. 组件结构
```vue
<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. 数据结构
```typescript
// 用户筛选条件
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. 状态管理
```typescript
// 组件内状态
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 操作
```typescript
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 辅助函数
```typescript
const formatRole = (role: string) => {
const roleMap = {
ADMIN: '管理员',
SUPERVISOR: '主管',
GRID_WORKER: '网格员',
DECISION_MAKER: '决策者'
};
return roleMap[role] || '未知角色';
};
```
## 7. API 调用
```typescript
// 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. 样式设计
```scss
.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 中对应的 `createUser``updateUser` action。
- 操作成功后,发出 `success` 事件。
## 10. 测试用例
- **集成测试**:
- 测试能否成功添加一个新用户。
- 测试能否成功编辑一个现有用户的信息(包括修改密码和不修改密码两种情况)。
- 测试能否成功删除一个用户。
- 测试启用/禁用开关是否能正确更新用户状态。
- 测试搜索和筛选功能是否能正确过滤用户列表。