CviLux_fe/src/views/dashboard/components/DashboardElecTrends.vue
2025-05-06 18:11:17 +08:00

248 lines
5.4 KiB
Vue

<script setup>
import { ref, onMounted, watch } from "vue";
import * as echarts from "echarts";
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 props = defineProps({
formState: {
type: Object,
required: true,
},
energyCostData: {
type: Object,
required: true,
},
getEnergyCostData: {
type: Function,
required: true,
}
});
const chartData = ref([]);
const floorList = ref([]);
const deptList = ref([]);
const weekComparisonOption = ref({});
// 生成柱狀圖的 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: "3%",
top: "15%",
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 = () => {
if (!props.energyCostData || !props.energyCostData.trend) {
chartData.value = [];
weekComparisonOption.value = generateCylinderChartOption(chartData.value);
return;
}
const dailyData = props.energyCostData.trend;
chartData.value = dailyData.map((item) => ({
date: dayjs(item.time).format("MM/DD"),
energy: item.value,
}));
weekComparisonOption.value = generateCylinderChartOption(chartData.value);
};
watch(
() => props.energyCostData,
(newEnergyCostData) => {
processEnergyData();
},
{ deep: true, immediate: true }
);
watch(
() => storeBuild.floorList,
(newValue) => {
if (newValue) {
console.log('newValue',newValue);
floorList.value = [
{
title: "All",
key: "all",
},
...storeBuild.floorList,
];
}
},
{
immediate: true,
}
);
watch(
() => storeBuild.floorList,
(newValue) => {
if (newValue) {
floorList.value = [
{
title: "All",
key: "all",
},
...storeBuild.floorList,
];
}
},
{
immediate: true,
}
);
watch(
() => storeBuild.deptList,
(newValue) => {
if (newValue) {
deptList.value = [
{
title: "All",
key: "all",
},
...storeBuild.deptList,
];
}
},
{
deep: true,
immediate: true,
}
);
</script>
<template>
<div class="w-full chart-data relative px-8 py-1">
<div class="flex flex-wrap items-center justify-between">
<h2 class="font-light">{{ $t("dashboard.last_30_days_energy_trend") }}</h2>
<div class="flex items-center w-52 gap-4">
<Select
:value="props.formState"
class="my-2"
selectClass="border-info focus-within:border-info btn-xs text-xs"
name="floor_guid"
Attribute="title"
:options="floorList"
:isTopLabelExist="false"
:isBottomLabelExist="false"
>
</Select>
<Select
:value="props.formState"
class="my-2"
selectClass="border-info focus-within:border-info btn-xs text-xs"
name="department_id"
Attribute="title"
:options="deptList"
:isTopLabelExist="false"
:isBottomLabelExist="false"
>
</Select>
</div>
</div>
<div class="h-[300px]">
<BarChart
id="dashboard_chart_week_comparison"
class="h-full"
:option="weekComparisonOption"
/>
</div>
</div>
</template>
<style lang="scss" scoped>
.chart-data:before {
@apply absolute right-0 left-2 top-0 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-0 bottom-0 h-10 w-10 bg-no-repeat z-10;
content: "";
background: url(@ASSET/img/chart-data-background02.svg) center center;
}
</style>