- 各页面 useCallback/useMemo 依赖补全(modal/mutation/setter 等),避免闭包过期 - ECharts 使用 optionRef、MainLayout 缓存菜单转换函数、main.tsx 增加挂载点校验 - 学生同步结果改用 recordsCount 展示
80 lines
1.9 KiB
TypeScript
80 lines
1.9 KiB
TypeScript
import React, { useEffect, useRef } from 'react';
|
|
import * as echarts from 'echarts/core';
|
|
import type { EChartsType } from 'echarts/core';
|
|
export type EChartsOption = Record<string, unknown>;
|
|
import {
|
|
BarChart,
|
|
CustomChart,
|
|
FunnelChart,
|
|
GaugeChart,
|
|
LineChart,
|
|
PieChart,
|
|
RadarChart,
|
|
ScatterChart,
|
|
} from 'echarts/charts';
|
|
import {
|
|
DataZoomComponent,
|
|
GridComponent,
|
|
LegendComponent,
|
|
RadarComponent,
|
|
TooltipComponent,
|
|
VisualMapComponent,
|
|
} from 'echarts/components';
|
|
import { CanvasRenderer } from 'echarts/renderers';
|
|
|
|
echarts.use([
|
|
BarChart,
|
|
CustomChart,
|
|
FunnelChart,
|
|
GaugeChart,
|
|
LineChart,
|
|
PieChart,
|
|
RadarChart,
|
|
ScatterChart,
|
|
DataZoomComponent,
|
|
GridComponent,
|
|
LegendComponent,
|
|
RadarComponent,
|
|
TooltipComponent,
|
|
VisualMapComponent,
|
|
CanvasRenderer,
|
|
]);
|
|
|
|
interface EChartsProps {
|
|
option: EChartsOption;
|
|
style?: React.CSSProperties;
|
|
className?: string;
|
|
/** 图表实例就绪回调(用于导出图片等场景) */
|
|
onReady?: (chart: EChartsType) => void;
|
|
}
|
|
|
|
const ECharts: React.FC<EChartsProps> = ({ option, style, className, onReady }) => {
|
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
const optionRef = useRef(option);
|
|
optionRef.current = option;
|
|
const onReadyRef = useRef(onReady);
|
|
onReadyRef.current = onReady;
|
|
|
|
useEffect(() => {
|
|
if (!containerRef.current) return;
|
|
const chart = echarts.init(containerRef.current);
|
|
chart.setOption(optionRef.current);
|
|
onReadyRef.current?.(chart);
|
|
const observer = new ResizeObserver(() => chart.resize());
|
|
observer.observe(containerRef.current);
|
|
return () => {
|
|
observer.disconnect();
|
|
chart.dispose();
|
|
};
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
const chart = containerRef.current ? echarts.getInstanceByDom(containerRef.current) : undefined;
|
|
chart?.setOption(option, true);
|
|
}, [option]);
|
|
|
|
return <div ref={containerRef} className={className} style={style} />;
|
|
};
|
|
|
|
export default ECharts;
|