Browse Source

点击优化

hongrunxia 1 year ago
parent
commit
a75f0e4130
55 changed files with 3058 additions and 1234 deletions
  1. BIN
      public/model/glft/fire/balancePress_2023-07-08.glb
  2. BIN
      public/model/glft/fire/tunFace_2023-06-29.glb
  3. BIN
      public/model/glft/fire/tunFace_2023-07-08.glb
  4. BIN
      public/model/glft/yafeng/compressor_2023-07-10.glb
  5. BIN
      src/assets/images/vent/alarm/11.png
  6. BIN
      src/assets/images/vent/alarm/21.png
  7. BIN
      src/assets/images/vent/alarm/31.png
  8. BIN
      src/assets/images/vent/alarm/41.png
  9. 93 0
      src/components/vent/ventBox1.vue
  10. 3 2
      src/utils/threejs/main.worker.ts
  11. 59 0
      src/utils/threejs/useEvent.ts
  12. 65 27
      src/utils/threejs/util.ts
  13. 1 1
      src/views/vent/deviceManager/comment/NormalTable.vue
  14. 13 9
      src/views/vent/deviceManager/damperTabel/damper.data.ts
  15. 7 3
      src/views/vent/deviceManager/deviceTable/device.data.ts
  16. 1 0
      src/views/vent/deviceManager/deviceTable/index.vue
  17. 7 3
      src/views/vent/deviceManager/fanTabel/fan.data.ts
  18. 60 0
      src/views/vent/deviceManager/mainFanTabel/fan.api.ts
  19. 159 0
      src/views/vent/deviceManager/mainFanTabel/fan.data.ts
  20. 29 0
      src/views/vent/deviceManager/mainFanTabel/index.vue
  21. 7 3
      src/views/vent/deviceManager/sensorTabel/sensor.data.ts
  22. 3 3
      src/views/vent/deviceManager/tableColumns/tableColumns.data.ts
  23. 7 14
      src/views/vent/deviceManager/windWindowTabel/ventanalyWindow.data.ts
  24. 7 3
      src/views/vent/deviceManager/windfindingTabel/windfinding.data.ts
  25. 17 35
      src/views/vent/monitorManager/balancePressMonitor/balancePress.threejs.base.ts
  26. 11 31
      src/views/vent/monitorManager/balancePressMonitor/balancePress.threejs.ts
  27. 14 11
      src/views/vent/monitorManager/balancePressMonitor/components/balancePressHome.vue
  28. 1 0
      src/views/vent/monitorManager/balancePressMonitor/index.vue
  29. 63 0
      src/views/vent/monitorManager/balancePressMonitor1/balancePress.api.ts
  30. 306 0
      src/views/vent/monitorManager/balancePressMonitor1/balancePress.data.ts
  31. 553 0
      src/views/vent/monitorManager/balancePressMonitor1/balancePress.three.ts
  32. 266 0
      src/views/vent/monitorManager/balancePressMonitor1/index.vue
  33. 1 1
      src/views/vent/monitorManager/beltTunMonitor/beltTun.threejs.ts
  34. 13 0
      src/views/vent/monitorManager/chamberMonitor/chamber.data.ts
  35. 0 36
      src/views/vent/monitorManager/chamberMonitor/chamber.threejs.base.ts
  36. 12 32
      src/views/vent/monitorManager/chamberMonitor/chamber.threejs.ts
  37. 50 2
      src/views/vent/monitorManager/chamberMonitor/components/chamberHome.vue
  38. 7 1
      src/views/vent/monitorManager/compressor/nitrogen.dishang.threejs.ts
  39. 21 36
      src/views/vent/monitorManager/compressor/nitrogen.threejs.ts
  40. 2 1
      src/views/vent/monitorManager/deviceMonitor/components/device/device.api.ts
  41. 2 2
      src/views/vent/monitorManager/fanLocalMonitor/fanLocal.three.ts
  42. 2 2
      src/views/vent/monitorManager/fiberMonitor/fiber.threejs.ts
  43. 608 0
      src/views/vent/monitorManager/gateMonitor/gate.threejs.three.ts
  44. 145 687
      src/views/vent/monitorManager/gateMonitor/gate.threejs.ts
  45. 9 23
      src/views/vent/monitorManager/gateMonitor/index.vue
  46. 11 43
      src/views/vent/monitorManager/groutMonitor/grout.threejs.ts
  47. 1 1
      src/views/vent/monitorManager/mainFanMonitor/main.threejs.ts
  48. 49 49
      src/views/vent/monitorManager/nitrogen/components/nitrogenHome.vue
  49. 38 34
      src/views/vent/monitorManager/nitrogen/nitrogen.dishang.threejs.ts
  50. 85 56
      src/views/vent/monitorManager/nitrogen/nitrogen.threejs.ts
  51. 4 4
      src/views/vent/monitorManager/tunFaceMonitor/tunFace.threejs.ts
  52. 11 39
      src/views/vent/monitorManager/windowMonitor/window.threejs.ts
  53. 215 0
      src/views/vent/monitorManager/windrectMonitor/dantou.threejs.ts
  54. 19 39
      src/views/vent/monitorManager/windrectMonitor/windrect.threejs.ts
  55. 1 1
      src/views/vent/monitorManager/workFaceMonitor/wokeFace.threejs.ts

BIN
public/model/glft/fire/balancePress_2023-07-08.glb


BIN
public/model/glft/fire/tunFace_2023-06-29.glb


BIN
public/model/glft/fire/tunFace_2023-07-08.glb


BIN
public/model/glft/yafeng/compressor_2023-06-02.glb → public/model/glft/yafeng/compressor_2023-07-10.glb


BIN
src/assets/images/vent/alarm/11.png


BIN
src/assets/images/vent/alarm/21.png


BIN
src/assets/images/vent/alarm/31.png


BIN
src/assets/images/vent/alarm/41.png


+ 93 - 0
src/components/vent/ventBox1.vue

@@ -0,0 +1,93 @@
+<template>
+  <div class="vent-box1-bg">
+    <div class="box1-top">
+      <div class="title">
+        <slot name = 'title'></slot>
+      </div>
+    </div>
+    <div class="box1-center">
+      <div class="box-container">
+        <slot name = 'container'></slot>
+      </div>      
+    </div>
+    <div class="box1-bottom"></div>
+  </div>
+</template>
+<script>
+import { defineComponent } from 'vue'
+export default defineComponent ({
+  name: 'ventBox1',
+  setup(){
+
+  }
+})
+</script>
+
+<style lang="less" scoped>
+  .vent-box1-bg{
+    width: 100%;
+    min-height: 80px;
+    position: relative;
+    .box1-top{
+      width: 100%;
+      height: 35px;
+      background: url('/@/assets/images/vent/border/box1-top.png') no-repeat;
+      background-size: 100% 100%;
+      .title{
+        width: 100%;
+        height: 35px;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        color: #fff;
+      }
+    }
+    .box1-center{
+      width: calc(100% + 0.5px);
+      position: relative;
+      
+      .box-container{
+        width: calc(100% - 2px);
+        min-height: 50px;
+        // position: relative;
+        padding: 10px;
+        color: #fff;
+        // background-color: #0097ff05;
+        background-color: #00213236;
+        backdrop-filter: blur(5px);
+
+        &::before{
+          content: '';
+          display: block;
+          position: absolute;
+          top: 5px;
+          left: 0;
+          width: 1px;
+          height: calc(100% - 10px);
+          background-image: linear-gradient(#3DF6FF00, #3DF6FF, #3DF6FF00);
+        }
+        &::after{
+          content: '';
+          display: block;
+          position: absolute;
+          right: 0;
+          top: 5px;
+          width: 1px;
+          height: calc(100% - 10px);
+          background: linear-gradient(#3DF6FF00, #3DF6FF, #3DF6FF00);
+        }
+      }
+    }
+    .box1-bottom{
+      width: 100%;
+      height: 35px;
+      background: url('/@/assets/images/vent/border/box1-bottom.png') no-repeat;
+      background-size: 100% 100%;
+      position: absolute;
+      bottom: 0px;
+      z-index: 1;
+      pointer-events: none;
+    }
+  }
+
+</style>

+ 3 - 2
src/utils/threejs/main.worker.ts

@@ -37,10 +37,11 @@ export function initModalWorker() {
     'fire/laneway_2023-06-02.glb',
     'fire/chamber_2023-06-02.glb',
     'fire/workFace_2023-06-29.glb',
-    'fire/tunFace_2023-06-29.glb',
+    'fire/tunFace_2023-07-08.glb',
     'fire/nitrogen_2023-06-02.glb',
     'fire/grout_2023-06-02.glb',
-    'yafeng/compressor_2023-06-02.glb',
+    'fire/balancePress_2023-07-08.glb',
+    'yafeng/compressor_2023-07-10.glb',
   ];
 
   const db: any = new Dexie('DB');

+ 59 - 0
src/utils/threejs/useEvent.ts

@@ -0,0 +1,59 @@
+import * as THREE from 'three';
+import { useAppStore } from '/@/store/modules/app';
+import UseThree from './useThree';
+import gsap from 'gsap';
+
+export default function useEvent() {
+  let point = <THREE.Vector3 | null>null;
+
+  const mouseDownFn = (modal: UseThree, group: THREE.Object3D, event: MouseEvent, callBack?: Function) => {
+    if (!modal || !modal.canvasContainer || !modal.orbitControls) return;
+    const appStore = useAppStore();
+    // event.stopPropagation();
+    // event.preventDefault();
+    const widthScale = appStore.getWidthScale;
+    const heightScale = appStore.getHeightScale;
+    // 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)
+    modal.mouse.x =
+      ((-modal.canvasContainer.getBoundingClientRect().left * widthScale + event.clientX) / (modal.canvasContainer.clientWidth * widthScale)) * 2 - 1;
+    modal.mouse.y =
+      -((-modal.canvasContainer.getBoundingClientRect().top + event.clientY) / (modal.canvasContainer.clientHeight * heightScale)) * 2 + 1;
+    (modal.rayCaster as THREE.Raycaster).setFromCamera(modal.mouse, modal.camera as THREE.Camera);
+
+    if (group) {
+      const intersects = modal.rayCaster?.intersectObjects(group.children, true) as THREE.Intersection[];
+      if (intersects.length > 0) {
+        point = intersects[0].point.clone();
+        if (callBack) callBack(intersects);
+      }
+    }
+  };
+
+  const mousemoveFn = () => {
+    point = null;
+  };
+
+  const mouseUpFn = (modal) => {
+    if (point) {
+      const target0 = modal.orbitControls.target.clone();
+      // gsap.fromTo(
+      //   modal.orbitControls.target,
+      //   { x: target0.x, y: target0.y, z: target0.z },
+      //   {
+      //     x: point.x,
+      //     y: point.y,
+      //     z: point.z,
+      //     duration: 0.4,
+      //     ease: 'easeInCirc',
+      //     onUpdate: function (object) {
+      //       if (object) modal.camera?.lookAt(new THREE.Vector3(object.x, object.y, object.z));
+      //     },
+      //   }
+      // );
+    }
+    console.log('摄像头控制信息', modal.orbitControls, modal.camera);
+  };
+
+  return { mouseDownFn, mouseUpFn, mousemoveFn };
+}
+

+ 65 - 27
src/utils/threejs/util.ts

@@ -7,10 +7,12 @@ import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js';
 import { TWEEN } from 'three/examples/jsm/libs/tween.module.min.js';
 import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader.js';
 import gsap from 'gsap';
+import { useAppStore } from '/@/store/modules/app';
+import UseThree from './useThree';
 // import * as dat from "dat.gui";
 
 /* 设置模型居中 */
-export const setModalCenter = (group) => {
+export const setModalCenter = (group, modal?) => {
   const box3 = new THREE.Box3();
   // 计算层级模型group的包围盒
   // 模型group是加载一个三维模型返回的对象,包含多个网格模型
@@ -23,6 +25,7 @@ export const setModalCenter = (group) => {
   group.position.x = group.position.x - center.x;
   group.position.y = group.position.y - center.y;
   group.position.z = group.position.z - center.z;
+
 };
 
 // 获取一个canvas 图文纹理
@@ -335,7 +338,7 @@ export const animateCamera = (oldP, oldT, newP, newT, model, duration = 0.5, cal
         onUpdate: function (object) {
           // 这里写逻辑
           camera.position.set(object.x1, object.y1, object.z1);
-          // controls.target.set(object.x2, object.y2, object.z2);
+          controls.target.set(object.x2, object.y2, object.z2);
           controls.update();
           if (callBack) callBack();
         },
@@ -395,32 +398,67 @@ export const deviceDetailCard = () => {
   //
 };
 
-export const updateAxisCenter = (modal, event) => {
-  const factor = 1;
-  //这里定义深度值为0.5,深度值越大,意味着精度越高
-  var vector = new THREE.Vector3(modal.mouse.x, modal.mouse.y, 0.5);
-  //将鼠标坐标转换为3D空间坐标
-  vector.unproject(modal.camera);
-  //获得从相机指向鼠标所对应的3D空间点的射线(归一化)
-  vector.sub(modal.camera.position).normalize();
-
-  if (event.originalEvent && event.originalEvent.deltaY && event.originalEvent.deltaY < 0) {
-    modal.camera.position.x += vector.x * factor;
-    modal.camera.position.y += vector.y * factor;
-    modal.camera.position.z += vector.z * factor;
-    modal.orbitControls.target.x += vector.x * factor;
-    modal.orbitControls.target.y += vector.y * factor;
-    modal.orbitControls.target.z += vector.z * factor;
-  } else {
-    modal.camera.position.x -= vector.x * factor;
-    modal.camera.position.y -= vector.y * factor;
-    modal.camera.position.z -= vector.z * factor;
-    modal.orbitControls.target.x -= vector.x * factor;
-    modal.orbitControls.target.y -= vector.y * factor;
-    modal.orbitControls.target.z -= vector.z * factor;
+export const updateAxisCenter = (modal: UseThree, group: THREE.Object3D, event, callBack?) => {
+  if (!modal) return;
+  const appStore = useAppStore();
+  event.stopPropagation();
+  const widthScale = appStore.getWidthScale;
+  const heightScale = appStore.getHeightScale;
+  // 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)
+  modal.mouse.x =
+    ((-modal.canvasContainer.getBoundingClientRect().left * widthScale + event.clientX) / (modal.canvasContainer.clientWidth * widthScale)) * 2 - 1;
+  modal.mouse.y =
+    -((-modal.canvasContainer.getBoundingClientRect().top + event.clientY) / (modal.canvasContainer.clientHeight * heightScale)) * 2 + 1;
+  (modal.rayCaster as THREE.Raycaster).setFromCamera(modal.mouse, modal.camera as THREE.Camera);
+
+  if (group) {
+    const intersects = modal.rayCaster?.intersectObjects(group.children, true) as THREE.Intersection[];
+    if (intersects.length > 0) {
+      const point = intersects[0].point;
+      const target0 = modal.orbitControls.target.clone();
+      gsap.fromTo(
+        modal.orbitControls.target,
+        { x: target0.x, y: target0.y, z: target0.z },
+        {
+          x: point.x,
+          y: point.y,
+          z: point.z,
+          duration: 0.4,
+          ease: 'easeInCirc',
+          onUpdate: function (object) {
+            if (object) modal.camera?.lookAt(new THREE.Vector3(object.x, object.y, object.z));
+          },
+        }
+      );
+      callBack(intersects);
+    }
   }
-  modal.orbitControls.update();
-  modal.camera.updateMatrixWorld();
+
+  // const factor = 1;
+  // //这里定义深度值为0.5,深度值越大,意味着精度越高
+  // var vector = new THREE.Vector3(modal.mouse.x, modal.mouse.y, 0.5);
+  // //将鼠标坐标转换为3D空间坐标
+  // vector.unproject(modal.camera);
+  // //获得从相机指向鼠标所对应的3D空间点的射线(归一化)
+  // vector.sub(modal.camera.position).normalize();
+
+  // if (event.originalEvent && event.originalEvent.deltaY && event.originalEvent.deltaY < 0) {
+  //   modal.camera.position.x += vector.x * factor;
+  //   modal.camera.position.y += vector.y * factor;
+  //   modal.camera.position.z += vector.z * factor;
+  //   modal.orbitControls.target.x += vector.x * factor;
+  //   modal.orbitControls.target.y += vector.y * factor;
+  //   modal.orbitControls.target.z += vector.z * factor;
+  // } else {
+  //   modal.camera.position.x -= vector.x * factor;
+  //   modal.camera.position.y -= vector.y * factor;
+  //   modal.camera.position.z -= vector.z * factor;
+  //   modal.orbitControls.target.x -= vector.x * factor;
+  //   modal.orbitControls.target.y -= vector.y * factor;
+  //   modal.orbitControls.target.z -= vector.z * factor;
+  // }
+  // modal.orbitControls.update();
+  // modal.camera.updateMatrixWorld();
 };
 
 export const addEnvMap = (hdr, modal) => {

+ 1 - 1
src/views/vent/deviceManager/comment/NormalTable.vue

@@ -37,7 +37,7 @@
   </div>
 </template>
 
-<script lang="ts" name="system-user" setup>
+<script lang="ts" setup>
   //ts语法
   import { ref, provide, reactive, toRaw, defineExpose } from 'vue';
   import { BasicTable, TableAction, ActionItem, EditRecordRow, BasicColumn } from '/@/components/Table';

+ 13 - 9
src/views/vent/deviceManager/damperTabel/damper.data.ts

@@ -73,9 +73,13 @@ export const recycleColumns: BasicColumn[] = [
 
 export const searchFormSchema: FormSchema[] = [
   {
-    label: '名称',
-    field: 'strname',
-    component: 'Input',
+    label: '设备类型',
+    field: 'strtype',
+    component: 'JDictSelectTag',
+    componentProps: {
+      dictCode: 'gatekind',
+      placeholder: '请选择设备类型',
+    },
     colProps: { span: 6 },
   },
   {
@@ -85,13 +89,13 @@ export const searchFormSchema: FormSchema[] = [
     colProps: { span: 6 },
   },
   {
-    label: '是否为常闭型',
-    field: 'bnormalclose',
-    component: 'JDictSelectTag',
+    label: '所属分站',
+    field: 'nsubstationid',
+    component: 'ApiSelect',
     componentProps: {
-      dictCode: 'user_status',
-      placeholder: '请选择读写类型',
-      stringToNumber: true,
+      api: list,
+      labelField: 'strname',
+      valueField: 'id',
     },
     colProps: { span: 6 },
   },

+ 7 - 3
src/views/vent/deviceManager/deviceTable/device.data.ts

@@ -50,9 +50,13 @@ export const recycleColumns: BasicColumn[] = [
 
 export const searchFormSchema: FormSchema[] = [
   {
-    label: '名称',
-    field: 'strname',
-    component: 'Input',
+    label: '设备类型',
+    field: 'strtype',
+    component: 'JDictSelectTag',
+    componentProps: {
+      dictCode: '',
+      placeholder: '请选择设备类型',
+    },
     colProps: { span: 6 },
   },
   {

+ 1 - 0
src/views/vent/deviceManager/deviceTable/index.vue

@@ -122,6 +122,7 @@
     }else {
       deviceType.value = pageType
     }
+    searchFormSchema[0].componentProps['dictCode'] =  `${deviceType.value}kind`
     columns.value = getTableHeaderColumns(`${deviceType.value}_list`) || []
     const formSchemaColumns = getFormSchemaColumns(`${deviceType.value}_edit`) || []
 

+ 7 - 3
src/views/vent/deviceManager/fanTabel/fan.data.ts

@@ -50,9 +50,13 @@ export const recycleColumns: BasicColumn[] = [
 
 export const searchFormSchema: FormSchema[] = [
   {
-    label: '名称',
-    field: 'strname',
-    component: 'Input',
+    label: '设备类型',
+    field: 'strtype',
+    component: 'JDictSelectTag',
+    componentProps: {
+      dictCode: 'fanlocalkind',
+      placeholder: '请选择设备类型',
+    },
     colProps: { span: 6 },
   },
   {

+ 60 - 0
src/views/vent/deviceManager/mainFanTabel/fan.api.ts

@@ -0,0 +1,60 @@
+import { defHttp } from '/@/utils/http/axios';
+import { Modal } from 'ant-design-vue';
+
+enum Api {
+  list = '/safety/ventanalyDeviceInfo/list',
+  save = '/safety/ventanalyFan/add',
+  edit = '/safety/ventanalyFan/edit',
+  deleteById = '/safety/ventanalyFan/delete',
+  deleteBatch = '/sys/user/deleteBatch',
+  importExcel = '/sys/user/importExcel',
+  exportXls = '/sys/user/exportXls',
+}
+/**
+ * 导出api
+ * @param params
+ */
+export const getExportUrl = Api.exportXls;
+/**
+ * 导入api
+ */
+export const getImportUrl = Api.importExcel;
+/**
+ * 列表接口
+ * @param params
+ */
+export const list = (params) => defHttp.get({ url: Api.list, params });
+
+/**
+ * 删除用户
+ */
+export const deleteById = (params, handleSuccess) => {
+  return defHttp.delete({ url: Api.deleteById, params: params.id }, { joinParamsToUrl: true }).then(() => {
+    handleSuccess();
+  });
+};
+/**
+ * 批量删除用户
+ * @param params
+ */
+export const batchDeleteById = (params, handleSuccess) => {
+  Modal.confirm({
+    title: '确认删除',
+    content: '是否删除选中数据',
+    okText: '确认',
+    cancelText: '取消',
+    onOk: () => {
+      return defHttp.delete({ url: Api.deleteBatch, data: params }, { joinParamsToUrl: true }).then(() => {
+        handleSuccess();
+      });
+    },
+  });
+};
+/**
+ * 保存或者更新用户
+ * @param params
+ */
+export const saveOrUpdate = (params, isUpdate) => {
+  const url = isUpdate ? Api.edit : Api.save;
+  return isUpdate ? defHttp.put({ url: url, params }) : defHttp.post({ url: url, params });
+};

+ 159 - 0
src/views/vent/deviceManager/mainFanTabel/fan.data.ts

@@ -0,0 +1,159 @@
+import { BasicColumn } from '/@/components/Table';
+import { FormSchema } from '/@/components/Table';
+import { list } from '../substationTabel/substation.api';
+
+export const columns: BasicColumn[] = [
+  {
+    title: '名称',
+    dataIndex: 'strname',
+    width: 120,
+  },
+  {
+    title: '安装位置',
+    dataIndex: 'strinstallpos',
+    width: 100,
+  },
+  {
+    title: '风筒长度(m)',
+    dataIndex: 'flength',
+    width: 100,
+  },
+  {
+    title: '风筒直径(m)',
+    dataIndex: 'fclearwidth',
+    width: 80,
+  },
+  {
+    title: '风机类型',
+    dataIndex: 'ntype_dictText',
+    width: 100,
+  },
+  {
+    title: '所属分站',
+    width: 150,
+    dataIndex: 'stationname',
+  },
+];
+
+export const recycleColumns: BasicColumn[] = [
+  {
+    title: '名称',
+    dataIndex: 'strname',
+    width: 100,
+  },
+  {
+    title: '是否为常闭型',
+    dataIndex: 'bnormalclose',
+    width: 100,
+  },
+];
+
+export const searchFormSchema: FormSchema[] = [
+  {
+    label: '设备类型',
+    field: 'strtype',
+    component: 'JDictSelectTag',
+    componentProps: {
+      dictCode: 'fanmainkind',
+      placeholder: '请选择设备类型',
+    },
+    colProps: { span: 6 },
+  },
+  {
+    label: '安装位置',
+    field: 'strinstallpos',
+    component: 'Input',
+    colProps: { span: 6 },
+  },
+  {
+    label: '所属分站',
+    field: 'nsubstationid',
+    component: 'ApiSelect',
+    componentProps: {
+      api: list,
+      labelField: 'strname',
+      valueField: 'id',
+    },
+  },
+];
+
+export const formSchema: FormSchema[] = [
+  {
+    label: '',
+    field: 'id',
+    component: 'Input',
+    show: false,
+  },
+  {
+    label: '名称',
+    field: 'strname',
+    component: 'Input',
+  },
+  {
+    label: '安装位置',
+    field: 'strinstallpos',
+    component: 'Input',
+  },
+  {
+    label: '风筒长度(m)',
+    field: 'flength',
+    component: 'InputNumber',
+  },
+  {
+    label: '风筒直径(m)',
+    field: 'fclearwidth',
+    component: 'InputNumber',
+  },
+  {
+    label: '风机类型',
+    field: 'ntype',
+    component: 'JDictSelectTag',
+    componentProps: {
+      dictCode: 'fantype',
+      placeholder: '请选择状态',
+      // stringToNumber: true,
+    },
+  },
+  {
+    label: '所属分站',
+    field: 'nsubstationid',
+    component: 'ApiSelect',
+    componentProps: {
+      api: list,
+      labelField: 'strname',
+      valueField: 'id',
+    },
+  },
+  {
+    label: '点表',
+    field: 'strtype',
+    component: 'JDictSelectTag',
+    componentProps: {
+      dictCode: 'fanlocalkind',
+      placeholder: '请选择状态',
+    },
+  },
+  {
+    label: '监测类型',
+    field: 'monitorflag_dictText',
+    component: 'JDictSelectTag',
+    componentProps: {
+      dictCode: 'monitorflag',
+      placeholder: '请选择状态',
+    },
+  },
+  {
+    label: '是否模拟数据',
+    field: 'testflag',
+    component: 'RadioGroup',
+    defaultValue: 1,
+    componentProps: () => {
+      return {
+        options: [
+          { label: '是', value: 1, key: '1' },
+          { label: '否', value: 0, key: '2' },
+        ],
+      };
+    },
+  },
+];

+ 29 - 0
src/views/vent/deviceManager/mainFanTabel/index.vue

@@ -0,0 +1,29 @@
+<template>
+  <div class="device-manager-box">
+    <NormalTable
+      :columns="columns"
+      :searchFormSchema="searchFormSchema"
+      :list="list"
+      :getImportUrl="getImportUrl"
+      :getExportUrl="getExportUrl"
+      :formSchema="formSchema"
+      :deleteById="deleteById"
+      :batchDelete="batchDeleteById"
+      :saveOrUpdate="saveOrUpdate"
+      designScope="fan-tabel"
+      title="风机列表"
+      :showTab="true"
+      deviceType="fanmain"
+    />
+  </div>
+</template>
+
+<script lang="ts" setup>
+  //ts语法
+
+  import NormalTable from '../comment/NormalTable.vue'
+  import { columns, searchFormSchema, formSchema } from './fan.data';
+  import { list, getImportUrl, getExportUrl, deleteById, batchDeleteById, saveOrUpdate } from './fan.api';
+</script>
+
+<style scoped></style>

+ 7 - 3
src/views/vent/deviceManager/sensorTabel/sensor.data.ts

@@ -45,9 +45,13 @@ export const recycleColumns: BasicColumn[] = [
 
 export const searchFormSchema: FormSchema[] = [
   {
-    label: '名称',
-    field: 'strname',
-    component: 'Input',
+    label: '传感器类型',
+    field: 'strtype',
+    component: 'JDictSelectTag',
+    componentProps: {
+      dictCode: 'modelsensorkind',
+      placeholder: '请选择传感器类型',
+    },
     colProps: { span: 6 },
   },
   {

+ 3 - 3
src/views/vent/deviceManager/tableColumns/tableColumns.data.ts

@@ -94,12 +94,12 @@ export const formSchema: FormSchema[] = [
     },
   },
   {
-    label: '描述',
+    label: '字段名称',
     field: 'des',
-    component: 'InputTextArea',
+    component: 'Input',
   },
   {
-    label: '监测字段Code',
+    label: '字段Code',
     field: 'monitorcode',
     component: 'Input',
   },

+ 7 - 14
src/views/vent/deviceManager/windWindowTabel/ventanalyWindow.data.ts

@@ -60,9 +60,13 @@ export const recycleColumns: BasicColumn[] = [
 
 export const searchFormSchema: FormSchema[] = [
   {
-    label: '名称',
-    field: 'strname',
-    component: 'Input',
+    label: '设备类型',
+    field: 'strtype',
+    component: 'JDictSelectTag',
+    componentProps: {
+      dictCode: 'windowkind',
+      placeholder: '请选择设备类型',
+    },
     colProps: { span: 6 },
   },
   {
@@ -72,17 +76,6 @@ export const searchFormSchema: FormSchema[] = [
     colProps: { span: 6 },
   },
   {
-    label: '风窗类型',
-    field: 'nwindowtype',
-    component: 'JDictSelectTag',
-    componentProps: {
-      dictCode: 'nwindowtype',
-      placeholder: '请选择读写类型',
-      stringToNumber: true,
-    },
-    colProps: { span: 6 },
-  },
-  {
     label: '所属分站',
     field: 'nsubstationid',
     component: 'ApiSelect',

+ 7 - 3
src/views/vent/deviceManager/windfindingTabel/windfinding.data.ts

@@ -60,9 +60,13 @@ export const recycleColumns: BasicColumn[] = [
 
 export const searchFormSchema: FormSchema[] = [
   {
-    label: '名称',
-    field: 'strname',
-    component: 'Input',
+    label: '设备类型',
+    field: 'strtype',
+    component: 'JDictSelectTag',
+    componentProps: {
+      dictCode: 'windrectkind',
+      placeholder: '请选择设备类型',
+    },
     colProps: { span: 6 },
   },
   {

+ 17 - 35
src/views/vent/monitorManager/balancePressMonitor/balancePress.threejs.base.ts

@@ -1,8 +1,8 @@
 import * as THREE from 'three';
 import { setModalCenter } from '/@/utils/threejs/util';
-// import * as dat from 'dat.gui';
-// const gui = new dat.GUI();
-// gui.domElement.style = 'position:absolute;top:100px;left:10px;z-index:99999999999999';
+import * as dat from 'dat.gui';
+const gui = new dat.GUI();
+gui.domElement.style = 'position:absolute;top:100px;left:10px;z-index:99999999999999';
 
 class balancePressBase {
   model;
@@ -14,8 +14,8 @@ class balancePressBase {
   }
 
   addLight() {
-    const directionalLight = new THREE.DirectionalLight(0xffffff, 1.2);
-    directionalLight.position.set(-0.8, 23, 3.9);
+    const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
+    directionalLight.position.set(-52, -35, -26);
     this.group?.add(directionalLight);
     directionalLight.target = this.group as THREE.Object3D;
 
@@ -36,36 +36,17 @@ class balancePressBase {
     // pointLight5.shadow.bias = 0.05;
     // this.group.add(pointLight5);
 
-    // const pointLight7 = new THREE.PointLight(0xffffff, 1, 1000);
-    // pointLight7.position.set(45, 51, -4.1);
-    // pointLight7.shadow.bias = 0.05;
-    // this.model.scene.add(pointLight7);
+    const pointLight7 = new THREE.PointLight(0xffffff, 1, 1000);
+    pointLight7.position.set(-7, 100, 8.5);
+    pointLight7.shadow.bias = 0.05;
+    this.model.scene.add(pointLight7);
 
-    const spotLight = new THREE.SpotLight();
-    spotLight.angle = Math.PI / 2;
-    spotLight.penumbra = 0;
-    spotLight.castShadow = true;
-    spotLight.intensity = 1;
-
-    spotLight.shadow.camera.near = 0.5; // default
-    spotLight.shadow.focus = 1.2;
-    spotLight.shadow.bias = -0.000002;
-
-    spotLight.position.set(-7.19, 199, -68.1);
-    // this.group.add(spotLight);
-
-    // gui.add(directionalLight.position, 'x', -10, 20).onChange(function (value) {
-    //   directionalLight.position.x = Number(value);
-    //   _this.render();
-    // });
-    // gui.add(directionalLight.position, 'y', -50, 50).onChange(function (value) {
-    //   directionalLight.position.y = Number(value);
-    //   _this.render();
-    // });
-    // gui.add(directionalLight.position, 'z', -20, 20).onChange(function (value) {
-    //   directionalLight.position.z = Number(value);
-    //   _this.render();
-    // });
+    // gui.add(directionalLight.position, 'x', -100, 100);
+    // gui.add(directionalLight.position, 'y', -100, 100);
+    // gui.add(directionalLight.position, 'z', -100, 100);
+    // gui.add(pointLight7.position, 'x', -100, 100);
+    // gui.add(pointLight7.position, 'y', -100, 100);
+    // gui.add(pointLight7.position, 'z', -100, 100);
 
     // gui.add(spotLight.position, 'x', -600, 600).onChange(function (value) {
     //   spotLight.position.x = Number(value);
@@ -86,8 +67,9 @@ class balancePressBase {
       this.model.setGLTFModel([this.modelName]).then((gltf) => {
         this.group = gltf[0];
         if (this.group) {
+          setModalCenter(this.group);
           this.group?.scale.set(0.1, 0.1, 0.1);
-          this.group.position.y += 40;
+          this.group.position.set(0.445, 0.68, -0.118);
           resolve(null);
           this.addLight();
         }

+ 11 - 31
src/views/vent/monitorManager/balancePressMonitor/balancePress.threejs.ts

@@ -2,43 +2,23 @@ import * as THREE from 'three';
 import UseThree from '../../../../utils/threejs/useThree';
 import balancePressBase from './balancePress.threejs.base';
 import { animateCamera, setModalCenter } from '/@/utils/threejs/util';
-import { useAppStore } from '/@/store/modules/app';
+import useEvent from '../../../../utils/threejs/useEvent';
 
 // 模型对象、 文字对象
 let model,
   balancePressBaseObj: balancePressBase,
   group,
   balancePressType = 'balancePressBase'; // workerFaceFiber
-const appStore = useAppStore();
 
+const { mouseDownFn } = useEvent();
 // 鼠标点击事件
 const mouseEvent = (event) => {
-  event.stopPropagation();
-  if (!model) return;
-  const widthScale = appStore.getWidthScale;
-  const heightScale = appStore.getHeightScale;
-  // 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)
-  model.mouse.x =
-    ((-model.canvasContainer.getBoundingClientRect().left * widthScale + event.clientX) / (model.canvasContainer.clientWidth * widthScale)) * 2 - 1;
-  model.mouse.y =
-    -((-model.canvasContainer.getBoundingClientRect().top + event.clientY) / (model.canvasContainer.clientHeight * heightScale)) * 2 + 1;
-  (model.rayCaster as THREE.Raycaster).setFromCamera(model.mouse, model.camera as THREE.Camera);
-  if (group) {
-    if (balancePressType === 'balancePressBase') {
+  mouseDownFn(model, group, event, (intersects) => {
+    if (balancePressType === 'balancePressType') {
       // balancePressBaseObj.mousedownModel.call(balancePressBaseObj, model.rayCaster);
     }
-
-    // const intersects = model.rayCaster?.intersectObjects([...group.children]) as THREE.Intersection[];
-    // if (intersects.length > 0) {
-    //   if (fiberType === 'beltFiber') {
-    //     beltFiberObj.mousedownModel.call(beltFiberObj, intersects);
-    //   } else if (fiberType === 'workFace') {
-    //     workerFaceFiberObj.mousedownModel.call(workerFaceFiberObj, intersects);
-    //   }
-    // }
-
-    console.log('摄像头,控制器------>', model.camera, model.orbitControls);
-  }
+  });
+  console.log('摄像头,控制器------>', model.camera, model.orbitControls);
 };
 
 const addMouseEvent = () => {
@@ -66,17 +46,17 @@ export const setModelType = (type) => {
   return new Promise((resolve) => {
     if (balancePressType === 'balancePressBase') {
       group = balancePressBaseObj.group;
-      const oldCameraPosition = { x: 124.736, y: 63.486, z: 103.337 };
+      const oldCameraPosition = { x: 0, y: 0, z: 10 };
       model.scene.add(balancePressBaseObj.group);
-      setModalCenter(model.scene);
+      
       model.camera.position.set(0, 0, 300);
       setTimeout(async () => {
         // const position = { x: 0, y: 3.8, z: 10.5 };
         await animateCamera(
           oldCameraPosition,
-          oldCameraPosition,
-          { x: 0.519594036828229, y: 411.8877286329627, z: 330.7728952161751 },
-          { x: 3.534969685817257, y: 14.506061950306899, z: -16.565361577001262 },
+          {x: 0, y: 0, z: 0},
+          { x: -4.701309176450354, y: 1.8413775084517353, z: 0.00649962854810722 },
+          { x: 0, y: 0, z: 0 },
           model,
           0.8
         );

+ 14 - 11
src/views/vent/monitorManager/balancePressMonitor/components/balancePressHome.vue

@@ -77,7 +77,7 @@
             </template>
           </ventBox1>
         </div>
-        <div class="item-box" >
+        <div class="item-box vent-margin-t-10" >
           <LivePlayer id="fm-player1" style="height: 250px;" ref="player1" :videoUrl="flvURL1()" muted live loading controls />
         </div>
       </div>
@@ -160,8 +160,11 @@ function handleDust() {
   //
 }
 
-watch(() => props.deviceId, () => {
-  setModelType('balancePressBase')
+watch(() => props.deviceId, (newVal, oldVal) => {
+  if(newVal && oldVal != undefined){
+    setModelType('balancePressBase')
+  }
+  
   loading.value = true
 })
 
@@ -170,14 +173,14 @@ onBeforeMount(() => {
 });
 
 onMounted(() => {
-  getMonitor()
-  // loading.value = true;
-  // mountedThree().then(async () => {
-  //   await setModelType('balancePressBase');
-  //   loading.value = false;
-  //   timer = null
-  //   await getMonitor()
-  // });
+  // getMonitor()
+  loading.value = true;
+  mountedThree().then(async () => {
+    await setModelType('balancePressBase');
+    loading.value = false;
+    timer = null
+    await getMonitor()
+  });
 });
 
 onUnmounted(() => {

+ 1 - 0
src/views/vent/monitorManager/balancePressMonitor/index.vue

@@ -122,6 +122,7 @@ onBeforeMount(() => {
 onMounted(async() => {
   if (currentRoute.value['query'] && currentRoute.value['query']['id']) optionValue.value = currentRoute.value['query']['id']
   await getSysDataSource()
+  
 });
 
 onUnmounted(() => {

+ 63 - 0
src/views/vent/monitorManager/balancePressMonitor1/balancePress.api.ts

@@ -0,0 +1,63 @@
+import { defHttp } from '/@/utils/http/axios';
+import { Modal } from 'ant-design-vue';
+
+enum Api {
+  list = '/ventanaly-device/monitor/device',
+  save = '/safety/ventanalyGate/add',
+  edit = '/safety/ventanalyGate/edit',
+  baseList = '/safety/ventanalyWindow/list',
+  deleteById = '/safety/ventanalyGate/delete',
+  deleteBatch = '/sys/user/deleteBatch',
+  importExcel = '/sys/user/importExcel',
+  exportXls = '/sys/user/exportXls',
+}
+/**
+ * 导出api
+ * @param params
+ */
+export const getExportUrl = Api.exportXls;
+/**
+ * 导入api
+ */
+export const getImportUrl = Api.importExcel;
+/**
+ * 列表接口
+ * @param params
+ */
+export const list = (params) => defHttp.post({ url: Api.list, params });
+
+export const getTableList = (params) => defHttp.get({ url: Api.baseList, params });
+
+/**
+ * 删除用户
+ */
+export const deleteById = (params, handleSuccess) => {
+  return defHttp.delete({ url: Api.deleteById, params }, { joinParamsToUrl: true }).then(() => {
+    handleSuccess();
+  });
+};
+/**
+ * 批量删除用户
+ * @param params
+ */
+export const batchDeleteById = (params, handleSuccess) => {
+  Modal.confirm({
+    title: '确认删除',
+    content: '是否删除选中数据',
+    okText: '确认',
+    cancelText: '取消',
+    onOk: () => {
+      return defHttp.delete({ url: Api.deleteBatch, data: params }, { joinParamsToUrl: true }).then(() => {
+        handleSuccess();
+      });
+    },
+  });
+};
+/**
+ * 保存或者更新用户
+ * @param params
+ */
+export const saveOrUpdate = (params, isUpdate) => {
+  const url = isUpdate ? Api.edit : Api.save;
+  return defHttp.put({ url: url, params });
+};

+ 306 - 0
src/views/vent/monitorManager/balancePressMonitor1/balancePress.data.ts

@@ -0,0 +1,306 @@
+import { BasicColumn } from '/@/components/Table';
+import { FormSchema } from '/@/components/Table';
+import { rules } from '/@/utils/helper/validator';
+export const columns: BasicColumn[] = [
+  {
+    title: '名称',
+    dataIndex: 'strname',
+    width: 120,
+  },
+  {
+    title: '安装位置',
+    dataIndex: 'strinstallpos',
+    width: 100,
+  },
+  {
+    title: '是否为常闭型',
+    dataIndex: 'bnormalclose',
+    width: 100,
+    // customRender: render.renderAvatar,
+  },
+  {
+    title: '净宽',
+    dataIndex: 'fclearwidth',
+    width: 80,
+  },
+  {
+    title: '净高',
+    dataIndex: 'fclearheight',
+    width: 100,
+  },
+  {
+    title: '风门道数',
+    dataIndex: 'ndoorcount',
+    width: 100,
+  },
+  {
+    title: '所属分站',
+    width: 150,
+    dataIndex: 'stationname',
+  },
+  {
+    title: '点表',
+    width: 100,
+    dataIndex: 'strtype',
+  },
+  {
+    title: '监测类型',
+    dataIndex: 'monitorflag',
+    width: 100,
+  },
+  {
+    title: '是否模拟数据',
+    dataIndex: 'testflag',
+    width: 100,
+  },
+];
+
+export const recycleColumns: BasicColumn[] = [
+  {
+    title: '名称',
+    dataIndex: 'strname',
+    width: 100,
+  },
+  {
+    title: '是否为常闭型',
+    dataIndex: 'bnormalclose',
+    width: 100,
+  },
+];
+
+export const searchFormSchema: FormSchema[] = [
+  {
+    label: '名称',
+    field: 'strname',
+    component: 'Input',
+    colProps: { span: 6 },
+  },
+  {
+    label: '安装位置',
+    field: 'strinstallpos',
+    component: 'Input',
+    colProps: { span: 6 },
+  },
+  {
+    label: '是否为常闭型',
+    field: 'bnormalclose',
+    component: 'JDictSelectTag',
+    componentProps: {
+      dictCode: 'user_status',
+      placeholder: '请选择读写类型',
+      stringToNumber: true,
+    },
+    colProps: { span: 6 },
+  },
+];
+
+export const formSchema: FormSchema[] = [
+  {
+    label: '',
+    field: 'id',
+    component: 'Input',
+    show: false,
+  },
+  {
+    label: '名称',
+    field: 'strname',
+    component: 'Input',
+  },
+  {
+    label: '安装位置',
+    field: 'strinstallpos',
+    component: 'Input',
+  },
+  {
+    label: '是否为常闭型',
+    field: 'bnormalclose',
+    component: 'RadioGroup',
+    defaultValue: 1,
+    componentProps: () => {
+      return {
+        options: [
+          { label: '是', value: 1, key: '1' },
+          { label: '否', value: 0, key: '2' },
+        ],
+      };
+    },
+  },
+  {
+    label: '净宽',
+    field: 'fclearwidth',
+    component: 'Input',
+  },
+  {
+    label: '净高',
+    field: 'fclearheight',
+    component: 'Input',
+  },
+  {
+    label: '风门道数',
+    field: 'ndoorcount',
+    component: 'Input',
+  },
+  {
+    label: '所属分站',
+    field: 'stationname',
+    component: 'JDictSelectTag',
+    componentProps: {
+      dictCode: 'user_status',
+      placeholder: '请选择状态',
+      stringToNumber: true,
+    },
+  },
+  {
+    label: '点表',
+    field: 'strtype',
+    component: 'JDictSelectTag',
+    componentProps: {
+      dictCode: 'user_status',
+      placeholder: '请选择状态',
+      stringToNumber: true,
+    },
+  },
+  {
+    label: '监测类型',
+    field: 'monitorflag',
+    component: 'JDictSelectTag',
+    componentProps: {
+      dictCode: 'user_status',
+      placeholder: '请选择状态',
+      stringToNumber: true,
+    },
+  },
+  {
+    label: '是否模拟数据',
+    field: 'testflag',
+    component: 'RadioGroup',
+    defaultValue: 1,
+    componentProps: () => {
+      return {
+        options: [
+          { label: '是', value: 1, key: '1' },
+          { label: '否', value: 0, key: '2' },
+        ],
+      };
+    },
+  },
+];
+
+export const formPasswordSchema: FormSchema[] = [
+  {
+    label: '用户账号',
+    field: 'username',
+    component: 'Input',
+    componentProps: { readOnly: true },
+  },
+  {
+    label: '登录密码',
+    field: 'password',
+    component: 'StrengthMeter',
+    componentProps: {
+      placeholder: '请输入登录密码',
+    },
+    rules: [
+      {
+        required: true,
+        message: '请输入登录密码',
+      },
+    ],
+  },
+  {
+    label: '确认密码',
+    field: 'confirmPassword',
+    component: 'InputPassword',
+    dynamicRules: ({ values }) => rules.confirmPassword(values, true),
+  },
+];
+
+export const formAgentSchema: FormSchema[] = [
+  {
+    label: '',
+    field: 'id',
+    component: 'Input',
+    show: false,
+  },
+  {
+    field: 'userName',
+    label: '用户名',
+    component: 'Input',
+    componentProps: {
+      readOnly: true,
+      allowClear: false,
+    },
+  },
+  {
+    field: 'agentUserName',
+    label: '代理人用户名',
+    required: true,
+    component: 'JSelectUser',
+    componentProps: {
+      rowKey: 'username',
+      labelKey: 'realname',
+      maxSelectCount: 10,
+    },
+  },
+  {
+    field: 'startTime',
+    label: '代理开始时间',
+    component: 'DatePicker',
+    required: true,
+    componentProps: {
+      showTime: true,
+      valueFormat: 'YYYY-MM-DD HH:mm:ss',
+      placeholder: '请选择代理开始时间',
+    },
+  },
+  {
+    field: 'endTime',
+    label: '代理结束时间',
+    component: 'DatePicker',
+    required: true,
+    componentProps: {
+      showTime: true,
+      valueFormat: 'YYYY-MM-DD HH:mm:ss',
+      placeholder: '请选择代理结束时间',
+    },
+  },
+  {
+    field: 'status',
+    label: '状态',
+    component: 'JDictSelectTag',
+    defaultValue: '1',
+    componentProps: {
+      dictCode: 'valid_status',
+      type: 'radioButton',
+    },
+  },
+];
+
+export const chartsColumns = [
+  {
+    legend: '瓦斯浓度',
+    seriesName: '瓦斯浓度(%)',
+    ymax: 100,
+    yname: '',
+    linetype: 'bar',
+    yaxispos: 'left',
+    color: '#cd5fff',
+    sort: 1,
+    dataIndex: '',
+    xRotate: 0,
+  },
+];
+export const chartsColumns1 = [
+  {
+    legend: '风量',
+    seriesName: 'm³/min',
+    ymax: 1000,
+    yname: '',
+    linetype: 'bar',
+    yaxispos: 'left',
+    color: '#755cf8',
+    sort: 1,
+    dataIndex: '',
+    xRotate: 0,
+  },
+];

+ 553 - 0
src/views/vent/monitorManager/balancePressMonitor1/balancePress.three.ts

@@ -0,0 +1,553 @@
+import * as THREE from 'three';
+import { CSS3DObject } from 'three/examples/jsm/renderers/CSS3DRenderer.js';
+import { animateCamera, getTextCanvas, renderVideo, updateAxisCenter } from '/@/utils/threejs/util';
+import UseThree from '../../../../utils/threejs/useThree';
+import Smoke from '/@/views/vent/comment/threejs/Smoke';
+import gsap from 'gsap';
+import { useAppStore } from '/@/store/modules/app';
+// import * as dat from 'dat.gui';
+// const gui = new dat.GUI();
+// gui.domElement.style = 'position:absolute;top:100px;left:10px;z-index:99999999999999';
+
+const modelName = 'jbfj-hd';
+// 模型对象、 文字对象
+let model,
+  group = new THREE.Object3D(),
+  player1,
+  topSmoke,
+  downSmoke,
+  playerStartClickTime1 = new Date().getTime();
+
+const appStore = useAppStore();
+
+// 打灯光
+const addLight = (scene) => {
+  const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
+  directionalLight.position.set(106, -348, 19.9);
+  group.add(directionalLight);
+  directionalLight.target = group;
+
+  // gui.add(directionalLight.position, 'x', -1000, 1000);
+  // gui.add(directionalLight.position, 'y', -1000, 1000);
+  // gui.add(directionalLight.position, 'z', -1000, 1000);
+
+  // const pointLight2 = new THREE.PointLight(0xffeeee, 1.5, 100);
+  // pointLight2.position.set(-120, 16, -33);
+  // pointLight2.shadow.bias = 0.05;
+  // scene.add(pointLight2);
+  //
+  // const pointLight3 = new THREE.PointLight(0xffffff, 1, 40);
+  // pointLight3.position.set(-66, 40, 1);
+  // pointLight3.shadow.bias = 0.05;
+  // scene.add(pointLight3);
+  //
+  // const pointLight4 = new THREE.PointLight(0xffeeee, 0.6, 230);
+  // pointLight4.position.set(-18, 30, 12);
+  // pointLight4.shadow.bias = 0.05;
+  // scene.add(pointLight4);
+  //
+  // const pointLight5 = new THREE.PointLight(0xffffff, 0.8, 90);
+  // pointLight5.position.set(-57, 7, -30);
+  // pointLight5.shadow.bias = 0.05;
+  // scene.add(pointLight5);
+  //
+  // const pointLight6 = new THREE.PointLight(0xffffff, 0.8, 270);
+  // pointLight6.position.set(72, -33, 11.4);
+  // pointLight6.shadow.bias = 0.05;
+  // scene.add(pointLight6);
+
+  // const pointLight7 = new THREE.PointLight(0xffffff, 0.8, 500);
+  // pointLight7.position.set(-20, -43, 12);
+  // pointLight7.shadow.bias = -0.05;
+  // scene.add(pointLight7);
+
+  const spotLight = new THREE.SpotLight();
+  spotLight.angle = Math.PI / 16;
+  spotLight.penumbra = 0;
+  spotLight.castShadow = true;
+  spotLight.position.set(0, 463, 687);
+  scene.add(spotLight);
+
+  spotLight.shadow.camera.near = 0.5; // default
+  spotLight.shadow.camera.far = 1000; // default
+  spotLight.shadow.focus = 1;
+  spotLight.shadow.bias = -0.000002;
+  spotLight.target = group;
+
+  // gui.add(pointLight6.position, 'x', -200, 200);
+  // gui.add(pointLight6.position, 'y', -200, 200);
+  // gui.add(pointLight6.position, 'z', -200, 200);
+  // gui.add(pointLight6, 'distance', 0, 500);
+};
+
+// 重置摄像头
+const resetCamera = () => {
+  // model.camera.position.set(0, 30, 80);
+  model.camera.position.set(0, -1000, 100);
+  // model.camera.fov = 20
+  model.camera.far = 1000;
+  model.orbitControls?.update();
+  model.camera.updateProjectionMatrix();
+};
+
+// 设置模型位置
+const setModalPosition = () => {
+  group.position.set(0, 13, -50);
+  group.rotation.y = Math.PI / 2;
+};
+
+const setControls = () => {
+  model.orbitControls.panSpeed = 0.5;
+  model.orbitControls.rotateSpeed = 0.5;
+  model.orbitControls.maxPolarAngle = Math.PI / 2.4;
+  model.orbitControls.minPolarAngle = Math.PI / 3;
+};
+
+// 切换局部通风机类型
+export const setModelType = (type) => {
+  return new Promise((resolve) => {
+    // 显示双道风窗
+    setTimeout(async () => {
+      const oldCameraPosition = { x: 500, y: 100, z: 500 };
+      await animateCamera(oldCameraPosition, oldCameraPosition, { x: 0, y: 20, z: 80 }, { x: 0, y: 0, z: 0 }, model, 0.8);
+      resolve(null);
+    }, 300);
+  });
+};
+
+/* 添加监控数据 */
+export const addText = (selectData) => {
+  if (!group) {
+    return;
+  }
+  const textArr = [
+    {
+      text: `煤矿巷道远程局部风机系统`,
+      font: 'normal 30px Arial',
+      color: '#009900',
+      strokeStyle: '#002200',
+      x: 50,
+      y: 110,
+    },
+    {
+      text: `进风量(m³/min):`,
+      font: 'normal 30px Arial',
+      color: '#009900',
+      strokeStyle: '#002200',
+      x: 0,
+      y: 165,
+    },
+    {
+      text: `${selectData.frontRearDP}`,
+      font: 'normal 30px Arial',
+      color: '#009900',
+      strokeStyle: '#002200',
+      x: 290,
+      y: 165,
+    },
+    {
+      text: `供风量(m³/min): `,
+      font: 'normal 30px Arial',
+      color: '#009900',
+      strokeStyle: '#002200',
+      x: 0,
+      y: 220,
+    },
+    {
+      text: ` ${selectData.sourcePressure}`,
+      font: 'normal 30px Arial',
+      color: '#009900',
+      strokeStyle: '#002200',
+      x: 280,
+      y: 220,
+    },
+    {
+      text: `故障诊断:`,
+      font: 'normal 30px Arial',
+      color: '#009900',
+      strokeStyle: '#002200',
+      x: 0,
+      y: 275,
+    },
+    {
+      text: `${selectData.fault}`,
+      font: 'normal 30px Arial',
+      color: '#009900',
+      strokeStyle: '#002200',
+      x: 280,
+      y: 275,
+    },
+    {
+      text: `煤炭科学技术研究院有限公司研制`,
+      font: 'normal 28px Arial',
+      color: '#009900',
+      strokeStyle: '#002200',
+      x: 20,
+      y: 325,
+    },
+  ];
+  getTextCanvas(526, 346, textArr, '').then((canvas: HTMLCanvasElement) => {
+    const textMap = new THREE.CanvasTexture(canvas); // 关键一步
+    const textMaterial = new THREE.MeshBasicMaterial({
+      // 关于材质并未讲解 实操即可熟悉                 这里是漫反射类似纸张的材质,对应的就有高光类似金属的材质.
+      map: textMap, // 设置纹理贴图
+      transparent: true,
+      side: THREE.FrontSide, // 这里是双面渲染的意思
+    });
+    textMaterial.blending = THREE.CustomBlending;
+    const monitorPlane = group.getObjectByName('monitorText');
+    if (monitorPlane) {
+      monitorPlane.material = textMaterial;
+    } else {
+      const planeGeometry = new THREE.PlaneGeometry(526, 346); // 平面3维几何体PlaneGeometry
+      const planeMesh = new THREE.Mesh(planeGeometry, textMaterial);
+      planeMesh.name = 'monitorText';
+      planeMesh.scale.set(0.0135, 0.0135, 0.0135);
+      planeMesh.rotation.y = -Math.PI / 2;
+      planeMesh.position.set(-84.79, 0.82, 17.01);
+      group.add(planeMesh);
+    }
+  });
+};
+
+// // css3D文字
+export const addCssText = () => {
+  if (!group.getObjectByName('text1')) {
+    const element = document.getElementById('inputBox') as HTMLElement;
+    const fanLocalCSS3D = new CSS3DObject(element);
+    fanLocalCSS3D.name = 'text1';
+    fanLocalCSS3D.scale.set(0.04, 0.04, 0.04);
+    fanLocalCSS3D.rotation.y = -Math.PI / 2;
+    fanLocalCSS3D.position.set(-85.68, 5.97, -17.74);
+    group.add(fanLocalCSS3D);
+  }
+  if (!group.getObjectByName('text2')) {
+    const element = document.getElementById('outBox') as HTMLElement;
+    const fanLocalCSS3D = new CSS3DObject(element);
+    fanLocalCSS3D.name = 'text2';
+    fanLocalCSS3D.scale.set(0.1, 0.1, 0.1);
+    fanLocalCSS3D.rotation.y = -Math.PI / 2;
+    fanLocalCSS3D.position.set(74.63, 13.54, 3.84);
+    group.add(fanLocalCSS3D);
+  }
+  if (!group.getObjectByName('text3')) {
+    const element = document.getElementById('returnBox') as HTMLElement;
+    const fanLocalCSS3D = new CSS3DObject(element);
+    fanLocalCSS3D.name = 'text3';
+    fanLocalCSS3D.scale.set(0.1, 0.1, 0.1);
+    fanLocalCSS3D.rotation.y = -Math.PI / 2;
+    fanLocalCSS3D.position.set(35.28, 10.05, -37.23);
+    group.add(fanLocalCSS3D);
+  }
+  if (!group.getObjectByName('text4')) {
+    const element = document.getElementById('gateBox') as HTMLElement;
+    if (element) {
+      element.innerHTML = '';
+      const fanLocalCSS3D = new CSS3DObject(element);
+      fanLocalCSS3D.name = 'text4';
+      fanLocalCSS3D.scale.set(0.04, 0.04, 0.04);
+      fanLocalCSS3D.rotation.y = -Math.PI / 2;
+      fanLocalCSS3D.position.set(-73.13, 8.44, -23.52);
+      group.add(fanLocalCSS3D);
+    }
+  }
+  if (!group.getObjectByName('text5')) {
+    const element = document.getElementById('windownBox') as HTMLElement;
+    if (element) {
+      // element.innerHTML = '';
+      const fanLocalCSS3D = new CSS3DObject(element);
+      fanLocalCSS3D.name = 'text5';
+      fanLocalCSS3D.scale.set(0.07, 0.07, 0.07);
+      fanLocalCSS3D.rotation.y = -Math.PI / 2;
+      fanLocalCSS3D.position.set(-28.44, 9.78, -40.42);
+      group.add(fanLocalCSS3D);
+    }
+  }
+};
+
+export const playSmoke = (controlType, deviceType, frequency, state) => {
+  if (frequency) {
+    setSmokeFrequency(deviceType, frequency);
+  }
+  if (controlType === 'startSmoke') {
+    runFly(deviceType, state);
+  }
+};
+
+const initFly = () => {
+  const topCurve = [
+    {
+      path0: new THREE.Vector3(-94.84, 2.359, 3.61),
+      path1: new THREE.Vector3(-85.678, 2.359, 3.61),
+      isSpread: true,
+      spreadDirection: -1, //
+    },
+    {
+      path0: new THREE.Vector3(-85.678, 2.352, 3.66),
+      path1: new THREE.Vector3(-85.636, 2.353, -3.829),
+      isSpread: false,
+      spreadDirection: 0,
+    },
+    {
+      path0: new THREE.Vector3(-85.636, 2.353, -3.829),
+      path1: new THREE.Vector3(-85.636, 1.026, -5.881),
+      isSpread: false,
+      spreadDirection: 0,
+    },
+    {
+      path0: new THREE.Vector3(-85.636, 1.026, -5.881),
+      path1: new THREE.Vector3(-85.618, 0.887, -12.862),
+      isSpread: false,
+      spreadDirection: 0,
+    },
+    {
+      path0: new THREE.Vector3(-85.618, 0.827, -12.962),
+      path1: new THREE.Vector3(80.404, 0.827, -12.962),
+      isSpread: false,
+      spreadDirection: 0,
+    },
+    {
+      path0: new THREE.Vector3(80.404, 0.827, -12.962),
+      path1: new THREE.Vector3(93.164, 0.85, -12.962),
+      isSpread: true,
+      spreadDirection: 1, // 1是由小变大,-1是由大变小
+    },
+  ];
+
+  const downCurve = [
+    {
+      path0: new THREE.Vector3(-94.84, -0.388, 3.61),
+      path1: new THREE.Vector3(-85.678, -0.393, 3.61),
+      isSpread: true,
+      spreadDirection: -1, //
+    },
+    {
+      path0: new THREE.Vector3(-85.678, -0.393, 3.275),
+      path1: new THREE.Vector3(-85.636, -0.392, -3.829),
+      isSpread: false,
+      spreadDirection: 0,
+    },
+    {
+      path0: new THREE.Vector3(-85.636, -0.392, -3.829),
+      path1: new THREE.Vector3(-85.636, 0.926, -5.881),
+      isSpread: false,
+      spreadDirection: 0,
+    },
+    {
+      path0: new THREE.Vector3(-85.636, 1.026, -5.881),
+      path1: new THREE.Vector3(-85.618, 0.887, -12.862),
+      isSpread: false,
+      spreadDirection: 0,
+    },
+    {
+      path0: new THREE.Vector3(-85.618, 0.887, -12.962),
+      path1: new THREE.Vector3(80.404, 0.887, -12.962),
+      isSpread: false,
+      spreadDirection: 0,
+    },
+    {
+      path0: new THREE.Vector3(80.404, 0.887, -12.962),
+      path1: new THREE.Vector3(93.164, 0.91, -12.962),
+      isSpread: true,
+      spreadDirection: 1, // 1是由小变大,-1是由大变小
+    },
+  ];
+
+  // const windowCurve = new THREE.CatmullRomCurve3([
+  //   new THREE.Vector3(83.479, 0.052, -16.487),
+  //   new THREE.Vector3(-90.436, 0.0, -16.32),
+  //   new THREE.Vector3(-90.712, 0.0, -16.395),
+  //   new THREE.Vector3(-90.77, 0.0, -16.663),
+  //   new THREE.Vector3(-90.77, 0.0, -36.015),
+  // ]);
+
+  // const gateCurve = new THREE.CatmullRomCurve3([
+  //   new THREE.Vector3(83.479, 0.052, -16.487),
+  //   new THREE.Vector3(-30.267, 0.013, -16.458),
+  //   new THREE.Vector3(-30.62, 0.013, -16.523),
+  //   new THREE.Vector3(-30.727, 0.013, -16.831),
+  //   new THREE.Vector3(-30.727, 0.013, -35.84),
+  // ]);
+
+  if (!topSmoke) {
+    topSmoke = new Smoke('/model/img/texture-smoke.png', '#ffffff', 0, 0.8, 0.5, 400);
+    topSmoke.setPath(topCurve);
+    topSmoke.setPoints();
+    group?.add(topSmoke.points);
+  }
+  if (!downSmoke) {
+    downSmoke = new Smoke('/model/img/texture-smoke.png', '#ffffff', 0, 0.8, 0.5, 400);
+    downSmoke.setPath(downCurve);
+    downSmoke.setPoints();
+    group?.add(downSmoke.points);
+  }
+
+  // if (!group.getObjectByName('gateFly')) {
+  // }
+};
+
+const runFly = (deviceType, state) => {
+  if (state === 'open') {
+    if (deviceType === 'top') {
+      if (downSmoke.frameId) {
+        downSmoke.stopSmoke();
+      }
+      topSmoke.startSmoke();
+    } else {
+      if (topSmoke.frameId) {
+        topSmoke.stopSmoke();
+      }
+      downSmoke.startSmoke();
+    }
+  } else {
+    if (downSmoke.frameId) {
+      downSmoke.stopSmoke();
+    }
+    if (topSmoke.frameId) {
+      topSmoke.stopSmoke();
+    }
+  }
+};
+
+// 调频 30-50 (life 300 - 800) , 25 = (800 - 300)/ 20
+const setSmokeFrequency = (deviceType, frequency) => {
+  const life = (frequency - 30) * 25;
+  const duration = (Math.abs(life - topSmoke.life) / 500) * 25;
+  let smoke;
+  if (deviceType === 'top') {
+    smoke = topSmoke;
+  } else {
+    smoke = downSmoke;
+  }
+  gsap.to(smoke, {
+    life: life,
+    duration: duration,
+    ease: 'easeInCubic',
+    overwrite: true,
+  });
+};
+
+const clearFly = () => {
+  if (topSmoke) topSmoke.clearSmoke();
+  if (downSmoke) downSmoke.clearSmoke();
+};
+// 初始化事件
+const startAnimation = () => {
+  // 定义鼠标点击事件
+  model.canvasContainer?.addEventListener('mousedown', mouseEvent.bind(null));
+  model.canvasContainer?.addEventListener('pointerup', (event) => {
+    event.stopPropagation();
+  });
+};
+// 鼠标点击、松开事件
+const mouseEvent = (event) => {
+  event.stopPropagation();
+  const widthScale = appStore.getWidthScale;
+  const heightScale = appStore.getHeightScale;
+
+  // 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)
+  model.mouse.x =
+    ((-model.canvasContainer.getBoundingClientRect().left * widthScale + event.clientX) / (model.canvasContainer.clientWidth * widthScale)) * 2 - 1;
+  model.mouse.y =
+    -((-model.canvasContainer.getBoundingClientRect().top + event.clientY) / (model.canvasContainer.clientHeight * heightScale)) * 2 + 1;
+  // model.orbitControls.target.set()
+
+  (model.rayCaster as THREE.Raycaster).setFromCamera(model.mouse, model.camera as THREE.Camera);
+
+  updateAxisCenter(model, event);
+
+  if (group) {
+    const intersects = model.rayCaster?.intersectObjects(group.children, false) as THREE.Intersection[];
+    if (intersects.length > 0) {
+      intersects.find((intersect) => {
+        const mesh = intersect.object;
+        if (mesh.name === 'player1') {
+          if (new Date().getTime() - playerStartClickTime1 < 400) {
+            // 双击,视频放大
+            if (player1) {
+              player1.requestFullscreen();
+            }
+          }
+          playerStartClickTime1 = new Date().getTime();
+          return true;
+        }
+      });
+    }
+  }
+};
+export const mountedThree = (playerVal1) => {
+  player1 = playerVal1;
+  return new Promise((resolve) => {
+    model = new UseThree('#fanLocal3D', '#fanLocal3DCSS');
+    model.setEnvMap('test1');
+    model.renderer.toneMappingExposure = 1;
+
+    resetCamera();
+    model.setGLTFModel([modelName]).then(async (gltf) => {
+      group = gltf[0];
+      model.scene?.add(group);
+
+      setModalPosition();
+      setControls();
+      initFly();
+      model.animate();
+      addLight(model.scene);
+
+      const videoPlayer1 = document.getElementById('jb-player1')?.getElementsByClassName('vjs-tech')[0];
+      if (videoPlayer1) {
+        const mesh = renderVideo(group, videoPlayer1, 'player1');
+        mesh.scale.set(0.222, 0.19, 0.2);
+        mesh.position.set(-84.87, 0.298, 24.76);
+        mesh.rotation.y = -Math.PI / 2;
+        group.add(mesh);
+      } else {
+        const textArr = [
+          {
+            text: `无信号输入`,
+            font: 'normal 40px Arial',
+            color: '#009900',
+            strokeStyle: '#002200',
+            x: 170,
+            y: 40,
+          },
+        ];
+        getTextCanvas(560, 346, textArr, '').then((canvas: HTMLCanvasElement) => {
+          const textMap = new THREE.CanvasTexture(canvas); // 关键一步
+          const textMaterial = new THREE.MeshBasicMaterial({
+            map: textMap, // 设置纹理贴图
+            transparent: true,
+            side: THREE.DoubleSide, // 这里是双面渲染的意思
+          });
+          textMaterial.blending = THREE.CustomBlending;
+          const monitorPlane = group?.getObjectByName('noPlayer');
+          if (monitorPlane) {
+            monitorPlane.material = textMaterial;
+          } else {
+            const planeGeometry = new THREE.PlaneGeometry(100, 100); // 平面3维几何体PlaneGeometry
+            const planeMesh = new THREE.Mesh(planeGeometry, textMaterial);
+            if (!videoPlayer1) {
+              planeMesh.name = 'noPlayer';
+              planeMesh.scale.set(0.07, 0.05, 0.07);
+              planeMesh.position.set(-84.82, -1.53, 24.94);
+              planeMesh.rotation.y = -Math.PI / 2;
+              group?.add(planeMesh.clone());
+            }
+          }
+        });
+      }
+      startAnimation();
+      resolve(model);
+    });
+  });
+};
+
+export const destroy = () => {
+  if (model) {
+    clearFly();
+    model.deleteModal();
+    model = null;
+    group = null;
+    topSmoke = null;
+    downSmoke = null;
+  }
+};

+ 266 - 0
src/views/vent/monitorManager/balancePressMonitor1/index.vue

@@ -0,0 +1,266 @@
+<template>
+  <div class="bg" style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; overflow: hidden">
+    <a-spin :spinning="loading" />
+
+    <div id="fanLocal3D" style="width: 100%; height: 100%; position: absolute; overflow: hidden"> </div>
+    <div id="fanLocal3DCSS" class="threejs-Object-CSS" style="width: 100%; height: 100%; position: absolute; overflow: hidden">
+      <div style="z-index: -1; position: relative">
+        <div class="elementTag" id="inputBox">
+          <div class="elementContent">
+            <p>风筒入口风速:{{ selectData.windSpeed1 ? selectData.windSpeed1 : '-' }}</p>
+            <p>风筒入口瓦斯浓度 {{ selectData.gas1 ? selectData.gas1 : '-' }}</p>
+          </div>
+        </div>
+        <div class="elementTag" id="outBox">
+          <div class="elementContent elementContent-r">
+            <p>迎头供风量:{{ selectData.windQuantity1 ? selectData.windQuantity2 : '-' }}</p>
+            <p>迎头瓦斯浓度:{{ selectData.gas1 ? selectData.gas1 : '-' }}</p>
+          </div>
+        </div>
+        <div class="elementTag" id="returnBox">
+          <div class="elementContent">
+            <p>回风流瓦斯浓度:{{ selectData.gas3 ? selectData.gas3 : '-' }}</p>
+          </div>
+        </div>
+        <div class="elementTag" id="gateBox">
+          <div class="elementContent">
+            <p>风门状态:关</p>
+            <p>风门过风面积:{{ selectData.gas1 ? selectData.gas1 : '-' }}</p>
+          </div>
+        </div>
+        <div  class="elementTag" id="windownBox">
+          <div class="elementContent">
+            <p>风窗全风压回风流:0</p>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+
+  <div class="scene-box">
+    <div class="title-text">
+      {{ selectData.strinstallpos }}
+    </div>
+    <div class="bottom-tabs-box" @mousedown="setDivHeight($event, 240, scroll)">
+      <a-tabs class="tabs-box" v-model:activeKey="activeKey" @change="tabChange">
+        <a-tab-pane key="1" tab="实时监测">
+          <GroupMonitorTable  v-if="activeKey === '1' && isRefresh" :dataSource="dataSource" columnsType="sys_surface_junya" @selectRow="getSelectRow" :scroll="scroll"/>
+        </a-tab-pane>
+        <a-tab-pane key="2" tab="实时曲线图" force-render>
+          <div class="tab-item" v-if="activeKey === '2' && isRefresh">
+            <div class="vent-flex-row-between" style="height: 100%">
+              <BarSingle
+                :xAxisData="[
+                  { key: 'T1', valueKey: 'gas1' },
+                  { key: 'T2', valueKey: 'gas2' },
+                  { key: 'T3', valueKey: 'gas3' },
+                  { key: 'T4', valueKey: 'gas4' },
+                ]"
+                :dataSource="dataSource[selectRowIndex]"
+                height="100%"
+                :chartsColumns="chartsColumns"
+                style="flex: 3"
+              />
+              <BarSingle
+                :xAxisData="[
+                  { key: 'F1', valueKey: 'windQuantity1' },
+                  { key: 'F2', valueKey: 'windQuantity2' },
+                ]"
+                :dataSource="dataSource[selectRowIndex]"
+                height="100%"
+                :chartsColumns="chartsColumns1"
+                style="flex: 2"
+              />
+            </div>
+          </div>
+        </a-tab-pane>
+        <a-tab-pane key="3" tab="历史数据">
+          <div class="tab-item" v-if="activeKey === '3' && isRefresh">
+            <HistoryTable columns-type="sys_surface_junya" device-type="sys_surface_junya" :device-list-api="baseList" designScope="sys_surface_junya-history" />
+          </div>
+        </a-tab-pane>
+        <a-tab-pane key="4" tab="报警历史">
+          <div class="tab-item" v-if="activeKey === '4' && isRefresh">
+            <AlarmHistoryTable columns-type="alarm" device-type="sys_surface_junya" :device-list-api="baseList" designScope="alarm-history" />
+          </div>
+        </a-tab-pane>
+        <a-tab-pane key="5" tab="操作历史">
+          <div class="tab-item" v-if="activeKey === '5' && isRefresh">
+            <HandlerHistoryTable columns-type="operatorhistory" device-type="sys_surface_junya" :device-list-api="baseList" designScope="alarm-history" />
+          </div>
+        </a-tab-pane>
+      </a-tabs>
+    </div>
+  </div>
+  <div style="z-index: -1; position: absolute; top: 50px; right: 10px; width: 300px; height: 280px; margin: auto" class="player1">
+    <LivePlayer id="jb-player1" ref="player1" :videoUrl="flvURL1()" muted live loading controls />
+  </div>
+</template>
+
+<script setup lang="ts">
+  import { onBeforeMount, ref, onMounted, nextTick, toRaw, reactive, onUnmounted, watch } from 'vue';
+  import BarSingle from '../../../../components/chart/BarSingle.vue';
+  import GroupMonitorTable from '../comment/GroupMonitorTable.vue';
+  import HistoryTable from '../comment/HistoryTable.vue';
+  import AlarmHistoryTable from '../comment/AlarmHistoryTable.vue';
+  import HandlerHistoryTable from '../comment/HandlerHistoryTable.vue';
+  import { mountedThree, setModelType, destroy, addCssText, addText, playSmoke } from './balancePress.three';
+  import lodash from 'lodash';
+  import { getTableList, list } from '/@/views/vent/monitorManager/fanLocalMonitor/fanLocal.api';
+  import { list as baseList } from '../../deviceManager/fanTabel/fan.api';
+  import { chartsColumns, chartsColumns1 } from './balancePress.data';
+  import LivePlayer from '@liveqing/liveplayer-v3';
+  import { setDivHeight } from '/@/utils/event';
+
+  const isRefresh = ref(true)
+  const scroll = reactive({
+    y: 180
+  })
+  
+  const loading = ref(false);
+  const activeKey = ref('1');
+  const player1 = ref();
+  // 默认初始是第一行
+  const selectRowIndex = ref(0);
+
+  // 监测数据
+  const initData = {
+    deviceID: '',
+    deviceType: '',
+    strname: '',
+    dataDh: '-', //压差
+    dataDtestq: '-', //测试风量
+    sourcePressure: '-', //气源压力
+    dataDequivalarea: '-',
+    netStatus: '0', //通信状态
+    fault: '气源压力超限',
+  };
+  const flvURL1 = () => {
+    // return `https://sf1-hscdn-tos.pstatp.com/obj/media-fe/xgplayer_doc_video/flv/xgplayer-demo-360p.flv`;
+    return ''
+  };
+  // 监测数据
+  const selectData = reactive(lodash.cloneDeep(initData));
+
+  const tabChange = (activeKeyVal) => {
+    activeKey.value = activeKeyVal;
+  };
+
+  const dataSource = ref([]);
+
+  //
+  async function getDataSource(){
+    const res = await list({ devicetype: 'sys_surface_junya', pagetype: 'normal' });
+    const dataArr = res.msgTxt[0].datalist || [];
+    dataSource.value = [];
+    dataArr.forEach((data) => {
+      const readData = data.readData;
+      data = Object.assign(data, readData);
+      dataSource.value.push(data);
+    });
+    const data: any = toRaw(dataSource.value[selectRowIndex.value]); //maxarea
+    return data;
+  };
+
+  // https获取监测数据
+  let timer: null | NodeJS.Timeout = null;
+  function getMonitor(flag?) {
+    if (Object.prototype.toString.call(timer) === '[object Null]') {
+      timer = setTimeout(async () => {
+        await getDataSource();
+        Object.assign(selectData, deviceBaseList.value, dataSource.value[selectRowIndex.value]);
+        addText(selectData);
+        // playAnimation(data, selectData.maxarea);
+        if (timer) {
+          timer = null;
+        }
+        getMonitor();
+      }, flag ? 0 :1000);
+    }
+  };
+
+  // 获取设备基本信息列表
+  const deviceBaseList = ref([]);
+  function getDeviceBaseList() {
+    getTableList({ pageSize: 1000 }).then((res) => {
+      deviceBaseList.value = res.records;
+    });
+  };
+
+  // 切换检测数据
+  function getSelectRow(id) {
+    if (!id) return;
+    loading.value = true;
+    const baseDataIndex: any = dataSource.value.findIndex((baseData: any) => baseData.deviceID === id);
+    selectRowIndex.value = baseDataIndex;
+    const type = baseDataIndex > 0 ? 'fm' : 'fc';
+    setModelType(type).then(() => {
+      loading.value = false;
+    });
+    // const data = dataSource.value[baseDataIndex];
+    
+    // addCssText(selectRowIndex.value);
+    return;
+  };
+
+  function addPlayVideo() {
+    if (player1.value && player1.value.play) {
+      if (!player1.value.paused()) player1.value.play();
+      document.body.removeEventListener('mousedown', addPlayVideo);
+    }
+  };
+
+  watch(() => scroll.y, () => {
+    isRefresh.value = false
+    nextTick(() => {
+      isRefresh.value = true
+    })
+  })
+
+  onBeforeMount(() => {
+    getDeviceBaseList();
+  });
+
+  onMounted(() => {
+    
+    // loading.value = true;
+    mountedThree(player1.value).then(() => {
+      nextTick(() => {
+        getMonitor(true);
+        // addCssText(selectRowIndex.value);
+
+        playSmoke('startSmoke', 'top', 30, 'open');
+      });
+    });
+    document.body.addEventListener('mousedown', addPlayVideo, false);
+  });
+
+  onUnmounted(() => {
+    destroy();
+    if (timer) {
+      clearTimeout(timer);
+      timer = undefined;
+    }
+  });
+</script>
+<style scoped lang="less">
+  @import '/@/design/vent/modal.less';
+  :deep(.@{ventSpace}-tabs-tabpane-active) {
+    overflow: auto;
+  }
+  .input-box {
+    display: flex;
+    align-items: center;
+    .input-title {
+      color: #73e8fe;
+      width: auto;
+    }
+    margin-right: 10px;
+  }
+  .label {
+    max-width: 220px;
+  }
+  .@{ventSpace}-input {
+    width: 150px;
+  }
+</style>

+ 1 - 1
src/views/vent/monitorManager/beltTunMonitor/beltTun.threejs.ts

@@ -82,7 +82,7 @@ export const setModelType = (type) => {
         const position = { x: 5.369494685025012, y: 3.6247292490341736, z: 7.5 };
         await animateCamera(
           oldCameraPosition,
-          oldCameraPosition,
+          { x: 0, y: 0, z: 0 },
           { x: position.x, y: position.y, z: position.z },
           { x: 0, y: 0, z: 0 },
           model,

+ 13 - 0
src/views/vent/monitorManager/chamberMonitor/chamber.data.ts

@@ -61,3 +61,16 @@ export const dustColumns: BasicColumn[] = [
     align: 'center',
   },
 ];
+
+export const windowParam = [
+  {
+    title: '前窗面积',
+    code: 'valve1Val',
+    inputNum: 0,
+  },
+  {
+    title: '后窗面积',
+    code: 'valve2Val',
+    inputNum: 0,
+  },
+];

+ 0 - 36
src/views/vent/monitorManager/chamberMonitor/chamber.threejs.base.ts

@@ -1,5 +1,4 @@
 import * as THREE from 'three';
-import { setModalCenter } from '/@/utils/threejs/util';
 // import * as dat from 'dat.gui';
 // const gui = new dat.GUI();
 // gui.domElement.style = 'position:absolute;top:100px;left:10px;z-index:99999999999999';
@@ -31,41 +30,6 @@ class ChamberBase {
     //   directionalLight.position.z = Number(value);
     //   _this.render();
     // });
-    // const pointLight5 = new THREE.PointLight(0xffffff, 0.8, 120);
-    // pointLight5.position.set(-54, 30, 23.8);
-    // pointLight5.shadow.bias = 0.05;
-    // this.group.add(pointLight5);
-
-    // const pointLight7 = new THREE.PointLight(0xffffff, 1, 1000);
-    // pointLight7.position.set(45, 51, -4.1);
-    // pointLight7.shadow.bias = 0.05;
-    // this.model.scene.add(pointLight7);
-
-    const spotLight = new THREE.SpotLight();
-    spotLight.angle = Math.PI / 2;
-    spotLight.penumbra = 0;
-    spotLight.castShadow = true;
-    spotLight.intensity = 1;
-
-    spotLight.shadow.camera.near = 0.5; // default
-    spotLight.shadow.focus = 1.2;
-    spotLight.shadow.bias = -0.000002;
-
-    spotLight.position.set(-7.19, 199, -68.1);
-    // this.group.add(spotLight);
-
-    // gui.add(directionalLight.position, 'x', -10, 20).onChange(function (value) {
-    //   directionalLight.position.x = Number(value);
-    //   _this.render();
-    // });
-    // gui.add(directionalLight.position, 'y', -50, 50).onChange(function (value) {
-    //   directionalLight.position.y = Number(value);
-    //   _this.render();
-    // });
-    // gui.add(directionalLight.position, 'z', -20, 20).onChange(function (value) {
-    //   directionalLight.position.z = Number(value);
-    //   _this.render();
-    // });
 
     // gui.add(spotLight.position, 'x', -600, 600).onChange(function (value) {
     //   spotLight.position.x = Number(value);

+ 12 - 32
src/views/vent/monitorManager/chamberMonitor/chamber.threejs.ts

@@ -2,43 +2,24 @@ import * as THREE from 'three';
 import UseThree from '../../../../utils/threejs/useThree';
 import ChamberBase from './chamber.threejs.base';
 import { animateCamera, setModalCenter } from '/@/utils/threejs/util';
-import { useAppStore } from '/@/store/modules/app';
+import useEvent from '../../../../utils/threejs/useEvent';
 
 // 模型对象、 文字对象
 let model,
   chamberBaseObj: ChamberBase,
   group,
-  chamberType = 'chamberBase'; // workerFaceFiber
-const appStore = useAppStore();
+  chamberType = 'chamberBase';
+
+const { mouseDownFn } = useEvent();
 
 // 鼠标点击事件
 const mouseEvent = (event) => {
-  event.stopPropagation();
-  if (!model) return;
-  const widthScale = appStore.getWidthScale;
-  const heightScale = appStore.getHeightScale;
-  // 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)
-  model.mouse.x =
-    ((-model.canvasContainer.getBoundingClientRect().left * widthScale + event.clientX) / (model.canvasContainer.clientWidth * widthScale)) * 2 - 1;
-  model.mouse.y =
-    -((-model.canvasContainer.getBoundingClientRect().top + event.clientY) / (model.canvasContainer.clientHeight * heightScale)) * 2 + 1;
-  (model.rayCaster as THREE.Raycaster).setFromCamera(model.mouse, model.camera as THREE.Camera);
-  if (group) {
+  mouseDownFn(model, group, event, (intersects) => {
     if (chamberType === 'chamberBase') {
-      // chamberBaseObj.mousedownModel.call(chamberBaseObj, model.rayCaster);
+      // chamberBaseObj.mousedownModel.call(chamberBaseObj, intersects);
     }
-
-    // const intersects = model.rayCaster?.intersectObjects([...group.children]) as THREE.Intersection[];
-    // if (intersects.length > 0) {
-    //   if (fiberType === 'beltFiber') {
-    //     beltFiberObj.mousedownModel.call(beltFiberObj, intersects);
-    //   } else if (fiberType === 'workFace') {
-    //     workerFaceFiberObj.mousedownModel.call(workerFaceFiberObj, intersects);
-    //   }
-    // }
-
-    console.log('摄像头,控制器------>', model.camera, model.orbitControls);
-  }
+  });
+  console.log('摄像头控制信息', model.orbitControls, model.camera);
 };
 
 const addMouseEvent = () => {
@@ -56,7 +37,7 @@ const render = () => {
 
 export const addChamberText = (selectData) => {
   if (chamberType === 'chamberBase') {
-    return chamberBaseObj.addChamberText.call(chamberBaseObj, selectData);
+    // return chamberBaseObj.addChamberText.call(chamberBaseObj, selectData);
   }
 };
 
@@ -71,12 +52,11 @@ export const setModelType = (type) => {
       setModalCenter(model.scene);
       model.camera.position.set(0, 0, 300);
       setTimeout(async () => {
-        // const position = { x: 0, y: 3.8, z: 10.5 };
         await animateCamera(
           oldCameraPosition,
-          oldCameraPosition,
-          { x: 0.519594036828229, y: 411.8877286329627, z: 330.7728952161751 },
-          { x: 3.534969685817257, y: 14.506061950306899, z: -16.565361577001262 },
+          {x: 0, y: 0, z: 0},
+          { x: 11.19, y: 400.13, z: 344.20 },
+          { x: 10.446, y: 0.875, z: -0.993 },
           model,
           0.8
         );

+ 50 - 2
src/views/vent/monitorManager/chamberMonitor/components/chamberHome.vue

@@ -8,7 +8,55 @@
               <div>通风监测</div>
             </template>
             <template #container>
-          
+              <div class="vent-param">
+                <div class="light-group">
+                  <div class="param-item">
+                    <div class="param">
+                      <div class="param-icon">
+                        <div class="param-title">硐室风量</div>
+                        <div class="param-unit">(m³/min)</div>
+                      </div>
+
+                      <div class="param-val-box">
+                        <div class="param-val-icon"></div>
+                        <div class="param-val">3000</div>
+                      </div>
+                    </div>
+                  </div>
+                  <div class="param-item">
+                    <div class="param">
+                      <div class="param-icon">
+                        <div class="param-title">硐室需风量</div>
+                        <div class="param-unit">(m³/min)</div>
+                      </div>
+                      <div class="param-val-box">
+                        <div class="param-val-icon"></div>
+                        <div class="param-val">3500</div>
+                      </div>
+                    </div>
+                  </div>
+                  <div class="param-item">
+                    <div class="param">
+                      <div class="param-icon">
+                        <div class="param-title" style="color: #61ddb1; font-weight: 600; font-size: 16px;">风量</div>
+                        <div class="param-unit" style="color: #61ddb1; font-weight: 600; font-size: 14px; top: -4px;">预测</div>
+                      </div>
+                      <div class="param-val-box">
+                        <div class="param-val-icon"></div>
+                        <div class="param-val" style="color: #FF3823;">风量不足</div>
+                      </div>
+                    </div>
+                  </div>
+                </div>
+              </div>
+              <div class="input-box">
+                <div v-for="(item, index) in windowParam" :key="index" class="input-item">
+                  <div class="">{{ item.title }}</div>
+                  <div class="value">-</div>
+                  <a-input class="input-value" v-model="item.inputNum" placeholder="" />
+                  <span class="btn btn1">调节</span>
+                </div>
+              </div>
             </template>
           </ventBox1>
         </div>
@@ -181,7 +229,7 @@ import ventBox1 from '/@/components/vent/ventBox1.vue'
 import { mountedThree, destroy, addChamberText, setModelType } from '../chamber.threejs';
 import { SvgIcon } from '/@/components/Icon';
 import FourBorderBg from '/@/components/vent/fourBorderBg.vue';
-import { warningConfig, sensorColumns, dustColumns } from '../chamber.data'
+import { warningConfig, sensorColumns, dustColumns, windowParam } from '../chamber.data'
 import { list } from '../chamber.api';
 import LivePlayer from '@liveqing/liveplayer-v3';
 

+ 7 - 1
src/views/vent/monitorManager/compressor/nitrogen.dishang.threejs.ts

@@ -208,10 +208,16 @@ class Nitrogen {
       }
       this.model.setGLTFModel([this.modelName]).then(async (gltf) => {
         const nitrogenGroup = new THREE.Object3D();
+        const flag = nitrogenNum % 2 == 0 ? 0 : 1;
         for (let i = 0; i < nitrogenNum; i++) {
           const nitrogenModal = gltf[0].clone();
           nitrogenModal.name = 'nitrogenModal' + i;
-          nitrogenModal.position.set(0, 0, -1.29 * i);
+          const c = Math.floor(nitrogenNum / 2);
+          if (flag) {
+            nitrogenModal.position.set(0, 0, 1.355 * (c - i));
+          } else {
+            nitrogenModal.position.set(0, 0, (c - i - 0.5) * 1.355);
+          }
           nitrogenGroup.add(nitrogenModal);
         }
 

+ 21 - 36
src/views/vent/monitorManager/compressor/nitrogen.threejs.ts

@@ -2,7 +2,7 @@ import * as THREE from 'three';
 import { animateCamera, setModalCenter, updateAxisCenter } from '/@/utils/threejs/util';
 import UseThree from '../../../../utils/threejs/useThree';
 import Nitrogen from './nitrogen.dishang.threejs';
-import { useAppStore } from '/@/store/modules/app';
+import useEvent from '../../../../utils/threejs/useEvent';
 // import * as dat from 'dat.gui';
 // const gui = new dat.GUI();
 // gui.domElement.style = 'position:absolute;top:100px;left:10px;z-index:99999999999999';
@@ -11,35 +11,18 @@ import { useAppStore } from '/@/store/modules/app';
 let model, //
   group,
   nitrogenObj,
-  modalType = 'lmWindRect';
+  modalType = 'nitrogen';
 
-const appStore = useAppStore();
+const { mouseDownFn } = useEvent();
 
 // 鼠标点击、松开事件
 const mouseEvent = (event) => {
-  event.stopPropagation();
-  const widthScale = appStore.getWidthScale;
-  const heightScale = appStore.getHeightScale;
-  // 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)
-  model.mouse.x =
-    ((-model.canvasContainer.getBoundingClientRect().left * widthScale + event.clientX) / (model.canvasContainer.clientWidth * widthScale)) * 2 - 1;
-  model.mouse.y =
-    -((-model.canvasContainer.getBoundingClientRect().top + event.clientY) / (model.canvasContainer.clientHeight * heightScale)) * 2 + 1;
-  (model.rayCaster as THREE.Raycaster).setFromCamera(model.mouse, model.camera as THREE.Camera);
-
-  // console.log('相机与控制器信息--->', model.camera, model.orbitControls);
-  // updateAxisCenter(model, event);
-
-  if (group) {
-    const intersects = model.rayCaster?.intersectObjects(group.children, false) as THREE.Intersection[];
-    if (intersects.length > 0) {
-      // 单道、 双道
-      if (modalType === 'nitrogen') {
-        nitrogenObj.mousedownModel.call(nitrogenObj, intersects);
-      }
+  mouseDownFn(model, group, event, (intersects) => {
+    if (modalType === 'nitrogen') {
+      nitrogenObj.mousedownModel.call(nitrogenObj, intersects);
     }
-    console.log('99999------>', model.camera, model.orbitControls);
-  }
+    console.log('摄像头控制信息', model.orbitControls, model.camera);
+  });
 };
 
 /* 添加监控数据 */
@@ -68,19 +51,21 @@ export const setModelType = (type) => {
       const oldCameraPosition = { x: -1000, y: 100, z: 500 };
       const oldControlsPosition = { x: -10, y: 10, z: 10 };
       model.scene.add(nitrogenObj.group);
+      let newCameraPosition = { x: 0, y: 0, z: 0 },
+        newControlsPosition = { x: 0, y: 0, z: 0 };
+      if (group.children.length == 5) {
+        newCameraPosition = { x: 3.4434042980363104, y: 34.06459454762187, z: 106.31900957493957 };
+        newControlsPosition = { x: 3.060603700582905, y: -10.818677071155214, z: 6.036159227572685 };
+      } else if (group.children.length == 4) {
+        newCameraPosition = { x: 3.90030651836962, y: 38.026892031369755, z: 87.12943006242206 };
+        newControlsPosition = { x: 3.584174940307743, y: -6.858117412269035, z: 4.311833565101436 };
+      } else if (group.children.length == 3) {
+        newCameraPosition = { x: 4.033864762820565, y: 46.68282110004381, z: 82.43762902763777 };
+        newControlsPosition = { x: 3.7177327628205648, y: 1.7978121000437965, z: -0.37996697236224625 };
+      }
       setTimeout(async () => {
         resolve(null);
-        await animateCamera(
-          oldCameraPosition,
-          oldControlsPosition,
-          // { x: -0.24658823766780538, y: 35.50352092191473, z: 83.90511756512278 },
-          // { x: -0.24658823766780538, y: 35.50352092191473, z: 83.90511756512278 },
-          // { x: 1.5582599568763913, y: -3.2828007511721147, z: 2.2606374587827234 },
-          { x: 0.2528210526315788, y: 38.731704155124646, z: 66.23189916897506 },
-          { x: 0, y: 0, z: 0 },
-          model,
-          0.8
-        );
+        await animateCamera(oldCameraPosition, oldControlsPosition, newCameraPosition, newControlsPosition, model, 0.8);
       }, 300);
     }
   });

+ 2 - 1
src/views/vent/monitorManager/deviceMonitor/components/device/device.api.ts

@@ -3,7 +3,8 @@ import { defHttp } from '/@/utils/http/axios';
 enum Api {
   list = '/ventanaly-device/monitor/device',
   baseList = '/safety/ventanalyDeviceInfo/list',
-  deviceTypeList = '/safety/ventanalyDeviceInfo/DeviceKind/query',
+  // deviceTypeList = '/safety/ventanalyDeviceInfo/DeviceKind/query',
+  deviceTypeList = '/sys/dict/DeviceKind/queryBySystem',
   itemList = '/sys/dictItem/list',
 }
 /**

+ 2 - 2
src/views/vent/monitorManager/fanLocalMonitor/fanLocal.three.ts

@@ -123,7 +123,7 @@ export const setModelType = (type) => {
         const oldCameraPosition = { x: 500, y: 100, z: 500 };
         await animateCamera(
           oldCameraPosition,
-          oldCameraPosition,
+          { x: 0, y: 0, z: 0 },
           { x: 0, y: 20, z: 80 },
           { x: position.x, y: position.y, z: position.z },
           model,
@@ -142,7 +142,7 @@ export const setModelType = (type) => {
         const oldCameraPosition = { x: 500, y: 100, z: 500 };
         await animateCamera(
           oldCameraPosition,
-          oldCameraPosition,
+          { x: 0, y: 0, z: 0 },
           { x: 0, y: 20, z: 80 },
           { x: position.x, y: position.y, z: position.z },
           model,

+ 2 - 2
src/views/vent/monitorManager/fiberMonitor/fiber.threejs.ts

@@ -101,7 +101,7 @@ export const setModelType = (type) => {
         const position = { x: 0, y: 3.8, z: 10.5 };
         await animateCamera(
           oldCameraPosition,
-          oldCameraPosition,
+          { x: 0, y: 0, z: 0 },
           { x: position.x, y: position.y, z: position.z },
           { x: 10, y: 3.1, z: -8.8 },
           model,
@@ -126,7 +126,7 @@ export const setModelType = (type) => {
         const position = { x: 0, y: 3.8, z: 1.5 };
         await animateCamera(
           oldCameraPosition,
-          oldCameraPosition,
+          { x: 0, y: 0, z: 0 },
           { x: position.x, y: position.y, z: position.z },
           { x: 10, y: 3.1, z: -8.8 },
           model,

+ 608 - 0
src/views/vent/monitorManager/gateMonitor/gate.threejs.three.ts

@@ -0,0 +1,608 @@
+import * as THREE from 'three';
+import { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer.js';
+import { getTextCanvas, renderVideo } from '/@/utils/threejs/util';
+import UseThree from '../../../../utils/threejs/useThree';
+import { drawHot } from '/@/utils/threejs/util';
+import { useAppStore } from '/@/store/modules/app';
+
+// const gui = new dat.GUI();
+// gui.domElement.style = 'position:absolute;top:10px;right:10px;z-index:99999999999999';
+
+class Fm1 {
+  modelName = 'fm';
+  model; //
+  group;
+  isLRAnimation = true; // 是否开启左右摇摆动画
+  direction = 1; // 摇摆方向
+  animationTimer: NodeJS.Timeout | null = null; // 摇摆开启定时器
+  player1;
+  player2;
+  deviceDetailCSS3D;
+  playerStartClickTime1 = new Date().getTime();
+  playerStartClickTime2 = new Date().getTime();
+
+  frontClock = new THREE.Clock();
+  backClock = new THREE.Clock();
+
+  appStore = useAppStore();
+
+  clipActionArr = {
+    frontDoor: null as unknown as THREE.AnimationAction,
+    backDoor: null as unknown as THREE.AnimationAction,
+  };
+
+  constructor(model, playerVal1, playerVal2) {
+    this.model = model;
+    this.player1 = playerVal1;
+    this.player2 = playerVal2;
+  }
+
+  addLight(scene) {
+    const pointLight2 = new THREE.PointLight(0xffeeee, 0.8, 300);
+    pointLight2.position.set(-113, 29, 10);
+    // light2.castShadow = true
+    pointLight2.shadow.bias = -0.05;
+    scene.add(pointLight2);
+    // const pointLightHelper2 = new THREE.PointLightHelper( pointLight2, 1 );
+    // scene.add( pointLightHelper2 );
+
+    const pointLight3 = new THREE.PointLight(0xffffff, 0.8, 100);
+    pointLight3.position.set(0, 30, 3);
+    // light2.castShadow = true
+    pointLight3.shadow.bias = -0.05;
+    scene.add(pointLight3);
+    // const pointLightHelper = new THREE.PointLightHelper( pointLight3, 1 );
+    // scene.add( pointLightHelper );
+
+    const pointLight4 = new THREE.PointLight(0xffeeee, 0.6, 100);
+    pointLight4.position.set(-14, 29, 13);
+    // light2.castShadow = true
+    pointLight4.shadow.bias = -0.05;
+    scene.add(pointLight4);
+    // const pointLightHelper4 = new THREE.PointLightHelper( pointLight4, 1 );
+    // scene.add( pointLightHelper4 );
+
+    const pointLight5 = new THREE.PointLight(0xffffff, 0.8, 100);
+    pointLight5.position.set(80, 43, -5.3);
+    // light2.castShadow = true
+    pointLight5.shadow.bias = -0.05;
+    scene.add(pointLight5);
+    // const pointLightHelper5 = new THREE.PointLightHelper( pointLight5, 1 );
+    // scene.add( pointLightHelper5 );
+
+    const pointLight6 = new THREE.PointLight(0xffffff, 1, 300);
+    // pointLight6.position.set(-47, 49, 12.9)
+    pointLight6.position.set(-7, 40, 9);
+    // light2.castShadow = true
+    pointLight6.shadow.bias = -0.05;
+    scene.add(pointLight6);
+    // const pointLightHelper6 = new THREE.PointLightHelper( pointLight6, 1 );
+    // scene.add( pointLightHelper6 );
+
+    const pointLight7 = new THREE.PointLight(0xffffff, 0.8, 300);
+    pointLight7.position.set(45, 51, -4.1);
+    // light2.castShadow = true
+    pointLight7.shadow.bias = -0.05;
+    scene.add(pointLight7);
+    // const pointLightHelper7 = new THREE.PointLightHelper( pointLight7, 1 );
+    // scene.add( pointLightHelper7 );
+
+    // const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
+    // directionalLight.target = group;
+    // directionalLight.position.set(-18, 20, 39);
+    // directionalLight.rotation.set(1.3, 0.3, 5.8);
+    // scene.add(directionalLight);
+    // const helper = new THREE.DirectionalLightHelper(directionalLight, 5);
+    // scene.add(helper);
+
+    const spotLight = new THREE.SpotLight();
+    spotLight.angle = Math.PI / 16;
+    spotLight.penumbra = 0;
+    // spotLight.castShadow = true;
+    spotLight.position.set(-231, 463, 687);
+    scene.add(spotLight);
+
+    // spotLight.shadow.mapSize.width = 1500;  // default
+    // spotLight.shadow.mapSize.height = 800; // default
+    spotLight.shadow.camera.near = 0.5; // default
+    spotLight.shadow.camera.far = 1000; // default
+    spotLight.shadow.focus = 1.2;
+    spotLight.shadow.bias = -0.000002;
+
+    // const spotLightHelper = new THREE.SpotLightHelper(spotLight);
+    // scene.add(spotLightHelper);
+
+    // model.canvasContainer?.appendChild(gui.domElement);
+    // gui.add(directionalLight.position, 'x', -100, 100).step(1);
+    // gui.add(directionalLight.position, 'y', -100, 100).step(1);
+    // gui.add(directionalLight.position, 'z', -100, 100).step(1);
+    // gui.add(directionalLight.rotation, 'x', -Math.PI, 2 * Math.PI).step(0.1);
+    // gui.add(directionalLight.rotation, 'y', -Math.PI, 2 * Math.PI).step(0.1);
+    // gui.add(directionalLight.rotation, 'z', -Math.PI, 2 * Math.PI).step(0.1);
+    // gui.add(spotLight, 'angle', 0, Math.PI / 2);
+    // gui.add(spotLight, 'distance', 0, 1000);
+    // gui.add(pointLight6.position, 'x', -200, 200)
+    // gui.add(pointLight6.position, 'y', -200, 200)
+    // gui.add(pointLight6.position, 'z', -200, 200)
+  }
+  // 重置摄像头
+  resetCamera() {
+    this.model.camera.far = 274;
+    this.model.orbitControls?.update();
+    this.model.camera.updateProjectionMatrix();
+  }
+  // 设置模型位置
+  setModalPosition() {
+    this.group?.scale.set(22, 22, 22);
+    this.group?.position.set(-20, 20, 9);
+  }
+
+  /* 添加监控数据 */
+  addFmText(selectData) {
+    if (!this.group) {
+      return;
+    }
+    const textArr = [
+      {
+        text: `远程控制自动风门`,
+        font: 'normal 30px Arial',
+        color: '#00FF00',
+        strokeStyle: '#007400',
+        x: 120,
+        y: 100,
+      },
+      {
+        text: `压力(Pa):`,
+        font: 'normal 30px Arial',
+        color: '#00FF00',
+        strokeStyle: '#007400',
+        x: 0,
+        y: 155,
+      },
+      {
+        text: `${selectData.frontRearDP}`,
+        font: 'normal 30px Arial',
+        color: '#00FF00',
+        strokeStyle: '#007400',
+        x: 290,
+        y: 155,
+      },
+      {
+        text: `动力源压力(MPa): `,
+        font: 'normal 30px Arial',
+        color: '#00FF00',
+        strokeStyle: '#007400',
+        x: 0,
+        y: 215,
+      },
+      {
+        text: ` ${selectData.sourcePressure}`,
+        font: 'normal 30px Arial',
+        color: '#00FF00',
+        strokeStyle: '#007400',
+        x: 280,
+        y: 215,
+      },
+      {
+        text: `故障诊断:`,
+        font: 'normal 30px Arial',
+        color: '#00FF00',
+        strokeStyle: '#007400',
+        x: 0,
+        y: 275,
+      },
+      {
+        text: `${selectData.fault}`,
+        font: 'normal 30px Arial',
+        color: '#00FF00',
+        strokeStyle: '#007400',
+        x: 280,
+        y: 275,
+      },
+      {
+        text: `煤炭科学技术研究院有限公司研制`,
+        font: 'normal 28px Arial',
+        color: '#00FF00',
+        strokeStyle: '#007400',
+        x: 20,
+        y: 325,
+      },
+    ];
+
+    //
+    getTextCanvas(526, 346, textArr, '').then((canvas: HTMLCanvasElement) => {
+      const textMap = new THREE.CanvasTexture(canvas); // 关键一步
+      textMap.encoding = THREE.sRGBEncoding;
+      const textMaterial = new THREE.MeshBasicMaterial({
+        // 关于材质并未讲解 实操即可熟悉                 这里是漫反射类似纸张的材质,对应的就有高光类似金属的材质.
+        map: textMap, // 设置纹理贴图
+        transparent: true,
+        side: THREE.FrontSide, // 这里是双面渲染的意思
+      });
+      textMaterial.blending = THREE.CustomBlending;
+      const monitorPlane = this.group.getObjectByName('monitorText');
+      if (monitorPlane) {
+        monitorPlane.material = textMaterial;
+      } else {
+        const planeGeometry = new THREE.PlaneGeometry(526, 346); // 平面3维几何体PlaneGeometry
+        const planeMesh = new THREE.Mesh(planeGeometry, textMaterial);
+        planeMesh.name = 'monitorText';
+        planeMesh.scale.set(0.002, 0.002, 0.002);
+        planeMesh.position.set(-1.255, 0.09, -0.41);
+        this.group.add(planeMesh);
+      }
+    });
+  }
+
+  /** 添加热点 */
+  drawHots() {
+    const hotPositions = [
+      { x: -0.37, y: 0.26, z: -0.32 },
+      { x: 0.28, y: -0.2, z: -0.43 },
+      { x: 0.55, y: -0.22, z: -0.38 },
+    ];
+    for (let i = 0; i < 3; i++) {
+      const hotPoint = drawHot(0.1);
+      const position = hotPositions[i];
+      // hotPoint.scale.set(0.3, 0.3, 0.3);
+      hotPoint.position.set(position.x, position.y, position.z);
+      hotPoint.name = 'hotPoint' + i;
+      this.group?.add(hotPoint);
+    }
+  }
+
+  /* 风门动画 */
+  render() {
+    if (!this.model) {
+      return;
+    }
+    if (this.isLRAnimation && this.group) {
+      // 左右摇摆动画
+      if (Math.abs(this.group.rotation.y) >= 0.2) {
+        this.direction = -this.direction;
+        this.group.rotation.y += 0.00002 * 30 * this.direction;
+      } else {
+        this.group.rotation.y += 0.00002 * 30 * this.direction;
+      }
+    }
+
+    // // //自发光
+    // const screen = group.getObjectByName('对象156');
+    // if (screen) {
+    //   model.renderer.clearDepth();
+    //   screen.layers.enable(31);
+    //   !!renderBloomPass && renderBloomPass(group);
+    // }
+
+    // 风门开关动画
+    const frontDelta = this.frontClock?.getElapsedTime() + 0.5;
+    const backDelta = this.backClock?.getElapsedTime() + 0.5;
+    if (this.model.mixers[0]) this.model.mixers[0]?.update(frontDelta); //前门
+    if (this.model.mixers[1]) this.model.mixers[1]?.update(backDelta); // 后门
+  }
+
+  /* 点击风窗,风窗全屏 */
+  mousedownModel(intersects: THREE.Intersection<THREE.Object3D<THREE.Event>>[]) {
+    this.isLRAnimation = false;
+    if (this.animationTimer) {
+      clearTimeout(this.animationTimer);
+      this.animationTimer = null;
+    }
+
+    // 判断是否点击到视频
+    intersects.find((intersect) => {
+      const mesh = intersect.object;
+      if (mesh.name === 'player1') {
+        if (new Date().getTime() - this.playerStartClickTime1 < 400) {
+          // model.orbitControls?.dispatchEvent.call(model.orbitControls, { type: 'end' })
+          // 双击,视频放大
+          if (this.player1) {
+            this.player1.requestFullscreen();
+          }
+        }
+        this.playerStartClickTime1 = new Date().getTime();
+        return true;
+      } else if (mesh.name === 'player2') {
+        if (new Date().getTime() - this.playerStartClickTime2 < 400) {
+          // model.orbitControls?.dispatchEvent.call(model.orbitControls, { type: 'end' })
+          // 双击,视频放大
+          if (this.player2) {
+            this.player2.requestFullscreen();
+          }
+        }
+        this.playerStartClickTime2 = new Date().getTime();
+        return true;
+      } else if (mesh.name.startsWith('hotPoint')) {
+        if (this.deviceDetailCSS3D) {
+          this.deviceDetailCSS3D.position.set(mesh.position.x + 0.035, mesh.position.y + 0.66, mesh.position.z + 0.02);
+          console.log('[ deviceDetailCSS3D.position ] >', this.deviceDetailCSS3D.position);
+          this.deviceDetailCSS3D.visible = true;
+          return true;
+        }
+        
+      } else {
+        this.deviceDetailCSS3D.visible = false;
+        console.log('[ 点击事件 ] >');
+      }
+      return false;
+    });
+  }
+
+  mouseUpModel() {
+    // 10s后开始摆动
+    if (!this.animationTimer && !this.isLRAnimation) {
+      this.animationTimer = setTimeout(() => {
+        this.isLRAnimation = true;
+      }, 10000);
+    }
+  }
+
+  /* 提取风门序列帧,初始化前后门动画 */
+  initAnimation() {
+    const fmGroup = this.group?.getObjectByName('Fm-door');
+    if (fmGroup) {
+      const tracks = fmGroup.animations[0].tracks;
+      const fontTracks: any[] = [],
+        backTracks: any[] = [];
+      for (let i = 0; i < tracks.length; i++) {
+        const track = tracks[i];
+        if (track.name.startsWith('qianmen')) {
+          fontTracks.push(track);
+        } else if (track.name.startsWith('houmen')) {
+          backTracks.push(track);
+        }
+      }
+      const frontDoor = new THREE.AnimationClip('frontDoor', 4, fontTracks);
+      const frontMixer = new THREE.AnimationMixer(fmGroup);
+      this.model.mixers.push(frontMixer);
+      const frontClipAction = frontMixer.clipAction(frontDoor, fmGroup);
+      frontClipAction.clampWhenFinished = true;
+      frontClipAction.loop = THREE.LoopOnce;
+      this.clipActionArr.frontDoor = frontClipAction;
+
+      const backDoor = new THREE.AnimationClip('backDoor', 4, backTracks);
+      const backMixer = new THREE.AnimationMixer(fmGroup);
+      this.model.mixers.push(backMixer);
+      const backClipAction = backMixer.clipAction(backDoor, fmGroup);
+      backClipAction.clampWhenFinished = true;
+      backClipAction.loop = THREE.LoopOnce;
+      this.clipActionArr.backDoor = backClipAction;
+    }
+  }
+
+  deviceDetailCard(position = { x: 0, y: 0, z: 0 }) {
+    const element = document.getElementById('deviceCard') as HTMLElement;
+    this.deviceDetailCSS3D = new CSS2DObject(element);
+    this.deviceDetailCSS3D.name = 'deviceCard';
+    this.deviceDetailCSS3D.position.set(position.x, position.y, position.z);
+    this.deviceDetailCSS3D.visible = false;
+    // this.model.scene.add(this.deviceDetailCSS3D);
+    this.group.add(this.deviceDetailCSS3D);
+  }
+
+  // 播放动画
+  play(handlerState, timeScale = 0.01) {
+    let handler = () => {};
+    switch (handlerState) {
+      case 1: // 打开前门
+        handler = () => {
+          debugger;
+          this.clipActionArr.frontDoor.paused = true;
+          this.clipActionArr.frontDoor.reset();
+          this.clipActionArr.frontDoor.time = 1.2;
+          this.clipActionArr.frontDoor.timeScale = timeScale;
+          this.clipActionArr.frontDoor.clampWhenFinished = true;
+          this.clipActionArr.frontDoor.play();
+          this.frontClock.start();
+        };
+        break;
+      case 2: // 关闭前门
+        handler = () => {
+          debugger;
+          this.clipActionArr.frontDoor.paused = true;
+          this.clipActionArr.frontDoor.reset(); //
+          this.clipActionArr.frontDoor.time = 4;
+          this.clipActionArr.frontDoor.timeScale = -timeScale;
+          this.clipActionArr.frontDoor.clampWhenFinished = true;
+          this.clipActionArr.frontDoor.play();
+          this.frontClock.start();
+        };
+        break;
+      case 3: // 打开后门
+        handler = () => {
+          debugger;
+          this.clipActionArr.backDoor.paused = true;
+          this.clipActionArr.backDoor.reset();
+          this.clipActionArr.backDoor.time = 1.2;
+          this.clipActionArr.backDoor.timeScale = timeScale;
+          this.clipActionArr.backDoor.clampWhenFinished = true;
+          this.clipActionArr.backDoor.play();
+          this.backClock.start();
+        };
+        break;
+      case 4: // 关闭后门
+        handler = () => {
+          debugger;
+          this.clipActionArr.backDoor.paused = true;
+          this.clipActionArr.backDoor.reset();
+          this.clipActionArr.backDoor.time = 4;
+          this.clipActionArr.backDoor.timeScale = -timeScale;
+          this.clipActionArr.backDoor.clampWhenFinished = true;
+          this.clipActionArr.backDoor.play();
+          this.backClock.start();
+        };
+        break;
+      case 5: // 打开前后门
+        handler = () => {
+          debugger;
+          this.clipActionArr.backDoor.paused = true;
+          this.clipActionArr.frontDoor.paused = true;
+
+          this.clipActionArr.frontDoor.reset();
+          this.clipActionArr.frontDoor.time = 0;
+          this.clipActionArr.frontDoor.timeScale = 0.01;
+          this.clipActionArr.frontDoor.clampWhenFinished = true;
+          this.clipActionArr.frontDoor.play();
+
+          this.clipActionArr.backDoor.reset();
+          this.clipActionArr.backDoor.time = 0;
+          this.clipActionArr.backDoor.timeScale = 0.01;
+          this.clipActionArr.backDoor.clampWhenFinished = true;
+          this.clipActionArr.backDoor.play();
+          this.frontClock.start();
+          this.backClock.start();
+        };
+        break;
+      case 6: // 关闭前后门
+        handler = () => {
+          debugger;
+          this.clipActionArr.backDoor.paused = true;
+          this.clipActionArr.frontDoor.paused = true;
+
+          this.clipActionArr.frontDoor.reset();
+          this.clipActionArr.frontDoor.time = 4;
+          this.clipActionArr.frontDoor.timeScale = -0.01;
+          this.clipActionArr.frontDoor.clampWhenFinished = true;
+          this.clipActionArr.frontDoor.play();
+          this.clipActionArr.backDoor.reset();
+          this.clipActionArr.backDoor.time = 4;
+          this.clipActionArr.backDoor.timeScale = -0.01;
+          this.clipActionArr.backDoor.clampWhenFinished = true;
+          this.clipActionArr.backDoor.play();
+          this.frontClock.start();
+          this.backClock.start();
+        };
+        break;
+      default:
+    }
+
+    handler();
+    // model.clock.start();
+    // const honglvdeng = group.getObjectByName('honglvdeng');
+    // const material = honglvdeng.material;
+    // setTimeout(() => {
+    //   if (handlerState === 2 || handlerState === 4 || handlerState === 6) {
+    //     material.color = new THREE.Color(0x00ff00);
+    //   } else {
+    //     material.color = new THREE.Color(0xff0000);
+    //   }
+    // }, 1000);
+  }
+
+  mountedThree() {
+    this.group = new THREE.Object3D();
+    this.group.name = this.modelName;
+    return new Promise((resolve) => {
+      this.model = new UseThree('#damper3D', '', '#deviceDetail');
+
+      this.model.setEnvMap('test1');
+      this.model.renderer.toneMappingExposure = 1;
+      this.model.scene?.add(this.group);
+      this.group?.layers.enableAll();
+
+      this.model.setGLTFModel(['Fm-door', 'Fm-wire', 'Fm-wall'], this.group).then(() => {
+        this.setModalPosition();
+        // 初始化左右摇摆动画;
+        this.initAnimation();
+        this.drawHots();
+
+        this.deviceDetailCard();
+        this.model.animate();
+        if (this.model.camera.layers.mask == -1) this.model.camera.layers.toggle(1);
+        setTimeout(async () => {
+          const videoPlayer1 = document.getElementById('fm-player1')?.getElementsByClassName('vjs-tech')[0];
+          const videoPlayer2 = document.getElementById('fm-player2')?.getElementsByClassName('vjs-tech')[0];
+          if (!videoPlayer1 || !videoPlayer2) {
+            const textArr = [
+              {
+                text: `无信号输入`,
+                font: 'normal 40px Arial',
+                color: '#009900',
+                strokeStyle: '#002200',
+                x: 170,
+                y: 40,
+              },
+            ];
+            getTextCanvas(560, 346, textArr, '').then((canvas: HTMLCanvasElement) => {
+              const textMap = new THREE.CanvasTexture(canvas); // 关键一步
+              const textMaterial = new THREE.MeshBasicMaterial({
+                map: textMap, // 设置纹理贴图
+                transparent: true,
+                side: THREE.DoubleSide, // 这里是双面渲染的意思
+              });
+              textMaterial.blending = THREE.CustomBlending;
+              const monitorPlane = this.group?.getObjectByName('noPlayer');
+              if (monitorPlane) {
+                monitorPlane.material = textMaterial;
+              } else {
+                const planeGeometry = new THREE.PlaneGeometry(100, 100); // 平面3维几何体PlaneGeometry
+                const planeMesh = new THREE.Mesh(planeGeometry, textMaterial);
+                if (!videoPlayer1) {
+                  planeMesh.name = 'noPlayer1';
+                  planeMesh.scale.set(0.011, 0.008, 0.011);
+                  planeMesh.position.set(-4.23, -0.28, -0.39);
+                  this.group?.add(planeMesh.clone());
+                }
+                if (!videoPlayer2) {
+                  planeMesh.name = 'noPlayer2';
+                  planeMesh.scale.set(0.012, 0.009, 0.012);
+                  planeMesh.position.set(4.33, -0.33, -0.39);
+                  this.group?.add(planeMesh.clone());
+                }
+                textMaterial.dispose();
+                planeGeometry.dispose();
+              }
+            });
+          } else {
+            if (videoPlayer2) {
+              const mesh = renderVideo(this.group, videoPlayer1, 'player1');
+              mesh?.scale.set(-0.028, 0.0285, 1);
+              mesh?.position.set(4.298, 0.02, -0.4);
+              mesh.rotation.y = -Math.PI;
+              this.group.add(mesh);
+            }
+            if (videoPlayer1) {
+              const mesh = renderVideo(this.group, videoPlayer2, 'player2');
+              mesh?.scale.set(-0.028, 0.0285, 1);
+              mesh?.position.set(-4.262, 0.02, -0.4);
+              mesh.rotation.y = -Math.PI;
+              this.group.add(mesh);
+            }
+          }
+
+          resolve(this.model);
+        }, 0);
+      });
+    });
+  }
+
+  destroy() {
+    if (this.model) {
+      if (this.model.mixers[0]) {
+        this.model.mixers[0].uncacheClip(this.clipActionArr.frontDoor.getClip());
+        this.model.mixers[0].uncacheClip(this.clipActionArr.backDoor.getClip());
+        this.model.mixers[0].uncacheAction(this.clipActionArr.frontDoor, this.group);
+        this.model.mixers[0].uncacheAction(this.clipActionArr.backDoor, this.group);
+        this.model.mixers[0].uncacheRoot(this.group);
+
+        this.model.mixers[1].uncacheClip(this.clipActionArr.frontDoor.getClip());
+        this.model.mixers[1].uncacheClip(this.clipActionArr.backDoor.getClip());
+        this.model.mixers[1].uncacheAction(this.clipActionArr.frontDoor, this.group);
+        this.model.mixers[1].uncacheAction(this.clipActionArr.backDoor, this.group);
+        this.model.mixers[1].uncacheRoot(this.group);
+
+        if (this.model.animations[0]) this.model.animations[0].tracks = [];
+      }
+
+      this.clipActionArr.backDoor = undefined;
+      this.clipActionArr.frontDoor = undefined;
+
+      this.model.mixers = [];
+      this.model.deleteModal();
+      this.model = null;
+      this.group = null;
+      // document.getElementById('damper3D').parentElement.remove(document.getElementById('damper3D'))
+    }
+  }
+}
+export default Fm1;

+ 145 - 687
src/views/vent/monitorManager/gateMonitor/gate.threejs.ts

@@ -1,735 +1,193 @@
 import * as THREE from 'three';
-
-import { CSS3DObject } from 'three/examples/jsm/renderers/CSS3DRenderer.js';
-import { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer.js';
-import { getTextCanvas, renderVideo, transScreenCoord } from '/@/utils/threejs/util';
 import UseThree from '../../../../utils/threejs/useThree';
+import Fm1 from './gate.threejs.three';
 import { animateCamera } from '/@/utils/threejs/util';
-import { flyLine } from '/@/views/vent/comment/threejs/FlyLine';
-import { createComposer } from '/@/views/vent/comment/threejs/bloomPass';
-import * as dat from 'dat.gui';
-import { drawHot } from '/@/utils/threejs/util';
-import { useAppStore } from '/@/store/modules/app';
-
-// const gui = new dat.GUI();
-// gui.domElement.style = 'position:absolute;top:10px;right:10px;z-index:99999999999999';
+import useEvent from '../../../../utils/threejs/useEvent';
 
-const modelName = 'fm';
 // 模型对象、 文字对象
-let model, //
+let model,
+  fm1,
+  fm2,
   group,
-  fmCSS3D, //文字
-  isLRAnimation = true, // 是否开启左右摇摆动画
-  direction = 1, // 摇摆方向
-  animationtimer: NodeJS.Timeout | null, // 摇摆开启定时器
-  renderBloomPass,
-  player1,
-  player2,
-  deviceDetailCSS3D,
-  playerStartClickTime1 = new Date().getTime(),
-  playerStartClickTime2 = new Date().getTime();
-
-const frontClock = new THREE.Clock();
-const backClock = new THREE.Clock();
+  fmType = '';
 
-const appStore = useAppStore();
-
-const clipActionArr = {
-  frontDoor: null as unknown as THREE.AnimationAction,
-  backDoor: null as unknown as THREE.AnimationAction,
-};
+const { mouseDownFn } = useEvent();
 
 // 打灯光
-function addLight(scene) {
-  const pointLight2 = new THREE.PointLight(0xffeeee, 0.8, 300);
-  pointLight2.position.set(-113, 29, 10);
-  // light2.castShadow = true
-  pointLight2.shadow.bias = -0.05;
-  scene.add(pointLight2);
-  // const pointLightHelper2 = new THREE.PointLightHelper( pointLight2, 1 );
-  // scene.add( pointLightHelper2 );
-
-  const pointLight3 = new THREE.PointLight(0xffffff, 0.8, 100);
-  pointLight3.position.set(0, 30, 3);
-  // light2.castShadow = true
-  pointLight3.shadow.bias = -0.05;
-  scene.add(pointLight3);
-  // const pointLightHelper = new THREE.PointLightHelper( pointLight3, 1 );
-  // scene.add( pointLightHelper );
-
-  const pointLight4 = new THREE.PointLight(0xffeeee, 0.6, 100);
-  pointLight4.position.set(-14, 29, 13);
-  // light2.castShadow = true
-  pointLight4.shadow.bias = -0.05;
-  scene.add(pointLight4);
-  // const pointLightHelper4 = new THREE.PointLightHelper( pointLight4, 1 );
-  // scene.add( pointLightHelper4 );
-
-  const pointLight5 = new THREE.PointLight(0xffffff, 0.8, 100);
-  pointLight5.position.set(80, 43, -5.3);
-  // light2.castShadow = true
-  pointLight5.shadow.bias = -0.05;
-  scene.add(pointLight5);
-  // const pointLightHelper5 = new THREE.PointLightHelper( pointLight5, 1 );
-  // scene.add( pointLightHelper5 );
-
-  const pointLight6 = new THREE.PointLight(0xffffff, 1, 300);
-  // pointLight6.position.set(-47, 49, 12.9)
-  pointLight6.position.set(-7, 40, 9);
-  // light2.castShadow = true
-  pointLight6.shadow.bias = -0.05;
-  scene.add(pointLight6);
-  // const pointLightHelper6 = new THREE.PointLightHelper( pointLight6, 1 );
-  // scene.add( pointLightHelper6 );
-
-  const pointLight7 = new THREE.PointLight(0xffffff, 0.8, 300);
+const addLight = () => {
+  const pointLight2 = new THREE.PointLight(0xffeeee, 1, 83);
+  pointLight2.position.set(-101, 34, 16);
+  pointLight2.shadow.bias = 0.05;
+  model.scene.add(pointLight2);
+
+  const pointLight3 = new THREE.PointLight(0xffffff, 1, 150);
+  pointLight3.position.set(-61, 37, 13.9);
+  pointLight3.shadow.bias = 0.05;
+  model.scene.add(pointLight3);
+
+  const pointLight4 = new THREE.PointLight(0xffeeee, 0.6, 300);
+  pointLight4.position.set(-2, 26, 20);
+  pointLight4.shadow.bias = 0.05;
+  model.scene.add(pointLight4);
+
+  const pointLight5 = new THREE.PointLight(0xffffff, 0.8, 120);
+  pointLight5.position.set(-54, 30, 23.8);
+  pointLight5.shadow.bias = 0.05;
+  model.scene.add(pointLight5);
+
+  const pointLight7 = new THREE.PointLight(0xffffff, 1, 1000);
   pointLight7.position.set(45, 51, -4.1);
-  // light2.castShadow = true
-  pointLight7.shadow.bias = -0.05;
-  scene.add(pointLight7);
-  // const pointLightHelper7 = new THREE.PointLightHelper( pointLight7, 1 );
-  // scene.add( pointLightHelper7 );
-
-  // const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
-  // directionalLight.target = group;
-  // directionalLight.position.set(-18, 20, 39);
-  // directionalLight.rotation.set(1.3, 0.3, 5.8);
-  // scene.add(directionalLight);
-  // const helper = new THREE.DirectionalLightHelper(directionalLight, 5);
-  // scene.add(helper);
+  pointLight7.shadow.bias = 0.05;
+  model.scene.add(pointLight7);
 
   const spotLight = new THREE.SpotLight();
   spotLight.angle = Math.PI / 16;
   spotLight.penumbra = 0;
-  // spotLight.castShadow = true;
+  spotLight.castShadow = true;
+  spotLight.intensity = 1;
   spotLight.position.set(-231, 463, 687);
-  scene.add(spotLight);
+  model.scene.add(spotLight);
 
-  // spotLight.shadow.mapSize.width = 1500;  // default
-  // spotLight.shadow.mapSize.height = 800; // default
   spotLight.shadow.camera.near = 0.5; // default
   spotLight.shadow.camera.far = 1000; // default
   spotLight.shadow.focus = 1.2;
   spotLight.shadow.bias = -0.000002;
-
-  // const spotLightHelper = new THREE.SpotLightHelper(spotLight);
-  // scene.add(spotLightHelper);
-
-  // model.canvasContainer?.appendChild(gui.domElement);
-  // gui.add(directionalLight.position, 'x', -100, 100).step(1);
-  // gui.add(directionalLight.position, 'y', -100, 100).step(1);
-  // gui.add(directionalLight.position, 'z', -100, 100).step(1);
-  // gui.add(directionalLight.rotation, 'x', -Math.PI, 2 * Math.PI).step(0.1);
-  // gui.add(directionalLight.rotation, 'y', -Math.PI, 2 * Math.PI).step(0.1);
-  // gui.add(directionalLight.rotation, 'z', -Math.PI, 2 * Math.PI).step(0.1);
-  // gui.add(spotLight, 'angle', 0, Math.PI / 2);
-  // gui.add(spotLight, 'distance', 0, 1000);
-  // gui.add(pointLight6.position, 'x', -200, 200)
-  // gui.add(pointLight6.position, 'y', -200, 200)
-  // gui.add(pointLight6.position, 'z', -200, 200)
-}
-
-// 重置摄像头
-function resetCamera() {
-  model.camera.far = 274;
-  model.orbitControls?.update();
-  model.camera.updateProjectionMatrix();
-}
-
-// 设置模型位置
-function setModalPosition() {
-  group?.scale.set(22, 22, 22);
-  group?.position.set(-20, 20, 9);
-}
-
-/* 添加监控数据 */
-export function addFmText(selectData) {
-  if (!group) {
-    return;
-  }
-  const textArr = [
-    {
-      text: `远程控制自动风门`,
-      font: 'normal 30px Arial',
-      color: '#00FF00',
-      strokeStyle: '#007400',
-      x: 120,
-      y: 100,
-    },
-    {
-      text: `压力(Pa):`,
-      font: 'normal 30px Arial',
-      color: '#00FF00',
-      strokeStyle: '#007400',
-      x: 0,
-      y: 155,
-    },
-    {
-      text: `${selectData.frontRearDP}`,
-      font: 'normal 30px Arial',
-      color: '#00FF00',
-      strokeStyle: '#007400',
-      x: 290,
-      y: 155,
-    },
-    {
-      text: `动力源压力(MPa): `,
-      font: 'normal 30px Arial',
-      color: '#00FF00',
-      strokeStyle: '#007400',
-      x: 0,
-      y: 215,
-    },
-    {
-      text: ` ${selectData.sourcePressure}`,
-      font: 'normal 30px Arial',
-      color: '#00FF00',
-      strokeStyle: '#007400',
-      x: 280,
-      y: 215,
-    },
-    {
-      text: `故障诊断:`,
-      font: 'normal 30px Arial',
-      color: '#00FF00',
-      strokeStyle: '#007400',
-      x: 0,
-      y: 275,
-    },
-    {
-      text: `${selectData.fault}`,
-      font: 'normal 30px Arial',
-      color: '#00FF00',
-      strokeStyle: '#007400',
-      x: 280,
-      y: 275,
-    },
-    {
-      text: `煤炭科学技术研究院有限公司研制`,
-      font: 'normal 28px Arial',
-      color: '#00FF00',
-      strokeStyle: '#007400',
-      x: 20,
-      y: 325,
-    },
-  ];
-
-  //
-  getTextCanvas(526, 346, textArr, '').then((canvas: HTMLCanvasElement) => {
-    const textMap = new THREE.CanvasTexture(canvas); // 关键一步
-    textMap.encoding = THREE.sRGBEncoding;
-    const textMaterial = new THREE.MeshBasicMaterial({
-      // 关于材质并未讲解 实操即可熟悉                 这里是漫反射类似纸张的材质,对应的就有高光类似金属的材质.
-      map: textMap, // 设置纹理贴图
-      transparent: true,
-      side: THREE.FrontSide, // 这里是双面渲染的意思
-    });
-    textMaterial.blending = THREE.CustomBlending;
-    const monitorPlane = group.getObjectByName('monitorText');
-    if (monitorPlane) {
-      monitorPlane.material = textMaterial;
-    } else {
-      const planeGeometry = new THREE.PlaneGeometry(526, 346); // 平面3维几何体PlaneGeometry
-      const planeMesh = new THREE.Mesh(planeGeometry, textMaterial);
-      planeMesh.name = 'monitorText';
-      planeMesh.scale.set(0.002, 0.002, 0.002);
-      planeMesh.position.set(-1.255, 0.09, -0.41);
-      group.add(planeMesh);
-    }
-  });
-}
-
-/** 添加热点 */
-function drawHots() {
-  const hotPositions = [
-    { x: -0.37, y: 0.26, z: -0.32 },
-    { x: 0.28, y: -0.2, z: -0.43 },
-    { x: 0.55, y: -0.22, z: -0.38 },
-  ];
-  for (let i = 0; i < 3; i++) {
-    const hotPoint = drawHot(0.1);
-    const position = hotPositions[i];
-    // hotPoint.scale.set(0.3, 0.3, 0.3);
-    hotPoint.position.set(position.x, position.y, position.z);
-    hotPoint.name = 'hotPoint' + i;
-    group?.add(hotPoint);
-  }
-}
-
-/* 漫游路线 */
-function createLine() {
-  const position = model.camera.position.clone();
-  //创建样条曲线,作为运动轨迹
-  const curve = new THREE.CatmullRomCurve3([
-    new THREE.Vector3(position.x, position.y, position.z),
-    new THREE.Vector3(26.586, 17.86, 14.144),
-    new THREE.Vector3(-0.075, 19.669, 15.051),
-    new THREE.Vector3(-154.882, 17.462, 14.981),
-    // new THREE.Vector3(76, 28, 27),
-  ]);
-  const geometry = new THREE.BufferGeometry().setFromPoints(curve.getPoints(5000));
-  // 材质对象
-  const material = new THREE.LineBasicMaterial({
-    color: 'red',
-  });
-  // 线条模型对象
-  const line = new THREE.Line(geometry, material);
-  // model?.scene.add(line) // 线条对象添加到场景中
-  return curve;
-}
-
-/* 开启漫游 */
-function enterMY() {
-  model.startAnimation = () => {};
-  model.camera.position.set(114.27, 15.293, 14.189);
-  model.camera.rotation.set(-86.23, 69.89, 85.98);
-  const curve = createLine();
-  let progress = 0;
-
-  model.startMY = () => {
-    if (progress <= 1 - 0.004 * 20) {
-      const point = curve.getPointAt(progress); //获取样条曲线指定点坐标,作为相机的位置
-      const pointBox = curve.getPointAt(progress + 0.004 * 20); //获取样条曲线指定点坐标
-      model.camera.position.set(point.x, point.y, point.z);
-      model.camera.lookAt(pointBox.x + 5, pointBox.y, pointBox.z);
-      // model.orbitControls.position0.set(point.x, point.y, point.z) //非必要,场景有控件时才加上
-      // model.orbitControls.target.set(pointBox.x, pointBox.y , pointBox.z) //非必要,场景有控件时才加上
-      progress += 0.004;
-    } else {
-      // progress = 0
-      model.camera.position.set(30.328, 58.993, 148.315);
-      model.camera.rotation.set(-27.88, 14.35, 7.47);
-      model.camera.lookAt(0, 0, 0);
-      model.startMY = () => {};
-      model.startAnimation = fmAnimation.bind(null);
-    }
-  };
-}
-
-/* 风门动画 */
-
-function render() {
-  if (!model) {
-    return;
-  }
-  if (isLRAnimation && group) {
-    // 左右摇摆动画
-    if (Math.abs(group.rotation.y) >= 0.2) {
-      direction = -direction;
-      group.rotation.y += 0.00002 * 30 * direction;
-    } else {
-      group.rotation.y += 0.00002 * 30 * direction;
-    }
-  }
-
-  // // //自发光
-  // const screen = group.getObjectByName('对象156');
-  // if (screen) {
-  //   model.renderer.clearDepth();
-  //   screen.layers.enable(31);
-  //   !!renderBloomPass && renderBloomPass(group);
-  // }
-
-  // 风门开关动画
-  const frontDelta = frontClock?.getElapsedTime() + 0.5;
-  const backDelta = backClock?.getElapsedTime() + 0.5;
-  if (model.mixers[0]) model.mixers[0]?.update(frontDelta); //前门
-  if (model.mixers[1]) model.mixers[1]?.update(backDelta); // 后门
-}
-
-// 鼠标点击、松开事件
-function mouseEvent(event) {
-  const widthScale = appStore.getWidthScale;
-  const heightScale = appStore.getHeightScale;
-  // debugger;
-  event.stopPropagation();
-  // 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)
-  model.mouse.x =
-    ((-model.canvasContainer.getBoundingClientRect().left * widthScale + event.clientX) / (model.canvasContainer.clientWidth * widthScale)) * 2 - 1;
-  model.mouse.y =
-    -((-model.canvasContainer.getBoundingClientRect().top + event.clientY) / (model.canvasContainer.clientHeight * heightScale)) * 2 + 1;
-  (model.rayCaster as THREE.Raycaster).setFromCamera(model.mouse, model.camera as THREE.Camera);
-  // 计算物体和射线的焦点
-  const FmWall = group.getObjectByName('Fm-wall');
-  const intersects = model.rayCaster?.intersectObjects([...group.children, ...(FmWall?.children || [])], false) as THREE.Intersection[];
-  if (intersects.length > 0) {
-    isLRAnimation = false;
-    if (animationtimer) {
-      clearTimeout(animationtimer);
-      animationtimer = null;
-    }
-    if (model.camera.layers.mask == -1) model.camera.layers.toggle(1);
-    // 判断是否点击到视频
-    intersects.find((intersect) => {
-      const mesh = intersect.object;
-      // deviceDetailCSS3D?.layers.set(1);
-      if (mesh.name === 'player1') {
-        if (new Date().getTime() - playerStartClickTime1 < 400) {
-          // model.orbitControls?.dispatchEvent.call(model.orbitControls, { type: 'end' })
-          // 双击,视频放大
-          if (player1) {
-            player1.requestFullscreen();
-          }
-        }
-        playerStartClickTime1 = new Date().getTime();
-        return true;
-      } else if (mesh.name === 'player2') {
-        if (new Date().getTime() - playerStartClickTime2 < 400) {
-          // model.orbitControls?.dispatchEvent.call(model.orbitControls, { type: 'end' })
-          // 双击,视频放大
-          if (player2) {
-            player2.requestFullscreen();
-          }
-        }
-        playerStartClickTime2 = new Date().getTime();
-        return true;
-      } else if (mesh.name.startsWith('hotPoint')) {
-        if (deviceDetailCSS3D) {
-          // document.getElementById('deviceCard') as HTMLElement;
-          deviceDetailCSS3D.position.set(intersect.point.x, intersect.point.y + 18, intersect.point.z);
-          console.log('[ deviceDetailCSS3D.position ] >', deviceDetailCSS3D.position);
-          // deviceDetailCSS3D?.layers.set(0);
-          model.camera.layers.enableAll();
-          return true;
-        }
-
-        // let position = new THREE.Vector3(mesh.position.x, mesh.position.y, 0.5);
-        // position = position.applyMatrix4(group.matrixWorld);
-        // model.scene.updateMatrixWorld(true);
-        // // let worldPosition = new THREE.Vector3();
-        // // let worldScale = new THREE.Vector3();
-        // // worldPosition = mesh.getWorldPosition(worldPosition);
-        // // worldScale = mesh.getWorldScale(worldScale);
-        // const devicePosition = transScreenCoord(intersect.point, model.camera);
-        // element.style.left = devicePosition.x + 'px';
-        // element.style.top = devicePosition.y + 'px';
-        // console.log('[ point 坐标位置 ] >', devicePosition, mesh.position);
-      } else {
-        // deviceDetailCSS3D?.layers.set(1);
-
-        console.log('[ 点击事件 ] >');
-      }
-
-      return false;
-    });
-  }
-}
+};
 
 // 初始化左右摇摆动画
-function startAnimation() {
-  // 开启动画
-  model.startAnimation = render.bind(null);
-  // 定义鼠标点击事件x
+const startAnimation = () => {
+  // 定义鼠标点击事件
   model.canvasContainer?.addEventListener('mousedown', mouseEvent.bind(null));
   model.canvasContainer?.addEventListener('pointerup', (event) => {
     event.stopPropagation();
-    // 10s后开始摆动
-    if (!animationtimer && !isLRAnimation) {
-      animationtimer = setTimeout(() => {
-        isLRAnimation = true;
-      }, 10000);
+    // 单道、 双道
+    if (fmType === 'fm1') {
+      fm1.mouseUpModel.call(fm1);
+    } else if (fmType === 'fm2') {
+      // fm2.mouseUpModel.call(fm2);
     }
   });
-}
+};
 
-/* 提取风门序列帧,初始化前后门动画 */
-function initAnimation() {
-  const fmGroup = group?.getObjectByName('Fm-door');
-  if (fmGroup) {
-    const tracks = fmGroup.animations[0].tracks;
-    const fontTracks: any[] = [],
-      backTracks: any[] = [];
-    for (let i = 0; i < tracks.length; i++) {
-      const track = tracks[i];
-      if (track.name.startsWith('qianmen')) {
-        fontTracks.push(track);
-      } else if (track.name.startsWith('houmen')) {
-        backTracks.push(track);
-      }
+// 鼠标点击、松开事件
+const mouseEvent = (event) => {
+  mouseDownFn(model, group, event, (intersects) => {
+    if (fmType === 'fm1') {
+      fm1.mousedownModel.call(fm1, intersects);
+    } else if (fmType === 'fm2') {
+      // fm2.mousedownModel.call(fm2, intersects);
     }
-    const frontDoor = new THREE.AnimationClip('frontDoor', 4, fontTracks);
-    const frontMixer = new THREE.AnimationMixer(fmGroup);
-    model.mixers.push(frontMixer);
-    const frontClipAction = frontMixer.clipAction(frontDoor, fmGroup);
-    frontClipAction.clampWhenFinished = true;
-    frontClipAction.loop = THREE.LoopOnce;
-    clipActionArr.frontDoor = frontClipAction;
+  });
+  console.log('摄像头控制信息', model.orbitControls, model.camera);
+};
 
-    const backDoor = new THREE.AnimationClip('backDoor', 4, backTracks);
-    const backMixer = new THREE.AnimationMixer(fmGroup);
-    model.mixers.push(backMixer);
-    const backClipAction = backMixer.clipAction(backDoor, fmGroup);
-    backClipAction.clampWhenFinished = true;
-    backClipAction.loop = THREE.LoopOnce;
-    clipActionArr.backDoor = backClipAction;
+export const addFmText = (selectData) => {
+  if (fmType === 'fm1') {
+    return fm1.addFmText.call(fm1, selectData);
+  } else {
+    // return fm2.addFmText.call(fm2, selectData);
   }
-}
-
-export function deviceDetailCard(position = { x: 0, y: 0, z: 0 }) {
-  const element = document.getElementById('deviceCard') as HTMLElement;
-  deviceDetailCSS3D = new CSS2DObject(element);
-  deviceDetailCSS3D.name = 'deviceCard';
-  deviceDetailCSS3D.position.set(position.x, position.y, position.z);
-  deviceDetailCSS3D?.layers.set(1);
-  // group.add(deviceDetailCSS3D);
-  model.scene.add(deviceDetailCSS3D);
-}
-// 播放动画
-export function play(handlerState, timeScale = 0.01) {
-  debugger;
-  let handler = () => {};
-  switch (handlerState) {
-    case 1: // 打开前门
-      handler = () => {
-        debugger;
-        clipActionArr.frontDoor.paused = true;
-        clipActionArr.frontDoor.reset();
-        clipActionArr.frontDoor.time = 1.2;
-        clipActionArr.frontDoor.timeScale = timeScale;
-        clipActionArr.frontDoor.clampWhenFinished = true;
-        clipActionArr.frontDoor.play();
-        frontClock.start();
-      };
-      break;
-    case 2: // 关闭前门
-      handler = () => {
-        debugger;
-        clipActionArr.frontDoor.paused = true;
-        clipActionArr.frontDoor.reset(); //
-        clipActionArr.frontDoor.time = 4;
-        clipActionArr.frontDoor.timeScale = -timeScale;
-        clipActionArr.frontDoor.clampWhenFinished = true;
-        clipActionArr.frontDoor.play();
-        frontClock.start();
-      };
-      break;
-    case 3: // 打开后门
-      handler = () => {
-        debugger;
-        clipActionArr.backDoor.paused = true;
-        clipActionArr.backDoor.reset();
-        clipActionArr.backDoor.time = 1.2;
-        clipActionArr.backDoor.timeScale = timeScale;
-        clipActionArr.backDoor.clampWhenFinished = true;
-        clipActionArr.backDoor.play();
-        backClock.start();
-      };
-      break;
-    case 4: // 关闭后门
-      handler = () => {
-        debugger;
-        clipActionArr.backDoor.paused = true;
-        clipActionArr.backDoor.reset();
-        clipActionArr.backDoor.time = 4;
-        clipActionArr.backDoor.timeScale = -timeScale;
-        clipActionArr.backDoor.clampWhenFinished = true;
-        clipActionArr.backDoor.play();
-        backClock.start();
-      };
-      break;
-    case 5: // 打开前后门
-      handler = () => {
-        debugger;
-        clipActionArr.backDoor.paused = true;
-        clipActionArr.frontDoor.paused = true;
-
-        clipActionArr.frontDoor.reset();
-        clipActionArr.frontDoor.time = 0;
-        clipActionArr.frontDoor.timeScale = 0.01;
-        clipActionArr.frontDoor.clampWhenFinished = true;
-        clipActionArr.frontDoor.play();
-
-        clipActionArr.backDoor.reset();
-        clipActionArr.backDoor.time = 0;
-        clipActionArr.backDoor.timeScale = 0.01;
-        clipActionArr.backDoor.clampWhenFinished = true;
-        clipActionArr.backDoor.play();
-        frontClock.start();
-        backClock.start();
-      };
-      break;
-    case 6: // 关闭前后门
-      handler = () => {
-        debugger;
-        clipActionArr.backDoor.paused = true;
-        clipActionArr.frontDoor.paused = true;
+};
 
-        clipActionArr.frontDoor.reset();
-        clipActionArr.frontDoor.time = 4;
-        clipActionArr.frontDoor.timeScale = -0.01;
-        clipActionArr.frontDoor.clampWhenFinished = true;
-        clipActionArr.frontDoor.play();
-        clipActionArr.backDoor.reset();
-        clipActionArr.backDoor.time = 4;
-        clipActionArr.backDoor.timeScale = -0.01;
-        clipActionArr.backDoor.clampWhenFinished = true;
-        clipActionArr.backDoor.play();
-        frontClock.start();
-        backClock.start();
-      };
-      break;
-    default:
+export const deviceDetailCard = () => {
+  if (fmType === 'fm1') {
+    return fm1.deviceDetailCard.call(fm1);
+  } else {
+    // return fm2.addFmText.call(fm2);
   }
+};
 
-  handler();
-  // model.clock.start();
-  // const honglvdeng = group.getObjectByName('honglvdeng');
-  // const material = honglvdeng.material;
-  // setTimeout(() => {
-  //   if (handlerState === 2 || handlerState === 4 || handlerState === 6) {
-  //     material.color = new THREE.Color(0x00ff00);
-  //   } else {
-  //     material.color = new THREE.Color(0xff0000);
-  //   }
-  // }, 1000);
-}
+export const play = (rotationParam, flag) => {
+  if (fmType === 'fm1') {
+    return fm1.play.call(fm1, rotationParam, flag);
+  } else {
+    // return fm2.play.call(fm2, rotationParam, flag);
+  }
+};
 
-// 初始化门的开关状态
-export function initOpenState(selectData) {
-  if (!group) return;
-  model.camera.position.set(-1000, 100, 500);
-  group.rotation.y = 0;
-  return new Promise(async (resolve) => {
-    const oldCameraPosition = { x: -1000, y: 100, z: 500 };
-    await animateCamera(oldCameraPosition, oldCameraPosition, { x: 46.257, y: 57.539, z: 94.313 }, { x: -50, y: 0, z: 0 }, model, 0.8);
-    resolve(null);
-    if (!selectData) {
-      return;
+// 切换风门类型
+export const setModelType = (type) => {
+  fmType = type;
+  return new Promise((resolve) => {
+    // 暂停风门1动画
+    fm1.clipActionArr.frontDoor.reset();
+    fm1.clipActionArr.frontDoor.time = 0.5;
+    fm1.clipActionArr.backDoor.reset();
+    fm1.clipActionArr.backDoor.time = 0.5;
+    fm1.clipActionArr.frontDoor.stop();
+    fm1.clipActionArr.backDoor.stop();
+
+    if (fmType === 'fm1') {
+      model.startAnimation = fm1.render.bind(fm1);
+      group = fm1.group;
+      group.rotation.y = 0;
+      if (model.scene.getObjectByName('fm')) {
+        model.scene.remove(fm2.group);
+      }
+      const oldCameraPosition = { x: -1000, y: 100, z: 500 };
+      model.scene.add(fm1.group);
+      setTimeout(async () => {
+        resolve(null);
+        await animateCamera(
+          oldCameraPosition,
+          { x: 0, y: 0, z: 0 },
+          { x: 50.99, y: 69.32, z: 93.61 },
+          { x: -10.04, y: -14.38, z: -31.4 },
+          model,
+          0.8
+        );
+      }, 300);
+    } else if (fmType === 'fm2') {
+      // 显示单道风窗
+      // model.startAnimation = fm2.render.bind(fm2);
+      // group = fm2.group;
+      // if (model.scene.getObjectByName('fm2')) {
+      //   model.scene.remove(fm1.group);
+      // }
+      // const oldCameraPosition = { x: 100, y: 0, z: 500 };
+      // model.scene.add(fm2.group);
+      // setTimeout(async () => {
+      //   resolve(null);
+      //   const position = { x: 0, y: 0, z: 0 };
+      //   await animateCamera(
+      //     oldCameraPosition,
+      //     { x: 0, y: 0, z: 0 },
+      //     { x: 66.257, y: 57.539, z: 94.313 },
+      //     { x: position.x, y: position.y, z: position.z },
+      //     model
+      //   );
+      // }, 300);
     }
-    clipActionArr.frontDoor.reset();
-    clipActionArr.frontDoor.time = 0.5;
-
-    clipActionArr.backDoor.reset();
-    clipActionArr.backDoor.time = 0.5;
-
-    clipActionArr.frontDoor.stop();
-    clipActionArr.backDoor.stop();
-
-    // frontClock.stop();
-    // backClock.stop();
   });
-}
+};
 
-export function mountedThree(playerVal1, playerVal2) {
-  group = new THREE.Object3D();
-  group.name = modelName;
-  return new Promise((resolve) => {
+export const mountedThree = (playerVal1, playerVal2) => {
+  return new Promise(async (resolve) => {
     model = new UseThree('#damper3D', '', '#deviceDetail');
-
     model.setEnvMap('test1');
-    model.renderer.toneMappingExposure = 1;
-    model.scene?.add(group);
-    group?.layers.enableAll();
-    const bb = new Date().getTime();
-
-    model.setGLTFModel(['Fm-door', 'Fm-wire', 'Fm-wall'], group).then(() => {
-      setModalPosition();
-      // 初始化左右摇摆动画;
-      // startAnimation();
-      initAnimation();
-      drawHots();
-
-      // deviceDetailCard();
-      // model.camera.position.set(-1000, 100, 500);
-      addLight(model.scene);
-      startAnimation();
-      model.animate();
-      if (model.camera.layers.mask == -1) model.camera.layers.toggle(1);
-      setTimeout(async () => {
-        player1 = playerVal1;
-        player2 = playerVal2;
-        const videoPlayer1 = document.getElementById('fm-player1')?.getElementsByClassName('vjs-tech')[0];
-        const videoPlayer2 = document.getElementById('fm-player2')?.getElementsByClassName('vjs-tech')[0];
-        if (!videoPlayer1 || !videoPlayer2) {
-          const textArr = [
-            {
-              text: `无信号输入`,
-              font: 'normal 40px Arial',
-              color: '#009900',
-              strokeStyle: '#002200',
-              x: 170,
-              y: 40,
-            },
-          ];
-          getTextCanvas(560, 346, textArr, '').then((canvas: HTMLCanvasElement) => {
-            const textMap = new THREE.CanvasTexture(canvas); // 关键一步
-            const textMaterial = new THREE.MeshBasicMaterial({
-              map: textMap, // 设置纹理贴图
-              transparent: true,
-              side: THREE.DoubleSide, // 这里是双面渲染的意思
-            });
-            textMaterial.blending = THREE.CustomBlending;
-            const monitorPlane = group?.getObjectByName('noPlayer');
-            if (monitorPlane) {
-              monitorPlane.material = textMaterial;
-            } else {
-              const planeGeometry = new THREE.PlaneGeometry(100, 100); // 平面3维几何体PlaneGeometry
-              const planeMesh = new THREE.Mesh(planeGeometry, textMaterial);
-              if (!videoPlayer1) {
-                planeMesh.name = 'noPlayer1';
-                planeMesh.scale.set(0.011, 0.008, 0.011);
-                planeMesh.position.set(-4.23, -0.28, -0.39);
-                group?.add(planeMesh.clone());
-              }
-              if (!videoPlayer2) {
-                planeMesh.name = 'noPlayer2';
-                planeMesh.scale.set(0.012, 0.009, 0.012);
-                planeMesh.position.set(4.33, -0.33, -0.39);
-                group?.add(planeMesh.clone());
-              }
-              textMaterial.dispose();
-              planeGeometry.dispose();
-            }
-          });
-        } else {
-          if (videoPlayer2) {
-            const mesh = renderVideo(group, videoPlayer1, 'player1');
-            mesh?.scale.set(-0.028, 0.0285, 1);
-            mesh?.position.set(4.298, 0.02, -0.4);
-            mesh.rotation.y = -Math.PI;
-            group.add(mesh);
-          }
-          if (videoPlayer1) {
-            const mesh = renderVideo(group, videoPlayer2, 'player2');
-            mesh?.scale.set(-0.028, 0.0285, 1);
-            mesh?.position.set(-4.262, 0.02, -0.4);
-            mesh.rotation.y = -Math.PI;
-            group.add(mesh);
-          }
-        }
-
-        resolve(model);
-      }, 0);
-      console.log('模型加载到渲染完成所用时间--------------->', new Date().getTime() - bb);
-    });
+    model.renderer.toneMappingExposure = 0.9;
+    model.camera.position.set(100, 0, 1000);
+    // 单道、 双道
+    fm1 = new Fm1(model, playerVal1, playerVal2);
+    // fm2 = new singleWindow(model, playerVal1);
+    await fm1.mountedThree();
+    // await singleWindowObj.mountedThree();
+
+    model.animate();
+    resolve(null);
+    addLight();
+    startAnimation();
   });
-}
+};
 
-export function destroy() {
+export const destroy = () => {
   if (model) {
-    if (model.mixers[0]) {
-      model.mixers[0].uncacheClip(clipActionArr.frontDoor.getClip());
-      model.mixers[0].uncacheClip(clipActionArr.backDoor.getClip());
-      model.mixers[0].uncacheAction(clipActionArr.frontDoor, group);
-      model.mixers[0].uncacheAction(clipActionArr.backDoor, group);
-      model.mixers[0].uncacheRoot(group);
-
-      model.mixers[1].uncacheClip(clipActionArr.frontDoor.getClip());
-      model.mixers[1].uncacheClip(clipActionArr.backDoor.getClip());
-      model.mixers[1].uncacheAction(clipActionArr.frontDoor, group);
-      model.mixers[1].uncacheAction(clipActionArr.backDoor, group);
-      model.mixers[1].uncacheRoot(group);
-
-      if (model.animations[0]) model.animations[0].tracks = [];
-    }
-
-    clipActionArr.backDoor = undefined;
-    clipActionArr.frontDoor = undefined;
-
-    model.mixers = [];
+    fm1.destroy();
+    // fm2.destroy();
     model.deleteModal();
     model = null;
     group = null;
-    // document.getElementById('damper3D').parentElement.remove(document.getElementById('damper3D'))
+    fm1 = null;
+    fm2 = null;
   }
 };

+ 9 - 23
src/views/vent/monitorManager/gateMonitor/index.vue

@@ -169,7 +169,7 @@
   import AlarmHistoryTable from '../comment/AlarmHistoryTable.vue';
   import HandlerHistoryTable from '../comment/HandlerHistoryTable.vue';
   import HandleModal from './modal.vue';
-  import { mountedThree, addFmText, play, destroy, initOpenState, deviceDetailCard } from './gate.threejs';
+  import { mountedThree, addFmText, play, destroy, setModelType } from './gate.threejs';
   import { deviceControlApi } from '/@/api/vent/index';
   import { message } from 'ant-design-vue';
   import { list, getTableList } from './gate.api';
@@ -277,23 +277,14 @@
     selectRowIndex.value = index;
     const baseData: any = deviceBaseList.value.find((baseData: any) => baseData.id === selectRow.deviceID);
     Object.assign(selectData, initData, selectRow, baseData);
-    // selectData = selectRow;
-    // frontDoorIsOpen.value = selectData.frontGateOpen === '1';
-    // backDoorIsOpen.value = selectData.rearGateOpen === '1';
-    if (timer) {
-      clearTimeout(timer);
-      timer = undefined;
-    }
-    initOpenState(selectData)?.then(() => {
+    isFrontRunning = false //开关门动作是否在进行
+    isRearRunning = false //开关门动作是否在进行
+    frontDeviceState = 0 //记录设备状态,为了与下一次监测数据做比较
+    rearDeviceState = 0 //记录设备状态,为了与下一次监测数据做比较
+    // const type = selectData.nwindownum == 1 ? 'singleWindow' : 'doubleWindow';
+    setModelType('fm1').then(() => {
+      addFmText(selectData);
       loading.value = false;
-
-      isFrontRunning = false //开关门动作是否在进行
-      isRearRunning = false //开关门动作是否在进行
-      frontDeviceState = 0 //记录设备状态,为了与下一次监测数据做比较
-      rearDeviceState = 0 //记录设备状态,为了与下一次监测数据做比较
-
-      timer = null;
-      getMonitor();
     });
   };
 
@@ -596,13 +587,8 @@
 
   onMounted(() => {
     loading.value = true;
-    
     mountedThree(player1.value, player2.value).then(() => {
-      nextTick(() => {
-        getMonitor(true);
-        addFmText(selectData);
-        deviceDetailCard();
-      });
+      getMonitor(true);
       loading.value = false;
     });
     document.body.addEventListener('mousedown', addPlayVideo, false);

+ 11 - 43
src/views/vent/monitorManager/groutMonitor/grout.threejs.ts

@@ -2,48 +2,29 @@ import * as THREE from 'three';
 import UseThree from '../../../../utils/threejs/useThree';
 import ChamberBase from './grout.threejs.base';
 import { animateCamera } from '/@/utils/threejs/util';
-import { useAppStore } from '/@/store/modules/app';
+import useEvent from '../../../../utils/threejs/useEvent';
 
 // 模型对象、 文字对象
 let model,
   groutBaseObj: ChamberBase,
   group,
   groutType = 'groutBase'; // workerFaceFiber
-const appStore = useAppStore();
+
+const { mouseDownFn } = useEvent();
 
 // 鼠标点击事件
 const mouseEvent = (event) => {
-  event.stopPropagation();
-  if (!model) return;
-  const widthScale = appStore.getWidthScale;
-  const heightScale = appStore.getHeightScale;
-  // 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)
-  model.mouse.x =
-    ((-model.canvasContainer.getBoundingClientRect().left * widthScale + event.clientX) / (model.canvasContainer.clientWidth * widthScale)) * 2 - 1;
-  model.mouse.y =
-    -((-model.canvasContainer.getBoundingClientRect().top + event.clientY) / (model.canvasContainer.clientHeight * heightScale)) * 2 + 1;
-  (model.rayCaster as THREE.Raycaster).setFromCamera(model.mouse, model.camera as THREE.Camera);
-  if (group) {
+  mouseDownFn(model, group, event, (intersects) => {
     if (groutType === 'groutBase') {
       // groutBaseObj.mousedownModel.call(groutBaseObj, model.rayCaster);
     }
-
-    // const intersects = model.rayCaster?.intersectObjects([...group.children]) as THREE.Intersection[];
-    // if (intersects.length > 0) {
-    //   if (fiberType === 'beltFiber') {
-    //     beltFiberObj.mousedownModel.call(beltFiberObj, intersects);
-    //   } else if (fiberType === 'workFace') {
-    //     workerFaceFiberObj.mousedownModel.call(workerFaceFiberObj, intersects);
-    //   }
-    // }
-
-    console.log('摄像头,控制器------>', model.camera, model.orbitControls);
-  }
+  });
+  console.log('摄像头控制信息', model.orbitControls, model.camera);
 };
 
 const addMouseEvent = () => {
   // 定义鼠标点击事件
-  model.canvasContainer?.addEventListener('mousedown', mouseEvent.bind(null));
+  model.canvasContainer?.addEventListener('mousedown', mouseEvent);
 };
 
 const render = () => {
@@ -66,20 +47,11 @@ export const setModelType = (type) => {
   return new Promise((resolve) => {
     if (groutType === 'groutBase') {
       group = groutBaseObj.group;
-      const oldCameraPosition = { x: 24.736, y: 63.486, z: 103.337 };
+      const oldCameraPosition = { x: 100, y: 0, z: 600 };
       model.scene.add(groutBaseObj.group);
-      model.camera.position.set(0, 0, 300);
       setTimeout(async () => {
-        // const position = { x: 0, y: 3.8, z: 10.5 };
-        await animateCamera(
-          oldCameraPosition,
-          oldCameraPosition,
-          { x: -36.224455845316, y: 21.749986776845592, z: -0.10614789855468158 },
-          { x: 0, y: 0, z: 0 },
-          model,
-          0.8
-        );
-      }, 300);
+        await animateCamera(oldCameraPosition, {x: 0, y: 0, z: 0}, { x: -36.224455845316, y: 21.749986776845592, z: -0.10614789855468158 }, { x: 0, y: 0, z: 0 }, model, 0.8);
+      }, 500);
 
       resolve(null);
     }
@@ -91,15 +63,11 @@ export const mountedThree = () => {
     model = new UseThree('#grout3D');
     model.setEnvMap('test1');
     model.renderer.toneMappingExposure = 1;
-    // model.camera.position.set(100, 0, 1000);
-
+    model.camera.position.set(100, 0, 600);
     groutBaseObj = new ChamberBase(model);
     await groutBaseObj.mountedThree();
 
-    // model.scene.add(groutBaseObj.group);
-
     addMouseEvent();
-    // render();
     model.animate();
     resolve(null);
   });

+ 1 - 1
src/views/vent/monitorManager/mainFanMonitor/main.threejs.ts

@@ -302,7 +302,7 @@ export const setModelType = (type) => {
         const oldCameraPosition = { x: -500, y: 100, z: 2000 };
         await animateCamera(
           oldCameraPosition,
-          oldCameraPosition,
+          { x: 0, y: 0, z: 0 },
           { x: 2.36, y: 79.2, z: 115.9 },
           { x: position.x, y: position.y, z: position.z },
           model,

+ 49 - 49
src/views/vent/monitorManager/nitrogen/components/nitrogenHome.vue

@@ -1,55 +1,55 @@
 <template>
-    <div id="nitrogenCss3D" class="threejs-Object-CSS"
-      style="width: 100%; height: 100%; position: absolute; pointer-events: none; overflow: hidden; z-index: 2; top: 0px; left: 0px">
-      <a-spin :spinning="loading" />
-      <div v-for="groupNum in monitorDataGroupNum" :key="groupNum" class="modal-monitor">
-        <fourBorderBg :class="`kyj${groupNum}`" :id="`nitrogenMonitor${groupNum}`">
-          <div class="title">{{ groupNum }}号空压机 </div>
-          <div class="monitor-item">
-            <span class="monitor-title">排气压力:</span>
-            <span class="monitor-val"><span class="val">{{ monitorData[groupNum - 1]['compressExhaustPressF1'] ?
-              monitorData[groupNum - 1]['compressExhaustPressF1'] : '-' }}</span><span class="unit">Mpa</span></span>
-          </div>
-          <div class="monitor-item">
-            <span class="monitor-title">分离压力:</span>
-            <span class="monitor-val"><span class="val">{{ monitorData[groupNum - 1]['compressSeparatePressF1'] ?
-              monitorData[groupNum - 1]['compressSeparatePressF1'] : '-' }}</span><span class="unit">Mpa</span></span>
-          </div>
-          <div class="monitor-item">
-            <span class="monitor-title">排气温度:</span>
-            <span class="monitor-val"><span class="val">{{ monitorData[groupNum - 1]['exhaustTemp'] ? monitorData[groupNum
-              - 1]['exhaustTemp'] : '-' }}</span><span class="unit">℃</span></span>
-          </div>
-          <div class="signal-item">
-            <div class="signal"><span class="monitor-title">运行信号</span><span
-                :class="{ 'signal-round': true, 'signal-round-run': monitorData[groupNum - 1]['compressRunSigF1'], 'signal-round-gry': !monitorData[groupNum - 1]['compressRunSigF1'] }"></span>
+    <div id="compressor3D" style="width: 100%; height: 100%; position: absolute; overflow: hidden"></div>
+    <div id="ncompressorCss3D" class="threejs-Object-CSS"
+        style="width: 100%; height: 100%; position: absolute; pointer-events: none; overflow: hidden; z-index: 2; top: 0px; left: 0px">
+        <a-spin :spinning="loading" />
+        <div v-for="groupNum in monitorDataGroupNum" :key="groupNum" class="modal-monitor">
+          <fourBorderBg :class="`kyj${groupNum}`" :id="`nitrogenMonitor${groupNum}`">
+            <div class="title">{{ groupNum }}号空压机 </div>
+            <div class="monitor-item">
+              <span class="monitor-title">排气压力:</span>
+              <span class="monitor-val"><span class="val">{{ monitorData[groupNum - 1]['compressExhaustPressF1'] ?
+                monitorData[groupNum - 1]['compressExhaustPressF1'] : '-' }}</span><span class="unit">Mpa</span></span>
             </div>
-            <div class="signal"><span class="monitor-title">加载信号</span><span
-                :class="{ 'signal-round': true, 'signal-round-run': monitorData[groupNum - 1]['compressLoadSigF1'], 'signal-round-gry': !monitorData[groupNum - 1]['compressLoadSigF1'] }"></span>
+            <div class="monitor-item">
+              <span class="monitor-title">分离压力:</span>
+              <span class="monitor-val"><span class="val">{{ monitorData[groupNum - 1]['compressSeparatePressF1'] ?
+                monitorData[groupNum - 1]['compressSeparatePressF1'] : '-' }}</span><span class="unit">Mpa</span></span>
             </div>
-          </div>
-        </fourBorderBg>
-        <fourBorderBg :class="`cqg${groupNum}`" :id="`cqgMonitor${groupNum}`">
-          <div class="title">{{ cqgs[groupNum - 1] }}</div>
-          <div class="monitor-item">
-            <span class="monitor-title">气囊温度:</span>
-            <span class="monitor-val"><span class="val">{{ monitorData[groupNum - 1]['airReceiverTemp'] ?
-              monitorData[groupNum - 1]['airReceiverTemp'] : '-' }}</span><span class="unit">℃</span></span>
-          </div>
-          <div class="monitor-item">
-            <span class="monitor-title">气囊压力<span class="unit"></span>:</span>
-            <span class="monitor-val"><span class="val">{{ monitorData[groupNum - 1]['airReceiverPress'] ?
-              monitorData[groupNum - 1]['airReceiverPress'] : '-' }}</span><span class="unit">Mpa</span></span>
-          </div>
-          <div class="monitor-item">
-            <span class="monitor-title">气囊流量<span class="unit"></span>:</span>
-            <span class="monitor-val"><span class="val">{{ monitorData[groupNum - 1]['airReceiverFlow'] ?
-              monitorData[groupNum - 1]['airReceiverFlow'] : '-' }}</span><span class="unit">m³/k</span></span>
-          </div>
-        </fourBorderBg>
+            <div class="monitor-item">
+              <span class="monitor-title">排气温度:</span>
+              <span class="monitor-val"><span class="val">{{ monitorData[groupNum - 1]['exhaustTemp'] ? monitorData[groupNum
+                - 1]['exhaustTemp'] : '-' }}</span><span class="unit">℃</span></span>
+            </div>
+            <div class="signal-item">
+              <div class="signal"><span class="monitor-title">运行信号</span><span
+                  :class="{ 'signal-round': true, 'signal-round-run': monitorData[groupNum - 1]['compressRunSigF1'], 'signal-round-gry': !monitorData[groupNum - 1]['compressRunSigF1'] }"></span>
+              </div>
+              <div class="signal"><span class="monitor-title">加载信号</span><span
+                  :class="{ 'signal-round': true, 'signal-round-run': monitorData[groupNum - 1]['compressLoadSigF1'], 'signal-round-gry': !monitorData[groupNum - 1]['compressLoadSigF1'] }"></span>
+              </div>
+            </div>
+          </fourBorderBg>
+          <fourBorderBg :class="`cqg${groupNum}`" :id="`cqgMonitor${groupNum}`">
+            <div class="title">{{ cqgs[groupNum - 1] }}</div>
+            <div class="monitor-item">
+              <span class="monitor-title">气囊温度:</span>
+              <span class="monitor-val"><span class="val">{{ monitorData[groupNum - 1]['airReceiverTemp'] ?
+                monitorData[groupNum - 1]['airReceiverTemp'] : '-' }}</span><span class="unit">℃</span></span>
+            </div>
+            <div class="monitor-item">
+              <span class="monitor-title">气囊压力<span class="unit"></span>:</span>
+              <span class="monitor-val"><span class="val">{{ monitorData[groupNum - 1]['airReceiverPress'] ?
+                monitorData[groupNum - 1]['airReceiverPress'] : '-' }}</span><span class="unit">Mpa</span></span>
+            </div>
+            <div class="monitor-item">
+              <span class="monitor-title">气囊流量<span class="unit"></span>:</span>
+              <span class="monitor-val"><span class="val">{{ monitorData[groupNum - 1]['airReceiverFlow'] ?
+                monitorData[groupNum - 1]['airReceiverFlow'] : '-' }}</span><span class="unit">m³/k</span></span>
+            </div>
+          </fourBorderBg>
+        </div>
       </div>
-    </div>
-    <div id="nitrogen3D" style="width: 100%; height: 100%; position: absolute; overflow: hidden"></div>
     <div class="nitrogen-home">
       <div class="nitrogen-container">
         <div class="top-box">
@@ -434,8 +434,8 @@ onUnmounted(() => {
         display: flex;
         flex-direction: column;
         position: relative;
-
         z-index: 9999;
+        pointer-events: auto;
       }
 
       .item {

+ 38 - 34
src/views/vent/monitorManager/nitrogen/nitrogen.dishang.threejs.ts

@@ -1,5 +1,5 @@
 import * as THREE from 'three';
-import { getTextCanvas, addEnvMap, setModalCenter } from '/@/utils/threejs/util';
+import { setModalCenter } from '/@/utils/threejs/util';
 import { CSS3DSprite } from 'three/examples/jsm/renderers/CSS3DRenderer.js';
 // import * as dat from 'dat.gui';
 // const gui = new dat.GUI();
@@ -65,22 +65,20 @@ class Nitrogen {
 
   // 设置模型位置
   setModalPosition() {
-    if (this.nitrogenNum == 4) {
-      this.group.position.set(0, -17, 3);
-      this.group?.scale.set(24.0, 24.0, 24.0);
-    }
-    if (this.nitrogenNum == 3) {
-      this.group.position.set(0, -12, 3);
-      this.group?.scale.set(24.0, 24.0, 24.0);
-    }
-    if (this.nitrogenNum == 2) {
-      this.group.position.set(0, 0.42, 1.21);
-      this.group?.scale.set(24.0, 24.0, 24.0);
-    }
-    if (this.nitrogenNum == 1) {
-      this.group.position.set(0, 8, 3.0);
-      this.group?.scale.set(24.0, 24.0, 24.0);
-    }
+    this.group.position.set(0, 0, 0);
+    this.group?.scale.set(24.0, 24.0, 24.0);
+    // if (this.nitrogenNum == 4) {
+    //   this.group.position.set(0, -17, 3);
+    // }
+    // if (this.nitrogenNum == 3) {
+    //   this.group.position.set(0, -12, 3);
+    // }
+    // if (this.nitrogenNum == 2) {
+    //   this.group.position.set(0, 0.42, 1.21);
+    // }
+    // if (this.nitrogenNum == 1) {
+    //   this.group.position.set(0, 8, 3.0);
+    // }
   }
 
   /* 提取风门序列帧,初始化前后门动画 */
@@ -130,23 +128,23 @@ class Nitrogen {
   addCssText = () => {
     if (this.nitrogenNum > 0) {
       for (let i = 0; i < this.nitrogenNum; i++) {
-        const nitrogenModal = this.group.getObjectByName('nitrogenModal' + i) as THREE.Object3D;
-        if (!nitrogenModal.getObjectByName('monitorNitrogenText')) {
-          const element = document.getElementById('nitrogenMonitor' + (i + 1)) as HTMLElement;
+        const compressorModal = this.group.getObjectByName('compressorModal' + i) as THREE.Object3D;
+        if (!compressorModal.getObjectByName('monitorNitrogenText')) {
+          const element = document.getElementById('compressorMonitor' + (i + 1)) as HTMLElement;
           if (element) {
             element.style.top = '0px';
             element.style.left = '0px';
-            const nitrogenMonitorCSS3D = new CSS3DSprite(element);
-            nitrogenMonitorCSS3D.name = 'monitorNitrogenText';
-            nitrogenMonitorCSS3D.scale.set(0.003, 0.003, 0.003);
-            if (i == 0) nitrogenMonitorCSS3D.position.set(-0.89, 0.31, 0);
-            if (i == 1) nitrogenMonitorCSS3D.position.set(-0.89, 0.31, 0.04);
-            if (i == 2) nitrogenMonitorCSS3D.position.set(-0.89, 0.31, 0.08);
-            if (i == 3) nitrogenMonitorCSS3D.position.set(-0.89, 0.31, 0.12);
-            nitrogenModal.add(nitrogenMonitorCSS3D);
+            const compressorMonitorCSS3D = new CSS3DSprite(element);
+            compressorMonitorCSS3D.name = 'monitorNitrogenText';
+            compressorMonitorCSS3D.scale.set(0.003, 0.003, 0.003);
+            if (i == 0) compressorMonitorCSS3D.position.set(-0.89, 0.31, 0);
+            if (i == 1) compressorMonitorCSS3D.position.set(-0.89, 0.31, 0.04);
+            if (i == 2) compressorMonitorCSS3D.position.set(-0.89, 0.31, 0.08);
+            if (i == 3) compressorMonitorCSS3D.position.set(-0.89, 0.31, 0.12);
+            compressorModal.add(compressorMonitorCSS3D);
           }
         }
-        if (!nitrogenModal.getObjectByName('cqgMonitorText')) {
+        if (!compressorModal.getObjectByName('cqgMonitorText')) {
           const element = document.getElementById('cqgMonitor' + (i + 1)) as HTMLElement;
           if (element) {
             element.style.top = '0px';
@@ -158,7 +156,7 @@ class Nitrogen {
             if (i == 1) cqgMonitorCSS3D.position.set(1.24, 0.49, 0.04);
             if (i == 2) cqgMonitorCSS3D.position.set(1.24, 0.49, 0.08);
             if (i == 3) cqgMonitorCSS3D.position.set(1.24, 0.49, 0.12);
-            nitrogenModal.add(cqgMonitorCSS3D);
+            compressorModal.add(cqgMonitorCSS3D);
           }
         }
       }
@@ -212,11 +210,17 @@ class Nitrogen {
       }
       this.model.setGLTFModel([this.modelName]).then(async (gltf) => {
         const nitrogenGroup = new THREE.Object3D();
+        const flag = nitrogenNum % 2 == 0 ? 0 : 1;
         for (let i = 0; i < nitrogenNum; i++) {
-          const nitrogenModal = gltf[0].clone();
-          nitrogenModal.name = 'nitrogenModal' + i;
-          nitrogenModal.position.set(0, 0, -1.29 * i);
-          nitrogenGroup.add(nitrogenModal);
+          const compressorModal = gltf[0].clone();
+          compressorModal.name = 'compressorModal' + i;
+          const c = Math.floor(nitrogenNum / 2);
+          if (flag) {
+            compressorModal.position.set(0, 0, 1.29 * (c - i));
+          } else {
+            compressorModal.position.set(0, 0, (c - i - 0.5) * 1.29);
+          }
+          nitrogenGroup.add(compressorModal);
         }
 
         this.group = nitrogenGroup;

+ 85 - 56
src/views/vent/monitorManager/nitrogen/nitrogen.threejs.ts

@@ -1,108 +1,137 @@
 import * as THREE from 'three';
 import { animateCamera, setModalCenter, updateAxisCenter } from '/@/utils/threejs/util';
 import UseThree from '../../../../utils/threejs/useThree';
+import useEvent from '../../../../utils/threejs/useEvent';
 import Nitrogen from './nitrogen.dishang.threejs';
-import { useAppStore } from '/@/store/modules/app';
+
 // import * as dat from 'dat.gui';
 // const gui = new dat.GUI();
 // gui.domElement.style = 'position:absolute;top:100px;left:10px;z-index:99999999999999';
 
 // 模型对象、 文字对象
-let model, //
-  group,
-  nitrogenObj,
-  modalType = 'lmWindRect';
+let model: UseThree,
+  group: THREE.Object3D,
+  compressorObj,
+  modalType = 'compressor';
 
-const appStore = useAppStore();
+const { mouseDownFn, mousemoveFn, mouseUpFn } = useEvent();
 
 // 鼠标点击、松开事件
 const mouseEvent = (event) => {
-  event.stopPropagation();
-  const widthScale = appStore.getWidthScale;
-  const heightScale = appStore.getHeightScale;
-  // 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)
-  model.mouse.x =
-    ((-model.canvasContainer.getBoundingClientRect().left * widthScale + event.clientX) / (model.canvasContainer.clientWidth * widthScale)) * 2 - 1;
-  model.mouse.y =
-    -((-model.canvasContainer.getBoundingClientRect().top + event.clientY) / (model.canvasContainer.clientHeight * heightScale)) * 2 + 1;
-  (model.rayCaster as THREE.Raycaster).setFromCamera(model.mouse, model.camera as THREE.Camera);
-
-  // console.log('相机与控制器信息--->', model.camera, model.orbitControls);
-  // updateAxisCenter(model, event);
-
-  if (group) {
-    const intersects = model.rayCaster?.intersectObjects(group.children, false) as THREE.Intersection[];
-    if (intersects.length > 0) {
-      // 单道、 双道
-      if (modalType === 'nitrogen') {
-        nitrogenObj.mousedownModel.call(nitrogenObj, intersects);
-      }
+  // 单道、 双道
+  model.canvasContainer?.addEventListener('mousemove', mousemove);
+  mouseDownFn(model, group, event, (intersects) => {
+    if (modalType === 'compressor') {
+      compressorObj.mousedownModel.call(compressorObj, intersects);
+    }
+  });
+};
+
+const mouseUp = () => {
+  if (!model) return;
+  mouseUpFn(model);
+  model.canvasContainer?.removeEventListener('mousemove', mousemove);
+};
+
+const mousemove = () => {
+  mousemoveFn();
+};
+
+const render = () => {
+  if (model.animationId != -1) {
+    model.animationId = requestAnimationFrame(render.bind(this));
+    // model.camera?.lookAt(group.position);
+
+    // if (cameraLookAtPoint) {
+    //   const point = cameraLookAtPoint.clone().applyMatrix4(group.matrixWorld);
+    //   const point1 = point.project(model.camera as THREE.Camera);
+    //   // model.orbitControls.target = point1;
+    // }
+
+    // model.camera?.lookAt(point1);
+    model.stats?.update();
+    // this.renderAnimationScene();
+    if (model.renderEnabled) {
+      model.render();
     }
-    console.log('99999------>', model.camera, model.orbitControls);
   }
 };
 
 /* 添加监控数据 */
 export const addText = (selectData) => {
-  if (modalType === 'nitrogen') {
-    return nitrogenObj.addText.call(nitrogenObj, selectData);
+  if (modalType === 'compressor') {
+    return compressorObj.addText.call(compressorObj, selectData);
   }
 };
 
 export const play = () => {
-  if (modalType === 'nitrogen') {
-    return nitrogenObj.play.call(nitrogenObj);
+  if (modalType === 'compressor') {
+    return compressorObj.play.call(compressorObj);
   }
 };
 
 // 切换风窗类型
 export const setModelType = (type) => {
   modalType = type;
-  model.camera.position.set(-1000, 100, 500);
+  model?.camera?.position.set(-1000, 100, 500);
 
   return new Promise((resolve) => {
     // 显示双道风窗
-    if (modalType === 'nitrogen') {
-      group = nitrogenObj.group;
-      // setModalCenter(group);
+    if (modalType === 'compressor') {
+      group = compressorObj.group;
+
       const oldCameraPosition = { x: -1000, y: 100, z: 500 };
       const oldControlsPosition = { x: 0, y: 0, z: 0 };
-      model.scene.add(nitrogenObj.group);
+      model?.scene?.add(compressorObj.group);
+
+      let newCameraPosition = { x: 0, y: 0, z: 0 },
+        newControlsPosition = { x: 0, y: 0, z: 0 };
+      if (group.children.length == 6) {
+        newCameraPosition = { x: -1.7434040517387115, y: 46.41089142470955, z: 114.33388865672832 };
+        newControlsPosition = { x: -1.6994314417499141, y: -12.38981035037152, z: 10.110013648346193 };
+      } else if (group.children.length == 5) {
+        newCameraPosition = { x: -1.2741159124866441, y: 46.04318455197148, z: 95.25814325750986 };
+        newControlsPosition = { x: -1.699431, y: -12.38981, z: -1.699431 };
+      } else if (group.children.length == 4) {
+        newCameraPosition = { x: -1.2741159124866441, y: 46.04318455197148, z: 85.25814325750986 };
+        newControlsPosition = { x: -1.699431, y: -12.38981, z: -1.699431 };
+      } else if (group.children.length == 3) {
+        newCameraPosition = { x: -1.2741159124866441, y: 46.04318455197148, z: 70.25814325750986 };
+        newControlsPosition = { x: -1.699431, y: -12.38981, z: -1.699431 };
+      }
+
       setTimeout(async () => {
         resolve(null);
-        await animateCamera(
-          oldCameraPosition,
-          oldControlsPosition,
-          // { x: -0.24658823766780538, y: 35.50352092191473, z: 83.90511756512278 },
-          // { x: -0.24658823766780538, y: 35.50352092191473, z: 83.90511756512278 },
-          // { x: 1.5582599568763913, y: -3.2828007511721147, z: 2.2606374587827234 },
-          { x: -0.03221356849453339, y: 60.58380705766696, z: 66.35361856273981 },
-          { x: 0, y: 0, z: 0 },
-          model,
-          0.8
-        );
+        await animateCamera(oldCameraPosition, oldControlsPosition, newCameraPosition, newControlsPosition, model, 0.8);
       }, 300);
     }
   });
 };
 
-export const mountedThree = (nitrogenNum) => {
+export const mountedThree = (compressorNum) => {
   return new Promise(async (resolve) => {
-    model = new UseThree('#nitrogen3D', '#nitrogenCss3D');
+    model = new UseThree('#compressor3D', '#compressorCss3D');
     model.setEnvMap('test1');
-    model.renderer.toneMappingExposure = 1;
-    model.canvasContainer?.addEventListener('mousedown', mouseEvent.bind(null));
-    nitrogenObj = new Nitrogen(model);
-    await nitrogenObj.mountedThree(nitrogenNum);
-    setModelType('nitrogen');
+    if (model.renderer) model.renderer.toneMappingExposure = 1;
+    model.canvasContainer?.addEventListener('mousedown', mouseEvent);
+    model.canvasContainer?.addEventListener('pointerup', mouseUp);
+    compressorObj = new Nitrogen(model);
+    await compressorObj.mountedThree(compressorNum);
+    setModelType('compressor');
     resolve(null);
-    model.animate();
+
+    // 添加摄像机辅助
+
+    const helper = new THREE.CameraHelper(model.camera as THREE.Camera);
+    model?.scene?.add(helper);
+
+    render();
   });
 };
 
 export const destroy = () => {
   if (model) {
-    nitrogenObj?.destroy();
+    compressorObj?.destroy();
     model.deleteModal();
     model = null;
     group = null;

+ 4 - 4
src/views/vent/monitorManager/tunFaceMonitor/tunFace.threejs.ts

@@ -61,7 +61,7 @@ const render = () => {
 export const refreshModal = () => {
   if (fiberType === 'tunFace') {
     // workFaceObj.render();
-    render()
+    render();
   }
 };
 
@@ -73,7 +73,7 @@ export const setModelType = (type) => {
       group = workFaceObj.group;
 
       // const oldCameraPosition = { x: 124.736, y: 63.486, z: 103.337 };
-      const oldCameraPosition = { x: 124.736, y: 63.486, z: 203.337 };
+      const oldCameraPosition = { x: 124.736, y: 63.486, z: 603.337 };
       if (!model.scene.getObjectByName('tunFace')) {
         model.scene.add(workFaceObj.group);
       }
@@ -81,10 +81,10 @@ export const setModelType = (type) => {
 
       setTimeout(async () => {
         resolve(null);
-        const position = { x: 0, y: 39, z: 43 };
+        const position = { x: 14.826074594663222, y: 16.901762713393836, z: 36.459944037951004 };
         await animateCamera(
           oldCameraPosition,
-          oldCameraPosition,
+          { x: 0, y: 0, z: 0 },
           { x: position.x, y: position.y, z: position.z },
           { x: 0, y: 0, z: 0 },
           model,

+ 11 - 39
src/views/vent/monitorManager/windowMonitor/window.threejs.ts

@@ -3,7 +3,7 @@ import UseThree from '../../../../utils/threejs/useThree';
 import singleWindow from './dandaoFc.threejs';
 import doubleWindow from './shuangdaoFc.threejs';
 import { animateCamera } from '/@/utils/threejs/util';
-import { useAppStore } from '/@/store/modules/app';
+import useEvent from '../../../../utils/threejs/useEvent';
 
 // 模型对象、 文字对象
 let model,
@@ -11,7 +11,8 @@ let model,
   doubleWindowObj,
   group,
   windowType = 'singleWindow';
-const appStore = useAppStore();
+
+const { mouseDownFn } = useEvent();
 // 打灯光
 const addLight = () => {
   const pointLight2 = new THREE.PointLight(0xffeeee, 1, 83);
@@ -78,26 +79,13 @@ const startAnimation = () => {
 
 // 鼠标点击、松开事件
 const mouseEvent = (event) => {
-  event.stopPropagation();
-  const widthScale = appStore.getWidthScale;
-  const heightScale = appStore.getHeightScale;
-  // 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)
-  model.mouse.x =
-    ((-model.canvasContainer.getBoundingClientRect().left * widthScale + event.clientX) / (model.canvasContainer.clientWidth * widthScale)) * 2 - 1;
-  model.mouse.y =
-    -((-model.canvasContainer.getBoundingClientRect().top + event.clientY) / (model.canvasContainer.clientHeight * heightScale)) * 2 + 1;
-  (model.rayCaster as THREE.Raycaster).setFromCamera(model.mouse, model.camera as THREE.Camera);
-  if (group) {
-    const intersects = model.rayCaster?.intersectObjects([...group.children]) as THREE.Intersection[];
-    if (intersects.length > 0) {
-      // 单道、 双道
-      if (windowType === 'doubleWindow') {
-        doubleWindowObj.mousedownModel.call(doubleWindowObj, intersects);
-      } else if (windowType === 'singleWindow') {
-        singleWindowObj.mousedownModel.call(singleWindowObj, intersects);
-      }
+  mouseDownFn(model, group, event, (intersects) => {
+    if (windowType === 'doubleWindow') {
+      doubleWindowObj.mousedownModel.call(doubleWindowObj, intersects);
+    } else if (windowType === 'singleWindow') {
+      singleWindowObj.mousedownModel.call(singleWindowObj, intersects);
     }
-  }
+  });
 };
 
 export const addFmText = (selectData) => {
@@ -131,15 +119,7 @@ export const setModelType = (type) => {
       model.scene.add(doubleWindowObj.group);
       setTimeout(async () => {
         resolve(null);
-
-        const position = doubleWindowObj.group;
-        await animateCamera(
-          oldCameraPosition,
-          oldCameraPosition,
-          { x: 66.257, y: 57.539, z: 94.313 },
-          { x: position.x, y: position.y, z: position.z },
-          model
-        );
+        await animateCamera(oldCameraPosition, { x: 0, y: 0, z: 0 }, { x: 66.257, y: 57.539, z: 94.313 }, { x: 0, y: 0, z: 0 }, model);
       }, 300);
     } else if (windowType === 'singleWindow') {
       // 显示单道风窗
@@ -152,15 +132,7 @@ export const setModelType = (type) => {
       model.scene.add(singleWindowObj.group);
       setTimeout(async () => {
         resolve(null);
-        const position = { x: 0, y: 0, z: 0 };
-
-        await animateCamera(
-          oldCameraPosition,
-          { x: 0, y: 0, z: 0 },
-          { x: 66.257, y: 57.539, z: 94.313 },
-          { x: position.x, y: position.y, z: position.z },
-          model
-        );
+        await animateCamera(oldCameraPosition, { x: 0, y: 0, z: 0 }, { x: 66.257, y: 57.539, z: 94.313 }, { x: 0, y: 0, z: 0 }, model);
       }, 300);
     }
   });

+ 215 - 0
src/views/vent/monitorManager/windrectMonitor/dantou.threejs.ts

@@ -0,0 +1,215 @@
+import * as THREE from 'three';
+
+import { getTextCanvas, renderVideo } from '/@/utils/threejs/util';
+import gsap from 'gsap';
+// import * as dat from 'dat.gui';
+// const gui = new dat.GUI();
+// gui.domElement.style = 'position:absolute;top:100px;left:10px;z-index:99999999999999';
+
+class ddWindRect {
+  model;
+  modelName = 'ddcf';
+  group: THREE.Object3D = new THREE.Object3D();
+  animationTimer;
+  isLRAnimation = true;
+  direction = 1;
+
+  constructor(model) {
+    this.model = model;
+    this.group.name = this.modelName;
+  }
+
+  addLight() {
+    const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
+    directionalLight.position.set(42.4, 248, 86);
+    this.group.add(directionalLight);
+    directionalLight.target = this.group;
+
+    // gui.add(directionalLight.position, 'x', -500, 500);
+    // gui.add(directionalLight.position, 'y', -500, 500);
+    // gui.add(directionalLight.position, 'z', -500, 500);
+
+    const spotLight = new THREE.SpotLight();
+    spotLight.angle = Math.PI / 16;
+    spotLight.penumbra = 0;
+    spotLight.castShadow = true;
+    spotLight.distance = 0;
+    spotLight.position.set(-470, -500, 500);
+    this.group.add(spotLight);
+
+    spotLight.shadow.camera.near = 0.5; // default
+    spotLight.shadow.camera.far = 1000; // default
+    spotLight.shadow.focus = 1;
+    spotLight.shadow.bias = -0.000002;
+
+    // gui.add(spotLight.position, 'x', -500, 500);
+    // gui.add(spotLight.position, 'y', -500, 500);
+    // gui.add(spotLight.position, 'z', -500, 500);
+    // gui.add(spotLight, 'distance', 0, 1000);
+  }
+
+  // 设置模型位置
+  setModalPosition() {
+    this.group?.scale.set(22, 22, 22);
+    this.group?.position.set(-10, 25, 20);
+  }
+
+  addFmText(selectData) {
+    if (!this.group) {
+      return;
+    }
+    const textArr = [
+      {
+        text: `单点式测风装置`,
+        font: 'normal 32px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 140,
+        y: 75,
+      },
+      {
+        text: `风量(m3/min):`,
+        font: 'normal 29px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 12,
+        y: 133,
+      },
+      {
+        text: `${selectData.m3 ? selectData.m3 : '-'}`,
+        font: 'normal 29px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 311,
+        y: 133,
+      },
+      {
+        text: `风速(m/s): `,
+        font: 'normal 29px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 12,
+        y: 192,
+      },
+      {
+        text: `${selectData.va ? selectData.va : '-'}`,
+        font: 'normal 29px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 310,
+        y: 192,
+      },
+      {
+        text: `断面积(㎡):`,
+        font: 'normal 29px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 12,
+        y: 247,
+      },
+      {
+        text: `${selectData.fsectarea ? selectData.fsectarea : '-'}`,
+        font: 'normal 29px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 310,
+        y: 247,
+      },
+      {
+        text: `煤炭科学技术研究院有限公司研制`,
+        font: 'normal 28px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 50,
+        y: 302,
+      },
+    ];
+
+    getTextCanvas(560, 346, textArr, '').then((canvas: HTMLCanvasElement) => {
+      const textMap = new THREE.CanvasTexture(canvas); // 关键一步
+      const textMaterial = new THREE.MeshBasicMaterial({
+        map: textMap, // 设置纹理贴图
+        transparent: true,
+        side: THREE.DoubleSide, // 这里是双面渲染的意思
+      });
+      textMaterial.blending = THREE.CustomBlending;
+      const monitorPlane = this.group?.getObjectByName('monitorText');
+      if (monitorPlane) {
+        monitorPlane.material = textMaterial;
+      } else {
+        const planeGeometry = new THREE.PlaneGeometry(5.6, 3.46); // 平面3维几何体PlaneGeometry
+        const planeMesh = new THREE.Mesh(planeGeometry, textMaterial);
+        planeMesh.name = 'monitorText';
+        planeMesh.scale.set(0.26, 0.26, 0.26);
+        planeMesh.position.set(-2.52, 0.038, -0.42);
+        this.group?.add(planeMesh);
+      }
+    });
+  }
+
+  /* 风门动画 */
+  render() {
+    if (!this.model) {
+      return;
+    }
+    if (this.isLRAnimation && this.group) {
+      // 左右摇摆动画
+      if (Math.abs(this.group.rotation.y) >= 0.2) {
+        this.direction = -this.direction;
+        this.group.rotation.y += 0.00002 * 30 * this.direction;
+      } else {
+        this.group.rotation.y += 0.00002 * 30 * this.direction;
+      }
+    }
+  }
+
+  /* 点击风窗,风窗全屏 */
+  mousedownModel(intersects: THREE.Intersection<THREE.Object3D<THREE.Event>>[]) {
+    this.isLRAnimation = false;
+    if (this.animationTimer) {
+      clearTimeout(this.animationTimer);
+      this.animationTimer = null;
+    }
+    // 判断是否点击到视频
+    intersects.find((intersect) => {
+      intersect;
+      return false;
+    });
+  }
+
+  mouseUpModel() {
+    // 10s后开始摆动
+    if (!this.animationTimer && !this.isLRAnimation) {
+      this.animationTimer = setTimeout(() => {
+        this.isLRAnimation = true;
+      }, 10000);
+    }
+  }
+
+  resetModel() {
+    clearTimeout(this.animationTimer);
+    this.isLRAnimation = false;
+  }
+
+  mountedThree() {
+    return new Promise((resolve) => {
+      this.model.setGLTFModel([this.modelName]).then((gltf) => {
+        this.group.name = this.modelName;
+        this.group = gltf[0];
+        this.setModalPosition();
+        this.addLight();
+      });
+    });
+  }
+
+  destroy() {
+    if (this.group) {
+      this.model.clearGroup(this.group);
+    }
+
+    this.model = null;
+    this.group = null;
+  }
+}
+
+export default ddWindRect;

+ 19 - 39
src/views/vent/monitorManager/windrectMonitor/windrect.threejs.ts

@@ -5,7 +5,7 @@ import lmWindRect from './longmen.threejs';
 import zdWindRect from './zhedie.threejs';
 import dsWindRect from './duishe.threejs';
 import lmWindRectSide from './longmenSide.threejs';
-import { useAppStore } from '/@/store/modules/app';
+import useEvent from '../../../../utils/threejs/useEvent';
 import gsap from 'gsap';
 // import * as dat from 'dat.gui';
 // const gui = new dat.GUI();
@@ -20,7 +20,7 @@ let model, //
   lmWindRectSideObj,
   windRectType = 'lmWindRect';
 
-const appStore = useAppStore();
+const { mouseDownFn } = useEvent();
 
 // 初始化左右摇摆动画
 const startAnimation = () => {
@@ -43,30 +43,18 @@ const startAnimation = () => {
 
 // 鼠标点击、松开事件
 const mouseEvent = (event) => {
-  event.stopPropagation();
-  const widthScale = appStore.getWidthScale;
-  const heightScale = appStore.getHeightScale;
-  // 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)
-  model.mouse.x =
-    ((-model.canvasContainer.getBoundingClientRect().left * widthScale + event.clientX) / (model.canvasContainer.clientWidth * widthScale)) * 2 - 1;
-  model.mouse.y =
-    -((-model.canvasContainer.getBoundingClientRect().top + event.clientY) / (model.canvasContainer.clientHeight * heightScale)) * 2 + 1;
-  (model.rayCaster as THREE.Raycaster).setFromCamera(model.mouse, model.camera as THREE.Camera);
-  if (group) {
-    const intersects = model.rayCaster?.intersectObjects(group.children, true) as THREE.Intersection[];
-    if (intersects.length > 0) {
-      // 单道、 双道
-      if (windRectType === 'lmWindRect') {
-        lmWindRectObj.mousedownModel.call(lmWindRectObj, intersects);
-      } else if (windRectType === 'zdWindRect') {
-        zdWindRectObj.mousedownModel.call(zdWindRectObj, intersects);
-      } else if (windRectType.startsWith('dsWindRect')) {
-        dsWindRectObj.mousedownModel.call(dsWindRectObj, intersects);
-      } else if (windRectType === 'lmWindSide') {
-        lmWindRectSideObj.mousedownModel.call(lmWindRectSideObj, intersects);
-      }
+  mouseDownFn(model, group, event, (intersects) => {
+    if (windRectType === 'lmWindRect') {
+      lmWindRectObj.mousedownModel.call(lmWindRectObj, intersects);
+    } else if (windRectType === 'zdWindRect') {
+      zdWindRectObj.mousedownModel.call(zdWindRectObj, intersects);
+    } else if (windRectType.startsWith('dsWindRect')) {
+      dsWindRectObj.mousedownModel.call(dsWindRectObj, intersects);
+    } else if (windRectType === 'lmWindSide') {
+      lmWindRectSideObj.mousedownModel.call(lmWindRectSideObj, intersects);
     }
-  }
+  });
+  console.log('摄像头控制信息', model.orbitControls, model.camera);
 };
 
 /* 添加监控数据 */
@@ -138,11 +126,11 @@ export const setModelType = (type) => {
       model.scene.add(lmWindRectObj.group);
       setTimeout(async () => {
         resolve(null);
-        const position = lmWindRectObj.group.position;
+        const position = { x: 0, y: 0, z: 0 };
 
         await animateCamera(
           oldCameraPosition,
-          oldCameraPosition,
+          { x: 0, y: 0, z: 0 },
           { x: 46.257, y: 57.539, z: 94.313 },
           { x: position.x, y: position.y, z: position.z },
           model,
@@ -167,10 +155,10 @@ export const setModelType = (type) => {
       const oldCameraPosition = { x: -1000, y: 100, z: 500 };
       setTimeout(async () => {
         resolve(null);
-        const position = zdWindRectObj.group.position;
+        const position = { x: 0, y: 0, z: 0 };
         await animateCamera(
           oldCameraPosition,
-          oldCameraPosition,
+          { x: 0, y: 0, z: 0 },
           { x: 66.257, y: 57.539, z: 104.313 },
           { x: position.x, y: position.y, z: position.z },
           model,
@@ -200,16 +188,8 @@ export const setModelType = (type) => {
       model.scene.add(dsWindRectObj.group);
       setTimeout(async () => {
         resolve(null);
-        const position = dsWindRectObj.group.position;
         const oldCameraPosition = { x: -1020, y: 100, z: 500 };
-        await animateCamera(
-          oldCameraPosition,
-          oldCameraPosition,
-          { x: 46.257, y: 57.539, z: 104.313 },
-          { x: position.x, y: position.y, z: position.z },
-          model,
-          0.8
-        );
+        await animateCamera(oldCameraPosition, { x: 0, y: 0, z: 0 }, { x: 46.257, y: 57.539, z: 104.313 }, { x: 1.84, y: 0.98, z: -1.44 }, model, 0.8);
       }, 300);
     } else if (windRectType === 'lmWindSide') {
       model.startAnimation = lmWindRectSideObj.render.bind(lmWindRectSideObj);
@@ -234,7 +214,7 @@ export const setModelType = (type) => {
         // const position = new THREE.Vector3(0, 0, 0)
         await animateCamera(
           oldCameraPosition,
-          oldCameraPosition,
+          { x: 0, y: 0, z: 0 },
           { x: 46.257, y: 57.539, z: 94.313 },
           // { x: 1, y: 2, z: 4 },
           { x: position.x, y: position.y, z: position.z },

+ 1 - 1
src/views/vent/monitorManager/workFaceMonitor/wokeFace.threejs.ts

@@ -91,7 +91,7 @@ export const setModelType = (type) => {
         resolve(null);
         await animateCamera(
           oldCameraPosition,
-          oldCameraPosition,
+          { x: 0, y: 0, z: 0 },
           { x: position.x, y: position.y, z: position.z },
           { x: 0.0562941204325611, y: -0.10220461054955868, z: 0.08680791118329842 },
           model,