diff --git a/frontend/src/stores/index.ts b/frontend/src/stores/index.ts index 11af9e2be..28659d21a 100644 --- a/frontend/src/stores/index.ts +++ b/frontend/src/stores/index.ts @@ -4,7 +4,3 @@ import piniaPluginPersistedstate from 'pinia-plugin-persistedstate' export const pinia = createPinia() pinia.use(piniaPluginPersistedstate) - -// 导出所有 store -export * from './modules/auth' -export * from './modules/ui' diff --git a/frontend/src/views/accounts/components/AccountFilters.vue b/frontend/src/views/accounts/components/AccountFilters.vue new file mode 100644 index 000000000..fb6bdd76e --- /dev/null +++ b/frontend/src/views/accounts/components/AccountFilters.vue @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + 删除选中 ({{ selectedCount }}) + + + + 导出选中 ({{ selectedCount }}) + + + + 导入账号 + + + + diff --git a/frontend/src/views/accounts/composables/useAccountConnectionTest.ts b/frontend/src/views/accounts/composables/useAccountConnectionTest.ts index e2ee7df91..207b5c3ff 100644 --- a/frontend/src/views/accounts/composables/useAccountConnectionTest.ts +++ b/frontend/src/views/accounts/composables/useAccountConnectionTest.ts @@ -6,6 +6,7 @@ import { computed, onBeforeUnmount, ref, shallowRef, watch } from 'vue' import { getAccountModels, refreshAccountModels } from '@/api' import { API_BASE_URL } from '@/api/constants' import { toast } from '@/components/base/BaseToast' +import { useIdSet } from '@/composables/useIdSet' import { errorMessage, withMinimumDuration } from '@/utils/async' import { formatDateTime, formatTime } from '@/utils/date' @@ -49,7 +50,7 @@ export function useAccountConnectionTest(options: AccountConnectionTestOptions) const connectionTestStartedAt = shallowRef('') const connectionTestFinishedAt = shallowRef('') const connectionTestDurationMs = shallowRef(null) - const testingConnectionIds = ref>(new Set()) + const testingConnections = useIdSet() const loadingConnectionTestModels = shallowRef(false) const refreshingConnectionTestModels = shallowRef(false) const connectionTestSelectedModel = shallowRef('') @@ -218,9 +219,7 @@ export function useAccountConnectionTest(options: AccountConnectionTestOptions) connectionTestRun = undefined closeConnectionTestEventSource() if (run) { - const next = new Set(testingConnectionIds.value) - next.delete(run.accountId) - testingConnectionIds.value = next + testingConnections.remove(run.accountId) run.resolve() } } @@ -350,7 +349,7 @@ export function useAccountConnectionTest(options: AccountConnectionTestOptions) connectionTestError.value = '请先选择测试模型' return } - if (testingConnectionIds.value.has(account.id)) + if (testingConnections.has(account.id)) return abortConnectionTest() connectionTestStatus.value = 'running' @@ -364,7 +363,7 @@ export function useAccountConnectionTest(options: AccountConnectionTestOptions) connectionTestStartedAt.value = formatDateTime() connectionTestFinishedAt.value = '' appendConnectionTestLog('准备发送测试请求', 'info') - testingConnectionIds.value = new Set(testingConnectionIds.value).add(account.id) + testingConnections.add(account.id) try { await withMinimumDuration( () => @@ -436,7 +435,7 @@ export function useAccountConnectionTest(options: AccountConnectionTestOptions) connectionTestStartedAt, connectionTestFinishedAt, connectionTestDurationMs, - testingConnectionIds, + testingConnectionIds: testingConnections.ids, loadingConnectionTestModels, refreshingConnectionTestModels, connectionTestSelectedModel, diff --git a/frontend/src/views/accounts/index.vue b/frontend/src/views/accounts/index.vue index c7cec6335..2c46c5bdb 100644 --- a/frontend/src/views/accounts/index.vue +++ b/frontend/src/views/accounts/index.vue @@ -1,19 +1,16 @@ diff --git a/frontend/src/views/settings/composables/useAdminApiKey.ts b/frontend/src/views/settings/composables/useAdminApiKey.ts index 7e95fa6b0..264955379 100644 --- a/frontend/src/views/settings/composables/useAdminApiKey.ts +++ b/frontend/src/views/settings/composables/useAdminApiKey.ts @@ -6,17 +6,20 @@ import { regenerateAdminApiKey, } from '@/api' import { toast } from '@/components/base/BaseToast' +import { useAsyncAction } from '@/composables/useAsyncAction' import { useCopyText } from '@/composables/useCopyText' import { errorMessage } from '@/utils/async' export function useAdminApiKey() { const loading = shallowRef(true) - const regenerating = shallowRef(false) - const deleting = shallowRef(false) const showDeleteModal = shallowRef(false) const generatedKey = shallowRef('') const status = reactive({ exists: false }) const copyText = useCopyText() + const regenerateAction = useAsyncAction() + const removeAction = useAsyncAction() + const regenerating = regenerateAction.loading + const deleting = removeAction.loading async function loadStatus() { try { @@ -35,39 +38,31 @@ export function useAdminApiKey() { if (regenerating.value || deleting.value) return - try { - regenerating.value = true - const wasEnabled = status.exists - generatedKey.value = (await regenerateAdminApiKey()).key - status.exists = true - toast.success(wasEnabled ? '管理员 API Key 已更新' : '管理员 API Key 已生成') - } - catch (error: unknown) { - toast.error(errorMessage(error, '生成失败')) - } - finally { - regenerating.value = false - } + await regenerateAction.run( + async () => { + const wasEnabled = status.exists + generatedKey.value = (await regenerateAdminApiKey()).key + status.exists = true + toast.success(wasEnabled ? '管理员 API Key 已更新' : '管理员 API Key 已生成') + }, + { errorText: false, onError: error => toast.error(errorMessage(error, '生成失败')) }, + ) } async function remove() { if (deleting.value || regenerating.value) return - try { - deleting.value = true - await deleteAdminApiKey() - status.exists = false - generatedKey.value = '' - showDeleteModal.value = false - toast.success('管理员 API Key 已删除') - } - catch (error: unknown) { - toast.error(errorMessage(error, '删除失败')) - } - finally { - deleting.value = false - } + await removeAction.run( + async () => { + await deleteAdminApiKey() + status.exists = false + generatedKey.value = '' + showDeleteModal.value = false + toast.success('管理员 API Key 已删除') + }, + { errorText: false, onError: error => toast.error(errorMessage(error, '删除失败')) }, + ) } async function copyGeneratedKey() {