CviLux_fe/src/views/system/System.vue

274 lines
8.2 KiB
Vue

<script setup>
import { RouterView, useRoute } from 'vue-router';
import { computed, watch, provide, ref, onMounted, onBeforeUnmount } from "vue";
import SystemFloorBar from './components/SystemFloorBar.vue';
import useBuildingStore from "@/stores/useBuildingStore";
import ForgeForSystem from "@/components/forge/ForgeForSystem.vue";
import { getSystemDevices, getSystemRealTime } from "@/apis/system";
import { getOperationCompanyList } from "@/apis/operation";
import { getAssetSingle, getAssetFloorList } from "@/apis/asset";
import SystemSubBar from './components/SystemSubBar.vue';
import SystemInfoModal from './components/SystemInfoModal.vue';
import SystemMain from "./SystemMain.vue";
import SystemMode from './components/SystemMode.vue';
import SystemFloor from './SystemFloor.vue';
import { twMerge } from 'tailwind-merge';
import dayjs from "dayjs";
const buildingStore = useBuildingStore()
const statusList = computed(() => {
const sub = buildingStore.selectedSystem
if (sub) {
return {
device_normal_color: sub.device_normal_color,
device_normal_text: sub.device_normal_text,
device_close_color: sub.device_close_color,
device_close_text: sub.device_close_text,
device_error_color: sub.device_error_color,
device_error_text: sub.device_error_text
}
}
return null
})
const raw_data = ref([]);
const data = ref([]); // filter data
const route = useRoute();
const floors = ref([]);
const companyOptions = ref([]);
const selected_dbid = ref([]);
const getFloors = async () => {
const res = await getAssetFloorList();
floors.value = res.data[0]?.floors.map((d) => ({ ...d, key: d.floor_guid }));
};
const getCompany = async () => {
const res = await getOperationCompanyList();
companyOptions.value = res.data.map((d) => ({ ...d, key: d.id }));
};
const getData = async () => {
if (!route.params.sub_system_id) return
const res = await getSystemDevices({
sub_system_tag: route.params.sub_system_id,
building_tag: buildingStore.selectedBuilding?.building_tag,
})
const devices = res.data.map(d => ({
...d,
key: d.full_name,
device_list: d.device_list.map((dev, index) => ({
...dev,
forge_dbid: parseInt(dev.forge_dbid),
room_dbid: parseInt(dev.room_dbid),
device_coordinate_3d: dev.device_coordinate_3d ? JSON.parse(dev.device_coordinate_3d) : "",
alarmMsg: "",
is_show: true,
currentColor: dev.device_normal_point_color,
spriteDbId: 10 + dev.main_id,
sensorTypes: dev.points.map(({ points }) => points),
floor_guid: d.floor_guid,
is2DActive: false
})),
}));
raw_data.value = devices
data.value = devices
console.log("devices", res.data,devices)
}
const subscribeData = ref([]); // flat data
const getSubData = (value) => {
let items = [];
value.forEach((device) => {
items = [
...items,
...device.device_list
];
});
return items
}
watch(raw_data, (newValue) => {
if (route.query.gas) {
updateDataByGas(route.query.gas)
} else {
const items = getSubData(newValue)
data.value = newValue;
subscribeData.value = items;
}
});
const updateDataByGas = (gas) => {
let update_values = []
if (gas === "all") {
update_values = raw_data.value
} else {
update_values = raw_data.value.map((d) => (
{
...d,
device_list: d.device_list.filter(({ points }) => points.some(({ points: p }) => p === gas))
}
))
}
data.value = update_values
subscribeData.value = getSubData(update_values);
}
watch(
() => buildingStore.selectedBuilding,
(newBuilding) => {
if (Boolean(newBuilding)) {
getData();
}
},
{
immediate: true,
deep: true,
}
);
watch(
() => route.params.sub_system_id,
(newRoute, oldRoute) => {
if (buildingStore.selectedBuilding && newRoute !== oldRoute) {
getData();
}
}
);
onMounted(() => {
getFloors();
getCompany();
});
const currentFloor = ref(null);
const updateCurrentFloor = (floor) => {
currentFloor.value = floor;
}
const realtimeData = ref([])
const timeId = ref(null)
const getAllDeviceRealtime = () => {
timeId.value = setInterval(async () => {
const res = await getSystemRealTime(subscribeData.value.map(d => d.device_number))
console.log(res.data)
realtimeData.value = res.data
}, 10000)
}
watch(subscribeData, (newValue) => {
timeId.value && clearInterval(timeId.value)
newValue.length > 0 && getAllDeviceRealtime()
}, { deep: true, immediate: true })
provide("system_deviceList", { data, subscribeData, currentFloor, updateCurrentFloor, updateDataByGas, realtimeData })
const selectedDevice = ref(null);
const selectedDeviceCog = ref({});
// const selectedDevice = computed(() => {
// return {
// ...currentInfo.value,
// points: realtimeData.value.find(({ device_number }) => device_number === currentInfo.value?.value.device_number)
// }
// });
// 傳遞目前點擊資訊
const isMobile = (e) => {
return e.pointerType !== "mouse" && e.type !== "click"; // is mobile
};
const getCurrentInfoModalData = async (e, position, value) => {
if (value.main_id) {
const res = await getAssetSingle(value.main_id);
if (res.isSuccess) {
selectedDeviceCog.value = {
...res.data,
key: res.data.id,
floor: floors.value.find(
({ floor_guid }) => res.data.floor_guid === floor_guid
)?.full_name,
company: companyOptions.value.find(
({ id }) => res.data.operation_id === id
)?.name,
buying_date: res.data?.buying_date
? dayjs(res.data.buying_date).format("YYYY-MM-DD")
: "",
created_at: res.data?.created_at
? dayjs(res.data.created_at).format("YYYY-MM-DD")
: "",
};
}
}
const mobile = isMobile(e);
selectedDevice.value = {
initPos: { left: `50%`, top: `50%` },
value,
isMobile: mobile,
};
document.getElementById('system_info_modal').showModal();
};
const selectedDeviceRealtime = computed(() => realtimeData.value?.find(({ device_number }) => device_number === selectedDevice.value?.value?.device_number)?.data)
const clearSelectedDeviceInfo = () => {
selectedDevice.value.value = null;
}
provide("system_selectedDevice", { selectedDeviceRealtime, selectedDevice, getCurrentInfoModalData, clearSelectedDeviceInfo, selectedDeviceCog, selected_dbid })
onBeforeUnmount(() => {
clearInterval(timeId.value);
});
</script>
<template>
<SystemInfoModal :data="selectedDevice" />
<SystemFloorBar />
<div class="grid grid-cols-2 gap-5 mt-8 mb-4">
<div class="col-span-1 h-[calc(100vh-170px)] flex flex-col justify-start">
<div>
<div class="flex mb-4 items-center">
<span class="flex items-center mr-3" v-if="statusList?.device_normal_text">
<span class="w-7 h-7 rounded-full inline-block mr-1"
:style="{ backgroundColor: statusList.device_normal_color }"></span>
<span>{{ statusList.device_normal_text }}</span>
</span>
<span class="flex items-center mr-3" v-if="statusList?.device_close_text">
<span class="w-7 h-7 rounded-full inline-block mr-1"
:style="{ backgroundColor: statusList.device_close_color }"></span>
<span>{{ statusList.device_close_text }}</span>
</span>
<span class="flex items-center mr-3" v-if="statusList?.device_error_text">
<span class="w-7 h-7 rounded-full inline-block mr-1"
:style="{ backgroundColor: statusList.device_error_color }"></span>
<span>{{ statusList.device_error_text }}</span>
</span>
</div>
<SystemSubBar class="mt-2 mb-4" />
</div>
<div class="h-full pr-2 overflow-y-auto">
<RouterView />
</div>
</div>
<div class="col-span-1 h-full flex flex-col justify-between">
<SystemMode />
<div class="h-full relative">
<SystemFloor
:class="twMerge('absolute h-full w-full', route.query.mode === '2D' ? 'opacity-100 z-10' : 'opacity-0 z-0')" />
<div
:class="twMerge('absolute h-full w-full', route.query.mode === '3D' ? 'opacity-100 z-10' : 'opacity-0 z-0')">
<ForgeForSystem :initialData="{}" />
</div>
</div>
</div>
</div>
</template>
<style lang='scss' scoped></style>