120 lines
2.7 KiB
TypeScript
120 lines
2.7 KiB
TypeScript
import * as echarts from 'echarts';
|
|
import type { ECharts, EChartsOption } from 'echarts';
|
|
|
|
export interface ChartDataItem {
|
|
name: string;
|
|
value: number;
|
|
key: string;
|
|
}
|
|
|
|
export function usePieChart(
|
|
chartRefs: Map<string, HTMLElement>,
|
|
chartData: { value: ChartDataItem[] },
|
|
tabIndex: { value: string },
|
|
typeMap: Record<string, string>,
|
|
legendCallback?: (e: any) => void
|
|
) {
|
|
let chartInstance: ECharts | null = null;
|
|
|
|
const initChart = (retryCount = 0) => {
|
|
const dom = chartRefs.get(tabIndex.value);
|
|
if (!dom) {
|
|
if (retryCount < 10) {
|
|
setTimeout(() => initChart(retryCount + 1), 100);
|
|
}
|
|
return;
|
|
}
|
|
|
|
const rect = dom.getBoundingClientRect();
|
|
if (rect.width === 0 || rect.height === 0) {
|
|
if (retryCount < 10) {
|
|
setTimeout(() => initChart(retryCount + 1), 100);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (!chartInstance) {
|
|
chartInstance = echarts.init(dom);
|
|
}
|
|
|
|
const option: EChartsOption = {
|
|
tooltip: {
|
|
trigger: 'item',
|
|
formatter: (params: any) => `${params.marker} ${params.name}: ${params.value}(次)`
|
|
},
|
|
legend: {
|
|
orient: 'vertical',
|
|
right: 10,
|
|
top: 80,
|
|
textStyle: { fontSize: 12 }
|
|
},
|
|
series: []
|
|
};
|
|
|
|
if (!chartData.value || chartData.value.length === 0) {
|
|
chartInstance.setOption(option, true);
|
|
return;
|
|
}
|
|
|
|
const total = chartData.value.reduce((acc: number, item: ChartDataItem) => acc + (item.value || 0), 0);
|
|
const titleText = typeMap[tabIndex.value] || '识别(次)';
|
|
|
|
option.series = [
|
|
{
|
|
type: 'pie',
|
|
radius: ['26%', '35%'],
|
|
center: ['35%', '50%'],
|
|
avoidLabelOverlap: false,
|
|
label: {
|
|
show: true,
|
|
formatter: '{c}'
|
|
},
|
|
labelLine: {
|
|
show: true,
|
|
length: 12,
|
|
length2: 12
|
|
},
|
|
data: chartData.value.map((item: ChartDataItem) => ({
|
|
name: item.name,
|
|
value: item.value
|
|
}))
|
|
}
|
|
];
|
|
|
|
option.title = {
|
|
text: String(total),
|
|
left: '34%',
|
|
top: '44%',
|
|
textAlign: 'center',
|
|
textStyle: {
|
|
fontSize: 24,
|
|
fontWeight: 'bold',
|
|
color: '#333'
|
|
},
|
|
subtext: titleText,
|
|
subtextStyle: {
|
|
fontSize: 12,
|
|
color: '#333'
|
|
}
|
|
};
|
|
|
|
chartInstance.setOption(option, true);
|
|
|
|
if (legendCallback) {
|
|
chartInstance.off('legendselectchanged');
|
|
chartInstance.on('legendselectchanged', legendCallback);
|
|
}
|
|
};
|
|
|
|
const dispose = () => {
|
|
chartInstance?.dispose();
|
|
chartInstance = null;
|
|
};
|
|
|
|
const resize = () => {
|
|
chartInstance?.resize();
|
|
};
|
|
|
|
return { initChart, dispose, resize };
|
|
}
|