修改
This commit is contained in:
@@ -12,62 +12,120 @@ export default {
|
||||
// 1. 重命名 props:ref → chartRef,避免关键字冲突,同时定义类型和默认值
|
||||
chartRef: {
|
||||
type: String,
|
||||
required: true, // 强制父组件传值,避免获取不到 DOM
|
||||
default: () =>'pieChartRef' // 默认空数组,避免报错
|
||||
|
||||
// validator: (value) => {
|
||||
// // 验证:ref 名不能为空,确保有效
|
||||
// return value.trim() !== '';
|
||||
// }
|
||||
default: 'pieChartRef' // 默认ref名称
|
||||
},
|
||||
pieData: {
|
||||
type: Object,
|
||||
default: () => { } // 默认空数组,避免报错
|
||||
chartData: {
|
||||
type: Array, // 明确类型为数组(接收[{name, rate, value}, ...])
|
||||
default: () => [] // 默认空数组,避免报错
|
||||
},
|
||||
chartTitle: { // 新增:动态标题(可选,灵活配置)
|
||||
type: String,
|
||||
default: '客户销量分析'
|
||||
},
|
||||
unit: { // 新增:动态单位(可选)
|
||||
type: String,
|
||||
default: '万m²'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
return {
|
||||
// 提取公共颜色配置,复用样式
|
||||
customColors: [
|
||||
'rgba(39, 96, 255, 1)',
|
||||
'rgba(40, 138, 255, 1)',
|
||||
'rgba(118, 218, 190, 1)',
|
||||
'rgba(255, 206, 106, 1)',
|
||||
'rgba(255, 123, 123, 1)', // 额外补充颜色,适配更多数据项
|
||||
'rgba(153, 102, 255, 1)'
|
||||
],
|
||||
myChart: null // 保存图表实例,便于销毁和缩放
|
||||
};
|
||||
},
|
||||
computed: {},
|
||||
watch: {
|
||||
// 监听 pieData 变化,只要数据变了,就更新图表
|
||||
pieData: {
|
||||
// 监听 chartData 变化,只要数据变了,就更新图表
|
||||
chartData: {
|
||||
handler() {
|
||||
this.initData(); // 直接调用更新,无需判断 myChart 是否存在
|
||||
this.initData(); // 直接调用更新
|
||||
},
|
||||
deep: true,
|
||||
deep: true, // 深度监听数组/对象变化
|
||||
immediate: true // 初始化时立即执行
|
||||
},
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
this.initData(); // 只负责初始化图表实例
|
||||
this.initData(); // 初始化图表
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
initData() {
|
||||
console.log(this.pieData,'this.pieData.value');
|
||||
console.log('动态饼图数据:', this.chartData);
|
||||
|
||||
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)',
|
||||
];
|
||||
// 销毁旧实例,避免内存泄漏
|
||||
if (this.myChart) {
|
||||
this.myChart.dispose();
|
||||
}
|
||||
// 初始化新实例
|
||||
this.myChart = echarts.init(chartDom);
|
||||
|
||||
// ========== 核心:动态生成饼图数据 ==========
|
||||
const dynamicPieData = this.chartData.map((item, index) => {
|
||||
const color = this.customColors[index % this.customColors.length]; // 循环取色,适配多数据项
|
||||
return {
|
||||
name: item.name, // 动态名称(产品1/产品2/客户1等)
|
||||
value: item.value || 0, // 动态数值
|
||||
rate: item.rate || 0, // 动态占比(备用)
|
||||
// 标签样式(复用原有格式,动态匹配颜色)
|
||||
label: {
|
||||
normal: {
|
||||
align: 'left',
|
||||
distanceToLabelLine: 2,
|
||||
formatter: (params) => [
|
||||
`{b|${params.value.toLocaleString()}}`, // 数值(格式化千分位)
|
||||
`{hr|■}{c|${params.name}}` // 名称 + 颜色标识
|
||||
].join('\n'),
|
||||
rich: {
|
||||
hr: {
|
||||
color: color,
|
||||
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: color },
|
||||
length: 10,
|
||||
length2: 20,
|
||||
},
|
||||
// 扇区样式(动态匹配颜色)
|
||||
itemStyle: { color: color }
|
||||
};
|
||||
});
|
||||
|
||||
// 图表配置项
|
||||
const option = {
|
||||
// 标题配置(主标题+副标题)
|
||||
// 动态标题(支持父组件传递)
|
||||
title: [
|
||||
{
|
||||
text: '客户销量分析',
|
||||
text: this.chartTitle,
|
||||
left: 'center',
|
||||
top: '35%',
|
||||
textStyle: {
|
||||
@@ -78,7 +136,7 @@ export default {
|
||||
}
|
||||
},
|
||||
{
|
||||
text: '单位:万m²',
|
||||
text: `单位:${this.unit}`,
|
||||
left: 'center',
|
||||
top: '50%',
|
||||
textStyle: {
|
||||
@@ -112,175 +170,32 @@ export default {
|
||||
length: 0,
|
||||
length2: 10,
|
||||
lineStyle: {
|
||||
color: (params) => customColors[params.dataIndex]
|
||||
// 若未单独配置标签线颜色,默认取对应数据项的颜色
|
||||
color: (params) => this.customColors[params.dataIndex % this.customColors.length]
|
||||
}
|
||||
},
|
||||
itemStyle: {
|
||||
color: (params) => customColors[params.dataIndex]
|
||||
// 若未单独配置扇区颜色,默认取对应数据项的颜色
|
||||
color: (params) => this.customColors[params.dataIndex % this.customColors.length]
|
||||
},
|
||||
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)' }
|
||||
}
|
||||
]
|
||||
data: dynamicPieData // 使用动态生成的数据,替代硬编码数据
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
option && myChart.setOption(option);
|
||||
// 设置图表配置
|
||||
option && this.myChart.setOption(option);
|
||||
|
||||
// 窗口缩放监听
|
||||
window.addEventListener('resize', () => {
|
||||
myChart.resize();
|
||||
});
|
||||
// 窗口缩放监听(优化:避免重复绑定)
|
||||
const resizeHandler = () => {
|
||||
this.myChart && this.myChart.resize();
|
||||
};
|
||||
window.addEventListener('resize', resizeHandler);
|
||||
|
||||
// 组件销毁清理
|
||||
this.$once('hook:destroyed', () => {
|
||||
window.removeEventListener('resize', () => {
|
||||
myChart.resize();
|
||||
});
|
||||
myChart.dispose();
|
||||
window.removeEventListener('resize', resizeHandler);
|
||||
this.myChart && this.myChart.dispose();
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user