ソースを参照

[Feat 0000] 除尘风机添加环境监测、模型添加详情框

houzekong 2 ヶ月 前
コミット
36c0f1cddb

+ 0 - 1
src/components/Table/src/hooks/useCustomSelection.tsx

@@ -530,7 +530,6 @@ function getTableBody(wrap: HTMLDivElement) {
   return new Promise<HTMLDivElement>((resolve) => {
     (function fn() {
       const bodyEl = wrap.querySelector(`.${ventSpace}-table-wrapper .${ventSpace}-table-body`) as HTMLDivElement;
-      console.log('debug r', bodyEl);
       if (bodyEl) {
         resolve(bodyEl);
       } else {

+ 99 - 73
src/views/vent/monitorManager/dedustMonitor/components/DedustHome.vue

@@ -1,41 +1,73 @@
 <template>
-  <a-spin tip="Loading..." :spinning="loading">
-    <div class="monitor-container">
-      <div style="position: absolute; height: 40px; width: 100%; top: calc(50%-20px); font-size: 20px; color: red; text-align: center">
-        {{ deviceInfo.warnDes }}
+  <div
+    v-show="!loading"
+    id="dedustCss"
+    style="width: 100%; height: 100%; position: absolute; pointer-events: none; overflow: hidden; z-index: 2; top: 0px; left: 0px"
+  >
+    <FourBorderBg id="dedustEnvA">
+      <div class="monitor-item" v-for="(data, index) in dedustEnvModalA" :key="index" :id="`dedustCss3D${index}`">
+        <span class="monitor-title">{{ data.label }}:</span>
+        <span class="monitor-val">{{ get(deviceInfo, data.prop, '-') }}</span>
       </div>
-      <div class="lr left-box vent-margin-t-10">
-        <ventBox1>
-          <template #title>
-            <div>除尘机状态</div>
-          </template>
-          <template #container>
-            <List icon="warning-title" type="status-light" :labelWidth="130" layout="double-columns" title="故障状态" v-bind="dedustStatusPropA" />
-            <List icon="warning-title" type="status-light" :labelWidth="300" title="报警状态" v-bind="dedustStatusPropB" />
-            <List icon="warning-title" type="status-light" :labelWidth="280" title="激活状态" v-bind="dedustStatusPropC" />
-          </template>
-        </ventBox1>
-      </div>
-      <div class="lr right-box">
-        <ventBox1 class="vent-margin-t-10">
-          <template #title>
-            <div>监测参数</div>
-          </template>
-          <template #container>
-            <List :labelWidth="200" v-bind="dedustMonitorProp" />
-          </template>
-        </ventBox1>
+      <!-- <div class="title">
+        {{ monitorData[groupNum - 1]['strname'] }}
+      </div> -->
+    </FourBorderBg>
+    <FourBorderBg id="dedustEnvB">
+      <div class="monitor-item" v-for="(data, index) in dedustEnvModalB" :key="index" :id="`dedustCss3D${index}`">
+        <span class="monitor-title">{{ data.label }}:</span>
+        <span class="monitor-val">{{ get(deviceInfo, data.prop, '-') }}</span>
       </div>
+    </FourBorderBg>
+  </div>
+  <div class="monitor-container">
+    <div style="position: absolute; height: 40px; width: 100%; top: calc(50%-20px); font-size: 20px; color: red; text-align: center">
+      {{ deviceInfo.warnDes }}
+    </div>
+    <div class="lr left-box vent-margin-t-10">
+      <ventBox1>
+        <template #title>
+          <div>除尘机状态</div>
+        </template>
+        <template #container>
+          <List icon="warning-title" type="status-light" :labelWidth="130" layout="double-columns" title="故障状态" v-bind="dedustStatusPropA" />
+          <List icon="warning-title" type="status-light" :labelWidth="300" title="报警状态" v-bind="dedustStatusPropB" />
+          <List icon="warning-title" type="status-light" :labelWidth="280" title="激活状态" v-bind="dedustStatusPropC" />
+        </template>
+      </ventBox1>
+    </div>
+    <div class="lr right-box">
+      <ventBox1 class="vent-margin-t-10">
+        <template #title>
+          <div>监测参数</div>
+        </template>
+        <template #container>
+          <List :labelWidth="200" v-bind="dedustMonitorProp" />
+        </template>
+      </ventBox1>
+      <ventBox1>
+        <template #title>
+          <div>环境参数</div>
+        </template>
+        <template #container>
+          <List :labelWidth="200" v-bind="dedustEnvProp" />
+        </template>
+      </ventBox1>
     </div>
-  </a-spin>
+  </div>
 </template>
 
 <script setup lang="ts">
-  import { onBeforeMount, ref, onMounted, onUnmounted, reactive, defineProps, computed } from 'vue';
+  import FourBorderBg from '/@/views/vent/comment/components/fourBorderBg.vue';
+  import { onBeforeMount, ref, onMounted, onUnmounted, defineProps, computed } from 'vue';
   import { list } from '../dedust.api';
   import ventBox1 from '/@/components/vent/ventBox1.vue';
+  import { mountedThree, destroy, setModelType } from '../dedust.threejs';
   // import { SvgIcon } from '/@/components/Icon';
   import {
+    dedustEnvConfig,
+    dedustEnvModalA,
+    dedustEnvModalB,
     dedustMonitorConfig,
     dedustStatusConfigA,
     dedustStatusConfigB,
@@ -46,6 +78,7 @@
   } from '../dedust.data';
   import List from '/@/views/vent/gas/components/list/index.vue';
   import _ from 'lodash';
+  import { get } from '../../../home/billboard/utils';
 
   const props = defineProps({
     deviceId: {
@@ -55,17 +88,7 @@
   });
 
   const loading = ref(false);
-
-  // 默认初始是第一行
-  // const openDust = ref(false);
   const deviceInfo = ref<any>({});
-  const workFaceSource = ref({});
-  const workFaceHistorySource = ref([]);
-  // const gateDataSource = ref([]);
-  // const windowDataSource = ref([]);
-  // const windDataSource = ref([]);
-  // const temperatureDataSource = ref([]);
-  // const fireDataSource = ref([]);
 
   // 将列表配置项转换为列表可用的prop
   function transConfigToProp(config, source) {
@@ -91,6 +114,11 @@
       items: transConfigToProp(dedustMonitorConfig, deviceInfo.value),
     };
   });
+  const dedustEnvProp = computed(() => {
+    return {
+      items: transConfigToProp(dedustEnvConfig, deviceInfo.value),
+    };
+  });
   const dedustStatusPropA = computed(() => {
     return {
       status: statusConfigA as any,
@@ -110,62 +138,60 @@
     };
   });
 
-  // 监测数据
-  const selectData = reactive({});
-
   // https获取监测数据
-  let timer: null | NodeJS.Timeout = null;
-  function getMonitor(flag?) {
-    if (Object.prototype.toString.call(timer) === '[object Null]') {
-      timer = setTimeout(
-        async () => {
-          if (props.deviceId) {
-            const data = await getDataSource(props.deviceId);
-            Object.assign(selectData, data);
-          }
-          if (timer) {
-            timer = null;
-          }
-          await getMonitor();
-          loading.value = false;
-        },
-        flag ? 0 : 1000
-      );
-    }
-  }
-
+  let timer: NodeJS.Timeout;
   async function getDataSource(systemID) {
     const res = await list({ devicetype: 'sys', systemID, type: 'all' });
-    res.deviceInfo.dedustefan.datalist.forEach((e: any) => {
+    // 保留第一项数据
+    _.forEach(_.get(res, 'deviceInfo.dedustefan.datalist', []), (e) => {
       Object.assign(e, e.readData);
-      e.readData = null;
+      deviceInfo.value = e || { warnDes: '设备断开' };
+      return -1;
     });
-    deviceInfo.value = _.get(res, 'deviceInfo.dedustefan.datalist[0]', { warnDes: '设备断开' });
-    workFaceHistorySource.value = res.sysInfo.history;
-    workFaceSource.value = Object.assign(res.sysInfo, res.sysInfo.readData);
-    loading.value = false;
   }
 
   onBeforeMount(() => {});
 
-  onMounted(async () => {
+  onMounted(() => {
     loading.value = true;
-    timer = null;
-    await getMonitor(true);
+    mountedThree('#dedust3D', ['#dedustCss', '#dedustEnvA', '#dedustEnvB']).then(() => {
+      setModelType('dedust').finally(() => {
+        loading.value = false;
+      });
+    });
+    timer = setInterval(() => {
+      getDataSource(props.deviceId);
+    }, 1000);
   });
   onUnmounted(() => {
-    if (timer) {
-      clearTimeout(timer);
-      timer = null;
-    }
+    clearInterval(timer);
+    destroy();
   });
 </script>
 <style lang="less" scoped>
+  @import '/@/design/theme.less';
   @import '/@/design/vent/modal.less';
   // @import '../less/tunFace.less';
   @import '../../comment/less/workFace.less';
   @ventSpace: zxm;
 
+  .monitor-item {
+    display: flex;
+    justify-content: space-between;
+    margin-bottom: 3px;
+
+    .monitor-val {
+      font-size: 14px;
+    }
+  }
+
+  .monitor-title {
+    width: 200px;
+    color: var(--vent-font-action-link);
+    font-weight: 400;
+    font-size: 14px;
+  }
+
   .dust-fan-monitor {
     display: flex;
     flex-wrap: wrap;

+ 25 - 32
src/views/vent/monitorManager/dedustMonitor/dedust.data.ts

@@ -27,40 +27,33 @@ export const dedustMonitorConfig = [
   //   prop: 'FrequencySetPoint',
   //   label: '给定频率',
   // },
-  {
-    prop: 'Outputcurrent',
-    label: '输出电流(A)',
-  },
-  {
-    prop: 'Current1',
-    label: '前机电流(A)',
-  },
-  {
-    prop: 'Current2',
-    label: '后机电流(A)',
-  },
-  {
-    prop: 'OutputVoltage',
-    label: '输出电压(V)',
-  },
-  {
-    prop: 'OutputPower',
-    label: '输出功率(kW)',
-  },
-  {
-    prop: 'Frequency',
-    label: '运行频率(Hz)',
-  },
-  {
-    prop: 'BusVoltage',
-    label: '母线电压(V)',
-  },
-  {
-    prop: 'FrequencySetPoint',
-    label: '给定频率(Hz)',
-  },
+  { prop: 'Outputcurrent', label: '输出电流(A)' },
+  { prop: 'Current1', label: '前机电流(A)' },
+  { prop: 'Current2', label: '后机电流(A)' },
+  { prop: 'OutputVoltage', label: '输出电压(V)' },
+  { prop: 'OutputPower', label: '输出功率(kW)' },
+  { prop: 'Frequency', label: '运行频率(Hz)' },
+  { prop: 'BusVoltage', label: '母线电压(V)' },
+  { prop: 'FrequencySetPoint', label: '给定频率(Hz)' },
 ];
 
+export const dedustEnvConfig = [
+  { prop: 'temperature', label: '掘进工作面温度(℃)' },
+  { prop: 'gas', label: '掘进工作面甲烷(%CH₄)' },
+  { prop: 'dust', label: '掘进工作面粉尘(mg/m³)' },
+  { prop: 'hflgas', label: '掘进工作面回风流甲烷(%CH₄)' },
+  { prop: 'smoke_str', label: '掘进工作面皮带机尾烟雾' },
+];
+
+/** 用于模型css详情展示的配置 */
+export const dedustEnvModalA = [
+  { prop: 'gas', label: '掘进工作面甲烷(%CH₄)' },
+  { prop: 'dust', label: '掘进工作面粉尘(mg/m³)' },
+  { prop: 'smoke_str', label: '掘进工作面皮带机尾烟雾' },
+];
+
+export const dedustEnvModalB = [{ prop: 'hflgas', label: '掘进工作面回风流甲烷(%CH₄)' }];
+
 /** 故障相关配置 */
 export const dedustStatusConfigA = [
   {

+ 46 - 67
src/views/vent/monitorManager/dedustMonitor/dedust.threejs.base.ts

@@ -1,16 +1,27 @@
 import * as THREE from 'three';
+import { CSS3DSprite } from 'three/examples/jsm/renderers/CSS3DRenderer';
+import { setModalCenter } from '/@/utils/threejs/util';
 // import { setModalCenter } from '/@/utils/threejs/util';
-import Smoke from '/@/views/vent/comment/threejs/Smoke';
 // import * as dat from 'dat.gui';
 // const gui = new dat.GUI();
 // gui.domElement.style = 'position:absolute;top:100px;left:10px;z-index:99999999999999';
 
-class WorkFace {
+class ModelContext {
   model;
   modelName = 'tunFace';
+  // modelName = 'dedust';
   group: THREE.Object3D | null = null;
-  inSmoke: Smoke | null = null;
-  outSmoke: Smoke | null = null;
+  /** 本模型内支持的锚点位置数组 */
+  anchors: [number, number, number][] = [
+    [-46.1, -12.8, 8],
+    // [0, 0, 0],
+    // 右侧传感器
+    [11.7, -14, 8],
+    // [-25.847, 8.783, 3.267],
+    // [31.142, 8.783, 3.267],
+  ];
+  /** 本模型显示的css详情元素数组 */
+  cssSprites: CSS3DSprite[] = [];
 
   constructor(model) {
     this.model = model;
@@ -26,77 +37,48 @@ class WorkFace {
     pointLight.position.set(45, 51, -4.1);
     pointLight.shadow.bias = 0.05;
     this.model.scene.add(pointLight);
-
-    // gui.add(directionalLight.position, 'x', -100, 100);
-    // gui.add(directionalLight.position, 'y', -100, 100);
-    // gui.add(directionalLight.position, 'z', -100, 100);
   }
 
-  addChamberText() {
-    //
+  /** 初始化css元素,将css元素选择器传入,该方法会将这些元素按顺序放入本模型支持的锚点中 */
+  initCssElement(selectors: string[]) {
+    selectors.forEach((selector, index) => {
+      const element = document.querySelector(selector) as HTMLElement;
+      if (element) {
+        const css3D = new CSS3DSprite(element);
+        this.cssSprites.push(css3D);
+        css3D.name = selector;
+        css3D.scale.set(0.05, 0.05, 0.05);
+        // const ff = gui.addFolder(`css元素${index}`);
+        // ff.add(css3D.position, 'x', -100, 100);
+        // ff.add(css3D.position, 'y', -100, 100);
+        // ff.add(css3D.position, 'z', -100, 100);
+        if (index < this.anchors.length) {
+          const [x, y, z] = this.anchors[index];
+          css3D.position.set(x, y, z);
+          this.group?.add(css3D);
+        } else {
+          console.warn(`指定的元素${selector}没有合适的位置放置`);
+        }
+      }
+    });
   }
 
-  initFly = async () => {
-    const inCurve = [
-      {
-        path0: new THREE.Vector3(-15.134, 3.734, -3.485),
-        path1: new THREE.Vector3(-17.13, 3.734, -3.485),
-        isSpread: false,
-        spreadDirection: 0,
-      },
-      {
-        path0: new THREE.Vector3(-17.13, 3.734, -3.485),
-        path1: new THREE.Vector3(-19.518, 3.075, 2.071),
-        isSpread: true,
-        spreadDirection: 1, // 1是由小变大,-1是由大变小
-      },
-    ];
-
-    const outCurve = [
-      {
-        path0: new THREE.Vector3(-31.51, 3.075, 2.071),
-        path1: new THREE.Vector3(-26.51, 3.075, 2.071),
-        isSpread: true,
-        spreadDirection: -1,
-      },
-      {
-        path0: new THREE.Vector3(-26.51, 3.075, 2.071),
-        path1: new THREE.Vector3(-24.514, 3.075, 2.071),
-        isSpread: false,
-        spreadDirection: 0, // 1是由小变大,-1是由大变小
-      },
-    ];
-
-    if (!this.inSmoke) {
-      this.inSmoke = new Smoke('/model/img/texture-smoke.png', '#ffffff', 0, 0.5, 0.5, 30);
-      this.inSmoke.setPath(inCurve);
-      await this.inSmoke.setPoints();
-      this.group?.add(this.inSmoke.points);
-    }
-    if (!this.outSmoke) {
-      this.outSmoke = new Smoke('/model/img/texture-smoke.png', '#333333', 0, 1, 0.8, 20);
-      this.outSmoke.setPath(outCurve);
-      await this.outSmoke.setPoints();
-      this.group?.add(this.outSmoke.points);
-    }
-
-    this.inSmoke.startSmoke(1);
-    this.outSmoke.startSmoke(1);
-  };
-
-  clearFly = () => {
-    if (this.inSmoke) this.inSmoke.clearSmoke();
-    if (this.outSmoke) this.outSmoke.clearSmoke();
-  };
+  /** 清除css元素 */
+  clearCssElement() {
+    this.cssSprites.forEach((sprite) => {
+      this.group?.remove(sprite);
+    });
+    this.cssSprites = [];
+  }
 
   mountedThree() {
     return new Promise((resolve) => {
       this.model.setGLTFModel([this.modelName]).then(async (gltf) => {
         this.group = gltf[0];
         if (this.group) {
+          setModalCenter(this.group);
           resolve(null);
           this.addLight();
-          await this.initFly();
         }
       });
     });
@@ -104,13 +86,10 @@ class WorkFace {
 
   destroy() {
     if (this.model) {
-      this.clearFly();
       this.model.clearGroup(this.group);
       this.model = null;
       this.group = null;
-      this.inSmoke = null;
-      this.outSmoke = null;
     }
   }
 }
-export default WorkFace;
+export default ModelContext;

+ 85 - 74
src/views/vent/monitorManager/dedustMonitor/dedust.threejs.ts

@@ -1,102 +1,113 @@
 import * as THREE from 'three';
 import UseThree from '../../../../utils/threejs/useThree';
-import WorkFace from './dedust.threejs.base';
+import ModelContext from './dedust.threejs.base';
 import { animateCamera } from '/@/utils/threejs/util';
 import useEvent from '../../../../utils/threejs/useEvent';
 
-// 模型对象、 文字对象
-let model: UseThree | undefined,
-  workFaceObj: WorkFace | undefined,
-  group: THREE.Object3D | undefined,
-  fiberType = 'tunFace'; // workerFaceFiber
+/** 模型总控制器 */
+let model: UseThree;
+/** 当前展示的具体模型的 Object3D 对象 */
+let group: THREE.Object3D;
+/** 具体模型内容列表,包含此模型总控制器下的所有可用的具体模型内容 */
+const modelContextList: {
+  /** 当前模型类型,在控制器下有多个具体模型时分辨它们 */
+  type: string;
+  /** 模型的具体内容,即负责模型导入、绘制的上下文对象,一个控制器可以新建多个 */
+  context?: ModelContext;
+}[] = [];
 const { mouseDownFn } = useEvent();
 
-// 鼠标点击、松开事件
-const mouseEvent = (event) => {
+/** 分发鼠标事件到具体实现方法 */
+function dispatchMouseEvent(event) {
   if (event.button == 0 && model && group) {
     mouseDownFn(model, group, event, () => {});
   }
-};
-
-const addMouseEvent = () => {
-  // 定义鼠标点击事件
-  if (!model) return;
-  model.canvasContainer?.addEventListener('mousedown', mouseEvent.bind(null));
-};
-
-const render = () => {
-  if (model && model.isRender && model.renderer) {
-    // model.animationId = requestAnimationFrame(render);
-    model.css3dRender?.render(model.scene as THREE.Scene, model.camera as THREE.PerspectiveCamera);
-    model.renderer.render(model.scene as THREE.Scene, model.camera as THREE.PerspectiveCamera);
-    model.stats?.update();
-  }
-};
-
-export const refreshModal = () => {
-  if (fiberType === 'tunFace') {
-    // workFaceObj.render();
-    render();
-  }
-};
+}
 
-// 切换风窗类型
-export const setModelType = (type) => {
+/** 初始化模型CSS展示框的鼠标事件,应该在模型总控制器初始化后调用 */
+function initEventListender() {
   if (!model) return;
-  fiberType = type;
-  return new Promise((resolve) => {
-    if (fiberType === 'tunFace' && workFaceObj && workFaceObj.group) {
-      group = workFaceObj.group;
+  model.canvasContainer?.addEventListener('mousedown', (e) => dispatchMouseEvent(e));
+  // model.orbitControls?.addEventListener('change', () => render());
+}
 
-      // const oldCameraPosition = { x: 124.736, y: 63.486, z: 103.337 };
+/** 渲染并更新总模型 */
+// function render() {
+//   if (model && model.isRender && model.renderer) {
+//     // model.animationId = requestAnimationFrame(render);
+//     model.css3dRender?.render(model.scene as THREE.Scene, model.camera as THREE.PerspectiveCamera);
+//     model.renderer.render(model.scene as THREE.Scene, model.camera as THREE.PerspectiveCamera);
+//     model.stats?.update();
+//   }
+// }
 
-      model?.orbitControls?.addEventListener('change', render);
+/** 刷新(再渲染)总模型 */
+// export function refreshModal() {
+//   render();
+//   // modelContextList.forEach((item) => {
+//   //   if (item.context) {
+//   //     item.context.render();
+//   //   }
+//   // });
+// }
 
-      setTimeout(async () => {
-        resolve(null);
-        const oldCameraPosition = { x: -693, y: 474, z: 398 };
-        if (!model?.scene?.getObjectByName('tunFace') && group) {
-          model?.scene?.add(group);
-        }
-        const position = { x: 14.826074594663222, y: 16.901762713393836, z: 36.459944037951004 };
-        await animateCamera(
-          oldCameraPosition,
-          { x: 0, y: 0, z: 0 },
-          { x: position.x, y: position.y, z: position.z },
-          { x: 0, y: 0, z: 0 },
-          model,
-          0.8,
-          render
-        );
-      }, 400);
-    }
+/** 设置模型类型并切换,不同的类型通常对应不同的具体模型,在模型总控制器下的具体模型会根据传入的参数彼此交互、切换 */
+export function setModelType(modelType: 'dedust') {
+  return new Promise((resolve, reject) => {
+    if (!model) return reject('模型未初始化');
+    modelContextList.forEach(({ type, context }) => {
+      if (!context) return reject('模型未初始化');
+      if (modelType === type) {
+        group = context?.group as THREE.Object3D;
+        setTimeout(async () => {
+          if (!model.scene?.getObjectByName(type) && group) {
+            model.scene?.add(group);
+          }
+          const oldCameraPosition = { x: -693, y: 474, z: 398 };
+          const position = { x: 14.826074594663222, y: 16.901762713393836, z: 36.459944037951004 };
+          await animateCamera(
+            oldCameraPosition,
+            { x: 0, y: 0, z: 0 },
+            { x: position.x, y: position.y, z: position.z },
+            { x: 0, y: 0, z: 0 },
+            model,
+            0.8
+          );
+          resolve(null);
+        }, 400);
+      }
+    });
   });
-};
+}
 
-export const mountedThree = () => {
+/** 挂载模型控制器,sceneSelctor表示放置模型的元素选择器,cssSelectors表示放置类似详情框的元素选择器,其中第一项需要是根元素选择器 */
+export function mountedThree(sceneSelctor: string, cssSelectors: string[]) {
   return new Promise(async (resolve) => {
-    model = new UseThree('#tunFace3D', '#tunFace3DCSS');
+    const [rootSelector, ...selectors] = cssSelectors;
+    model = new UseThree(sceneSelctor, rootSelector);
     model.setEnvMap('test1.hdr');
     /** @ts-ignore-next-line */
     model.renderer.toneMappingExposure = 1.0;
-    // model?.camera?.position.set(100, 0, 1000);
-    workFaceObj = new WorkFace(model);
-    await workFaceObj.mountedThree();
 
-    addMouseEvent();
-    // render();
+    const model1 = new ModelContext(model);
+    await model1.mountedThree();
+    model1.initCssElement(selectors);
+    modelContextList.push({
+      type: 'dedust',
+      context: model1,
+    });
+
+    initEventListender();
     model.animate();
     resolve(null);
   });
-};
+}
 
 export const destroy = () => {
-  if (model) {
-    model.isRender = false;
-    workFaceObj?.destroy();
-    workFaceObj = undefined;
-    group = undefined;
-    model.destroy();
-    model = undefined;
-  }
+  if (!model) return;
+  model.isRender = false;
+  modelContextList.forEach((item) => {
+    if (item.context) item.context.destroy();
+  });
+  model.destroy();
 };

+ 4 - 36
src/views/vent/monitorManager/dedustMonitor/index.vue

@@ -1,19 +1,7 @@
+<!-- eslint-disable vue/multi-word-component-names -->
 <template>
-  <div
-    v-show="activeKey == 'monitor' && !loading"
-    class="bg"
-    style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; overflow: hidden"
-  >
-    <a-spin :spinning="loading" />
-    <div
-      id="tunFace3DCSS"
-      class="threejs-Object-CSS"
-      v-show="!loading"
-      style="width: 100%; height: 100%; position: absolute; pointer-events: none; overflow: hidden; z-index: 1; top: 0"
-    >
-    </div>
-    <div id="tunFace3D" style="width: 100%; height: 100%; position: absolute; overflow: hidden"> </div>
-  </div>
+  <!-- 把 dedust3D 放到这里则模型可以正常旋转 -->
+  <div id="dedust3D" v-show="activeKey == 'monitor'" style="width: 100%; height: 100%; position: absolute; overflow: hidden"> </div>
   <div class="scene-box">
     <customHeader
       :fieldNames="{ label: 'systemname', value: 'id', options: 'children' }"
@@ -68,8 +56,7 @@
 </template>
 
 <script setup lang="ts">
-  import { onBeforeMount, ref, onMounted, onUnmounted, reactive } from 'vue';
-  import { mountedThree, destroy, setModelType } from './dedust.threejs';
+  import { onBeforeMount, ref, onMounted, reactive } from 'vue';
   import { systemList, getTableList } from './dedust.api';
   import customHeader from '/@/components/vent/customHeader.vue';
   import BottomMenu from '/@/views/vent/comment/components/bottomMenu.vue';
@@ -83,7 +70,6 @@
 
   const { currentRoute } = useRouter();
   const activeKey = ref('monitor');
-  const loading = ref(false);
 
   const historyTable = ref();
   const alarmHistoryTable = ref();
@@ -106,15 +92,6 @@
 
   function changeActive(activeValue) {
     activeKey.value = activeValue;
-    loading.value = true;
-    if (activeKey.value === 'monitor') {
-      setModelType('tunFace');
-      setTimeout(() => {
-        loading.value = false;
-      }, 600);
-    } else {
-      loading.value = false;
-    }
   }
 
   function deviceChange(index) {
@@ -173,21 +150,12 @@
   onBeforeMount(() => {});
 
   onMounted(async () => {
-    loading.value = true;
-    mountedThree().then(async () => {
-      setModelType('tunFace');
-      loading.value = false;
-    });
     if (currentRoute.value && currentRoute.value['query'] && currentRoute.value['query']['id']) {
       optionValue.value = currentRoute.value['query']['id'] as string;
     }
     await getSysDataSource();
     await getDeviceList();
   });
-
-  onUnmounted(() => {
-    destroy();
-  });
 </script>
 <style lang="less" scoped>
   @import '/@/design/theme.less';