hxf/backend/th_agenter/api/endpoints/database_config.py

153 lines
5.9 KiB
Python
Raw Normal View History

2025-12-04 14:48:38 +08:00
"""数据库配置管理API"""
2025-12-16 13:55:16 +08:00
from loguru import logger
2025-12-04 14:48:38 +08:00
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from typing import List, Dict, Any
from pydantic import BaseModel, Field
from th_agenter.models.user import User
2025-12-16 13:55:16 +08:00
from th_agenter.db.database import get_session
2025-12-04 14:48:38 +08:00
from th_agenter.services.database_config_service import DatabaseConfigService
from th_agenter.services.auth import AuthService
2025-12-16 13:55:16 +08:00
from utils.util_schemas import FileListResponse,ExcelPreviewRequest,NormalResponse
2026-01-07 11:30:54 +08:00
from utils.util_exceptions import HxfResponse
2025-12-04 14:48:38 +08:00
# 在文件顶部添加
from functools import lru_cache
2025-12-16 13:55:16 +08:00
router = APIRouter(prefix="/api/database-config", tags=["database-config"])
2025-12-04 14:48:38 +08:00
# 创建服务单例
@lru_cache()
def get_database_config_service() -> DatabaseConfigService:
"""获取DatabaseConfigService单例"""
# 注意这里需要处理db session的问题
return DatabaseConfigService(None) # 临时方案
# 或者使用全局变量
_database_service_instance = None
2025-12-16 13:55:16 +08:00
def get_database_service(session: Session = Depends(get_session)) -> DatabaseConfigService:
2025-12-04 14:48:38 +08:00
"""获取DatabaseConfigService实例"""
global _database_service_instance
if _database_service_instance is None:
2025-12-16 13:55:16 +08:00
_database_service_instance = DatabaseConfigService(session)
2025-12-04 14:48:38 +08:00
else:
# 更新db session
2025-12-16 13:55:16 +08:00
_database_service_instance.db = session
2025-12-04 14:48:38 +08:00
return _database_service_instance
2025-12-16 13:55:16 +08:00
2025-12-04 14:48:38 +08:00
class DatabaseConfigCreate(BaseModel):
name: str = Field(..., description="配置名称")
db_type: str = Field(default="postgresql", description="数据库类型")
host: str = Field(..., description="主机地址")
port: int = Field(..., description="端口号")
database: str = Field(..., description="数据库名")
username: str = Field(..., description="用户名")
password: str = Field(..., description="密码")
is_default: bool = Field(default=False, description="是否为默认配置")
connection_params: Dict[str, Any] = Field(default=None, description="额外连接参数")
class DatabaseConfigResponse(BaseModel):
id: int
name: str
db_type: str
2025-12-16 13:55:16 +08:00
host: str
2025-12-04 14:48:38 +08:00
port: int
database: str
username: str
2025-12-16 13:55:16 +08:00
password: str
2025-12-04 14:48:38 +08:00
is_active: bool
is_default: bool
created_at: str
2025-12-16 13:55:16 +08:00
updated_at: str
2025-12-04 14:48:38 +08:00
2025-12-16 13:55:16 +08:00
@router.post("/", response_model=NormalResponse, summary="创建或更新数据库配置")
2025-12-04 14:48:38 +08:00
async def create_database_config(
config_data: DatabaseConfigCreate,
current_user: User = Depends(AuthService.get_current_user),
2025-12-16 13:55:16 +08:00
service: DatabaseConfigService = Depends(get_database_service)
2025-12-04 14:48:38 +08:00
):
"""创建或更新数据库配置"""
2025-12-16 13:55:16 +08:00
config = await service.create_or_update_config(current_user.id, config_data.model_dump())
2026-01-07 11:30:54 +08:00
response = NormalResponse(
2025-12-16 13:55:16 +08:00
success=True,
message="保存数据库配置成功",
data=config
2025-12-04 14:48:38 +08:00
)
2026-01-07 11:30:54 +08:00
return HxfResponse(response)
2025-12-04 14:48:38 +08:00
2025-12-16 13:55:16 +08:00
@router.get("/", response_model=List[DatabaseConfigResponse], summary="获取用户的数据库配置列表")
2025-12-04 14:48:38 +08:00
async def get_database_configs(
current_user: User = Depends(AuthService.get_current_user),
2025-12-16 13:55:16 +08:00
service: DatabaseConfigService = Depends(get_database_service)
2025-12-04 14:48:38 +08:00
):
"""获取用户的数据库配置列表"""
2025-12-16 13:55:16 +08:00
configs = service.get_user_configs(current_user.id)
2025-12-04 14:48:38 +08:00
2025-12-16 13:55:16 +08:00
config_list = [config.to_dict(include_password=True, decrypt_service=service) for config in configs]
2026-01-07 11:30:54 +08:00
return HxfResponse(config_list)
2025-12-04 14:48:38 +08:00
2025-12-16 13:55:16 +08:00
@router.post("/{config_id}/test", response_model=NormalResponse, summary="测试数据库连接")
2025-12-04 14:48:38 +08:00
async def test_database_connection(
config_id: int,
current_user: User = Depends(AuthService.get_current_user),
2025-12-16 13:55:16 +08:00
service: DatabaseConfigService = Depends(get_database_service)
2025-12-04 14:48:38 +08:00
):
"""测试数据库连接"""
2025-12-16 13:55:16 +08:00
result = await service.test_connection(config_id, current_user.id)
2026-01-07 11:30:54 +08:00
return HxfResponse(result)
2025-12-04 14:48:38 +08:00
2025-12-16 13:55:16 +08:00
@router.post("/{config_id}/connect", response_model=NormalResponse, summary="连接数据库并获取表列表")
2025-12-04 14:48:38 +08:00
async def connect_database(
config_id: int,
current_user: User = Depends(AuthService.get_current_user),
service: DatabaseConfigService = Depends(get_database_service)
):
"""连接数据库并获取表列表"""
2025-12-16 13:55:16 +08:00
result = await service.connect_and_get_tables(config_id, current_user.id)
2026-01-07 11:30:54 +08:00
return HxfResponse(result)
2025-12-04 14:48:38 +08:00
2025-12-16 13:55:16 +08:00
@router.get("/tables/{table_name}/data", summary="获取表数据预览")
2025-12-04 14:48:38 +08:00
async def get_table_data(
table_name: str,
db_type: str,
limit: int = 100,
current_user: User = Depends(AuthService.get_current_user),
service: DatabaseConfigService = Depends(get_database_service)
):
"""获取表数据预览"""
try:
result = await service.get_table_data(table_name, current_user.id, db_type, limit)
2026-01-07 11:30:54 +08:00
return HxfResponse(result)
2025-12-04 14:48:38 +08:00
except Exception as e:
logger.error(f"获取表数据失败: {str(e)}")
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=str(e)
)
2025-12-16 13:55:16 +08:00
@router.get("/tables/{table_name}/schema", summary="获取表结构信息")
2025-12-04 14:48:38 +08:00
async def get_table_schema(
table_name: str,
current_user: User = Depends(AuthService.get_current_user),
2025-12-16 13:55:16 +08:00
service: DatabaseConfigService = Depends(get_database_service)
2025-12-04 14:48:38 +08:00
):
"""获取表结构信息"""
2025-12-16 13:55:16 +08:00
result = await service.describe_table(table_name, current_user.id) # 这在哪里实现的?
2026-01-07 11:30:54 +08:00
return HxfResponse(result)
2025-12-04 14:48:38 +08:00
2025-12-16 13:55:16 +08:00
@router.get("/by-type/{db_type}", response_model=DatabaseConfigResponse, summary="根据数据库类型获取配置")
2025-12-04 14:48:38 +08:00
async def get_config_by_type(
db_type: str,
current_user: User = Depends(AuthService.get_current_user),
2025-12-16 13:55:16 +08:00
service: DatabaseConfigService = Depends(get_database_service)
2025-12-04 14:48:38 +08:00
):
"""根据数据库类型获取配置"""
2025-12-16 13:55:16 +08:00
config = service.get_config_by_type(current_user.id, db_type)
if not config:
2025-12-04 14:48:38 +08:00
raise HTTPException(
2025-12-16 13:55:16 +08:00
status_code=status.HTTP_404_NOT_FOUND,
detail=f"未找到类型为 {db_type} 的配置"
2025-12-04 14:48:38 +08:00
)
2025-12-16 13:55:16 +08:00
# 返回包含解密密码的配置
2026-01-07 11:30:54 +08:00
return HxfResponse(config.to_dict(include_password=True, decrypt_service=service))