CviLux_fe/src/components/forge/index.vue

271 lines
7.3 KiB
Vue

<script setup>
import {
ref,
onMounted,
defineProps,
markRaw,
watch,
nextTick,
provide,
} from "vue";
import { getUrn, getAccessToken } from "@/apis/forge";
import useForgeDbIdStore from "@/stores/useForgeDbIdStore";
import ForgeModal from "./ForgeModal.vue";
import useRefrigerantTemp from "@/hooks/baja/useRefrigerantHeatMap";
import { twMerge } from "tailwind-merge";
import hexToRgb from "@/util/hexToRgb"
const props = defineProps({
data: Array,
fullScreen: Boolean,
});
const deviceList = ref([]);
const forgeDom = ref(null);
const forgeViewer = ref(null);
const forgeViewerModel = ref(null);
const urn = ref("");
let allDbIdsStr = [];
const open = ref(false);
const modalContent = ref(null);
provide("modalContent", modalContent);
const moveModal = (elmnt) => {
console.log(elmnt);
var pos1 = 0,
pos2 = 0,
pos3 = 0,
pos4 = 0;
document.querySelector(
".forge_modal .ant-modal-body .card-title"
).onmousedown = dragMouseDown;
function dragMouseDown(e) {
e = e || window.event;
e.preventDefault();
// get the mouse cursor position at startup:
pos3 = e.clientX;
pos4 = e.clientY;
document.onmouseup = closeDragElement;
// call a function whenever the cursor moves:
document.onmousemove = elementDrag;
}
function elementDrag(e) {
e = e || window.event;
e.preventDefault();
// calculate the new cursor position:
pos1 = pos3 - e.clientX;
pos2 = pos4 - e.clientY;
pos3 = e.clientX;
pos4 = e.clientY;
// set the element's new position:
elmnt.style.top = elmnt.offsetTop - pos2 + "px";
elmnt.style.left = elmnt.offsetLeft - pos1 + "px";
}
function closeDragElement() {
// stop moving when mouse button is released:
document.onmouseup = null;
document.onmousemove = null;
}
};
const toggleModal = async (e) => {
open.value = !open.value;
await nextTick();
if (open.value) {
const elmnt = document.querySelector(".forge_modal .ant-modal");
elmnt.style.top = e.clientY - 20 + "px";
elmnt.style.left = e.clientX + 20 + "px";
moveModal(elmnt);
}
};
const onSpriteClicked = (event) => {
event.hasStopped = true;
const data = deviceList.value.find((d) => d.spriteDbId === event.dbId);
modalContent.value = data;
store.getDbIdStore(data.forge_dbid);
toggleModal(event.originalEvent);
};
// 創建 sprites
const createSprites = async (dataVizExtn) => {
if (!dataVizExtn || !props.data || props.data.length === 0) return;
const DataVizCore = Autodesk.DataVisualization.Core;
const viewableType = DataVizCore.ViewableType.SPRITE;
let spriteColor = new THREE.Color(0xffffff);
const BASEURL = window.env?.VITE_FILE_API_BASEURL;
const spriteIconUrl = `${BASEURL}/hotspot.svg`;
const style = new DataVizCore.ViewableStyle(
viewableType,
spriteColor,
spriteIconUrl
);
const viewableData = new DataVizCore.ViewableData();
viewableData.spriteSize = 24; // Sprites as points of size 24 x 24 pixels
deviceList.value = props.data?.map((myData, index) => {
const dbId = 10 + index;
const position = JSON.parse(myData.device_coordinate_3d);
style.color = new THREE.Color(hexToRgb(myData.device_normal_color));
const viewable = new DataVizCore.SpriteViewable(position, style, dbId);
viewableData.addViewable(viewable);
return {
...myData,
spriteDbId: dbId,
};
});
await viewableData.finish();
dataVizExtn.addViewables(viewableData);
forgeViewer.value.addEventListener(DataVizCore.MOUSE_CLICK, onSpriteClicked);
forgeViewer.value.addEventListener(
Autodesk.Viewing.SELECTION_CHANGED_EVENT,
onSpriteClicked
);
};
const initViewer = (container) => {
return new Promise(function (resolve, reject) {
Autodesk.Viewing.Initializer({ getAccessToken }, function () {
const config = {
extensions: ["Autodesk.DataVisualization", "Autodesk.DocumentBrowser"],
};
let viewer = new Autodesk.Viewing.GuiViewer3D(container, config);
Autodesk.Viewing.Private.InitParametersSetting.alpha = true;
viewer.start();
viewer.setTheme("light-theme");
resolve(viewer);
});
});
};
const loadModel = (viewer, urn) => {
return new Promise(function (resolve, reject) {
async function onDocumentLoadSuccess(doc) {
viewer.setGroundShadow(false);
viewer.impl.renderer().setClearAlpha(0); //clear alpha channel
viewer.impl.glrenderer().setClearColor(0xffffff, 0); //set transparent background, color code does not matter
viewer.impl.invalidate(true); //trigger rendering
const documentNode = await viewer.loadDocumentNode(
doc,
doc.getRoot().getDefaultGeometry()
);
resolve(documentNode);
}
function onDocumentLoadFailure(code, message, errors) {
reject({ code, message, errors });
}
viewer.setLightPreset(0);
Autodesk.Viewing.Document.load(
"urn:" + urn,
onDocumentLoadSuccess,
onDocumentLoadFailure
);
});
};
const hideAllObjects = (viewer, filDbids = []) => {
for (var i = 0; i < allDbIdsStr.length; i++) {
viewer.hide(parseInt(allDbIdsStr[i]));
}
for (var i = 0; i < filDbids.length; i++) {
viewer.show(parseInt(filDbids[i]));
}
viewer.impl.invalidate(true);
};
const initForge = () => {
getUrn().then((res) => {
if (!res.isSuccess) return;
urn.value = res.data[0].urn_3D;
initViewer(forgeDom.value).then((viewer) => {
loadModel(viewer, res.data[0].urn_3D).then(() => {
viewer.addEventListener(
Autodesk.Viewing.GEOMETRY_LOADED_EVENT,
async function () {
forgeViewer.value = markRaw(viewer);
forgeViewerModel.value = viewer.model;
const dataVizExtn = await viewer.loadExtension(
"Autodesk.DataVisualization"
);
createSprites(dataVizExtn);
refrigerantHeatMap.getBasicData(
viewer,
dataVizExtn,
deviceList.value
);
viewer.fitToView([0], viewer.model);
window.setTimeout(() => {
let instanceTree = viewer.model?.getData().instanceTree;
allDbIdsStr = Object.keys(instanceTree.nodeAccess.dbIdToIndex);
const filDbids = deviceList.value.map((x) => x.forge_dbid);
hideAllObjects(forgeViewer.value, filDbids);
}, 500);
}
);
});
});
});
};
onMounted(() => {
initForge();
});
// 聚焦
const store = useForgeDbIdStore();
const fitToView = () => {
forgeViewer.value?.fitToView(store.dbId);
};
const refrigerantHeatMap = useRefrigerantTemp();
watch(
() => store.dbId,
(newVal) => {
if (forgeViewer.value) {
fitToView();
}
}
);
</script>
<template>
<div
:class="
twMerge(
fullScreen
? 'absolute top-0 left-0 w-screen h-screen z-0'
: 'w-full relative'
)
"
>
<slot name="heat_bar"></slot>
<div
id="forge-preview"
ref="forgeDom"
:class="
twMerge(
'relative w-full max-h-full ',
fullScreen ? 'h-screen' : 'min-h-[600px]'
)
"
></div>
</div>
<ForgeModal :open="open" :toggleModal="toggleModal" />
</template>
<style lang="css">
.adsk-viewing-viewer {
background-color: transparent !important;
}
#guiviewer3d-toolbar {
/* display: none; */
bottom: 200px;
}
</style>