From b3cba9e091078a3ca22106d820f6f58e85a2ce30 Mon Sep 17 00:00:00 2001 From: shaw Date: Tue, 12 Aug 2025 15:01:56 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=8C=E5=96=84API=20Keys=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E5=A4=9A=E5=B9=B3=E5=8F=B0=E8=B4=A6=E6=88=B7=E7=BB=91?= =?UTF-8?q?=E5=AE=9A=E4=BF=A1=E6=81=AF=E5=B1=95=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 支持显示Claude、Gemini和OpenAI三个平台的账户绑定信息 - 添加账户状态提醒(不存在、专属、分组、共享池) - 优化UI设计,使用彩色标签区分不同平台 - 改进响应式布局,适配移动端和平板设备 - 修复OpenAI账户绑定数量统计问题 - 修复删除账户时OpenAI绑定检查逻辑 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- web/admin-spa/src/views/AccountsView.vue | 11 +- web/admin-spa/src/views/ApiKeysView.vue | 207 ++++++++++++++++++++--- 2 files changed, 195 insertions(+), 23 deletions(-) diff --git a/web/admin-spa/src/views/AccountsView.vue b/web/admin-spa/src/views/AccountsView.vue index 59dd3191..c6802e13 100644 --- a/web/admin-spa/src/views/AccountsView.vue +++ b/web/admin-spa/src/views/AccountsView.vue @@ -1010,8 +1010,12 @@ const loadAccounts = async (forceReload = false) => { } if (openaiData.success) { const openaiAccounts = (openaiData.data || []).map((acc) => { + // 计算每个OpenAI账户绑定的API Key数量 + const boundApiKeysCount = apiKeys.value.filter( + (key) => key.openaiAccountId === acc.id + ).length const groupInfo = accountGroupMap.value.get(acc.id) || null - return { ...acc, platform: 'openai', boundApiKeysCount: 0, groupInfo } + return { ...acc, platform: 'openai', boundApiKeysCount, groupInfo } }) allAccounts.push(...openaiAccounts) } @@ -1210,7 +1214,10 @@ const editAccount = (account) => { const deleteAccount = async (account) => { // 检查是否有API Key绑定到此账号 const boundKeysCount = apiKeys.value.filter( - (key) => key.claudeAccountId === account.id || key.geminiAccountId === account.id + (key) => + key.claudeAccountId === account.id || + key.geminiAccountId === account.id || + key.openaiAccountId === account.id ).length if (boundKeysCount > 0) { diff --git a/web/admin-spa/src/views/ApiKeysView.vue b/web/admin-spa/src/views/ApiKeysView.vue index dc52fad1..3b9bad49 100644 --- a/web/admin-spa/src/views/ApiKeysView.vue +++ b/web/admin-spa/src/views/ApiKeysView.vue @@ -206,18 +206,60 @@
{{ key.id }}
-
- +
+ +
+ + + Claude + + + {{ getClaudeBindingInfo(key) }} + +
+ +
+ + + Gemini + + + {{ getGeminiBindingInfo(key) }} + +
+ +
+ + + OpenAI + + + {{ getOpenAIBindingInfo(key) }} + +
+ +
- - {{ getBoundAccountName(key.claudeAccountId) }} - - - 共享池 - + 使用共享池 +
@@ -712,16 +754,58 @@ - -
- - - 绑定: {{ getBoundAccountName(key.claudeAccountId, key.claudeConsoleAccountId) }} - - + +
+ +
+ + + Claude + + + {{ getClaudeBindingInfo(key) }} + +
+ +
+ + + Gemini + + + {{ getGeminiBindingInfo(key) }} + +
+ +
+ + + OpenAI + + + {{ getOpenAIBindingInfo(key) }} + +
+ +
使用共享池 - +
@@ -1300,6 +1384,12 @@ const getBoundAccountName = (accountId) => { return `分组-${geminiGroup.name}` } + // 从OpenAI分组中查找 + const openaiGroup = accounts.value.openaiGroups.find((g) => g.id === groupId) + if (openaiGroup) { + return `分组-${openaiGroup.name}` + } + // 如果找不到分组,返回分组ID的前8位 return `分组-${groupId.substring(0, 8)}` } @@ -1307,17 +1397,92 @@ const getBoundAccountName = (accountId) => { // 从Claude账户列表中查找 const claudeAccount = accounts.value.claude.find((acc) => acc.id === accountId) if (claudeAccount) { - return `账户-${claudeAccount.name}` + return `${claudeAccount.name}` } // 从Gemini账户列表中查找 const geminiAccount = accounts.value.gemini.find((acc) => acc.id === accountId) if (geminiAccount) { - return `账户-${geminiAccount.name}` + return `${geminiAccount.name}` + } + + // 从OpenAI账户列表中查找 + const openaiAccount = accounts.value.openai.find((acc) => acc.id === accountId) + if (openaiAccount) { + return `${openaiAccount.name}` } // 如果找不到,返回账户ID的前8位 - return `账户-${accountId.substring(0, 8)}` + return `${accountId.substring(0, 8)}` +} + +// 获取Claude绑定信息 +const getClaudeBindingInfo = (key) => { + if (key.claudeAccountId) { + const info = getBoundAccountName(key.claudeAccountId) + if (key.claudeAccountId.startsWith('group:')) { + return info + } + // 检查账户是否存在 + const account = accounts.value.claude.find((acc) => acc.id === key.claudeAccountId) + if (!account) { + return `⚠️ ${info} (账户不存在)` + } + if (account.accountType === 'dedicated') { + return `🔒 专属-${info}` + } + return info + } + if (key.claudeConsoleAccountId) { + const account = accounts.value.claude.find( + (acc) => acc.id === key.claudeConsoleAccountId && acc.platform === 'claude-console' + ) + if (!account) { + return `⚠️ Console账户不存在` + } + return `Console-${account.name}` + } + return '' +} + +// 获取Gemini绑定信息 +const getGeminiBindingInfo = (key) => { + if (key.geminiAccountId) { + const info = getBoundAccountName(key.geminiAccountId) + if (key.geminiAccountId.startsWith('group:')) { + return info + } + // 检查账户是否存在 + const account = accounts.value.gemini.find((acc) => acc.id === key.geminiAccountId) + if (!account) { + return `⚠️ ${info} (账户不存在)` + } + if (account.accountType === 'dedicated') { + return `🔒 专属-${info}` + } + return info + } + return '' +} + +// 获取OpenAI绑定信息 +const getOpenAIBindingInfo = (key) => { + if (key.openaiAccountId) { + const info = getBoundAccountName(key.openaiAccountId) + if (key.openaiAccountId.startsWith('group:')) { + return info + } + // 检查账户是否存在 + const account = accounts.value.openai.find((acc) => acc.id === key.openaiAccountId) + if (!account) { + return `⚠️ ${info} (账户不存在)` + } + if (account.accountType === 'dedicated') { + return `🔒 专属-${info}` + } + return info + } + return '' } // 检查API Key是否过期