1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
| <template>
| <div ref="chartRef" class="pie-chart-container"></div>
| </template>
|
| <script setup>
| import * as echarts from 'echarts/core';
| import { CanvasRenderer } from 'echarts/renderers';
| import { PieChart } from 'echarts/charts';
| import { ref, onMounted, onBeforeUnmount, watch, nextTick } from 'vue';
| import { LegendComponent } from 'echarts/components';
| import { TooltipComponent } from 'echarts/components';
| // 注册ECharts组件
| echarts.use([CanvasRenderer, PieChart,LegendComponent,TooltipComponent ]);
|
| // 定义组件属性
| const props = defineProps({
| data: {
| type: Array,
| required: true,
| default: () => [
| { value: 111, name: '已取消' },
| { value: 735, name: '已完成' }
| ]
| },
| options: {
| type: Object,
| default: () => ({
| tooltip: { trigger: 'item' },
| legend: { top: '5%', left: 'center' }
| })
| }
| });
|
| const chartRef = ref(null);
| let chartInstance = null;
|
| // 初始化图表
| const initChart = () => {
| if (!chartRef.value) return;
|
| chartInstance = echarts.init(chartRef.value);
| chartInstance.setOption({
| tooltip: {
| trigger: 'item'
| },
| legend: {
| top: '5%',
| left: 'center'
| },
| series: [{
| name: '今日任务数据',
| type: 'pie',
| radius: ['40%', '70%'],
| avoidLabelOverlap: false,
| padAngle: 5,
| itemStyle: {
| borderRadius: 10
| },
| labelLine: {
| show: false
| },
| data: props.data,
| label: { show: false },
| emphasis: { label: { show: true, fontSize: 18, fontWeight: 'bold' ,formatter: '{b}: {c}'} },
| ...props.options.series?.[0]
| }]
| });
|
| // 响应式处理
| const resizeHandler = debounce(() => chartInstance.resize(), 300);
| window.addEventListener('resize', resizeHandler);
| };
|
| // 清理资源
| const cleanup = () => {
| if (chartInstance) {
| chartInstance.dispose();
| chartInstance = null;
| }
| window.removeEventListener('resize', cleanup);
| };
|
| // 监听数据变化
| watch(() => props.data, (newData) => {
| nextTick(() => {
| if (chartInstance) {
| chartInstance.setOption({ series: [{ data: newData }] });
| }
| });
| }, { deep: true });
|
| onMounted(() => {
| nextTick(initChart);
| });
|
| onBeforeUnmount(() => {
| cleanup();
| });
|
| // 防抖函数
| function debounce(fn, delay) {
| let timer;
| return () => {
| clearTimeout(timer);
| timer = setTimeout(fn, delay);
| };
| }
| </script>
|
| <style scoped>
| .pie-chart-container {
| width: 100%;
| height: 100%;
| min-height: 400px;
| }
| </style>
|
|