You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

296 lines
9.1 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

"""
配置管理路由
"""
from typing import List
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from app.db.session import get_db
from app.schemas.config import SDKConfigCreate, SDKConfigUpdate, SDKConfigResponse, SDKConfigTestResponse
from app.schemas.base import ResponseModel, PaginatedResponse, PaginatedData
from app.services.config_service import ConfigService
from app.services.amazing_data_adapter import AmazingDataAdapter
from app.services.sdk_manager import sdk_manager
from app.core.security import get_current_user
from app.models.user import User
router = APIRouter()
@router.get("/sdk", response_model=ResponseModel[List[SDKConfigResponse]])
async def get_sdk_configs(
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""获取SDK配置列表"""
configs = ConfigService.get_sdk_configs(db)
return ResponseModel(data=[SDKConfigResponse.model_validate(c) for c in configs])
@router.get("/sdk/{config_id}", response_model=ResponseModel[SDKConfigResponse])
async def get_sdk_config(
config_id: int,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""获取指定SDK配置"""
config = ConfigService.get_sdk_config(db, config_id)
if not config:
raise HTTPException(status_code=404, detail="配置不存在")
return ResponseModel(data=SDKConfigResponse.model_validate(config))
@router.post("/sdk", response_model=ResponseModel[SDKConfigResponse])
async def create_sdk_config(
config_data: SDKConfigCreate,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""创建SDK配置"""
config_dict = config_data.model_dump()
config = ConfigService.create_sdk_config(db, config_dict)
return ResponseModel(data=SDKConfigResponse.model_validate(config))
@router.put("/sdk/{config_id}", response_model=ResponseModel[SDKConfigResponse])
async def update_sdk_config(
config_id: int,
config_data: SDKConfigUpdate,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""更新SDK配置"""
config_dict = config_data.model_dump(exclude_unset=True)
config = ConfigService.update_sdk_config(db, config_id, config_dict)
return ResponseModel(data=SDKConfigResponse.model_validate(config))
@router.delete("/sdk/{config_id}", response_model=ResponseModel)
async def delete_sdk_config(
config_id: int,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""删除SDK配置"""
ConfigService.delete_sdk_config(db, config_id)
return ResponseModel(message="删除成功")
@router.post("/sdk/{config_id}/test", response_model=ResponseModel[SDKConfigTestResponse])
async def test_sdk_config(
config_id: int,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""测试SDK连接连接成功后会保持登录状态"""
import asyncio
config = ConfigService.get_sdk_config(db, config_id)
if not config:
raise HTTPException(status_code=404, detail="配置不存在")
def _test_connection():
adapter = sdk_manager.get_connection(config_id)
if adapter:
return True
return False
success = await asyncio.to_thread(_test_connection)
if success:
return ResponseModel(data=SDKConfigTestResponse(success=True, message="连接成功(已保持登录状态)"))
else:
return ResponseModel(
code=1001,
message="连接失败",
data=SDKConfigTestResponse(success=False, message="SDK连接失败请检查配置")
)
@router.post("/sdk/{config_id}/release", response_model=ResponseModel)
async def release_sdk_connection(
config_id: int,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""释放SDK连接登出释放资源"""
import asyncio
config = ConfigService.get_sdk_config(db, config_id)
if not config:
raise HTTPException(status_code=404, detail="配置不存在")
def _release():
sdk_manager.release_connection(config_id)
await asyncio.to_thread(_release)
return ResponseModel(message="SDK连接已释放")
@router.get("/sdk/{config_id}/status", response_model=ResponseModel)
async def get_sdk_connection_status(
config_id: int,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""获取SDK连接状态"""
config = ConfigService.get_sdk_config(db, config_id)
if not config:
raise HTTPException(status_code=404, detail="配置不存在")
status_info = sdk_manager.get_status(config_id)
return ResponseModel(data={
"connected": status_info["connected"],
"last_activity": status_info["last_activity"],
"config_id": status_info["config_id"]
})
@router.post("/sdk/{config_id}/set-default", response_model=ResponseModel)
async def set_default_config(
config_id: int,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""设为默认配置"""
ConfigService.set_default_config(db, config_id)
return ResponseModel(message="设置成功")
@router.get("/system", response_model=ResponseModel[dict])
async def get_system_configs(
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""获取系统配置数据库、Redis等"""
configs = {
"database": ConfigService.get_system_config(db, "DATABASE_URL") or "sqlite:///./amazing_data.db",
"redis": ConfigService.get_system_config(db, "REDIS_URL") or "redis://localhost:6379/0"
}
return ResponseModel(data=configs)
@router.put("/system", response_model=ResponseModel)
async def update_system_configs(
configs: dict,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user)
):
"""更新系统配置"""
if "database" in configs:
ConfigService.set_system_config(
db,
"DATABASE_URL",
configs["database"],
"数据库连接URL"
)
if "redis" in configs:
ConfigService.set_system_config(
db,
"REDIS_URL",
configs["redis"],
"Redis连接URL"
)
return ResponseModel(message="更新成功")
@router.post("/system/test", response_model=ResponseModel[dict])
async def test_system_connection(
configs: dict,
current_user: User = Depends(get_current_user)
):
"""测试系统连接数据库和Redis"""
import sqlalchemy
import redis
result = {
"database": False,
"redis": False
}
# 测试数据库连接
if "database" in configs:
try:
engine = sqlalchemy.create_engine(
configs["database"],
connect_args={"check_same_thread": False} if "sqlite" in configs["database"] else {}
)
with engine.connect() as conn:
result["database"] = True
except Exception as e:
pass
# 测试Redis连接
if "redis" in configs:
try:
redis_client = redis.from_url(configs["redis"])
redis_client.ping()
result["redis"] = True
except Exception as e:
pass
return ResponseModel(data=result)
@router.post("/system/init", response_model=ResponseModel[dict])
async def init_system_database(
current_user: User = Depends(get_current_user)
):
"""初始化数据库结构"""
try:
from app.db.session import init_db
init_db()
return ResponseModel(data={"success": True})
except Exception as e:
return ResponseModel(
code=1001,
message=str(e),
data={"success": False}
)
@router.get("/system/structure", response_model=ResponseModel[dict])
async def check_database_structure(
current_user: User = Depends(get_current_user)
):
"""检测数据库结构是否完整"""
try:
from sqlalchemy import inspect
from app.db.session import engine
inspector = inspect(engine)
existing_tables = inspector.get_table_names()
# 检查必要的表是否存在
required_tables = [
'users',
'sdk_configs',
'system_configs',
'stock_kline_daily',
'stock_kline_minute',
'future_kline_daily',
'future_kline_minute',
'cache_tasks',
'stock_basic',
'index_basic',
'index_trade'
]
missing_tables = [table for table in required_tables if table not in existing_tables]
complete = len(missing_tables) == 0
return ResponseModel(data={
"complete": complete,
"missing_tables": missing_tables,
"existing_tables": existing_tables
})
except Exception as e:
return ResponseModel(
code=1001,
message=str(e),
data={"complete": False, "missing_tables": [], "existing_tables": []}
)