mirror of
https://github.com/snailyp/gemini-balance.git
synced 2026-08-25 02:00:36 +08:00
feat: 添加密钥检查调度器并重构前端UI
主要变更:
- **调度器功能:**
- 集成 APScheduler 实现定时任务,用于定期检查API密钥的有效性。
- 在 `.env.example` 和 `app/config/config.py` 中添加了 `CHECK_INTERVAL_HOURS` 和 `TIMEZONE` 配置项。
- 在应用生命周期 (`app/core/application.py`) 中添加了调度器的启动和停止逻辑。
- 新增 `app/scheduler/` 目录及相关实现 (`key_checker.py`)。
- 新增 `app/router/scheduler_routes.py` 用于调度器相关API (如果未来需要)。
- 在 `requirements.txt` 中添加 `apscheduler` 依赖。
- **前端重构与改进:**
- 引入 `app/templates/base.html` 作为基础模板,统一页面结构和样式引入。
- 使用新的样式(推测为Tailwind CSS)重构了 `auth.html`, `config_editor.html`, `error_logs.html`, `keys_status.html` 页面,提升了UI一致性和响应式布局。
- 删除了旧的CSS文件 (`auth.css`, `config_editor.css`, `error_logs.css`, `keys_status.css`)。
- 更新了对应的 JavaScript 文件 (`config_editor.js`, `error_logs.js`, `keys_status.js`) 以适应新的HTML结构和交互。
- 在 `keys_status.html` 页面增加了按失败次数过滤密钥、批量重置失败次数、确认模态框等功能。
- 添加了新的 Logo 图片 (`logo.png`, `logo1.png`)。
- **其他:**
- 更新了 `app/router/routes.py` 以包含新的路由。
- 对 `app/service/key/key_manager.py` 和 `app/database/services.py` 进行了相关调整以支持新功能。
```
72 lines
2.6 KiB
Python
72 lines
2.6 KiB
Python
"""
|
|
日志路由模块
|
|
"""
|
|
from typing import Any, Dict, List, Optional
|
|
from datetime import datetime
|
|
from pydantic import BaseModel
|
|
from fastapi import APIRouter, HTTPException, Request, Query
|
|
from fastapi.responses import RedirectResponse
|
|
|
|
from app.core.security import verify_auth_token
|
|
from app.log.logger import get_log_routes_logger
|
|
from app.database.services import get_error_logs, get_error_logs_count
|
|
|
|
# 创建路由
|
|
router = APIRouter(prefix="/api/logs", tags=["logs"])
|
|
|
|
logger = get_log_routes_logger()
|
|
|
|
|
|
# Define a response model that includes the total count for pagination
|
|
class ErrorLogResponse(BaseModel):
|
|
logs: List[Dict[str, Any]]
|
|
total: int
|
|
|
|
@router.get("/errors", response_model=ErrorLogResponse)
|
|
async def get_error_logs_api(
|
|
request: Request,
|
|
limit: int = Query(20, ge=1, le=1000), # Default to 20 to match frontend
|
|
offset: int = Query(0, ge=0),
|
|
key_search: Optional[str] = Query(None, description="Search term for Gemini key (partial match)"),
|
|
error_search: Optional[str] = Query(None, description="Search term for error type or log message"),
|
|
start_date: Optional[datetime] = Query(None, description="Start datetime for filtering (YYYY-MM-DDTHH:MM)"),
|
|
end_date: Optional[datetime] = Query(None, description="End datetime for filtering (YYYY-MM-DDTHH:MM)")
|
|
):
|
|
"""
|
|
获取错误日志
|
|
|
|
Args:
|
|
request: 请求对象
|
|
limit: 限制数量
|
|
offset: 偏移量
|
|
|
|
Returns:
|
|
ErrorLogResponse: An object containing the list of logs and the total count.
|
|
"""
|
|
auth_token = request.cookies.get("auth_token")
|
|
if not auth_token or not verify_auth_token(auth_token):
|
|
logger.warning("Unauthorized access attempt to error logs")
|
|
return RedirectResponse(url="/", status_code=302)
|
|
|
|
try:
|
|
# Fetch logs with search parameters
|
|
logs = await get_error_logs(
|
|
limit=limit,
|
|
offset=offset,
|
|
key_search=key_search,
|
|
error_search=error_search,
|
|
start_date=start_date,
|
|
end_date=end_date
|
|
)
|
|
# Fetch total count with the same search parameters
|
|
total_count = await get_error_logs_count(
|
|
key_search=key_search,
|
|
error_search=error_search,
|
|
start_date=start_date,
|
|
end_date=end_date
|
|
)
|
|
return ErrorLogResponse(logs=logs, total=total_count)
|
|
except Exception as e:
|
|
logger.exception(f"Failed to get error logs: {str(e)}") # Use logger.exception for stack trace
|
|
raise HTTPException(status_code=500, detail=f"Failed to get error logs: {str(e)}")
|