hongrunxia hai 1 ano
pai
achega
31447f7a48
Modificáronse 47 ficheiros con 1811 adicións e 378 borrados
  1. BIN=BIN
      public/model/glft/cf/dscf.glb
  2. BIN=BIN
      public/model/glft/yafeng/nitrogen.glb
  3. BIN=BIN
      public/model/hdr/royal_esplanade_1k.hdr
  4. 0 1
      src/components/chart/BarAndLine.vue
  5. 1 1
      src/design/vent/index.less
  6. 4 2
      src/design/vent/modal.less
  7. 2 2
      src/enums/pageEnum.ts
  8. 16 14
      src/layouts/default/content/index.vue
  9. 3 2
      src/layouts/default/header/components/user-dropdown/index.vue
  10. 3 0
      src/layouts/default/header/index.less
  11. 6 1
      src/layouts/default/header/index.vue
  12. 2 1
      src/layouts/default/index.vue
  13. 2 0
      src/utils/threejs/main.worker.ts
  14. 0 1
      src/utils/threejs/useThree.ts
  15. 44 3
      src/utils/threejs/util.ts
  16. 2 1
      src/views/dashboard/Analysis/homePage/network.vue
  17. 1 2
      src/views/dashboard/Analysis/homePage/workerFace.vue
  18. 2 1
      src/views/dashboard/Analysis/index.vue
  19. 31 5
      src/views/demo/threejs/damper.vue
  20. 3 0
      src/views/system/dict/dict.api.ts
  21. 1 1
      src/views/vent/monitorManager/comment/DeviceEcharts.vue
  22. 6 2
      src/views/vent/monitorManager/comment/HistoryTable.vue
  23. 68 13
      src/views/vent/monitorManager/fanLocalMonitor/fanLocal.three.ts
  24. 9 10
      src/views/vent/monitorManager/fanLocalMonitor/index.vue
  25. 20 18
      src/views/vent/monitorManager/fiberMonitor/fiber.belt.threejs.ts
  26. 25 3
      src/views/vent/monitorManager/fiberMonitor/index.vue
  27. 61 38
      src/views/vent/monitorManager/fireMonitor/index.vue
  28. 61 17
      src/views/vent/monitorManager/gateMonitor/gate.threejs.ts
  29. 2 1
      src/views/vent/monitorManager/gateMonitor/index.vue
  30. 4 3
      src/views/vent/monitorManager/mainFanMonitor/index.vue
  31. 7 3
      src/views/vent/monitorManager/mainFanMonitor/main.threejs.ts
  32. 1 1
      src/views/vent/monitorManager/mainFanMonitor/mainWind.threejs.ts
  33. 481 0
      src/views/vent/monitorManager/nitrogen/index.vue
  34. 67 0
      src/views/vent/monitorManager/nitrogen/nitrogen.data.ts
  35. 404 0
      src/views/vent/monitorManager/nitrogen/nitrogen.dishang.threejs.ts
  36. 106 0
      src/views/vent/monitorManager/nitrogen/nitrogen.threejs.ts
  37. 39 14
      src/views/vent/monitorManager/windowMonitor/dandaoFc.threejs.ts
  38. 2 1
      src/views/vent/monitorManager/windowMonitor/index.vue
  39. 51 26
      src/views/vent/monitorManager/windowMonitor/shuangdaoFc.threejs.ts
  40. 1 1
      src/views/vent/monitorManager/windowMonitor/window.threejs.ts
  41. 8 5
      src/views/vent/monitorManager/windrectMonitor/components/resultTable.vue
  42. 83 82
      src/views/vent/monitorManager/windrectMonitor/duishe.threejs.ts
  43. 63 21
      src/views/vent/monitorManager/windrectMonitor/index.vue
  44. 34 3
      src/views/vent/monitorManager/windrectMonitor/longmen.threejs.ts
  45. 50 74
      src/views/vent/monitorManager/windrectMonitor/longmenSide.threejs.ts
  46. 1 1
      src/views/vent/monitorManager/windrectMonitor/windrect.threejs.ts
  47. 34 3
      src/views/vent/monitorManager/windrectMonitor/zhedie.threejs.ts

BIN=BIN
public/model/glft/cf/dscf.glb


BIN=BIN
public/model/glft/yafeng/nitrogen.glb


BIN=BIN
public/model/hdr/royal_esplanade_1k.hdr


+ 0 - 1
src/components/chart/BarAndLine.vue

@@ -96,7 +96,6 @@ import { object } from 'vue-types';
       });
 
       function initChartsOption() {
-        debugger
         optionUtil = new EchartsUtil(Object.assign(option, props.option));
         optionUtil.initChartOption(props.chartsType, chartsColumns);
       }

+ 1 - 1
src/design/vent/index.less

@@ -348,7 +348,7 @@
 
 .device-manager-box {
   margin: 10px 8px;
-  height: calc(100% - 30px);
+  height: calc(100% - 72px);
   padding-bottom: 10px;
   // border: 1px solid #447fff55;
   border: 1px solid #44d3ff70;

+ 4 - 2
src/design/vent/modal.less

@@ -205,7 +205,7 @@
 
   .top-box {
     position: absolute;
-    top: 5px;
+    top: 50px;
     width: 100%;
     height: 50px;
     // background-image: linear-gradient(to right, #046ad500, #006effe7, #046ad500);
@@ -280,7 +280,7 @@
       align-items: center;
       justify-content: center;
       color: #fff;
-      padding: 0 15px;
+      padding: 0 15px 5px 15px;
       cursor: pointer;
       &:hover {
         background: linear-gradient(#2cd1ff55, #1eb0ff55);
@@ -331,6 +331,8 @@
     font-size: 16px;
     text-align: center;
     line-height: 32px;
+    position: relative;
+    top: 47px;
   }
   .title-box {
     font-family: Geneva, sans-serif;

+ 2 - 2
src/enums/pageEnum.ts

@@ -5,8 +5,8 @@ export enum PageEnum {
   // 暂时修改
   // BASE_LOGIN = '/monitor/monitor-fan-main',
   // basic home path
-  // BASE_HOME = '/micro-vent-3dModal/dashboard/analysis',
-  BASE_HOME = '/monitorChannel/monitor-windrect',
+  BASE_HOME = '/micro-vent-3dModal/dashboard/analysis',
+  // BASE_HOME = '/monitorChannel/monitor-windrect',
   // error page path
   ERROR_PAGE = '/exception',
   // error log page path

+ 16 - 14
src/layouts/default/content/index.vue

@@ -2,7 +2,7 @@
   <div :class="[prefixCls, getLayoutContentMode, { 'layout-content-full': getShowFullHeader }]" v-loading="getOpenPageLoading && getPageLoading">
     <PageLayout class="page-box"/>
     <!-- update-begin-author:zyf date:20211129 for:qiankun 挂载子应用盒子 -->
-    <div v-if="!getShowFullHeader && loading" class="app-loading">
+    <div v-if="getShowFullHeader && loading" class="app-loading">
       <div id="loader-wrapper" class="app-loading">
         <div class="app-loading-wrap">
           <div class="app-loading-dots">
@@ -54,22 +54,22 @@
               }
             }
           }
-          const route = unref(currentRoute);
-          if (route.path.startsWith('/micro-vent-3dModal/modelchannel/safety/VentanalyModel3D') && document.body.getAttribute('class')?.includes('style-styleTwo')) {
-            document.body.removeAttribute('class', 'style-styleTwo');
-          }
+          // const route = unref(currentRoute);
+          // if (route.path.startsWith('/micro-vent-3dModal/modelchannel/safety/VentanalyModel3D') && document.body.getAttribute('class')?.includes('style-styleTwo')) {
+          //   document.body.removeAttribute('class', 'style-styleTwo');
+          // }
         });
       }
       useContentViewHeight();
 
       const getShowFullHeader = computed(() => {
         const route = unref(currentRoute);
-        if (!route.path.startsWith('/micro-vent-3dModal') || route.path.startsWith('/micro-vent-3dModal/modelchannel/safety/VentanalyModel3D')) {
-          if (document.body.getAttribute('class')?.includes('style-styleTwo')) document.body.removeAttribute('class', 'style-styleTwo');
-        } else {
-          document.body.setAttribute('class', 'style-styleTwo');
-        }
-        return getShowFullHeaderRef.value && ((!route.path.startsWith('/micro-') && !route.path.startsWith('/micro-vent-3dModal/modelchannel/safety/VentanalyModel3D')) || (route.path.startsWith('/micro-') && (route.path.endsWith('home') || !route.path.startsWith('/micro-vent-3dModal/modelchannel/safety/VentanalyModel3D'))));
+        // if (!route.path.startsWith('/micro-vent-3dModal') || route.path.startsWith('/micro-vent-3dModal/modelchannel/safety/VentanalyModel3D')) {
+        //   if (document.body.getAttribute('class')?.includes('style-styleTwo')) document.body.removeAttribute('class', 'style-styleTwo');
+        // } else {
+        //   document.body.setAttribute('class', 'style-styleTwo');
+        // }
+        return getShowFullHeaderRef.value && ((route.path.startsWith('/micro-')));
       });
       onBeforeMount(() => {});
       onMounted(() => {
@@ -120,12 +120,14 @@
     height: 100%;
     top: 0;
     left:0;
+    background: transparent;
   }
 
   .layout-content-full {
-    height: calc(100vh - 48px);
-    margin-top: 48px;
-    overflow-y: auto;
+    // height: calc(100vh - 48px);
+    // margin-top: 48px;
+    // overflow-y: auto;
+    height: 100%
   }
   .app-loading {
     display: flex;

+ 3 - 2
src/layouts/default/header/components/user-dropdown/index.vue

@@ -52,7 +52,7 @@
 
   import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
 
-  import { refreshCache, queryAllDictItems } from '/@/views/system/dict/dict.api';
+  import { refreshCache, queryAllDictItems, refreshRedis } from '/@/views/system/dict/dict.api';
   import { DB_DICT_DATA_KEY } from '/src/enums/cacheEnum';
   import { removeAuthCache, setAuthCache } from '/src/utils/auth';
   import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
@@ -116,7 +116,8 @@
       // 清除缓存
       async function clearCache() {
         const result = await refreshCache();
-        if (result.success) {
+        const refreshRedisResult = await refreshRedis()
+        if (result.success && refreshRedisResult) {
           const res = await queryAllDictItems();
           removeAuthCache(DB_DICT_DATA_KEY);
           setAuthCache(DB_DICT_DATA_KEY, res.result);

+ 3 - 0
src/layouts/default/header/index.less

@@ -268,4 +268,7 @@
   border: none !important;
   padding-bottom: 0px !important;
   box-shadow: none !important;
+  position: fixed !important;
+  width: 100%;
+  z-index: 999;
 }

+ 6 - 1
src/layouts/default/header/index.vue

@@ -1,5 +1,6 @@
 <template>
-  <Header v-if="!getShowFullHeader || (currentRoute.path.startsWith('/micro-vent-3dModal/modelchannel/') && !currentRoute.path.endsWith('home')) " :class="[...getHeaderClass, { 'vent-header': currentRoute.path.startsWith('/monitorChannel/monitor-'), 'normal-header': !currentRoute.path.startsWith('/monitorChannel/monitor-') }]">
+  <Header v-if="!getShowFullHeader || (currentRoute.path.startsWith('/micro-vent-3dModal/modelchannel/') && !currentRoute.path.endsWith('home')) " 
+    :class="[...getHeaderClass, { 'vent-header': currentRoute.path.startsWith('/monitorChannel/monitor-'), 'normal-header': !currentRoute.path.startsWith('/monitorChannel/monitor-'), 'no-header': currentRoute.path.endsWith('home') }]">
     <!-- left start -->
     <div :class="`${prefixCls}-left`">
       <!-- logo -->
@@ -271,4 +272,8 @@
     box-shadow: 0 0 20px #44caff55 inset !important;
     padding: 0 8px !important;
   }
+  .no-header{
+    height: 0px !important;
+    display: none !important;
+  }
 </style>

+ 2 - 1
src/layouts/default/index.vue

@@ -2,7 +2,8 @@
   <Layout :class="prefixCls" v-bind="lockEvents" style="height: 100%">
     <LayoutFeatures />
     <!-- <LayoutHeader fixed v-if="getShowFullHeader" /> -->
-    <LayoutHeader fixed />
+    <!-- <LayoutHeader fixed /> -->
+    <LayoutHeader />
     <Layout :class="[layoutClass]">
       <LayoutSideBar v-if="getShowSidebar || getIsMobile" />
       <Layout :class="[`${prefixCls}-main`, 'vent']">

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

@@ -27,6 +27,8 @@ export function initModalWorker() {
     'ztfj/bg.glb',
     'fire/laneway.glb',
     'fire/workFace.glb',
+    'yafeng/nitrogen.glb',
+    'ceshi/glass.glb',
   ];
 
   const db: any = new Dexie('DB');

+ 0 - 1
src/utils/threejs/useThree.ts

@@ -82,7 +82,6 @@ class UseThree {
   }
 
   createStats() {
-
     this.stats = Stats();
     this.stats?.setMode(0);
     this.stats.domElement.style = 'position: absolute; top: 300px';

+ 44 - 3
src/utils/threejs/util.ts

@@ -5,6 +5,7 @@ import { OutlinePass } from 'three/examples/jsm/postprocessing/OutlinePass.js';
 import { FXAAShader } from 'three/examples/jsm/shaders/FXAAShader.js';
 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 * as dat from "dat.gui";
 
@@ -334,9 +335,8 @@ export const animateCamera = (oldP, oldT, newP, newT, model, duration = 0.5, cal
         ease: 'easeOutBounce',
         onUpdate: function (object) {
           // 这里写逻辑
-          camera.position.x = object.x1;
-          camera.position.y = object.y1;
-          camera.position.z = object.z1;
+          camera.position.set(object.x1, object.y1, object.z1);
+          // controls.target.set(object.x2, object.y2, object.z2);
           controls.update();
           if (callBack) callBack();
         },
@@ -395,3 +395,44 @@ export const drawHot = (scale: number) => {
 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.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) => {
+  return new Promise((resolve) => {
+    new RGBELoader().setPath('/model/hdr/').load(hdr + '.hdr', (texture) => {
+      texture.mapping = THREE.EquirectangularReflectionMapping;
+      const defaultEnvironment = texture;
+      modal.scene.environment = defaultEnvironment;
+
+      resolve(texture);
+    });
+  });
+};
+

+ 2 - 1
src/views/dashboard/Analysis/homePage/network.vue

@@ -269,7 +269,7 @@ function handleTitleChange() {
 
 onMounted(() => {
   getMonitorData()
-  if (document.body.getAttribute('class')?.includes('style-styleTwo')) document.body.removeAttribute('class', 'style-styleTwo');
+  // if (document.body.getAttribute('class')?.includes('style-styleTwo')) document.body.removeAttribute('class', 'style-styleTwo');
 });
 
 onUnmounted(() => {
@@ -300,6 +300,7 @@ onUnmounted(() => {
 
 .zl-container-box {
   pointer-events: none;
+  margin-top: 30px;
   
   .top-box {
     display: flex;

+ 1 - 2
src/views/dashboard/Analysis/homePage/workerFace.vue

@@ -346,7 +346,6 @@ onMounted(() => {
 })
 
 onUnmounted(() => {
-  debugger
   if(timer)
   timer = undefined
 })
@@ -361,7 +360,7 @@ onUnmounted(() => {
   display: flex;
   justify-content: space-between;
   position: absolute;
-  top: 40px;
+  top: 90px;
   .lr-box {
     height: 100%;
     width: 347px;

+ 2 - 1
src/views/dashboard/Analysis/index.vue

@@ -14,7 +14,7 @@
             {{ item.text }}
           </Decoration11>
         </div>
-    </div>>
+    </div>
   </div>
 </template>
 <script lang="ts" setup>
@@ -106,6 +106,7 @@
       display: flex;
       justify-content: space-between;
       margin-bottom: 100px;
+      margin-top: 20px;
     }
     .bottom-btn-group{
       display: flex;

+ 31 - 5
src/views/demo/threejs/damper.vue

@@ -1,4 +1,8 @@
 <template>
+  <div class="vent-home-header">
+    <Decoration5 class="header-icon" :dur="2" :color="['#21437F', '#2CF7FE']" style="width:500px;height:40px;" />
+    <div class="header-text">实时网络解算</div>
+  </div>
   <div class="zl-box">
     <div class="zl-container-box">
       <div class="top-box">
@@ -194,7 +198,7 @@
   import { ref, onMounted, onUnmounted } from 'vue';
   import { Icon as SvgIcon  } from '/@/components/Icon';
   import { Progress } from 'ant-design-vue';
-  import { BorderBox11, BorderBox1  } from '@kjgl77/datav-vue3';
+  import { BorderBox11, BorderBox1,  Decoration5  } from '@kjgl77/datav-vue3';
   import { sensorColumns, sensorData, networkColumns, networkData, warningColumns, warningData } from './network.data'
   import dayjs from 'dayjs'
 
@@ -274,7 +278,7 @@
 
   onMounted(() => {
     getMonitorData()
-    if (document.body.getAttribute('class')?.includes('style-styleTwo')) document.body.removeAttribute('class', 'style-styleTwo');
+    // if (document.body.getAttribute('class')?.includes('style-styleTwo')) document.body.removeAttribute('class', 'style-styleTwo');
   });
 
   onUnmounted(() => {
@@ -286,10 +290,30 @@
 </script>
 <style scoped lang="less">
   @ventSpace: zxm;
+  .vent-home-header {
+    width: 100%;
+    height: 100px;
+    position: fixed;
+    top: 0;
+    background: url('/@/assets/images/vent/new-home/header-bg.png') no-repeat;
+    background-size: contain;
+    display: flex;
+    justify-content: center;
+    z-index: 99;
+    .header-icon{
+      margin-top: 45px;
+    }
+    .header-text{
+      position: fixed;
+      top: 18px;
+      color: #fff;
+      font-size: 26px;
+    }
+  }
   .zl-box{
     width: 100%;
-    height: calc(100% - 42px);
-    top: 40px;
+    height: calc(100%);
+    top: 0px;
     position: relative;
     overflow: hidden;
     color: #fff;
@@ -513,7 +537,9 @@
       height: calc(30% - 20px);
       display: flex;
       justify-content: space-between;
-      margin-top: 20px;
+      margin-top: 0px;
+      position: relative;
+      top: -20px;
       .bottom-lr-box{
         flex: 1;
         display: flex;

+ 3 - 0
src/views/system/dict/dict.api.ts

@@ -19,6 +19,7 @@ enum Api {
   dictItemCheck = '/sys/dictItem/dictItemCheck',
   refreshCache = '/sys/dict/refleshCache',
   queryAllDictItems = '/sys/dict/queryAllDictItems',
+  refreshRedis = '/safety/ventanalyMonitorData/refreshRedis',
 }
 /**
  * 导出api
@@ -133,3 +134,5 @@ export const refreshCache = () => defHttp.get({ url: Api.refreshCache }, { isTra
  * @param params
  */
 export const queryAllDictItems = () => defHttp.get({ url: Api.queryAllDictItems }, { isTransformResponse: false });
+
+export const refreshRedis = () => defHttp.get({ url: Api.refreshRedis }, {});

+ 1 - 1
src/views/vent/monitorManager/comment/DeviceEcharts.vue

@@ -169,7 +169,7 @@
               ttime_begin: historyParams.ttime[0] ? historyParams.ttime[0] : null,
               ttime_end: historyParams.ttime[1] ? historyParams.ttime[1] : null,
               tData: dayjs(historyParams.tData).format('YYYY-MM-DD'),
-              gdevicetype: props.deviceType + '*',
+              strtype: props.deviceType + '*',
               gdeviceid: newDeviceId,
               skip: historyParams.skip,
               pageSize: pageSize.value,

+ 6 - 2
src/views/vent/monitorManager/comment/HistoryTable.vue

@@ -1,6 +1,10 @@
 <template>
   <div class="history-table">
-    <BasicTable ref="historyTable" @register="registerTable" />
+    <BasicTable ref="historyTable" @register="registerTable" >
+      <template #bodyCell="{ column, record }">
+        <slot name="filterCell" v-bind="{ column, record }"></slot>
+      </template>
+    </BasicTable>
   </div>
 </template>
 
@@ -130,7 +134,7 @@
         pageSizeOptions: ['5', '10', '20'],
       },
       beforeFetch(params) {
-        params.gdevicetype = props.deviceType + '*';
+        params.strtype = props.deviceType + '*';
       },
       afterFetch(resultItems) {
         resultItems.map((item) => {

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

@@ -1,12 +1,15 @@
 import * as THREE from 'three';
 import { CSS3DObject } from 'three/examples/jsm/renderers/CSS3DRenderer.js';
-import { animateCamera, getTextCanvas, renderVideo } from '/@/utils/threejs/util';
+import { animateCamera, getTextCanvas, renderVideo, updateAxisCenter } from '/@/utils/threejs/util';
 import UseThree from '../../../../utils/threejs/useThree';
 import fcFan from './fcfanLocal.three';
 import fmFan from './fmfanLocal.three';
 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';
 // 模型对象、 文字对象
@@ -25,6 +28,15 @@ 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;
@@ -50,10 +62,10 @@ const addLight = (scene) => {
   // 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 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;
@@ -66,6 +78,7 @@ const addLight = (scene) => {
   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);
@@ -85,7 +98,7 @@ const resetCamera = () => {
 
 // 设置模型位置
 const setModalPosition = () => {
-  group.position.set(0, 18, -50);
+  group.position.set(0, 13, -50);
   group.rotation.y = Math.PI / 2;
 };
 
@@ -111,7 +124,7 @@ export const setModelType = (type) => {
         await animateCamera(
           oldCameraPosition,
           oldCameraPosition,
-          { x: 0, y: 30, z: 80 },
+          { x: 0, y: 20, z: 80 },
           { x: position.x, y: position.y, z: position.z },
           model,
           0.8
@@ -130,7 +143,7 @@ export const setModelType = (type) => {
         await animateCamera(
           oldCameraPosition,
           oldCameraPosition,
-          { x: 0, y: 30, z: 80 },
+          { x: 0, y: 20, z: 80 },
           { x: position.x, y: position.y, z: position.z },
           model,
           0.8
@@ -245,7 +258,7 @@ export const addCssText = () => {
     fanLocalCSS3D.name = 'text1';
     fanLocalCSS3D.scale.set(0.04, 0.04, 0.04);
     fanLocalCSS3D.rotation.y = -Math.PI / 2;
-    fanLocalCSS3D.position.set(-82.96, 5.97, -0.84);
+    fanLocalCSS3D.position.set(-85.68, 5.97, -17.74);
     group.add(fanLocalCSS3D);
   }
   if (!group.getObjectByName('text2')) {
@@ -263,7 +276,7 @@ export const addCssText = () => {
     fanLocalCSS3D.name = 'text3';
     fanLocalCSS3D.scale.set(0.1, 0.1, 0.1);
     fanLocalCSS3D.rotation.y = -Math.PI / 2;
-    fanLocalCSS3D.position.set(74.63, 10.05, -37.23);
+    fanLocalCSS3D.position.set(35.28, 10.05, -37.23);
     group.add(fanLocalCSS3D);
   }
   if (!group.getObjectByName('text4')) {
@@ -281,7 +294,7 @@ export const addCssText = () => {
   if (!group.getObjectByName('text5')) {
     const element = document.getElementById('windownBox') as HTMLElement;
     if (element) {
-      element.innerHTML = '';
+      // element.innerHTML = '';
       const fanLocalCSS3D = new CSS3DObject(element);
       fanLocalCSS3D.name = 'text5';
       fanLocalCSS3D.scale.set(0.07, 0.07, 0.07);
@@ -468,15 +481,22 @@ const startAnimation = () => {
 };
 // 鼠标点击、松开事件
 const mouseEvent = (event) => {
+  const factor = 3;
   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) {
@@ -501,8 +521,8 @@ export const mountedThree = (playerVal1) => {
   return new Promise((resolve) => {
     model = new UseThree('#fanLocal3D', '#fanLocal3DCSS');
     model.setEnvMap('test1');
-    model.renderer.toneMappingExposure = 0.8;
-    addLight(model.scene);
+    model.renderer.toneMappingExposure = 1;
+
     resetCamera();
     model.setModel([modelName]).then(async (gltf) => {
       group = gltf[0];
@@ -512,6 +532,7 @@ export const mountedThree = (playerVal1) => {
       setControls();
       initFly();
       model.animate();
+      addLight(model.scene);
 
       fcFanObj = new fcFan(model);
       await fcFanObj.mountedThree();
@@ -526,6 +547,40 @@ export const mountedThree = (playerVal1) => {
         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);

+ 9 - 10
src/views/vent/monitorManager/fanLocalMonitor/index.vue

@@ -7,20 +7,19 @@
       <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>
+            <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.windSpeed12 ? selectData.windSpeed2 : '-' }}</p>
-            <p>出风口瓦斯1浓度:{{ selectData.gas1 ? selectData.gas1 : '-' }}</p>
-            <p>出风口瓦斯2浓度:{{ selectData.gas2 ? selectData.gas2 : '-' }}</p>
+            <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>
+            <p>回风瓦斯浓度:{{ selectData.gas3 ? selectData.gas3 : '-' }}</p>
           </div>
         </div>
         <div class="elementTag" id="gateBox">
@@ -31,8 +30,7 @@
         </div>
         <div  class="elementTag" id="windownBox">
           <div class="elementContent">
-            <p>风窗开度:{{ selectData.getRotate1 ? selectData.getRotate1 : '-' }}</p>
-            <p>过风面积:{{ selectData.getRotate2 ? selectData.getRotate2 : '-' }}</p>
+            <p>风窗全风压回风流:0</p>
           </div>
         </div>
       </div>
@@ -312,7 +310,8 @@
     fault: '气源压力超限',
   };
   const flvURL1 = () => {
-    return `https://sf1-hscdn-tos.pstatp.com/obj/media-fe/xgplayer_doc_video/flv/xgplayer-demo-360p.flv`;
+    // 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));
@@ -458,7 +457,7 @@
         console.log('设备操作结果', res);
       });
     } else if (handType === 'changeSmoke') {
-      debugger
+
       // 一键倒机
       if (mainWindIsShow1.value === 'open' && mainWindIsShow2.value === 'stop') {
         playSmoke('startSmoke', 'down', frequency, 'open');

+ 20 - 18
src/views/vent/monitorManager/fiberMonitor/fiber.belt.threejs.ts

@@ -177,15 +177,15 @@ class beltFiber {
           this.group.add(mainCSS3D);
         }
       }
-      if (!this.group.getObjectByName('location' + i)) {
-        const geometry = new THREE.PlaneGeometry(1, 0.8);
-        const location = new THREE.Mesh(geometry, this.locationMaterial as THREE.Material);
-        location.scale.set(0.3, 0.3, 0.3);
-        location.name = 'location' + i;
-        location.position.set(locationX[i - 1], 1.384, position.z);
-        location.layers.enable(this.glob.ENTIRE_SCENE);
-        this.group.add(location);
-      }
+      // if (!this.group.getObjectByName('location' + i)) {
+      //   const geometry = new THREE.PlaneGeometry(1, 0.8);
+      //   const location = new THREE.Mesh(geometry, this.locationMaterial as THREE.Material);
+      //   location.scale.set(0.3, 0.3, 0.3);
+      //   location.name = 'location' + i;
+      //   location.position.set(locationX[i - 1], 1.384, position.z);
+      //   location.layers.enable(this.glob.ENTIRE_SCENE);
+      //   this.group.add(location);
+      // }
     }
   }
 
@@ -318,14 +318,16 @@ class beltFiber {
 
   /* 点击 */
   mousedownModel(intersects: THREE.Intersection<THREE.Object3D<THREE.Event>>[]) {
-    // 判断是否点击到视频
-    intersects.find((intersect) => {
-      const mesh = intersect.object;
-      if (mesh.name === 'player1') {
-        return true;
-      }
-      return false;
-    });
+    if (intersects.length > 0) {
+      // 判断是否点击到视频
+      intersects.find((intersect) => {
+        const mesh = intersect.object;
+        if (mesh.name === 'player1') {
+          return true;
+        }
+        return false;
+      });
+    }
   }
   mouseUpModel() {}
   mountedThree() {
@@ -355,7 +357,7 @@ class beltFiber {
         this.drawSpheres().then(() => {
           // this.render();
         });
-        this.addBeltText();
+        // this.addBeltText();
         resolve(null);
       });
 

+ 25 - 3
src/views/vent/monitorManager/fiberMonitor/index.vue

@@ -2,6 +2,26 @@
   <div class="bg"
     style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; overflow: hidden">
     <a-spin :spinning="loading" />
+    <!-- <div
+        id="fiber3DCSS"
+        class="threejs-Object-CSS"
+        v-show="!loading"
+        style="width: 100%; height: 100%; position: absolute; pointer-events: none; overflow: hidden; z-index: 1; top: 0"
+      >
+      <div v-for="i in fiberListNum">
+        <div v-for="item in 10" :id="'fiberMeg' + i + item" :key="item" class="monitor-msg-box"> 
+             
+            <div class="monitor-msg-container"  :class="{ errorColor: errorNum.includes(item), warningColor: warningNum.includes(item) }">
+              <div class="monitor-item">
+                <p class="item-title">{{ (item - 1) * 100 }}~{{ item * 100 }}m区域:</p>
+                <p><span class="data-title">平均温度(℃):</span><span class="num">30</span></p>
+                <p><span class="data-title">最高温度(℃):</span><span class="num">40</span></p>
+                <p><span class="data-title">最低温度(℃):</span><span class="num">10</span></p>
+              </div>
+            </div>
+          </div>
+        </div>
+    </div> -->
     <div id="fiberBox"  style="width: 100%; height: 100%; position: absolute; overflow: hidden"> </div>
   </div>
   <div class="scene-box">
@@ -77,12 +97,13 @@ import MonitorTable from '../comment/MonitorTable.vue';
 import HistoryTable from '../comment/HistoryTable.vue';
 import AlarmHistoryTable from '../comment/AlarmHistoryTable.vue';
 import HandlerHistoryTable from '../comment/HandlerHistoryTable.vue';
-import { mountedThree, destroy, setModelType, refreshModal } from './fiber.threejs';
+import { mountedThree, destroy, setModelType, refreshModal, addFiberText } from './fiber.threejs';
 import { list, getTableList } from './fiber.api';
 import { list as baseList } from '../../deviceManager/windWindowTabel/ventanalyWindow.api';
 import { chartsColumns } from './fiber.data';
 import lodash from 'lodash';
 
+const fiberListNum = ref(3)
 
 const deviceBaseList = ref([]);
 const activeKey = ref('1');
@@ -143,6 +164,7 @@ function getMonitor(){
     timer = setTimeout(async () => {
       const data = await getDataSource();
       Object.assign(selectData, data);
+      // addFiberText(selectData)
       if (timer) {
         timer = null;
       }
@@ -175,8 +197,8 @@ function getSelectRow(selectRow, index){
   selectRowIndex.value = index;
   const baseData: any = deviceBaseList.value.find((baseData: any) => baseData.id === selectRow.deviceID);
   Object.assign(selectData, initData, selectRow, baseData);
-
-  setModelType('workFace')
+  
+  setModelType('beltFiber')
 };
 
 onBeforeMount(() => {

+ 61 - 38
src/views/vent/monitorManager/fireMonitor/index.vue

@@ -1,4 +1,8 @@
 <template>
+    <div class="vent-home-header">
+        <Decoration5 class="header-icon" :dur="2" :color="['#21437F', '#2CF7FE']" style="width:500px;height:40px;" />
+        <div class="header-text">皮带机监测</div>
+    </div>
     <div class="fire-box">
         <div class="fire-top">
             <div class="top-lr top-left">
@@ -49,18 +53,17 @@
                 :chartsColumns="[]"
                 chartsType="detail"
                 @refresh="refreshEchatrs"
-              />
+                />
             </BorderBox11>
         </div>
     </div>
 </template>
 <script setup lang="ts">
 import BarAndLine from '/@/components/chart/BarAndLine.vue';
-import { BorderBox1, ScrollBoard, BorderBox11 } from '@kjgl77/datav-vue3';
+import { BorderBox1, ScrollBoard, BorderBox11, Decoration5 } from '@kjgl77/datav-vue3';
 import { ref, reactive, onMounted, onUnmounted } from 'vue'
 import { hyConfigFn, ywConfigFn, plConfigFn } from './fire.data'
 import { list } from './fire.api'
-import { async } from 'rxjs';
 
 const hyScrollBoard = ref()
 const ywScrollBoard = ref()
@@ -155,45 +158,65 @@ onUnmounted(() => {
 </script>
 
 <style lang="less" scoped>
-    .fire-box{
-        position: relative;
-        z-index: 999;
-        width: 100%;
-        height: calc(100% - 48px);
-        top: 48px;
-        pointer-events: none;
-        .fire-top{
-            height: calc(100% - 300px);
+.vent-home-header {
+    width: 100%;
+    height: 100px;
+    position: fixed;
+    top: 0;
+    background: url('/@/assets/images/vent/new-home/header-bg.png') no-repeat;
+    background-size: contain;
+    display: flex;
+    justify-content: center;
+    z-index: 99;
+    .header-icon{
+      margin-top: 45px;
+    }
+    .header-text{
+      position: fixed;
+      top: 18px;
+      color: #fff;
+      font-size: 26px;
+    }
+  }
+.fire-box{
+    position: relative;
+    z-index: 999;
+    width: 100%;
+    height: calc(100% - 48px);
+    top: 0px;
+    pointer-events: none;
+    .fire-top{
+        height: calc(100% - 300px);
+        display: flex;
+        flex-direction: row;
+        justify-content: space-between;
+        .top-lr{
+            width: 400px;
+            height: 100%;
+            margin-top: 10px;
             display: flex;
-            flex-direction: row;
-            justify-content: space-between;
-            .top-lr{
-                width: 400px;
-                height: 100%;
-                margin-top: 10px;
-                display: flex;
-                flex-direction: column;
-                .lr-item{
-                    flex: 1;
-                    margin-top: 20px;
-                    .item-top-title{
-                        position: relative;
-                        top: -5px;
-                        color: #fff;
-                    }
+            flex-direction: column;
+            .lr-item{
+                flex: 1;
+                margin-top: 20px;
+                .item-top-title{
+                    position: relative;
+                    top: -5px;
+                    color: #fff;
                 }
             }
-            .top-right{
-                
-            }
         }
-        
-        .fire-bottom{
-            height: 300px;
-        }
-        .scroll-box{
-            padding: 0 20px;
-            height: 100%;
+        .top-right{
+            
         }
     }
+    
+    .fire-bottom{
+        height: 300px;
+    }
+    .scroll-box{
+        padding: 0 20px;
+        height: 100%;
+    }
+}
 </style>

+ 61 - 17
src/views/vent/monitorManager/gateMonitor/gate.threejs.ts

@@ -149,11 +149,11 @@ export function addFmText(selectData) {
   }
   const textArr = [
     {
-      text: `煤矿巷道远程风门系统`,
+      text: `远程控制自动风门`,
       font: 'normal 30px Arial',
       color: '#00FF00',
       strokeStyle: '#007400',
-      x: 80,
+      x: 120,
       y: 100,
     },
     {
@@ -603,7 +603,7 @@ export function initOpenState(selectData) {
     clipActionArr.backDoor.time = 0.5;
 
     clipActionArr.frontDoor.stop();
-    clipActionArr.backDoor.stop()
+    clipActionArr.backDoor.stop();
 
     // frontClock.stop();
     // backClock.stop();
@@ -617,7 +617,7 @@ export function mountedThree(playerVal1, playerVal2) {
     model = new UseThree('#damper3D', '', '#deviceDetail');
 
     model.setEnvMap('test1');
-    model.renderer.toneMappingExposure = 0.8;
+    model.renderer.toneMappingExposure = 1;
     model.scene?.add(group);
     group?.layers.enableAll();
     const bb = new Date().getTime();
@@ -640,20 +640,64 @@ export function mountedThree(playerVal1, playerVal2) {
         player2 = playerVal2;
         const videoPlayer1 = document.getElementById('fm-player1')?.getElementsByClassName('vjs-tech')[0];
         const videoPlayer2 = document.getElementById('fm-player2')?.getElementsByClassName('vjs-tech')[0];
-        if (videoPlayer1) {
-          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 (videoPlayer2) {
-          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);
+        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);

+ 2 - 1
src/views/vent/monitorManager/gateMonitor/index.vue

@@ -219,7 +219,8 @@
   const selectData = reactive(lodash.cloneDeep(initData));
 
   const flvURL1 = () => {
-    return `https://sf1-hscdn-tos.pstatp.com/obj/media-fe/xgplayer_doc_video/flv/xgplayer-demo-360p.flv`;
+    // return `https://sf1-hscdn-tos.pstatp.com/obj/media-fe/xgplayer_doc_video/flv/xgplayer-demo-360p.flv`;
+    return ''
   };
   const flvURL2 = () => {
     return `https://sf1-hscdn-tos.pstatp.com/obj/media-fe/xgplayer_doc_video/flv/xgplayer-demo-360p.flv`;

+ 4 - 3
src/views/vent/monitorManager/mainFanMonitor/index.vue

@@ -11,14 +11,14 @@
         <div class="elementTag" id="inputBox">
           <div class="elementContent elementContent-r" v-if="selectData.DataPa && backMonitorIsShow">
             <p><span class="data-title">风机气压(Pa):</span>{{ selectData.DataPa ? selectData.DataPa : '-' }}</p>
-            <p><span class="data-title">风机压(Pa):</span>{{ selectData.Fan2Negative ? selectData.Fan2Negative : '-' }}</p>
+            <p><span class="data-title">风机压(Pa):</span>{{ selectData.Fan2Negative ? selectData.Fan2Negative : '-' }}</p>
             <p><span class="data-title">风机风量(m³/s):</span>{{ selectData.Fan2m3 ? selectData.Fan2m3 : '-' }}</p>
           </div>
         </div>
         <div class="elementTag" id="inputBox1">
           <div class="elementContent elementContent-r" v-if="selectData.DataPa && frontMonitorIsShow">
             <p><span class="data-title">风机全压(Pa):</span>{{ selectData.DataPa ? selectData.DataPa : '-' }}</p>
-            <p><span class="data-title">风机压(Pa):</span>{{ selectData.Fan1Negative ? selectData.Fan1Negative : '-' }}</p>
+            <p><span class="data-title">风机压(Pa):</span>{{ selectData.Fan1Negative ? selectData.Fan1Negative : '-' }}</p>
             <p><span class="data-title">风机风量(m³/s):</span>{{ selectData.Fan1m3 ? selectData.Fan1m3 : '-' }}</p>
           </div>
         </div>
@@ -639,7 +639,7 @@
     width: 915px !important;
     height: 75px !important;
     left: 50% !important;
-    top: 32px !important;
+    top: 85px !important;
     transform: translateX(-50%) !important;
     background: url('/@/assets/images/vent/tab-group-bg.png') no-repeat !important;
     padding: 0 30px !important;
@@ -671,6 +671,7 @@
     padding: 10px;
     color: #ffffff;
     z-index: 999;
+    top: 50px;
     .data-item {
       pointer-events: auto;
       .item-header {

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

@@ -3,6 +3,7 @@ import { animateCamera, getTextCanvas, renderVideo } from '/@/utils/threejs/util
 import UseThree from '../../../../utils/threejs/useThree';
 import mainWindRect from './mainWind.threejs';
 import { useAppStore } from '/@/store/modules/app';
+import { log } from 'console';
 // import * as dat from 'dat.gui';
 // const gui = new dat.GUI();
 
@@ -113,6 +114,7 @@ const mouseEvent = (event) => {
         mainWindObj.mousedownModel.call(mainWindObj, intersects);
       }
     }
+    console.log(model.camera, model.orbitControls);
   }
 };
 
@@ -234,12 +236,13 @@ export const setModelType = (type) => {
       group = mainWindObj.group;
       setTimeout(async () => {
         resolve(null);
-        const position = mainWindObj.group.position;
+        // const position = mainWindObj.group.position;
+        const position = new THREE.Vector3(3.1, 8.6, -6.38);
         const oldCameraPosition = { x: -500, y: 100, z: 2000 };
         await animateCamera(
           oldCameraPosition,
           oldCameraPosition,
-          { x: 0, y: -100.539, z: 104.313 },
+          { x: 2.36, y: 79.2, z: 115.9 },
           { x: position.x, y: position.y, z: position.z },
           model,
           0.8
@@ -260,7 +263,8 @@ export const mountedThree = (playerVal1) => {
     resetCamera();
     model.setModel(['bg']).then(async (gltf) => {
       bgGroup = gltf[0];
-      bgGroup.position.y = 36.6;
+      bgGroup.position.set(3.43, 27.13, 22.0);
+      // bgGroup.position.y = 36.6;
       model.scene.add(bgGroup);
       mainWindObj = new mainWindRect(model, playerVal1);
       await mainWindObj.mountedThree();

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

@@ -662,7 +662,7 @@ class mainWindRect {
     return new Promise(async (resolve) => {
       this.model.setModel([this.modelName]).then(async (gltf) => {
         this.group = gltf[0];
-        this.group?.position.set(-0.44, 29.88, 12.37);
+        this.group?.position.set(-0.44, 19.88, 22.37);
 
         // this.initAnimation();
         // this.startAnimation()

+ 481 - 0
src/views/vent/monitorManager/nitrogen/index.vue

@@ -0,0 +1,481 @@
+<template>
+  <div class="threejs-Object-CSS"></div>
+  <div id="nitrogen3D" style="width: 100%; height: 100%; position: absolute; overflow: hidden"></div>
+  <div class="vent-home">
+    <div class="vent-home-header">
+      <Decoration5 class="header-icon" :dur="2" :color="['#21437F', '#2CF7FE']" style="width:500px;height:40px;" />
+      <div class="header-text">智能压风管控系统</div>
+    </div>
+    
+    <div class="nitrogen-container">
+      <div class="top-box">
+          <!-- 左边监测数据 -->
+          <div class="lr-box left-box">
+            <div class="item item-l" v-for="groupNum in monitorDataGroupNum" :key="groupNum">
+              <dv-decoration7 style="height:30px;">
+                <div class="base-title">空压机{{ groupNum }}</div>
+              </dv-decoration7>
+              <div class="monitor-box">
+                <div class="state-item" v-for="(data, index) in showMonitorData" :key="index">
+                  <div class="item-col" v-if="Object.values(data).length > 0">
+                    <span class="state-title">{{ Object.values(data)[0] }} :</span>
+                    <span class="state-val">{{ (monitorData.length > 0 && monitorData[groupNum - 1][Object.keys(data)[0]]) >= 0 ? monitorData[groupNum - 1][Object.keys(data)[0]] : '-' }}</span>
+                  </div>
+                  <div class="item-col" v-if="Object.values(data).length > 1">
+                    <span class="state-title">{{ Object.values(data)[1] }} :</span>
+                    <span class="state-val">{{ (monitorData.length > 0 && monitorData[groupNum - 1][Object.keys(data)[1]]) >= 0 ? monitorData[groupNum - 1][Object.keys(data)[1]] : '-' }}</span>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+          <!-- 右边控制状态 -->
+          <div class="lr-box right-box">
+            <div class="item" >
+              <div class="control-item">
+                <div class="control-item-l">
+                    <!-- <img src="@/assets/img/yccz.png" alt="" width="36px" height="36px" style="margin-right: 10px;"> -->
+                    <span style="font-size: 18px;">远程控制</span>
+                </div>
+              </div>
+              <div class="control-item" v-for="groupNum in monitorDataGroupNum" :key="groupNum">
+                <div class="control-item-l">
+                  <span class="round"></span>
+                  <span>{{ kyjs[groupNum - 1] }}</span>
+                </div>
+                <div class="control-item-r" style="display: flex; align-items: center;">
+                  <a-switch
+                    v-model="airCompressorState[groupNum - 1][`compressRunSigF1`]"
+                    checked-children="开启"
+                    un-checked-children="关闭"
+                    :disabled="airCompressorState[groupNum - 1][`controlModel`]"
+                    @change="handlerDevice(airCompressorState[groupNum - 1])">
+                  </a-switch>
+                  <div class="button-box">
+                    <!-- <a-button type="primary" siz="small" @click="resetDevice(airCompressorState[groupNum - 1])">复位</a-button> -->
+                    <span class="">复位</span>
+                  </div>
+                </div>
+              </div>
+              <div class="control-item">
+                <div class="control-item-l">
+                  <span class="round"></span>
+                  <span>控制模式</span>
+                </div>
+                <div>
+                  <a-switch
+                    v-model="airCompressorState[0][`controlModel`]"
+                    checked-children="就地"
+                    un-checked-children="远程"
+                    @change="handlerControlModel(airCompressorState[0])">
+                  </a-switch>
+                </div>
+              </div>
+            </div>
+            <!-- <div class="item" >
+              <assembly-flv ref="video" class="video-box" height="250px"  :url="videoUrl" :destroy="isDestroyVideo" ></assembly-flv>
+            </div> -->
+
+          </div>
+        </div>
+    </div>
+    <div class="bottom-btn-group">  
+      <div v-for="item in bottomBtnList" :key="item.value" class="vent-row-center btn-item" @click="setBtn('click', item)" @mouseenter="setBtn('over', item)" @mouseleave="setBtn('leave', item)">
+        <dv-decoration11 :color="isBtnActive === item.value ? activeColors : item.isHover ? activeColors : noActiveColors" style="width:200px;height:60px;">
+          {{ item.text }}
+        </dv-decoration11>
+      </div>
+    </div>
+  </div>
+</template>
+<script lang="ts" setup>
+import { onMounted, onUnmounted, ref } from 'vue'
+import { Decoration5, Decoration11 as DvDecoration11, Decoration7 as DvDecoration7, BorderBox7 as DvBorderBox7 } from '@kjgl77/datav-vue3'
+import { bottomBtnList } from './nitrogen.data'
+import { mountedThree } from './nitrogen.threejs'
+
+const activeColors = ['#009BFF', '#28DBE4']
+const noActiveColors = ['#aaa', '#aaa']
+const isBtnActive = ref('workFace')
+
+const kyjs = ['1号空压机', '2号空压机', '3号空压机', '4号空压机'];
+// const cqgs = ['1号储气罐', '2号储气罐', '3号储气罐', '4号储气罐'];
+// const checkedKyjs = new Set(['1号空压机']);
+const monitorDataGroupNum = 3;
+const airCompressorState = ref([
+  {
+    id: '',
+    compressRunSigF1: false,
+    controlModel: false
+  },
+  {
+    id: '',
+    compressRunSigF1: false,
+    controlModel: false
+  },
+  {
+    id: '',
+    compressRunSigF1: false,
+    controlModel: false
+  },
+  {
+    id: '',
+    compressRunSigF1: false,
+    controlModel: false
+  }
+]);
+const showMonitorData = [
+  {
+    supVolt1: '电流A(A)',
+    supVolt2: '电流B(A)',
+  },
+  {
+    supVolt3: '电流C(A)',
+    current: '电源电压(V)',
+  },
+  {
+    shock1: '震动X(mm/s)',
+    shock2: '震动Y(mm/s)',
+  },
+  {
+    shock3: '震动Z(mm/s)',
+    noise: '噪声',
+  },
+  {
+    ambTempCol: '环境温度(℃)',
+  },
+];
+const monitorData = ref(new Array(4).fill({
+  strName: '空压机',
+  compressGroupName: '',
+  compressExhaustPressF1: '-',
+  compressSeparatePressF1: '-',
+  compressHostTempF1: '-',
+  compressCrewTempF1: '-',
+  compressRunTimeF1: '-',
+  controlModel: 'LOC'
+}));
+
+
+function setBtn(type, activeObj) {
+  if (type === 'over') {
+    activeObj.isHover = true
+  } else if (type === 'leave') {
+    activeObj.isHover = false
+  } else if (type === 'click') {
+    isBtnActive.value = activeObj.value
+  }
+}
+
+function handlerDevice(data) {
+  // if (data.length < 1) return
+  // handleAirCompressor({ id: data.id, compressRunF1: data.compressRunSigF1 }).then(res => {
+  //   if (res.success) {
+  //     message.success('操作成功')
+  //   } else {
+  //     message.warning(data.msg)
+  //   }
+  // })
+};
+function resetDevice(data) {
+
+}
+
+function handlerControlModel(data) {
+
+}
+
+
+onMounted(() => {
+  mountedThree()
+})
+
+onUnmounted(() => {
+
+})
+
+</script>
+<style lang="less">
+@import '/@/design/vent/modal.less';
+
+.@{ventSpace}-select-dropdown {
+  border-bottom: 1px solid #ececec66;
+  background: transparent !important;
+  backdrop-filter: blur(50px);
+
+  .@{ventSpace}-select-item {
+    color: #fff !important;
+  }
+
+  .@{ventSpace}-select-item-option-selected,
+  .@{ventSpace}-select-item-option-active {
+    background-color: #00678b66 !important;
+  }
+
+  .@{ventSpace}-select-item:hover {
+    background-color: #008fc366 !important;
+  }
+}
+</style>
+<style lang="less" scoped>
+@ventSpace: zxm;
+
+.vent-home {
+  width: 100%;
+  height: calc(100%);
+  position: fixed;
+  z-index: 99;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+  pointer-events: none;
+
+  .vent-home-header {
+    width: 100%;
+    height: 100px;
+    position: fixed;
+    top: 0;
+    background: url('/@/assets/images/vent/new-home/header-bg.png') no-repeat;
+    background-size: contain;
+    display: flex;
+    justify-content: center;
+
+    .header-icon {
+      margin-top: 45px;
+    }
+
+    .header-text {
+      position: fixed;
+      top: 18px;
+      color: #fff;
+      font-size: 24px;
+    }
+  }
+
+  .nitrogen-container {
+    width: 100%;
+    height: calc(100% - 200px);
+    display: flex;
+    justify-content: space-between;
+    margin-bottom: 100px;
+    .top-box{
+      width: 100%;
+      padding: 10px;
+      overflow: hidden;
+      display: flex;
+      justify-content: space-between;
+      .lr-box{
+        height: fit-content;
+        display: flex;
+        flex-direction: column;
+        position: relative;
+        overflow: hidden;
+        z-index: 9999;
+      }
+      .item{
+        width: 285px;
+        height: auto;
+        position: relative;
+        border-radius: 5px;
+        margin-top: 10px;
+        margin-bottom: 0px;
+        pointer-events: auto;
+        color: #fff;
+        overflow: hidden;
+      
+        .control-item{
+          height: auto;
+          min-height: 35px;
+          display: flex;
+          flex-direction: row;
+          justify-content: space-between;
+          align-items: center;
+          padding: 5px;
+          margin: 0 10px 0 3px;
+          pointer-events: auto;
+          background: linear-gradient(to right, #0063CD22, #0063CD04);
+
+          margin-bottom: 5px;
+          border-width: 1px;
+          border-style: dashed;
+
+          border-image: linear-gradient(to right, #008ccd66, #0063CD04)1 1;
+          border-radius: 5px;
+          &:last-child{
+            margin-bottom: 0
+          }
+          .control-item-l{
+            display: flex;
+            align-items: center;
+            font-size: 14px;
+            .round{
+              display: inline-block;
+              width: 3px;
+              height: 3px;
+              padding: 1px;
+              border-radius: 50%;
+              background-color: #3DF6FF;
+              margin-right: 5px;
+              box-shadow: 0 0 1px 1px #64f7ff;
+            }
+          }
+          .control-item-r{
+            text-align: right;
+          }
+          .button-box{
+            position: relative;
+            padding: 5px;
+            border:1px transparent solid;
+            background-clip: border-box;
+            border-radius: 5px;
+            margin-left: 8px;
+          }
+          .a-button{
+            pointer-events: auto;
+          }
+          &::v-deep .a-button--mini {
+            padding: 6px 10px;
+          }
+          &::v-deep .a-button--mini.is-round{
+            padding: 6px 10px;
+          }
+        }
+        .base-title {
+          width: calc(100% - 60px);
+          text-align: center;
+          color: #00d8ff;
+        }
+        .state-item{
+          display: flex;
+          flex-direction: row;
+          padding: 5px;
+          .item-col{
+            width: 50%;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            padding-right: 4px;
+            .state-title{
+              color: #ffffffcc;
+              flex: 9;
+              font-size: 14px;
+              .unit{
+                // color: #ffffffbb;
+              }
+            }
+            .state-val{
+              flex: 1;
+              color: #e4a300;
+              margin-right: 5px;
+              text-align: right;
+              font-size: 14px;
+            }
+          }
+        }
+        .signal-box{
+          margin: 5px 0;
+          display: flex;
+          align-items: center;
+          .signal-title{
+            color: #7AF5FF;
+            margin: 0 5px;
+          }
+
+          &:last-child{
+              margin-right: 0px;
+            }
+        }
+
+        .list-item {
+          padding: 0 10px;
+          display: flex;
+          justify-content: space-between;
+          align-items: center;
+          .item-data-key{
+            color: #ffffff99;
+          }
+        }
+        .item-data-box {
+            color: #fff;
+            .state-icon {
+              display: inline-block;
+              width: 12px;
+              height: 12px;
+              border-radius: 12px;
+            }
+
+            .open {
+              border: 5px solid #133a56;
+              background: #4ecb73;
+            }
+
+            .close {
+              border: 5px solid #192961;
+              background: #6d7898;
+            }
+          }
+      }
+      .item-l{
+        width: 335px;
+        .monitor-box{
+          width: 335px;
+          background-color: #ffffff05;
+          margin-left: 2px;
+          border-radius: 5px;
+          backdrop-filter: blur(10px);
+        }
+      }
+      .right-box{
+        .item{
+          height: auto;
+        }
+      }
+      .left-box{
+        width: 365px;
+        .control-item{
+          height: 36px;
+        }
+      }
+    }
+  }
+
+  .bottom-btn-group {
+    display: flex;
+    position: fixed;
+    width: calc(100% - 400px);
+    height: 100px;
+    bottom: 20px;
+    align-items: center;
+    justify-content: center;
+
+    .btn-item {
+      width: 200px;
+      height: 60px;
+      margin: 10px;
+      color: #fff;
+      cursor: pointer;
+      pointer-events: auto;
+    }
+  }
+
+}
+
+:deep(.zxm-select) {
+  width: 300px;
+
+  .@{ventSpace}-select-selector {
+    background: transparent !important;
+    border: none !important;
+    box-shadow: none !important;
+
+    .zxm-select-selection-item {
+      color: #fff !important;
+      font-size: 20px;
+    }
+  }
+
+  .@{ventSpace}-select-arrow {
+    color: #fff !important;
+  }
+}</style>

+ 67 - 0
src/views/vent/monitorManager/nitrogen/nitrogen.data.ts

@@ -0,0 +1,67 @@
+import { ref } from 'vue';
+export const bottomBtnList = ref([
+  {
+    text: '工作面智能管控',
+    value: 'workFace',
+    isHover: false,
+  },
+  {
+    text: '实时网络解算',
+    value: 'netWork',
+    isHover: false,
+  },
+  {
+    text: '关键通风路线',
+    value: 'mainPath',
+    isHover: false,
+  },
+  {
+    text: '通风设备监测',
+    value: 'deviceMonitor',
+    isHover: false,
+  },
+  {
+    text: '通风预警监测',
+    value: 'warningMonitor',
+    isHover: false,
+  },
+]);
+
+
+      // dataInfo: {
+      //   controlModel: false
+      // };
+      // videoUrl: '',
+      // isDestroyVideo: false,
+      // navList: [
+      //   {
+      //     title: '监控界面',
+      //     pathName: 'nitrogen_page_lh'
+      //   },
+      //   // {
+      //   //   title: '关键节点监测',
+      //   //   pathName: 'critical_node'
+      //   // },
+      //   {
+      //     title: '实时曲线',
+      //     pathName: 'yfj_monitor_echarts_cy'
+      //   },
+      //   {
+      //     title: '压风机历史记录',
+      //     pathName: 'yfj_history'
+      //   },
+      //   {
+      //     title: '操作历史记录',
+      //     pathName: 'yfj_handler_history'
+      //   },
+      //   {
+      //     title: '故障诊断历史记录',
+      //     pathName: 'yfj_faultRecord'
+      //   }
+      // ],
+      // kyjMonitorDataKey: new Map(
+      //   [
+      //     ['压力', 'pressure'],
+      //     ['温度', 'temp'],
+      //   ]
+      // ),

+ 404 - 0
src/views/vent/monitorManager/nitrogen/nitrogen.dishang.threejs.ts

@@ -0,0 +1,404 @@
+import * as THREE from 'three';
+import { getTextCanvas, addEnvMap } 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';
+
+class Nitrogen {
+  model;
+  modelName = 'nitrogen';
+  // modelName = 'glass';
+  group: THREE.Object3D = new THREE.Object3D();
+  animationTimer;
+  isLRAnimation = true;
+  direction = 1;
+  playerStartClickTime1 = new Date().getTime();
+  playerStartClickTime2 = new Date().getTime();
+  deviceRunState = '';
+
+  constructor(model) {
+    this.model = model;
+    this.group.name = this.modelName;
+  }
+
+  addLight() {
+    const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
+    directionalLight.position.set(141, 259, 121);
+    this.group.add(directionalLight);
+    directionalLight.target = this.group;
+
+    // gui.add(directionalLight.position, 'x', -100, 200).onChange(function (value) {
+    //   directionalLight.position.x = Number(value);
+    // });
+    // gui.add(directionalLight.position, 'y', -500, 500).onChange(function (value) {
+    //   directionalLight.position.y = Number(value);
+    // });
+    // gui.add(directionalLight.position, 'z', -200, 200).onChange(function (value) {
+    //   directionalLight.position.z = Number(value);
+    // });
+
+    const spotLight = new THREE.SpotLight();
+    spotLight.angle = Math.PI / 4;
+    spotLight.penumbra = 0;
+    spotLight.castShadow = true;
+    spotLight.distance = 0;
+    spotLight.position.set(-36, 68, 189);
+    spotLight.target = this.group;
+    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', -800, 800).onChange(function (value) {
+    //   spotLight.position.x = Number(value);
+    // });
+    // gui.add(spotLight.position, 'y', -800, 800).onChange(function (value) {
+    //   spotLight.position.y = Number(value);
+    // });
+    // gui.add(spotLight.position, 'z', -800, 800).onChange(function (value) {
+    //   spotLight.position.z = Number(value);
+    // });
+  }
+
+  // 设置模型位置
+  setModalPosition() {
+    this.group?.scale.set(22, 22, 22);
+    this.group?.position.set(-25, 25, 15);
+  }
+
+  addText(selectData) {
+    if (!this.group) {
+      return;
+    }
+    const textArr = [
+      {
+        text: `龙门式测风装置`,
+        font: 'normal 32px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 170,
+        y: 40,
+      },
+      {
+        text: `风量(m3/min):`,
+        font: 'normal 29px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 2,
+        y: 115,
+      },
+      {
+        text: `${selectData.m3 ? selectData.m3 : '-'}`,
+        font: 'normal 29px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 200,
+        y: 115,
+      },
+      {
+        text: `气源压力(MPa): `,
+        font: 'normal 29px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 2,
+        y: 182,
+      },
+      {
+        text: `${selectData.temperature ? selectData.temperature : '-'}`,
+        font: 'normal 29px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 215,
+        y: 182,
+      },
+      {
+        text: `Va(m/s):`,
+        font: 'normal 29px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 2,
+        y: 245,
+      },
+      {
+        text: `${selectData.va ? selectData.va : '-'}`,
+        font: 'normal 29px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 130,
+        y: 246,
+      },
+      {
+        text: `V1(m/s):`,
+        font: 'normal 28px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 331,
+        y: 115,
+      },
+      {
+        text: `${selectData.incipientWindSpeed1 ? selectData.incipientWindSpeed1 : '-'}`,
+        font: 'normal 28px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 455,
+        y: 115,
+      },
+      {
+        text: `V2(m/s):`,
+        font: 'normal 28px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 330,
+        y: 182,
+      },
+      {
+        text: `${selectData.incipientWindSpeed2 ? selectData.incipientWindSpeed2 : '-'}`,
+        font: 'normal 28px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 452,
+        y: 182,
+      },
+      {
+        text: `V3(m/s):`,
+        font: 'normal 28px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 330,
+        y: 245,
+      },
+      {
+        text: `${selectData.incipientWindSpeed3 ? selectData.incipientWindSpeed3 : '-'}`,
+        font: 'normal 28px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 452,
+        y: 245,
+      },
+      {
+        text: `煤炭科学技术研究院有限公司研制`,
+        font: 'normal 28px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 60,
+        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(560, 346); // 平面3维几何体PlaneGeometry
+        const planeMesh = new THREE.Mesh(planeGeometry, textMaterial);
+        planeMesh.name = 'monitorText';
+        planeMesh.scale.set(0.0022, 0.0022, 0.0022);
+        planeMesh.position.set(3.25, -0.002, -0.41);
+        this.group?.add(planeMesh);
+      }
+    });
+  }
+
+  /* 提取风门序列帧,初始化前后门动画 */
+  initAnimation() {}
+
+  /* 点击 */
+  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;
+
+      return false;
+    });
+  }
+
+  mouseUpModel() {}
+
+  // 播放动画
+  play() {}
+  /**
+   * 生序排列模型的子元素
+   */
+  sortMeshChildren = (children: THREE.Mesh[]) => {
+    //生序排列
+    children.sort((x, y) => {
+      return x.geometry.attributes.position.count - y.geometry.attributes.position.count;
+    });
+    return children;
+  };
+
+  /**
+   * 设置模型透明
+   */
+  transparentModel = (model: THREE.Mesh) => {
+    const transparentMaterial = new THREE.MeshBasicMaterial({
+      transparent: true,
+      opacity: 0,
+    });
+    model.material = transparentMaterial;
+  };
+
+  /**
+   * 处理杯子的纹理和杯子外层透明壳子
+   */
+  handleGlassAndWrap = (
+    objects: THREE.Object3D,
+    withVolume: THREE.Object3D[],
+    glassModel: THREE.Mesh,
+    params: THREE.MeshPhysicalMaterialParameters,
+    scale: number,
+    position: THREE.Vector3,
+    rotation?: THREE.Vector3
+  ) => {
+    //辨别杯子和壳 大的是杯子 小的是壳 壳的点比杯子少
+    const children = glassModel.children as THREE.Mesh[];
+    this.sortMeshChildren(children);
+
+    children.forEach((mesh) => {
+      mesh.position.copy(position);
+      mesh.scale.set(scale, scale, scale);
+      rotation && mesh.rotation.setFromVector3(rotation, 'XYZ');
+    });
+
+    const [transparentWrap, glass] = children;
+
+    this.transparentModel(transparentWrap);
+
+    glass.material = new THREE.MeshPhysicalMaterial({
+      side: THREE.DoubleSide,
+      // specularColor: new Color("#ffffff"),
+      // color: new Color(0xffa000),
+      ...params,
+    });
+
+    objects.add(...children);
+    //只检测壳子 减小开销
+    withVolume.push(transparentWrap);
+  };
+
+  mountedThree() {
+    return new Promise((resolve) => {
+      this.model.setModel([this.modelName]).then(async (gltf) => {
+        const nitrogenGroup = new THREE.Object3D();
+        const nitrogenModal = gltf[0].clone();
+        nitrogenModal.name = 'nitrogenModal0';
+        nitrogenModal;
+
+        const nitrogenModal1 = gltf[0].clone();
+        nitrogenModal1.name = 'nitrogenModal1';
+        nitrogenModal1.position.set(0, 0, 1.29);
+
+        const texture = await addEnvMap('royal_esplanade_1k', this.model);
+
+        const material = new THREE.MeshPhysicalMaterial({
+          side: THREE.DoubleSide,
+          // specularColor: new Color("#ffffff"),
+          // color: new Color(0xffa000),
+          color: 0xffffff,
+          //类似透明度
+          // transmission: 0.5,
+          opacity: 0,
+          metalness: 0,
+          roughness: 0.12,
+          ior: 1.8,
+          thickness: 0.39, //透过看物体的模糊程度
+          specularIntensity: 1.1,
+          // color: new THREE.Color(0x72531e),
+          transmission: 1,
+          // envMap: texture,
+        });
+
+        nitrogenModal.children[0].children[1].material = new THREE.MeshPhysicalMaterial({
+          side: THREE.DoubleSide,
+          transparent: true,
+          opacity: 0.1,
+          color: 0xffffff,
+          //类似透明度
+          // transmission: 0.5,
+          metalness: 0,
+          roughness: 0.2,
+          ior: 1.3,
+          thickness: 1.2, //透过看物体的模糊程度
+          specularIntensity: 1,
+          // color: new THREE.Color(0x72531e),
+          transmission: 0,
+        });
+
+        gui.add(material, 'metalness', 0, 1).onChange(function (value) {
+          material.metalness = Number(value);
+        });
+        gui.add(material, 'roughness', 0, 1).onChange(function (value) {
+          material.roughness = Number(value);
+        });
+        gui.add(material, 'thickness', 0, 2).onChange(function (value) {
+          material.thickness = Number(value);
+        });
+        gui.add(material, 'specularIntensity', 0, 2).onChange(function (value) {
+          material.specularIntensity = Number(value);
+        });
+        gui.add(material, 'transmission', 0, 1).onChange(function (value) {
+          material.transmission = Number(value);
+        });
+        gui.add(material, 'ior', 0, 3).onChange(function (value) {
+          material.ior = Number(value);
+        });
+
+        nitrogenModal.children[0].children[0].material = material;
+
+        nitrogenGroup.add(nitrogenModal);
+        nitrogenGroup.add(nitrogenModal1);
+
+        this.group = nitrogenGroup;
+        this.group.name = this.modelName;
+
+        // this.handleGlassAndWrap(
+        //   this.group,
+        //   withVolume,
+        //   glass1,
+        //   roughnessParams,
+        //   10,
+        //   new THREE.Vector3(60, -2.4, -120),
+        //   new THREE.Vector3(1.5, 1, -3)
+        // );
+        // this.handleGlassAndWrap(
+        //   objects,
+        //   withVolume,
+        //   glass3,
+        //   { ...roughnessParams, color: new THREE.Color(0x72531e), transmission: 0.7 },
+        //   5,
+        //   new THREE.Vector3(-42, -2.5, -97)
+        // );
+
+        this.setModalPosition();
+        this.addLight();
+        resolve(null);
+      });
+    });
+  }
+
+  destroy() {
+    if (this.group) {
+      this.model.clearGroup(this.group);
+    }
+    this.model = null;
+    this.group = null;
+  }
+}
+
+export default Nitrogen;

+ 106 - 0
src/views/vent/monitorManager/nitrogen/nitrogen.threejs.ts

@@ -0,0 +1,106 @@
+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 * 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';
+
+const appStore = useAppStore();
+
+// 鼠标点击、松开事件
+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);
+
+  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);
+      }
+    }
+    console.log('99999------>', model.camera, model.orbitControls);
+  }
+};
+
+/* 添加监控数据 */
+export const addText = (selectData) => {
+  if (modalType === 'nitrogen') {
+    return nitrogenObj.addText.call(nitrogenObj, selectData);
+  }
+};
+
+export const play = () => {
+  if (modalType === 'nitrogen') {
+    return nitrogenObj.play.call(nitrogenObj);
+  }
+};
+
+// 切换风窗类型
+export const setModelType = (type) => {
+  modalType = type;
+  model.camera.position.set(-1000, 100, 500);
+
+  return new Promise((resolve) => {
+    // 显示双道风窗
+    if (modalType === 'nitrogen') {
+      group = nitrogenObj.group;
+      setModalCenter(group);
+      const oldCameraPosition = { x: -1000, y: 100, z: 500 };
+      const oldControlsPosition = { x: -10, y: 10, z: 10 };
+      model.scene.add(nitrogenObj.group);
+      setTimeout(async () => {
+        resolve(null);
+        await animateCamera(
+          oldCameraPosition,
+          oldControlsPosition,
+          { x: -0.24658823766780538, y: 35.50352092191473, z: 83.90511756512278 },
+          { x: 1.5582599568763913, y: -3.2828007511721147, z: 2.2606374587827234 },
+          model,
+          0.8
+        );
+      }, 300);
+    }
+  });
+};
+
+export const mountedThree = () => {
+  return new Promise(async (resolve) => {
+    model = new UseThree('#nitrogen3D');
+    model.setEnvMap('test1');
+    model.renderer.toneMappingExposure = 1;
+    model.canvasContainer?.addEventListener('mousedown', mouseEvent.bind(null));
+    nitrogenObj = new Nitrogen(model);
+    await nitrogenObj.mountedThree();
+    setModelType('nitrogen');
+    resolve(null);
+    model.animate();
+  });
+};
+
+export const destroy = () => {
+  if (model) {
+    nitrogenObj?.destroy();
+    model.deleteModal();
+    model = null;
+    group = null;
+  }
+};

+ 39 - 14
src/views/vent/monitorManager/windowMonitor/dandaoFc.threejs.ts

@@ -41,7 +41,7 @@ class singleWindow {
     }
     const textArr = [
       {
-        text: `煤矿巷道远程风窗系统`,
+        text: `远程定量调节自动风窗`,
         font: 'normal 30px Arial',
         color: '#009900',
         strokeStyle: '#002200',
@@ -57,11 +57,7 @@ class singleWindow {
         y: 150,
       },
       {
-        text: `${
-          selectData.frontRearDifference && selectData.rearPresentValue
-            ? Math.min(selectData.frontRearDifference, selectData.rearPresentValue)
-            : selectData.frontRearDifference || selectData.rearPresentValue || '-'
-        }`,
+        text: `${selectData.forntm3}`,
         font: 'normal 30px Arial',
         color: '#009900',
         strokeStyle: '#002200',
@@ -77,11 +73,7 @@ class singleWindow {
         y: 205,
       },
       {
-        text: `${
-          selectData.forntArea && selectData.rearArea
-            ? Math.min(selectData.forntArea, selectData.rearArea)
-            : selectData.forntArea || selectData.rearArea || '-'
-        }`,
+        text: `${selectData.forntArea}`,
         font: 'normal 30px Arial',
         color: '#009900',
         strokeStyle: '#002200',
@@ -97,7 +89,7 @@ class singleWindow {
         y: 256,
       },
       {
-        text: `${selectData.dataDh}`,
+        text: `${selectData.frontRearDifference}`,
         font: 'normal 30px Arial',
         color: '#009900',
         strokeStyle: '#002200',
@@ -129,7 +121,7 @@ class singleWindow {
         y: 205,
       },
       {
-        text: `${selectData.maxarea}`,
+        text: `0~6`,
         font: 'normal 30px Arial',
         color: '#009900',
         strokeStyle: '#002200',
@@ -257,7 +249,7 @@ class singleWindow {
     return new Promise((resolve) => {
       this.model.setModel(['ddFc']).then((gltf) => {
         this.group = gltf[0];
-        
+
         this.setModalPosition();
         this.initAnimation();
 
@@ -268,6 +260,39 @@ class singleWindow {
             mesh?.scale.set(0.0382, 0.028, 0.022);
             mesh?.position.set(-2.008, 0.148, -0.22);
             this.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 = 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);
+                planeMesh.name = 'noPlayer';
+                planeMesh.scale.set(0.011, 0.008, 0.011);
+                planeMesh.position.set(-1.99, -0.18, -0.23);
+                this.group?.add(planeMesh.clone());
+                textMaterial.dispose();
+                planeGeometry.dispose();
+              }
+            });
           }
           resolve(null);
         }, 0);

+ 2 - 1
src/views/vent/monitorManager/windowMonitor/index.vue

@@ -165,7 +165,8 @@
   // });
 
   const flvURL1 = () => {
-    return `https://sf1-hscdn-tos.pstatp.com/obj/media-fe/xgplayer_doc_video/flv/xgplayer-demo-360p.flv`;
+    // return `https://sf1-hscdn-tos.pstatp.com/obj/media-fe/xgplayer_doc_video/flv/xgplayer-demo-360p.flv`;
+    return ''
   };
   const flvURL2 = () => {
     return `https://sf1-hscdn-tos.pstatp.com/obj/media-fe/xgplayer_doc_video/flv/xgplayer-demo-360p.flv`;

+ 51 - 26
src/views/vent/monitorManager/windowMonitor/shuangdaoFc.threejs.ts

@@ -39,7 +39,7 @@ class doubleWindow {
     }
     const textArr = [
       {
-        text: `煤矿巷道远程风窗系统`,
+        text: `远程定量调节自动风窗`,
         font: 'normal 30px Arial',
         color: '#009900',
         strokeStyle: '#002200',
@@ -48,39 +48,31 @@ class doubleWindow {
       },
       {
         text: `过风量(m3/min):`,
-        font: 'normal 30px Arial',
+        font: 'normal 28px Arial',
         color: '#009900',
         strokeStyle: '#002200',
         x: 5,
         y: 150,
       },
       {
-        text: `${
-          selectData.frontRearDifference && selectData.rearPresentValue
-            ? Math.min(selectData.frontRearDifference, selectData.rearPresentValue)
-            : selectData.frontRearDifference || selectData.rearPresentValue || '-'
-        }`,
-        font: 'normal 30px Arial',
+        text: `${selectData.forntm3}`,
+        font: 'normal 28px Arial',
         color: '#009900',
         strokeStyle: '#002200',
-        x: 235,
+        x: 220,
         y: 150,
       },
       {
         text: `过风面积(m2): `,
-        font: 'normal 30px Arial',
+        font: 'normal 28px Arial',
         color: '#009900',
         strokeStyle: '#002200',
         x: 5,
         y: 205,
       },
       {
-        text: `${
-          selectData.forntArea && selectData.rearArea
-            ? Math.min(selectData.forntArea, selectData.rearArea)
-            : selectData.forntArea || selectData.rearArea || '-'
-        }`,
-        font: 'normal 30px Arial',
+        text: `${selectData.forntArea}`,
+        font: 'normal 28px Arial',
         color: '#009900',
         strokeStyle: '#002200',
         x: 200,
@@ -88,15 +80,15 @@ class doubleWindow {
       },
       {
         text: `风窗压差(Pa):`,
-        font: 'normal 30px Arial',
+        font: 'normal 28px Arial',
         color: '#009900',
         strokeStyle: '#002200',
         x: 5,
         y: 256,
       },
       {
-        text: `${selectData.dataDh}`,
-        font: 'normal 30px Arial',
+        text: `${selectData.frontRearDifference}`,
+        font: 'normal 28px Arial',
         color: '#009900',
         strokeStyle: '#002200',
         x: 200,
@@ -104,7 +96,7 @@ class doubleWindow {
       },
       {
         text: `调节精度:`,
-        font: 'normal 30px Arial',
+        font: 'normal 28px Arial',
         color: '#009900',
         strokeStyle: '#002200',
         x: 320,
@@ -112,23 +104,23 @@ class doubleWindow {
       },
       {
         text: `1% FS`,
-        font: 'normal 30px Arial',
+        font: 'normal 28px Arial',
         color: '#009900',
         strokeStyle: '#002200',
         x: 460,
         y: 150,
       },
       {
-        text: `调节范围:`,
-        font: 'normal 30px Arial',
+        text: `调节范围(㎡):`,
+        font: 'normal 28px Arial',
         color: '#009900',
         strokeStyle: '#002200',
         x: 320,
         y: 205,
       },
       {
-        text: `${selectData.maxarea}`,
-        font: 'normal 30px Arial',
+        text: `0~6`,
+        font: 'normal 28px Arial',
         color: '#009900',
         strokeStyle: '#002200',
         x: 460,
@@ -282,7 +274,7 @@ class doubleWindow {
   mountedThree() {
     return new Promise((resolve) => {
       this.model.setModel([this.modelName]).then((gltf) => {
-        this.group = gltf[0]
+        this.group = gltf[0];
         this.setModalPosition();
         this.initAnimation();
 
@@ -293,6 +285,39 @@ class doubleWindow {
             mesh?.scale.set(0.0385, 0.028, 0.022);
             mesh?.position.set(-4.307, 0.145, -0.22);
             this.group?.add(mesh as THREE.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 = 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);
+                planeMesh.name = 'noPlayer';
+                planeMesh.scale.set(0.011, 0.008, 0.011);
+                planeMesh.position.set(-4.28, -0.18, -0.23);
+                this.group?.add(planeMesh.clone());
+                textMaterial.dispose();
+                planeGeometry.dispose();
+              }
+            });
           }
           resolve(null);
         }, 0);

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

@@ -170,7 +170,7 @@ export const mountedThree = (playerVal1, playerVal2) => {
   return new Promise(async (resolve) => {
     model = new UseThree('#window3D');
     model.setEnvMap('test1');
-    model.renderer.toneMappingExposure = 0.8;
+    model.renderer.toneMappingExposure = 0.9;
     model.camera.position.set(100, 0, 1000);
     // 单道、 双道
     doubleWindowObj = new doubleWindow(model, playerVal1, playerVal2);

+ 8 - 5
src/views/vent/monitorManager/windrectMonitor/components/resultTable.vue

@@ -10,10 +10,16 @@
           <TableAction :actions="createActions(record, column)" />
           <!-- <a href="javascript:void(0)" ><Icon icon="ant-design:delete-outlined"></Icon></a> -->
         </template>
-      </template>
+        
+    </template>
     <template #expandedRowRender="{record}">
       <a-empty v-if="record.testDetail && record.testDetail.length < 1"/>
-      <a-table v-else :columns="innerResultColumns" :data-source="record.testDetail" rowKey="id"  size="small">
+      <a-table v-else :columns="innerResultColumns" :data-source="record.testDetail" rowKey="id"  size="small" :pagination="false">
+        <template #bodyCell="{ record, column }">
+          <template v-if="record[column.dataIndex] === null">
+            <span>-</span>
+          </template>
+      </template>
       </a-table>
     </template>
     <!-- <template></template> -->
@@ -56,9 +62,6 @@
             label: '导出',
             onClick: handleExportXls.bind(null, '测风报表导出', getExportUrl, { testid : record.id}),
           },
-          {
-            label: '删除',
-          },
         ];
       }
 

+ 83 - 82
src/views/vent/monitorManager/windrectMonitor/duishe.threejs.ts

@@ -65,11 +65,11 @@ class dsWindRect {
     }
     const textArr = [
       {
-        text: `煤矿巷道远程测风系统`,
+        text: `扫描式测风装置`,
         font: 'normal 32px Arial',
         color: '#009900',
         strokeStyle: '#002200',
-        x: 90,
+        x: 140,
         y: 75,
       },
       {
@@ -77,7 +77,7 @@ class dsWindRect {
         font: 'normal 29px Arial',
         color: '#009900',
         strokeStyle: '#002200',
-        x: 2,
+        x: 12,
         y: 133,
       },
       {
@@ -85,95 +85,47 @@ class dsWindRect {
         font: 'normal 29px Arial',
         color: '#009900',
         strokeStyle: '#002200',
-        x: 200,
+        x: 311,
         y: 133,
       },
       {
-        text: `气源压力(MPa): `,
+        text: `风速(m/s): `,
         font: 'normal 29px Arial',
         color: '#009900',
         strokeStyle: '#002200',
-        x: 2,
+        x: 12,
         y: 192,
       },
       {
-        text: `${selectData.temperature ? selectData.temperature : '-'}`,
+        text: `${selectData.va ? selectData.va : '-'}`,
         font: 'normal 29px Arial',
         color: '#009900',
         strokeStyle: '#002200',
-        x: 215,
+        x: 310,
         y: 192,
       },
       {
-        text: `Va(m/s):`,
+        text: `断面积(㎡):`,
         font: 'normal 29px Arial',
         color: '#009900',
         strokeStyle: '#002200',
-        x: 2,
+        x: 12,
         y: 247,
       },
       {
-        text: `${selectData.va ? selectData.va : '-'}`,
+        text: `${selectData.fsectarea ? selectData.fsectarea : '-'}`,
         font: 'normal 29px Arial',
         color: '#009900',
         strokeStyle: '#002200',
-        x: 130,
+        x: 310,
         y: 247,
       },
       {
-        text: `V1(m/s):`,
-        font: 'normal 28px Arial',
-        color: '#009900',
-        strokeStyle: '#002200',
-        x: 301,
-        y: 133,
-      },
-      {
-        text: `${selectData.incipientWindSpeed1 ? selectData.incipientWindSpeed1 : '-'}`,
-        font: 'normal 28px Arial',
-        color: '#009900',
-        strokeStyle: '#002200',
-        x: 425,
-        y: 133,
-      },
-      {
-        text: `V2(m/s):`,
-        font: 'normal 28px Arial',
-        color: '#009900',
-        strokeStyle: '#002200',
-        x: 300,
-        y: 190,
-      },
-      {
-        text: `${selectData.incipientWindSpeed2 ? selectData.incipientWindSpeed2 : '-'}`,
-        font: 'normal 28px Arial',
-        color: '#009900',
-        strokeStyle: '#002200',
-        x: 422,
-        y: 190,
-      },
-      {
-        text: `V3(m/s):`,
-        font: 'normal 28px Arial',
-        color: '#009900',
-        strokeStyle: '#002200',
-        x: 300,
-        y: 250,
-      },
-      {
-        text: `${selectData.incipientWindSpeed3 ? selectData.incipientWindSpeed3 : '-'}`,
-        font: 'normal 28px Arial',
-        color: '#009900',
-        strokeStyle: '#002200',
-        x: 422,
-        y: 250,
-      },
-      {
         text: `煤炭科学技术研究院有限公司研制`,
         font: 'normal 28px Arial',
         color: '#009900',
         strokeStyle: '#002200',
-        x: 60,
+        x: 50,
         y: 302,
       },
     ];
@@ -293,13 +245,9 @@ class dsWindRect {
   // 播放动画
   play(flag, isDirect = false) {
     const dsTanTou = this.group?.getObjectByName('dsTanTou') as THREE.Group;
-    if (!dsTanTou && flag != 'start') return;
-    if (!isDirect) {
-      if (this.isRun) return;
-      dsTanTou.position.setY(0);
-      this.isRun = true;
+    if (!dsTanTou && flag != 'start' && flag != 'moni') return;
+    if (flag == 'moni') {
       gsap.to(dsTanTou['position'], {
-        id: 'dsDown',
         y: -0.49,
         duration: Math.abs(dsTanTou['position']['y'] - 0.49) * 21,
         overwrite: true,
@@ -310,27 +258,49 @@ class dsWindRect {
               y: 0,
               duration: Math.abs(dsTanTou['position']['y']) * 21,
               overwrite: true,
-              // onComplete: function () {
-              //   _this.isRun = false;
-              // },
             });
           }, 2000);
         },
       });
     } else {
-      if (!this.isRun) return;
-      const dsDown = gsap.getById('dsDown');
-      const dsUp = gsap.getById('dsUp');
-      if (dsDown) {
-        dsDown.pause();
-        dsDown.kill();
-      }
-      if (dsUp) {
-        dsUp.pause();
-        dsUp.kill();
+      if (!isDirect) {
+        if (this.isRun) return;
+        dsTanTou.position.setY(0);
+        this.isRun = true;
+        gsap.to(dsTanTou['position'], {
+          id: 'dsDown',
+          y: -0.49,
+          duration: Math.abs(dsTanTou['position']['y'] - 0.49) * 21,
+          overwrite: true,
+          onComplete: function () {
+            setTimeout(() => {
+              gsap.to(dsTanTou['position'], {
+                id: 'dsUp',
+                y: 0,
+                duration: Math.abs(dsTanTou['position']['y']) * 21,
+                overwrite: true,
+                // onComplete: function () {
+                //   _this.isRun = false;
+                // },
+              });
+            }, 2000);
+          },
+        });
+      } else {
+        if (!this.isRun) return;
+        const dsDown = gsap.getById('dsDown');
+        const dsUp = gsap.getById('dsUp');
+        if (dsDown) {
+          dsDown.pause();
+          dsDown.kill();
+        }
+        if (dsUp) {
+          dsUp.pause();
+          dsUp.kill();
+        }
+        dsTanTou.position.setY(0);
+        this.isRun = false;
       }
-      dsTanTou.position.setY(0);
-      this.isRun = false;
     }
   }
 
@@ -348,6 +318,37 @@ class dsWindRect {
             mesh?.scale.set(0.042, 0.036, 1);
             mesh?.position.set(2.215, 0.016, -0.38);
             this.group?.add(mesh as THREE.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 = 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);
+                planeMesh.name = 'noPlayer';
+                planeMesh.scale.set(0.012, 0.009, 0.012);
+                planeMesh.position.set(2.25, -0.34, -0.39);
+                this.group?.add(planeMesh);
+              }
+            });
           }
           resolve(null);
         }, 0);

+ 63 - 21
src/views/vent/monitorManager/windrectMonitor/index.vue

@@ -8,8 +8,8 @@
       <div class="top-center row">
         <!-- <div class="button-box" @click="start(0)">复位</div> -->
         <!-- <div class="button-box" @click="testPlay('')">模拟动画</div> -->
-        <div class="button-box" @click="clearPlay('')">自动清洁</div>
-        <!-- <div class="button-box" @click="startRun()">启动测风</div> -->
+        <div class="button-box" @click="clearPlay()">自动清洁</div>
+        <div class="button-box" @click="startRun()">启动测风</div>
         <!-- <div class="button-box" @click="testPlay('up')">上</div>
         <div class="button-box" @click="testPlay('center')">中</div>
         <div class="button-box" @click="testPlay('down')">下</div>
@@ -55,6 +55,12 @@
             title="测风装置监测"
           >
             <template #filterCell="{ column, record }">
+              <a-tag v-if="column.dataIndex === 'netStatus'" :color="record.netStatus == 0 ? '#FF5812' : 'green'">{{
+                record.netStatus == 0 ? '断开' : '连接'
+              }}</a-tag>
+              <a-tag v-if="column.dataIndex === 'warnFlag'" :color="record.warnFlag == 0 ? 'green' : record.warnFlag == 1 ? '#FF5812' : 'gray' "> {{
+                record.warnFlag == 0 ? '正常' : record.warnFlag == 1 ? '报警' : record.warnFlag == 2 ? '断开' : '未监测'
+              }}</a-tag>
               <a-tag v-if="column.dataIndex === 'sign'" :color="record.sign == 0 ? '#95CF65' : record.sign == 1 ? '#4590EA' : '#9876AA'"> {{ 
                 record.sign == 0 ? '高位' : record.sign == 1 ? '中位' : '低位'
               }}</a-tag>
@@ -68,7 +74,7 @@
             </template>
           </MonitorTable>
         </a-tab-pane>
-        <a-tab-pane key="2" tab="实时曲线图" force-render>
+        <a-tab-pane key="2" tab="监测曲线图" force-render>
           <div class="tab-item" v-if="activeKey === '2'">
             <DeviceEcharts
               chartsColumnsType="windrect_chart"
@@ -83,7 +89,13 @@
         </a-tab-pane>
         <a-tab-pane key="3" tab="历史数据">
           <div class="tab-item">
-            <HistoryTable columns-type="windrect_history" device-type="windrect" :device-list-api="baseList" designScope="windrect-history" />
+            <HistoryTable columns-type="windrect_history" device-type="windrect" :device-list-api="baseList" designScope="windrect-history" >
+              <template #filterCell="{ column, record }">
+                <a-tag v-if="column.dataIndex === 'warnFlag'" :color="record.warnFlag == 0 ? 'green' : record.warnFlag == 1 ? '#FF5812' : 'gray'"> {{
+                  record.warnFlag == 0 ? '正常' : record.warnFlag == 1 ? '报警' : record.warnFlag == 2 ? '断开' : '未监测'
+                }}</a-tag>
+              </template>
+            </HistoryTable>
           </div>
         </a-tab-pane>
         <a-tab-pane key="4" tab="报警历史">
@@ -93,7 +105,7 @@
         </a-tab-pane>
         <a-tab-pane key="5" tab="操作历史">
           <div class="tab-item">
-            <HandlerHistoryTable columns-type="alarm_history" device-type="fanlocal" :device-list-api="baseList" designScope="alarm-history" />
+            <HandlerHistoryTable columns-type="operator_history" device-type="fanlocal" :device-list-api="baseList" designScope="operator_history" />
           </div>
         </a-tab-pane>
         <a-tab-pane key="6" tab="测风结果">
@@ -143,7 +155,6 @@
   import { list as baseList } from '../../deviceManager/windfindingTabel/windfinding.api';
   import { message, Progress } from 'ant-design-vue';
   import { chartsColumns } from './windrect.data';
-import { log } from 'console';
 
   const modalTable = ref();
   const runNum = ref(5); //设备运行数量
@@ -172,8 +183,8 @@ import { log } from 'console';
   });
 
   const flvURL1 = () => {
-    return `https://sf1-hscdn-tos.pstatp.com/obj/media-fe/xgplayer_doc_video/flv/xgplayer-demo-360p.flv`;
-    // return ''
+    // return `https://sf1-hscdn-tos.pstatp.com/obj/media-fe/xgplayer_doc_video/flv/xgplayer-demo-360p.flv`;
+    return ''
   };
   const flvURL2 = () => {
     return `https://sf1-hscdn-tos.pstatp.com/obj/media-fe/xgplayer_doc_video/flv/xgplayer-demo-360p.flv`;
@@ -467,7 +478,6 @@ import { log } from 'console';
         }
         
       } else {
-        debugger
         deviceRunState = ''
         play('start', true)
       }
@@ -476,21 +486,53 @@ import { log } from 'console';
 
   // 自测动画方法
   function testPlay(flag) {
-    setTimeout(() => {
-      play('center')
-    }, 0)
-    setTimeout(() => {
-      play('down')
-    }, 4000)
-    setTimeout(() => {
-      play('up')
-    }, 10000)
+
+    if (selectData.deviceType == 'windrect_rect') {
+      setTimeout(() => {
+        play('center')
+      }, 0)
+      setTimeout(() => {
+        play('down')
+      }, 4000)
+      setTimeout(() => {
+        play('up')
+      }, 10000)
+    }
+    if(selectData.deviceType == 'windrect_fold') {
+      setTimeout(() => {
+        play('up')
+      }, 0)
+      setTimeout(() => {
+        play('center')
+      }, 10000)
+      setTimeout(() => {
+        play('down')
+      }, 18000)
+      setTimeout(() => {
+        play('up')
+      }, 21000)
+
+    }
+    if(selectData.deviceType == 'windrect_ds') {
+      play('moni')
+    }
   };
   
   function clearPlay() {
-    setTimeout(() => {
-      message.success('自清洁功能启动成功!')
-    }, 800)
+    const data = {
+      deviceid: selectData.deviceID,
+      devicetype: selectData.deviceType,
+      paramcode: 'autoClear',
+      value: null,
+      masterComputer: selectData.masterComputer,
+    };
+    deviceControlApi(data)
+    .then((res) => {
+      // 模拟时开启
+      if (res.success) {
+        message.success('自清洁功能启动成功!')
+      }
+    })
   }
 
   function startRun() {

+ 34 - 3
src/views/vent/monitorManager/windrectMonitor/longmen.threejs.ts

@@ -68,11 +68,11 @@ class lmWindRect {
     }
     const textArr = [
       {
-        text: `煤矿巷道远程测风系统`,
+        text: `龙门式测风装置`,
         font: 'normal 32px Arial',
         color: '#009900',
         strokeStyle: '#002200',
-        x: 130,
+        x: 170,
         y: 40,
       },
       {
@@ -359,12 +359,43 @@ class lmWindRect {
         this.addLight();
         setTimeout(async () => {
           const videoPlayer1 = document.getElementById('cf-player1')?.getElementsByClassName('vjs-tech')[0];
-
           if (videoPlayer1) {
             const mesh = renderVideo(this.group, videoPlayer1, 'player1');
             mesh?.scale.set(0.042, 0.036, 0.022);
             mesh?.position.set(-2.74, 0.03, -0.39);
             this.group?.add(mesh as THREE.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 = 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);
+                planeMesh.name = 'noPlayer';
+                planeMesh.scale.set(0.012, 0.009, 0.012);
+                planeMesh.position.set(-2.72, -0.34, -0.39);
+                this.group?.add(planeMesh);
+              }
+            });
           }
           resolve(null);
         }, 0);

+ 50 - 74
src/views/vent/monitorManager/windrectMonitor/longmenSide.threejs.ts

@@ -70,15 +70,15 @@ class lmWindRectSide {
     const textArr = [
       {
         text: `煤矿巷道远程测风系统`,
-        font: 'normal 32px Arial',
+        font: 'normal 34px Arial',
         color: '#009900',
         strokeStyle: '#002200',
-        x: 130,
-        y: 38,
+        x: 125,
+        y: 42,
       },
       {
         text: `风量(m3/min):`,
-        font: 'normal 29px Arial',
+        font: 'normal 30px Arial',
         color: '#009900',
         strokeStyle: '#002200',
         x: 2,
@@ -86,90 +86,42 @@ class lmWindRectSide {
       },
       {
         text: `${selectData.m3 ? selectData.m3 : '-'}`,
-        font: 'normal 29px Arial',
+        font: 'normal 30px Arial',
         color: '#009900',
         strokeStyle: '#002200',
-        x: 200,
+        x: 331,
         y: 115,
       },
       {
-        text: `气源压力(MPa): `,
-        font: 'normal 29px Arial',
+        text: `风速(m/s):`,
+        font: 'normal 30px Arial',
         color: '#009900',
         strokeStyle: '#002200',
         x: 2,
         y: 182,
       },
       {
-        text: `${selectData.temperature ? selectData.temperature : '-'}`,
-        font: 'normal 29px Arial',
-        color: '#009900',
-        strokeStyle: '#002200',
-        x: 215,
-        y: 182,
-      },
-      {
-        text: `Va(m/s):`,
-        font: 'normal 29px Arial',
-        color: '#009900',
-        strokeStyle: '#002200',
-        x: 2,
-        y: 245,
-      },
-      {
         text: `${selectData.va ? selectData.va : '-'}`,
-        font: 'normal 29px Arial',
-        color: '#009900',
-        strokeStyle: '#002200',
-        x: 130,
-        y: 246,
-      },
-      {
-        text: `V1(m/s):`,
-        font: 'normal 28px Arial',
-        color: '#009900',
-        strokeStyle: '#002200',
-        x: 331,
-        y: 115,
-      },
-      {
-        text: `${selectData.incipientWindSpeed1 ? selectData.incipientWindSpeed1 : '-'}`,
-        font: 'normal 28px Arial',
-        color: '#009900',
-        strokeStyle: '#002200',
-        x: 455,
-        y: 115,
-      },
-      {
-        text: `V2(m/s):`,
-        font: 'normal 28px Arial',
+        font: 'normal 30px Arial',
         color: '#009900',
         strokeStyle: '#002200',
         x: 330,
         y: 182,
       },
       {
-        text: `${selectData.incipientWindSpeed2 ? selectData.incipientWindSpeed2 : '-'}`,
-        font: 'normal 28px Arial',
+        text: `断面积(MPa): `,
+        font: 'normal 30px Arial',
         color: '#009900',
         strokeStyle: '#002200',
-        x: 452,
-        y: 182,
-      },
-      {
-        text: `V3(m/s):`,
-        font: 'normal 28px Arial',
-        color: '#009900',
-        strokeStyle: '#002200',
-        x: 330,
+        x: 2,
         y: 245,
       },
       {
-        text: `${selectData.incipientWindSpeed3 ? selectData.incipientWindSpeed3 : '-'}`,
-        font: 'normal 28px Arial',
+        text: `${selectData.fsectarea ? selectData.fsectarea : '-'}`,
+        font: 'normal 30px Arial',
         color: '#009900',
         strokeStyle: '#002200',
-        x: 452,
+        x: 330,
         y: 245,
       },
       {
@@ -178,7 +130,7 @@ class lmWindRectSide {
         color: '#009900',
         strokeStyle: '#002200',
         x: 60,
-        y: 302,
+        y: 303,
       },
     ];
 
@@ -292,6 +244,7 @@ class lmWindRectSide {
     //   this.animationTimer = null;
     // }
     // 判断是否点击到视频
+
     intersects.find((intersect) => {
       const mesh = intersect.object;
       if (mesh.name === 'player1') {
@@ -301,20 +254,13 @@ class lmWindRectSide {
             this.player1.requestFullscreen();
           }
         }
+
         this.playerStartClickTime1 = new Date().getTime();
         return true;
-      } else if (mesh.name === 'player2') {
-        if (new Date().getTime() - this.playerStartClickTime2 < 400) {
-          // 双击,视频放大
-          if (this.player2) {
-            this.player2.requestFullscreen();
-          }
-        }
-        this.playerStartClickTime2 = new Date().getTime();
-        return true;
       }
       return false;
     });
+    // console.log('999999999', this.model.camera.position, this.model.orbitControls);
   }
 
   mouseUpModel() {
@@ -450,10 +396,40 @@ class lmWindRectSide {
             mesh?.scale.set(0.042, 0.036, 0.022);
             mesh?.position.set(-2.65, 0.03, -0.39);
             this.group?.add(mesh as THREE.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 = 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);
+                planeMesh.name = 'noPlayer';
+                planeMesh.scale.set(0.012, 0.009, 0.012);
+                planeMesh.position.set(-2.63, -0.32, -0.39);
+                this.group?.add(planeMesh);
+              }
+            });
           }
           resolve(null);
         }, 0);
-        
       });
     });
   }

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

@@ -246,7 +246,7 @@ export const mountedThree = (playerVal1, playerVal2) => {
   return new Promise(async (resolve) => {
     model = new UseThree('#window3D');
     model.setEnvMap('test1');
-    model.renderer.toneMappingExposure = 0.8;
+    model.renderer.toneMappingExposure = 1;
 
     lmWindRectObj = new lmWindRect(model, playerVal1, playerVal2);
     await lmWindRectObj.mountedThree();

+ 34 - 3
src/views/vent/monitorManager/windrectMonitor/zhedie.threejs.ts

@@ -61,12 +61,12 @@ class zdWindRect {
     }
     const textArr = [
       {
-        text: `煤矿巷道远程测风系统`,
+        text: `折叠式测风装置`,
         font: 'normal 32px Arial',
         color: '#009900',
         strokeStyle: '#002200',
-        x: 90,
-        y: 95,
+        x: 140,
+        y: 90,
       },
       {
         text: `风量(m3/min):`,
@@ -317,6 +317,37 @@ class zdWindRect {
             mesh?.scale.set(0.0385, 0.028, 0.022);
             mesh?.position.set(4.792, -0.16, -0.4);
             if (mesh) this.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 = 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);
+                planeMesh.name = 'noPlayer';
+                planeMesh.scale.set(0.012, 0.009, 0.012);
+                planeMesh.position.set(4.83, -0.5, -0.39);
+                this.group?.add(planeMesh);
+              }
+            });
           }
           resolve(null);
         }, 0);