empower_front/src/views/dashboard/components/DashboardHumidity.vue
2025-07-24 16:43:41 +08:00

201 lines
4.7 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>
import LineChart from "@/components/chart/LineChart.vue";
import { SECOND_CHART_COLOR } from "@/constant";
import dayjs from "dayjs";
import { ref, watch, onUnmounted } from "vue";
import useActiveBtn from "@/hooks/useActiveBtn";
import { getDashboardTemp } from "@/apis/dashboard";
import useSearchParams from "@/hooks/useSearchParam";
import useBuildingStore from "@/stores/useBuildingStore";
const { searchParams } = useSearchParams();
const buildingStore = useBuildingStore();
const intervalType = "immediateTemp";
const timeoutTimer = ref("");
const { items, changeActiveBtn, setItems, selectedBtn } = useActiveBtn();
const data = ref([]);
const other_real_temp_chart = ref(null);
const defaultChartOption = ref({
tooltip: {
trigger: "axis",
},
legend: {
data: [],
textStyle: {
color: "#ffffff",
fontSize: 16,
},
},
grid: {
top: "10%",
left: "0%",
right: "0%",
bottom: "0%",
containLabel: true,
},
xAxis: {
// type: 'time',
type: "category",
splitLine: {
show: false,
},
axisLabel: {
color: "#ffffff",
},
data: [],
},
yAxis: {
type: "value",
splitLine: {
show: false,
},
axisLabel: {
color: "#ffffff",
},
},
series: [],
});
const getData = async (tempOption) => {
const res = await getDashboardTemp({
building_guid: buildingStore.selectedBuilding.building_guid,
tempOption, // 1室溫 2:冷藏
timeInterval: 1, // 時間間隔=>1.4.8
option: 2, // 2:濕度
});
if (res.isSuccess) {
if (tempOption === 1) {
console.log("室內溼度資料:", res.data["室溫"]);
data.value = res.data["室溫"] || [];
} else {
console.log("冷藏溼度資料:", res.data["冷藏溫度"]);
data.value = res.data["冷藏溫度"] || [];
}
}
};
// 監聽建築物選擇變化
watch(
() => buildingStore.sysConfig,
(newValue) => {
if (newValue) {
// 根據 sysConfig 設定動態生成按鈕
const itemsArr = buildingStore.sysConfig?.humiture_options
? Object.entries(buildingStore.sysConfig.humiture_options).map(
([key, title], index) => ({
key: Number(key),
title,
active: index === 0,
})
)
: [];
setItems(itemsArr);
} else {
// 清除定時器
if (timeoutTimer.value) {
clearInterval(timeoutTimer.value);
}
}
},
{
immediate: true,
}
);
watch(
selectedBtn,
(newValue) => {
if (timeoutTimer.value) {
clearInterval(timeoutTimer.value);
}
if (newValue?.key) {
getData(newValue.key);
// 重新設置定時器
timeoutTimer.value = setInterval(() => {
getData(newValue.key);
}, 60 * 1000);
}
},
{
immediate: true,
deep: true,
}
);
watch(
data,
(newValue) => {
if (newValue?.length > 0 && other_real_temp_chart.value?.chart) {
const firstItem = newValue[0];
if (firstItem?.data?.length > 0) {
const validData = firstItem.data.filter(
(item) => item.value !== null && item.value !== undefined
);
if (validData.length > 0) {
const minValue = Math.min(...validData.map(({ value }) => value));
const maxValue = Math.max(...validData.map(({ value }) => value));
other_real_temp_chart.value.chart.setOption({
legend: {
data: newValue.map(({ full_name }) => full_name),
},
xAxis: {
data: firstItem.data.map(({ time }) =>
dayjs(time).format("HH:mm:ss")
),
},
yAxis: {
min: Math.floor(minValue),
max: Math.ceil(maxValue),
},
series: newValue.map(({ full_name, data }, index) => ({
name: full_name,
type: "line",
data: data.map(({ value }) => value),
showSymbol: false,
itemStyle: {
color: SECOND_CHART_COLOR[index % SECOND_CHART_COLOR.length],
},
})),
});
}
}
}
},
{ deep: true }
);
onUnmounted(() => {
// 清除定時器
if (timeoutTimer.value) {
clearInterval(timeoutTimer.value);
}
});
</script>
<template>
<h3 class="text-info text-xl text-center">濕度趨勢</h3>
<div className="my-3 w-full flex justify-center relative">
<ButtonConnectedGroup
:items="items"
:onclick="
(e, item) => {
changeActiveBtn(item);
}
"
/>
</div>
<LineChart
id="dashboard_other_real_temp"
class="min-h-[260px] max-h-fit"
:option="defaultChartOption"
ref="other_real_temp_chart"
/>
</template>
<style lang="scss" scoped></style>