From d566c28fa2b40a2c13cefa8280264ff1d8fd1208 Mon Sep 17 00:00:00 2001 From: yinpeng <2291314224@qq.com> Date: Sat, 15 Feb 2025 01:00:47 +0800 Subject: [PATCH] =?UTF-8?q?feat(gemini):=20=E6=B7=BB=E5=8A=A0=20API=20?= =?UTF-8?q?=E5=AF=86=E9=92=A5=E9=AA=8C=E8=AF=81=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 gemini_routes.py 中添加 verify_key 路由,用于验证 API 密钥的有效性 - 在 keys_status 页面中添加验证按钮和相关逻辑 - 优化 keys_status 页面的样式,增加密钥验证相关 CSS 类 - 在 config.py 中添加 TEST_MODEL 设置,用于密钥验证测试 --- app/api/gemini_routes.py | 31 +++++++++++++++++++++-- app/core/config.py | 1 + app/static/css/keys_status.css | 46 +++++++++++++++++++++++++++++++--- app/static/js/keys_status.js | 42 ++++++++++++++++++++++++++++++- app/templates/keys_status.html | 28 +++++++++++++++------ 5 files changed, 133 insertions(+), 15 deletions(-) diff --git a/app/api/gemini_routes.py b/app/api/gemini_routes.py index 80f1903..a50889a 100644 --- a/app/api/gemini_routes.py +++ b/app/api/gemini_routes.py @@ -1,10 +1,10 @@ from fastapi import APIRouter, Depends, HTTPException -from fastapi.responses import StreamingResponse +from fastapi.responses import StreamingResponse, JSONResponse from app.core.config import settings from app.core.logger import get_gemini_logger from app.core.security import SecurityService -from app.schemas.gemini_models import GeminiRequest +from app.schemas.gemini_models import GeminiContent, GeminiRequest from app.services.gemini_chat_service import GeminiChatService from app.services.key_manager import KeyManager, get_key_manager_instance from app.services.model_service import ModelService @@ -102,3 +102,30 @@ async def stream_generate_content( except Exception as e: logger.error(f"Streaming request failed: {str(e)}") + + +@router.post("/verify-key/{api_key}") +async def verify_key(api_key: str): + key_manager = await get_key_manager() + chat_service = GeminiChatService(settings.BASE_URL, key_manager) + """验证Gemini API密钥的有效性""" + logger.info("-" * 50 + "verify_gemini_key" + "-" * 50) + logger.info("Verifying API key validity") + + try: + # 使用generate_content接口测试key的有效性 + gemini_requset = GeminiRequest( + contents=[ + GeminiContent( + role="user", + parts=[{"text": "hi"}] + ) + ] + ) + response = chat_service.generate_content(settings.TEST_MODEL,gemini_requset, api_key) + if response: + return JSONResponse({"status": "valid"}) + return JSONResponse({"status": "invalid"}) + except Exception as e: + logger.error(f"Key verification failed: {str(e)}") + return JSONResponse({"status": "invalid", "error": str(e)}) diff --git a/app/core/config.py b/app/core/config.py index f7566bb..7b9ac09 100644 --- a/app/core/config.py +++ b/app/core/config.py @@ -16,6 +16,7 @@ class Settings(BaseSettings): CREATE_IMAGE_MODEL: str = "imagen-3.0-generate-002" UPLOAD_PROVIDER: str = "smms" SMMS_SECRET_TOKEN: str = "" + TEST_MODEL: str = "gemini-1.5-flash" def __init__(self): super().__init__() diff --git a/app/static/css/keys_status.css b/app/static/css/keys_status.css index 093b56d..e943cbc 100644 --- a/app/static/css/keys_status.css +++ b/app/static/css/keys_status.css @@ -154,7 +154,13 @@ li:hover { font-size: 12px; } -.copy-btn { +.key-actions { + display: flex; + gap: 10px; + align-items: center; +} + +.verify-btn, .copy-btn { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border: none; @@ -169,6 +175,26 @@ li:hover { gap: 5px; } +.verify-btn { + background: linear-gradient(135deg, #2ecc71, #27ae60); +} + +.verify-btn:hover { + transform: translateY(-2px); + box-shadow: 0 5px 15px rgba(46, 204, 113, 0.3); +} + +.verify-btn:disabled { + opacity: 0.7; + cursor: not-allowed; + transform: none; + box-shadow: none; +} + +.verify-btn i { + font-size: 14px; +} + .copy-btn:hover { transform: translateY(-2px); box-shadow: 0 5px 15px rgba(118, 75, 162, 0.3); @@ -199,8 +225,6 @@ li:hover { top: 50%; left: 50%; transform: translate(-50%, -50%); - background: rgba(39, 174, 96, 0.95); - color: white; padding: 15px 30px; border-radius: 25px; font-weight: bold; @@ -211,6 +235,15 @@ li:hover { z-index: 1000; text-align: center; min-width: 200px; + color: white; +} + +#copyStatus.success { + background: rgba(39, 174, 96, 0.95); +} + +#copyStatus.error { + background: rgba(231, 76, 60, 0.95); } .status-badge { @@ -375,7 +408,12 @@ li:hover { flex-direction: column; gap: 10px; } - .copy-btn { + .key-actions { + width: 100%; + flex-direction: column; + } + + .verify-btn, .copy-btn { width: 100%; justify-content: center; } diff --git a/app/static/js/keys_status.js b/app/static/js/keys_status.js index 1ab80e9..c9bc849 100644 --- a/app/static/js/keys_status.js +++ b/app/static/js/keys_status.js @@ -50,15 +50,55 @@ function copyKey(key) { }); } -function showCopyStatus(message) { +function showCopyStatus(message, type = 'success') { const statusElement = document.getElementById('copyStatus'); statusElement.textContent = message; + statusElement.className = type; // 设置样式类 statusElement.style.opacity = 1; setTimeout(() => { statusElement.style.opacity = 0; + setTimeout(() => { + statusElement.className = ''; // 清除样式类 + }, 300); }, 2000); } +async function verifyKey(key, button) { + try { + // 禁用按钮并显示加载状态 + button.disabled = true; + const originalHtml = button.innerHTML; + button.innerHTML = ' 验证中'; + + const response = await fetch(`/gemini/v1beta/verify-key/${key}`, { + method: 'POST' + }); + const data = await response.json(); + + // 根据验证结果更新UI + if (data.status === 'valid') { + showCopyStatus('密钥验证成功', 'success'); + button.style.backgroundColor = '#27ae60'; + } else { + showCopyStatus('密钥验证失败', 'error'); + button.style.backgroundColor = '#e74c3c'; + } + + // 3秒后恢复按钮原始状态 + setTimeout(() => { + button.innerHTML = originalHtml; + button.disabled = false; + button.style.backgroundColor = ''; + }, 3000); + + } catch (error) { + console.error('验证失败:', error); + showCopyStatus('验证请求失败', 'error'); + button.disabled = false; + button.innerHTML = ' 验证'; + } +} + function scrollToTop() { const container = document.querySelector('.container'); container.scrollTo({ diff --git a/app/templates/keys_status.html b/app/templates/keys_status.html index da69302..d81a9e5 100644 --- a/app/templates/keys_status.html +++ b/app/templates/keys_status.html @@ -46,10 +46,16 @@ 失败: {{ fail_count }} - +