first commit
This commit is contained in:
240
backend/app/routes/history.py
Normal file
240
backend/app/routes/history.py
Normal file
@@ -0,0 +1,240 @@
|
||||
"""历史记录管理路由,提供调用历史查询、统计和导出功能"""
|
||||
|
||||
from fastapi import APIRouter, HTTPException, status, Depends
|
||||
from typing import List, Dict, Any, Optional
|
||||
from datetime import datetime
|
||||
import json
|
||||
|
||||
from app.services.history_manager import history_manager
|
||||
from app.models.database import get_db
|
||||
from app.routes.user import get_current_active_user
|
||||
|
||||
router = APIRouter(prefix="/history", tags=["history"])
|
||||
|
||||
|
||||
@router.get("/user-calls")
|
||||
async def get_user_call_history(
|
||||
algorithm_id: Optional[str] = None,
|
||||
start_date: Optional[str] = None,
|
||||
end_date: Optional[str] = None,
|
||||
status: Optional[str] = None,
|
||||
skip: int = 0,
|
||||
limit: int = 100,
|
||||
current_user: dict = Depends(get_current_active_user),
|
||||
db = Depends(get_db)
|
||||
):
|
||||
"""获取用户的调用历史"""
|
||||
# 解析日期参数
|
||||
start_dt = None
|
||||
end_dt = None
|
||||
if start_date:
|
||||
try:
|
||||
start_dt = datetime.fromisoformat(start_date.replace('Z', '+00:00'))
|
||||
except ValueError:
|
||||
raise HTTPException(status_code=400, detail="Invalid start_date format")
|
||||
|
||||
if end_date:
|
||||
try:
|
||||
end_dt = datetime.fromisoformat(end_date.replace('Z', '+00:00'))
|
||||
except ValueError:
|
||||
raise HTTPException(status_code=400, detail="Invalid end_date format")
|
||||
|
||||
# 普通用户只能查看自己的历史,管理员可以查看所有用户历史
|
||||
user_id = current_user.get("id")
|
||||
if current_user.get("role") == "admin":
|
||||
# 管理员可以指定用户ID,否则查看所有用户
|
||||
user_id = None # 这样会返回所有用户的记录
|
||||
|
||||
history = history_manager.get_user_call_history(
|
||||
db=db,
|
||||
user_id=user_id or current_user.get("id"),
|
||||
algorithm_id=algorithm_id,
|
||||
start_date=start_dt,
|
||||
end_date=end_dt,
|
||||
status=status,
|
||||
skip=skip,
|
||||
limit=limit
|
||||
)
|
||||
|
||||
return {
|
||||
"history": [call.__dict__ for call in history],
|
||||
"count": len(history),
|
||||
"skip": skip,
|
||||
"limit": limit
|
||||
}
|
||||
|
||||
|
||||
@router.get("/algorithm-calls/{algorithm_id}")
|
||||
async def get_algorithm_call_history(
|
||||
algorithm_id: str,
|
||||
user_id: Optional[str] = None,
|
||||
start_date: Optional[str] = None,
|
||||
end_date: Optional[str] = None,
|
||||
status: Optional[str] = None,
|
||||
skip: int = 0,
|
||||
limit: int = 100,
|
||||
current_user: dict = Depends(get_current_active_user),
|
||||
db = Depends(get_db)
|
||||
):
|
||||
"""获取特定算法的调用历史"""
|
||||
# 验证权限:用户必须有权访问该算法
|
||||
# 在实际实现中,这里应该检查用户是否有权访问该算法
|
||||
# 为简化,我们只检查是否为管理员或查看自己的记录
|
||||
|
||||
# 解析日期参数
|
||||
start_dt = None
|
||||
end_dt = None
|
||||
if start_date:
|
||||
try:
|
||||
start_dt = datetime.fromisoformat(start_date.replace('Z', '+00:00'))
|
||||
except ValueError:
|
||||
raise HTTPException(status_code=400, detail="Invalid start_date format")
|
||||
|
||||
if end_date:
|
||||
try:
|
||||
end_dt = datetime.fromisoformat(end_date.replace('Z', '+00:00'))
|
||||
except ValueError:
|
||||
raise HTTPException(status_code=400, detail="Invalid end_date format")
|
||||
|
||||
history = history_manager.get_algorithm_call_history(
|
||||
db=db,
|
||||
algorithm_id=algorithm_id,
|
||||
user_id=user_id,
|
||||
start_date=start_dt,
|
||||
end_date=end_dt,
|
||||
status=status,
|
||||
skip=skip,
|
||||
limit=limit
|
||||
)
|
||||
|
||||
return {
|
||||
"history": [call.__dict__ for call in history],
|
||||
"count": len(history),
|
||||
"skip": skip,
|
||||
"limit": limit
|
||||
}
|
||||
|
||||
|
||||
@router.get("/statistics")
|
||||
async def get_call_statistics(
|
||||
user_id: Optional[str] = None,
|
||||
algorithm_id: Optional[str] = None,
|
||||
current_user: dict = Depends(get_current_active_user),
|
||||
db = Depends(get_db)
|
||||
):
|
||||
"""获取调用统计信息"""
|
||||
# 权限检查
|
||||
if current_user.get("role") != "admin":
|
||||
# 普通用户只能查看自己的统计
|
||||
if user_id and user_id != current_user.get("id"):
|
||||
raise HTTPException(status_code=403, detail="Insufficient permissions")
|
||||
user_id = current_user.get("id")
|
||||
|
||||
stats = history_manager.get_call_statistics(
|
||||
db=db,
|
||||
user_id=user_id,
|
||||
algorithm_id=algorithm_id
|
||||
)
|
||||
|
||||
return stats
|
||||
|
||||
|
||||
@router.post("/compare")
|
||||
async def get_comparison_data(
|
||||
call_ids: List[str],
|
||||
current_user: dict = Depends(get_current_active_user),
|
||||
db = Depends(get_db)
|
||||
):
|
||||
"""获取用于对比的历史数据"""
|
||||
# 权限检查:用户只能对比自己的调用记录
|
||||
# 获取调用记录
|
||||
calls = db.query(AlgorithmCall).filter(AlgorithmCall.id.in_(call_ids)).all()
|
||||
|
||||
# 检查权限:用户只能对比自己的记录
|
||||
for call in calls:
|
||||
if call.user_id != current_user.get("id") and current_user.get("role") != "admin":
|
||||
raise HTTPException(status_code=403, detail="Insufficient permissions to access call data")
|
||||
|
||||
comparison_data = history_manager.get_comparison_data(db, call_ids)
|
||||
|
||||
return {
|
||||
"comparison_data": comparison_data,
|
||||
"count": len(comparison_data)
|
||||
}
|
||||
|
||||
|
||||
@router.get("/export")
|
||||
async def export_history(
|
||||
algorithm_id: Optional[str] = None,
|
||||
start_date: Optional[str] = None,
|
||||
end_date: Optional[str] = None,
|
||||
format_type: str = "json",
|
||||
current_user: dict = Depends(get_current_active_user),
|
||||
db = Depends(get_db)
|
||||
):
|
||||
"""导出历史记录"""
|
||||
# 解析日期参数
|
||||
start_dt = None
|
||||
end_dt = None
|
||||
if start_date:
|
||||
try:
|
||||
start_dt = datetime.fromisoformat(start_date.replace('Z', '+00:00'))
|
||||
except ValueError:
|
||||
raise HTTPException(status_code=400, detail="Invalid start_date format")
|
||||
|
||||
if end_date:
|
||||
try:
|
||||
end_dt = datetime.fromisoformat(end_date.replace('Z', '+00:00'))
|
||||
except ValueError:
|
||||
raise HTTPException(status_code=400, detail="Invalid end_date format")
|
||||
|
||||
file_path = history_manager.export_history(
|
||||
db=db,
|
||||
user_id=current_user.get("id"),
|
||||
algorithm_id=algorithm_id,
|
||||
start_date=start_dt,
|
||||
end_date=end_dt,
|
||||
format_type=format_type
|
||||
)
|
||||
|
||||
if file_path:
|
||||
return {
|
||||
"success": True,
|
||||
"file_path": file_path,
|
||||
"download_url": f"/api/files/download/{file_path}",
|
||||
"message": "History exported successfully"
|
||||
}
|
||||
else:
|
||||
raise HTTPException(status_code=500, detail="Failed to export history")
|
||||
|
||||
|
||||
@router.delete("/cleanup")
|
||||
async def cleanup_old_history(
|
||||
days_old: int,
|
||||
algorithm_id: Optional[str] = None,
|
||||
current_user: dict = Depends(get_current_active_user),
|
||||
db = Depends(get_db)
|
||||
):
|
||||
"""清理旧的历史记录"""
|
||||
# 只有管理员可以清理历史记录
|
||||
if current_user.get("role") != "admin":
|
||||
raise HTTPException(status_code=403, detail="Only administrators can clean up history")
|
||||
|
||||
# 确保天数为正数
|
||||
if days_old <= 0:
|
||||
raise HTTPException(status_code=400, detail="days_old must be positive")
|
||||
|
||||
deleted_count = history_manager.delete_old_history(
|
||||
db=db,
|
||||
days_old=days_old,
|
||||
algorithm_id=algorithm_id
|
||||
)
|
||||
|
||||
return {
|
||||
"message": f"Cleaned up {deleted_count} old history records",
|
||||
"deleted_count": deleted_count
|
||||
}
|
||||
|
||||
|
||||
# 导入需要的模型
|
||||
from app.models.models import AlgorithmCall
|
||||
Reference in New Issue
Block a user