mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-03 01:40:21 +08:00
feat: Provider 摘要 API 改为服务端分页,支持搜索和筛选
- 后端 /summary 接口新增 page/page_size/search/status/api_format/model_id 参数 - 新增 ProviderSummaryPageResponse 分页响应模型 - 前端 useProviderFilters 从客户端筛选改为构建服务端查询参数 - ProviderManagement 通过 watch queryParams 实现分页/筛选联动,搜索 debounce 300ms - PriorityManagementDialog 改为对话框打开时自行加载全量 providers - 其他使用方(StandaloneKeyFormDialog/UserFormDialog/ReplayDialog/ModelManagement)适配新接口
This commit is contained in:
@@ -36,7 +36,7 @@
|
||||
|
||||
<!-- 空状态 -->
|
||||
<div
|
||||
v-else-if="filteredProviders.length === 0"
|
||||
v-else-if="providers.length === 0"
|
||||
class="flex flex-col items-center justify-center py-16 text-center"
|
||||
>
|
||||
<div class="text-muted-foreground mb-2">
|
||||
@@ -87,7 +87,7 @@
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
<ProviderTableRow
|
||||
v-for="provider in paginatedProviders"
|
||||
v-for="provider in providers"
|
||||
:key="provider.id"
|
||||
:provider="provider"
|
||||
:editing-description-id="editingDescriptionId"
|
||||
@@ -118,11 +118,11 @@
|
||||
|
||||
<!-- 移动端卡片列表 -->
|
||||
<div
|
||||
v-if="!loading && filteredProviders.length > 0"
|
||||
v-if="!loading && providers.length > 0"
|
||||
class="xl:hidden divide-y divide-border/40"
|
||||
>
|
||||
<ProviderMobileCard
|
||||
v-for="provider in paginatedProviders"
|
||||
v-for="provider in providers"
|
||||
:key="provider.id"
|
||||
:provider="provider"
|
||||
:editing-description-id="editingDescriptionId"
|
||||
@@ -146,9 +146,9 @@
|
||||
|
||||
<!-- 分页 -->
|
||||
<Pagination
|
||||
v-if="!loading && filteredProviders.length > 0"
|
||||
v-if="!loading && total > 0"
|
||||
:current="currentPage"
|
||||
:total="filteredProviders.length"
|
||||
:total="total"
|
||||
:page-size="pageSize"
|
||||
cache-key="provider-management-page-size"
|
||||
@update:current="currentPage = $event"
|
||||
@@ -168,7 +168,6 @@
|
||||
|
||||
<PriorityManagementDialog
|
||||
v-model="priorityDialogOpen"
|
||||
:providers="providers"
|
||||
@saved="handlePrioritySaved"
|
||||
/>
|
||||
|
||||
@@ -190,7 +189,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted, onUnmounted } from 'vue'
|
||||
import { ref, computed, watch, onMounted, onUnmounted } from 'vue'
|
||||
import Button from '@/components/ui/button.vue'
|
||||
import Card from '@/components/ui/card.vue'
|
||||
import Table from '@/components/ui/table.vue'
|
||||
@@ -247,13 +246,12 @@ const {
|
||||
apiFormatFilters,
|
||||
modelFilters,
|
||||
hasActiveFilters,
|
||||
filteredProviders,
|
||||
currentPage,
|
||||
pageSize,
|
||||
paginatedProviders,
|
||||
total,
|
||||
queryParams,
|
||||
resetFilters,
|
||||
} = useProviderFilters(
|
||||
() => providers.value,
|
||||
() => globalModels.value,
|
||||
)
|
||||
|
||||
@@ -349,14 +347,15 @@ async function loadGlobalModelList() {
|
||||
}
|
||||
}
|
||||
|
||||
// 加载提供商列表
|
||||
// 加载提供商列表(服务端分页)
|
||||
async function loadProviders() {
|
||||
const requestId = ++providersRequestId
|
||||
loading.value = true
|
||||
try {
|
||||
const nextProviders = await getProvidersSummary()
|
||||
const response = await getProvidersSummary(queryParams.value)
|
||||
if (requestId !== providersRequestId) return
|
||||
providers.value = nextProviders
|
||||
providers.value = response.items
|
||||
total.value = response.total
|
||||
// 异步加载配置了 ops 的 provider 的余额数据
|
||||
loadBalances(providers.value)
|
||||
} catch (err: unknown) {
|
||||
@@ -369,6 +368,24 @@ async function loadProviders() {
|
||||
}
|
||||
}
|
||||
|
||||
// 分页/筛选/搜索变化时重新加载
|
||||
let debounceTimer: ReturnType<typeof setTimeout> | null = null
|
||||
watch(queryParams, (newParams, oldParams) => {
|
||||
if (debounceTimer) clearTimeout(debounceTimer)
|
||||
// 搜索输入 debounce 300ms,其他变化立即执行
|
||||
const isSearchOnly = newParams.search !== oldParams?.search &&
|
||||
newParams.page === oldParams?.page &&
|
||||
newParams.page_size === oldParams?.page_size &&
|
||||
newParams.status === oldParams?.status &&
|
||||
newParams.api_format === oldParams?.api_format &&
|
||||
newParams.model_id === oldParams?.model_id
|
||||
if (isSearchOnly) {
|
||||
debounceTimer = setTimeout(loadProviders, 300)
|
||||
} else {
|
||||
loadProviders()
|
||||
}
|
||||
}, { deep: true })
|
||||
|
||||
// 使用复用的行点击逻辑
|
||||
const { handleMouseDown, shouldTriggerRowClick } = useRowClick()
|
||||
|
||||
@@ -508,6 +525,7 @@ onMounted(() => {
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
if (debounceTimer) clearTimeout(debounceTimer)
|
||||
document.removeEventListener('click', handleGlobalClick, true)
|
||||
stopTick()
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user