diff --git a/app/core/application.py b/app/core/application.py
index da1bf6d..a36cc4c 100644
--- a/app/core/application.py
+++ b/app/core/application.py
@@ -11,6 +11,7 @@ from app.exception.exceptions import setup_exception_handlers
from app.router.routes import setup_routers
from app.service.key.key_manager import get_key_manager_instance
from app.database.connection import connect_to_db, disconnect_from_db
+from app.utils.helpers import get_current_version # Import from helpers
from app.database.initialization import initialize_database
from app.scheduler.key_checker import start_scheduler, stop_scheduler
from app.service.update.update_service import check_for_updates
@@ -20,28 +21,11 @@ logger = get_application_logger()
# Define project paths using pathlib
# Assuming this file is at app/core/application.py
PROJECT_ROOT = Path(__file__).resolve().parent.parent.parent
-VERSION_FILE_PATH = PROJECT_ROOT / "VERSION"
+# VERSION_FILE_PATH = PROJECT_ROOT / "VERSION" # Removed: Defined in helpers.py
STATIC_DIR = PROJECT_ROOT / "app" / "static"
TEMPLATES_DIR = PROJECT_ROOT / "app" / "templates"
-
-def _get_current_version(default_version: str = "0.0.0") -> str:
- """Reads the current version from the VERSION file."""
- version_file = VERSION_FILE_PATH # Use Path object
- try:
- # Use Path object's open method
- with version_file.open('r', encoding='utf-8') as f:
- version = f.read().strip()
- if not version:
- logger.warning(f"VERSION file ('{version_file}') is empty. Using default version '{default_version}'.")
- return default_version
- return version
- except FileNotFoundError:
- logger.warning(f"VERSION file not found at '{version_file}'. Using default version '{default_version}'.")
- return default_version
- except IOError as e:
- logger.error(f"Error reading VERSION file ('{version_file}'): {e}. Using default version '{default_version}'.")
- return default_version
+# Removed _get_current_version function definition, moved to helpers.py
# 初始化模板引擎,并添加全局变量
templates = Jinja2Templates(directory="app/templates")
@@ -88,7 +72,7 @@ def _stop_scheduler():
async def _perform_update_check(app: FastAPI):
"""Checks for updates and stores the info in app.state."""
update_available, latest_version, error_message = await check_for_updates()
- current_version = _get_current_version() # Read from VERSION file
+ current_version = get_current_version() # Use imported function
update_info = {
"update_available": update_available,
"latest_version": latest_version,
@@ -119,7 +103,7 @@ async def lifespan(app: FastAPI):
await _setup_database_and_config(settings) # Pass settings object
# Perform update check after core components are ready
- await _perform_update_check(app)
+ # await _perform_update_check(app) # Removed: Version check moved to frontend API call
# Start the scheduler
_start_scheduler()
@@ -148,7 +132,7 @@ def create_app() -> FastAPI:
# 创建FastAPI应用
# Read version from file for consistency
- current_version = _get_current_version()
+ current_version = get_current_version() # Use imported function
app = FastAPI(
title="Gemini Balance API",
description="Gemini API代理服务,支持负载均衡和密钥管理",
diff --git a/app/router/routes.py b/app/router/routes.py
index 7693ad0..5cf23ff 100644
--- a/app/router/routes.py
+++ b/app/router/routes.py
@@ -8,7 +8,7 @@ from fastapi.templating import Jinja2Templates
from app.core.security import verify_auth_token
from app.log.logger import get_routes_logger
-from app.router import error_log_routes, gemini_routes, openai_routes, config_routes, scheduler_routes, stats_routes # 新增导入 stats_routes
+from app.router import error_log_routes, gemini_routes, openai_routes, config_routes, scheduler_routes, stats_routes, version_routes # 新增导入 version_routes
from app.service.key.key_manager import get_key_manager_instance
from app.service.stats_service import StatsService
@@ -33,6 +33,7 @@ def setup_routers(app: FastAPI) -> None:
app.include_router(error_log_routes.router)
app.include_router(scheduler_routes.router) # 新增包含 scheduler 路由
app.include_router(stats_routes.router) # 包含 stats API 路由
+ app.include_router(version_routes.router) # 包含 version API 路由
# 添加页面路由
setup_page_routes(app)
diff --git a/app/router/version_routes.py b/app/router/version_routes.py
new file mode 100644
index 0000000..8f7b27a
--- /dev/null
+++ b/app/router/version_routes.py
@@ -0,0 +1,38 @@
+from fastapi import APIRouter, HTTPException
+from pydantic import BaseModel, Field
+from typing import Optional
+
+from app.service.update.update_service import check_for_updates
+from app.utils.helpers import get_current_version
+from app.log.logger import get_update_logger
+
+router = APIRouter(prefix="/api/version", tags=["Version"])
+logger = get_update_logger()
+
+class VersionInfo(BaseModel):
+ current_version: str = Field(..., description="当前应用程序版本")
+ latest_version: Optional[str] = Field(None, description="可用的最新版本")
+ update_available: bool = Field(False, description="是否有可用更新")
+ error_message: Optional[str] = Field(None, description="检查更新时发生的错误信息")
+
+@router.get("/check", response_model=VersionInfo, summary="检查应用程序更新")
+async def get_version_info():
+ """
+ 检查当前应用程序版本与最新的 GitHub release 版本。
+ """
+ try:
+ current_version = get_current_version() # Use imported function
+ update_available, latest_version, error_message = await check_for_updates()
+
+ # Log the result for debugging
+ logger.info(f"Version check API result: current={current_version}, latest={latest_version}, available={update_available}, error='{error_message}'")
+
+ return VersionInfo(
+ current_version=current_version,
+ latest_version=latest_version,
+ update_available=update_available,
+ error_message=error_message
+ )
+ except Exception as e:
+ logger.error(f"Error in /api/version/check endpoint: {e}", exc_info=True)
+ raise HTTPException(status_code=500, detail="检查版本信息时发生内部错误")
\ No newline at end of file
diff --git a/app/templates/base.html b/app/templates/base.html
index 11d95bd..55e4d57 100644
--- a/app/templates/base.html
+++ b/app/templates/base.html
@@ -202,20 +202,9 @@
免费项目,谨防诈骗
- {% if request and request.app.state.update_info %}
- {% set update_info = request.app.state.update_info %}
- |
- v{{ update_info.current_version }}
- {% if update_info.update_available %}
- |
-
- 新版本: v{{ update_info.latest_version }}
-
- {% elif update_info.error_message and update_info.error_message != 'Checking...' %}
- |
- 更新检查失败
- {% endif %}
- {% endif %}
+
+
+
@@ -279,6 +268,48 @@
}, 300); // Short delay to show spinner
}
+ // --- Version Check ---
+ const versionInfoContainer = document.getElementById('version-info-container');
+
+ async function fetchVersionInfo() {
+ if (!versionInfoContainer) return;
+ versionInfoContainer.innerHTML = '|检查更新中...'; // Initial loading state
+
+ try {
+ const response = await fetch('/api/version/check');
+ if (!response.ok) {
+ throw new Error(`HTTP error! status: ${response.status}`);
+ }
+ const data = await response.json();
+
+ let versionHtml = `|v${data.current_version}`;
+ if (data.update_available) {
+ versionHtml += `
+ |
+
+ 新版本: v${data.latest_version}
+ `;
+ } else if (data.error_message) {
+ versionHtml += `
+ |
+ 更新检查失败`;
+ } else {
+ versionHtml += `|已是最新`; // Indicate up-to-date
+ }
+ versionInfoContainer.innerHTML = versionHtml;
+
+ } catch (error) {
+ console.error('Error fetching version info:', error);
+ versionInfoContainer.innerHTML = `|更新检查失败`;
+ }
+ }
+
+ // Fetch immediately on load
+ fetchVersionInfo();
+
+ // Fetch periodically (e.g., every hour)
+ setInterval(fetchVersionInfo, 3600000); // 3600000 ms = 1 hour
+
{% block body_scripts %}{% endblock %}