forge sprite 配置

This commit is contained in:
JouChun 2024-10-21 23:21:29 -04:00
parent 334d0d5212
commit 520810b1ce
10 changed files with 154 additions and 136 deletions

View File

@ -33,7 +33,7 @@ const updateHeatBarIsShow = (isShow) => {
heat_bar_isShow.value = isShow; heat_bar_isShow.value = isShow;
}; };
const { updateDataVisualization, createSprites, hideAllObjects } = useForgeSprite() const { updateDataVisualization, createSprites, hideAllObjects, forgeClickListener } = useForgeSprite()
const forgeDom = ref(null); const forgeDom = ref(null);
@ -162,9 +162,13 @@ const initForge = async () => {
"Autodesk.Viewing.GEOMETRY_LOADED_EVENT", "Autodesk.Viewing.GEOMETRY_LOADED_EVENT",
viewer.isLoadDone() viewer.isLoadDone()
); );
// updateForgeViewer(viewer);
// createSprites() if (viewer.isLoadDone()) {
hideAllObjects(); // updateForgeViewer(viewer);
hideAllObjects();
createSprites();
forgeClickListener();
}
}) })
}; };

View File

@ -18,9 +18,9 @@ const iniFroList = async () => {
res.data.map((d) => res.data.map((d) =>
AUTHPAGES.find(({ authCode }) => authCode === d.authCode) AUTHPAGES.find(({ authCode }) => authCode === d.authCode)
? { ? {
...d, ...d,
...AUTHPAGES.find(({ authCode }) => authCode === d.authCode), ...AUTHPAGES.find(({ authCode }) => authCode === d.authCode),
} }
: d : d
) )
); );
@ -71,85 +71,38 @@ onMounted(() => {
<template> <template>
<ul class="px-1 menu-box my-2"> <ul class="px-1 menu-box my-2">
<li class="flex flex-col items-center justify-center"> <li class="flex flex-col items-center justify-center">
<router-link <router-link :to="{ name: 'dashboard' }" class="flex flex-col justify-center items-center btn-group text-white">
:to="{ name: 'dashboard' }" <font-awesome-icon :icon="['fas', 'home']" size="2x" class="w-10 m-auto" />
class="flex flex-col justify-center items-center btn-group text-white"
>
<font-awesome-icon
:icon="['fas', 'home']"
size="2x"
class="w-10 m-auto"
/>
{{ $t("home") }} {{ $t("home") }}
</router-link> </router-link>
</li> </li>
<li <li v-for="page in authPages" class="flex flex-col items-center justify-center">
v-for="page in authPages" <a v-if="page.authCode === 'PF1'" @click="showDrawer"
class="flex flex-col items-center justify-center" class="flex flex-col justify-center items-center btn-group text-white cursor-pointer">
> <font-awesome-icon :icon="['fas', page.icon]" size="2x" class="w-10 m-auto" />
<a
v-if="page.authCode === 'PF1'"
@click="showDrawer"
class="flex flex-col justify-center items-center btn-group text-white cursor-pointer"
>
<font-awesome-icon
:icon="['fas', page.icon]"
size="2x"
class="w-10 m-auto"
/>
{{ page.subName }} {{ page.subName }}
</a> </a>
<router-link <router-link v-else :to="page.navigate" type="link"
v-else class="flex flex-col justify-center items-center btn-group text-white">
:to="page.navigate" <font-awesome-icon :icon="['fas', page.icon]" size="2x" class="w-10 m-auto" />
type="link"
class="flex flex-col justify-center items-center btn-group text-white"
>
<font-awesome-icon
:icon="['fas', page.icon]"
size="2x"
class="w-10 m-auto"
/>
{{ page.subName }} {{ page.subName }}
</router-link> </router-link>
</li> </li>
</ul> </ul>
<a-drawer <a-drawer :width="250" placement="left" :open="open" :closable="false" @close="onClose" class="sub-drawer"
:width="250" :maskStyle="{ opacity: 0 }" :bodyStyle="{ paddingLeft: 0, paddingRight: 0 }">
placement="left" <a-menu mode="inline" theme="dark" class="text-lg bg-transparent" :openKeys="openKeys"
:open="open" @openChange="handleOpenChange">
:closable="false" <a-sub-menu v-for="main in buildingStore.mainSubSys" :key="main.main_system_tag" :title="main.full_name">
@close="onClose" <a-menu-item v-for="sub in main.history_Sub_systems" :key="sub.sub_system_tag" @click="() => onClose()">
class="sub-drawer" <router-link :to="{
:maskStyle="{ opacity: 0 }" name: 'sub_system',
:bodyStyle="{ paddingLeft: 0, paddingRight: 0 }" params: {
> main_system_id: main.main_system_tag,
<a-menu sub_system_id: sub.sub_system_tag,
mode="inline" floor_id: 'main'
theme="dark" },
class="text-lg bg-transparent" }">
:openKeys="openKeys"
@openChange="handleOpenChange"
>
<a-sub-menu
v-for="main in buildingStore.mainSubSys"
:key="main.main_system_tag"
:title="main.full_name"
>
<a-menu-item
v-for="sub in main.history_Sub_systems"
:key="sub.sub_system_tag"
@click="() => onClose()"
>
<router-link
:to="{
name: 'sub_system',
params: {
main_system_id: main.main_system_tag,
sub_system_id: sub.sub_system_tag,
},
}"
>
{{ sub.full_name }} {{ sub.full_name }}
</router-link> </router-link>
</a-menu-item> </a-menu-item>
@ -166,16 +119,19 @@ onMounted(() => {
color: #35759d !important; color: #35759d !important;
background-color: transparent !important; background-color: transparent !important;
} }
::v-deep .ant-menu-item:not(.ant-menu-item-selected) { ::v-deep .ant-menu-item:not(.ant-menu-item-selected) {
&::before { &::before {
@apply absolute w-[15px] h-[15px] bottom-3.5 left-7 bg-no-repeat z-10 grayscale; @apply absolute w-[15px] h-[15px] bottom-3.5 left-7 bg-no-repeat z-10 grayscale;
content: ""; content: "";
background: url(@ASSET/img/chart-data-background03.svg) center center; background: url(@ASSET/img/chart-data-background03.svg) center center;
} }
&:active { &:active {
background-color: transparent !important; background-color: transparent !important;
} }
} }
::v-deep .ant-menu-item-selected { ::v-deep .ant-menu-item-selected {
@apply bg-transparent relative; @apply bg-transparent relative;
@ -184,9 +140,11 @@ onMounted(() => {
content: ""; content: "";
background: url(@ASSET/img/chart-data-background03.svg) center center; background: url(@ASSET/img/chart-data-background03.svg) center center;
} }
&:active { &:active {
background-color: transparent !important; background-color: transparent !important;
} }
a { a {
color: #89d2ff !important; color: #89d2ff !important;
text-shadow: 0px 0px 1px #fff; text-shadow: 0px 0px 1px #fff;

View File

@ -1,6 +1,8 @@
import { watch, inject, markRaw, ref } from "vue"; import { watch, inject, markRaw, ref, computed } from "vue";
import useAlarmStore from "@/stores/useAlarmStore"; import useAlarmStore from "@/stores/useAlarmStore";
import hexToRgb from "@/util/hexToRgb"; import hexToRgb from "@/util/hexToRgb";
import { useRoute } from "vue-router";
import useSelectedFloor from "@/hooks/useSelectedFloor";
export default function useForgeSprite() { export default function useForgeSprite() {
const store = useAlarmStore(); const store = useAlarmStore();
@ -12,7 +14,7 @@ export default function useForgeSprite() {
forgeViewer.value = markRaw(viewer); forgeViewer.value = markRaw(viewer);
} }
const dataVisualization = await NOP_VIEWER.loadExtension( const dataVisualization = await viewer.loadExtension(
"Autodesk.DataVisualization" "Autodesk.DataVisualization"
); );
dataVizExtn.value = markRaw(dataVisualization); dataVizExtn.value = markRaw(dataVisualization);
@ -20,41 +22,78 @@ export default function useForgeSprite() {
const onSpriteClicked = (event) => { const onSpriteClicked = (event) => {
event.hasStopped = true; event.hasStopped = true;
const data = deviceList.value.find((d) => d.spriteDbId === event.dbId); console.log("onSpriteClicked", event);
modalContent.value = data; // const data = deviceList.value.find((d) => d.spriteDbId === event.dbId);
store.getDbIdStore(data.forge_dbid); // modalContent.value = data;
toggleModal(event.originalEvent);
}; };
const { selectedFloor } = useSelectedFloor();
const showData = computed(() =>
selectedFloor.value?.key === "main"
? subscribeData.value
: subscribeData.value.filter(
({ floor_guid }) => floor_guid === selectedFloor.value?.key
) || []
);
// 創建 sprites // 創建 sprites
const createSprites = async () => { const createSprites = async () => {
const DataVizCore = Autodesk.DataVisualization.Core; if (dataVizExtn.value) {
const viewableType = DataVizCore.ViewableType.SPRITE; dataVizExtn.value.removeAllViewables();
let spriteColor = new THREE.Color(0xffffff); const DataVizCore = Autodesk.DataVisualization.Core;
const BASEURL = import.meta.env.VITE_FORGE_BASEURL; const viewableType = DataVizCore.ViewableType.SPRITE;
const spriteIconUrl = `${BASEURL}/hotspot.svg`; let spriteColor = new THREE.Color(0xffffff);
const style = new DataVizCore.ViewableStyle( const BASEURL = import.meta.env.VITE_FORGE_BASEURL;
viewableType, const spriteIconUrl = `${BASEURL}/hotspot.svg`;
spriteColor, const style = new DataVizCore.ViewableStyle(
spriteIconUrl viewableType,
); spriteColor,
const viewableData = new DataVizCore.ViewableData(); spriteIconUrl
viewableData.spriteSize = 24; // Sprites as points of size 24 x 24 pixels );
subscribeData.value?.forEach((d, index) => { const viewableData = new DataVizCore.ViewableData();
if (d.device_coordinate_3d) { viewableData.spriteSize = 24; // Sprites as points of size 24 x 24 pixels
const position = d.device_coordinate_3d; showData.value?.forEach((d, index) => {
style.color = new THREE.Color(hexToRgb(d.device_normal_color)); if (d.device_coordinate_3d) {
const viewable = new DataVizCore.SpriteViewable( console.log(d.device_coordinate_3d);
position, const position = d.device_coordinate_3d;
style, style.color = new THREE.Color(hexToRgb(d.device_normal_color));
d.spriteDbId const viewable = new DataVizCore.SpriteViewable(
); position,
viewableData.addViewable(viewable); style,
} d.spriteDbId
}); );
await viewableData.finish(); viewableData.addViewable(viewable);
dataVizExtn.value.addViewables(viewableData); }
});
// await viewableData.finish();
// dataVizExtn.value.addViewables(viewableData);
// console.log(dataVizExtn.value);
viewableData.then(
() => {
dataVizExtn.value.addViewables(viewableData);
},
(error) => {
console.log(error);
}
);
}
};
forgeViewer.value.addEventListener(DataVizCore.MOUSE_CLICK, onSpriteClicked); watch(
() => showData,
() => {
forgeViewer.value?.isLoadDone() && createSprites();
},
{
deep: true,
}
);
const forgeClickListener = () => {
forgeViewer.value.addEventListener(
Autodesk.DataVisualization.Core.MOUSE_CLICK,
onSpriteClicked
);
forgeViewer.value.addEventListener( forgeViewer.value.addEventListener(
Autodesk.Viewing.SELECTION_CHANGED_EVENT, Autodesk.Viewing.SELECTION_CHANGED_EVENT,
onSpriteClicked onSpriteClicked
@ -99,5 +138,6 @@ export default function useForgeSprite() {
createSprites, createSprites,
updateDataVisualization, updateDataVisualization,
hideAllObjects, hideAllObjects,
forgeClickListener,
}; };
} }

View File

@ -0,0 +1,17 @@
import { useRoute } from "vue-router";
import { computed, inject, ref, watch } from "vue";
function useSelectedFloor() {
const { currentFloor } = inject("system_deviceList");
const route = useRoute();
const selectedFloor = computed(() =>
currentFloor.value?.find(({ key }) => key == route.params.floor_id)
);
return {
selectedFloor,
currentFloor,
};
}
export default useSelectedFloor;

View File

@ -38,15 +38,10 @@ const router = createRouter({
component: System, component: System,
children: [ children: [
{ {
path: "", path: ":floor_id",
name: "sub_system", name: "sub_system",
component: SystemMain, component: SystemMain,
}, },
{
path: "floor/:floor_id",
name: "floor",
component: SystemFloor,
},
], ],
}, },
{ {

View File

@ -7,6 +7,7 @@ import ForgeForSystem from "@/components/forge/ForgeForSystem.vue";
import { getSystemDevices, getSystemRealTime } from "@/apis/system"; import { getSystemDevices, getSystemRealTime } from "@/apis/system";
import SystemSubBar from './components/SystemSubBar.vue'; import SystemSubBar from './components/SystemSubBar.vue';
import SystemInfoModal from './components/SystemInfoModal.vue'; import SystemInfoModal from './components/SystemInfoModal.vue';
import SystemMain from "./SystemMain.vue"
const buildingStore = useBuildingStore() const buildingStore = useBuildingStore()
@ -41,7 +42,7 @@ const getData = async () => {
forge_dbid: parseInt(dev.forge_dbid), forge_dbid: parseInt(dev.forge_dbid),
device_coordinate_3d: dev.device_coordinate_3d device_coordinate_3d: dev.device_coordinate_3d
? JSON.parse(dev.device_coordinate_3d) ? JSON.parse(dev.device_coordinate_3d)
: { x: 0, y: 0 }, : null,
alarmMsg: "", alarmMsg: "",
is_show: true, is_show: true,
currentColor: dev.device_normal_point_color, currentColor: dev.device_normal_point_color,
@ -79,7 +80,7 @@ watch(raw_data, (newValue) => {
}); });
const updateDataByGas = (gas) => { const updateDataByGas = (gas) => {
console.log(`updateDataByGas`, gas)
const update_values = raw_data.value.map((d) => ( const update_values = raw_data.value.map((d) => (
{ {
...d, ...d,
@ -98,8 +99,8 @@ watch(() => buildingStore.selectedBuilding, (newBuilding) => {
deep: true, deep: true,
}) })
watch(route, (newRoute, oldRoute) => { watch(() => route.params.sub_system_id, (newRoute, oldRoute) => {
if (buildingStore.selectedBuilding && newRoute.params.sub_system_id !== oldRoute?.params.sub_system_id) { if (buildingStore.selectedBuilding && newRoute !== oldRoute) {
getData() getData()
} }
}) })
@ -195,6 +196,7 @@ provide("system_selectedDevice", { selectedDeviceRealtime, selectedDevice, getCu
</div> </div>
</div> </div>
<div class="col-span-1 h-full"> <div class="col-span-1 h-full">
<ForgeForSystem :initialData="{}" /> <ForgeForSystem :initialData="{}" />
</div> </div>
</div> </div>

View File

@ -3,6 +3,8 @@ import { useRoute } from 'vue-router';
import EffectScatter from "@/components/chart/EffectScatter.vue"; import EffectScatter from "@/components/chart/EffectScatter.vue";
import { computed, inject, ref, watch } from 'vue'; import { computed, inject, ref, watch } from 'vue';
import { twMerge } from 'tailwind-merge'; import { twMerge } from 'tailwind-merge';
import useSelectedFloor from "@/hooks/useSelectedFloor"
const route = useRoute() const route = useRoute()
const { currentFloor, subscribeData } = inject("system_deviceList") const { currentFloor, subscribeData } = inject("system_deviceList")
@ -34,7 +36,7 @@ const defaultOption = (map, data = []) => ({
}, },
}); });
const selectedFloor = computed(() => currentFloor.value?.find(({ key }) => key == route.params.floor_id)) const { selectedFloor } = useSelectedFloor()
watch([selectedFloor, () => asset_floor_chart, subscribeData], ([newValue, newChart, newData]) => { watch([selectedFloor, () => asset_floor_chart, subscribeData], ([newValue, newChart, newData]) => {
if (newValue && newChart.value) { if (newValue && newChart.value) {

View File

@ -1,17 +1,26 @@
<script setup> <script setup>
import { inject } from "vue" import { computed, inject, watch } from "vue"
import useSelectedFloor from "@/hooks/useSelectedFloor"
const { data } = inject("system_deviceList") const { data } = inject("system_deviceList")
const { getCurrentInfoModalData } = inject("system_selectedDevice") const { getCurrentInfoModalData } = inject("system_selectedDevice")
const { selectedFloor } = useSelectedFloor()
const showData = computed(() => selectedFloor.value?.key === 'main' ? data.value : data.value.filter(({ floor_guid }) => floor_guid === selectedFloor.value?.key) || [])
watch(selectedFloor, (newValue) => {
console.log(newValue)
})
</script> </script>
<template> <template>
<!-- <InfoModal :data="currentInfoModalData" /> --> <!-- <InfoModal :data="currentInfoModalData" /> -->
<template v-if="data.length > 0"> <template v-if="showData.length > 0">
<div class="equipment-show" v-for="d in data" :key="d.full_name"> <div class="equipment-show" v-for="d in showData" :key="d.full_name">
<template v-if="d.device_list.length > 0"> <template v-if="d.device_list.length > 0">
<p class="title">{{ d.full_name }}</p> <p class="title">{{ d.full_name }}</p>
<div class="grid grid-cols-3 gap-5"> <div class="grid grid-cols-3 gap-5">

View File

@ -19,7 +19,7 @@ const getFloors = async () => {
{ {
title: "總覽", title: "總覽",
key: "main", key: "main",
active: route.params.floor_id ? false : true, active: route.params.floor_id === "main",
}, },
...data.floors.map((d, idx) => ({ ...data.floors.map((d, idx) => ({
title: d.full_name, title: d.full_name,
@ -36,20 +36,11 @@ const getFloors = async () => {
const onClick = (item) => { const onClick = (item) => {
changeActiveBtn(item) changeActiveBtn(item)
if (item.key == "main") { router.push({
router.push({
name: 'sub_system', params: { name: 'sub_system', params: {
...route.params
}, query: { gas: route.query.gas }
})
} else {
router.push({
name: 'floor', params: {
...route.params, floor_id: item.key ...route.params, floor_id: item.key
}, query: { gas: route.query.gas } }, query: { gas: route.query.gas }
}) })
}
} }

View File

@ -14,7 +14,7 @@ watch(() => buildingStore, (newValue) => {
newValue.selectedSystem?.points?.length > 0 && setItems(newValue.selectedSystem.points.map(d => ({ newValue.selectedSystem?.points?.length > 0 && setItems(newValue.selectedSystem.points.map(d => ({
title: d.full_name, title: d.full_name,
key: d.points, key: d.points,
active: route.query.gas ? route.query.gas === d.points : d.points === "Temp", active: route.query.gas ? route.query.gas === d.points : d.points === "temp",
}))) })))
}, { }, {
deep: true, deep: true,