From d5b9f809b00c45da970b15638d201c7cf1b5b787 Mon Sep 17 00:00:00 2001 From: Wangnov Date: Wed, 10 Sep 2025 18:13:27 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=E5=B8=83=E5=B1=80/?= =?UTF-8?q?=E4=BB=AA=E8=A1=A8=E6=9D=BF/=E7=94=A8=E6=88=B7=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E7=BB=84=E4=BB=B6=E5=9B=BD=E9=99=85=E5=8C=96=E4=B8=8E?= =?UTF-8?q?=E8=AF=AD=E8=A8=80=E5=88=87=E6=8D=A2=E4=BC=98=E5=8C=96=EF=BC=88?= =?UTF-8?q?TabBar/MainLayout/AppHeader=E3=80=81UsageTrend/ModelDistributio?= =?UTF-8?q?n=E3=80=81User*=E3=80=81Common=20=E7=BB=84=E4=BB=B6=E3=80=81i18?= =?UTF-8?q?n/locale=20=E5=A2=9E=E5=BC=BA=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/admin-spa/components.d.ts | 1 + .../src/components/common/AccountSelector.vue | 172 +++++------------- .../src/components/common/ConfirmDialog.vue | 12 +- .../src/components/common/ConfirmModal.vue | 8 +- .../src/components/common/CustomDropdown.vue | 5 +- .../src/components/common/LanguageSwitch.vue | 6 +- .../src/components/common/LogoTitle.vue | 2 +- .../src/components/common/ThemeToggle.vue | 26 ++- .../components/common/ToastNotification.vue | 12 +- .../dashboard/ModelDistribution.vue | 33 +++- .../src/components/dashboard/UsageTrend.vue | 34 ++-- .../src/components/layout/AppHeader.vue | 6 +- .../src/components/layout/MainLayout.vue | 5 +- .../src/components/layout/TabBar.vue | 42 ++++- .../src/components/user/CreateApiKeyModal.vue | 46 +++-- .../components/user/UserApiKeysManager.vue | 78 +++++--- .../src/components/user/UserUsageStats.vue | 90 +++++---- .../src/components/user/ViewApiKeyModal.vue | 93 +++++++--- web/admin-spa/src/i18n/index.js | 22 +++ web/admin-spa/src/stores/locale.js | 17 +- 20 files changed, 410 insertions(+), 300 deletions(-) diff --git a/web/admin-spa/components.d.ts b/web/admin-spa/components.d.ts index 9112dcd1..212216a5 100644 --- a/web/admin-spa/components.d.ts +++ b/web/admin-spa/components.d.ts @@ -20,6 +20,7 @@ declare module 'vue' { CreateApiKeyModal: typeof import('./src/components/apikeys/CreateApiKeyModal.vue')['default'] CustomDropdown: typeof import('./src/components/common/CustomDropdown.vue')['default'] EditApiKeyModal: typeof import('./src/components/apikeys/EditApiKeyModal.vue')['default'] + ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider'] ElDatePicker: typeof import('element-plus/es')['ElDatePicker'] ElTooltip: typeof import('element-plus/es')['ElTooltip'] ExpiryEditModal: typeof import('./src/components/apikeys/ExpiryEditModal.vue')['default'] diff --git a/web/admin-spa/src/components/common/AccountSelector.vue b/web/admin-spa/src/components/common/AccountSelector.vue index ac9e4894..13fa1aa4 100644 --- a/web/admin-spa/src/components/common/AccountSelector.vue +++ b/web/admin-spa/src/components/common/AccountSelector.vue @@ -41,7 +41,7 @@ ref="searchInput" v-model="searchQuery" class="form-input w-full border-gray-300 text-sm dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200 dark:placeholder-gray-400" - placeholder="搜索账号名称..." + :placeholder="$t('common.accountSelector.searchPlaceholder')" style="padding-left: 40px; padding-right: 36px" type="text" @input="handleSearch" @@ -68,7 +68,9 @@ :class="{ 'bg-blue-50 dark:bg-blue-900/20': !modelValue }" @click="selectAccount(null)" > - {{ defaultOptionText }} + {{ + props.defaultOptionText || $t('common.accountSelector.useSharedPool') + }} @@ -76,7 +78,7 @@
- 调度分组 + {{ $t('common.accountSelector.schedulingGroups') }}
{{ group.name }} {{ group.memberCount || 0 }} 个成员{{ group.memberCount || 0 + }}{{ $t('common.accountSelector.membersUnit') }}
@@ -101,10 +104,8 @@ > {{ platform === 'claude' - ? 'Claude OAuth 专属账号' - : platform === 'openai' - ? 'OpenAI 专属账号' - : 'OAuth 专属账号' + ? $t('common.accountSelector.claudeOAuthAccounts') + : $t('common.accountSelector.oauthAccounts') }}
- Claude Console 专属账号 + {{ $t('common.accountSelector.claudeConsoleAccounts') }}
- -
-
- OpenAI-Responses 专属账号 -
-
-
-
- {{ account.name }} - - {{ getAccountStatusText(account) }} - -
- - {{ formatDate(account.createdAt) }} - -
-
-
-
-

没有找到匹配的账号

+

{{ $t('common.accountSelector.noResultsFound') }}

@@ -232,6 +194,9 @@ diff --git a/web/admin-spa/src/i18n/index.js b/web/admin-spa/src/i18n/index.js index 4bd2028f..31dd2b49 100644 --- a/web/admin-spa/src/i18n/index.js +++ b/web/admin-spa/src/i18n/index.js @@ -35,6 +35,28 @@ function getBrowserLocale() { const savedLocale = localStorage.getItem('app-locale') const defaultLocale = savedLocale || getBrowserLocale() +// 创建一个函数来获取本地化的语言信息 +export function getSupportedLocalesWithI18n(t) { + return { + 'zh-cn': { + name: t('common.languageSwitch.zhCnName'), + flag: t('common.languageSwitch.zhCnFlag'), + shortName: t('common.languageSwitch.zhCnFlag') + }, + 'zh-tw': { + name: t('common.languageSwitch.zhTwName'), + flag: t('common.languageSwitch.zhTwFlag'), + shortName: t('common.languageSwitch.zhTwFlag') + }, + en: { + name: t('common.languageSwitch.enName'), + flag: t('common.languageSwitch.enFlag'), + shortName: t('common.languageSwitch.enFlag') + } + } +} + +// 保持原有的SUPPORTED_LOCALES作为默认值,用于不依赖i18n的场景 export const SUPPORTED_LOCALES = { 'zh-cn': { name: '简体中文', diff --git a/web/admin-spa/src/stores/locale.js b/web/admin-spa/src/stores/locale.js index 7b6ad24d..eb795048 100644 --- a/web/admin-spa/src/stores/locale.js +++ b/web/admin-spa/src/stores/locale.js @@ -1,6 +1,6 @@ import { defineStore } from 'pinia' import { ref } from 'vue' -import { i18n, SUPPORTED_LOCALES } from '@/i18n' +import { i18n, SUPPORTED_LOCALES, getSupportedLocalesWithI18n } from '@/i18n' export const useLocaleStore = defineStore('locale', () => { const currentLocale = ref(i18n.global.locale.value) @@ -20,14 +20,19 @@ export const useLocaleStore = defineStore('locale', () => { document.documentElement.setAttribute('lang', locale) } - // 获取当前语言信息 - const getCurrentLocaleInfo = () => { + // 获取当前语言信息(兼容i18n) + const getCurrentLocaleInfo = (t = null) => { + if (t) { + const supportedLocales = getSupportedLocalesWithI18n(t) + return supportedLocales[currentLocale.value] || supportedLocales['zh-cn'] + } return SUPPORTED_LOCALES[currentLocale.value] || SUPPORTED_LOCALES['zh-cn'] } - // 获取所有支持的语言 - const getSupportedLocales = () => { - return Object.entries(SUPPORTED_LOCALES).map(([key, value]) => ({ + // 获取所有支持的语言(兼容i18n) + const getSupportedLocales = (t = null) => { + const supportedLocales = t ? getSupportedLocalesWithI18n(t) : SUPPORTED_LOCALES + return Object.entries(supportedLocales).map(([key, value]) => ({ code: key, ...value }))