187 lines
5.0 KiB
Vue
187 lines
5.0 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: ["stockValues"],
|
||
watch: {
|
||
// 监听 stockValues 变化,动态更新图表
|
||
stockValues: {
|
||
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);
|
||
},
|
||
|
||
// 解析 stockValues:提取地名和对应库存值
|
||
parseStockData() {
|
||
const xData = []; // X轴地名
|
||
const data = []; // 对应库存值
|
||
|
||
if (Array.isArray(this.stockValues) && this.stockValues.length) {
|
||
this.stockValues.forEach(item => {
|
||
// 获取对象的唯一键(如“宜兴基地库存”)
|
||
// const key = Object.keys(item)[0];
|
||
// 提取地名:去掉“基地库存”后缀(如“宜兴基地库存”→“宜兴”)
|
||
const place = item.name.replace('分公司', '');
|
||
// 获取库存值(保留两位小数,避免精度问题)
|
||
const value = item.stockValue
|
||
|
||
xData.push(place);
|
||
data.push(value);
|
||
});
|
||
}
|
||
|
||
return { xData, data };
|
||
},
|
||
|
||
// 更新图表(核心:动态渲染数据)
|
||
updateChart() {
|
||
if (!this.myChart) return;
|
||
|
||
// 解析数据
|
||
const { xData, data } = this.parseStockData();
|
||
|
||
const option = {
|
||
tooltip: {
|
||
trigger: 'axis',
|
||
axisPointer: {
|
||
type: 'cross',
|
||
label: {
|
||
backgroundColor: '#6a7985'
|
||
}
|
||
},
|
||
formatter: (params) => {
|
||
let html = `${params[0].axisValue}<br/>`;
|
||
params.forEach(item => {
|
||
html += `${item.marker} 库存: ${item.value} 万㎡<br/>`;
|
||
});
|
||
return html;
|
||
}
|
||
},
|
||
grid: {
|
||
top: 30,
|
||
bottom: 30,
|
||
right: 20,
|
||
left: 60,
|
||
},
|
||
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, // 无数据时默认最大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
|
||
}
|
||
],
|
||
series: [
|
||
{
|
||
name: '库存',
|
||
type: 'bar',
|
||
yAxisIndex: 0,
|
||
barWidth: 24,
|
||
label: {
|
||
show: true,
|
||
position: 'top',
|
||
textStyle: {
|
||
color: 'rgba(11, 88, 255, 1)',
|
||
fontSize: 14
|
||
}
|
||
},
|
||
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: data // 动态库存数据(解析后的值)
|
||
}
|
||
]
|
||
};
|
||
|
||
this.myChart.setOption(option);
|
||
},
|
||
|
||
// 窗口缩放处理函数
|
||
resizeHandler() {
|
||
this.myChart && this.myChart.resize();
|
||
}
|
||
},
|
||
};
|
||
</script>
|