diff --git a/src/views/DataBrowser/TradingViewChart.tsx b/src/views/DataBrowser/TradingViewChart.tsx index 9a9585bd..4f82c7fb 100644 --- a/src/views/DataBrowser/TradingViewChart.tsx +++ b/src/views/DataBrowser/TradingViewChart.tsx @@ -11,7 +11,8 @@ import { useColorMode, Tooltip, } from '@chakra-ui/react'; -import { createChart, IChartApi, ISeriesApi, LineData, Time } from 'lightweight-charts'; +import * as LightweightCharts from 'lightweight-charts'; +import type { IChartApi, ISeriesApi, LineData, Time } from 'lightweight-charts'; import { FaExpand, FaCompress, @@ -70,109 +71,141 @@ const TradingViewChart: React.FC = ({ useEffect(() => { if (!chartContainerRef.current || data.length === 0) return; - // 创建图表 (lightweight-charts 5.0 标准 API) - const chart = createChart(chartContainerRef.current, { - width: chartContainerRef.current.clientWidth, - height: 500, - layout: { - background: { type: 'solid', color: themeColors.bg.card }, - textColor: themeColors.text.secondary, - }, - grid: { - vertLines: { - color: 'rgba(255, 255, 255, 0.05)', - }, - horzLines: { - color: 'rgba(255, 255, 255, 0.05)', - }, - }, - crosshair: { - vertLine: { - color: themeColors.primary.gold, - width: 1, - style: 3, // 虚线 - labelBackgroundColor: themeColors.primary.gold, - }, - horzLine: { - color: themeColors.primary.gold, - width: 1, - style: 3, - labelBackgroundColor: themeColors.primary.gold, - }, - }, - rightPriceScale: { - borderColor: themeColors.border.default, - }, - timeScale: { - borderColor: themeColors.border.default, - timeVisible: true, - secondsVisible: false, - }, - handleScroll: { - mouseWheel: true, - pressedMouseMove: true, - }, - handleScale: { - axisPressedMouseMove: true, - mouseWheel: true, - pinch: true, - }, - }); + try { + // 调试信息 + console.log('🔍 TradingView Chart - 开始初始化'); + console.log('📦 LightweightCharts 模块:', LightweightCharts); + console.log('📊 createChart 函数类型:', typeof LightweightCharts.createChart); - // 创建折线系列 (lightweight-charts 5.0 标准 API) - const lineSeries = chart.addLineSeries({ - color: themeColors.primary.gold, - lineWidth: 2, - crosshairMarkerVisible: true, - crosshairMarkerRadius: 6, - crosshairMarkerBorderColor: themeColors.primary.goldLight, - crosshairMarkerBackgroundColor: themeColors.primary.gold, - lastValueVisible: true, - priceLineVisible: true, - priceLineColor: themeColors.primary.gold, - priceLineWidth: 1, - priceLineStyle: 3, // 虚线 - title: metricName, - }); - - // 转换数据格式 - const chartData: LineData[] = data - .filter((item) => item.value !== null) - .map((item) => ({ - time: item.date as Time, - value: item.value as number, - })) - .sort((a, b) => { - // 确保时间从左到右递增 - const timeA = new Date(a.time as string).getTime(); - const timeB = new Date(b.time as string).getTime(); - return timeA - timeB; + // 创建图表 (lightweight-charts 5.0 标准 API) + const chart = LightweightCharts.createChart(chartContainerRef.current, { + width: chartContainerRef.current.clientWidth, + height: 500, + layout: { + background: { type: 'solid', color: themeColors.bg.card }, + textColor: themeColors.text.secondary, + }, + grid: { + vertLines: { + color: 'rgba(255, 255, 255, 0.05)', + }, + horzLines: { + color: 'rgba(255, 255, 255, 0.05)', + }, + }, + crosshair: { + vertLine: { + color: themeColors.primary.gold, + width: 1, + style: 3, // 虚线 + labelBackgroundColor: themeColors.primary.gold, + }, + horzLine: { + color: themeColors.primary.gold, + width: 1, + style: 3, + labelBackgroundColor: themeColors.primary.gold, + }, + }, + rightPriceScale: { + borderColor: themeColors.border.default, + }, + timeScale: { + borderColor: themeColors.border.default, + timeVisible: true, + secondsVisible: false, + }, + handleScroll: { + mouseWheel: true, + pressedMouseMove: true, + }, + handleScale: { + axisPressedMouseMove: true, + mouseWheel: true, + pinch: true, + }, }); - // 设置数据 - lineSeries.setData(chartData); + // 调试信息 + console.log('📈 Chart 对象:', chart); + console.log('📈 Chart 类型:', typeof chart); + console.log('📈 Chart 的方法:', Object.keys(chart)); + console.log('📈 addLineSeries 存在?', typeof chart.addLineSeries); - // 自动缩放到合适的视图 - chart.timeScale().fitContent(); - - chartRef.current = chart; - lineSeriesRef.current = lineSeries; - - // 响应式调整 - const handleResize = () => { - if (chartContainerRef.current && chart) { - chart.applyOptions({ - width: chartContainerRef.current.clientWidth, - }); + // 检查 chart 对象是否有效 + if (!chart || typeof chart.addLineSeries !== 'function') { + console.error('❌ createChart 返回的对象无效!'); + console.error('Chart 对象:', chart); + throw new Error('createChart 返回的对象没有 addLineSeries 方法'); } - }; - window.addEventListener('resize', handleResize); + // 创建折线系列 (lightweight-charts 5.0 标准 API) + const lineSeries = chart.addLineSeries({ + color: themeColors.primary.gold, + lineWidth: 2, + crosshairMarkerVisible: true, + crosshairMarkerRadius: 6, + crosshairMarkerBorderColor: themeColors.primary.goldLight, + crosshairMarkerBackgroundColor: themeColors.primary.gold, + lastValueVisible: true, + priceLineVisible: true, + priceLineColor: themeColors.primary.gold, + priceLineWidth: 1, + priceLineStyle: 3, // 虚线 + title: metricName, + }); - return () => { - window.removeEventListener('resize', handleResize); - chart.remove(); - }; + console.log('✅ LineSeries 创建成功'); + + // 转换数据格式 + const chartData: LineData[] = data + .filter((item) => item.value !== null) + .map((item) => ({ + time: item.date as Time, + value: item.value as number, + })) + .sort((a, b) => { + // 确保时间从左到右递增 + const timeA = new Date(a.time as string).getTime(); + const timeB = new Date(b.time as string).getTime(); + return timeA - timeB; + }); + + // 设置数据 + lineSeries.setData(chartData); + + // 自动缩放到合适的视图 + chart.timeScale().fitContent(); + + chartRef.current = chart; + lineSeriesRef.current = lineSeries; + + // 响应式调整 + const handleResize = () => { + if (chartContainerRef.current && chart) { + chart.applyOptions({ + width: chartContainerRef.current.clientWidth, + }); + } + }; + + window.addEventListener('resize', handleResize); + + return () => { + window.removeEventListener('resize', handleResize); + chart.remove(); + }; + } catch (error) { + console.error('❌ TradingView Chart 初始化失败:', error); + console.error('Error details:', { + message: error.message, + stack: error.stack, + LightweightChartsModule: LightweightCharts, + createChartType: typeof LightweightCharts.createChart, + }); + // 重新抛出错误让 ErrorBoundary 捕获 + throw error; + } }, [data, metricName]); // 时间范围筛选