Files
admin-vben5/apps/web-antd/src/views/property/energyManagement/electricEnergy/electricTrend/index.vue
2025-09-14 21:46:33 +08:00

432 lines
10 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup lang="ts">
import dayjs from 'dayjs';
import { Dayjs } from 'dayjs';
import * as echarts from 'echarts';
import { Page } from '@vben/common-ui';
import { DatePicker } from 'ant-design-vue';
import { onMounted, onUnmounted, ref } from 'vue';
import FloorTree from '../components/floor-tree.vue';
import { meterRecordTrend } from '#/api/property/energyManagement/meterRecord';
const currentDay = ref<Dayjs>(dayjs());
const currentMonth = ref<Dayjs>(dayjs());
const currentYear = ref<Dayjs>(dayjs());
const disabledDay = (current: Dayjs) => {
return current && current > dayjs().endOf('day');
};
const disabledMonth = (current: Dayjs) => {
return current && current > dayjs().endOf('month');
};
const disabledYear = (current: Dayjs) => {
return current && current > dayjs().endOf('year');
};
onMounted(() => {
setTimeout(() => {
initChart();
}, 300);
window.addEventListener('resize', resizeChart);
});
onUnmounted(() => {
window.removeEventListener('resize', resizeChart);
});
const chartInstances = {
day: null as echarts.ECharts | null,
month: null as echarts.ECharts | null,
year: null as echarts.ECharts | null,
};
function initChart() {
//day
const chartDay = document.getElementById('day');
chartInstances.day = echarts.init(chartDay);
const optionDay = {
tooltip: {
show: true,
trigger: 'axis',
},
toolbox: {
show: true,
feature: {
magicType: { show: true, type: ['line', 'bar'] },
},
},
calculable: true,
xAxis: [
{
type: 'category',
name: '时',
},
],
yAxis: [
{
type: 'value',
name: 'KW.h',
},
],
};
optionDay && chartInstances.day.setOption(optionDay);
//month
const chartMonth = document.getElementById('month');
chartInstances.month = echarts.init(chartMonth);
const optionMonth = {
tooltip: {
trigger: 'axis',
},
toolbox: {
show: true,
feature: {
magicType: { show: true, type: ['line', 'bar'] },
},
},
calculable: true,
xAxis: [
{
type: 'category',
name: '日',
},
],
yAxis: [
{
type: 'value',
name: 'KW.h',
},
],
dataZoom: [
{
type: 'inside',
xAxisIndex: 0,
zoomOnMouseWheel: true,
filterMode: 'filter',
},
],
};
optionMonth && chartInstances.month.setOption(optionMonth);
//year
const chartYear = document.getElementById('year');
chartInstances.year = echarts.init(chartYear);
const optionYear = {
tooltip: {
trigger: 'axis',
},
toolbox: {
show: true,
feature: {
magicType: { show: true, type: ['line', 'bar'] },
},
},
calculable: true,
xAxis: [
{
type: 'category',
name: '月',
},
],
yAxis: [
{
type: 'value',
name: 'KW.h',
},
],
dataZoom: [
{
type: 'inside',
xAxisIndex: 0,
zoomOnMouseWheel: true,
filterMode: 'filter',
},
],
};
optionYear && chartInstances.year.setOption(optionYear);
// 鼠标悬停时激活缩放
chartInstances.day.on('mouseover', { seriesIndex: 0 }, () => {
chartInstances.day.dispatchAction({
type: 'takeGlobalCursor',
key: 'dataZoomSelect',
dataZoomSelectActive: true,
});
});
// 鼠标离开时取消缩放
chartInstances.day.on('mouseout', { seriesIndex: 0 }, () => {
chartInstances.day.dispatchAction({
type: 'takeGlobalCursor',
key: 'dataZoomSelect',
dataZoomSelectActive: false,
});
});
// 鼠标悬停时激活缩放
chartInstances.year.on('mouseover', { seriesIndex: 0 }, () => {
chartInstances.year.dispatchAction({
type: 'takeGlobalCursor',
key: 'dataZoomSelect',
dataZoomSelectActive: true,
});
});
// 鼠标离开时取消缩放
chartInstances.year.on('mouseout', { seriesIndex: 0 }, () => {
chartInstances.year.dispatchAction({
type: 'takeGlobalCursor',
key: 'dataZoomSelect',
dataZoomSelectActive: false,
});
});
// 鼠标悬停时激活缩放
chartInstances.month.on('mouseover', { seriesIndex: 0 }, () => {
chartInstances.month.dispatchAction({
type: 'takeGlobalCursor',
key: 'dataZoomSelect',
dataZoomSelectActive: true,
});
});
// 鼠标离开时取消缩放
chartInstances.month.on('mouseout', { seriesIndex: 0 }, () => {
chartInstances.month.dispatchAction({
type: 'takeGlobalCursor',
key: 'dataZoomSelect',
dataZoomSelectActive: false,
});
});
}
function resizeChart() {
chartInstances.day && chartInstances.day.resize();
chartInstances.month && chartInstances.month.resize();
chartInstances.year && chartInstances.year.resize();
}
const hourTotal = ref<number>();
const dayTotal = ref<number>();
const monthTotal = ref<number>();
async function handleSelectFloor(selectedKeys, info) {
let data = {
day: currentDay.value.format('YYYY-MM-DD'),
month: currentMonth.value.format('YYYY-MM'),
year: currentYear.value.format('YYYY'),
meterType: 1,
meterId: null,
floorId: null,
};
if (info.node.level == 3) {
data.floorId = selectedKeys[0];
} else {
data.meterId = selectedKeys[0];
}
const trend = await meterRecordTrend(data);
// 更新日数据图表
if (chartInstances.day && trend.hour) {
const yesterday = currentDay.value
.clone()
.subtract(1, 'day')
.format('YYYY-MM-DD');
hourTotal.value = trend.hour.today.total;
chartInstances.day.setOption({
legend: {
data: [yesterday, data.day],
},
series: [
{
name: yesterday,
type: 'bar',
data: trend.hour.yesterday.data || [],
markPoint: {
data: [
{ type: 'max', name: 'Max' },
{ type: 'min', name: 'Min' },
],
},
markLine: {
data: [{ type: 'average', name: 'Avg' }],
},
},
{
name: data.day,
type: 'bar',
data: trend.hour.today.data || [],
markPoint: {
data: [
{ type: 'max', name: 'Max' },
{ type: 'min', name: 'Min' },
],
},
markLine: {
data: [{ type: 'average', name: 'Avg' }],
},
},
],
});
}
// 更新月数据图表
if (chartInstances.month && trend.day) {
const lastMonth = currentDay.value
.clone()
.subtract(1, 'month')
.format('YYYY-MM');
dayTotal.value = trend.day.nowMonth.total;
chartInstances.month.setOption({
legend: {
data: [lastMonth, data.month],
},
series: [
{
name: lastMonth,
type: 'bar',
data: trend.day.lastMonth.data || [],
markPoint: {
data: [
{ type: 'max', name: 'Max' },
{ type: 'min', name: 'Min' },
],
},
markLine: {
data: [{ type: 'average', name: 'Avg' }],
},
},
{
name: data.month,
type: 'bar',
data: trend.day.nowMonth.data || [],
markPoint: {
data: [
{ type: 'max', name: 'Max' },
{ type: 'min', name: 'Min' },
],
},
markLine: {
data: [{ type: 'average', name: 'Avg' }],
},
},
],
});
}
// 更新年数据图表
if (chartInstances.year && trend.month) {
const lastYear = currentDay.value
.clone()
.subtract(1, 'year')
.format('YYYY');
monthTotal.value = trend.month.nowYear.total;
chartInstances.year.setOption({
legend: {
data: [lastYear, data.year],
},
series: [
{
name: lastYear,
type: 'bar',
data: trend.month.lastYear.data || [],
markPoint: {
data: [
{ type: 'max', name: 'Max' },
{ type: 'min', name: 'Min' },
],
},
markLine: {
data: [{ type: 'average', name: 'Avg' }],
},
},
{
name: data.year,
type: 'bar',
data: trend.month.nowYear.data || [],
markPoint: {
data: [
{ type: 'max', name: 'Max' },
{ type: 'min', name: 'Min' },
],
},
markLine: {
data: [{ type: 'average', name: 'Avg' }],
},
},
],
});
}
}
</script>
<template>
<Page :auto-content-height="true">
<div class="flex h-full gap-[8px]">
<FloorTree class="w-[260px]" @select="handleSelectFloor"></FloorTree>
<div class="flex-1 overflow-hidden">
<div
style="
background: #fff;
border-radius: 8px;
padding: 10px;
height: 33%;
"
>
<div>
<div style="display: flex; justify-content: space-between">
<DatePicker
v-model:value="currentDay"
:disabled-date="disabledDay"
/>
<span>当日能耗总值{{ hourTotal }}KW.h</span>
</div>
</div>
<div id="day" style="height: 100%; width: 100%"></div>
</div>
<div
style="
background: #fff;
border-radius: 8px;
padding: 10px;
margin-top: 16px;
height: 33%;
"
>
<div>
<div style="display: flex; justify-content: space-between">
<DatePicker
v-model:value="currentMonth"
:disabled-date="disabledMonth"
picker="month"
/>
<span>当月能耗总值{{ dayTotal }}KW.h</span>
</div>
</div>
<div id="month" style="height: 100%; width: 100%"></div>
</div>
<div
style="
background: #fff;
border-radius: 8px;
padding: 10px;
margin-top: 16px;
height: 33%;
"
>
<div>
<div style="display: flex; justify-content: space-between">
<DatePicker
v-model:value="currentYear"
:disabled-date="disabledYear"
picker="year"
/>
<span>当年能耗总值{{ monthTotal }}KW.h</span>
</div>
</div>
<div id="year" style="height: 100%; width: 100%"></div>
</div>
</div>
</div>
</Page>
</template>