Files
yudao-dev/src/views/home/components/pieChart.vue

296 lines
9.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<!-- 动态绑定 ref使用 props 中的 chartRef而非硬编码 -->
<div :ref="chartRef" id="coreLineChart" style="height: 100%; width: 100%;"></div>
</template>
<script>
import * as echarts from 'echarts';
export default {
name: 'Container',
props: {
// 1. 重命名 propsref → chartRef避免关键字冲突同时定义类型和默认值
chartRef: {
type: String,
required: true, // 强制父组件传值,避免获取不到 DOM
// validator: (value) => {
// // 验证ref 名不能为空,确保有效
// return value.trim() !== '';
// }
},
pieData: {
type: Object,
default: () => { } // 默认空数组,避免报错
},
},
data() {
return {
myChart: null,
resizeHandler: null
};
},
computed: {},
watch: {
// 监听 pieData 变化,只要数据变了,就更新图表
pieData: {
handler() {
this.initData(); // 直接调用更新,无需判断 myChart 是否存在
},
deep: true,
immediate: true // 初始化时立即执行
},
},
mounted() {
this.$nextTick(() => {
this.initChart(); // 只负责初始化图表实例
});
// 注册窗口resize事件使用稳定的引用以便后续移除
this.resizeHandler = () => {
if (this.myChart) {
this.myChart.resize();
}
};
window.addEventListener('resize', this.resizeHandler);
},
methods: {
initData() {
console.log(this.pieData,'this.pieData.value');
const chartDom = this.$refs[this.chartRef];
if (!chartDom) {
console.error(`图表容器未找到!请确认父组件传递的 chartRef 为 "${this.chartRef}"`);
return;
}
const myChart = echarts.init(chartDom);
// 自定义颜色数组(与系列一一对应)
const customColors = [
'rgba(113, 100, 255, 1)',
'rgba(40, 138, 255, 1)',
'rgba(118, 218, 190, 1)',
'rgba(255, 206, 106, 1)',
];
const option = {
// 标题配置(主标题+副标题)
title: [
{
text: '月度',
left: 'center',
top: '35%',
textStyle: {
fontSize: 24,
letterSpacing: 5,
color: 'rgba(0, 0, 0, 0.85)',
fontFamily: 'PingFangSC, PingFang SC'
}
},
{
text: '单位:万m²',
left: 'center',
top: '50%',
textStyle: {
fontSize: 16,
color: 'rgba(0, 0, 0, 0.55)',
fontFamily: 'PingFangSC, PingFang SC'
}
}
],
series: [
{
name: '销量',
type: 'pie',
radius: ['60%', '80%'],
center: ['50%', '50%'],
avoidLabelOverlap: false,
label: {
show: true,
position: 'outside',
distance: 10,
formatter: '{c}万m²\n{b}',
textStyle: {
fontSize: 14,
color: 'rgba(0, 0, 0, 0.7)',
fontFamily: 'PingFangSC, PingFang SC',
lineHeight: 1.5
}
},
labelLine: {
show: true,
length: 0,
length2: 10,
lineStyle: {
color: (params) => customColors[params.dataIndex]
}
},
itemStyle: {
color: (params) => customColors[params.dataIndex]
},
data: [
{
value: this.pieData?.value || 0, name: '单镀面板',
label: {
normal: {
align: 'left',
distanceToLabelLine: 2,
formatter: (params) => [
`{b|${params.value.toLocaleString()}}`,
`{hr|■}{c|${params.name}}`
].join('\n'),
rich: {
hr: {
color: 'rgba(39, 96, 255, 1)',
fontSize: 20,
padding: [26, 8, 0, 0]
},
b: {
color: 'rgba(0, 0, 0, 0.75)',
fontSize: 18,
padding: [0, 0, 0, 0]
},
c: {
color: 'rgba(64, 64, 64, 1)',
fontSize: 14,
padding: [30, 0, 0, -5]
}
}
}
},
labelLine: {
lineStyle: { color: 'rgba(39, 96, 255, 1)' },
length: 10,
length2: 20,
},
itemStyle: { color: 'rgba(39, 96, 255, 1)' }
},
{
value: 735, name: '双镀销量',
label: {
normal: {
align: 'left',
distanceToLabelLine: 2,
formatter: (params) => [
`{b|${params.value.toLocaleString()}}`,
`{hr|■}{c|${params.name}}`
].join('\n'),
rich: {
hr: {
color: 'rgba(40, 138, 255, 1)',
fontSize: 20,
padding: [6, 8, 0, 10]
},
b: {
color: 'rgba(0, 0, 0, 0.75)',
fontSize: 18,
padding: [-30, 0, 0, 30]
},
c: {
color: 'rgba(64, 64, 64, 1)',
fontSize: 14,
padding: [10, 0, 0, -5]
}
}
}
},
labelLine: {
length: 0,
length2: 10,
lineStyle: { color: 'rgba(40, 138, 255, 1)' },
},
itemStyle: { color: 'rgba(40, 138, 255, 1)' }
},
{
value: 580, name: '丝印打孔',
label: {
normal: {
align: 'left',
distanceToLabelLine: 2,
formatter: (params) => [
`{b|${params.value.toLocaleString()}}`,
`{hr|■}{c|${params.name}}`
].join('\n'),
rich: {
hr: {
color: 'rgba(118, 218, 190, 1)',
fontSize: 20,
padding: [36, 5, 0, 0]
},
b: {
color: 'rgba(0, 0, 0, 0.75)',
fontSize: 18,
padding: [0, 10, 0, 0]
},
c: {
color: 'rgba(64, 64, 64, 1)',
fontSize: 14,
padding: [40, -5, 0, 0]
}
}
}
},
labelLine: {
lineStyle: { color: 'rgba(118, 218, 190, 1)' },
length: 0,
length2: 10,
},
itemStyle: { color: 'rgba(118, 218, 190, 1)' }
},
{
value: 484, name: '无印打孔',
label: {
normal: {
align: 'left',
distanceToLabelLine: 2,
formatter: (params) => [
`{b|${params.value.toLocaleString()}}`,
`{hr|■}{c|${params.name}}`
].join('\n'),
rich: {
hr: {
color: 'rgba(255, 206, 106, 1)',
fontSize: 20,
padding: [36, 5, 0, 0]
},
b: {
color: 'rgba(0, 0, 0, 0.75)',
fontSize: 18,
padding: [0, 20, 0, 0]
},
c: {
color: 'rgba(64, 64, 64, 1)',
fontSize: 14,
padding: [40, 15, 0, 0]
}
}
}
},
labelLine: {
lineStyle: { color: 'rgba(255, 206, 106, 1)' },
length: 10,
length2: 10,
},
itemStyle: { color: 'rgba(255, 206, 106, 1)' }
}
]
}
]
};
option && this.myChart.setOption(option);
}
},
beforeDestroy() {
// 移除窗口resize事件监听器
if (this.resizeHandler) {
window.removeEventListener('resize', this.resizeHandler);
this.resizeHandler = null;
}
// 销毁图表实例
if (this.myChart) {
this.myChart.dispose();
this.myChart = null;
}
}
};
</script>