123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- <template>
- <iframe class="external" :src="url" ref="iframeRef" v-if="url"></iframe>
- <div class="laser-layer" v-show="!url">
- <div class="scene-canvas" ref="fuseRef" :class="{ full: full === 'scene' }">
- <span class="taggle switch" v-if="full !== 'scene'" @click="full = 'scene'">
- <ui-icon type="f-l" ctrl />
- </span>
- <div id="direction"></div>
- </div>
- <div id="scene-map" :class="{ full: full === 'map' }">
- <span class="taggle switch" v-if="full === 'scene'" @click="full = 'map'">
- <ui-icon type="f-l" ctrl />
- </span>
- </div>
- </div>
- </template>
- <script lang="ts">
- import { defineComponent, ref, watchEffect, computed, watch, nextTick } from "vue";
- import { SceneType } from "@/store";
- import { params } from "@/env";
- import { fuseModel, modelProps } from "./index";
- import { modelSDKFactory } from "./platform";
- const typeChange = () => {
- const oldType = modelProps.type;
- let stopWatch = (null as unknown) as () => void;
- const typePromise = new Promise((_, reject) => {
- stopWatch = watchEffect(() => {
- if (modelProps.type !== oldType) {
- reject(new Error("当前模型未加载完已切换到下个"));
- stopWatch!();
- }
- });
- });
- return { typePromise, typeCleanup: stopWatch };
- };
- export const Model = defineComponent({
- name: "model",
- setup() {
- const scene = computed(() => modelProps.type !== fuseModel && modelProps.type);
- const url = ref("");
- const setUrl = (newURL: string) => {
- if (newURL !== url.value) {
- setTimeout(() => {
- const hook = (iframeRef.value?.contentWindow as any)?.beforeDestroy;
- if (hook) {
- try {
- hook();
- } catch (e) {
- console.error(e);
- }
- url.value = "";
- setTimeout(() => (url.value = newURL), 300);
- } else {
- url.value = newURL;
- }
- });
- }
- };
- watchEffect(() => {
- if (!scene.value) {
- return setUrl("");
- }
- const type = scene.value.type;
- const urls = !(window as any).offline
- ? {
- [SceneType.SWKK]: `/swkk/spg.html?m=${scene.value.num}`,
- [SceneType.SWKJ]: `/swkk/spg.html?m=${scene.value.num}`,
- [SceneType.SWSS]: `/swss/index.html?m=${scene.value.num}`,
- [SceneType.SWSSMX]: `/swkk/spg.html?m=${scene.value.num}`,
- [SceneType.SWMX]: `index.html?caseId=${params.caseId}&app=${params.app}&modelId=${scene.value.num}&share=1#sign-model`,
- [SceneType.SWYDSS]: `/swss/index.html?m=${scene.value.num}`,
- [SceneType.SWYDMX]: `/swkk/spg.html?m=${scene.value.num}`,
- }
- : {
- [SceneType.SWKK]: `/swkk/spg.html?m=${scene.value.num}`,
- [SceneType.SWKJ]: `/swkk/spg.html?m=${scene.value.num}`,
- [SceneType.SWSS]: `/swss/offline.html?m=${scene.value.num}`,
- [SceneType.SWSSMX]: `/swkk/spg.html?m=${scene.value.num}`,
- [SceneType.SWMX]: `offline.html?caseId=${params.caseId}&app=${params.app}&modelId=${scene.value.num}&share=1#sign-model`,
- [SceneType.SWYDSS]: `/swss/offline.html?m=${scene.value.num}`,
- [SceneType.SWYDMX]: `/swkk/spg.html?m=${scene.value.num}`,
- };
- setUrl(urls[type as SceneType]);
- });
- const fuseRef = ref<HTMLDivElement>();
- const iframeRef = ref<HTMLIFrameElement>();
- watch(
- () => [modelProps.type, url.value],
- async ([type, url], oldType, onCleanup) => {
- if (type !== fuseModel && !url) {
- return;
- }
- const callback = modelProps.callback;
- await nextTick();
- const { typePromise, typeCleanup } = typeChange();
- const modelPromise = modelSDKFactory(
- type as any,
- type === fuseModel ? fuseRef.value! : iframeRef.value!
- );
- let result: any = null,
- error = null;
- try {
- result = await Promise.race([typePromise, modelPromise]);
- } catch (err: any) {
- error = err;
- }
- typeCleanup();
- callback && callback(result, error);
- },
- { immediate: true, flush: "post" }
- );
- // 处理iframe 定制页面
- watch(
- () => [scene.value && scene.value.type, url.value],
- ([type], oldType, onCleanup) => {
- if (type === false) {
- // 手动渲染融合场景
- console.log("手动渲染!");
- setTimeout(() => {
- (window as any).viewer.setDisplay(true);
- }, 100);
- }
- const interval = setInterval(async () => {
- let doc: Document | undefined;
- try {
- doc = iframeRef.value?.contentWindow?.document!;
- } catch {
- clearInterval(interval);
- }
- if (!doc || !doc.querySelector("div")) return;
- console.error(doc, doc.head);
- const target = doc.head;
- clearInterval(interval);
- (window as any).iframeCreated && (window as any).iframeCreated(iframeRef.value);
- if (type === SceneType.SWSS) {
- const $style = document.createElement("style");
- $style.type = "text/css";
- var textNode = document.createTextNode(`
- .mode-tab > .model-mode-tab.strengthen {
- display: none !important;
- }
- `);
- $style.appendChild(textNode);
- target.appendChild($style);
- }
- }, 16);
- onCleanup(() => clearInterval(interval));
- },
- { flush: "post", immediate: true }
- );
- return {
- iframeRef,
- full: ref("scene"),
- fuseRef,
- url,
- };
- },
- });
- export default Model;
- </script>
- <style scoped lang="scss">
- .laser-layer {
- position: absolute;
- z-index: 1;
- left: 0;
- top: 0;
- width: 100%;
- height: 100%;
- }
- .external {
- position: absolute;
- z-index: 1;
- border: none;
- top: calc(var(--editor-head-height) + var(--header-top));
- left: 0;
- height: calc(100% - (var(--editor-head-height) + var(--header-top)));
- width: 100%;
- }
- #direction {
- right: calc(var(--editor-menu-right) + var(--editor-toolbox-width)) !important;
- top: calc(var(--header-top) + var(--editor-head-height)) !important;
- margin: 10px;
- transition: top 0.3s ease, right 0.3s ease;
- }
- .scene-canvas,
- #scene-map {
- &:not(.full) {
- position: absolute !important;
- right: calc(var(--editor-menu-right) + var(--editor-toolbox-width)) !important;
- bottom: 0;
- width: 320px;
- height: 200px;
- z-index: 99;
- #direction {
- top: 0 !important;
- right: 0 !important;
- }
- }
- &.full {
- width: 100%;
- height: 100%;
- background-color: #ccc;
- z-index: 90;
- }
- }
- #scene-map {
- display: none;
- }
- .taggle {
- position: absolute;
- font-size: 16px;
- color: #fff;
- background: rgba(0, 0, 0, 0.3);
- z-index: 9999999;
- width: var(--taggle-btn-width);
- height: var(--taggle-btn-width);
- display: flex;
- align-items: center;
- left: 10px;
- top: 10px;
- overflow: hidden;
- justify-content: center;
- border-radius: 3px;
- cursor: pointer;
- }
- </style>
|