import React, { useState, useEffect, useRef } from 'react'; import { Card, Button, Row, Col, Select, Tabs, Tag, Statistic, Alert, Spin } from 'antd'; import { useParams, useNavigate } from 'react-router-dom'; import { LineChartOutlined, BarChartOutlined, AreaChartOutlined, ArrowUpOutlined, AlertOutlined, RobotOutlined, SafetyOutlined } from '@ant-design/icons'; import { generateFutureData, generateKlineData } from '../../utils/mockData'; import { createChart } from 'lightweight-charts'; import './Detail.css'; const { Option } = Select; const { TabPane } = Tabs; const Detail = () => { const navigate = useNavigate(); const { code } = useParams(); const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [currentPeriod, setCurrentPeriod] = useState('1H'); const [currentIndicator, setCurrentIndicator] = useState('MA'); const chartRef = useRef(null); const chartInstance = useRef(null); console.log('Detail page loaded with code:', code); useEffect(() => { // 从后端API获取品种详情数据 const fetchFutureDetail = async () => { try { console.log('Fetching detail for code:', code); const response = await fetch(`http://localhost:3007/api/market/detail/${code}`); if (!response.ok) { throw new Error('获取品种详情失败'); } const result = await response.json(); console.log('Received detail data:', result); setData(result.data); setLoading(false); } catch (error) { console.error('获取品种详情失败:', error); // 失败时使用模拟数据 const futureData = generateFutureData(code, code); // 使用code作为品种名称 setData(futureData); setLoading(false); } }; fetchFutureDetail(); }, [code]); // 初始化和更新K线图表 useEffect(() => { if (!data || !chartRef.current) return; // 销毁旧图表 if (chartInstance.current) { chartInstance.current.destroy(); } // 从后端API获取K线数据 const fetchKlineData = async () => { try { console.log('Fetching Kline data for code:', code, 'period:', currentPeriod); const response = await fetch(`http://localhost:3007/api/market/klines/${code}?period=${currentPeriod}`); if (!response.ok) { throw new Error('获取K线数据失败'); } const result = await response.json(); console.log('Received Kline data:', result); // 检查数据格式 if (result.data && Array.isArray(result.data) && result.data.length > 0) { return result.data; } else { console.warn('Kline data is empty or invalid, using mock data'); // 失败时使用模拟数据 return generateKlineData(30); } } catch (error) { console.error('获取K线数据失败:', error); // 失败时使用模拟数据 return generateKlineData(30); } }; fetchKlineData().then(klineData => { // 检查chartRef.current是否存在 if (!chartRef.current) return; // 创建图表 const chart = createChart(chartRef.current, { width: chartRef.current.clientWidth, height: 400, timeScale: { timeVisible: true, secondsVisible: false, }, grid: { vertLines: { color: 'rgba(42, 46, 57, 0.1)', }, horzLines: { color: 'rgba(42, 46, 57, 0.1)', }, }, }); // 检查chart对象是否正确创建 console.log('Chart object:', chart); console.log('Chart methods:', Object.keys(chart)); // 添加K线系列 try { const candlestickSeries = chart.addCandlestickSeries({ upColor: '#52c41a', downColor: '#ff4d4f', borderVisible: false, wickUpColor: '#52c41a', wickDownColor: '#ff4d4f', }); // 设置K线数据 candlestickSeries.setData(klineData.map(item => ({ time: new Date(item.timestamp * 1000).toISOString().split('T')[0], open: item.open, high: item.high, low: item.low, close: item.close, }))); // 根据当前指标添加相应的技术指标 if (currentIndicator === 'MA') { // 添加MA5 const ma5Series = chart.addLineSeries({ color: '#1890ff', lineWidth: 1, }); // 计算MA5数据 const ma5Data = []; for (let i = 4; i < klineData.length; i++) { const sum = klineData.slice(i - 4, i + 1).reduce((acc, item) => acc + item.close, 0); ma5Data.push({ time: new Date(klineData[i].timestamp * 1000).toISOString().split('T')[0], value: sum / 5, }); } ma5Series.setData(ma5Data); // 添加MA10 const ma10Series = chart.addLineSeries({ color: '#faad14', lineWidth: 1, }); // 计算MA10数据 const ma10Data = []; for (let i = 9; i < klineData.length; i++) { const sum = klineData.slice(i - 9, i + 1).reduce((acc, item) => acc + item.close, 0); ma10Data.push({ time: new Date(klineData[i].timestamp * 1000).toISOString().split('T')[0], value: sum / 10, }); } ma10Series.setData(ma10Data); } } catch (error) { console.error('Error creating chart series:', error); // 失败时使用模拟数据创建简单的线图 const lineSeries = chart.addLineSeries({ color: '#1890ff', lineWidth: 1, }); lineSeries.setData(klineData.map(item => ({ time: new Date(item.timestamp * 1000).toISOString().split('T')[0], value: item.close, }))); } // 保存图表实例 chartInstance.current = chart; // 处理窗口大小变化 const handleResize = () => { if (chartInstance.current) { chartInstance.current.resize(chartRef.current.clientWidth, 400); } }; window.addEventListener('resize', handleResize); // 清理函数 return () => { window.removeEventListener('resize', handleResize); if (chartInstance.current) { chartInstance.current.destroy(); } }; }); }, [data, currentPeriod, currentIndicator, code]); const handleBack = () => { navigate('/'); }; const handlePeriodChange = (value) => { setCurrentPeriod(value); }; const handleIndicatorChange = (value) => { setCurrentIndicator(value); }; if (loading) { return (
); } if (!data) { return (
); } return (
{/* 页面头部 */}

{data.name} ({data.code})

= 0 ? '#52c41a' : '#ff4d4f' }} /> = 0 ? '#52c41a' : '#ff4d4f' }} />
{/* K线图表区 */}

K线图表

周期: 指标:
{/* TradingView Lightweight Charts */}
{/* 技术指标区 */}

技术指标

MA5
{data.technicalIndicators?.ma5 || 'N/A'}
MA10
{data.technicalIndicators?.ma10 || 'N/A'}
MACD
{data.technicalIndicators?.macd || 'N/A'}
RSI
{data.technicalIndicators?.rsi || 'N/A'}
KDJ
{data.technicalIndicators?.kdj || 'N/A'}
布林带
{data.technicalIndicators?.bollinger || 'N/A'}
ATR
{data.atr}
ADX
{data.adx}
{/* 多周期趋势和AI研判区 */} {/* 多周期趋势 */}

多周期趋势

{data.trends && Object.entries(data.trends).map(([period, trend]) => (

{period.replace('MIN', 'min').replace('HOUR', 'min')}

{trend.direction}
{trend.status}
RSI: {trend.rsi}
))}
{/* AI研判区 */}

AI研判

AI分析

{data.aiAnalysis || 'AI正在分析中...'}

关键因素

{data.aiPrediction?.keyFactors?.map((factor, index) => ( {factor} ))}
{/* 交易建议区和风险评估区 */} {/* 交易建议区 */}

交易建议

入场价
{data.tradingAdvice?.entryPrice || 'N/A'}
止损价
{data.tradingAdvice?.stopLoss || 'N/A'}
目标价
{data.tradingAdvice?.targetPrice || 'N/A'}

操作建议

{data.tradingAdvice?.strategy || 'AI正在生成策略...'}

{/* 风险评估区 */}

风险评估

风险等级
{data.riskLevel}
波动率
{data.volatility || 'N/A'}%
最大回撤
{data.maxDrawdown || 'N/A'}%

风险提示

); }; export default Detail;