From 4ca9674772c135fe05295cb7ba52eaaebf4a7140 Mon Sep 17 00:00:00 2001 From: shaw Date: Tue, 12 Aug 2025 17:55:45 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=8C=E5=96=84=E5=A4=9A=E5=B9=B3?= =?UTF-8?q?=E5=8F=B0=E8=B4=A6=E6=88=B7=E7=AE=A1=E7=90=86=E5=92=8CAPI=20Key?= =?UTF-8?q?s=E9=A1=B5=E9=9D=A2=E5=B1=95=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复OpenAI路由中的gpt-5模型ID处理 - 增强统一调度器的账户选择日志输出 - 优化OAuth流程中的账户类型处理 - 完善API Keys页面的多平台账户信息展示 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- src/routes/openaiRoutes.js | 4 +- src/services/unifiedGeminiScheduler.js | 12 +++++ src/services/unifiedOpenAIScheduler.js | 12 +++++ .../src/components/accounts/AccountForm.vue | 8 +-- .../src/components/accounts/OAuthFlow.vue | 53 ++++++++++++++----- web/admin-spa/src/views/ApiKeysView.vue | 43 ++++++++++++++- 6 files changed, 112 insertions(+), 20 deletions(-) diff --git a/src/routes/openaiRoutes.js b/src/routes/openaiRoutes.js index cf5a08c6..af1a482a 100644 --- a/src/routes/openaiRoutes.js +++ b/src/routes/openaiRoutes.js @@ -68,14 +68,14 @@ router.post('/responses', authenticateApiKey, async (req, res) => { // 从请求体中提取模型和流式标志 let requestedModel = req.body?.model || null - + // 如果模型是 gpt-5 开头且后面还有内容(如 gpt-5-2025-08-07),则覆盖为 gpt-5 if (requestedModel && requestedModel.startsWith('gpt-5-') && requestedModel !== 'gpt-5') { logger.info(`📝 Model ${requestedModel} detected, normalizing to gpt-5 for Codex API`) requestedModel = 'gpt-5' req.body.model = 'gpt-5' // 同时更新请求体中的模型 } - + const isStream = req.body?.stream !== false // 默认为流式(兼容现有行为) // 判断是否为 Codex CLI 的请求 diff --git a/src/services/unifiedGeminiScheduler.js b/src/services/unifiedGeminiScheduler.js index 8ff6d5e5..face2c81 100644 --- a/src/services/unifiedGeminiScheduler.js +++ b/src/services/unifiedGeminiScheduler.js @@ -38,6 +38,8 @@ class UnifiedGeminiScheduler { logger.info( `🎯 Using bound dedicated Gemini account: ${boundAccount.name} (${apiKeyData.geminiAccountId}) for API key ${apiKeyData.name}` ) + // 更新账户的最后使用时间 + await geminiAccountService.markAccountUsed(apiKeyData.geminiAccountId) return { accountId: apiKeyData.geminiAccountId, accountType: 'gemini' @@ -62,6 +64,8 @@ class UnifiedGeminiScheduler { logger.info( `🎯 Using sticky session account: ${mappedAccount.accountId} (${mappedAccount.accountType}) for session ${sessionHash}` ) + // 更新账户的最后使用时间 + await geminiAccountService.markAccountUsed(mappedAccount.accountId) return mappedAccount } else { logger.warn( @@ -108,6 +112,9 @@ class UnifiedGeminiScheduler { `🎯 Selected account: ${selectedAccount.name} (${selectedAccount.accountId}, ${selectedAccount.accountType}) with priority ${selectedAccount.priority} for API key ${apiKeyData.name}` ) + // 更新账户的最后使用时间 + await geminiAccountService.markAccountUsed(selectedAccount.accountId) + return { accountId: selectedAccount.accountId, accountType: selectedAccount.accountType @@ -378,6 +385,8 @@ class UnifiedGeminiScheduler { logger.info( `🎯 Using sticky session account from group: ${mappedAccount.accountId} (${mappedAccount.accountType}) for session ${sessionHash}` ) + // 更新账户的最后使用时间 + await geminiAccountService.markAccountUsed(mappedAccount.accountId) return mappedAccount } } @@ -473,6 +482,9 @@ class UnifiedGeminiScheduler { `🎯 Selected account from Gemini group ${group.name}: ${selectedAccount.name} (${selectedAccount.accountId}, ${selectedAccount.accountType}) with priority ${selectedAccount.priority}` ) + // 更新账户的最后使用时间 + await geminiAccountService.markAccountUsed(selectedAccount.accountId) + return { accountId: selectedAccount.accountId, accountType: selectedAccount.accountType diff --git a/src/services/unifiedOpenAIScheduler.js b/src/services/unifiedOpenAIScheduler.js index cd93cb59..0c8b89a5 100644 --- a/src/services/unifiedOpenAIScheduler.js +++ b/src/services/unifiedOpenAIScheduler.js @@ -38,6 +38,8 @@ class UnifiedOpenAIScheduler { logger.info( `🎯 Using bound dedicated OpenAI account: ${boundAccount.name} (${apiKeyData.openaiAccountId}) for API key ${apiKeyData.name}` ) + // 更新账户的最后使用时间 + await openaiAccountService.recordUsage(apiKeyData.openaiAccountId, 0) return { accountId: apiKeyData.openaiAccountId, accountType: 'openai' @@ -62,6 +64,8 @@ class UnifiedOpenAIScheduler { logger.info( `🎯 Using sticky session account: ${mappedAccount.accountId} (${mappedAccount.accountType}) for session ${sessionHash}` ) + // 更新账户的最后使用时间 + await openaiAccountService.recordUsage(mappedAccount.accountId, 0) return mappedAccount } else { logger.warn( @@ -108,6 +112,9 @@ class UnifiedOpenAIScheduler { `🎯 Selected account: ${selectedAccount.name} (${selectedAccount.accountId}, ${selectedAccount.accountType}) with priority ${selectedAccount.priority} for API key ${apiKeyData.name}` ) + // 更新账户的最后使用时间 + await openaiAccountService.recordUsage(selectedAccount.accountId, 0) + return { accountId: selectedAccount.accountId, accountType: selectedAccount.accountType @@ -372,6 +379,8 @@ class UnifiedOpenAIScheduler { logger.info( `🎯 Using sticky session account from group: ${mappedAccount.accountId} (${mappedAccount.accountType})` ) + // 更新账户的最后使用时间 + await openaiAccountService.recordUsage(mappedAccount.accountId, 0) return mappedAccount } } @@ -459,6 +468,9 @@ class UnifiedOpenAIScheduler { `🎯 Selected account from group: ${selectedAccount.name} (${selectedAccount.accountId}) with priority ${selectedAccount.priority}` ) + // 更新账户的最后使用时间 + await openaiAccountService.recordUsage(selectedAccount.accountId, 0) + return { accountId: selectedAccount.accountId, accountType: selectedAccount.accountType diff --git a/web/admin-spa/src/components/accounts/AccountForm.vue b/web/admin-spa/src/components/accounts/AccountForm.vue index 86faf2de..f7ab22d0 100644 --- a/web/admin-spa/src/components/accounts/AccountForm.vue +++ b/web/admin-spa/src/components/accounts/AccountForm.vue @@ -355,8 +355,8 @@ @@ -529,8 +529,8 @@ @@ -1115,8 +1115,8 @@ @@ -1234,8 +1234,8 @@ diff --git a/web/admin-spa/src/components/accounts/OAuthFlow.vue b/web/admin-spa/src/components/accounts/OAuthFlow.vue index fa798518..f688f988 100644 --- a/web/admin-spa/src/components/accounts/OAuthFlow.vue +++ b/web/admin-spa/src/components/accounts/OAuthFlow.vue @@ -325,6 +325,17 @@

请在新标签页中打开授权链接,登录您的 OpenAI 账户并授权。

+
+

+ + 重要提示:授权后页面可能会加载较长时间,请耐心等待。 +

+

+ 当浏览器地址栏变为 + http://localhost:1455/... + 开头时,表示授权已完成。 +

+

@@ -345,27 +356,40 @@ 3

-

输入 Authorization Code

+

输入授权链接或 Code

- 授权完成后,页面会显示一个 - Authorization Code,请将其复制并粘贴到下方输入框: + 授权完成后,当页面地址变为 + http://localhost:1455/... 时: