|
|
"""
|
|
|
配置管理路由
|
|
|
"""
|
|
|
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": []}
|
|
|
)
|