Files
012-kaopeilian/知识库/问题修复/用户管理页面修复说明.md
111 998211c483 feat: 初始化考培练系统项目
- 从服务器拉取完整代码
- 按框架规范整理项目结构
- 配置 Drone CI 测试环境部署
- 包含后端(FastAPI)、前端(Vue3)、管理端

技术栈: Vue3 + TypeScript + FastAPI + MySQL
2026-01-24 19:33:28 +08:00

269 lines
6.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 用户管理页面分页和搜索功能修复
## 问题描述
用户反馈在 https://kpl.ireborn.com.cn/admin/user-management 页面:
1. ❌ 只显示了20个用户总共有117个
2. ❌ 翻页功能无效
3. ❌ 搜索员工名字找不到
## 问题原因
前端代码使用了**客户端过滤和分页**,但应该使用**服务端分页和搜索**。
### 原有逻辑(错误)
1. `loadUserList()` 只加载第1页的20条数据
2. 使用 `filteredUsers` 计算属性在这20条数据中进行客户端过滤
3. 翻页和搜索都只在本地已加载的20条数据中操作
4. 后端有117个用户但前端只能看到和搜索前20个
### 正确逻辑(修复后)
1. 所有筛选和分页都向后端发送请求
2. 每次筛选/翻页/搜索都重新调用 `loadUserList()`
3. 直接显示后端返回的数据,不在前端过滤
## 修复内容
### 文件:`kaopeilian-frontend/src/views/admin/user-management.vue`
#### 1. 移除前端过滤逻辑
**修改前**:
```typescript
const filteredUsers = computed(() => {
return userList.value.filter(user => {
const matchUsername = !filterForm.username ||
user.username.toLowerCase().includes(filterForm.username.toLowerCase()) ||
(user.realName && user.realName.toLowerCase().includes(filterForm.username.toLowerCase()))
const matchStatus = !filterForm.status || user.status === filterForm.status
const matchRole = !filterForm.role || user.role === filterForm.role
const matchPosition = !filterForm.position || user.position === filterForm.position
return matchUsername && matchStatus && matchRole && matchPosition
})
})
```
**修改后**:
```typescript
// 显示的用户数据(直接使用后端返回的数据,不在前端过滤)
const filteredUsers = computed(() => {
return userList.value
})
```
#### 2. 实时搜索触发后端请求
**修改前**:
```typescript
const handleRealTimeSearch = () => {
// 筛选逻辑在计算属性中处理
}
```
**修改后**:
```typescript
const handleRealTimeSearch = () => {
// 重置到第一页并重新加载数据
currentPage.value = 1
loadUserList()
}
```
#### 3. 重置功能触发后端请求
**修改前**:
```typescript
const handleReset = () => {
filterForm.username = ''
filterForm.status = ''
filterForm.role = ''
filterForm.position = ''
ElMessage.success('已重置所有筛选条件')
}
```
**修改后**:
```typescript
const handleReset = () => {
filterForm.username = ''
filterForm.status = ''
filterForm.role = ''
filterForm.position = ''
currentPage.value = 1
loadUserList() // 重新加载数据
ElMessage.success('已重置所有筛选条件')
}
```
#### 4. 清除单个筛选条件时触发后端请求
`clearUsername()`, `clearStatus()`, `clearRole()`, `clearPosition()` 四个函数都添加:
```typescript
currentPage.value = 1
loadUserList()
```
#### 5. 修正API参数格式
**修改前**:
```typescript
const params = {
page: currentPage.value,
pageSize: pageSize.value, // 错误应该是page_size
keyword: filterForm.username,
status: filterForm.status, // 错误后端不支持status参数
role: filterForm.role
}
```
**修改后**:
```typescript
const params: any = {
page: currentPage.value,
page_size: pageSize.value // 正确:使用下划线
}
// 添加关键词搜索(用户名或姓名)
if (filterForm.username && filterForm.username.trim()) {
params.keyword = filterForm.username.trim()
}
// 添加角色筛选
if (filterForm.role) {
params.role = filterForm.role
}
// 添加状态筛选后端使用is_active参数
if (filterForm.status) {
if (filterForm.status === 'active') {
params.is_active = true
} else if (filterForm.status === 'disabled') {
params.is_active = false
}
// pending状态不传is_active参数
}
```
## 修复结果
### ✅ 功能验证
#### 1. 分页功能
- ✅ 可以正常翻页查看所有117个用户
- ✅ 每页显示20条记录
- ✅ 总共6页20+20+20+20+20+17
#### 2. 搜索功能
- ✅ 输入员工姓名可以搜索到对应员工
- ✅ 例如搜索"何平",能找到对应的员工记录
- ✅ 搜索会在所有117个用户中进行不局限于当前页
#### 3. 筛选功能
- ✅ 角色筛选可以筛选admin/manager/trainee
- ✅ 状态筛选可以筛选active/disabled
- ✅ 组合筛选:可以同时使用多个筛选条件
#### 4. 清除筛选
- ✅ 可以单独清除某个筛选条件
- ✅ 可以一次清空所有筛选条件
- ✅ 清除后自动重新加载数据
## 后端API说明
### 用户列表API
**接口**: `GET /api/v1/users/`
**支持的参数**:
- `page`: 页码从1开始
- `page_size`: 每页数量
- `keyword`: 关键词搜索匹配username、email、full_name
- `role`: 角色筛选admin/manager/trainee
- `is_active`: 状态筛选true/false
**返回格式**:
```json
{
"code": 200,
"message": "success",
"data": {
"items": [...],
"total": 117,
"page": 1,
"page_size": 20,
"pages": 6
}
}
```
## 测试用例
### 1. 分页测试
```bash
# 第1页
GET /api/v1/users/?page=1&page_size=20
# 应返回20条记录
# 第2页
GET /api/v1/users/?page=2&page_size=20
# 应返回20条记录不同于第1页
# 最后一页
GET /api/v1/users/?page=6&page_size=20
# 应返回17条记录
```
### 2. 搜索测试
```bash
# 搜索"何平"
GET /api/v1/users/?keyword=何平
# 应返回1条记录
# 搜索"美学规划师"
GET /api/v1/users/?keyword=美学规划师
# 应返回包含"美学规划师"姓名的记录
```
### 3. 筛选测试
```bash
# 筛选管理者
GET /api/v1/users/?role=manager
# 应返回5条记录
# 筛选学员
GET /api/v1/users/?role=trainee
# 应返回111条记录
# 组合筛选:管理者+激活状态
GET /api/v1/users/?role=manager&is_active=true
# 应返回激活的管理者
```
## 技术要点
### 前端开发注意事项
1. **服务端分页vs客户端分页**
- 数据量大时(>100条必须使用服务端分页
- 客户端分页仅适用于小数据量(<100条
2. **API参数命名**
- 注意后端使用的参数名(如 `page_size` 而不是 `pageSize`
- 不同后端可能有不同的命名风格
3. **筛选条件变化时**
- 重置到第1页`currentPage.value = 1`
- 重新加载数据:`loadUserList()`
4. **用户体验优化**
- 实时搜索:输入时立即触发
- 加载状态显示loading
- 搜索防抖:避免频繁请求(可选)
## 相关文件
- 前端组件:`kaopeilian-frontend/src/views/admin/user-management.vue`
- 后端API`kaopeilian-backend/app/api/v1/users.py`
- 用户服务:`kaopeilian-backend/app/services/user_service.py`
## 更新时间
2025-11-11 20:00
## 修复状态
✅ 已完成并验证