CviLux_fe/src/views/headquarters/components/ElecTrends.vue

209 lines
5.1 KiB
Vue

<script setup>
import { ref, onMounted, watch, onUnmounted } from "vue";
import * as echarts from "echarts";
import { getSystemEnergyCostTrend } from "@/apis/headquarters";
import BarChart from "@/components/chart/BarChart.vue";
import { useI18n } from "vue-i18n";
import dayjs from "dayjs";
import useBuildingStore from "@/stores/useBuildingStore";
const storeBuild = useBuildingStore();
const { t } = useI18n();
const chartData = ref([]);
const buildingList = ref([]);
const energyCostData = ref([]);
const weekComparisonOption = ref({});
const currentType = ref({});
let intervalId = null;
// 生成柱狀圖的 option
const generateCylinderChartOption = (data) => {
const barWidth = 15;
return {
xAxis: {
type: "category",
data: data.map((item) => item.date),
axisLine: {
lineStyle: {
color: "#fff",
},
},
},
yAxis: {
type: "value",
name: "kWh",
axisLine: {
lineStyle: {
color: "#fff",
},
},
splitLine: {
show: false,
},
},
series: [
{
data: data.map((item) => item.energy),
type: "bar",
barWidth: barWidth,
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 1, 1, [
{ offset: 0, color: "#1F7B47" },
{ offset: 1, color: "#247E95" },
]),
shadowBlur: 5,
shadowColor: "rgba(0, 0, 0, 0.5)",
shadowOffsetY: 5,
},
},
{
z: 15,
type: "pictorialBar",
symbolPosition: "end",
data: data.map((item) => item.energy),
symbol: "diamond",
symbolOffset: [0, -5],
symbolSize: [barWidth, barWidth * 0.5],
itemStyle: {
color: "#62E39A",
},
},
{
z: 10,
type: "pictorialBar",
data: data.map((item) => item.energy),
symbol: "diamond",
symbolSize: [barWidth, barWidth * 0.5],
symbolOffset: [0, 6],
itemStyle: {
color: "#247E95",
},
},
],
grid: {
left: "0%",
right: "0%",
bottom: "0%",
top: "16%",
containLabel: true,
},
tooltip: {
trigger: "axis",
formatter: function (params) {
const item = params[0];
return `<p>${item.name}</p> <p>${item.marker}Energy consumption : ${item.value}</p>`;
},
},
};
};
const processEnergyData = async () => {
try {
const res = await getSystemEnergyCostTrend({
building_id: currentType.value.name,
});
energyCostData.value = res.data.trend || [];
if (!energyCostData.value || energyCostData.value.length === 0) {
chartData.value = [];
weekComparisonOption.value = generateCylinderChartOption(chartData.value);
return;
}
const dailyData = [...energyCostData.value].sort(
(a, b) => new Date(a.time) - new Date(b.time)
);
chartData.value = dailyData.map((item) => ({
date: dayjs(item.time).format("MM/DD"),
energy: item.value,
}));
weekComparisonOption.value = generateCylinderChartOption(chartData.value);
} catch (error) {
console.error("Error fetching energy cost trend:", error);
}
};
watch(
() => storeBuild.buildings,
(newValue) => {
if (newValue) {
currentType.value = {
name: newValue[0]?.building_guid || "all",
};
buildingList.value = [
...newValue.map((building) => ({
title: building.full_name,
key: building.building_guid,
})),
];
}
},
{
immediate: true,
}
);
// 監聽 currentType 變化時重新取得資料
watch(
() => currentType.value.name,
(newValue) => {
if (newValue) {
processEnergyData();
if (intervalId) {
clearInterval(intervalId);
}
intervalId = setInterval(() => {
processEnergyData();
}, 60 * 60 * 1000);
}
},
{
immediate: true,
}
);
onUnmounted(() => {
clearInterval(intervalId);
});
</script>
<template>
<div class="w-full chart-data relative px-3">
<div class="flex flex-wrap items-center justify-between">
<h2 class="font-light pt-1 px-1">
{{ $t("dashboard.last_30_days_energy_trend") }}
</h2>
<Select
:value="currentType"
class="w-[8.5rem] my-2"
selectClass="border-info focus-within:border-info btn-xs text-xs"
name="name"
Attribute="title"
:options="buildingList"
:isTopLabelExist="false"
:isBottomLabelExist="false"
>
</Select>
</div>
<div class="h-[200px]">
<BarChart
id="dashboard_chart_week_comparison"
class="h-full"
:option="weekComparisonOption"
/>
</div>
</div>
</template>
<style lang="scss" scoped>
.chart-data:before {
@apply absolute -left-0 -top-1 h-10 w-10 bg-no-repeat z-10;
content: "";
background: url(@ASSET/img/chart-data-background01.svg) center center;
}
.chart-data::after {
@apply absolute -right-1 bottom-1 h-10 w-10 bg-no-repeat z-10;
content: "";
background: url(@ASSET/img/chart-data-background02.svg) center center;
}
</style>