fix(fe): 修复中优先级表格功能问题

修复的问题:

1. **搜索和筛选防抖不同步**(AccountsView.vue)
   - 问题:筛选器使用 reload(立即),搜索使用 debouncedReload(300ms延迟)
   - 修复:统一使用 debouncedReload,避免多余的API调用

2. **useTableLoader 竞态条件**(useTableLoader.ts)
   - 问题:finally 块检查 signal.aborted 而不是 controller 实例
   - 修复:检查 abortController === currentController

3. **改进错误处理**(UsersView.vue)
   - 添加详细错误消息:error.response?.data?.detail || error.message
   - 用户可以看到具体的错误原因而不是通用消息

4. **分页边界检查**(useTableLoader.ts, UsersView.vue)
   - 添加页码有效性检查:Math.max(1, Math.min(page, pagination.pages || 1))
   - 防止分页越界导致显示空表

影响范围:
- frontend/src/composables/useTableLoader.ts
- frontend/src/views/admin/AccountsView.vue
- frontend/src/views/admin/UsersView.vue

测试:✓ 前端构建测试通过
This commit is contained in:
IanShaw027
2026-01-09 17:58:21 +08:00
parent ee9b9b3971
commit 514f5802b5
3 changed files with 15 additions and 9 deletions

View File

@@ -43,7 +43,8 @@ export function useTableLoader<T, P extends Record<string, any>>(options: TableL
if (abortController) {
abortController.abort()
}
abortController = new AbortController()
const currentController = new AbortController()
abortController = currentController
loading.value = true
try {
@@ -51,9 +52,9 @@ export function useTableLoader<T, P extends Record<string, any>>(options: TableL
pagination.page,
pagination.page_size,
toRaw(params) as P,
{ signal: abortController.signal }
{ signal: currentController.signal }
)
items.value = response.items || []
pagination.total = response.total || 0
pagination.pages = response.pages || 0
@@ -63,7 +64,7 @@ export function useTableLoader<T, P extends Record<string, any>>(options: TableL
throw error
}
} finally {
if (abortController && !abortController.signal.aborted) {
if (abortController === currentController) {
loading.value = false
}
}
@@ -77,7 +78,9 @@ export function useTableLoader<T, P extends Record<string, any>>(options: TableL
const debouncedReload = useDebounceFn(reload, debounceMs)
const handlePageChange = (page: number) => {
pagination.page = page
// 确保页码在有效范围内
const validPage = Math.max(1, Math.min(page, pagination.pages || 1))
pagination.page = validPage
load()
}

View File

@@ -7,7 +7,7 @@
v-model:searchQuery="params.search"
:filters="params"
@update:filters="(newFilters) => Object.assign(params, newFilters)"
@change="reload"
@change="debouncedReload"
@update:searchQuery="debouncedReload"
/>
<AccountTableActions

View File

@@ -893,12 +893,13 @@ const loadUsers = async () => {
}
}
}
} catch (error) {
} catch (error: any) {
const errorInfo = error as { name?: string; code?: string }
if (errorInfo?.name === 'AbortError' || errorInfo?.name === 'CanceledError' || errorInfo?.code === 'ERR_CANCELED') {
return
}
appStore.showError(t('admin.users.failedToLoad'))
const message = error.response?.data?.detail || error.message || t('admin.users.failedToLoad')
appStore.showError(message)
console.error('Error loading users:', error)
} finally {
if (abortController === currentAbortController) {
@@ -917,7 +918,9 @@ const handleSearch = () => {
}
const handlePageChange = (page: number) => {
pagination.page = page
// 确保页码在有效范围内
const validPage = Math.max(1, Math.min(page, pagination.pages || 1))
pagination.page = validPage
loadUsers()
}