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