195 lines
6.3 KiB
Vue
195 lines
6.3 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 DashboardElectricity from "./components/DashboardElectricity.vue";
|
||
import DashboardEmission from "./components/DashboardEmission.vue";
|
||
import DashboardAlert from "./components/DashboardAlert.vue";
|
||
import DashboardRefrig from "./components/DashboardRefrig.vue";
|
||
|
||
import { computed, inject, ref, watch, onMounted, onUnmounted } from "vue";
|
||
import useBuildingStore from "@/stores/useBuildingStore";
|
||
import { getSystemDevices, getSystemRealTime } from "@/apis/system";
|
||
// ⭐ 新增:引入 getSystemConfig
|
||
import { getSystemConfig } from "@/apis/system";
|
||
|
||
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);
|
||
|
||
// ⭐ 新增:冷凍空調卡片顯示狀態(預設 false)
|
||
const showRefrigeration = ref(false);
|
||
|
||
// ⭐ 新增:讀取系統配置
|
||
const loadSystemConfig = async () => {
|
||
const building_guid = buildingStore.selectedBuilding?.building_guid;
|
||
if (!building_guid) {
|
||
showRefrigeration.value = false;
|
||
return;
|
||
}
|
||
try {
|
||
const res = await getSystemConfig(building_guid);
|
||
// 你的 apiHandler 可能回傳 { data, code, msg } 或直接回 data,兩者都兼容:
|
||
const data = res?.data ?? res;
|
||
showRefrigeration.value = !!data?.show_refrigeration;
|
||
// 若未來還要控制其他區塊(如 show_room、show_production_indicator),也可一併在這裡設定
|
||
} catch (err) {
|
||
console.error("[Dashboard] getSystemConfig error:", err);
|
||
showRefrigeration.value = false; // 失敗時保守處理:不顯示
|
||
}
|
||
};
|
||
|
||
// 取得設備資料(維持原本邏輯)
|
||
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,
|
||
is_rtsp: device.is_rtsp === true,
|
||
rtsp_url: device.rtsp_url || "",
|
||
},
|
||
];
|
||
});
|
||
}
|
||
});
|
||
|
||
console.log("transformedData", transformedData);
|
||
systemData.value = transformedData;
|
||
};
|
||
|
||
// 每 5 秒輪詢設備資料(維持原本邏輯)
|
||
const startInterval = () => {
|
||
if (intervalId) clearInterval(intervalId);
|
||
intervalId = setInterval(() => {
|
||
getData();
|
||
}, 5000);
|
||
};
|
||
|
||
// 當切換建物時:同時載入系統設定 + 設備資料
|
||
watch(
|
||
() => buildingStore.selectedBuilding,
|
||
async (newBuilding) => {
|
||
if (newBuilding) {
|
||
await loadSystemConfig(); // ⭐ 先載設定(避免先渲染出不該顯示的卡片)
|
||
getData();
|
||
startInterval();
|
||
} else {
|
||
showRefrigeration.value = false;
|
||
}
|
||
},
|
||
{ 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 item-center z-10 border-dashboard gap-12"
|
||
>
|
||
<div class="flex flex-col gap-5">
|
||
<DashboardIndoor />
|
||
</div>
|
||
|
||
<!-- ⭐ 依 show_refrigeration 決定是否渲染 -->
|
||
<div class="flex flex-col gap-5" v-if="showRefrigeration">
|
||
<DashboardRefrig />
|
||
</div>
|
||
</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-last w-full lg:w-1/4 flex flex-col justify-start border-dashboard z-20 gap-12"
|
||
>
|
||
<div class="flex flex-col gap-5">
|
||
<DashboardElectricity />
|
||
</div>
|
||
<div class="flex flex-col gap-5">
|
||
<DashboardEmission />
|
||
</div>
|
||
<div class="flex flex-col gap-5">
|
||
<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>
|