From c9e4b267b6fac1f00060eab983e606f7a2b2d4fc Mon Sep 17 00:00:00 2001 From: feeeei Date: Sat, 10 Oct 2026 19:12:10 +0800 Subject: [PATCH] =?UTF-8?q?fix(account):=20=E5=90=8C=E6=AD=A5=E4=B8=8A?= =?UTF-8?q?=E6=B8=B8=E6=A8=A1=E5=9E=8B=E5=A4=B1=E8=B4=A5=E6=97=B6=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E5=90=8E=E7=AB=AF=E8=BF=94=E5=9B=9E=E7=9A=84=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E5=8E=9F=E5=9B=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - apiClient 拒绝的是普通对象而非 Error,原写法 instanceof Error 恒为假, 错误提示被替换成通用文案"同步上游模型失败:同步上游模型失败" - 白名单选择器与 Antigravity 同步按钮改用 extractApiErrorMessage 取消息 --- .../components/account/EditAccountModal.vue | 2 +- .../account/ModelWhitelistSelector.vue | 3 ++- .../__tests__/ModelWhitelistSelector.spec.ts | 22 ++++++++++++++++++- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/frontend/src/components/account/EditAccountModal.vue b/frontend/src/components/account/EditAccountModal.vue index 9bc4f9167a..04b1c9f68f 100644 --- a/frontend/src/components/account/EditAccountModal.vue +++ b/frontend/src/components/account/EditAccountModal.vue @@ -4771,7 +4771,7 @@ const syncAntigravityUpstreamModels = async () => { appStore.showWarning(t('admin.accounts.syncUpstreamModelsMetadataPartial')) } } catch (error) { - const message = error instanceof Error ? error.message : t('admin.accounts.syncUpstreamModelsFailed') + const message = extractApiErrorMessage(error, t('admin.accounts.syncUpstreamModelsFailed')) appStore.showError(t('admin.accounts.syncUpstreamModelsError', { message })) } finally { isSyncingAntigravityUpstream.value = false diff --git a/frontend/src/components/account/ModelWhitelistSelector.vue b/frontend/src/components/account/ModelWhitelistSelector.vue index d953c21ce9..aa09de7bbb 100644 --- a/frontend/src/components/account/ModelWhitelistSelector.vue +++ b/frontend/src/components/account/ModelWhitelistSelector.vue @@ -155,6 +155,7 @@ import ModelIcon from '@/components/common/ModelIcon.vue' import Icon from '@/components/icons/Icon.vue' import { allModels, getModelsByPlatform } from '@/composables/useModelWhitelist' import { supportsUpstreamModelSync } from '@/constants/platformCatalog' +import { extractApiErrorMessage } from '@/utils/apiError' const { t } = useI18n() @@ -343,7 +344,7 @@ const syncUpstreamModels = async () => { appStore.showWarning(t('admin.accounts.syncUpstreamModelsMetadataPartial')) } } catch (error) { - const message = error instanceof Error ? error.message : t('admin.accounts.syncUpstreamModelsFailed') + const message = extractApiErrorMessage(error, t('admin.accounts.syncUpstreamModelsFailed')) appStore.showError(t('admin.accounts.syncUpstreamModelsError', { message })) } finally { isSyncingUpstream.value = false diff --git a/frontend/src/components/account/__tests__/ModelWhitelistSelector.spec.ts b/frontend/src/components/account/__tests__/ModelWhitelistSelector.spec.ts index 9e27d29db9..0b5f10a015 100644 --- a/frontend/src/components/account/__tests__/ModelWhitelistSelector.spec.ts +++ b/frontend/src/components/account/__tests__/ModelWhitelistSelector.spec.ts @@ -29,7 +29,7 @@ vi.mock('vue-i18n', async () => { return { ...actual, useI18n: () => ({ - t: (key: string, params?: Record) => key === 'common.copy' ? '复制' : key === 'admin.accounts.modelMappingConflict' ? `Model mapping conflict: ${params?.from} → ${params?.to}` : key + t: (key: string, params?: Record) => key === 'common.copy' ? '复制' : key === 'admin.accounts.modelMappingConflict' ? `Model mapping conflict: ${params?.from} → ${params?.to}` : key === 'admin.accounts.syncUpstreamModelsError' ? `${key}: ${params?.message}` : key }) } }) @@ -244,6 +244,26 @@ describe('ModelWhitelistSelector', () => { expect(showSuccess).not.toHaveBeenCalled() }) + it('shows the backend message when upstream sync is rejected', async () => { + syncUpstreamModels.mockRejectedValue({ + status: 400, + code: 'BAD_REQUEST', + message: 'Vertex API key accounts do not support upstream model listing' + }) + const wrapper = mountSelector({ platform: 'gemini', accountId: 174 }) + + const syncButton = wrapper + .findAll('button') + .find(button => button.text() === 'admin.accounts.syncUpstreamModels') + expect(syncButton).toBeDefined() + await syncButton!.trigger('click') + await flushPromises() + + expect(showError).toHaveBeenCalledWith( + 'admin.accounts.syncUpstreamModelsError: Vertex API key accounts do not support upstream model listing' + ) + }) + it('shows success and a partial warning when some capabilities were saved', async () => { syncUpstreamModels.mockResolvedValue({ models: ['gpt-6-astra', 'gpt-image-2'],