This commit is contained in:
lcw
2026-04-15 16:04:50 +08:00
parent 763057ed9f
commit fbf259663b
41 changed files with 3651 additions and 2148 deletions

View File

@ -1,67 +1,89 @@
<template>
<div style="height:100%;width:100%" :id="echartsId"></div>
<div style="height: 100%; width: 100%" :id="echartsId"></div>
</template>
<script setup>
import * as echarts from "echarts";
import { onMounted, ref, reactive, defineProps, onUnmounted, watch, nextTick } from "vue";
import {
onMounted,
ref,
reactive,
defineProps,
onUnmounted,
watch,
nextTick,
onBeforeUnmount
} from "vue";
const props = defineProps({
echartsId:{
type:String,
default:'barId'
echartsId: {
type: String,
default: "barId"
},
data:{
type:Object,
default:{
title:'', // 图表标题
color:[], //['#EB00FF','#F57100']
list:[], //[{label:'总数',val:[80,70,60,50]}, {label:'已处置',val:[70,40,30,80]}, ]
xData:[] ,//['09-01','09-02','09-03','09-04']
labelColor:'#000', //横坐标颜色 - 纵坐标颜色 - 标题颜色
rotate:0, //横坐标旋转角度
interval:0, //横坐标间隔
isVertical:false,//是否竖排垂直展示
data: {
type: Object,
default: {
title: "", // 图表标题
color: [], //['#EB00FF','#F57100']
list: [], //[{label:'总数',val:[80,70,60,50]}, {label:'已处置',val:[70,40,30,80]}, ]
xData: [], //['09-01','09-02','09-03','09-04']
labelColor: "#000", //横坐标颜色 - 纵坐标颜色 - 标题颜色
rotate: 0, //横坐标旋转角度
interval: 0, //横坐标间隔
isVertical: false //是否竖排垂直展示
}
},
dataZoom:{
type:Boolean,
default:false
dataZoom: {
type: Boolean,
default: false
},
rotate:{
type:Number,
default:0
rotate: {
type: Number,
default: 0
}
});
watch(()=>props.data,val=>{
nextTick(()=>{
init(val)
})
},{immediate:true,deep:true})
// 保存图表实例和 resize 处理函数
let myChart = null;
const handleResize = () => {
myChart && myChart.resize();
};
watch(
() => props.data,
(val) => {
nextTick(() => {
init(val);
});
},
{ immediate: true, deep: true }
);
// 初始化
function init (val) {
function init(val) {
let color = val.color;
let list = val.list
let series = list.map((item ,idx)=>{
let list = val.list;
let series = list.map((item, idx) => {
return {
type: "bar",
name:item.label,
data:item.val,
itemStyle:{normal: { color: color[idx] }},
showSymbol:false,
barWidth: '30%', // 柱状图宽度
}
})
chartFn(series)
name: item.label,
data: item.val,
itemStyle: { normal: { color: color[idx] } },
showSymbol: false,
barWidth: "30%" // 柱状图宽度
};
});
chartFn(series);
}
function chartFn(series) {
var myChart = echarts.init(document.getElementById(props.echartsId));
// 复用已有的图表实例,避免重复创建
if (!myChart) {
myChart = echarts.init(document.getElementById(props.echartsId));
}
var option = {
title: {
text: props.data.title || '',
left: 'center',
text: props.data.title || "",
left: "center",
textStyle: {
color: props.data.color[0] || "#000",
fontSize: 14
@ -71,11 +93,13 @@ function chartFn(series) {
top: "25%",
right: "0%",
left: "0%",
bottom: "0%", // 增加底部空间为两行X轴标签留出空间
bottom: "0%",
containLabel: true
},
legend: {
data: props.data.list.map(v => { return v.label }),
data: props.data.list.map((v) => {
return v.label;
}),
textStyle: {
color: props.data.color[0] || "#409EFF",
fontSize: 12
@ -86,7 +110,7 @@ function chartFn(series) {
tooltip: {
trigger: "axis",
axisPointer: {
type: 'shadow'
type: "shadow"
},
backgroundColor: "rgba(255,255,255,1)",
padding: [5, 10],
@ -104,18 +128,17 @@ function chartFn(series) {
}
},
axisLabel: {
rotate: props.rotate, // 设置标签旋转角度
rotate: props.rotate,
show: true,
color: props.data.color[0] || "#409EFF",
fontSize: 10,
interval: props.data.interval || 0, // 强制显示所有标签
formatter: function(value, index) {
// 组合显示数量和年龄范围,数量在上,范围在下
interval: props.data.interval || 0,
formatter: function (value, index) {
const bottomValues = props.data.bottomValues || [];
const bottomValue = bottomValues[index] || '';
const bottomValue = bottomValues[index] || "";
return `${bottomValue}\n${value}`;
},
margin: 10 // 调整边距
margin: 10
}
},
yAxis: {
@ -123,12 +146,12 @@ function chartFn(series) {
axisLabel: {
color: props.data.color[0] || "#409EFF",
fontSize: 10,
formatter: '{value}%' // 显示百分比
formatter: "{value}%"
},
splitLine: {
show: true,
lineStyle: {
type: 'solid',
type: "solid",
color: props.data.color[0] || "#409EFF"
}
},
@ -144,9 +167,8 @@ function chartFn(series) {
...item,
label: {
show: true,
position: 'top',
formatter: function(params) {
// 显示顶部百分比标签
position: "top",
formatter: function (params) {
return `占比 ${params.value}%`;
},
color: props.data.color[0] || "#409EFF",
@ -157,29 +179,24 @@ function chartFn(series) {
color: item.itemStyle.normal.color
}
}
})),
// // 底部数值标签
// graphic: props.data.bottomValues ? props.data.bottomValues.map((value, idx) => {
// const percent = (idx + 0.5) / props.data.xData.length * 100;
// return {
// type: 'text',
// left: `${percent}%`,
// bottom: '5%', // 调整到底部显示在x轴标签下方
// style: {
// text: value,
// fill: '#000',
// fontSize: 12
// }
// };
// }) : []
}))
};
option && myChart.setOption(option);
window.addEventListener('resize', function() {
myChart.resize();
})
}
// 组件挂载时添加 resize 监听
onMounted(() => {
window.addEventListener("resize", handleResize);
});
// 组件卸载时清理资源
onBeforeUnmount(() => {
window.removeEventListener("resize", handleResize);
if (myChart) {
myChart.dispose();
myChart = null;
}
});
</script>
<style lang="scss" scoped>
</style>
<style lang="scss" scoped></style>