<div class="bottom"><div class="topli"><p>用电统计</p><div class="tabs"><div class="tab" :class="{ active: active.tab1 === index }"v-for="(item, index) in tabsList1" :key="index" @click="changeTab(1, index)">{{ item.label }}</div></div></div><div class="list"><div id="sum-electricity" v-if="!loading.tab1 && active.tab1 === 0"><TestEleChart pid="sum-electricity" title="月用电统计" :eleData="eleData":eleXdata="eleXdata"></TestEleChart></div><div id="day-electricity" v-if="!loading.tab1 && active.tab1 === 1"><TestEleChart pid="day-electricity" title="日用电统计" :eleData="eleData":eleXdata="eleXdata"></TestEleChart></div></div></div><div class="sitestutus"><div class="top"><p>用水统计</p><div class="tabs"><div class="tab" :class="{ active: active.tab2 === index }"v-for="(item, index) in tabsList" :key="index" @click="changeTab(2, index)">{{ item.label }}</div></div></div><div class="sitebutom"><div id="monthWate" v-if="!loading.tab2 && active.tab2 === 0"><TestWaterChart pid="monthWate" title="月用水" :waterData="waterData":waterXdata="waterXdata"></TestWaterChart></div><div id="dayWater" v-if="!loading.tab2 && active.tab2 === 1"><TestWaterChart pid="dayWater" title="日用水" :waterData="waterData":waterXdata="waterXdata"></TestWaterChart></div></div></div><script setup lang="ts">// tabs切换const tabsList = [{ label: '日' },{ label: '月' },
];const tabsList1 = [{ label: '日' },{ label: '月' },
];const active = ref({tab1: 0,tab2: 0,
});
const loading = ref({tab1: false,tab2: false,
});const waterData = ref<number[]>([]);
const waterXdata = ref<string[]>([]);
const eleData = ref<number[]>([]);
const eleXdata = ref<string[]>([]);// const loading = ref(false)
const fetchData = async (type: string, tabGroup: number) => {if (tabGroup === 1) {loading.value.tab1 = true;const store = siteStore();const res = await reqGetEleStatistics(store.curSite.id, type);eleXdata.value = res.data[type === 'day' ? 'elcWrDay' : 'elcWrMonth'].map((item: any) => item.createTime);eleData.value = res.data[type === 'day' ? 'elcWrDay' : 'elcWrMonth'].map((item: any) => item.value);if (eleData.value.length === 0) {eleXdata.value = ["无数据"];eleData.value = [0];}loading.value.tab1 = false;} else if (tabGroup === 2) {loading.value.tab2 = true;const store = siteStore();const res = await reqGetWaterStatistics(store.curSite.id, type);waterXdata.value = res.data[type === 'day' ? 'elcWrDay' : 'elcWrMonth'].map((item: any) => item.createTime);waterData.value = res.data[type === 'day' ? 'elcWrDay' : 'elcWrMonth'].map((item: any) => item.value);if (waterData.value.length === 0) {waterXdata.value = ["无数据"];waterData.value = [0];}loading.value.tab2 = false;}
};const changeTab = async (tabGroup: number, index: number) => {if (tabGroup === 1) {active.value.tab1 = index;const type = index === 0 ? 'day' : 'month';await fetchData(type, tabGroup);} else if (tabGroup === 2) {active.value.tab2 = index;const type = index === 0 ? 'day' : 'month';await fetchData(type, tabGroup);}
};// 初始化时获取数据
onMounted(async () => {await changeTab(1, active.value.tab1);await changeTab(2, active.value.tab2);
});// scss.bottom {position: absolute;top: vh(635);width: vw(390);height: 400px;.topli {display: flex;}p {width: vw(435);margin-left: vw(10);line-height: vh(40);color: #fff !important;text-indent: 1rem;font-weight: 700;font-size: 25px;}#sum-electricity,#day-electricity {width: vw(385);height: vh(300);}}.sitestutus {position: absolute;top: vh(300);width: vw(385);height: 350px;p {width: vw(435);margin-left: vw(10);line-height: vh(40);color: #fff !important;// background: linear-gradient(84deg, #1d4591 0%, rgba(57, 123, 243, 0) 100%) !important;text-indent: 1rem;font-weight: 700;font-size: 25px;}.sitebutom {color: #fff;font-size: 20px;}#dayWater,#monthWate {width: vw(385);height: vh(300);}}</script>
封装的 柱状图 组件 TestEleChart
成品如图所示
<!-- 水电大屏用电趋势 -->
<template><div></div>
</template><script setup lang="ts">
import { nextTick, watch, computed, onMounted, ref, onUpdated, onBeforeUnmount } from 'vue';
import echarts from '@/assets/ts/echarts';
import { ZRColor } from 'echarts/types/dist/shared';
import useResizeChart from '@/components/CommonChart/hooks/useResizeChart';
import { color } from 'echarts';
import { EffectScatterChart } from 'echarts/charts';
echarts.use([EffectScatterChart]);const props = defineProps({pid: {type: String,required: true,},title: {type: String,required: true,},// 饼图 颜色color: {type: Array as () => ZRColor[],default: [],},eleData: {type: Array,required: true,},// 横坐标值eleXdata: {type: Array,required: true,}
})const sideData = props.eleData.map((item: any) => item + 7.5)// nextTick(() => {
// // 2. 容器
// const container = document.querySelector('#' + props.pid) as HTMLElement;
// if (container) renderChart(container);
// });
// // 3. 初始化 echarts 实例, 将配置添加给 echarts 实例
let myChart: echarts.ECharts | null = null;
// const renderChart = (container?: HTMLElement) => {
// if (!myChart) {
// myChart = echarts.init(container as HTMLElement);
// // 自适应 chart
// useResizeChart(container as HTMLElement, myChart as echarts.ECharts);
// }// myChart.setOption(option);
// };
// 改进
const initChart = async () => {await nextTick(); // 确保 DOM 更新完成const container = document.querySelector('#' + props.pid) as HTMLElement;if (container) {myChart = echarts.init(container);// 自适应 chart// @ts-ignoreuseResizeChart(container as HTMLElement, myChart);renderChart();}
}// 4.配置项
const renderChart = () => {if(!myChart) return;const option = {backgroundColor: 'transparent',tooltip: {trigger: 'axis',formatter: "{b} : {c}",axisPointer: { // 坐标轴指示器,坐标轴触发有效type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'}},xAxis: {data: props.eleXdata,//坐标轴axisLine: {lineStyle: {color: '#3eb2e8'}},//坐标值标注axisLabel: {show: true,textStyle: {color: '#fff',}}},yAxis: {//坐标轴axisLine: {show: false},//坐标值标注axisLabel: {show: true,textStyle: {color: '#fff',}},//分格线splitLine: {lineStyle: {color: '#4784e8'}}},series: [{name: 'a',tooltip: {show: false},type: 'bar',// 柱子的宽度barWidth: 15,itemStyle: {normal: {color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [{offset: 0,color: "#0B4EC3" // 0% 处的颜色}, {offset: 0.6,color: "#138CEB" // 60% 处的颜色}, {offset: 1,color: "#17AAFE" // 100% 处的颜色}], false)}},data: props.eleData,barGap: 0}, {type: 'bar',barWidth: 8,itemStyle: {normal: {color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [{offset: 0,color: "#09337C" // 0% 处的颜色}, {offset: 0.6,color: "#0761C0" // 60% 处的颜色}, {offset: 1,color: "#0575DE" // 100% 处的颜色}], false)}},barGap: 0,data: sideData}, {name: 'b',tooltip: {show: false},type: 'pictorialBar',itemStyle: {borderWidth: 0,borderColor: '#0571D5',color: '#1779E0'},symbol: 'path://M 0,-10 l 110,0 l -12,85 l -110,0 z',// key[0]为盖子宽度 key[1]为倾斜程度 值小倾斜小symbolSize: ['23', '8'],// key[1] y轴symbolOffset: ['0', '-8'],//symbolRotate: -5,symbolPosition: 'end',data: props.eleData,z: 3}]};myChart.setOption(option);
}
onMounted(initChart);onBeforeUnmount(() => {if (myChart) {myChart.dispose();myChart = null;}
});watch([() => props.eleData, () => props.eleXdata],() => {renderChart();},{ deep: true }
);
</script><style scoped></style>
封装的 柱状图 组件 TestEleChart
成品如图所示
<!-- 水务大屏柱状图 -->
<template><div :id="props.pid" style="width: 100%; height: 100%;"></div></template><script setup lang="ts">import { nextTick, watch, ref, onMounted, onBeforeUnmount } from 'vue';import * as echarts from 'echarts';import { ZRColor } from 'echarts/types/dist/shared';import useResizeChart from '@/components/CommonChart/hooks/useResizeChart';const props = defineProps({pid: {type: String,required: true,},title: {type: String,required: true,},color: {type: Array as () => ZRColor[],default: () => [],},waterData: {type: Array,required: true,},waterXdata: {type: Array,required: true,}});let myChart: echarts.ECharts | null = null;const initChart = async () => {await nextTick(); // 确保 DOM 更新完成const container = document.querySelector('#' + props.pid) as HTMLElement;if (container) {myChart = echarts.init(container);// 自适应 chart// @ts-ignoreuseResizeChart(container as HTMLElement, myChart);renderChart();}};const renderChart = () => {if (!myChart) return;const option = {backgroundColor: "transparent",color: ["#3cefff"],tooltip: {},grid: {containLabel: true,},xAxis: [{type: "category",data: props.waterXdata,axisTick: {alignWithLabel: true,},nameTextStyle: {color: "#82b0ec",},axisLine: {lineStyle: {color: "#82b0ec",},},axisLabel: {textStyle: {color: "#82b0ec",},},},],yAxis: [{type: "value",axisLabel: {textStyle: {color: "#82b0ec",},formatter: "{value}%",},splitLine: {lineStyle: {color: "#0c2c5a",},},axisLine: {show: false,},},],series: [{name: "",type: "pictorialBar",symbolSize: [20, 10],symbolOffset: [0, -5],symbolPosition: "end",z: 12,label: {show: true,position: "top",formatter: "{c}%",},data: props.waterData,},{name: "",type: "pictorialBar",symbolSize: [20, 10],symbolOffset: [0, 5],z: 12,data: props.waterData,},{type: "bar",itemStyle: {opacity: 0.7,},barWidth: "20",data: props.waterData,markLine: {silent: true,symbol: "none",label: {position: "middle",formatter: "{b}",},data: [{name: "目标值",yAxis: 80,lineStyle: {color: "#ffc832",},label: {position: "end",formatter: "{b}\n {c}%",},},],},},{type: "effectScatter",silent: true,tooltip: {show: false,},zlevel: 3,symbolSize: 10,showEffectOn: "render",rippleEffect: {brushType: "stroke",color: "#3cefff",scale: 5,},itemStyle: {color: "#3cefff",},hoverAnimation: true,data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0],},],};myChart.setOption(option);};onMounted(initChart);onBeforeUnmount(() => {if (myChart) {myChart.dispose();myChart = null;}});watch([() => props.waterData, () => props.waterXdata],() => {renderChart();},{ deep: true });</script><style scoped>/* 样式代码 */</style>