183 lines
5.6 KiB
Vue
183 lines
5.6 KiB
Vue
<script setup>
|
||
import DashboardFloorBar from "./components/DashboardFloorBar.vue";
|
||
import DashboardEffectScatter from "./components/DashboardEffectScatter.vue";
|
||
import DashboardSysCard from "./components/DashboardSysCard.vue";
|
||
import DashboardProduct from "./components/DashboardProduct.vue";
|
||
import DashboardProductComplete from "./components/DashboardProductComplete.vue";
|
||
import DashboardIndoor from "./components/DashboardIndoor.vue";
|
||
// import DashboardRefrigTemp from "./components/DashboardRefrigTemp.vue";
|
||
// import DashboardIndoorTemp from "./components/DashboardIndoorTemp.vue";
|
||
import DashboardElectricity from "./components/DashboardElectricity.vue";
|
||
import DashboardEmission from "./components/DashboardEmission.vue";
|
||
import DashboardAlert from "./components/DashboardAlert.vue";
|
||
import { computed, inject, ref, watch, onMounted, onUnmounted } from "vue";
|
||
import useBuildingStore from "@/stores/useBuildingStore";
|
||
import { getSystemDevices, getSystemRealTime } from "@/apis/system";
|
||
import DashboardRefrig from "./components/DashboardRefrig.vue";
|
||
const FILE_BASEURL = import.meta.env.VITE_FILE_API_BASEURL;
|
||
const buildingStore = useBuildingStore();
|
||
|
||
const subscribeData = ref([]);
|
||
const systemData = ref({});
|
||
let intervalId = null;
|
||
|
||
const productVisible = ref(false); // 產品產量儀表是否顯示
|
||
const productCompleteVisible = ref(false); // 今日達成率是否顯示
|
||
|
||
// 開始定時器
|
||
const startInterval = () => {
|
||
// 清除之前的定時器(如果存在)
|
||
if (intervalId) {
|
||
clearInterval(intervalId);
|
||
}
|
||
|
||
// 每5秒呼叫一次 getData
|
||
intervalId = setInterval(() => {
|
||
getData();
|
||
}, 5000);
|
||
};
|
||
|
||
const getData = async () => {
|
||
const res = await getSystemDevices({
|
||
building_guid: buildingStore.selectedBuilding?.building_guid,
|
||
});
|
||
|
||
subscribeData.value = res.data;
|
||
console.log("devices", subscribeData.value);
|
||
|
||
// 轉換資料格式
|
||
const transformedData = {};
|
||
|
||
subscribeData.value.forEach((floor) => {
|
||
if (floor.device_list && floor.device_list.length > 0) {
|
||
const fullUrl = floor.floor_map_name;
|
||
const uuid = fullUrl ? fullUrl.replace(/\.svg$/, "") : "";
|
||
transformedData[uuid] = floor.device_list.map((device) => {
|
||
// 解析座標
|
||
const coordinates = JSON.parse(device.device_coordinate || "[0,0]");
|
||
const x = coordinates[0];
|
||
const y = coordinates[1];
|
||
|
||
// 決定設備狀態和顏色
|
||
let state = "Online";
|
||
let bgColor = device.device_normal_color;
|
||
|
||
if (
|
||
device.device_status === "Offline" ||
|
||
device.device_status === null
|
||
) {
|
||
state = "Offline";
|
||
bgColor = device.device_close_color;
|
||
}
|
||
if (device.device_status === "Error") {
|
||
state = "Error";
|
||
bgColor = device.device_error_color;
|
||
}
|
||
|
||
return [
|
||
x,
|
||
y,
|
||
{
|
||
device_number: device.device_number || "", // 設備編號
|
||
device_coordinate: device.device_coordinate || "", // 設備座標
|
||
device_image_url: device.device_image_url,
|
||
full_name: device.full_name, // 設備名稱
|
||
main_id: device.main_id,
|
||
points: device.points || [],
|
||
floor: floor.full_name,
|
||
state: state,
|
||
icon: device.device_image
|
||
? `${FILE_BASEURL}/upload/device_icon/${device.device_image}`
|
||
: "",
|
||
bgColor: bgColor,
|
||
Online_color: device.device_normal_color,
|
||
Offline_color: device.device_close_color,
|
||
Error_color: device.device_error_color,
|
||
brand: device.brand || "",
|
||
device_model: device.device_model,
|
||
operation_name: device.operation_name,
|
||
operation_contact_person: device.operation_contact_person,
|
||
buying_date: device.buying_date,
|
||
created_at: device.created_at,
|
||
bgSize: 50,
|
||
},
|
||
];
|
||
});
|
||
}
|
||
});
|
||
|
||
console.log("transformedData", transformedData);
|
||
systemData.value = transformedData;
|
||
};
|
||
|
||
watch(
|
||
() => buildingStore.selectedBuilding,
|
||
(newBuilding) => {
|
||
if (newBuilding) {
|
||
getData();
|
||
startInterval();
|
||
}
|
||
},
|
||
{
|
||
immediate: true,
|
||
}
|
||
);
|
||
|
||
// 組件卸載時清除定時器
|
||
onUnmounted(() => {
|
||
if (intervalId) {
|
||
clearInterval(intervalId);
|
||
}
|
||
});
|
||
</script>
|
||
|
||
<template>
|
||
<div class="flex flex-wrap justify-between">
|
||
<div
|
||
class="order-3 lg:order-1 w-full lg:w-1/4 min-h-screen flex flex-col justify-start z-10 border-dashboard gap-5"
|
||
>
|
||
<!-- 無資料時:完整隱藏區塊,不留空白 -->
|
||
|
||
<!-- <DashboardProduct
|
||
@visible-change="(v) => (productVisible = v)"
|
||
v-show="productVisible"
|
||
/>
|
||
<DashboardProductComplete
|
||
@visible-change="(v) => (productCompleteVisible = v)"
|
||
v-show="productVisible"
|
||
/> -->
|
||
<DashboardIndoor />
|
||
<DashboardRefrig class="mb-10" />
|
||
</div>
|
||
|
||
<div
|
||
class="order-1 lg:order-2 w-full lg:w-2/4 relative lg:static min-h-[300px] lg:h-full"
|
||
>
|
||
<DashboardFloorBar />
|
||
<DashboardEffectScatter :data="systemData" />
|
||
</div>
|
||
<div class="order-2 w-full lg:hidden my-3">
|
||
<DashboardSysCard :data="systemData" />
|
||
</div>
|
||
<div
|
||
class="order-last w-full lg:w-1/4 flex flex-col justify-start border-dashboard z-20 gap-5"
|
||
>
|
||
<div>
|
||
<DashboardElectricity />
|
||
</div>
|
||
<div class="mt-10">
|
||
<DashboardEmission />
|
||
</div>
|
||
<div class="mt-10">
|
||
<DashboardAlert />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<style lang="css" scoped>
|
||
.border-dashboard {
|
||
@apply lg:border lg:border-light-info bg-dark-info bg-opacity-70 lg:rounded-md py-12 px-8 first:mt-0 last:mb-0;
|
||
}
|
||
</style>
|