2025-04-16 23:06:01 +08:00
|
|
|
<template>
|
|
|
|
|
<div style="height:100%;width:100%" :id="echartsId"></div>
|
|
|
|
|
</template>
|
|
|
|
|
<script setup>
|
|
|
|
|
import * as echarts from "echarts";
|
2025-12-27 11:10:31 +08:00
|
|
|
import { onMounted, ref, reactive, defineProps, onUnmounted, watch, nextTick } from "vue";
|
2025-04-16 23:06:01 +08:00
|
|
|
const props = defineProps({
|
|
|
|
|
echartsId:{
|
|
|
|
|
type:String,
|
2025-12-27 11:10:31 +08:00
|
|
|
default:'3DbarId'
|
2025-04-16 23:06:01 +08:00
|
|
|
},
|
2025-12-27 11:10:31 +08:00
|
|
|
data:{
|
|
|
|
|
type:Array,
|
|
|
|
|
default:[]
|
2025-04-16 23:06:01 +08:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2025-12-27 11:10:31 +08:00
|
|
|
// 保存echarts实例
|
|
|
|
|
const myChart = ref(null);
|
2025-04-16 23:06:01 +08:00
|
|
|
|
2025-12-27 11:10:31 +08:00
|
|
|
// 定义resize处理函数
|
|
|
|
|
const handleResize = () => {
|
|
|
|
|
if (myChart.value) {
|
|
|
|
|
myChart.value.resize();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
function chartFn() {
|
|
|
|
|
// 如果已有实例,先销毁
|
|
|
|
|
if (myChart.value) {
|
|
|
|
|
myChart.value.dispose();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 创建新实例
|
|
|
|
|
myChart.value = echarts.init(document.getElementById(props.echartsId));
|
|
|
|
|
|
|
|
|
|
// 处理数据
|
|
|
|
|
const sideData1 = props.data.map(v => {
|
|
|
|
|
return {
|
|
|
|
|
value: v.value * 1.2,
|
|
|
|
|
itemStyle: {
|
|
|
|
|
color: v.color || '#1bd6c2'
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const topData1 = props.data.map(v => {
|
|
|
|
|
return {
|
|
|
|
|
value: v.value + 0.1,
|
|
|
|
|
itemStyle: {
|
|
|
|
|
color: v.color || '#1bd6c2'
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const option = {
|
2025-04-16 23:06:01 +08:00
|
|
|
grid: {
|
2025-12-27 11:10:31 +08:00
|
|
|
top: '8%',
|
|
|
|
|
left: '2%',
|
|
|
|
|
right: '2%',
|
|
|
|
|
bottom: '12%',
|
2025-04-16 23:06:01 +08:00
|
|
|
containLabel: true
|
|
|
|
|
},
|
2025-12-27 11:10:31 +08:00
|
|
|
tooltip: {
|
|
|
|
|
trigger: 'axis',
|
|
|
|
|
axisPointer: {
|
|
|
|
|
lineStyle: {
|
|
|
|
|
color: '#ddd'
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
backgroundColor: 'rgba(255,255,255,1)',
|
|
|
|
|
padding: [5, 10],
|
|
|
|
|
textStyle: {
|
|
|
|
|
color: '#7588E4'
|
|
|
|
|
},
|
|
|
|
|
extraCssText: 'box-shadow: 0 0 5px rgba(0,0,0,0.3)'
|
2025-04-16 23:06:01 +08:00
|
|
|
},
|
2025-12-27 11:10:31 +08:00
|
|
|
xAxis: {
|
|
|
|
|
type: 'category',
|
|
|
|
|
data: props.data.map(v => v.label),
|
|
|
|
|
axisTick: {
|
|
|
|
|
show: false
|
|
|
|
|
},
|
|
|
|
|
axisLine: {
|
|
|
|
|
show: false
|
|
|
|
|
},
|
|
|
|
|
axisLabel: {
|
|
|
|
|
show: true,
|
|
|
|
|
color: '#fff',
|
|
|
|
|
interval: 0
|
2025-04-16 23:06:01 +08:00
|
|
|
}
|
2025-12-27 11:10:31 +08:00
|
|
|
},
|
|
|
|
|
yAxis: {
|
|
|
|
|
type: 'value',
|
|
|
|
|
splitLine: {
|
|
|
|
|
show: true,
|
|
|
|
|
lineStyle: {
|
|
|
|
|
type: 'dashed',
|
|
|
|
|
color: 'rgba(14,95,255,0.5)'
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
axisTick: {
|
|
|
|
|
show: false
|
|
|
|
|
},
|
|
|
|
|
axisLine: {
|
|
|
|
|
show: false
|
|
|
|
|
},
|
|
|
|
|
axisLabel: {
|
|
|
|
|
color: '#fff'
|
2025-04-16 23:06:01 +08:00
|
|
|
}
|
2025-12-27 11:10:31 +08:00
|
|
|
},
|
2025-04-16 23:06:01 +08:00
|
|
|
series: [
|
|
|
|
|
{
|
|
|
|
|
type: 'bar',
|
2025-12-27 11:10:31 +08:00
|
|
|
data: props.data.map(v => v.value),
|
|
|
|
|
barWidth: '22', // 柱子的宽度
|
|
|
|
|
z: 1,
|
2025-04-16 23:06:01 +08:00
|
|
|
itemStyle: {
|
2025-12-27 11:10:31 +08:00
|
|
|
color: '#004056' // 底部柱子的颜色
|
2025-04-16 23:06:01 +08:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
type: 'bar',
|
|
|
|
|
data: sideData1,
|
2025-12-27 11:10:31 +08:00
|
|
|
barWidth: '22', // 柱子的宽度
|
|
|
|
|
z: 2,
|
|
|
|
|
itemStyle: {
|
|
|
|
|
color: function(params) {
|
|
|
|
|
return params.data.itemStyle.color || '#1bd6c2';
|
2025-04-16 23:06:01 +08:00
|
|
|
}
|
|
|
|
|
}
|
2025-12-27 11:10:31 +08:00
|
|
|
},
|
2025-04-16 23:06:01 +08:00
|
|
|
{
|
2025-12-27 11:10:31 +08:00
|
|
|
type: 'scatter',
|
|
|
|
|
data: topData1,
|
2025-04-16 23:06:01 +08:00
|
|
|
itemStyle: {
|
|
|
|
|
borderWidth: 1,
|
|
|
|
|
borderColor: '#fff',
|
2025-12-27 11:10:31 +08:00
|
|
|
color: function(params) {
|
|
|
|
|
return params.data.itemStyle.color || '#1bd6c2';
|
|
|
|
|
}
|
2025-04-16 23:06:01 +08:00
|
|
|
},
|
|
|
|
|
symbol: 'path://M 0,0 l 90,0 l -60,60 l -90,0 z',
|
2025-12-27 11:10:31 +08:00
|
|
|
symbolSize: ['22', '12'],
|
|
|
|
|
symbolOffset: ['-0', '-6'],
|
2025-04-16 23:06:01 +08:00
|
|
|
symbolRotate: -30,
|
|
|
|
|
symbolPosition: 'end',
|
|
|
|
|
barGap: 0,
|
|
|
|
|
data: sideData1,
|
|
|
|
|
z: 3,
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
};
|
2025-12-27 11:10:31 +08:00
|
|
|
|
|
|
|
|
option && myChart.value.setOption(option);
|
2025-04-16 23:06:01 +08:00
|
|
|
}
|
2025-12-27 11:10:31 +08:00
|
|
|
|
|
|
|
|
// 监听数据变化
|
|
|
|
|
watch(() => props.data, val => {
|
|
|
|
|
nextTick(() => { chartFn() })
|
|
|
|
|
}, { immediate: true, deep: true })
|
|
|
|
|
|
|
|
|
|
// 组件挂载时初始化图表并添加事件监听
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
chartFn();
|
|
|
|
|
window.addEventListener('resize', handleResize);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 组件卸载时清理资源
|
|
|
|
|
onUnmounted(() => {
|
|
|
|
|
if (myChart.value) {
|
|
|
|
|
myChart.value.dispose();
|
|
|
|
|
myChart.value = null;
|
|
|
|
|
}
|
|
|
|
|
window.removeEventListener('resize', handleResize);
|
|
|
|
|
});
|
2025-04-16 23:06:01 +08:00
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
|
|
|
|
|
|
</style>
|