This commit is contained in:
‘937886381’
2025-12-30 09:04:48 +08:00
parent 80deffbb42
commit 7b3873f9ea
232 changed files with 13127 additions and 17011 deletions

View File

@@ -12,62 +12,120 @@ export default {
// 1. 重命名 propsref → 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();
});
}
},