174 lines
4.6 KiB
Vue
174 lines
4.6 KiB
Vue
<template>
|
||
<div ref="cockpitEffChip" id="coreLineChart" style="width: 100%; height: 400px;"></div>
|
||
</template>
|
||
<script>
|
||
import * as echarts from 'echarts';
|
||
|
||
export default {
|
||
components: {},
|
||
data() {
|
||
return {
|
||
myChart: null // 存储图表实例,避免重复创建
|
||
};
|
||
},
|
||
props: {
|
||
// 明确接收的props结构,增强可读性
|
||
chartData: {
|
||
type: Object,
|
||
default: () => ({
|
||
series: [],
|
||
allPlaceNames: []
|
||
}),
|
||
// 校验数据格式
|
||
validator: (value) => {
|
||
return Array.isArray(value.series) && Array.isArray(value.allPlaceNames);
|
||
}
|
||
}
|
||
},
|
||
mounted() {
|
||
this.$nextTick(() => {
|
||
this.updateChart();
|
||
});
|
||
},
|
||
|
||
// 新增:监听 chartData 变化
|
||
watch: {
|
||
// 深度监听数据变化,仅更新图表配置(不销毁实例)
|
||
chartData: {
|
||
handler() {
|
||
console.log(this.chartData,'chartData');
|
||
|
||
this.updateChart();
|
||
},
|
||
deep: true,
|
||
immediate: true // 初始化时立即执行
|
||
}
|
||
},
|
||
methods: {
|
||
updateChart() {
|
||
const chartDom = this.$refs.cockpitEffChip;
|
||
if (!chartDom) {
|
||
console.error('图表容器未找到!');
|
||
return;
|
||
}
|
||
|
||
if (this.myChart) {
|
||
this.myChart.dispose();
|
||
}
|
||
|
||
this.myChart = echarts.init(chartDom);
|
||
const { allPlaceNames, series } = this.chartData || {};
|
||
|
||
// 处理空数据
|
||
const xData = allPlaceNames || [];
|
||
const chartSeries = series || []; // 父组件传递的 series
|
||
|
||
const option = {
|
||
tooltip: {
|
||
trigger: 'axis',
|
||
axisPointer: {
|
||
type: 'cross',
|
||
label: {
|
||
backgroundColor: '#6a7985'
|
||
}
|
||
},
|
||
// formatter: (params) => {
|
||
// let html = `${params[0].axisValue}<br/>`;
|
||
// params.forEach(item => {
|
||
// const unit = item.seriesName === '完成率' ? '%' : (
|
||
// ['产量', '销量'].includes(this.$parent.selectedProfit) ? '片' : '万元'
|
||
// );
|
||
// html += `${item.marker} ${item.seriesName}: ${item.value}${unit}<br/>`;
|
||
// });
|
||
// return html;
|
||
// }
|
||
},
|
||
grid: {
|
||
top: 30,
|
||
bottom: 30,
|
||
right: 70,
|
||
left: 40,
|
||
},
|
||
xAxis: [
|
||
{
|
||
type: 'category',
|
||
boundaryGap: true,
|
||
axisTick: { show: false },
|
||
axisLine: {
|
||
show: true,
|
||
lineStyle: { color: 'rgba(0, 0, 0, 0.15)' }
|
||
},
|
||
axisLabel: {
|
||
color: 'rgba(0, 0, 0, 0.45)',
|
||
fontSize: 12,
|
||
interval: 0,
|
||
padding: [5, 0, 0, 0]
|
||
},
|
||
data: xData
|
||
}
|
||
],
|
||
yAxis: [
|
||
// 左侧Y轴:营业收入、成本(单位万元)
|
||
{
|
||
type: 'value',
|
||
name: '万元',
|
||
nameTextStyle: {
|
||
color: 'rgba(0, 0, 0, 0.45)',
|
||
fontSize: 12,
|
||
align: 'right'
|
||
},
|
||
min: 0,
|
||
max: (value) => Math.ceil((value.max || 0) * 1.1),
|
||
scale: false,
|
||
axisTick: { show: false },
|
||
axisLabel: {
|
||
color: 'rgba(0, 0, 0, 0.45)',
|
||
fontSize: 12,
|
||
formatter: '{value}'
|
||
},
|
||
splitLine: { lineStyle: { color: 'rgba(0, 0, 0, 0.15)' } },
|
||
axisLine: { lineStyle: { color: 'rgba(0, 0, 0, 0.15)' } },
|
||
splitNumber: 4
|
||
},
|
||
// 右侧Y轴:利润占比(百分比)
|
||
{
|
||
type: 'value',
|
||
nameTextStyle: {
|
||
color: 'rgba(0, 0, 0, 0.45)',
|
||
fontSize: 12,
|
||
align: 'left'
|
||
},
|
||
// min: 0,
|
||
// max: 100,
|
||
axisTick: { show: false },
|
||
axisLabel: {
|
||
color: 'rgba(0, 0, 0, 0.45)',
|
||
fontSize: 12,
|
||
formatter: '{value}%'
|
||
},
|
||
splitLine: { show: false },
|
||
axisLine: { lineStyle: { color: 'rgba(0, 0, 0, 0.15)' } },
|
||
splitNumber: 4
|
||
}
|
||
],
|
||
series: chartSeries // 直接使用父组件传递的 series
|
||
};
|
||
|
||
option && this.myChart.setOption(option);
|
||
|
||
// 窗口缩放适配和销毁逻辑保持不变
|
||
window.addEventListener('resize', () => {
|
||
this.myChart && this.myChart.resize();
|
||
});
|
||
|
||
this.$once('hook:destroyed', () => {
|
||
window.removeEventListener('resize', () => {
|
||
this.myChart && this.myChart.resize();
|
||
});
|
||
this.myChart && this.myChart.dispose();
|
||
});
|
||
}
|
||
},
|
||
};
|
||
</script>
|