重構儀表板與熱圖功能 | 新增水管數據處理與即時溫度更新邏輯 | 調整電表與冷藏設備的數據傳遞與顯示
This commit is contained in:
parent
babef0e2ae
commit
be4ff70043
@ -10,37 +10,40 @@ import {
|
|||||||
provide,
|
provide,
|
||||||
inject,
|
inject,
|
||||||
} from "vue";
|
} from "vue";
|
||||||
import { getUrn, getAccessToken } from "@/apis/forge";
|
|
||||||
import { twMerge } from "tailwind-merge";
|
import { twMerge } from "tailwind-merge";
|
||||||
import useSystemStatusByBaja from "@/hooks/baja/useSystemStatusByBaja";
|
import useSystemStatusByBaja from "@/hooks/baja/useSystemStatusByBaja";
|
||||||
|
import useSystemHeatmap from "@/hooks/baja/useSystemHeatmap";
|
||||||
import ForgeInfoModal from "./ForgeInfoModal.vue";
|
import ForgeInfoModal from "./ForgeInfoModal.vue";
|
||||||
import useAlarmStore from "@/stores/useAlarmStore";
|
import useSearchParams from "@/hooks/useSearchParam";
|
||||||
|
const { searchParams } = useSearchParams();
|
||||||
|
const { updateTemp } = useSystemHeatmap();
|
||||||
const FILE_BASEURL = import.meta.env.VITE_FILE_API_BASEURL;
|
const FILE_BASEURL = import.meta.env.VITE_FILE_API_BASEURL;
|
||||||
const { forgeLock } = inject("app_toggle");
|
const { forgeLock } = inject("app_toggle");
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
fullScreen: Boolean,
|
fullScreen: Boolean,
|
||||||
initialData: Object,
|
initialData: Object,
|
||||||
|
pipeData: Array,
|
||||||
realTime: String,
|
realTime: String,
|
||||||
|
meterList: Array,
|
||||||
|
heatmapDevices: Array,
|
||||||
});
|
});
|
||||||
|
|
||||||
const heat_bar_isShow = ref(false);
|
|
||||||
const updateHeatBarIsShow = (isShow) => {
|
|
||||||
heat_bar_isShow.value = isShow;
|
|
||||||
};
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
subscribeData,
|
|
||||||
visibleDbid,
|
visibleDbid,
|
||||||
updateDbidPosition,
|
updateMeterPositions,
|
||||||
hideAllObjects,
|
hideAllObjects,
|
||||||
updateForgeViewer,
|
updateForgeViewer,
|
||||||
forgeViewer,
|
forgeViewer,
|
||||||
urn,
|
urn,
|
||||||
loadModel,
|
loadModel,
|
||||||
updateInitialData,
|
updateInitialData,
|
||||||
|
updatePipeData,
|
||||||
subComponents,
|
subComponents,
|
||||||
clearSprites
|
clearSprites,
|
||||||
} = useSystemStatusByBaja(updateHeatBarIsShow);
|
} = useSystemStatusByBaja();
|
||||||
|
|
||||||
|
// 用於存儲 meter label 的 2D 位置
|
||||||
|
const meterPositions = ref(new Map());
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.initialData,
|
() => props.initialData,
|
||||||
@ -52,19 +55,44 @@ watch(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const store = useAlarmStore();
|
watch(
|
||||||
const subscribeDataWithErrorMsg = computed(() => {
|
() => props.pipeData,
|
||||||
let data = { ...subscribeData.value };
|
(newValue, oldValue) => {
|
||||||
|
if (JSON.stringify(newValue) === JSON.stringify(oldValue)) return;
|
||||||
for (let [key, value] of Object.entries(subscribeData.value)) {
|
newValue && updatePipeData(newValue);
|
||||||
const alarm = store.alarmData.find(
|
},
|
||||||
({ device_number }) => device_number === key
|
{
|
||||||
);
|
deep: true,
|
||||||
data[key].alarmMsg = alarm ? alarm.msg : "";
|
|
||||||
}
|
}
|
||||||
console.log("baja update data: ", data);
|
);
|
||||||
return data;
|
|
||||||
});
|
watch(
|
||||||
|
() => props.heatmapDevices,
|
||||||
|
(newValue) => {
|
||||||
|
if (!newValue || newValue.length === 0) return;
|
||||||
|
newValue &&
|
||||||
|
updateTemp(newValue[0]?.forge_dbid, parseFloat(newValue[0]?.temperature));
|
||||||
|
},
|
||||||
|
{
|
||||||
|
deep: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// 更新 meter labels 的位置
|
||||||
|
const updateMeterPositionsLocal = () => {
|
||||||
|
if (!props.meterList) return;
|
||||||
|
const newPositions = updateMeterPositions(props.meterList);
|
||||||
|
meterPositions.value = newPositions;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 監聽 meterList 變化
|
||||||
|
watch(
|
||||||
|
() => props.meterList,
|
||||||
|
() => {
|
||||||
|
updateMeterPositionsLocal();
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
|
|
||||||
const forgeDom = ref(null);
|
const forgeDom = ref(null);
|
||||||
|
|
||||||
@ -107,17 +135,17 @@ const initForge = () => {
|
|||||||
viewer.isLoadDone()
|
viewer.isLoadDone()
|
||||||
);
|
);
|
||||||
updateForgeViewer(viewer);
|
updateForgeViewer(viewer);
|
||||||
|
// 初始化 meter 位置
|
||||||
|
updateMeterPositionsLocal();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 添加 camera 變化事件監聽,更新 meter 位置
|
||||||
viewer.addEventListener(
|
viewer.addEventListener(
|
||||||
Autodesk.Viewing.CAMERA_CHANGE_EVENT,
|
Autodesk.Viewing.CAMERA_CHANGE_EVENT,
|
||||||
function (e) {
|
() => {
|
||||||
viewer.isLoadDone() && updateDbidPosition(this, subscribeData.value);
|
console.log("CAMERA_CHANGE_EVENT");
|
||||||
console.log(
|
updateMeterPositionsLocal();
|
||||||
"camera position changed: ",
|
|
||||||
NOP_VIEWER.navigation.getTarget(),
|
|
||||||
e.camera.position
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -129,23 +157,6 @@ onMounted(() => {
|
|||||||
initForge();
|
initForge();
|
||||||
});
|
});
|
||||||
|
|
||||||
// 傳遞目前點擊資訊
|
|
||||||
const currentInfoModalData = ref(null);
|
|
||||||
const isMobile = (pointerType) => {
|
|
||||||
return pointerType !== "mouse"; // is desktop
|
|
||||||
};
|
|
||||||
const getCurrentInfoModalData = (e, position, value) => {
|
|
||||||
const mobile = isMobile(e.pointerType);
|
|
||||||
currentInfoModalData.value = {
|
|
||||||
initPos: mobile
|
|
||||||
? { left: `50%`, top: `50%` }
|
|
||||||
: { left: `${position.left}px`, top: `${position.top}px` },
|
|
||||||
value,
|
|
||||||
isMobile: mobile,
|
|
||||||
};
|
|
||||||
forge_info_modal.showModal();
|
|
||||||
};
|
|
||||||
|
|
||||||
watch([forgeViewer, forgeLock], ([newViewer, newLock]) => {
|
watch([forgeViewer, forgeLock], ([newViewer, newLock]) => {
|
||||||
if (newViewer && newLock !== undefined) {
|
if (newViewer && newLock !== undefined) {
|
||||||
newViewer.setNavigationLock(newLock); // 鎖定視角
|
newViewer.setNavigationLock(newLock); // 鎖定視角
|
||||||
@ -166,7 +177,7 @@ onUnmounted(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ForgeInfoModal :data="currentInfoModalData" />
|
<!-- <ForgeInfoModal :data="currentInfoModalData" /> -->
|
||||||
<div
|
<div
|
||||||
:class="
|
:class="
|
||||||
twMerge(
|
twMerge(
|
||||||
@ -186,8 +197,11 @@ onUnmounted(() => {
|
|||||||
)
|
)
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<p class="absolute z-10 top-14 left-[27%]">更新時間 : {{ props.realTime }}</p>
|
<p class="absolute z-10 top-14 left-[27%]">
|
||||||
<div v-show="heat_bar_isShow" class="absolute z-10 heatbar">
|
更新時間 : {{ props.realTime }}
|
||||||
|
{{ searchParams?.option == 4 ? " (溫度)" : "" }}
|
||||||
|
</p>
|
||||||
|
<div v-show="searchParams?.option == 4" class="absolute z-10 heatbar">
|
||||||
<div class="w-40 flex justify-between text-[10px] mb-1">
|
<div class="w-40 flex justify-between text-[10px] mb-1">
|
||||||
<span class="text-gradient-1">-20°C</span>
|
<span class="text-gradient-1">-20°C</span>
|
||||||
<span class="text-gradient-2">0°C</span>
|
<span class="text-gradient-2">0°C</span>
|
||||||
@ -207,38 +221,27 @@ onUnmounted(() => {
|
|||||||
"
|
"
|
||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
|
<template v-if="searchParams?.option == 5">
|
||||||
<!-- <label
|
<label
|
||||||
v-for="(value, key) in subscribeDataWithErrorMsg"
|
v-for="value in props.meterList"
|
||||||
:key="key"
|
:key="value.main_id"
|
||||||
:data-dbid="value.forge_dbid"
|
:data-dbid="value.forge_dbid"
|
||||||
|
v-show="meterPositions.get(value.main_id)?.visible !== false"
|
||||||
:class="
|
:class="
|
||||||
twMerge(
|
twMerge(
|
||||||
`after:border-t-[${value.currentColor}]`,
|
'flex items-center justify-center h-12 -translate-x-1/2 -translate-y-1/5 absolute z-50 px-5 py-4 text-center rounded-md text-lg border-2 border-white bg-green-600',
|
||||||
'flex items-center justify-center h-12 -translate-x-1/2 -translate-y-1/5 absolute z-50 px-5 py-4 text-center rounded-md text-lg border-2 border-white',
|
|
||||||
'after:absolute after:border-t-[10px] after:border-x-[12px] after:border-x-transparent after:-bottom-[8px] after:left-1/2 after:-translate-x-1/2 ',
|
'after:absolute after:border-t-[10px] after:border-x-[12px] after:border-x-transparent after:-bottom-[8px] after:left-1/2 after:-translate-x-1/2 ',
|
||||||
'before:absolute before:border-t-[12px] before:border-x-[14px] before:border-x-transparent before:-bottom-[12px] before:left-1/2 before:-translate-x-1/2 before:border-white'
|
'before:absolute before:border-t-[12px] before:border-x-[14px] before:border-x-transparent before:-bottom-[12px] before:left-1/2 before:-translate-x-1/2 before:border-white'
|
||||||
)
|
)
|
||||||
"
|
"
|
||||||
:style="{
|
:style="{
|
||||||
left: `${Math.floor(value.device_coordinate_3d.x)}px`,
|
left: `${meterPositions.get(value.main_id)?.x || 0}px`,
|
||||||
top: `${Math.floor(value.device_coordinate_3d.y) - 100}px`,
|
top: `${meterPositions.get(value.main_id)?.y || 0}px`,
|
||||||
display: value.is_show,
|
|
||||||
backgroundColor: value.currentColor,
|
|
||||||
}"
|
}"
|
||||||
@click.prevent="
|
|
||||||
(e) =>
|
|
||||||
getCurrentInfoModalData(
|
|
||||||
e,
|
|
||||||
{ left: e.clientX, top: e.clientY },
|
|
||||||
value
|
|
||||||
)
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<span class="mr-2">{{ value.full_name }}</span>
|
<span class="mr-2">{{ value.name }}</span>
|
||||||
<span v-if="value.alarmMsg">{{ value.alarmMsg }}</span>
|
</label>
|
||||||
<span v-else>{{ value.show_value }}</span>
|
</template>
|
||||||
</label> -->
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import { ref, watch, markRaw, onUnmounted } from "vue";
|
import { ref, watch, markRaw, onUnmounted } from "vue";
|
||||||
import useSearchParams from "@/hooks/useSearchParam";
|
import useSearchParams from "@/hooks/useSearchParam";
|
||||||
|
|
||||||
export default function useSystemHeatmap(updateHeatBarIsShow) {
|
export default function useSystemHeatmap() {
|
||||||
const { searchParams } = useSearchParams();
|
const { searchParams } = useSearchParams();
|
||||||
|
|
||||||
// Viewer and DataVisualization Extension References
|
// Viewer and DataVisualization Extension References
|
||||||
@ -25,12 +25,13 @@ export default function useSystemHeatmap(updateHeatBarIsShow) {
|
|||||||
const updateHeatMapData = (deviceArr) => {
|
const updateHeatMapData = (deviceArr) => {
|
||||||
deviceList.value = Object.values(deviceArr).map((d) => ({
|
deviceList.value = Object.values(deviceArr).map((d) => ({
|
||||||
...d,
|
...d,
|
||||||
id: d.device_number, // An ID to identify this device
|
id: d.forge_dbid, // An ID to identify this device
|
||||||
roomDbId: d.room_dbid,
|
roomDbId: d.room_dbid,
|
||||||
position: d.device_coordinate_3d, // World coordinates of this device
|
position: JSON.parse(d.device_coordinate_3d),
|
||||||
sensorTypes: ["temperature"], // The types/properties this device exposes
|
sensorTypes: ["temperature"], // The types/properties this device exposes
|
||||||
temp: 10,
|
temp: 25,
|
||||||
dbId: d.forge_dbid,
|
dbId: d.forge_dbid,
|
||||||
|
subSys: "freezer",
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -132,22 +133,10 @@ export default function useSystemHeatmap(updateHeatBarIsShow) {
|
|||||||
|
|
||||||
// Watcher for Device List Changes
|
// Watcher for Device List Changes
|
||||||
watch(deviceList, (newValue) => {
|
watch(deviceList, (newValue) => {
|
||||||
console.log("熱圖更新", newValue);
|
console.log("熱圖更新", newValue, searchParams.value.option);
|
||||||
switch (parseInt(searchParams.value.option)) {
|
switch (parseInt(searchParams.value.option)) {
|
||||||
case 2:
|
case 1:
|
||||||
createHeatMap("frozen");
|
createHeatMap("frozen");
|
||||||
updateHeatBarIsShow(true);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
createHeatMap("gland");
|
|
||||||
updateHeatBarIsShow(true);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
createHeatMap("packing");
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
createHeatMap("formula");
|
|
||||||
updateHeatBarIsShow(true);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (isHeatMapSetup.value) {
|
if (isHeatMapSetup.value) {
|
||||||
@ -159,7 +148,6 @@ export default function useSystemHeatmap(updateHeatBarIsShow) {
|
|||||||
"跳過 removeSurfaceShading,因為尚未 setupSurfaceShading"
|
"跳過 removeSurfaceShading,因為尚未 setupSurfaceShading"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
updateHeatBarIsShow(false);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -3,9 +3,12 @@ import { getDashboardDevice } from "@/apis/dashboard";
|
|||||||
import useSearchParams from "@/hooks/useSearchParam";
|
import useSearchParams from "@/hooks/useSearchParam";
|
||||||
import useSystemHeatmap from "./useSystemHeatmap";
|
import useSystemHeatmap from "./useSystemHeatmap";
|
||||||
|
|
||||||
export default function useSystemStatusByBaja(updateHeatBarIsShow) {
|
export default function useSystemStatusByBaja() {
|
||||||
const rawData = ref([]);
|
const rawData = ref([]);
|
||||||
const forgeViewer = ref(null);
|
const forgeViewer = ref(null);
|
||||||
|
const visibleDbid = ref([]);
|
||||||
|
const heatmapDevices = ref([]);
|
||||||
|
|
||||||
const urn = ref("");
|
const urn = ref("");
|
||||||
const lightColorMap = {
|
const lightColorMap = {
|
||||||
1: "#009100",
|
1: "#009100",
|
||||||
@ -20,106 +23,56 @@ export default function useSystemStatusByBaja(updateHeatBarIsShow) {
|
|||||||
let cameraEventAdded = false; // 追蹤是否已經添加了相機事件監聽器
|
let cameraEventAdded = false; // 追蹤是否已經添加了相機事件監聽器
|
||||||
|
|
||||||
const initialData = ref(null);
|
const initialData = ref(null);
|
||||||
|
const pipeList = ref(null);
|
||||||
|
const subscribeData = ref({});
|
||||||
|
|
||||||
const updateInitialData = (data = false) => {
|
const updateInitialData = (data = false) => {
|
||||||
initialData.value = data;
|
initialData.value = data;
|
||||||
|
if (data && Array.isArray(data.dbid_list)) {
|
||||||
|
visibleDbid.value = data.dbid_list.map((d) => d.forge_dbid);
|
||||||
|
heatmapDevices.value = data.dbid_list.filter((d) => d.room_dbid !== null);
|
||||||
|
} else {
|
||||||
|
visibleDbid.value = [];
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const { updateHeatMapData, updateTemp, initHeatMap } =
|
function updatePipeData(data) {
|
||||||
useSystemHeatmap(updateHeatBarIsShow);
|
const newDbids = data.map((item) => item.forge_dbid);
|
||||||
|
const oldDbids = pipeList.value
|
||||||
|
? pipeList.value.map((item) => item.forge_dbid)
|
||||||
|
: [];
|
||||||
|
const toHide = oldDbids.filter((dbid) => !newDbids.includes(dbid));
|
||||||
|
console.log("更新水管數據", forgeViewer.value, data);
|
||||||
|
if (forgeViewer.value) {
|
||||||
|
if (toHide.length > 0 && forgeViewer.value.hide)
|
||||||
|
forgeViewer.value.hide(toHide);
|
||||||
|
if (newDbids.length > 0 && forgeViewer.value.show)
|
||||||
|
forgeViewer.value.show(newDbids);
|
||||||
|
}
|
||||||
|
|
||||||
const updateForgeViewer = (viewer) => {
|
pipeList.value = data;
|
||||||
|
clearSprites(); // 清理之前的 Sprites
|
||||||
|
// 如果有特定的 dbid 需要顯示動畫,則創建動畫
|
||||||
|
if (forgeViewer.value && pipeList.value.length > 0) {
|
||||||
|
pipeList.value.forEach(({ forge_dbid, reverse }) => {
|
||||||
|
if (reverse !== null) {
|
||||||
|
createSprites(forgeViewer.value, forge_dbid, reverse);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { updateHeatMapData, initHeatMap } = useSystemHeatmap();
|
||||||
|
|
||||||
|
const updateForgeViewer = async (viewer) => {
|
||||||
if (!viewer) {
|
if (!viewer) {
|
||||||
forgeViewer.value = null;
|
forgeViewer.value = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
forgeViewer.value = markRaw(viewer);
|
forgeViewer.value = markRaw(viewer);
|
||||||
initHeatMap(viewer);
|
await initHeatMap(viewer); // 等待初始化完成
|
||||||
};
|
updateHeatMapData(heatmapDevices.value);
|
||||||
|
updatePipeData(pipeList.value || []);
|
||||||
const getSubPoint = (normal, close, error, sub_points = []) => {
|
|
||||||
let points = {
|
|
||||||
...Object.fromEntries(sub_points.map((p) => [p, ""])),
|
|
||||||
};
|
|
||||||
if (normal) points[normal] = "";
|
|
||||||
if (close) points[close] = "";
|
|
||||||
if (error) points[error] = "";
|
|
||||||
return points;
|
|
||||||
};
|
|
||||||
const subscribeData = ref({});
|
|
||||||
|
|
||||||
watch(rawData, () => {
|
|
||||||
let sub_data = {};
|
|
||||||
|
|
||||||
rawData.value.forEach((d) => {
|
|
||||||
sub_data = {
|
|
||||||
...sub_data,
|
|
||||||
...Object.fromEntries(
|
|
||||||
(d.device || []).map((dev) => [
|
|
||||||
dev.device_number,
|
|
||||||
{
|
|
||||||
...dev,
|
|
||||||
labelText: d.labelText,
|
|
||||||
show_value: d.labelText,
|
|
||||||
device_normal_point_name: d.device_normal_point_name,
|
|
||||||
device_close_point_name: d.device_close_point_name,
|
|
||||||
device_error_point_name: d.device_error_point_name,
|
|
||||||
device_normal_point_value: d.device_normal_point_value,
|
|
||||||
device_close_point_value: d.device_close_point_value,
|
|
||||||
device_error_point_value: d.device_error_point_value,
|
|
||||||
device_normal_color: d.device_normal_color,
|
|
||||||
device_close_color: d.device_close_color,
|
|
||||||
device_error_color: d.device_error_color,
|
|
||||||
forge_dbid: parseInt(dev.forge_dbid),
|
|
||||||
device_coordinate_3d: dev.device_coordinate_3d
|
|
||||||
? JSON.parse(dev.device_coordinate_3d)
|
|
||||||
: { x: 0, y: 0 },
|
|
||||||
points: getSubPoint(
|
|
||||||
d.device_normal_point_name,
|
|
||||||
d.device_close_point_name,
|
|
||||||
d.device_error_point_name,
|
|
||||||
d.points || []
|
|
||||||
),
|
|
||||||
subSys: d.subSys,
|
|
||||||
is_show: true,
|
|
||||||
currentColor: d.device_normal_color,
|
|
||||||
},
|
|
||||||
])
|
|
||||||
),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
subscribeData.value = sub_data;
|
|
||||||
updateHeatMapData(sub_data);
|
|
||||||
// updateSubscribeDataFromBaja(sub_data);
|
|
||||||
});
|
|
||||||
|
|
||||||
const visibleDbid = computed(() => {
|
|
||||||
let visible = [];
|
|
||||||
|
|
||||||
rawData.value.forEach((d) => {
|
|
||||||
visible = [
|
|
||||||
...visible,
|
|
||||||
...d.device.map((dev) => parseInt(dev.forge_dbid)),
|
|
||||||
];
|
|
||||||
});
|
|
||||||
|
|
||||||
// return visible;
|
|
||||||
return [
|
|
||||||
26, 32, 38, 43, 48, 53, 58, 63, 70, 76, 879, 1068, 1011, 1065, 855, 1109,
|
|
||||||
867, 963, 1044, 966, 1139, 936, 1136, 957, 1133, 954, 610, 1130, 951,
|
|
||||||
1041, 939, 1145, 987, 999, 1148, 1002, 1151, 981, 813, 1088, 825, 1091,
|
|
||||||
804,
|
|
||||||
];
|
|
||||||
});
|
|
||||||
|
|
||||||
const getDevice = async (option = 1) => {
|
|
||||||
const res = await getDashboardDevice({
|
|
||||||
option: parseInt(option),
|
|
||||||
});
|
|
||||||
rawData.value = res.data.map((d) => ({
|
|
||||||
...d,
|
|
||||||
key: d.subSys,
|
|
||||||
}));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// subscribe from baja
|
// subscribe from baja
|
||||||
@ -130,238 +83,64 @@ export default function useSystemStatusByBaja(updateHeatBarIsShow) {
|
|||||||
[point]: facets,
|
[point]: facets,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
const updateDeviceData = (device_number, point, value) => {
|
|
||||||
// 檢查 subscribeData.value[device_number] 是否存在
|
|
||||||
if (!subscribeData.value[device_number]) {
|
|
||||||
console.log(`Device ${device_number} is not initialized.`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const correspondPoint = initialData.value.points.find(
|
|
||||||
({ name }) => name === point
|
|
||||||
);
|
|
||||||
// console.log("sub 回傳值 ", typeof value)
|
|
||||||
const text = correspondPoint
|
|
||||||
? correspondPoint.values.find(
|
|
||||||
({ value: pValue }) => pValue === parseInt(value)
|
|
||||||
)?.text || ""
|
|
||||||
: value;
|
|
||||||
|
|
||||||
// console.log("baja update data sub", correspondPoint, device_number, point, value);
|
|
||||||
subscribeData.value[device_number].points[point] = text;
|
|
||||||
if (
|
|
||||||
point.toLowerCase() === "temp" &&
|
|
||||||
parseInt(searchParams.value.option) > 1
|
|
||||||
) {
|
|
||||||
updateTemp(device_number, value);
|
|
||||||
}
|
|
||||||
// 當點位是 "light",且目前顏色不是錯誤顏色時,從 lightColorMap 取顏色
|
|
||||||
if (
|
|
||||||
point.toLowerCase() === "light" &&
|
|
||||||
subscribeData.value[device_number].currentColor !==
|
|
||||||
subscribeData.value[device_number].device_error_color
|
|
||||||
) {
|
|
||||||
subscribeData.value[device_number].currentColor =
|
|
||||||
lightColorMap[Number(value)] ||
|
|
||||||
subscribeData.value[device_number].device_normal_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 當點位是錯誤點時,判斷值是否等於錯誤值,決定是否使用錯誤顏色
|
|
||||||
if (point === subscribeData.value[device_number].device_error_point_name) {
|
|
||||||
subscribeData.value[device_number].currentColor =
|
|
||||||
value === subscribeData.value[device_number].device_error_point_value
|
|
||||||
? subscribeData.value[device_number].device_error_color
|
|
||||||
: subscribeData.value[device_number].device_normal_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
updateLabelText(device_number, point, text);
|
|
||||||
};
|
|
||||||
|
|
||||||
const transformDeviceNumber = (device_number) => {
|
|
||||||
const transformed = device_number.replaceAll("_", "/");
|
|
||||||
// 找到最後一個 / 的位置,並截取到該位置之前
|
|
||||||
const lastSlashIndex = transformed.lastIndexOf("/");
|
|
||||||
return lastSlashIndex !== -1
|
|
||||||
? transformed.substring(0, lastSlashIndex)
|
|
||||||
: transformed;
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateLabelText = (key, point, value) => {
|
|
||||||
let text = subscribeData.value[key].labelText.replace(`%${point}`, value);
|
|
||||||
Object.keys(subscribeData.value[key].points)
|
|
||||||
.filter((p) => p !== point)
|
|
||||||
.forEach((p) => {
|
|
||||||
text = text.replace(`%${p}`, subscribeData.value[key].points[p]);
|
|
||||||
});
|
|
||||||
subscribeData.value[key].show_value = text;
|
|
||||||
};
|
|
||||||
|
|
||||||
const subComponents = ref(null);
|
const subComponents = ref(null);
|
||||||
const updateSubscribeDataFromBaja = (data) => {
|
|
||||||
for (let [key, value] of Object.entries(data)) {
|
|
||||||
window.require &&
|
|
||||||
window.requirejs(["baja!"], (baja) => {
|
|
||||||
console.log("進入 bajaSubscriber 準備執行BQL訂閱");
|
|
||||||
|
|
||||||
const ordKey = key;
|
const updateMeterPositions = (meterList) => {
|
||||||
const ordPath = transformDeviceNumber(key);
|
if (!forgeViewer.value || !meterList) return new Map();
|
||||||
console.log("ordPath", ordPath, "ordKey", ordKey, value);
|
|
||||||
const fullOrdPath = `local:|foxs:|station:|slot:/Drivers/NiagaraNetwork/PCCV/points/${ordPath}/${ordKey}`; // 完整路徑
|
|
||||||
console.log("嘗試訪問路徑:", fullOrdPath); // 打印完整路徑
|
|
||||||
|
|
||||||
baja.Ord.make(fullOrdPath)
|
const viewer = forgeViewer.value;
|
||||||
.get()
|
const tree = viewer.model?.getData()?.instanceTree;
|
||||||
.then((folder) => {
|
const fragList = viewer.model?.getFragmentList();
|
||||||
console.log("成功獲取 folder:", folder);
|
|
||||||
const batch = new baja.comm.Batch();
|
|
||||||
const sub = new baja.Subscriber();
|
|
||||||
sub.attach({
|
|
||||||
changed: function (prop, cx) {
|
|
||||||
console.log("數據變更觸發:", prop.$getDisplayName());
|
|
||||||
if (prop.$getDisplayName() !== "Out") return;
|
|
||||||
if (
|
|
||||||
Object.hasOwn(
|
|
||||||
booleanPointFacets.value,
|
|
||||||
prop.$complex.$propInParent.$slotName
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
const facets =
|
|
||||||
booleanPointFacets.value[
|
|
||||||
prop.$complex.$propInParent.$slotName
|
|
||||||
];
|
|
||||||
|
|
||||||
for (let [facetKey, facetValue] of Object.entries(facets)) {
|
if (!tree || !fragList) return new Map();
|
||||||
if (facetValue === prop.$getValue().getValueDisplay()) {
|
|
||||||
updateDeviceData(
|
|
||||||
key,
|
|
||||||
prop.$complex.$propInParent.$slotName,
|
|
||||||
facetKey
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
updateDeviceData(
|
|
||||||
key,
|
|
||||||
prop.$complex.$propInParent.$slotName,
|
|
||||||
prop.$getValue().getValueDisplay()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
console.log("開始遍歷控制點");
|
|
||||||
folder
|
|
||||||
.getSlots()
|
|
||||||
.is("control:ControlPoint")
|
|
||||||
.eachValue((point) => {
|
|
||||||
console.log("找到控制點:", point.getDisplayName());
|
|
||||||
console.log("配置的點位:", Object.keys(value.points));
|
|
||||||
|
|
||||||
if (
|
const newPositions = new Map();
|
||||||
Object.keys(value.points).includes(point.getDisplayName())
|
|
||||||
) {
|
|
||||||
console.log(
|
|
||||||
"匹配到點位,開始訂閱:",
|
|
||||||
point.getDisplayName()
|
|
||||||
);
|
|
||||||
baja.Ord.make(
|
|
||||||
`local:|foxs:|station:|slot:/Drivers/NiagaraNetwork/PCCV/points/${ordPath}/${ordKey}/${point.getDisplayName()}`
|
|
||||||
)
|
|
||||||
.get()
|
|
||||||
.then((component) => {
|
|
||||||
console.log("獲取到 component:", component);
|
|
||||||
if (
|
|
||||||
point.getType().getTypeSpec() ===
|
|
||||||
"control:BooleanWritable"
|
|
||||||
) {
|
|
||||||
const facets = component.getFacets1().toObject();
|
|
||||||
updateFacets(point.getDisplayName(), facets);
|
|
||||||
for (let [facetKey, facetValue] of Object.entries(
|
|
||||||
facets
|
|
||||||
)) {
|
|
||||||
if (
|
|
||||||
facetValue ===
|
|
||||||
component.getOut().getValue().toString()
|
|
||||||
) {
|
|
||||||
updateDeviceData(
|
|
||||||
key,
|
|
||||||
point.getDisplayName(),
|
|
||||||
facetKey
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
updateDeviceData(
|
|
||||||
key,
|
|
||||||
point.getDisplayName(),
|
|
||||||
component.getOut().getValue()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub
|
meterList.forEach((meter) => {
|
||||||
.subscribe({
|
if (meter.forge_dbid) {
|
||||||
comps: component, // Can also just be an singular Component instance
|
try {
|
||||||
batch, // if defined, any network calls will be batched into this object (optional)
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
console.log("subscribed successfully");
|
|
||||||
subComponents.value = sub;
|
|
||||||
})
|
|
||||||
.catch(function (err) {
|
|
||||||
baja.error(
|
|
||||||
"some components failed to subscribe: " + err
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateDbidPosition = (viewer, data) => {
|
|
||||||
if (!viewer) return;
|
|
||||||
if (!forgeViewer.value) forgeViewer.value = markRaw(viewer);
|
|
||||||
const tree = viewer.model.getData().instanceTree;
|
|
||||||
const fragList = viewer.model.getFragmentList();
|
|
||||||
for (let [key, value] of Object.entries(data)) {
|
|
||||||
const nodebBox = new window.THREE.Box3();
|
const nodebBox = new window.THREE.Box3();
|
||||||
|
|
||||||
// for each fragId on the list, get the bounding box
|
// 取得物件的 bounding box
|
||||||
tree.enumNodeFragments(
|
tree.enumNodeFragments(
|
||||||
value.forge_dbid,
|
meter.forge_dbid,
|
||||||
(fragId) => {
|
(fragId) => {
|
||||||
const fragbBox = new window.THREE.Box3();
|
const fragbBox = new window.THREE.Box3();
|
||||||
fragList.getWorldBounds(fragId, fragbBox);
|
fragList.getWorldBounds(fragId, fragbBox);
|
||||||
nodebBox.union(fragbBox); // create a unifed bounding box
|
nodebBox.union(fragbBox);
|
||||||
},
|
},
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
subscribeData.value[key].device_coordinate_3d = viewer.worldToClient(
|
|
||||||
nodebBox.getCenter()
|
if (!nodebBox.isEmpty()) {
|
||||||
);
|
const center = nodebBox.getCenter(new window.THREE.Vector3());
|
||||||
subscribeData.value[key].is_show = viewer.isNodeVisible(value.forge_dbid);
|
const pos2d = viewer.worldToClient(center);
|
||||||
|
newPositions.set(meter.main_id, {
|
||||||
|
x: pos2d.x,
|
||||||
|
y: pos2d.y - 100, // 往上偏移 100px
|
||||||
|
visible: viewer.isNodeVisible(meter.forge_dbid)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.warn(`無法計算 dbid ${meter.forge_dbid} 的位置:`, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return newPositions;
|
||||||
};
|
};
|
||||||
|
|
||||||
const fitToView = () => {
|
const fitToView = () => {
|
||||||
const { x, y, z } = JSON.parse(searchParams.value.camera_position);
|
const { x, y, z } = JSON.parse(searchParams.value.camera_position);
|
||||||
const newPosition = new THREE.Vector3(x, y, z); //!<<< 相机的新位置
|
const newPosition = new THREE.Vector3(x, y, z);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
x: x1,
|
x: x1,
|
||||||
y: y1,
|
y: y1,
|
||||||
z: z1,
|
z: z1,
|
||||||
} = JSON.parse(searchParams.value.target_position); //!<<< 计算新焦点位置
|
} = JSON.parse(searchParams.value.target_position);
|
||||||
const newTarget = new THREE.Vector3(x1, y1, z1); //!<<< 焦點的新位置
|
const newTarget = new THREE.Vector3(x1, y1, z1);
|
||||||
|
forgeViewer.value.navigation.setView(newPosition, newTarget);
|
||||||
forgeViewer.value.navigation.getCamera().setView({
|
|
||||||
position: newPosition.clone(),
|
|
||||||
target: newTarget.clone(),
|
|
||||||
});
|
|
||||||
setTimeout(() => {
|
|
||||||
updateDbidPosition(forgeViewer.value, subscribeData.value);
|
|
||||||
}, 700);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const hideAllObjects = (instanceTree, filDbids = []) => {
|
const hideAllObjects = (instanceTree, filDbids = []) => {
|
||||||
@ -374,7 +153,6 @@ export default function useSystemStatusByBaja(updateHeatBarIsShow) {
|
|||||||
if (filDbids.length > 0) {
|
if (filDbids.length > 0) {
|
||||||
forgeViewer.value.show(filDbids);
|
forgeViewer.value.show(filDbids);
|
||||||
}
|
}
|
||||||
fitToView();
|
|
||||||
forgeViewer.value.impl.invalidate(true);
|
forgeViewer.value.impl.invalidate(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -459,41 +237,20 @@ export default function useSystemStatusByBaja(updateHeatBarIsShow) {
|
|||||||
|
|
||||||
watch([forgeViewer, visibleDbid], ([viewer, dbids]) => {
|
watch([forgeViewer, visibleDbid], ([viewer, dbids]) => {
|
||||||
console.log("監聽到 forgeViewer 或 visibleDbid 的變化", viewer, dbids);
|
console.log("監聽到 forgeViewer 或 visibleDbid 的變化", viewer, dbids);
|
||||||
stopBlinking();
|
|
||||||
clearSprites(); // 清理之前的 Sprites
|
|
||||||
|
|
||||||
if (viewer) {
|
if (viewer) {
|
||||||
hideAllObjects(viewer.model.getData().instanceTree, dbids);
|
hideAllObjects(viewer.model.getData().instanceTree, dbids);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// 判斷新狀態是否需要閃爍和 Sprites
|
watch(
|
||||||
if (viewer && dbids.includes(879)) {
|
[forgeViewer, () => searchParams.value.camera_position],
|
||||||
// startBlinking([879, 1068, 1011, 1065, 855, 1109, 867,963,1044,966,1139,936,1136,957,1133,954,610,1130,951,1041,939,1145,987,999,1148,1002,1151,981,813,1088,825,1091,804]);
|
([viewer, newValue]) => {
|
||||||
const spriteConfigs = [
|
if (viewer && newValue) {
|
||||||
{ dbId: 879, reverse: false },
|
fitToView();
|
||||||
{ dbId: 1011, reverse: false },
|
|
||||||
{ dbId: 855, reverse: true },
|
|
||||||
{ dbId: 867, reverse: true },
|
|
||||||
{ dbId: 963, reverse: false },
|
|
||||||
{ dbId: 966, reverse: true },
|
|
||||||
{ dbId: 936, reverse: true },
|
|
||||||
{ dbId: 957, reverse: true },
|
|
||||||
{ dbId: 954, reverse: true },
|
|
||||||
{ dbId: 951, reverse: true },
|
|
||||||
{ dbId: 939, reverse: true },
|
|
||||||
{ dbId: 987, reverse: true },
|
|
||||||
{ dbId: 999, reverse: true },
|
|
||||||
{ dbId: 1002, reverse: true },
|
|
||||||
{ dbId: 981, reverse: true },
|
|
||||||
{ dbId: 813, reverse: true },
|
|
||||||
{ dbId: 825, reverse: false },
|
|
||||||
{ dbId: 804, reverse: false },
|
|
||||||
];
|
|
||||||
spriteConfigs.forEach(({ dbId, reverse }) => {
|
|
||||||
createSprites(viewer, dbId, reverse);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// 動態Sprites創建函數
|
// 動態Sprites創建函數
|
||||||
const createSprites = async (viewer, dbId, reverse = false) => {
|
const createSprites = async (viewer, dbId, reverse = false) => {
|
||||||
@ -612,15 +369,6 @@ export default function useSystemStatusByBaja(updateHeatBarIsShow) {
|
|||||||
animEnd = tmp;
|
animEnd = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`dbId ${dbId} 動畫資訊:`, {
|
|
||||||
axis: axis,
|
|
||||||
size: size,
|
|
||||||
animStart: animStart,
|
|
||||||
animEnd: animEnd,
|
|
||||||
distance: animStart.distanceTo(animEnd),
|
|
||||||
reverse: reverse,
|
|
||||||
});
|
|
||||||
|
|
||||||
// 4. 建立 SpriteViewable,初始在 animStart
|
// 4. 建立 SpriteViewable,初始在 animStart
|
||||||
const viewable = new DataVizCore.SpriteViewable(
|
const viewable = new DataVizCore.SpriteViewable(
|
||||||
animStart.clone(),
|
animStart.clone(),
|
||||||
@ -655,19 +403,6 @@ export default function useSystemStatusByBaja(updateHeatBarIsShow) {
|
|||||||
arrow.style.transform = `rotate(${angle}deg)`;
|
arrow.style.transform = `rotate(${angle}deg)`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// camera 移動時也要更新所有箭頭(只添加一次事件監聽器)
|
|
||||||
if (!cameraEventAdded) {
|
|
||||||
viewer.addEventListener(
|
|
||||||
Autodesk.Viewing.CAMERA_CHANGE_EVENT,
|
|
||||||
() => {
|
|
||||||
spriteAnimations.forEach((animation) => {
|
|
||||||
animation.updateArrow(animation.currentPos);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
cameraEventAdded = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 動畫主程式
|
// 動畫主程式
|
||||||
let t = 0;
|
let t = 0;
|
||||||
let currentPos = animStart.clone();
|
let currentPos = animStart.clone();
|
||||||
@ -725,8 +460,6 @@ export default function useSystemStatusByBaja(updateHeatBarIsShow) {
|
|||||||
|
|
||||||
// 移除這個 dbId 的記錄
|
// 移除這個 dbId 的記錄
|
||||||
spriteAnimations.delete(dbId);
|
spriteAnimations.delete(dbId);
|
||||||
|
|
||||||
console.log(`已清理 dbId ${dbId} 的 Sprite 資源`);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -751,9 +484,10 @@ export default function useSystemStatusByBaja(updateHeatBarIsShow) {
|
|||||||
return {
|
return {
|
||||||
subscribeData,
|
subscribeData,
|
||||||
visibleDbid,
|
visibleDbid,
|
||||||
updateDbidPosition,
|
updateMeterPositions,
|
||||||
hideAllObjects,
|
hideAllObjects,
|
||||||
updateForgeViewer,
|
updateForgeViewer,
|
||||||
|
updatePipeData,
|
||||||
forgeViewer,
|
forgeViewer,
|
||||||
loadModel,
|
loadModel,
|
||||||
urn,
|
urn,
|
||||||
|
@ -16,14 +16,18 @@ import {
|
|||||||
import { getAssetFloorList } from "@/apis/asset";
|
import { getAssetFloorList } from "@/apis/asset";
|
||||||
import { getOperationCompanyList } from "@/apis/operation";
|
import { getOperationCompanyList } from "@/apis/operation";
|
||||||
import useSearchParams from "@/hooks/useSearchParam";
|
import useSearchParams from "@/hooks/useSearchParam";
|
||||||
|
import useSystemHeatmap from "@/hooks/baja/useSystemHeatmap";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
const initialData = ref(null);
|
const initialData = ref(null);
|
||||||
const realTimeData = ref(null);
|
const realTimeData = ref(null);
|
||||||
|
const pipeData = ref([]);
|
||||||
const realTime = ref(null);
|
const realTime = ref(null);
|
||||||
// 電表列表
|
// 電表列表
|
||||||
const meterList = ref([]);
|
const meterList = ref([]);
|
||||||
const selectedMeter = ref(null);
|
const selectedMeter = ref(null);
|
||||||
|
// 冷藏室及時溫度
|
||||||
|
const heatmapDevices = ref([]);
|
||||||
// 樓層列表
|
// 樓層列表
|
||||||
const floors = ref([]);
|
const floors = ref([]);
|
||||||
// 廠商列表
|
// 廠商列表
|
||||||
@ -48,10 +52,37 @@ const getDevice = async (option = 1) => {
|
|||||||
});
|
});
|
||||||
realTimeData.value = res.data;
|
realTimeData.value = res.data;
|
||||||
if (res.data?.meterData) {
|
if (res.data?.meterData) {
|
||||||
meterList.value = (res.data?.meterData || []).sort();
|
// 先複製 meterList
|
||||||
|
let meters = (res.data?.meterData || []).sort();
|
||||||
|
// 取得 dbid_list
|
||||||
|
const dbidList = initialData.value?.dbid_list || [];
|
||||||
|
// 對每個 meter 做 forge_dbid 對應
|
||||||
|
meters = meters.map((meter) => {
|
||||||
|
const dbidItem = dbidList.find(
|
||||||
|
(d) => d.forge_dbid === meter.forge_dbid
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
...meter,
|
||||||
|
device_coordinate_3d: JSON.parse(dbidItem?.device_coordinate_3d) || null,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
meterList.value = meters;
|
||||||
|
// 如果 selectedMeter 沒有值,且 meterList 有資料,預設選擇第一個
|
||||||
|
if (
|
||||||
|
selectedMeter.value == null &&
|
||||||
|
meterList.value[0]?.main_id !== undefined
|
||||||
|
) {
|
||||||
|
selectedMeter.value = meterList.value[0].main_id;
|
||||||
|
}
|
||||||
|
} else if (res.data?.refrigerationData) {
|
||||||
|
heatmapDevices.value = res.data.refrigerationData;
|
||||||
} else {
|
} else {
|
||||||
meterList.value = [];
|
meterList.value = [];
|
||||||
|
heatmapDevices.value = [];
|
||||||
}
|
}
|
||||||
|
// 水管數據
|
||||||
|
pipeData.value = res.data?.pipeData || [];
|
||||||
|
// 更新熱點圖數據時間
|
||||||
realTime.value = dayjs().format("YYYY-MM-DD HH:mm:ss");
|
realTime.value = dayjs().format("YYYY-MM-DD HH:mm:ss");
|
||||||
console.log("實時數據:", realTimeData.value);
|
console.log("實時數據:", realTimeData.value);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -82,7 +113,7 @@ const startInterval = (option) => {
|
|||||||
// 設定每5秒執行一次
|
// 設定每5秒執行一次
|
||||||
intervalId = setInterval(() => {
|
intervalId = setInterval(() => {
|
||||||
getDevice(option);
|
getDevice(option);
|
||||||
}, 5000);
|
}, 10 * 1000);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 停止定時器
|
// 停止定時器
|
||||||
@ -128,7 +159,14 @@ onUnmounted(() => {
|
|||||||
<DashboardAlert />
|
<DashboardAlert />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Forge :fullScreen="true" :initialData="initialData" :realTime="realTime" />
|
<Forge
|
||||||
|
:fullScreen="true"
|
||||||
|
:initialData="initialData"
|
||||||
|
:pipeData="pipeData"
|
||||||
|
:realTime="realTime"
|
||||||
|
:meterList="meterList"
|
||||||
|
:heatmapDevices="heatmapDevices"
|
||||||
|
/>
|
||||||
<DashboardForgeOptionButton
|
<DashboardForgeOptionButton
|
||||||
:initialData="initialData"
|
:initialData="initialData"
|
||||||
:meterList="meterList"
|
:meterList="meterList"
|
||||||
|
@ -45,6 +45,7 @@ watch(
|
|||||||
changeParams({
|
changeParams({
|
||||||
option: option.option,
|
option: option.option,
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
@ -59,7 +60,9 @@ watch(
|
|||||||
href="#"
|
href="#"
|
||||||
:style="{
|
:style="{
|
||||||
background:
|
background:
|
||||||
props.selectedMeter === meter.main_id ? '#2563eb' : 'transparent',
|
props.selectedMeter === meter.main_id
|
||||||
|
? '#2563eb'
|
||||||
|
: 'transparent',
|
||||||
}"
|
}"
|
||||||
@click.prevent="
|
@click.prevent="
|
||||||
() => {
|
() => {
|
||||||
|
@ -15,7 +15,7 @@ import ValveCard from "./dashboardForgeCards/ValveCard.vue";
|
|||||||
const { searchParams, changeParams } = useSearchParams();
|
const { searchParams, changeParams } = useSearchParams();
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
realTimeData: Object,
|
realTimeData: Object,
|
||||||
selectedMeter: String,
|
selectedMeter: [String, Number, null],
|
||||||
floors: Array,
|
floors: Array,
|
||||||
companyOptions: Array,
|
companyOptions: Array,
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user