301 lines
10 KiB
JavaScript
301 lines
10 KiB
JavaScript
// 如果设置了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 = {
|
||
// 配置管理
|
||
getConfigs: async () => {
|
||
const response = await fetch(buildUrl('/api/config'));
|
||
if (!response.ok) {
|
||
const error = await response.json().catch(() => ({ detail: '获取配置失败' }));
|
||
throw new Error(error.detail || '获取配置失败');
|
||
}
|
||
return response.json();
|
||
},
|
||
|
||
getConfig: async (key) => {
|
||
const response = await fetch(buildUrl(`/api/config/${key}`));
|
||
if (!response.ok) {
|
||
const error = await response.json().catch(() => ({ detail: '获取配置失败' }));
|
||
throw new Error(error.detail || '获取配置失败');
|
||
}
|
||
return response.json();
|
||
},
|
||
|
||
updateConfig: async (key, data) => {
|
||
const response = await fetch(buildUrl(`/api/config/${key}`), {
|
||
method: 'PUT',
|
||
headers: {'Content-Type': 'application/json'},
|
||
body: JSON.stringify(data)
|
||
});
|
||
if (!response.ok) {
|
||
const error = await response.json();
|
||
throw new Error(error.detail || '更新配置失败');
|
||
}
|
||
return response.json();
|
||
},
|
||
|
||
updateConfigsBatch: async (configs) => {
|
||
const response = await fetch(buildUrl('/api/config/batch'), {
|
||
method: 'POST',
|
||
headers: {'Content-Type': 'application/json'},
|
||
body: JSON.stringify(configs)
|
||
});
|
||
if (!response.ok) {
|
||
const error = await response.json().catch(() => ({ detail: '批量更新配置失败' }));
|
||
throw new Error(error.detail || '批量更新配置失败');
|
||
}
|
||
return response.json();
|
||
},
|
||
|
||
// 检查配置可行性
|
||
checkConfigFeasibility: async () => {
|
||
const response = await fetch(buildUrl('/api/config/feasibility-check'));
|
||
if (!response.ok) {
|
||
const error = await response.json().catch(() => ({ detail: '检查配置可行性失败' }));
|
||
throw new Error(error.detail || '检查配置可行性失败');
|
||
}
|
||
return response.json();
|
||
},
|
||
|
||
// 交易记录
|
||
getTrades: async (params = {}) => {
|
||
const query = new URLSearchParams(params).toString();
|
||
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) {
|
||
const error = await response.json().catch(() => ({ detail: '获取交易记录失败' }));
|
||
throw new Error(error.detail || '获取交易记录失败');
|
||
}
|
||
return response.json();
|
||
},
|
||
|
||
getTradeStats: async (params = {}) => {
|
||
const query = new URLSearchParams(params).toString();
|
||
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) {
|
||
const error = await response.json().catch(() => ({ detail: '获取交易统计失败' }));
|
||
throw new Error(error.detail || '获取交易统计失败');
|
||
}
|
||
return response.json();
|
||
},
|
||
|
||
// 统计
|
||
getPerformance: async (days = 7) => {
|
||
const response = await fetch(buildUrl(`/api/stats/performance?days=${days}`));
|
||
if (!response.ok) {
|
||
const error = await response.json().catch(() => ({ detail: '获取性能统计失败' }));
|
||
throw new Error(error.detail || '获取性能统计失败');
|
||
}
|
||
return response.json();
|
||
},
|
||
|
||
getDashboard: async () => {
|
||
const response = await fetch(buildUrl('/api/dashboard'));
|
||
if (!response.ok) {
|
||
const error = await response.json().catch(() => ({ detail: '获取仪表板数据失败' }));
|
||
throw new Error(error.detail || '获取仪表板数据失败');
|
||
}
|
||
return response.json();
|
||
},
|
||
|
||
// 平仓操作
|
||
closePosition: async (symbol) => {
|
||
const response = await fetch(buildUrl(`/api/account/positions/${symbol}/close`), {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
},
|
||
});
|
||
if (!response.ok) {
|
||
const error = await response.json().catch(() => ({ detail: '平仓失败' }));
|
||
throw new Error(error.detail || '平仓失败');
|
||
}
|
||
return response.json();
|
||
},
|
||
|
||
// 同步持仓状态
|
||
syncPositions: async () => {
|
||
const response = await fetch(buildUrl('/api/account/positions/sync'), {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
},
|
||
});
|
||
if (!response.ok) {
|
||
const error = await response.json().catch(() => ({ detail: '同步失败' }));
|
||
throw new Error(error.detail || '同步失败');
|
||
}
|
||
return response.json();
|
||
},
|
||
|
||
// 交易推荐
|
||
getRecommendations: async (params = {}) => {
|
||
// 默认使用实时推荐
|
||
if (!params.type) {
|
||
params.type = 'realtime'
|
||
}
|
||
const query = new URLSearchParams(params).toString();
|
||
const url = query ? `${buildUrl('/api/recommendations')}?${query}` : buildUrl('/api/recommendations');
|
||
const response = await fetch(url);
|
||
if (!response.ok) {
|
||
const error = await response.json().catch(() => ({ detail: '获取推荐失败' }));
|
||
throw new Error(error.detail || '获取推荐失败');
|
||
}
|
||
return response.json();
|
||
},
|
||
|
||
bookmarkRecommendation: async (recommendationData) => {
|
||
const response = await fetch(buildUrl('/api/recommendations/bookmark'), {
|
||
method: 'POST',
|
||
headers: {'Content-Type': 'application/json'},
|
||
body: JSON.stringify(recommendationData)
|
||
});
|
||
if (!response.ok) {
|
||
const error = await response.json().catch(() => ({ detail: '标记推荐失败' }));
|
||
throw new Error(error.detail || '标记推荐失败');
|
||
}
|
||
return response.json();
|
||
},
|
||
|
||
getActiveRecommendations: async () => {
|
||
const response = await fetch(buildUrl('/api/recommendations/active'));
|
||
if (!response.ok) {
|
||
const error = await response.json().catch(() => ({ detail: '获取有效推荐失败' }));
|
||
throw new Error(error.detail || '获取有效推荐失败');
|
||
}
|
||
return response.json();
|
||
},
|
||
|
||
getRecommendation: async (id) => {
|
||
const response = await fetch(buildUrl(`/api/recommendations/${id}`));
|
||
if (!response.ok) {
|
||
const error = await response.json().catch(() => ({ detail: '获取推荐详情失败' }));
|
||
throw new Error(error.detail || '获取推荐详情失败');
|
||
}
|
||
return response.json();
|
||
},
|
||
|
||
generateRecommendations: async (minSignalStrength = 5, maxRecommendations = 20) => {
|
||
const response = await fetch(
|
||
buildUrl(`/api/recommendations/generate?min_signal_strength=${minSignalStrength}&max_recommendations=${maxRecommendations}`),
|
||
{
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
},
|
||
}
|
||
);
|
||
if (!response.ok) {
|
||
const error = await response.json().catch(() => ({ detail: '生成推荐失败' }));
|
||
throw new Error(error.detail || '生成推荐失败');
|
||
}
|
||
return response.json();
|
||
},
|
||
|
||
markRecommendationExecuted: async (id, tradeId = null) => {
|
||
const response = await fetch(buildUrl(`/api/recommendations/${id}/execute`), {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
},
|
||
body: JSON.stringify({ trade_id: tradeId }),
|
||
});
|
||
if (!response.ok) {
|
||
const error = await response.json().catch(() => ({ detail: '标记执行失败' }));
|
||
throw new Error(error.detail || '标记执行失败');
|
||
}
|
||
return response.json();
|
||
},
|
||
|
||
cancelRecommendation: async (id, notes = null) => {
|
||
const response = await fetch(buildUrl(`/api/recommendations/${id}/cancel`), {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
},
|
||
body: JSON.stringify({ notes }),
|
||
});
|
||
if (!response.ok) {
|
||
const error = await response.json().catch(() => ({ detail: '取消推荐失败' }));
|
||
throw new Error(error.detail || '取消推荐失败');
|
||
}
|
||
return response.json();
|
||
},
|
||
|
||
// 系统控制(supervisor)
|
||
clearSystemCache: async () => {
|
||
const response = await fetch(buildUrl('/api/system/clear-cache'), {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
});
|
||
if (!response.ok) {
|
||
const error = await response.json().catch(() => ({ detail: '清理缓存失败' }));
|
||
throw new Error(error.detail || '清理缓存失败');
|
||
}
|
||
return response.json();
|
||
},
|
||
|
||
getTradingSystemStatus: async () => {
|
||
const response = await fetch(buildUrl('/api/system/trading/status'));
|
||
if (!response.ok) {
|
||
const error = await response.json().catch(() => ({ detail: '获取交易系统状态失败' }));
|
||
throw new Error(error.detail || '获取交易系统状态失败');
|
||
}
|
||
return response.json();
|
||
},
|
||
|
||
startTradingSystem: async () => {
|
||
const response = await fetch(buildUrl('/api/system/trading/start'), {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
});
|
||
if (!response.ok) {
|
||
const error = await response.json().catch(() => ({ detail: '启动交易系统失败' }));
|
||
throw new Error(error.detail || '启动交易系统失败');
|
||
}
|
||
return response.json();
|
||
},
|
||
|
||
stopTradingSystem: async () => {
|
||
const response = await fetch(buildUrl('/api/system/trading/stop'), {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
});
|
||
if (!response.ok) {
|
||
const error = await response.json().catch(() => ({ detail: '停止交易系统失败' }));
|
||
throw new Error(error.detail || '停止交易系统失败');
|
||
}
|
||
return response.json();
|
||
},
|
||
|
||
restartTradingSystem: async () => {
|
||
const response = await fetch(buildUrl('/api/system/trading/restart'), {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
});
|
||
if (!response.ok) {
|
||
const error = await response.json().catch(() => ({ detail: '重启交易系统失败' }));
|
||
throw new Error(error.detail || '重启交易系统失败');
|
||
}
|
||
return response.json();
|
||
},
|
||
};
|