diff --git a/src/routes/admin.js b/src/routes/admin.js index f7b50ff5..ff64da54 100644 --- a/src/routes/admin.js +++ b/src/routes/admin.js @@ -4192,7 +4192,14 @@ router.get('/accounts/:accountId/usage-history', authenticateAdmin, async (req, const { accountId } = req.params const { platform = 'claude', days = 30 } = req.query - const allowedPlatforms = ['claude', 'claude-console', 'openai', 'openai-responses', 'gemini'] + const allowedPlatforms = [ + 'claude', + 'claude-console', + 'openai', + 'openai-responses', + 'gemini', + 'droid' + ] if (!allowedPlatforms.includes(platform)) { return res.status(400).json({ success: false, @@ -4202,7 +4209,8 @@ router.get('/accounts/:accountId/usage-history', authenticateAdmin, async (req, const accountTypeMap = { openai: 'openai', - 'openai-responses': 'openai-responses' + 'openai-responses': 'openai-responses', + droid: 'droid' } const fallbackModelMap = { @@ -4210,7 +4218,8 @@ router.get('/accounts/:accountId/usage-history', authenticateAdmin, async (req, 'claude-console': 'claude-3-5-sonnet-20241022', openai: 'gpt-4o-mini-2024-07-18', 'openai-responses': 'gpt-4o-mini-2024-07-18', - gemini: 'gemini-1.5-flash' + gemini: 'gemini-1.5-flash', + droid: 'unknown' } // 获取账户信息以获取创建时间 @@ -4234,6 +4243,9 @@ router.get('/accounts/:accountId/usage-history', authenticateAdmin, async (req, case 'gemini': accountData = await geminiAccountService.getAccount(accountId) break + case 'droid': + accountData = await droidAccountService.getAccount(accountId) + break } if (accountData && accountData.createdAt) { diff --git a/web/admin-spa/src/components/accounts/AccountUsageDetailModal.vue b/web/admin-spa/src/components/accounts/AccountUsageDetailModal.vue index 8b9fbf33..42cb4bf1 100644 --- a/web/admin-spa/src/components/accounts/AccountUsageDetailModal.vue +++ b/web/admin-spa/src/components/accounts/AccountUsageDetailModal.vue @@ -352,7 +352,8 @@ const platformLabelMap = { 'claude-console': 'Claude Console', openai: 'OpenAI', 'openai-responses': 'OpenAI Responses', - gemini: 'Gemini' + gemini: 'Gemini', + droid: 'Droid' } const platformLabel = computed(() => platformLabelMap[props.account?.platform] || '未知平台') diff --git a/web/admin-spa/src/components/accounts/OAuthFlow.vue b/web/admin-spa/src/components/accounts/OAuthFlow.vue index ae6e9f20..e9965204 100644 --- a/web/admin-spa/src/components/accounts/OAuthFlow.vue +++ b/web/admin-spa/src/components/accounts/OAuthFlow.vue @@ -679,10 +679,8 @@ const sessionId = ref('') // 保存sessionId用于后续交换 const userCode = ref('') const verificationUri = ref('') const verificationUriComplete = ref('') -const pollInterval = ref(5) const remainingSeconds = ref(0) let countdownTimer = null -let pendingTimer = null // 计算是否可以交换code const canExchange = computed(() => { @@ -788,10 +786,6 @@ watch(authCode, (newValue) => { // 生成授权URL const generateAuthUrl = async () => { - if (pendingTimer) { - clearTimeout(pendingTimer) - pendingTimer = null - } stopCountdown() authUrl.value = '' authCode.value = '' @@ -800,7 +794,6 @@ const generateAuthUrl = async () => { verificationUriComplete.value = '' remainingSeconds.value = 0 sessionId.value = '' - pollInterval.value = 5 copied.value = false loading.value = true try { @@ -834,7 +827,6 @@ const generateAuthUrl = async () => { verificationUri.value = result.verificationUri verificationUriComplete.value = result.verificationUriComplete || result.verificationUri userCode.value = result.userCode - pollInterval.value = Number(result.interval || 5) || 5 startCountdown(result.expiresIn || 300) sessionId.value = result.sessionId } @@ -848,10 +840,6 @@ const generateAuthUrl = async () => { // 重新生成授权URL const regenerateAuthUrl = () => { stopCountdown() - if (pendingTimer) { - clearTimeout(pendingTimer) - pendingTimer = null - } authUrl.value = '' authCode.value = '' userCode.value = '' @@ -972,34 +960,17 @@ const exchangeCode = async () => { const response = await accountsStore.exchangeDroidCode(data) if (!response.success) { if (response.pending) { - const retrySeconds = Number(response.retryAfter || pollInterval.value || 5) const message = response.message || '授权尚未完成,请在浏览器确认后稍候再次尝试。' showToast(message, 'info') if (typeof response.expiresIn === 'number' && response.expiresIn >= 0) { startCountdown(response.expiresIn) } - // 等待建议的轮询间隔后自动重试 - if (Number.isFinite(retrySeconds) && retrySeconds > 0) { - if (pendingTimer) { - clearTimeout(pendingTimer) - } - pendingTimer = setTimeout(() => { - pendingTimer = null - if (!exchanging.value) { - exchangeCode() - } - }, retrySeconds * 1000) - } return } throw new Error(response.message || '授权失败,请重试') } tokenInfo = response.data stopCountdown() - if (pendingTimer) { - clearTimeout(pendingTimer) - pendingTimer = null - } } emit('success', tokenInfo) @@ -1012,9 +983,5 @@ const exchangeCode = async () => { onBeforeUnmount(() => { stopCountdown() - if (pendingTimer) { - clearTimeout(pendingTimer) - pendingTimer = null - } }) diff --git a/web/admin-spa/src/views/AccountsView.vue b/web/admin-spa/src/views/AccountsView.vue index 8993c359..1b03629f 100644 --- a/web/admin-spa/src/views/AccountsView.vue +++ b/web/admin-spa/src/views/AccountsView.vue @@ -1702,7 +1702,14 @@ const accountUsageSummary = ref({}) const accountUsageOverview = ref({}) const accountUsageGeneratedAt = ref('') -const supportedUsagePlatforms = ['claude', 'claude-console', 'openai', 'openai-responses', 'gemini'] +const supportedUsagePlatforms = [ + 'claude', + 'claude-console', + 'openai', + 'openai-responses', + 'gemini', + 'droid' +] // 缓存状态标志 const apiKeysLoaded = ref(false)