diff --git a/backend/src/services/marketService.ts b/backend/src/services/marketService.ts
index 64ef3d2..75435e2 100644
--- a/backend/src/services/marketService.ts
+++ b/backend/src/services/marketService.ts
@@ -14,188 +14,286 @@ export const fetchMarketOverview = async () => {
try {
// 获取数据源配置
const dataSourceConfig = getDataSourceConfig();
- // 使用TQSDK数据源
- const dataSource = await DataSourceFactory.getDataSource(DataSourceType.TQSDK, dataSourceConfig);
- const overview = await dataSource.getMarketOverview();
- // 转换为前端需要的格式
- return overview.map(item => ({
- code: item.symbol,
- name: item.name,
- currentPrice: item.price,
- changePercent: item.change_percent,
- winRate: Math.floor(Math.random() * 50) + 30, // 模拟胜率
- atr: +(Math.random() * 5 + 0.5).toFixed(2), // 模拟ATR
- adx: Math.floor(Math.random() * 60) + 10, // 模拟ADX
- adxStatus: adx => {
- if (adx < 20) return '无趋势/震荡';
- if (adx < 40) return '弱趋势';
- return '强趋势';
- },
- trends: {
- '5MIN': {
- direction: ['看多', '看空', '观望'][Math.floor(Math.random() * 3)],
- status: ['多头趋势', '空头趋势', '震荡'][Math.floor(Math.random() * 3)],
- rsi: Math.floor(Math.random() * 80) + 10
- },
- '30MIN': {
- direction: ['看多', '看空', '观望'][Math.floor(Math.random() * 3)],
- status: ['多头趋势', '空头趋势', '震荡'][Math.floor(Math.random() * 3)],
- rsi: Math.floor(Math.random() * 80) + 10
- },
- '1HOUR': {
- direction: ['看多', '看空', '观望'][Math.floor(Math.random() * 3)],
- status: ['多头趋势', '空头趋势', '震荡'][Math.floor(Math.random() * 3)],
- rsi: Math.floor(Math.random() * 80) + 10
- },
- '1DAY': {
- direction: ['看多', '看空', '观望'][Math.floor(Math.random() * 3)],
- status: ['多头趋势', '空头趋势', '震荡'][Math.floor(Math.random() * 3)],
- rsi: Math.floor(Math.random() * 80) + 10
+ // 检查是否有可用的数据源
+ const hasAvailableDataSource = dataSourceConfig.tqsdk?.enabled || dataSourceConfig.test?.enabled;
+ if (!hasAvailableDataSource) {
+ throw new Error('无可用数据源,请在管理配置中启用至少一个数据源');
+ }
+
+ // 尝试使用TQSDK数据源
+ if (dataSourceConfig.tqsdk?.enabled) {
+ try {
+ const dataSource = await DataSourceFactory.getDataSource(DataSourceType.TQSDK, dataSourceConfig);
+
+ // 使用用户指定的合约列表
+ const overview = [];
+ for (const future of futuresList) {
+ try {
+ // 构建合约符号
+ const symbol = `${future.exchange}.${future.code}${new Date().getFullYear().toString().slice(-2)}05`;
+ // 获取合约详情和实时行情
+ const tick = await dataSource.getTickData(symbol);
+
+ overview.push({
+ code: future.code,
+ name: future.name,
+ currentPrice: tick.last_price,
+ changePercent: tick.price_change / tick.pre_close * 100,
+ winRate: Math.floor(Math.random() * 50) + 30, // 模拟胜率
+ atr: +(Math.random() * 5 + 0.5).toFixed(2), // 模拟ATR
+ adx: Math.floor(Math.random() * 60) + 10, // 模拟ADX
+ adxStatus: adx => {
+ if (adx < 20) return '无趋势/震荡';
+ if (adx < 40) return '弱趋势';
+ return '强趋势';
+ },
+ trends: {
+ '5MIN': {
+ direction: ['看多', '看空', '观望'][Math.floor(Math.random() * 3)],
+ status: ['多头趋势', '空头趋势', '震荡'][Math.floor(Math.random() * 3)],
+ rsi: Math.floor(Math.random() * 80) + 10
+ },
+ '30MIN': {
+ direction: ['看多', '看空', '观望'][Math.floor(Math.random() * 3)],
+ status: ['多头趋势', '空头趋势', '震荡'][Math.floor(Math.random() * 3)],
+ rsi: Math.floor(Math.random() * 80) + 10
+ },
+ '1HOUR': {
+ direction: ['看多', '看空', '观望'][Math.floor(Math.random() * 3)],
+ status: ['多头趋势', '空头趋势', '震荡'][Math.floor(Math.random() * 3)],
+ rsi: Math.floor(Math.random() * 80) + 10
+ },
+ '1DAY': {
+ direction: ['看多', '看空', '观望'][Math.floor(Math.random() * 3)],
+ status: ['多头趋势', '空头趋势', '震荡'][Math.floor(Math.random() * 3)],
+ rsi: Math.floor(Math.random() * 80) + 10
+ }
+ },
+ tradingAdvice: {
+ entry: tick.last_price,
+ stopLoss: tick.last_price * (1 - 0.02 * (Math.random() + 0.5)),
+ target: tick.last_price * (1 + 0.03 * (Math.random() + 0.5)),
+ resistance: tick.last_price * (1 + 0.05 * (Math.random() + 0.5)),
+ support: tick.last_price * (1 - 0.05 * (Math.random() + 0.5))
+ },
+ overallView: ['观望', '中线', '多头排列', '空头排列', '震荡'][Math.floor(Math.random() * 5)],
+ aiAnalysis: `MACD:金叉向上 | RSI:${Math.floor(Math.random() * 80) + 10}(中性) | 布林带:中轨附近`
+ });
+ } catch (error) {
+ console.error(`获取合约${future.code}行情失败:`, error);
+ // 跳过获取失败的合约
+ continue;
+ }
}
- },
- tradingAdvice: {
- entry: item.price,
- stopLoss: item.price * (1 - 0.02 * (Math.random() + 0.5)),
- target: item.price * (1 + 0.03 * (Math.random() + 0.5)),
- resistance: item.price * (1 + 0.05 * (Math.random() + 0.5)),
- support: item.price * (1 - 0.05 * (Math.random() + 0.5))
- },
- overallView: ['观望', '中线', '多头排列', '空头排列', '震荡'][Math.floor(Math.random() * 5)],
- aiAnalysis: `MACD:金叉向上 | RSI:${Math.floor(Math.random() * 80) + 10}(中性) | 布林带:中轨附近`
- }));
- } catch (error) {
- console.error('获取市场概览失败:', error);
- // 获取数据源配置
- const dataSourceConfig = getDataSourceConfig();
- // 检查是否启用了测试数据源
- if (dataSourceConfig.test && dataSourceConfig.test.enabled) {
- // 启用了测试数据源,使用测试数据
+
+ return overview;
+ } catch (error) {
+ console.error('TQSDK数据源获取失败:', error);
+ // TQSDK数据源失败,尝试使用测试数据源
+ if (dataSourceConfig.test?.enabled) {
+ console.log('切换到测试数据源');
+ // 启用了测试数据源,使用测试数据
+ await new Promise(resolve => setTimeout(resolve, 300));
+ return generateFuturesOverview();
+ } else {
+ // 未启用测试数据源,返回友好的错误提示
+ throw new Error('获取市场概览失败,所有数据源均不可用');
+ }
+ }
+ } else if (dataSourceConfig.test?.enabled) {
+ // 直接使用测试数据源
+ console.log('使用测试数据源');
await new Promise(resolve => setTimeout(resolve, 300));
return generateFuturesOverview();
} else {
- // 未启用测试数据源,返回友好的错误提示
- throw new Error('获取市场概览失败,请检查数据源配置');
+ // 无可用数据源
+ throw new Error('无可用数据源,请在管理配置中启用至少一个数据源');
}
+ } catch (error) {
+ console.error('获取市场概览失败:', error);
+ // 直接返回友好的错误提示
+ throw new Error(error instanceof Error ? error.message : '获取市场概览失败,请检查数据源配置');
}
};
// 获取品种详情
export const fetchMarketDetail = async (symbol: string) => {
try {
+ // 查找合约信息
+ const future = futuresList.find(item => item.code === symbol);
+ if (!future) {
+ throw new Error('品种不存在');
+ }
+
// 获取数据源配置
const dataSourceConfig = getDataSourceConfig();
- // 使用TQSDK数据源
- const dataSource = await DataSourceFactory.getDataSource(DataSourceType.TQSDK, dataSourceConfig);
- const contract = await dataSource.getContractDetail(symbol);
- const tick = await dataSource.getTickData(symbol);
- // 转换为前端需要的格式
- return {
- code: contract.symbol,
- name: contract.name,
- fullName: `${contract.name}-${contract.symbol}605`,
- currentPrice: tick.last_price,
- changePercent: tick.price_change / tick.pre_close * 100,
- winRate: Math.floor(Math.random() * 50) + 30,
- atr: +(Math.random() * 5 + 0.5).toFixed(2),
- adx: Math.floor(Math.random() * 60) + 10,
- adxStatus: adx => {
- if (adx < 20) return '无趋势/震荡';
- if (adx < 40) return '弱趋势';
- return '强趋势';
- },
- trends: {
- '5MIN': {
- direction: ['看多', '看空', '观望'][Math.floor(Math.random() * 3)],
- status: ['多头趋势', '空头趋势', '震荡'][Math.floor(Math.random() * 3)],
- rsi: Math.floor(Math.random() * 80) + 10
- },
- '30MIN': {
- direction: ['看多', '看空', '观望'][Math.floor(Math.random() * 3)],
- status: ['多头趋势', '空头趋势', '震荡'][Math.floor(Math.random() * 3)],
- rsi: Math.floor(Math.random() * 80) + 10
- },
- '1HOUR': {
- direction: ['看多', '看空', '观望'][Math.floor(Math.random() * 3)],
- status: ['多头趋势', '空头趋势', '震荡'][Math.floor(Math.random() * 3)],
- rsi: Math.floor(Math.random() * 80) + 10
- },
- '1DAY': {
- direction: ['看多', '看空', '观望'][Math.floor(Math.random() * 3)],
- status: ['多头趋势', '空头趋势', '震荡'][Math.floor(Math.random() * 3)],
- rsi: Math.floor(Math.random() * 80) + 10
+ // 检查是否有可用的数据源
+ const hasAvailableDataSource = dataSourceConfig.tqsdk?.enabled || dataSourceConfig.test?.enabled;
+ if (!hasAvailableDataSource) {
+ throw new Error('无可用数据源,请在管理配置中启用至少一个数据源');
+ }
+
+ // 尝试使用TQSDK数据源
+ if (dataSourceConfig.tqsdk?.enabled) {
+ try {
+ const dataSource = await DataSourceFactory.getDataSource(DataSourceType.TQSDK, dataSourceConfig);
+
+ // 构建合约符号
+ const contractSymbol = `${future.exchange}.${future.code}${new Date().getFullYear().toString().slice(-2)}05`;
+
+ // 获取合约详情和实时行情
+ const tick = await dataSource.getTickData(contractSymbol);
+
+ // 转换为前端需要的格式
+ return {
+ code: future.code,
+ name: future.name,
+ fullName: `${future.name}-${future.code}605`,
+ currentPrice: tick.last_price,
+ changePercent: tick.price_change / tick.pre_close * 100,
+ winRate: Math.floor(Math.random() * 50) + 30,
+ atr: +(Math.random() * 5 + 0.5).toFixed(2),
+ adx: Math.floor(Math.random() * 60) + 10,
+ adxStatus: adx => {
+ if (adx < 20) return '无趋势/震荡';
+ if (adx < 40) return '弱趋势';
+ return '强趋势';
+ },
+ trends: {
+ '5MIN': {
+ direction: ['看多', '看空', '观望'][Math.floor(Math.random() * 3)],
+ status: ['多头趋势', '空头趋势', '震荡'][Math.floor(Math.random() * 3)],
+ rsi: Math.floor(Math.random() * 80) + 10
+ },
+ '30MIN': {
+ direction: ['看多', '看空', '观望'][Math.floor(Math.random() * 3)],
+ status: ['多头趋势', '空头趋势', '震荡'][Math.floor(Math.random() * 3)],
+ rsi: Math.floor(Math.random() * 80) + 10
+ },
+ '1HOUR': {
+ direction: ['看多', '看空', '观望'][Math.floor(Math.random() * 3)],
+ status: ['多头趋势', '空头趋势', '震荡'][Math.floor(Math.random() * 3)],
+ rsi: Math.floor(Math.random() * 80) + 10
+ },
+ '1DAY': {
+ direction: ['看多', '看空', '观望'][Math.floor(Math.random() * 3)],
+ status: ['多头趋势', '空头趋势', '震荡'][Math.floor(Math.random() * 3)],
+ rsi: Math.floor(Math.random() * 80) + 10
+ }
+ },
+ indicators: {
+ macd: ['金叉向上', '死叉向下', '走平'][Math.floor(Math.random() * 3)],
+ rsi: `${Math.floor(Math.random() * 80) + 10}(中性)`,
+ bollinger: ['触及上轨', '触及下轨', '中轨附近'][Math.floor(Math.random() * 3)],
+ kdj: ['金叉向上', '死叉向下', '走平'][Math.floor(Math.random() * 3)]
+ },
+ tradingAdvice: {
+ entry: tick.last_price,
+ stopLoss: tick.last_price * (1 - 0.02 * (Math.random() + 0.5)),
+ target: tick.last_price * (1 + 0.03 * (Math.random() + 0.5)),
+ resistance: tick.last_price * (1 + 0.05 * (Math.random() + 0.5)),
+ support: tick.last_price * (1 - 0.05 * (Math.random() + 0.5))
+ },
+ riskLevel: ['低', '中等', '高'][Math.floor(Math.random() * 3)],
+ volatility: ['低', '中等', '高'][Math.floor(Math.random() * 3)],
+ overallView: ['观望', '中线', '多头排列', '空头排列', '震荡'][Math.floor(Math.random() * 5)],
+ aiAnalysis: `MACD:金叉向上 | RSI:${Math.floor(Math.random() * 80) + 10}(中性) | 布林带:中轨附近`
+ };
+ } catch (error) {
+ console.error('TQSDK数据源获取失败:', error);
+ // TQSDK数据源失败,尝试使用测试数据源
+ if (dataSourceConfig.test?.enabled) {
+ console.log('切换到测试数据源');
+ // 启用了测试数据源,使用测试数据
+ await new Promise(resolve => setTimeout(resolve, 200));
+ return generateFutureData(symbol, future.name);
+ } else {
+ // 未启用测试数据源,返回友好的错误提示
+ throw new Error('获取品种详情失败,所有数据源均不可用');
}
- },
- indicators: {
- macd: ['金叉向上', '死叉向下', '走平'][Math.floor(Math.random() * 3)],
- rsi: `${Math.floor(Math.random() * 80) + 10}(中性)`,
- bollinger: ['触及上轨', '触及下轨', '中轨附近'][Math.floor(Math.random() * 3)],
- kdj: ['金叉向上', '死叉向下', '走平'][Math.floor(Math.random() * 3)]
- },
- tradingAdvice: {
- entry: tick.last_price,
- stopLoss: tick.last_price * (1 - 0.02 * (Math.random() + 0.5)),
- target: tick.last_price * (1 + 0.03 * (Math.random() + 0.5)),
- resistance: tick.last_price * (1 + 0.05 * (Math.random() + 0.5)),
- support: tick.last_price * (1 - 0.05 * (Math.random() + 0.5))
- },
- riskLevel: ['低', '中等', '高'][Math.floor(Math.random() * 3)],
- volatility: ['低', '中等', '高'][Math.floor(Math.random() * 3)],
- overallView: ['观望', '中线', '多头排列', '空头排列', '震荡'][Math.floor(Math.random() * 5)],
- aiAnalysis: `MACD:金叉向上 | RSI:${Math.floor(Math.random() * 80) + 10}(中性) | 布林带:中轨附近`
- };
- } catch (error) {
- console.error(`获取品种${symbol}详情失败:`, error);
- // 获取数据源配置
- const dataSourceConfig = getDataSourceConfig();
- // 检查是否启用了测试数据源
- if (dataSourceConfig.test && dataSourceConfig.test.enabled) {
- // 启用了测试数据源,使用测试数据
- await new Promise(resolve => setTimeout(resolve, 200));
- const future = futuresList.find(item => item.code === symbol);
- if (!future) {
- throw new Error('品种不存在');
}
+ } else if (dataSourceConfig.test?.enabled) {
+ // 直接使用测试数据源
+ console.log('使用测试数据源');
+ await new Promise(resolve => setTimeout(resolve, 200));
return generateFutureData(symbol, future.name);
} else {
- // 未启用测试数据源,返回友好的错误提示
- throw new Error('获取品种详情失败,请检查数据源配置');
+ // 无可用数据源
+ throw new Error('无可用数据源,请在管理配置中启用至少一个数据源');
}
+ } catch (error) {
+ console.error(`获取品种${symbol}详情失败:`, error);
+ // 直接返回友好的错误提示
+ throw new Error(error instanceof Error ? error.message : '获取品种详情失败,请检查数据源配置');
}
};
// 获取K线数据
export const fetchKlineData = async (symbol: string, period: string) => {
try {
- // 获取数据源配置
- const dataSourceConfig = getDataSourceConfig();
- // 使用TQSDK数据源
- const dataSource = await DataSourceFactory.getDataSource(DataSourceType.TQSDK, dataSourceConfig);
- const klineData = await dataSource.getKlineData(symbol, period, 30);
+ // 查找合约信息
+ const future = futuresList.find(item => item.code === symbol);
+ if (!future) {
+ throw new Error('品种不存在');
+ }
- // 转换为前端需要的格式
- return klineData.map(item => ({
- timestamp: item.datetime / 1000000000, // 转换为秒
- open: item.open,
- high: item.high,
- low: item.low,
- close: item.close,
- volume: item.volume
- }));
- } catch (error) {
- console.error(`获取合约${symbol}K线数据失败:`, error);
// 获取数据源配置
const dataSourceConfig = getDataSourceConfig();
- // 检查是否启用了测试数据源
- if (dataSourceConfig.test && dataSourceConfig.test.enabled) {
- // 启用了测试数据源,使用测试数据
+
+ // 检查是否有可用的数据源
+ const hasAvailableDataSource = dataSourceConfig.tqsdk?.enabled || dataSourceConfig.test?.enabled;
+ if (!hasAvailableDataSource) {
+ throw new Error('无可用数据源,请在管理配置中启用至少一个数据源');
+ }
+
+ // 尝试使用TQSDK数据源
+ if (dataSourceConfig.tqsdk?.enabled) {
+ try {
+ const dataSource = await DataSourceFactory.getDataSource(DataSourceType.TQSDK, dataSourceConfig);
+
+ // 构建合约符号
+ const contractSymbol = `${future.exchange}.${future.code}${new Date().getFullYear().toString().slice(-2)}05`;
+
+ // 获取K线数据
+ const klineData = await dataSource.getKlineData(contractSymbol, period, 30);
+
+ // 转换为前端需要的格式
+ return klineData.map(item => ({
+ timestamp: item.datetime / 1000000000, // 转换为秒
+ open: item.open,
+ high: item.high,
+ low: item.low,
+ close: item.close,
+ volume: item.volume
+ }));
+ } catch (error) {
+ console.error('TQSDK数据源获取失败:', error);
+ // TQSDK数据源失败,尝试使用测试数据源
+ if (dataSourceConfig.test?.enabled) {
+ console.log('切换到测试数据源');
+ // 启用了测试数据源,使用测试数据
+ await new Promise(resolve => setTimeout(resolve, 200));
+ return generateKlineData(30);
+ } else {
+ // 未启用测试数据源,返回友好的错误提示
+ throw new Error('获取K线数据失败,所有数据源均不可用');
+ }
+ }
+ } else if (dataSourceConfig.test?.enabled) {
+ // 直接使用测试数据源
+ console.log('使用测试数据源');
await new Promise(resolve => setTimeout(resolve, 200));
return generateKlineData(30);
} else {
- // 未启用测试数据源,返回友好的错误提示
- throw new Error('获取K线数据失败,请检查数据源配置');
+ // 无可用数据源
+ throw new Error('无可用数据源,请在管理配置中启用至少一个数据源');
}
+ } catch (error) {
+ console.error(`获取合约${symbol}K线数据失败:`, error);
+ // 直接返回友好的错误提示
+ throw new Error(error instanceof Error ? error.message : '获取K线数据失败,请检查数据源配置');
}
};
@@ -204,27 +302,70 @@ export const fetchMarketHotspots = async () => {
try {
// 获取数据源配置
const dataSourceConfig = getDataSourceConfig();
- // 使用TQSDK数据源
- const dataSource = await DataSourceFactory.getDataSource(DataSourceType.TQSDK, dataSourceConfig);
- const overview = await dataSource.getMarketOverview();
- // 按涨跌幅排序,返回前10个
- return overview
- .sort((a, b) => Math.abs(b.change_percent) - Math.abs(a.change_percent))
- .slice(0, 10)
- .map(item => ({
- symbol: item.symbol,
- name: item.name,
- change: item.change_percent,
- volume: item.volume
- }));
- } catch (error) {
- console.error('获取市场热点失败:', error);
- // 获取数据源配置
- const dataSourceConfig = getDataSourceConfig();
- // 检查是否启用了测试数据源
- if (dataSourceConfig.test && dataSourceConfig.test.enabled) {
- // 启用了测试数据源,使用测试数据
+ // 检查是否有可用的数据源
+ const hasAvailableDataSource = dataSourceConfig.tqsdk?.enabled || dataSourceConfig.test?.enabled;
+ if (!hasAvailableDataSource) {
+ throw new Error('无可用数据源,请在管理配置中启用至少一个数据源');
+ }
+
+ // 尝试使用TQSDK数据源
+ if (dataSourceConfig.tqsdk?.enabled) {
+ try {
+ const dataSource = await DataSourceFactory.getDataSource(DataSourceType.TQSDK, dataSourceConfig);
+
+ // 使用用户指定的合约列表
+ const hotspots = [];
+ for (const future of futuresList) {
+ try {
+ // 构建合约符号
+ const symbol = `${future.exchange}.${future.code}${new Date().getFullYear().toString().slice(-2)}05`;
+ // 获取合约详情和实时行情
+ const tick = await dataSource.getTickData(symbol);
+
+ hotspots.push({
+ symbol: future.code,
+ name: future.name,
+ change: tick.price_change / tick.pre_close * 100,
+ volume: tick.volume
+ });
+ } catch (error) {
+ console.error(`获取合约${future.code}行情失败:`, error);
+ // 跳过获取失败的合约
+ continue;
+ }
+ }
+
+ // 按涨跌幅排序,返回前10个
+ return hotspots
+ .sort((a, b) => Math.abs(b.change) - Math.abs(a.change))
+ .slice(0, 10);
+ } catch (error) {
+ console.error('TQSDK数据源获取失败:', error);
+ // TQSDK数据源失败,尝试使用测试数据源
+ if (dataSourceConfig.test?.enabled) {
+ console.log('切换到测试数据源');
+ // 启用了测试数据源,使用测试数据
+ await new Promise(resolve => setTimeout(resolve, 200));
+ const overview = generateFuturesOverview();
+ // 按涨跌幅排序,返回前10个
+ return overview
+ .sort((a, b) => Math.abs(b.changePercent) - Math.abs(a.changePercent))
+ .slice(0, 10)
+ .map(item => ({
+ symbol: item.code,
+ name: item.name,
+ change: item.changePercent,
+ volume: Math.floor(Math.random() * 1000000) + 100000
+ }));
+ } else {
+ // 未启用测试数据源,返回友好的错误提示
+ throw new Error('获取市场热点失败,所有数据源均不可用');
+ }
+ }
+ } else if (dataSourceConfig.test?.enabled) {
+ // 直接使用测试数据源
+ console.log('使用测试数据源');
await new Promise(resolve => setTimeout(resolve, 200));
const overview = generateFuturesOverview();
// 按涨跌幅排序,返回前10个
@@ -238,9 +379,13 @@ export const fetchMarketHotspots = async () => {
volume: Math.floor(Math.random() * 1000000) + 100000
}));
} else {
- // 未启用测试数据源,返回友好的错误提示
- throw new Error('获取市场热点失败,请检查数据源配置');
+ // 无可用数据源
+ throw new Error('无可用数据源,请在管理配置中启用至少一个数据源');
}
+ } catch (error) {
+ console.error('获取市场热点失败:', error);
+ // 直接返回友好的错误提示
+ throw new Error(error instanceof Error ? error.message : '获取市场热点失败,请检查数据源配置');
}
};
diff --git a/backend/src/utils/mockData.ts b/backend/src/utils/mockData.ts
index 2be010c..91bc19d 100644
--- a/backend/src/utils/mockData.ts
+++ b/backend/src/utils/mockData.ts
@@ -3,44 +3,65 @@
// 期货品种列表
export const futuresList = [
// 金属类
- { code: 'AU', name: '金', type: '金属' },
- { code: 'AG', name: '银', type: '金属' },
- { code: 'CU', name: '铜', type: '金属' },
- { code: 'NI', name: '镍', type: '金属' },
- { code: 'SN', name: '锡', type: '金属' },
- { code: 'AL', name: '铝', type: '金属' },
- { code: 'ZN', name: '锌', type: '金属' },
+ { code: 'AU', name: '黄金', type: '金属', exchange: 'SHFE' },
+ { code: 'AG', name: '白银', type: '金属', exchange: 'SHFE' },
+ { code: 'CU', name: '铜', type: '金属', exchange: 'SHFE' },
+ { code: 'NI', name: '镍', type: '金属', exchange: 'SHFE' },
+ { code: 'SN', name: '锡', type: '金属', exchange: 'SHFE' },
+ { code: 'AL', name: '铝', type: '金属', exchange: 'SHFE' },
+ { code: 'ZN', name: '锌', type: '金属', exchange: 'SHFE' },
+ { code: 'PB', name: '铅', type: '金属', exchange: 'SHFE' },
// 建材类
- { code: 'FG', name: '玻璃', type: '建材' },
- { code: 'SJS', name: '烧碱', type: '建材' },
- { code: 'SCA', name: '纯碱', type: '建材' },
- { code: 'JM', name: '焦煤', type: '建材' },
- { code: 'RB', name: '螺纹钢', type: '建材' },
- { code: 'ALO', name: '氧化铝', type: '建材' },
+ { code: 'FG', name: '玻璃', type: '建材', exchange: 'CZCE' },
+ { code: 'LY', name: '烧碱', type: '建材', exchange: 'CZCE' },
+ { code: 'SA', name: '纯碱', type: '建材', exchange: 'CZCE' },
+ { code: 'JM', name: '焦煤', type: '建材', exchange: 'DCE' },
+ { code: 'RB', name: '螺纹钢', type: '建材', exchange: 'SHFE' },
+ { code: 'ALO', name: '氧化铝', type: '建材', exchange: 'SHFE' },
+ { code: 'HC', name: '热轧卷板', type: '建材', exchange: 'SHFE' },
// 能源化工类
- { code: 'MA', name: '甲醇', type: '能源化工' },
- { code: 'PVC', name: 'PVC', type: '能源化工' },
- { code: 'FU', name: '燃油', type: '能源化工' },
- { code: 'SC', name: '原油', type: '能源化工' },
- { code: 'L', name: '橡胶', type: '能源化工' },
- { code: 'NR', name: '20号胶', type: '能源化工' },
- { code: 'BU', name: '沥青', type: '能源化工' },
- { code: 'LU', name: '低硫燃油', type: '能源化工' },
+ { code: 'MA', name: '甲醇', type: '能源化工', exchange: 'CZCE' },
+ { code: 'V', name: 'PVC', type: '能源化工', exchange: 'DCE' },
+ { code: 'FU', name: '燃油', type: '能源化工', exchange: 'SHFE' },
+ { code: 'SC', name: '原油', type: '能源化工', exchange: 'INE' },
+ { code: 'RU', name: '橡胶', type: '能源化工', exchange: 'SHFE' },
+ { code: 'BR', name: '合成橡胶', type: '能源化工', exchange: 'DCE' },
+ { code: 'NR', name: '20号胶', type: '能源化工', exchange: 'SHFE' },
+ { code: 'BU', name: '沥青', type: '能源化工', exchange: 'SHFE' },
+ { code: 'LU', name: '低硫燃油', type: '能源化工', exchange: 'INE' },
+ { code: 'L', name: '聚乙烯', type: '能源化工', exchange: 'DCE' },
+ { code: 'PP', name: '聚丙烯', type: '能源化工', exchange: 'DCE' },
+ { code: 'TA', name: 'PTA', type: '能源化工', exchange: 'CZCE' },
// 农产品类
- { code: 'P', name: '棕榈油', type: '农产品' },
+ { code: 'P', name: '棕榈油', type: '农产品', exchange: 'DCE' },
+ { code: 'A', name: '大豆', type: '农产品', exchange: 'DCE' },
+ { code: 'B', name: '豆粕', type: '农产品', exchange: 'DCE' },
+ { code: 'M', name: '豆粕', type: '农产品', exchange: 'DCE' },
+ { code: 'Y', name: '豆油', type: '农产品', exchange: 'DCE' },
+ { code: 'C', name: '玉米', type: '农产品', exchange: 'DCE' },
+ { code: 'CS', name: '玉米淀粉', type: '农产品', exchange: 'DCE' },
+ { code: 'CF', name: '棉花', type: '农产品', exchange: 'CZCE' },
+ { code: 'SR', name: '白糖', type: '农产品', exchange: 'CZCE' },
+ { code: 'RM', name: '菜籽粕', type: '农产品', exchange: 'CZCE' },
+ { code: 'OI', name: '菜籽油', type: '农产品', exchange: 'CZCE' },
// 新能源类
- { code: 'LC', name: '碳酸锂', type: '新能源' },
- { code: 'SI', name: '工业硅', type: '新能源' },
- { code: 'PGS', name: '多晶硅', type: '新能源' },
+ { code: 'LI', name: '碳酸锂', type: '新能源', exchange: 'SHFE' },
+ { code: 'SI', name: '工业硅', type: '新能源', exchange: 'GEM' },
+ { code: 'SP', name: '多晶硅', type: '新能源', exchange: 'GEM' },
// 金融类
- { code: 'IC', name: '中证500', type: '金融' },
- { code: 'IM', name: '中证1000', type: '金融' },
- { code: 'IH', name: '上证50', type: '金融' }
+ { code: 'IM', name: '中证1000', type: '金融', exchange: 'CFFEX' },
+ { code: 'IC', name: '中证500', type: '金融', exchange: 'CFFEX' },
+ { code: 'IH', name: '上证50', type: '金融', exchange: 'CFFEX' },
+
+ // 其他
+ { code: 'I', name: '铁矿石', type: '其他', exchange: 'DCE' },
+ { code: 'J', name: '焦炭', type: '其他', exchange: 'DCE' },
+ { code: 'ZC', name: '动力煤', type: '其他', exchange: 'CZCE' }
];
// 生成随机数据的工具函数
diff --git a/src/App.jsx b/src/App.jsx
index f1abf88..242955c 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -1,6 +1,7 @@
import React, { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import { Provider } from 'react-redux';
+import { App as AntdApp } from 'antd';
import store from './store';
import MainLayout from './components/layout/MainLayout';
// 使用懒加载优化性能
@@ -14,22 +15,24 @@ import './App.css';
function App() {
return (
-