918bbed0fc
- 修复 deps.py 中 get_vn_service 的引用错误 (vn_service.vn_service -> vn_service) - 移除登录页面上的明文密码提示 - 改进前端错误处理,避免数据加载失败导致登录显示错误
374 lines
8.0 KiB
JavaScript
374 lines
8.0 KiB
JavaScript
/**
|
|
* API 请求封装
|
|
* 处理认证、错误处理、请求拦截
|
|
*/
|
|
|
|
const API_BASE = '/api/v1';
|
|
|
|
/**
|
|
* API 客户端类
|
|
*/
|
|
class ApiClient {
|
|
constructor() {
|
|
this.token = localStorage.getItem('token');
|
|
this.tokenExpiry = localStorage.getItem('tokenExpiry');
|
|
}
|
|
|
|
/**
|
|
* 保存 Token
|
|
*/
|
|
setToken(token, expiresIn) {
|
|
this.token = token;
|
|
const expiry = new Date(Date.now() + expiresIn * 1000);
|
|
this.tokenExpiry = expiry.toISOString();
|
|
localStorage.setItem('token', token);
|
|
localStorage.setItem('tokenExpiry', this.tokenExpiry);
|
|
}
|
|
|
|
/**
|
|
* 清除 Token
|
|
*/
|
|
clearToken() {
|
|
this.token = null;
|
|
this.tokenExpiry = null;
|
|
localStorage.removeItem('token');
|
|
localStorage.removeItem('tokenExpiry');
|
|
}
|
|
|
|
/**
|
|
* 检查 Token 是否有效
|
|
*/
|
|
isTokenValid() {
|
|
if (!this.token || !this.tokenExpiry) {
|
|
return false;
|
|
}
|
|
const expiry = new Date(this.tokenExpiry);
|
|
return expiry > new Date();
|
|
}
|
|
|
|
/**
|
|
* 获取请求头
|
|
*/
|
|
getHeaders() {
|
|
const headers = {
|
|
'Content-Type': 'application/json'
|
|
};
|
|
|
|
if (this.token) {
|
|
headers['Authorization'] = `Bearer ${this.token}`;
|
|
}
|
|
|
|
return headers;
|
|
}
|
|
|
|
/**
|
|
* 处理响应
|
|
*/
|
|
async handleResponse(response) {
|
|
if (response.status === 401) {
|
|
// Token 过期或无效
|
|
this.clearToken();
|
|
window.location.reload();
|
|
throw new Error('Authentication failed');
|
|
}
|
|
|
|
if (response.status === 204) {
|
|
return null;
|
|
}
|
|
|
|
const data = await response.json();
|
|
|
|
if (!response.ok) {
|
|
const error = data.error || data.message || 'Request failed';
|
|
throw new Error(error);
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
/**
|
|
* GET 请求
|
|
*/
|
|
async get(url, params = {}) {
|
|
const queryString = new URLSearchParams(params).toString();
|
|
const fullUrl = `${API_BASE}${url}${queryString ? '?' + queryString : ''}`;
|
|
|
|
const response = await fetch(fullUrl, {
|
|
method: 'GET',
|
|
headers: this.getHeaders()
|
|
});
|
|
|
|
return this.handleResponse(response);
|
|
}
|
|
|
|
/**
|
|
* POST 请求
|
|
*/
|
|
async post(url, data = {}) {
|
|
const response = await fetch(`${API_BASE}${url}`, {
|
|
method: 'POST',
|
|
headers: this.getHeaders(),
|
|
body: JSON.stringify(data)
|
|
});
|
|
|
|
return this.handleResponse(response);
|
|
}
|
|
|
|
/**
|
|
* PUT 请求
|
|
*/
|
|
async put(url, data = {}) {
|
|
const response = await fetch(`${API_BASE}${url}`, {
|
|
method: 'PUT',
|
|
headers: this.getHeaders(),
|
|
body: JSON.stringify(data)
|
|
});
|
|
|
|
return this.handleResponse(response);
|
|
}
|
|
|
|
/**
|
|
* DELETE 请求
|
|
*/
|
|
async delete(url) {
|
|
const response = await fetch(`${API_BASE}${url}`, {
|
|
method: 'DELETE',
|
|
headers: this.getHeaders()
|
|
});
|
|
|
|
return this.handleResponse(response);
|
|
}
|
|
|
|
// ============================================
|
|
// 认证 API
|
|
// ============================================
|
|
|
|
/**
|
|
* 用户登录
|
|
*/
|
|
async login(username, password) {
|
|
const data = await this.post('/auth/login', { username, password });
|
|
this.setToken(data.access_token, data.expires_in);
|
|
return data;
|
|
}
|
|
|
|
/**
|
|
* 用户登出
|
|
*/
|
|
async logout() {
|
|
try {
|
|
await this.post('/auth/logout');
|
|
} finally {
|
|
this.clearToken();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 验证 Token
|
|
*/
|
|
async verifyToken() {
|
|
return await this.post('/auth/verify', { token: this.token });
|
|
}
|
|
|
|
/**
|
|
* 获取当前用户信息
|
|
*/
|
|
async getCurrentUser() {
|
|
return await this.get('/auth/me');
|
|
}
|
|
|
|
// ============================================
|
|
// 系统 API
|
|
// ============================================
|
|
|
|
/**
|
|
* 获取系统信息
|
|
*/
|
|
async getSystemInfo() {
|
|
return await this.get('/system/info');
|
|
}
|
|
|
|
// ============================================
|
|
// 网关 API
|
|
// ============================================
|
|
|
|
/**
|
|
* 获取网关列表
|
|
*/
|
|
async getGateways() {
|
|
return await this.get('/gateway/list');
|
|
}
|
|
|
|
/**
|
|
* 获取网关状态
|
|
*/
|
|
async getGatewayStatus(name) {
|
|
return await this.get(`/gateway/${name}/status`);
|
|
}
|
|
|
|
// ============================================
|
|
// 行情 API
|
|
// ============================================
|
|
|
|
/**
|
|
* 获取合约列表
|
|
*/
|
|
async getContracts() {
|
|
const data = await this.get('/market/contracts');
|
|
return data.contracts || [];
|
|
}
|
|
|
|
/**
|
|
* 获取行情数据
|
|
*/
|
|
async getTicks(symbols = null) {
|
|
const params = symbols ? { symbols: symbols.join(',') } : {};
|
|
const data = await this.get('/market/ticks', params);
|
|
return data.ticks || [];
|
|
}
|
|
|
|
/**
|
|
* 订阅行情
|
|
*/
|
|
async subscribe(symbol, exchange, gatewayName = null) {
|
|
return await this.post('/market/subscribe', {
|
|
symbol,
|
|
exchange,
|
|
gateway_name: gatewayName
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 取消订阅行情
|
|
*/
|
|
async unsubscribe(symbol, exchange, gatewayName = null) {
|
|
return await this.post('/market/unsubscribe', {
|
|
symbol,
|
|
exchange,
|
|
gateway_name: gatewayName
|
|
});
|
|
}
|
|
|
|
// ============================================
|
|
// 交易 API
|
|
// ============================================
|
|
|
|
/**
|
|
* 获取账户列表
|
|
*/
|
|
async getAccounts() {
|
|
return await this.get('/trading/accounts');
|
|
}
|
|
|
|
/**
|
|
* 获取持仓列表
|
|
*/
|
|
async getPositions() {
|
|
return await this.get('/trading/positions');
|
|
}
|
|
|
|
/**
|
|
* 获取订单列表
|
|
*/
|
|
async getOrders() {
|
|
return await this.get('/trading/orders');
|
|
}
|
|
|
|
/**
|
|
* 获取活动订单
|
|
*/
|
|
async getActiveOrders() {
|
|
return await this.get('/trading/orders/active');
|
|
}
|
|
|
|
/**
|
|
* 发送订单
|
|
*/
|
|
async sendOrder(params) {
|
|
return await this.post('/trading/orders', params);
|
|
}
|
|
|
|
/**
|
|
* 撤销订单
|
|
*/
|
|
async cancelOrder(orderId) {
|
|
return await this.delete(`/trading/orders/${orderId}`);
|
|
}
|
|
|
|
/**
|
|
* 获取成交列表
|
|
*/
|
|
async getTrades() {
|
|
return await this.get('/trading/trades');
|
|
}
|
|
|
|
/**
|
|
* 获取账户综合信息
|
|
*/
|
|
async getAccount() {
|
|
return await this.get('/trading/account');
|
|
}
|
|
|
|
// ============================================
|
|
// 策略 API
|
|
// ============================================
|
|
|
|
/**
|
|
* 获取策略列表
|
|
*/
|
|
async getStrategies() {
|
|
return await this.get('/strategy/list');
|
|
}
|
|
|
|
/**
|
|
* 创建策略
|
|
*/
|
|
async createStrategy(strategyName, className, setting) {
|
|
return await this.post('/strategy/create', {
|
|
strategy_name: strategyName,
|
|
class_name: className,
|
|
setting
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 初始化策略
|
|
*/
|
|
async initStrategy(strategyName) {
|
|
return await this.post('/strategy/init', {
|
|
strategy_name: strategyName
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 启动策略
|
|
*/
|
|
async startStrategy(strategyName) {
|
|
return await this.post('/strategy/start', {
|
|
strategy_name: strategyName
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 停止策略
|
|
*/
|
|
async stopStrategy(strategyName) {
|
|
return await this.post('/strategy/stop', {
|
|
strategy_name: strategyName
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 编辑策略
|
|
*/
|
|
async editStrategy(strategyName, setting) {
|
|
return await this.post('/strategy/edit', {
|
|
strategy_name: strategyName,
|
|
setting
|
|
});
|
|
}
|
|
}
|
|
|
|
// 创建全局 API 客户端实例
|
|
const api = new ApiClient();
|