'use client';
import { useMemo } from 'react';
import type { EChartsOption } from 'echarts';
import ReactECharts from 'echarts-for-react';
type TrendChartSeries = {
label: string;
color: string;
fillColor?: string;
values: number[];
variant?: 'line' | 'area';
valueFormatter?: (value: number) => string;
};
type TrendChartProps = {
labels: string[];
series: TrendChartSeries[];
height?: number;
};
const defaultFormatter = (value: number) => value.toLocaleString('zh-CN');
export function TrendChart({ labels, series, height = 220 }: TrendChartProps) {
if (labels.length === 0 || series.length === 0) {
return (
暂无趋势数据
);
}
const option = useMemo(() => {
const maxValue =
Math.max(
1,
...series.flatMap((item) => item.values.map((value) => value || 0)),
) * 1.1;
return {
animationDuration: 500,
animationEasing: 'cubicOut',
grid: {
left: 16,
right: 16,
top: 20,
bottom: 20,
containLabel: true,
},
tooltip: {
trigger: 'axis',
backgroundColor: 'rgba(15, 23, 42, 0.92)',
borderWidth: 0,
textStyle: {
color: '#e2e8f0',
fontSize: 12,
},
},
legend: {
show: false,
},
xAxis: {
type: 'category',
boundaryGap: false,
data: labels,
axisLine: {
lineStyle: {
color: 'rgba(148, 163, 184, 0.24)',
},
},
axisTick: {
show: false,
},
axisLabel: {
color: '#94a3b8',
margin: 14,
},
},
yAxis: {
type: 'value',
min: 0,
max: maxValue,
splitNumber: 4,
axisLabel: {
color: '#94a3b8',
},
splitLine: {
lineStyle: {
color: 'rgba(148, 163, 184, 0.16)',
type: 'dashed',
},
},
},
series: series.map((item) => ({
name: item.label,
type: 'line',
smooth: true,
showSymbol: false,
symbol: 'circle',
symbolSize: 8,
lineStyle: {
color: item.color,
width: 3,
},
itemStyle: {
color: item.color,
},
areaStyle:
item.variant === 'area'
? {
color: item.fillColor ?? `${item.color}33`,
}
: undefined,
emphasis: {
focus: 'series',
scale: true,
},
data: item.values,
})),
};
}, [labels, series]);
return (
{series.map((item) => {
const latestValue = item.values[item.values.length - 1] ?? 0;
const formatter = item.valueFormatter ?? defaultFormatter;
return (
);
})}
);
}