46 lines
1.6 KiB
TypeScript
46 lines
1.6 KiB
TypeScript
'use client';
|
|
|
|
import React, { useMemo } from 'react';
|
|
import { type ChartInstance } from '@/domain/entities/ChartInstance';
|
|
import { chartRenderer } from '@/frameworks/di/container';
|
|
import { EChartsBase } from './EChartsBase';
|
|
import { KPICard } from './KPICard';
|
|
import { DataTable } from './DataTable';
|
|
|
|
export interface ChartRendererProps {
|
|
chart: ChartInstance;
|
|
data: Record<string, any>[];
|
|
}
|
|
|
|
export const ChartRenderer: React.FC<ChartRendererProps> = ({ chart, data }) => {
|
|
// 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 (chart.type === 'kpi' || chart.type === 'data-table') return null;
|
|
if (!data.length) return null;
|
|
try {
|
|
return chartRenderer.build(chart, data);
|
|
} catch (e) {
|
|
console.warn('ECharts build error:', e);
|
|
return null;
|
|
}
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [chartKey, data]);
|
|
|
|
switch (chart.type) {
|
|
case 'kpi':
|
|
return <KPICard chart={chart} data={data} />;
|
|
case 'data-table':
|
|
return <DataTable chart={chart} data={data} />;
|
|
default:
|
|
const borderRadius = chart.style?.background?.borderRadius ?? 0;
|
|
const overflow = borderRadius > 0 ? 'hidden' as const : undefined;
|
|
return echartsOption
|
|
? <EChartsBase option={echartsOption} style={{ width: '100%', height: '100%', minHeight: 250, borderRadius, overflow }} />
|
|
: <div style={{ padding: 16, color: '#999', textAlign: 'center' }}>请绑定数据字段</div>;
|
|
}
|
|
};
|
|
|
|
export default ChartRenderer;
|