diff --git a/src/components/ChatBot/EChartsRenderer.js b/src/components/ChatBot/EChartsRenderer.js index 735a44dd..1042a3c2 100644 --- a/src/components/ChatBot/EChartsRenderer.js +++ b/src/components/ChatBot/EChartsRenderer.js @@ -5,6 +5,33 @@ import React, { useEffect, useRef } from 'react'; import { Box, useColorModeValue } from '@chakra-ui/react'; import * as echarts from 'echarts'; +/** + * 验证 ECharts 配置是否有效 + */ +const isValidOption = (option) => { + if (!option || typeof option !== 'object') return false; + + // 检查 xAxis 配置 + if (option.xAxis) { + const xAxis = Array.isArray(option.xAxis) ? option.xAxis[0] : option.xAxis; + if (xAxis && xAxis.type === 'category' && (!xAxis.data || xAxis.data.length === 0)) { + // category 类型的 xAxis 必须有数据 + return false; + } + } + + // 检查 series 配置 + if (option.series) { + const series = Array.isArray(option.series) ? option.series : [option.series]; + const hasValidSeries = series.some(s => s && s.data && s.data.length > 0); + if (!hasValidSeries) { + return false; + } + } + + return true; +}; + /** * ECharts 图表渲染组件 * @param {Object} option - ECharts 配置对象 @@ -26,6 +53,12 @@ export const EChartsRenderer = ({ option, height = 400, variant = 'auto' }) => { useEffect(() => { if (!chartRef.current || !option) return; + // 验证配置是否有效 + if (!isValidOption(option)) { + console.warn('EChartsRenderer: Invalid or empty chart configuration, skipping render'); + return; + } + // 初始化图表(支持深色模式) if (!chartInstance.current) { chartInstance.current = echarts.init(chartRef.current, isDarkMode ? 'dark' : null); diff --git a/src/views/AgentChat/components/ChatArea/ExecutionStepsDisplay.js b/src/views/AgentChat/components/ChatArea/ExecutionStepsDisplay.js index 9eea2537..09380c0c 100644 --- a/src/views/AgentChat/components/ChatArea/ExecutionStepsDisplay.js +++ b/src/views/AgentChat/components/ChatArea/ExecutionStepsDisplay.js @@ -113,41 +113,51 @@ const StepCard = ({ result, idx }) => { // 如果有 echarts 图表数据,尝试生成图表 if (data.data?.chart_data) { const chartData = data.data.chart_data; - const echartsConfig = { - title: { text: `${data.data.formatted_date || ''} 涨停概念分布` }, - tooltip: { trigger: 'axis' }, - xAxis: { - type: 'category', - data: chartData.labels || [], - axisLabel: { rotate: 30, fontSize: 10 }, - }, - yAxis: { type: 'value' }, - series: [ - { - name: '涨停家数', - type: 'bar', - data: chartData.counts || [], - itemStyle: { - color: { - type: 'linear', - x: 0, y: 0, x2: 0, y2: 1, - colorStops: [ - { offset: 0, color: '#ff7043' }, - { offset: 1, color: '#ff5722' }, - ], - }, - }, - }, - ], - }; - const markdownContent = `\`\`\`echarts -${JSON.stringify(echartsConfig)} -\`\`\``; + // 验证图表数据是否有效 + const hasValidChartData = chartData.labels?.length > 0 && chartData.counts?.length > 0; return ( - + {hasValidChartData ? ( + (() => { + const echartsConfig = { + title: { text: `${data.data.formatted_date || ''} 涨停概念分布` }, + tooltip: { trigger: 'axis' }, + xAxis: { + type: 'category', + data: chartData.labels, + axisLabel: { rotate: 30, fontSize: 10 }, + }, + yAxis: { type: 'value' }, + series: [ + { + name: '涨停家数', + type: 'bar', + data: chartData.counts, + itemStyle: { + color: { + type: 'linear', + x: 0, y: 0, x2: 0, y2: 1, + colorStops: [ + { offset: 0, color: '#ff7043' }, + { offset: 1, color: '#ff5722' }, + ], + }, + }, + }, + ], + }; + + const markdownContent = `\`\`\`echarts +${JSON.stringify(echartsConfig)} +\`\`\``; + + return ; + })() + ) : ( + 暂无图表数据 + )} {/* 板块详情 */} {data.data?.sector_data && (