This commit is contained in:
‘937886381’
2025-11-12 16:56:14 +08:00
commit 1ea62af1d6
1135 changed files with 109385 additions and 0 deletions

View File

@@ -0,0 +1,267 @@
<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,
resizeHandler: null
};
},
props: ["saleAndProductData"],
watch: {
// 监听数据变化,动态更新图表
saleAndProductData: {
handler() {
this.updateChart();
},
deep: true,
immediate: true
}
},
mounted() {
this.$nextTick(() => {
this.initChart();
});
},
beforeDestroy() {
// 清理资源
this.myChart && this.myChart.dispose();
window.removeEventListener('resize', this.resizeHandler);
},
methods: {
// 初始化图表实例
initChart() {
const chartDom = this.$refs.cockpitEffChip;
if (!chartDom) {
console.error('图表容器未找到!');
return;
}
this.myChart = echarts.init(chartDom);
this.resizeHandler = () => this.myChart?.resize();
window.addEventListener('resize', this.resizeHandler);
},
// 解析数据提取地名和对应数值统一去掉“基地XX”后缀
parseData() {
// const { saleValues = [], productValues = [], productAndSaleRates = [] } = this.saleAndProductData || {};
const xData = []; // 统一X轴地名
const saleData = []; // 销量数据
const productData = []; // 产量数据
const rateData = []; // 产销率数据(转为百分比)
// 第一步:提取所有地名(以销量数据为准,其他数据按地名匹配)
if (Array.isArray(this.saleAndProductData) && this.saleAndProductData.length) {
this.saleAndProductData.forEach(item => {
// const key = Object.keys(item)[0];
const place = item.name.replace('分公司', ''); // 提取地名(如“宜兴基地销量”→“宜兴”)
xData.push(place);
saleData.push(item.saleValue); // 销量值(保留两位小数)
productData.push(item.productValue);
rateData.push(item.saleAndProductProportion *100 ); // 转为百分比后保留两位小数
});
}
// // 第二步匹配产量数据按X轴地名顺序
// if (Array.isArray(productValues) && productValues.length) {
// xData.forEach(place => {
// const targetItem = productValues.find(item => {
// const key = Object.keys(item)[0];
// return key.includes(place); // 匹配包含该地名的产量键
// });
// productData.push(targetItem ? (Number(targetItem[Object.keys(targetItem)[0]]).toFixed(2) * 1) : 0);
// });
// }
// // 第三步:匹配产销率数据(转为百分比,保留两位小数)
// if (Array.isArray(productAndSaleRates) && productAndSaleRates.length) {
// xData.forEach(place => {
// const targetItem = productAndSaleRates.find(item => {
// const key = Object.keys(item)[0];
// return key.includes(place); // 匹配包含该地名的产销率键
// });
// const rate = targetItem ? (Number(targetItem[Object.keys(targetItem)[0]]).toFixed(4) * 100) : 0;
// rateData.push(rate.toFixed(2) * 1); // 转为百分比后保留两位小数
// });
// }
return { xData, saleData, productData, rateData };
},
// 动态更新图表
updateChart() {
if (!this.myChart) return;
// 解析数据
const { xData, saleData, productData, rateData } = this.parseData();
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 === '产销率' ? '%' : '万㎡';
html += `${item.marker} ${item.seriesName}: ${item.value ? item.value :0}${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 // 动态X轴统一地名
}
],
yAxis: [
{
type: 'value',
name: '万㎡',
nameTextStyle: {
color: 'rgba(0, 0, 0, 0.45)',
fontSize: 12,
align: 'right'
},
min: 0,
max: (value) => value.max > 0 ? Math.ceil(value.max * 1.1) : 10,
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
},
{
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: [
// 1. 产销率折线图右侧Y轴
{
name: '产销率',
type: 'line',
yAxisIndex: 1,
lineStyle: {
color: 'rgba(40, 138, 255, .5)',
width: 2
},
itemStyle: {
color: 'rgba(40, 138, 255, 1)',
borderColor: 'rgba(40, 138, 255, 1)',
borderWidth: 2,
radius: 4
},
areaStyle: {
opacity: 0.2,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: 'rgba(40, 138, 255, .9)' },
{ offset: 1, color: 'rgba(255, 132, 0, 0)' }
])
},
data: rateData, // 动态产销率数据
symbol: 'circle',
symbolSize: 6
},
// 2. 销量柱状图左侧Y轴
{
name: '销量',
type: 'bar',
yAxisIndex: 0,
barWidth: 24,
itemStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{ offset: 0, color: 'rgba(130, 204, 255, 1)' },
{ offset: 1, color: 'rgba(75, 157, 255, 1)' }
]
},
borderRadius: [4, 4, 0, 0],
borderWidth: 0
},
data: saleData // 动态销量数据
},
// 3. 产量柱状图左侧Y轴
{
name: '产量',
type: 'bar',
yAxisIndex: 0,
barWidth: 24,
itemStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{ offset: 0, color: 'rgba(174, 239, 224, 1)' },
{ offset: 1, color: 'rgba(118, 218, 190, 1)' }
]
},
borderRadius: [4, 4, 0, 0],
borderWidth: 0
},
data: productData // 动态产量数据
}
]
};
this.myChart.setOption(option);
}
},
};
</script>