| | |
| | | const hasRenderedRef = useRef<boolean>(false); |
| | | const chartInstanceRef = useRef<any>(null); |
| | | |
| | | // 初始化DOM容器 |
| | | // 初始化DOM容器 - 提前设置固定高度 |
| | | useEffect(() => { |
| | | // 确保容器准备好了 |
| | | // 确保容器准备好了并且有确定的高度 |
| | | if (chartContainerRef.current) { |
| | | // 设置一个初始高度和宽度,避免"invalid dom"错误 |
| | | // 设置一个固定的高度,避免渲染后变化 |
| | | const container = chartContainerRef.current; |
| | | container.style.width = '100%'; |
| | | container.style.height = '400px'; |
| | | container.style.height = '400px'; // 固定高度400px |
| | | container.style.minHeight = '400px'; // 防止高度变小 |
| | | |
| | | // 添加临时内容,确保DOM渲染完成 |
| | | container.innerHTML = '<div style="width:100%;height:100%;display:flex;align-items:center;justify-content:center;"><span>正在准备图表...</span></div>'; |
| | | container.innerHTML = '<div style="width:100%;height:100%;display:flex;align-items:center;justify-content:center;background:#f5f7f9;"><span>正在准备图表...</span></div>'; |
| | | } |
| | | }, []); |
| | | |
| | |
| | | const chartOption = safeFunc(); |
| | | |
| | | if (chartOption) { |
| | | // 禁用动画,避免渲染时的布局变化 |
| | | chartOption.animation = false; |
| | | |
| | | // 修改tooltip配置,确保显示在适当位置 |
| | | if (chartOption.tooltip) { |
| | | chartOption.tooltip = { |
| | | ...chartOption.tooltip, |
| | | confine: false, // 不限制在图表区域内 |
| | | extraCssText: 'z-index:9999; pointer-events:auto; margin-top:60px;', |
| | | }; |
| | | } |
| | | |
| | | chartInstance.setOption(chartOption); |
| | | setError(null); |
| | | } else { |
| | |
| | | // 如果主图表已经初始化,复用其配置 |
| | | if (chartInstanceRef.current) { |
| | | const option = chartInstanceRef.current.getOption(); |
| | | |
| | | // 调整模态窗口中tooltip的配置 |
| | | if (option && option.tooltip) { |
| | | option.tooltip = { |
| | | ...option.tooltip, |
| | | confine: false, |
| | | extraCssText: 'z-index:10000; margin-top: 0; max-width: 80vw;', |
| | | }; |
| | | } |
| | | |
| | | modalChartInstance.setOption(option); |
| | | } else { |
| | | // 如果主图表没有初始化,尝试从代码初始化 |
| | |
| | | const chartOption = safeFunc(); |
| | | |
| | | if (chartOption) { |
| | | // 调整模态窗口的tooltip配置 |
| | | if (chartOption.tooltip) { |
| | | chartOption.tooltip = { |
| | | ...chartOption.tooltip, |
| | | confine: false, |
| | | extraCssText: 'z-index:10000; max-width: 80vw;', |
| | | }; |
| | | } |
| | | |
| | | modalChartInstance.setOption(chartOption); |
| | | } else { |
| | | throw new Error("无法获取模态图表配置"); |
| | |
| | | </div> |
| | | )} |
| | | |
| | | {/* 图表容器 */} |
| | | {/* 图表容器 - 固定高度 */} |
| | | <div |
| | | ref={chartContainerRef} |
| | | className="w-full bg-white border border-gray-200 rounded-lg overflow-hidden chart-container" |
| | | style={{ |
| | | height: '300px', |
| | | minHeight: '300px', |
| | | height: '400px', |
| | | minHeight: '400px', |
| | | visibility: 'visible', |
| | | position: 'relative' |
| | | }} |
| | |
| | | // 检查消息是否完整 - 通过父组件传递的isMessageComplete状态 |
| | | const isComplete = useContext(MessageCompletionContext); |
| | | |
| | | // 在消息未完成时显示加载动画 |
| | | // 在消息未完成时显示加载动画 - 固定高度匹配图表 |
| | | if (language === 'javascript' && !isComplete) { |
| | | return ( |
| | | <div className="w-full bg-gray-50 rounded-md my-4 p-6 text-center"> |
| | | <div className="flex flex-col items-center justify-center"> |
| | | <div className="w-full bg-gray-50 rounded-md my-4 p-6 text-center" style={{height: '400px'}}> |
| | | <div className="flex flex-col items-center justify-center h-full"> |
| | | <div className="animate-spin rounded-full h-8 w-8 border-t-2 border-b-2 border-gray-400 mb-4"></div> |
| | | <p className="text-gray-500">代码加载中...</p> |
| | | <p className="text-gray-500">加载中...</p> |
| | | <p className="text-xs text-gray-400 mt-2">等待消息完成后将渲染图表</p> |
| | | </div> |
| | | </div> |
| | | ); |
| | | } |
| | | |
| | | // 消息完成后,如果是图表代码则渲染为图表 |
| | | // 消息完成后,如果是图表代码则渲染为图表 - 在外部包装一层固定高度容器 |
| | | if (isEchartsCode() && isComplete) { |
| | | return <EchartsRenderer code={value} />; |
| | | return ( |
| | | <div style={{height: '400px', minHeight: '400px', position: 'relative'}}> |
| | | <EchartsRenderer code={value} /> |
| | | </div> |
| | | ); |
| | | } |
| | | |
| | | // 普通JavaScript代码或其他语言的代码块,直接显示代码 |