a
This commit is contained in:
parent
42a6f2c1f3
commit
65ca1d3d03
|
|
@ -97,13 +97,18 @@ app = FastAPI(
|
||||||
)
|
)
|
||||||
|
|
||||||
# CORS配置(允许React前端访问)
|
# CORS配置(允许React前端访问)
|
||||||
cors_origins = os.getenv('CORS_ORIGINS', 'http://localhost:3000,http://localhost:5173,http://as.deepx1.com').split(',')
|
cors_origins_str = os.getenv('CORS_ORIGINS', 'http://localhost:3000,http://localhost:5173,http://as.deepx1.com,http://asapi.deepx1.com')
|
||||||
|
cors_origins = [origin.strip() for origin in cors_origins_str.split(',') if origin.strip()]
|
||||||
|
|
||||||
|
logger.info(f"CORS允许的源: {cors_origins}")
|
||||||
|
|
||||||
app.add_middleware(
|
app.add_middleware(
|
||||||
CORSMiddleware,
|
CORSMiddleware,
|
||||||
allow_origins=cors_origins,
|
allow_origins=cors_origins,
|
||||||
allow_credentials=True,
|
allow_credentials=True,
|
||||||
allow_methods=["*"],
|
allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"],
|
||||||
allow_headers=["*"],
|
allow_headers=["*"],
|
||||||
|
expose_headers=["*"],
|
||||||
)
|
)
|
||||||
|
|
||||||
# 注册路由
|
# 注册路由
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,27 @@
|
||||||
const API_BASE_URL = import.meta.env.VITE_API_URL || 'http://localhost:8000';
|
// 如果设置了VITE_API_URL环境变量,使用它;否则在开发环境使用相对路径(通过vite代理),生产环境使用默认值
|
||||||
|
const API_BASE_URL = import.meta.env.VITE_API_URL || (import.meta.env.DEV ? '' : 'http://localhost:8000');
|
||||||
|
|
||||||
|
// 构建API URL的辅助函数,避免双斜杠和格式问题
|
||||||
|
const buildUrl = (path) => {
|
||||||
|
const baseUrl = API_BASE_URL.endsWith('/') ? API_BASE_URL.slice(0, -1) : API_BASE_URL;
|
||||||
|
const cleanPath = path.startsWith('/') ? path : `/${path}`;
|
||||||
|
return baseUrl ? `${baseUrl}${cleanPath}` : cleanPath;
|
||||||
|
};
|
||||||
|
|
||||||
export const api = {
|
export const api = {
|
||||||
// 配置管理
|
// 配置管理
|
||||||
getConfigs: async () => {
|
getConfigs: async () => {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/config/`);
|
const response = await fetch(buildUrl('/api/config/'));
|
||||||
return response.json();
|
return response.json();
|
||||||
},
|
},
|
||||||
|
|
||||||
getConfig: async (key) => {
|
getConfig: async (key) => {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/config/${key}`);
|
const response = await fetch(buildUrl(`/api/config/${key}`));
|
||||||
return response.json();
|
return response.json();
|
||||||
},
|
},
|
||||||
|
|
||||||
updateConfig: async (key, data) => {
|
updateConfig: async (key, data) => {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/config/${key}`, {
|
const response = await fetch(buildUrl(`/api/config/${key}`), {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
headers: {'Content-Type': 'application/json'},
|
headers: {'Content-Type': 'application/json'},
|
||||||
body: JSON.stringify(data)
|
body: JSON.stringify(data)
|
||||||
|
|
@ -26,41 +34,59 @@ export const api = {
|
||||||
},
|
},
|
||||||
|
|
||||||
updateConfigsBatch: async (configs) => {
|
updateConfigsBatch: async (configs) => {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/config/batch`, {
|
const response = await fetch(buildUrl('/api/config/batch'), {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {'Content-Type': 'application/json'},
|
headers: {'Content-Type': 'application/json'},
|
||||||
body: JSON.stringify(configs)
|
body: JSON.stringify(configs)
|
||||||
});
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
const error = await response.json().catch(() => ({ detail: '批量更新配置失败' }));
|
||||||
|
throw new Error(error.detail || '批量更新配置失败');
|
||||||
|
}
|
||||||
return response.json();
|
return response.json();
|
||||||
},
|
},
|
||||||
|
|
||||||
// 交易记录
|
// 交易记录
|
||||||
getTrades: async (params = {}) => {
|
getTrades: async (params = {}) => {
|
||||||
const query = new URLSearchParams(params).toString();
|
const query = new URLSearchParams(params).toString();
|
||||||
const response = await fetch(`${API_BASE_URL}/api/trades?${query}`);
|
const url = query ? `${buildUrl('/api/trades')}?${query}` : buildUrl('/api/trades');
|
||||||
|
const response = await fetch(url, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
});
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error('获取交易记录失败');
|
const error = await response.json().catch(() => ({ detail: '获取交易记录失败' }));
|
||||||
|
throw new Error(error.detail || '获取交易记录失败');
|
||||||
}
|
}
|
||||||
return response.json();
|
return response.json();
|
||||||
},
|
},
|
||||||
|
|
||||||
getTradeStats: async (params = {}) => {
|
getTradeStats: async (params = {}) => {
|
||||||
const query = new URLSearchParams(params).toString();
|
const query = new URLSearchParams(params).toString();
|
||||||
const response = await fetch(`${API_BASE_URL}/api/trades/stats?${query}`);
|
const url = query ? `${buildUrl('/api/trades/stats')}?${query}` : buildUrl('/api/trades/stats');
|
||||||
|
const response = await fetch(url, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
});
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error('获取交易统计失败');
|
const error = await response.json().catch(() => ({ detail: '获取交易统计失败' }));
|
||||||
|
throw new Error(error.detail || '获取交易统计失败');
|
||||||
}
|
}
|
||||||
return response.json();
|
return response.json();
|
||||||
},
|
},
|
||||||
|
|
||||||
// 统计
|
// 统计
|
||||||
getPerformance: async (days = 7) => {
|
getPerformance: async (days = 7) => {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/stats/performance?days=${days}`);
|
const response = await fetch(buildUrl(`/api/stats/performance?days=${days}`));
|
||||||
return response.json();
|
return response.json();
|
||||||
},
|
},
|
||||||
|
|
||||||
getDashboard: async () => {
|
getDashboard: async () => {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/dashboard/`);
|
const response = await fetch(buildUrl('/api/dashboard/'));
|
||||||
return response.json();
|
return response.json();
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -18,20 +18,41 @@ def _init_config_manager():
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import sys
|
import sys
|
||||||
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# 从trading_system目录向上两级到项目根目录,然后找backend
|
# 从trading_system目录向上两级到项目根目录,然后找backend
|
||||||
project_root = Path(__file__).parent.parent
|
project_root = Path(__file__).parent.parent
|
||||||
backend_path = project_root / 'backend'
|
backend_path = project_root / 'backend'
|
||||||
|
|
||||||
|
logger.debug(f"尝试初始化配置管理器,项目根目录: {project_root}, backend路径: {backend_path}")
|
||||||
|
|
||||||
if backend_path.exists():
|
if backend_path.exists():
|
||||||
sys.path.insert(0, str(backend_path))
|
sys.path.insert(0, str(backend_path))
|
||||||
|
try:
|
||||||
from config_manager import config_manager
|
from config_manager import config_manager
|
||||||
_config_manager = config_manager
|
_config_manager = config_manager
|
||||||
USE_DB_CONFIG = True
|
USE_DB_CONFIG = True
|
||||||
|
logger.info("✓ 配置管理器初始化成功,将从数据库读取配置")
|
||||||
return config_manager
|
return config_manager
|
||||||
else:
|
except ImportError as e:
|
||||||
|
logger.warning(f"无法导入config_manager: {e},将使用环境变量和默认配置")
|
||||||
USE_DB_CONFIG = False
|
USE_DB_CONFIG = False
|
||||||
return None
|
return None
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
logger.warning(f"配置管理器初始化失败: {e},将使用环境变量和默认配置")
|
||||||
|
USE_DB_CONFIG = False
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
logger.warning(f"backend目录不存在: {backend_path},将使用环境变量和默认配置")
|
||||||
|
USE_DB_CONFIG = False
|
||||||
|
return None
|
||||||
|
except Exception as e:
|
||||||
|
import logging
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
logger.warning(f"配置管理器初始化异常: {e},将使用环境变量和默认配置")
|
||||||
USE_DB_CONFIG = False
|
USE_DB_CONFIG = False
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
@ -41,9 +62,20 @@ _init_config_manager()
|
||||||
def _get_config_value(key, default=None):
|
def _get_config_value(key, default=None):
|
||||||
"""获取配置值(支持动态重载)"""
|
"""获取配置值(支持动态重载)"""
|
||||||
if _config_manager:
|
if _config_manager:
|
||||||
|
try:
|
||||||
_config_manager.reload() # 每次获取配置时重新加载
|
_config_manager.reload() # 每次获取配置时重新加载
|
||||||
return _config_manager.get(key, default) or os.getenv(key, default)
|
value = _config_manager.get(key, default)
|
||||||
return os.getenv(key, default)
|
# 如果从数据库获取到值,直接返回(即使是空字符串也返回)
|
||||||
|
if value is not None:
|
||||||
|
return value
|
||||||
|
except Exception as e:
|
||||||
|
import logging
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
logger.debug(f"从配置管理器获取{key}失败: {e},尝试环境变量")
|
||||||
|
|
||||||
|
# 回退到环境变量
|
||||||
|
env_value = os.getenv(key, default)
|
||||||
|
return env_value if env_value is not None else default
|
||||||
|
|
||||||
def _get_trading_config():
|
def _get_trading_config():
|
||||||
"""获取交易配置(支持动态重载)"""
|
"""获取交易配置(支持动态重载)"""
|
||||||
|
|
|
||||||
|
|
@ -49,25 +49,73 @@ async def main():
|
||||||
logger.info("币安自动交易系统启动")
|
logger.info("币安自动交易系统启动")
|
||||||
logger.info("=" * 60)
|
logger.info("=" * 60)
|
||||||
|
|
||||||
# 检查API密钥
|
# 检查配置管理器状态
|
||||||
if not config.BINANCE_API_KEY or not config.BINANCE_API_SECRET:
|
logger.info("检查配置管理器状态...")
|
||||||
|
if config.USE_DB_CONFIG:
|
||||||
|
logger.info("✓ 使用数据库配置")
|
||||||
|
# 尝试重新加载配置(确保获取最新值)
|
||||||
|
try:
|
||||||
|
config.reload_config()
|
||||||
|
logger.info("配置已重新加载")
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"重新加载配置失败: {e}")
|
||||||
|
else:
|
||||||
|
logger.warning("⚠ 未使用数据库配置,将使用环境变量和默认配置")
|
||||||
|
logger.warning("如果前端已配置API密钥,请检查:")
|
||||||
|
logger.warning("1. backend目录是否存在")
|
||||||
|
logger.warning("2. 数据库连接是否正常")
|
||||||
|
logger.warning("3. config_manager模块是否可以正常导入")
|
||||||
|
|
||||||
|
# 检查API密钥(重新获取,确保是最新值)
|
||||||
|
api_key = config._get_config_value('BINANCE_API_KEY', '')
|
||||||
|
api_secret = config._get_config_value('BINANCE_API_SECRET', '')
|
||||||
|
|
||||||
|
logger.info(f"API密钥检查: KEY存在={bool(api_key)}, SECRET存在={bool(api_secret)}")
|
||||||
|
|
||||||
|
if not api_key or not api_secret:
|
||||||
|
logger.error("=" * 60)
|
||||||
|
logger.error("API密钥未配置!")
|
||||||
|
logger.error("=" * 60)
|
||||||
|
if config.USE_DB_CONFIG:
|
||||||
|
logger.error("配置管理器已启用,但未从数据库读取到API密钥")
|
||||||
|
logger.error("请检查:")
|
||||||
|
logger.error("1. 前端配置界面是否已设置BINANCE_API_KEY和BINANCE_API_SECRET")
|
||||||
|
logger.error("2. 数据库trading_config表中是否有这些配置项")
|
||||||
|
logger.error("3. 数据库连接是否正常")
|
||||||
|
else:
|
||||||
logger.error("请设置 BINANCE_API_KEY 和 BINANCE_API_SECRET 环境变量")
|
logger.error("请设置 BINANCE_API_KEY 和 BINANCE_API_SECRET 环境变量")
|
||||||
logger.error("或在 config.py 中直接配置")
|
logger.error("或在 config.py 中直接配置")
|
||||||
|
logger.error("或确保backend目录存在,以便从数据库读取配置")
|
||||||
|
logger.error("=" * 60)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# 更新config模块的API密钥(确保使用最新值)
|
||||||
|
config.BINANCE_API_KEY = api_key
|
||||||
|
config.BINANCE_API_SECRET = api_secret
|
||||||
|
|
||||||
# 初始化组件
|
# 初始化组件
|
||||||
client = None
|
client = None
|
||||||
try:
|
try:
|
||||||
# 1. 初始化币安客户端
|
# 1. 初始化币安客户端
|
||||||
logger.info("初始化币安客户端...")
|
logger.info("初始化币安客户端...")
|
||||||
logger.info(f"测试网模式: {config.USE_TESTNET}")
|
|
||||||
|
# 再次确认API密钥(使用最新值)
|
||||||
|
api_key = config._get_config_value('BINANCE_API_KEY', config.BINANCE_API_KEY)
|
||||||
|
api_secret = config._get_config_value('BINANCE_API_SECRET', config.BINANCE_API_SECRET)
|
||||||
|
use_testnet = config._get_config_value('USE_TESTNET', config.USE_TESTNET)
|
||||||
|
if isinstance(use_testnet, str):
|
||||||
|
use_testnet = use_testnet.lower() in ('true', '1', 'yes', 'on')
|
||||||
|
elif not isinstance(use_testnet, bool):
|
||||||
|
use_testnet = bool(use_testnet)
|
||||||
|
|
||||||
|
logger.info(f"测试网模式: {use_testnet}")
|
||||||
logger.info(f"连接超时: {config.CONNECTION_TIMEOUT}秒")
|
logger.info(f"连接超时: {config.CONNECTION_TIMEOUT}秒")
|
||||||
logger.info(f"重试次数: {config.CONNECTION_RETRIES}次")
|
logger.info(f"重试次数: {config.CONNECTION_RETRIES}次")
|
||||||
|
|
||||||
client = BinanceClient(
|
client = BinanceClient(
|
||||||
api_key=config.BINANCE_API_KEY,
|
api_key=api_key,
|
||||||
api_secret=config.BINANCE_API_SECRET,
|
api_secret=api_secret,
|
||||||
testnet=config.USE_TESTNET
|
testnet=use_testnet
|
||||||
)
|
)
|
||||||
await client.connect()
|
await client.connect()
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user