diff --git a/frontend/src/frameworks/components/charts/ChartRenderer.tsx b/frontend/src/frameworks/components/charts/ChartRenderer.tsx index ba7bbd9..af24a77 100644 --- a/frontend/src/frameworks/components/charts/ChartRenderer.tsx +++ b/frontend/src/frameworks/components/charts/ChartRenderer.tsx @@ -2,66 +2,41 @@ import React, { useMemo } from 'react'; import { type ChartInstance } from '@/domain/entities/ChartInstance'; -import { type StyleConfig } from '@/domain/entities/StyleConfig'; import { chartRenderer } from '@/frameworks/di/container'; import { EChartsBase } from './EChartsBase'; import { KPICard } from './KPICard'; import { DataTable } from './DataTable'; -const DEFAULT_STYLE: StyleConfig = { - title: { text: '', visible: true, fontSize: 16, fontWeight: 'bold', color: '#333', align: 'left' }, - colors: ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4'], - legend: { visible: true, position: 'top', orient: 'horizontal', fontSize: 12, color: '#666' }, - xAxis: { visible: true, labelVisible: true, labelFontSize: 12, labelColor: '#666', labelRotation: 0, titleVisible: false, titleText: '', gridVisible: true, gridColor: '#eee' }, - yAxis: { visible: true, labelVisible: true, labelFontSize: 12, labelColor: '#666', labelRotation: 0, titleVisible: false, titleText: '', gridVisible: true, gridColor: '#eee' }, - dataLabel: { visible: false, fontSize: 12, color: '#333', position: 'outside', format: 'value' }, - background: { color: '#fff', opacity: 1, borderRadius: 4 }, - border: { visible: false, color: '#ddd', width: 1, style: 'solid' }, - animation: { enabled: true, duration: 500, easing: 'ease-out' }, -}; - -function ensureStyle(style: any): StyleConfig { - if (!style || typeof style !== 'object') return DEFAULT_STYLE; - return { - title: { ...DEFAULT_STYLE.title, ...(style.title ?? {}) }, - colors: style.colors ?? DEFAULT_STYLE.colors, - legend: { ...DEFAULT_STYLE.legend, ...(style.legend ?? {}) }, - xAxis: { ...DEFAULT_STYLE.xAxis, ...(style.xAxis ?? {}) }, - yAxis: { ...DEFAULT_STYLE.yAxis, ...(style.yAxis ?? {}) }, - dataLabel: { ...DEFAULT_STYLE.dataLabel, ...(style.dataLabel ?? {}) }, - background: { ...DEFAULT_STYLE.background, ...(style.background ?? {}) }, - border: { ...DEFAULT_STYLE.border, ...(style.border ?? {}) }, - animation: { ...DEFAULT_STYLE.animation, ...(style.animation ?? {}) }, - }; -} - export interface ChartRendererProps { chart: ChartInstance; data: Record[]; } export const ChartRenderer: React.FC = ({ chart, data }) => { - const safeChart = useMemo(() => ({ - ...chart, - style: ensureStyle(chart.style), - }), [chart]); + // Use JSON key to force recalculation when any chart property changes + const chartKey = JSON.stringify({ type: chart.type, bindings: chart.bindings, style: chart.style }); const echartsOption = useMemo(() => { - if (safeChart.type === 'kpi' || safeChart.type === 'data-table') return null; + if (chart.type === 'kpi' || chart.type === 'data-table') return null; + if (!data.length) return null; try { - return chartRenderer.build(safeChart, data); - } catch { + return chartRenderer.build(chart, data); + } catch (e) { + console.warn('ECharts build error:', e); return null; } - }, [safeChart, data]); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [chartKey, data]); - switch (safeChart.type) { + switch (chart.type) { case 'kpi': - return ; + return ; case 'data-table': - return ; + return ; default: - return echartsOption ? :
请绑定数据字段
; + return echartsOption + ? + :
请绑定数据字段
; } };