perf(frontend): 管理页面更新操作改为局部刷新,避免全量重载列表

Provider、API Key、Pool Key、Management Token 的更新操作
完成后直接替换本地列表中对应记录,仅创建操作保留全量刷新。
This commit is contained in:
fawney19
2026-03-01 11:57:09 +08:00
parent b61fc4eb6b
commit 8b0e92e408
5 changed files with 47 additions and 11 deletions

View File

@@ -302,7 +302,7 @@ const props = defineProps<{
const emit = defineEmits<{ const emit = defineEmits<{
'update:modelValue': [value: boolean] 'update:modelValue': [value: boolean]
'providerCreated': [] 'providerCreated': []
'providerUpdated': [] 'providerUpdated': [provider: ProviderWithEndpointsSummary]
}>() }>()
const { success, error: showError } = useToast() const { success, error: showError } = useToast()
@@ -456,9 +456,9 @@ const handleSubmit = async () => {
if (isEditMode.value && props.provider) { if (isEditMode.value && props.provider) {
// 更新提供商 // 更新提供商
await updateProvider(props.provider.id, payload) const updated = await updateProvider(props.provider.id, payload)
success('提供商更新成功') success('提供商更新成功')
emit('providerUpdated') emit('providerUpdated', updated)
} else { } else {
// 创建提供商 // 创建提供商
await createProvider(payload) await createProvider(payload)

View File

@@ -1141,7 +1141,12 @@ async function handleKeyFormSubmit(data: StandaloneKeyFormData) {
allowed_api_formats: data.allowed_api_formats, allowed_api_formats: data.allowed_api_formats,
allowed_models: data.allowed_models allowed_models: data.allowed_models
} }
await adminApi.updateApiKey(data.id, updateData) const { message: _, ...updated } = await adminApi.updateApiKey(data.id, updateData)
// 局部更新:直接替换列表中对应的记录
const index = apiKeys.value.findIndex(k => k.id === data.id)
if (index !== -1) {
apiKeys.value[index] = updated
}
success('API Key 更新成功') success('API Key 更新成功')
} else { } else {
// 创建 // 创建
@@ -1164,9 +1169,9 @@ async function handleKeyFormSubmit(data: StandaloneKeyFormData) {
newKeyValue.value = response.key newKeyValue.value = response.key
showNewKeyDialog.value = true showNewKeyDialog.value = true
success('独立 Key 创建成功') success('独立 Key 创建成功')
await loadApiKeys()
} }
closeKeyFormDialog() closeKeyFormDialog()
await loadApiKeys()
} catch (err: unknown) { } catch (err: unknown) {
log.error('保存独立Key失败:', err) log.error('保存独立Key失败:', err)
error(parseApiError(err, '保存失败')) error(parseApiError(err, '保存失败'))

View File

@@ -912,7 +912,11 @@ async function toggleKeyActive(key: PoolKeyDetail) {
key_ids: [key.key_id], key_ids: [key.key_id],
action, action,
}) })
await loadKeys() // 局部更新:直接修改本地列表中的状态
const target = keyPage.value.keys.find(k => k.key_id === key.key_id)
if (target) {
target.is_active = !target.is_active
}
} catch (err) { } catch (err) {
showError(parseApiError(err)) showError(parseApiError(err))
} }

View File

@@ -178,7 +178,7 @@
@update:open="providerDrawerOpen = $event" @update:open="providerDrawerOpen = $event"
@edit="openEditProviderDialog" @edit="openEditProviderDialog"
@toggle-status="toggleProviderStatus" @toggle-status="toggleProviderStatus"
@refresh="loadProviders" @refresh="handleDrawerRefresh"
/> />
<ProviderAuthDialog <ProviderAuthDialog
@@ -211,6 +211,7 @@ import { useProviderFilters } from '@/features/providers/composables/useProvider
import { useProviderBalance } from '@/features/providers/composables/useProviderBalance' import { useProviderBalance } from '@/features/providers/composables/useProviderBalance'
import { import {
getProvidersSummary, getProvidersSummary,
getProvider,
deleteProvider, deleteProvider,
updateProvider, updateProvider,
getGlobalModels, getGlobalModels,
@@ -407,8 +408,28 @@ function handleOpsConfigSaved() {
} }
// 处理提供商编辑完成 // 处理提供商编辑完成
function handleProviderUpdated() { function handleProviderUpdated(updated: ProviderWithEndpointsSummary) {
loadProviders() const index = providers.value.findIndex(p => p.id === updated.id)
if (index !== -1) {
providers.value[index] = updated
// 刷新该提供商的余额数据
loadBalances([updated])
}
}
// 处理详情抽屉内的刷新:只刷新当前查看的那一条提供商
async function handleDrawerRefresh() {
if (!selectedProviderId.value) return
try {
const updated = await getProvider(selectedProviderId.value)
const index = providers.value.findIndex(p => p.id === updated.id)
if (index !== -1) {
providers.value[index] = updated
loadBalances([updated])
}
} catch (err) {
showError(parseApiError(err, '刷新提供商数据失败'), '错误')
}
} }
// 优先级保存成功回调 // 优先级保存成功回调

View File

@@ -691,12 +691,18 @@ async function saveToken() {
if (editingToken.value) { if (editingToken.value) {
// 更新 // 更新
await managementTokenApi.updateToken(editingToken.value.id, { const tokenId = editingToken.value.id
const result = await managementTokenApi.updateToken(tokenId, {
name: formData.name, name: formData.name,
description: formData.description.trim() || null, description: formData.description.trim() || null,
allowed_ips: allowedIps.length > 0 ? allowedIps : null, allowed_ips: allowedIps.length > 0 ? allowedIps : null,
expires_at: expiresAtUtc expires_at: expiresAtUtc
}) })
// 局部更新:直接替换列表中对应的记录
const index = tokens.value.findIndex(t => t.id === tokenId)
if (index !== -1) {
tokens.value[index] = result.data
}
success('令牌更新成功') success('令牌更新成功')
} else { } else {
// 创建 // 创建
@@ -710,10 +716,10 @@ async function saveToken() {
isRegenerating.value = false isRegenerating.value = false
showTokenDialog.value = true showTokenDialog.value = true
success('令牌创建成功') success('令牌创建成功')
await loadTokens()
} }
closeDialog() closeDialog()
await loadTokens()
} catch (err: unknown) { } catch (err: unknown) {
log.error('保存 Token 失败:', err) log.error('保存 Token 失败:', err)
showError(parseApiError(err, '保存失败')) showError(parseApiError(err, '保存失败'))