Browse Source

新增瓦斯、预警监测、优化

hongrunxia 1 năm trước cách đây
mục cha
commit
9fc79bcc82
100 tập tin đã thay đổi với 1889 bổ sung965 xóa
  1. 2 2
      index.html
  2. 3 2
      package.json
  3. BIN
      public/model/glft/fire/balancePress_2023-07-20.glb
  4. BIN
      public/model/glft/fire/tunFace_2023-07-14.glb
  5. BIN
      public/model/glft/fm/fmThreeBase_2023-07-25.glb
  6. BIN
      public/model/glft/fm/fmThree_2023-07-25.glb
  7. BIN
      public/model/glft/gas/gasPump_2023-07-25.glb
  8. BIN
      public/model/glft/jbfj/jbfj-hd_2023-06-06.glb
  9. BIN
      public/model/glft/jbfj/jbfj-hd_2023-07-25.glb
  10. BIN
      public/model/hdr/test1.hdr
  11. BIN
      public/model/hdr/test2.hdr
  12. 0 0
      public/model/hdr/test2.jpeg
  13. BIN
      public/model/hdr/test3.hdr
  14. 10 1
      src/App.vue
  15. BIN
      src/assets/images/vent/alarm-icons/ccq.png
  16. BIN
      src/assets/images/vent/alarm-icons/cf.png
  17. BIN
      src/assets/images/vent/alarm-icons/fc.png
  18. BIN
      src/assets/images/vent/alarm-icons/fm.png
  19. BIN
      src/assets/images/vent/alarm-icons/js.png
  20. BIN
      src/assets/images/vent/alarm-icons/penfen.png
  21. BIN
      src/assets/images/vent/alarm-icons/penlin.png
  22. BIN
      src/assets/images/vent/alarm-icons/pw.png
  23. BIN
      src/assets/images/vent/alarm-icons/wasibeng.png
  24. BIN
      src/assets/images/vent/alarm-icons/wasichoucaig.png
  25. BIN
      src/assets/images/vent/alarm-icons/yafeng.png
  26. BIN
      src/assets/images/vent/alarm-icons/zhudan.png
  27. BIN
      src/assets/images/vent/alarm-icons/zhujiang.png
  28. BIN
      src/assets/images/vent/alarm-icons/zhushan.png
  29. 1 3
      src/components/chart/BarAndLine.vue
  30. 5 3
      src/components/chart/BarSingle.vue
  31. 1 1
      src/components/vent/fourBorderBg.vue
  32. 3 0
      src/design/vent/comment.less
  33. 36 28
      src/design/vent/modal.less
  34. 1 1
      src/hooks/core/useThree copy.ts
  35. 0 1
      src/hooks/system/useListPage.ts
  36. 16 5
      src/layouts/default/sider/bottomSideder.vue
  37. 0 1
      src/layouts/iframe/index.vue
  38. 8 1
      src/layouts/iframe/useFrameKeepAlive.ts
  39. 1 1
      src/layouts/page/index.vue
  40. 7 0
      src/main.ts
  41. 8 5
      src/router/helper/routeHelper.ts
  42. 43 22
      src/router/routes/basic.ts
  43. 1 0
      src/router/routes/modules/demo/iframe.ts
  44. 1 1
      src/settings/projectSetting.ts
  45. 2 0
      src/utils/echartsUtil.ts
  46. 6 3
      src/utils/event/index.ts
  47. 34 34
      src/utils/http/axios/axiosCancel.ts
  48. 2 1
      src/utils/lib/echarts.ts
  49. 34 7
      src/utils/threejs/main.worker.ts
  50. 133 23
      src/utils/threejs/useEvent.ts
  51. 212 185
      src/utils/threejs/useThree.ts
  52. 13 7
      src/utils/threejs/util.ts
  53. 1 0
      src/views/dashboard/Analysis/homePage/network.vue
  54. 42 46
      src/views/dashboard/Analysis/homePage/workerFace.vue
  55. 2 1
      src/views/system/menu/menu.data.ts
  56. 3 2
      src/views/system/menuModal/menu.data.ts
  57. 1 1
      src/views/vent/comment/threejs/FlyLine.ts
  58. 1 0
      src/views/vent/comment/threejs/FlyLine1.ts
  59. 53 36
      src/views/vent/comment/threejs/Smoke.ts
  60. 1 1
      src/views/vent/comment/threejs/SmokePath.ts
  61. 1 1
      src/views/vent/comment/threejs/SmokePath1.ts
  62. 1 1
      src/views/vent/deviceManager/comment/DeviceModal.vue
  63. 3 0
      src/views/vent/deviceManager/comment/FormModal.vue
  64. 2 2
      src/views/vent/deviceManager/comment/pointTabel/PointTable.vue
  65. 20 0
      src/views/vent/monitorManager/alarmMonitor/alarm.api.ts
  66. 112 0
      src/views/vent/monitorManager/alarmMonitor/alarm.data.ts
  67. 143 0
      src/views/vent/monitorManager/alarmMonitor/index.vue
  68. 7 0
      src/views/vent/monitorManager/balancePressMonitor/balancePress.api.ts
  69. 287 41
      src/views/vent/monitorManager/balancePressMonitor/balancePress.threejs.base.ts
  70. 51 45
      src/views/vent/monitorManager/balancePressMonitor/balancePress.threejs.ts
  71. 1 0
      src/views/vent/monitorManager/balancePressMonitor/components/balancePressHandleHistory.vue
  72. 2 3
      src/views/vent/monitorManager/balancePressMonitor/components/balancePressHistory.vue
  73. 9 4
      src/views/vent/monitorManager/balancePressMonitor/components/balancePressHome.vue
  74. 1 3
      src/views/vent/monitorManager/balancePressMonitor/index.vue
  75. 49 57
      src/views/vent/monitorManager/balancePressMonitor1/balancePress.three.ts
  76. 56 54
      src/views/vent/monitorManager/balancePressMonitor1/index.vue
  77. 44 48
      src/views/vent/monitorManager/beltTunMonitor/beltTun.data.ts
  78. 21 18
      src/views/vent/monitorManager/beltTunMonitor/beltTun.threejs.base.ts
  79. 27 41
      src/views/vent/monitorManager/beltTunMonitor/beltTun.threejs.ts
  80. 1 0
      src/views/vent/monitorManager/beltTunMonitor/components/beltTunHandleHistory.vue
  81. 4 13
      src/views/vent/monitorManager/chamberMonitor/chamber.threejs.base.ts
  82. 27 26
      src/views/vent/monitorManager/chamberMonitor/chamber.threejs.ts
  83. 1 0
      src/views/vent/monitorManager/chamberMonitor/components/chamberHandleHistory.vue
  84. 11 2
      src/views/vent/monitorManager/comment/AlarmHistoryTable.vue
  85. 40 2
      src/views/vent/monitorManager/comment/DeviceEcharts.vue
  86. 11 1
      src/views/vent/monitorManager/comment/GroupMonitorTable.vue
  87. 12 3
      src/views/vent/monitorManager/comment/HandlerHistoryTable.vue
  88. 55 35
      src/views/vent/monitorManager/comment/HistoryTable.vue
  89. 23 4
      src/views/vent/monitorManager/comment/MonitorTable.vue
  90. 1 1
      src/views/vent/monitorManager/comment/WorkFaceAlarmHistoryTable.vue
  91. 1 0
      src/views/vent/monitorManager/compressor/components/nitrogenEcharts.vue
  92. 1 0
      src/views/vent/monitorManager/compressor/components/nitrogenHandleHistory.vue
  93. 2 2
      src/views/vent/monitorManager/compressor/components/nitrogenHome.vue
  94. 45 49
      src/views/vent/monitorManager/compressor/nitrogen.data.ts
  95. 4 23
      src/views/vent/monitorManager/compressor/nitrogen.dishang.threejs.ts
  96. 27 22
      src/views/vent/monitorManager/compressor/nitrogen.threejs.ts
  97. 3 1
      src/views/vent/monitorManager/deviceMonitor/components/device/device.api.ts
  98. 65 0
      src/views/vent/monitorManager/deviceMonitor/components/device/device.data.ts
  99. 30 38
      src/views/vent/monitorManager/deviceMonitor/components/device/index.vue
  100. 1 0
      src/views/vent/monitorManager/deviceMonitor/components/device/modal/bundle.modal.vue

+ 2 - 2
index.html

@@ -13,7 +13,7 @@
       window._CONFIG = {};
     </script>
     <script src="/js/liveplayer-lib.min.js"></script>
-    <script type="text/javascript" src="http://47.94.222.6:9050/web-apps/apps/api/documents/api.js"></script>
+    <script type="text/javascript" src="http://182.92.126.35:9050/web-apps/apps/api/documents/api.js"></script>
   </head>
   <body style="background-color: #09172C">
     <script>
@@ -318,6 +318,6 @@
     </div>
     
     <script type="module" src="/src/main.ts"></script>
-    <script type="module" src="/src/utils/threejs/main.worker.ts"></script>
+    <!-- <script type="module" src="/src/utils/threejs/main.worker.ts"></script> -->
   </body>
 </html>

+ 3 - 2
package.json

@@ -42,7 +42,6 @@
     "@liveqing/liveplayer-v3": "^3.1.9",
     "@logicflow/core": "^1.1.13",
     "@logicflow/extension": "^1.1.13",
-    "@types/three": "^0.149.0",
     "@vue/runtime-core": "^3.2.33",
     "@vue/shared": "^3.2.33",
     "@vueuse/core": "^8.3.0",
@@ -80,7 +79,7 @@
     "resize-observer-polyfill": "^1.5.1",
     "showdown": "^2.1.0",
     "sortablejs": "^1.15.0",
-    "three": "^0.150.1",
+    "three": "^0.155.0",
     "tinymce": "^5.10.3",
     "vditor": "^3.8.13",
     "vite-plugin-theme": "^0.8.6",
@@ -120,6 +119,7 @@
     "@types/qs": "^6.9.7",
     "@types/showdown": "^1.9.4",
     "@types/sortablejs": "^1.10.7",
+    "@types/three": "^0.155.0",
     "@typescript-eslint/eslint-plugin": "^5.20.0",
     "@typescript-eslint/parser": "^5.20.0",
     "@vitejs/plugin-legacy": "^2.0.0",
@@ -267,6 +267,7 @@
         "sortablejs",
         "three",
         "three/examples/jsm/postprocessing/EffectComposer.js",
+        "three/examples/jsm/postprocessing/OutputPass.js",
         "three/examples/jsm/postprocessing/RenderPass.js",
         "three/examples/jsm/postprocessing/ShaderPass.js",
         "three/examples/jsm/postprocessing/UnrealBloomPass.js",

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


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


BIN
public/model/glft/fm/fmThreeBase_2023-07-25.glb


BIN
public/model/glft/fm/fmThree_2023-07-25.glb


BIN
public/model/glft/gas/gasPump_2023-07-25.glb


BIN
public/model/glft/jbfj/jbfj-hd_2023-06-06.glb


BIN
public/model/glft/jbfj/jbfj-hd_2023-07-25.glb


BIN
public/model/hdr/test1.hdr


BIN
public/model/hdr/test2.hdr


+ 0 - 0
public/model/hdr/test1.jpeg → public/model/hdr/test2.jpeg


BIN
public/model/hdr/test3.hdr


+ 10 - 1
src/App.vue

@@ -9,7 +9,7 @@
 </template>
 
 <script lang="ts" setup>
-  import { ref, watch } from 'vue';
+  import { ref, watch, onUnmounted } from 'vue';
   import { ConfigProvider } from 'ant-design-vue';
   import { AppProvider } from '/@/components/Application';
   import { useTitle } from '/@/hooks/web/useTitle';
@@ -40,6 +40,15 @@
   })
 
   useTitle();
+
+
+  onUnmounted(() => {
+    window['renderer']?.dispose()
+    window['renderer']?.forceContextLoss()
+    if(window['renderer'])window['renderer'].content = null
+    const gl = window['renderer']?.domElement.getContext('webgl')
+    gl && gl.getExtension('WEBGL_lose_context').loseContext()
+  })
 </script>
 <style lang="less" scoped>
   #app {

BIN
src/assets/images/vent/alarm-icons/ccq.png


BIN
src/assets/images/vent/alarm-icons/cf.png


BIN
src/assets/images/vent/alarm-icons/fc.png


BIN
src/assets/images/vent/alarm-icons/fm.png


BIN
src/assets/images/vent/alarm-icons/js.png


BIN
src/assets/images/vent/alarm-icons/penfen.png


BIN
src/assets/images/vent/alarm-icons/penlin.png


BIN
src/assets/images/vent/alarm-icons/pw.png


BIN
src/assets/images/vent/alarm-icons/wasibeng.png


BIN
src/assets/images/vent/alarm-icons/wasichoucaig.png


BIN
src/assets/images/vent/alarm-icons/yafeng.png


BIN
src/assets/images/vent/alarm-icons/zhudan.png


BIN
src/assets/images/vent/alarm-icons/zhujiang.png


BIN
src/assets/images/vent/alarm-icons/zhushan.png


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

@@ -62,9 +62,7 @@
           feature: {
             saveAsImage: {
               iconStyle: {
-                normal: {
-                  borderColor: '#ffffff',
-                },
+                borderColor: '#ffffff',
               },
               show: true,
             },

+ 5 - 3
src/components/chart/BarSingle.vue

@@ -49,9 +49,7 @@
           feature: {
             saveAsImage: {
               iconStyle: {
-                normal: {
-                  borderColor: '#ffffff',
-                },
+                borderColor: '#ffffff',
               },
               show: true,
             },
@@ -70,13 +68,17 @@
       });
 
       function initChartsOption() {
+
         const optionUtil = new EchartsUtil(option);
         optionUtil.initChartOption('listMonitor', chartsColumns);
         console.log('option----------->', option);
       }
+
       initChartsOption();
 
       function initCharts() {
+        
+
         //轴数据
         if (option.series) {
           const xAxisData: string[] = [];

+ 1 - 1
src/components/vent/fourBorderBg.vue

@@ -29,7 +29,7 @@ export default defineComponent ({
     border: 1px solid #4D7AD855;
     border-radius: 2px;
     background-color: #001d3055;
-    backdrop-filter: blur(2px);
+    // backdrop-filter: blur(2px);
     box-shadow: 0 0 10px #5984E055 inset;
     padding: 5px 8px;
     color: #ffffffee;

+ 3 - 0
src/design/vent/comment.less

@@ -63,6 +63,9 @@
 .vent-margin-r-8 {
   margin-right: 8px;
 }
+.vent-margin-r-10 {
+  margin-right: 10px;
+}
 .vent-margin-r-5 {
   margin-right: 5px;
 }

+ 36 - 28
src/design/vent/modal.less

@@ -16,6 +16,9 @@
     top: 0;
     background: #09172c;
   }
+  .elementTag{
+    pointer-events: none !important;
+  }
   .threejs-Object-CSS {
     pointer-events: none;
     .elementContent {
@@ -166,6 +169,7 @@
       .detail-box {
         display: flex;
         flex-direction: row;
+        position: relative;
         .left-box {
           width: 164px;
           height: 152px;
@@ -362,33 +366,37 @@
   }
   .bottom-tabs-box {
     position: fixed;
-    width: calc(100% - 10px);
-    height: 240px;
-    bottom: 20px;
-    padding: 0 20px;
-    margin: 0 5px;
+    width: 100%;
+    height: 340px;
+    bottom: 5px;
+    // padding: 0 10px;
+    margin: 0px;
     pointer-events: auto;
 
-    &:before {
-      position: absolute;
-      content: '';
-      width: 34px;
-      height: 315px;
-      left: 0;
-      top: -19px;
-      background: url('/@/assets/images/vent/bottom-tabs-l.png') no-repeat;
-      background-size: contain;
-    }
-    &:after {
-      position: absolute;
-      content: '';
-      width: 34px;
-      height: 315px;
-      right: 0;
-      top: -19px;
-      background: url('/@/assets/images/vent/bottom-tabs-r.png') no-repeat;
-      background-size: contain;
-    }
+    // &:before {
+    //   position: absolute;
+    //   content: '';
+    //   width: 2px;
+    //   height: calc(100% + 55px);
+    //   left: 2px;
+    //   top: -19px;
+    //   background-image: linear-gradient(#00F7FF05, #00F7FF, #00F7FF05);
+    //   background-position: center;
+    //   // background: url('/@/assets/images/vent/bottom-tabs-l.png') no-repeat;
+    //   // background-size: contain;
+    // }
+    // &:after {
+    //   position: absolute;
+    //   content: '';
+    //   width: 2px;
+    //   height: calc(100% + 55px);
+    //   right: 7px;
+    //   top: -19px;
+    //   background-image: linear-gradient(#00F7FF05, #00F7FF, #00F7FF05);
+    //   background-position: center;
+    //   // background: url('/@/assets/images/vent/bottom-tabs-r.png') no-repeat;
+    //   // background-size: contain;
+    // }
     .tabs-button-group {
       position: absolute;
       display: flex;
@@ -403,7 +411,7 @@
     }
     :deep(.tabs-box) {
       position: absolute;
-      width: calc(100% - 46px);
+      width: calc(100%);
       bottom: 0px;
       height: calc(100% - 0px);
       pointer-events: auto;
@@ -411,8 +419,8 @@
       // background: linear-gradient(#00daff33, #2081ff11);
       background: linear-gradient(#0091aa33, #2081ff11);
       // background: radial-gradient(circle at 50% 80%, #3df6ff33, #0038b433);
-      backdrop-filter: blur(8px);
-      overflow-y: hidden;
+      backdrop-filter: blur(18px);
+      overflow-y: auto;
       border-radius: 8px;
       .tabs-box {
         height: 100%;

+ 1 - 1
src/hooks/core/useThree copy.ts

@@ -366,7 +366,7 @@ class UseThree {
       this.animationAction?.halt(0.5);
     }, 500);
   }
-  deleteModal() {
+  clearScene() {
     this.scene?.children.forEach((obj:any) => {
       if(obj.type === 'Group'){
         obj.traverse(function(item:any) {

+ 0 - 1
src/hooks/system/useListPage.ts

@@ -90,7 +90,6 @@ export function useListPage(options: ListPageOptions) {
       if (selectedRowKeys.value && selectedRowKeys.value.length > 0) {
         paramsForm['selections'] = selectedRowKeys.value.join(',');
       }
-      debugger
       return handleExportXls(title as string, realUrl, filterObj(paramsForm));
       //update-end---author:wangshuai ---date:20220411  for:导出新增自定义参数--------------
     } else {

+ 16 - 5
src/layouts/default/sider/bottomSideder.vue

@@ -75,7 +75,15 @@
             history.pushState({}, '', path.path);
           }
         } else {
-          go(path.path);
+          // micro-vent-3dModal 
+          debugger
+
+          if(route.path.startsWith('/subSysmodal/')) {
+            router.replace('/micro-vent-3dModal' + path.path)
+          }else{
+            go(path.path);
+          }
+          
         }
         isShowMenu.value = 0;
       }
@@ -142,7 +150,7 @@
         .main-container {
           background-color: #ffffff00 !important;
           box-shadow: 0 0 3px #ffffff33 inset;
-          backdrop-filter: blur(0px)
+          backdrop-filter: none !important;
         }
 
         .parent-menu {
@@ -154,7 +162,9 @@
         }
         .child-menu-item {
           width: 100px;
-          background-color: #086193;
+          padding: 2px 0;
+          // background-color: #086193;
+          background: linear-gradient(#0d435d, #0e729d);
           border-radius: 2px;
           display: flex;
           align-items: center;
@@ -163,7 +173,7 @@
           cursor: pointer;
           box-shadow: 0 0 3px #ffffff22 inset;
           &:hover {
-            background-color: #0676b5;
+            background: linear-gradient(#1d89bf, #17aeee);
           }
         }
       }
@@ -172,7 +182,8 @@
     .menu-button-group {
       margin: 5px 0;
       .program-menu {
-        width: 90px;
+        // width: 90px;
+        padding: 1px 15px;
         background:linear-gradient(#217aa5, #0f4f75);
         margin-left: 5px;
         text-align: center;

+ 0 - 1
src/layouts/iframe/index.vue

@@ -16,7 +16,6 @@
     components: { FramePage },
     setup() {
       const { getFramePages, hasRenderFrame, showIframe } = useFrameKeepAlive();
-
       const showFrame = computed(() => unref(getFramePages).length > 0);
 
       return { getFramePages, hasRenderFrame, showIframe, showFrame };

+ 8 - 1
src/layouts/iframe/useFrameKeepAlive.ts

@@ -11,6 +11,7 @@ import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';
 import { useRouter } from 'vue-router';
 
 export function useFrameKeepAlive() {
+
   const router = useRouter();
   const { currentRoute } = router;
   const { getShowMultipleTab } = useMultipleTabSetting();
@@ -49,10 +50,16 @@ export function useFrameKeepAlive() {
   }
 
   function hasRenderFrame(name: string) {
+
     if (!unref(getShowMultipleTab)) {
       return router.currentRoute.value.name === name;
     }
-    return unref(getOpenTabList).includes(name);
+    if (!unref(getOpenTabList)) {
+      return unref(getOpenTabList).includes(name);
+    }
+    if(router.currentRoute.value.meta.frameSrc){
+      return true
+    }
   }
 
   return { hasRenderFrame, getFramePages, showIframe, getAllFramePages };

+ 1 - 1
src/layouts/page/index.vue

@@ -22,7 +22,7 @@
         <!--      </transition>-->
       </template>
     </RouterView>
-    <FrameLayout v-if="getCanEmbedIFramePage" />
+    <FrameLayout v-if="getCanEmbedIFramePage" class="test" />
   </div>
 </template>
 

+ 7 - 0
src/main.ts

@@ -23,6 +23,7 @@ import { registerGlobComp } from '/@/components/registerGlobComp';
 import { registerThirdComp } from '/@/settings/registerThirdComp';
 import { useSso } from '/@/hooks/web/useSso';
 import { registerPackages } from '/@/utils/monorepo/registerPackages';
+import { initModalWorker, initTHREE } from '/@/utils/threejs/main.worker';
 // 在本地开发中引入的,以提高浏览器响应速度
 if (import.meta.env.DEV) {
   import('ant-design-vue/dist/antd.less');
@@ -66,6 +67,12 @@ async function bootstrap() {
 
   // 当路由准备好时再执行挂载( https://next.router.vuejs.org/api/#isready)
   await router.isReady();
+
+  initModalWorker();
+
+  initTHREE();
+
+
   // 挂载应用
   app.mount('#app', true);
 }

+ 8 - 5
src/router/helper/routeHelper.ts

@@ -8,10 +8,11 @@ import { createRouter, createWebHashHistory } from 'vue-router';
 import { getTenantId, getToken } from '/@/utils/auth';
 import { URL_HASH_TAB } from '/@/utils';
 import { packageViews } from '/@/utils/monorepo/dynamicRouter';
-import {useI18n} from "/@/hooks/web/useI18n";
+import { useI18n } from '/@/hooks/web/useI18n';
 
 export type LayoutMapKey = 'LAYOUT';
 const IFRAME = () => import('/@/views/sys/iframe/FrameBlank.vue');
+// const IFRAME = () => import('/@/views/sys/iframe/index.vue');
 const LayoutContent = () => import('/@/layouts/default/content/index.vue');
 
 const LayoutMap = new Map<string, () => Promise<typeof import('*.vue')>>();
@@ -32,17 +33,16 @@ function asyncImportRoute(routes: AppRouteRecordRaw[] | undefined) {
   }
   if (!routes) return;
   routes.forEach((item) => {
-
     //【jeecg-boot/issues/I5N2PN】左侧动态菜单怎么做国际化处理  2022-10-09
     //菜单支持国际化翻译
     if (item?.meta?.title) {
       const { t } = useI18n();
-      if(item.meta.title.includes('t(\'') && t){
+      if (item.meta.title.includes("t('") && t) {
         item.meta.title = eval(item.meta.title);
         //console.log('译后: ',item.meta.title)
       }
     }
-   
+
     // update-begin--author:sunjianlei---date:20210918---for:适配旧版路由选项 --------
     // @ts-ignore 适配隐藏路由
     if (item?.hidden) {
@@ -60,7 +60,10 @@ function asyncImportRoute(routes: AppRouteRecordRaw[] | undefined) {
     let tenantId = getTenantId();
     // URL支持{{ window.xxx }}占位符变量
     //update-begin---author:wangshuai ---date:20220711  for:[VUEN-1638]菜单tenantId需要动态生成------------
-    item.component = (item.component || '').replace(/{{([^}}]+)?}}/g, (s1, s2) => eval(s2)).replace('${token}', token).replace('${tenantId}', tenantId);
+    item.component = (item.component || '')
+      .replace(/{{([^}}]+)?}}/g, (s1, s2) => eval(s2))
+      .replace('${token}', token)
+      .replace('${tenantId}', tenantId);
     //update-end---author:wangshuai ---date:20220711  for:[VUEN-1638]菜单tenantId需要动态生成------------
     // 适配 iframe
     if (/^\/?http(s)?/.test(item.component as string)) {

+ 43 - 22
src/router/routes/basic.ts

@@ -80,28 +80,49 @@ export const QIANKUN_ROUTE: AppRouteRecordRaw = {
         hideMenu: true,
       },
     },
-    {
-      path: '/micro-vent-3dModal/:path(.*)*',
-      name: QIANKUN_ROUTE_NAME,
-      component: QIANKUN_COMPONENT,
-      meta: {
-        title: '子应用',
-        hideBreadcrumb: true,
-        hideMenu: true,
-      },
-      children: [
-        {
-          path: '/modelchannel/safety/VentanalyModel3D/:path(.*)*',//lxh
-          name: QIANKUN_ROUTE_NAME,
-          component: import('/@/views/demo/threejs/damper.vue'),
-          meta: {
-            title: '子应用',
-            hideBreadcrumb: true,
-            hideMenu: true,
-          },
-        },
-      ],
-    },
+    // {
+    //   path: '/micro-vent-3dModal/:path(.*)*',
+    //   name: QIANKUN_ROUTE_NAME,
+    //   component: QIANKUN_COMPONENT,
+    //   meta: {
+    //     title: '子应用',
+    //     hideBreadcrumb: true,
+    //     hideMenu: true,
+    //   },
+    //   children: [
+    //     {
+    //       path: '/modelchannel/safety/VentanalyModel3D/:path(.*)*', //lxh
+    //       name: QIANKUN_ROUTE_NAME,
+    //       component: import('/@/views/demo/threejs/damper.vue'),
+    //       meta: {
+    //         title: '子应用',
+    //         hideBreadcrumb: true,
+    //         hideMenu: true,
+    //       },
+    //     },
+    //     {
+    //       path: '/modelchannel/activiti/:path(.*)*',
+    //       name: QIANKUN_ROUTE_NAME,
+    //       component: LAYOUT,
+    //       meta: {
+    //         title: '子应用',
+    //         hideBreadcrumb: true,
+    //         hideMenu: true,
+    //       },
+    //       children: [
+    //         {
+    //           path: '/:path(.*)*',
+    //           name: QIANKUN_ROUTE_NAME,
+    //           meta: {
+    //             title: '',
+    //             hideBreadcrumb: true,
+    //             hideMenu: true,
+    //           },
+    //         },
+    //       ],
+    //     },
+    //   ],
+    // },
   ],
 };
 

+ 1 - 0
src/router/routes/modules/demo/iframe.ts

@@ -2,6 +2,7 @@ import type { AppRouteModule } from '/@/router/types';
 
 import { LAYOUT } from '/@/router/constant';
 const IFrame = () => import('/@/views/sys/iframe/FrameBlank.vue');
+// const IFrame = () => import('/@/views/sys/iframe/index.vue');
 import { t } from '/@/hooks/web/useI18n';
 
 const iframe: AppRouteModule = {

+ 1 - 1
src/settings/projectSetting.ts

@@ -186,7 +186,7 @@ const setting: ProjectConfig = {
 
   // 切换界面的时候是否取消已经发送但是未响应的http请求。
   // 如果开启,想对单独接口覆盖。可以在单独接口设置
-  removeAllHttpPending: false,
+  removeAllHttpPending: true,
 };
 
 export default setting;

+ 2 - 0
src/utils/echartsUtil.ts

@@ -57,10 +57,12 @@ export default class echartsUtil {
     dataZoom = this.getDataZoom(type);
 
     if (this.option) {
+      if (!this.option['tooltip']) this.option['tooltip'] = {};
       Object.assign(this.option['tooltip'], tooltip);
       // this.option['tooltip'] = tooltip;
       this.option['grid'] = grid;
       // this.option['legend'] = this.getLegend(legends);
+      if (!this.option['legend']) this.option['legend'] = {};
       Object.assign(this.option['legend'], this.getLegend(legends));
       this.option['xAxis'] = xAxis;
       this.option['yAxis'] = yAxis;

+ 6 - 3
src/utils/event/index.ts

@@ -43,32 +43,35 @@ export function triggerWindowResize() {
 
 export function setDivHeight(e: MouseEvent, minHeight, scroll) {
   e.preventDefault();
+  e.stopPropagation();
   const divObject = e.currentTarget as HTMLElement;
   if (divObject) {
     const divHeight = divObject.offsetHeight;
     let height = divHeight;
     const startY = e.clientY;
+    let isMove = false;
     document.onmousemove = function (res) {
       res.preventDefault();
+      isMove = true;
       const distY = Math.abs(res.clientY - startY);
       if (res.clientY > startY) {
         if (divHeight - distY >= minHeight) {
           height = divHeight - distY;
-        } else {
+        } else if (divHeight - distY < minHeight) {
           height = minHeight;
         }
       }
       if (res.clientY < startY) {
         height = divHeight + distY;
       }
+      if (height > document.body.clientHeight - 175) height = document.body.clientHeight - 175;
       divObject.style.height = height + 'px';
     };
     document.onmouseup = function () {
       document.onmousemove = null;
-      if (scroll.y != height - 100) {
+      if (isMove && scroll.y != height - 100) {
         scroll.y = height - 100;
       }
-      console.log('scroll.y-------------->', scroll.y);
     };
   }
 }

+ 34 - 34
src/utils/http/axios/axiosCancel.ts

@@ -1,60 +1,60 @@
-import type { AxiosRequestConfig, Canceler } from 'axios';
-import axios from 'axios';
-import { isFunction } from '/@/utils/is';
+import type { AxiosRequestConfig } from 'axios';
 
-// Used to store the identification and cancellation function of each request
-let pendingMap = new Map<string, Canceler>();
+// 用于存储每个请求的标识和取消函数
+const pendingMap = new Map<string, AbortController>();
 
-export const getPendingUrl = (config: AxiosRequestConfig) => [config.method, config.url].join('&');
+const getPendingUrl = (config: AxiosRequestConfig): string => {
+  return [config.method, config.url].join('&');
+};
 
 export class AxiosCanceler {
   /**
-   * Add request
-   * @param {Object} config
+   * 添加请求
+   * @param config 请求配置
    */
-  addPending(config: AxiosRequestConfig) {
+  public addPending(config: AxiosRequestConfig): void {
     this.removePending(config);
-    const url = getPendingUrl(config);
-    config.cancelToken =
-      config.cancelToken ||
-      new axios.CancelToken((cancel) => {
-        if (!pendingMap.has(url)) {
-          // If there is no current request in pending, add it
-          pendingMap.set(url, cancel);
-        }
-      });
+    const url = getPendingUrl(config) +'_'+ new Date().getTime();
+    const controller = new AbortController();
+    config.signal = config.signal || controller.signal;
+    if (!pendingMap.has(url)) {
+      // 如果当前请求不在等待中,将其添加到等待中
+      pendingMap.set(url, controller);
+    }
   }
 
   /**
-   * @description: Clear all pending
+   * 清除所有等待中的请求
    */
-  removeAllPending() {
-    pendingMap.forEach((cancel) => {
-      cancel && isFunction(cancel) && cancel();
+  public removeAllPending(): void {
+    pendingMap.forEach((abortController) => {
+      if (abortController) {
+        abortController.abort();
+      }
     });
-    pendingMap.clear();
+    this.reset();
   }
 
   /**
-   * Removal request
-   * @param {Object} config
+   * 移除请求
+   * @param config 请求配置
    */
-  removePending(config: AxiosRequestConfig) {
+  public removePending(config: AxiosRequestConfig): void {
     const url = getPendingUrl(config);
-
     if (pendingMap.has(url)) {
-      // If there is a current request identifier in pending,
-      // the current request needs to be cancelled and removed
-      const cancel = pendingMap.get(url);
-      cancel && cancel(url);
+      // 如果当前请求在等待中,取消它并将其从等待中移除
+      const abortController = pendingMap.get(url);
+      if (abortController) {
+        abortController.abort(url);
+      }
       pendingMap.delete(url);
     }
   }
 
   /**
-   * @description: reset
+   * 重置
    */
-  reset(): void {
-    pendingMap = new Map<string, Canceler>();
+  public reset(): void {
+    pendingMap.clear();
   }
 }

+ 2 - 1
src/utils/lib/echarts.ts

@@ -1,6 +1,6 @@
 import * as echarts from 'echarts/core';
 
-import { BarChart, LineChart, PieChart, MapChart, PictorialBarChart, RadarChart, GaugeChart } from 'echarts/charts';
+import { BarChart, LineChart, PieChart, MapChart, PictorialBarChart, RadarChart, GaugeChart, ScatterChart } from 'echarts/charts';
 
 import {
   TitleComponent,
@@ -47,6 +47,7 @@ echarts.use([
   TimelineComponent,
   CalendarComponent,
   GraphicComponent,
+  ScatterChart,
 ]);
 
 export default echarts;

+ 34 - 7
src/utils/threejs/main.worker.ts

@@ -1,6 +1,8 @@
 import modalWorker from './loadGltf.worker?worker';
 import Dexie from 'dexie';
 import { useModelStore } from '/@/store/modules/threejs';
+import * as THREE from 'three';
+import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
 
 export function initModalWorker() {
   type model = {
@@ -13,8 +15,8 @@ export function initModalWorker() {
     'fm/Fm-door_2023-06-02.glb',
     'fm/Fm-wire_2023-06-02.glb',
     'fm/Fm-wall_2023-06-02.glb',
-    'fm/fmThree_2023-07-13.glb',
-    'fm/fmThreeBase_2023-07-13.glb',
+    'fm/fmThree_2023-07-25.glb',
+    'fm/fmThreeBase_2023-07-25.glb',
     'fc/sdFc_2023-06-02.glb',
     'fc/ddFc_2023-06-02.glb',
     'cf/lmcf_2023-06-02.glb',
@@ -25,7 +27,7 @@ export function initModalWorker() {
     'cf/ddcf_2023-07-13.glb',
     'cf/dsmove_2023-06-02.glb',
 
-    'jbfj/jbfj-hd_2023-06-06.glb',
+    'jbfj/jbfj-hd_2023-07-25.glb',
 
     'jbfj/jbfj-fm_2023-06-02.glb',
     'jbfj/jbfj-fc_2023-06-02.glb',
@@ -40,11 +42,12 @@ export function initModalWorker() {
     'fire/laneway_2023-06-02.glb',
     'fire/chamber_2023-06-02.glb',
     'fire/workFace_2023-06-29.glb',
-    'fire/tunFace_2023-07-08.glb',
+    'fire/tunFace_2023-07-14.glb',
     'fire/nitrogen_2023-06-02.glb',
     'fire/grout_2023-06-02.glb',
-    'fire/balancePress_2023-07-08.glb',
+    'fire/balancePress_2023-07-20.glb',
     'yafeng/compressor_2023-07-10.glb',
+    'gas/gasPump_2023-07-25.glb',
   ];
 
   const db: any = new Dexie('DB');
@@ -80,7 +83,7 @@ export function initModalWorker() {
               modalVal: modalArr[0].modalVal,
               version: modalArr[0].versionStr,
             };
-            modelStore.setModel(model);
+            // modelStore.setModel(model);
           }
         } else {
           // 版本不一致,删除模型,重新下载
@@ -108,4 +111,28 @@ export function initModalWorker() {
   });
 }
 
-initModalWorker();
+export function initTHREE() {
+  if (!window['$renderer']) {
+    const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true, logarithmicDepthBuffer: true }) as THREE.WebGLRenderer;
+    renderer?.setPixelRatio(window.devicePixelRatio);
+    renderer.toneMapping = THREE.ACESFilmicToneMapping;
+    // renderer.shadowMap.enabled = true;
+    renderer.toneMappingExposure = 1;
+    // renderer.outputColorSpace= THREE.SRGBColorSpace;
+    renderer.setClearAlpha(0);
+    //renderer.shadowMap.type = THREE.PCFSoftShadowMap;
+    //renderer.physicallyCorrectLights = true;
+
+    window['$renderer'] = renderer;
+  }
+
+  if (!window['$camera']) {
+    const camera = new THREE.PerspectiveCamera(50, document.body.clientWidth / document.body.clientHeight, 0.0000001, 1000);
+    window['$camera'] = camera;
+  }
+
+  if (!window['$orbitControls']) {
+    const orbitControls = new OrbitControls(window['$camera'] as THREE.Camera, window['$renderer']?.domElement) as OrbitControls;
+    window['$orbitControls'] = orbitControls;
+  }
+}

+ 133 - 23
src/utils/threejs/useEvent.ts

@@ -5,12 +5,15 @@ import gsap from 'gsap';
 
 export default function useEvent() {
   let point = <THREE.Vector3 | null>null;
+  let intersect0: THREE.Intersection | null | undefined;
 
-  const mouseDownFn = (modal: UseThree, group: THREE.Object3D, event: MouseEvent, callBack?: Function) => {
+  let startTime: number = 0;
+  const mouseDownFn = (modal: UseThree, group: THREE.Object3D | THREE.Object3D[], event: MouseEvent, callBack?: Function) => {
+    event.stopPropagation();
+    event.preventDefault();
     if (!modal || !modal.canvasContainer || !modal.orbitControls) return;
     const appStore = useAppStore();
-    // event.stopPropagation();
-    // event.preventDefault();
+
     const widthScale = appStore.getWidthScale;
     const heightScale = appStore.getHeightScale;
     // 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)
@@ -19,11 +22,21 @@ export default function useEvent() {
     modal.mouse.y =
       -((-modal.canvasContainer.getBoundingClientRect().top + event.clientY) / (modal.canvasContainer.clientHeight * heightScale)) * 2 + 1;
     (modal.rayCaster as THREE.Raycaster).setFromCamera(modal.mouse, modal.camera as THREE.Camera);
-
+    startTime = new Date().getTime();
     if (group) {
-      const intersects = modal.rayCaster?.intersectObjects(group.children, true) as THREE.Intersection[];
+      let intersects = <THREE.Intersection[]>[];
+      if (Object.prototype.toString.call(group) === '[object Array]') {
+        intersects = modal.rayCaster?.intersectObjects([...(group as THREE.Object3D[])], true) as THREE.Intersection[];
+      } else {
+        intersects = modal.rayCaster?.intersectObjects((group as THREE.Object3D).children, true) as THREE.Intersection[];
+      }
       if (intersects.length > 0) {
-        point = intersects[0].point.clone();
+        intersect0 = intersects.find((item) => {
+          if (item.object && item.object.type !== 'point') {
+            return true;
+          }
+          return false;
+        });
         if (callBack) callBack(intersects);
       }
     }
@@ -33,25 +46,122 @@ export default function useEvent() {
     point = null;
   };
 
-  const mouseUpFn = (modal) => {
-    if (point) {
-      const target0 = modal.orbitControls.target.clone();
-      // gsap.fromTo(
-      //   modal.orbitControls.target,
-      //   { x: target0.x, y: target0.y, z: target0.z },
-      //   {
-      //     x: point.x,
-      //     y: point.y,
-      //     z: point.z,
-      //     duration: 0.4,
-      //     ease: 'easeInCirc',
-      //     onUpdate: function (object) {
-      //       if (object) modal.camera?.lookAt(new THREE.Vector3(object.x, object.y, object.z));
-      //     },
+  const mouseUpFn = (modal, minDistance = 5, renderCallBack?) => {
+    const endTime = new Date().getTime();
+    if (endTime - startTime > 400) {
+      intersect0 = null;
+    }
+    if (intersect0) {
+      const point = intersect0.point;
+      const target0 = <THREE.Vector3>modal.orbitControls.target.clone();
+      const oldCameraPosition = <THREE.Vector3>modal.camera.position.clone();
+
+      const nor = point.clone().sub(oldCameraPosition.clone()).normalize();
+      const d = intersect0?.distance;
+
+      const animateObj = {
+        x1: target0.x, // 相机x
+        y1: target0.y, // 相机y
+        z1: target0.z, // 相机z
+        x2: oldCameraPosition.x, // 相机x
+        y2: oldCameraPosition.y, // 相机y
+        z2: oldCameraPosition.z, // 相机z
+      };
+      let newAnimateObj;
+
+      if (oldCameraPosition.z > target0.z) {
+        newAnimateObj = {
+          x1: point.x,
+          y1: point.y,
+          z1: point.z,
+          x2: point.x,
+          y2: Math.abs(nor.y) * d * 0.1 + point.y,
+          z2: Math.abs(nor.z) * d * 0.3 + point.z,
+        };
+      } else {
+        newAnimateObj = {
+          x1: point.x,
+          y1: point.y,
+          z1: point.z,
+          x2: point.x,
+          y2: Math.abs(nor.y) * d * 0.1 + point.y,
+          z2: -Math.abs(nor.z) * d * 0.3 + point.z,
+        };
+      }
+
+      // if (Math.abs(nor.z) * 0.2 * d > minDistance) {
+      //   if (oldCameraPosition.z > target0.z) {
+      //     newAnimateObj = {
+      //       x1: point.x,
+      //       y1: point.y,
+      //       z1: point.z,
+      //       x2: point.x,
+      //       y2: Math.abs(nor.y) * d * 0.2 + point.y,
+      //       z2: Math.abs(nor.z) * d * 0.2 + point.z,
+      //     };
+      //   } else {
+      //     newAnimateObj = {
+      //       x1: point.x,
+      //       y1: point.y,
+      //       z1: point.z,
+      //       x2: point.x,
+      //       y2: Math.abs(nor.y) * d * 0.2 + point.y,
+      //       z2: -Math.abs(nor.z) * d * 0.2 + point.z,
+      //     };
       //   }
-      // );
+      // } else {
+      //   if (oldCameraPosition.z > target0.z) {
+      //     newAnimateObj = {
+      //       x1: point.x,
+      //       y1: point.y,
+      //       z1: point.z,
+      //       x2: point.x,
+      //       y2: (minDistance * Math.abs(nor.y)) / Math.abs(nor.z) + point.y,
+      //       z2: minDistance + point.z,
+      //     };
+      //   } else {
+      //     newAnimateObj = {
+      //       x1: point.x,
+      //       y1: point.y,
+      //       z1: point.z,
+      //       x2: point.x,
+      //       y2: (minDistance * Math.abs(nor.y)) / -Math.abs(nor.z) + point.y,
+      //       z2: -minDistance + point.z,
+      //     };
+      //   }
+      // }
+
+      modal.orbitControls.renderEnabled = false;
+      modal.orbitControls.enabled = false;
+      gsap.fromTo(
+        animateObj,
+        {
+          x1: target0.x, // 相机x
+          y1: target0.y, // 相机y
+          z1: target0.z, // 相机z
+          x2: oldCameraPosition.x, // 相机x
+          y2: oldCameraPosition.y, // 相机y
+          z2: oldCameraPosition.z, // 相机z
+        },
+        {
+          ...newAnimateObj,
+          duration: 1,
+          ease: 'easeInCirc',
+          onUpdate: function (object) {
+            modal.orbitControls.target.set(object.x1, object.y1, object.z1);
+            modal.camera.position.set(object.x2, object.y2, object.z2);
+            if (renderCallBack) renderCallBack();
+          },
+          onUpdateParams: [animateObj],
+          onComplete: function () {
+            modal.orbitControls.renderEnabled = true;
+            modal.orbitControls.enabled = true;
+          },
+        }
+      );
     }
-    console.log('摄像头控制信息', modal.orbitControls, modal.camera);
+
+    console.log('摄像机信息------->', modal.camera, modal.orbitControls);
   };
 
   return { mouseDownFn, mouseUpFn, mousemoveFn };

+ 212 - 185
src/utils/threejs/useThree.ts

@@ -1,20 +1,19 @@
 import * as THREE from 'three';
-import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader.js';
 // 导入轨道控制器
 import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
 import { CSS3DRenderer } from 'three/examples/jsm/renderers/CSS3DRenderer.js';
 import { CSS2DRenderer } from 'three/examples/jsm/renderers/CSS2DRenderer.js';
-// import gsap from 'gsap';
-import ResourceTracker from '/@/utils/threejs/ResourceTracker.js';
 import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
-import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader.js';
+// import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader.js';
 import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
 import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js';
 import { FXAAShader } from 'three/examples/jsm/shaders/FXAAShader.js';
 import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js';
 import Stats from 'three/examples/jsm/libs/stats.module.js';
 import { useModelStore } from '/@/store/modules/threejs';
-import { TWEEN } from 'three/examples/jsm/libs/tween.module.min.js';
+import TWEEN from 'three/examples/jsm/libs/tween.module.js';
+import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader.js';
+
 // import * as dat from 'dat.gui';
 // const gui = new dat.GUI();
 // gui.domElement.style = 'position:absolute;top:10px;left:10px;z-index:99999999999999';
@@ -34,20 +33,20 @@ class UseThree {
   clock: THREE.Clock | null = new THREE.Clock(); // 计时器
   timeoutId: NodeJS.Timeout | null = null;
   animationId = 0;
+  isRender = true;
   spriteText: THREE.Sprite | null = null;
   mouse = new THREE.Vector2();
   rayCaster: THREE.Raycaster | null = null;
   animations: THREE.AnimationClip[] = [];
   mixers: THREE.AnimationMixer[] = [];
-  renderT = 1 / 60;
+  renderT = 1 / 40;
   timeS = 0;
-  resourceTracker: ResourceTracker | null = null;
   track: any = null;
   composer; //后期
   timeOut: NodeJS.Timeout | null = null; //
+  textureMap = new Map<string, THREE.Texture>();
 
   constructor(canvasSelector, css3Canvas?, css2Canvas?) {
-    this.animationId = 0;
     this.canvasContainer = document.querySelector(canvasSelector);
     //初始化
     this.init(css3Canvas, css2Canvas);
@@ -105,8 +104,17 @@ class UseThree {
   }
 
   initCamera() {
-    this.camera = new THREE.PerspectiveCamera(50, this.canvasContainer.clientWidth / this.canvasContainer.clientHeight, 0.0000001, 1000);
-    this.camera.layers.enableAll();
+    // this.camera = new THREE.PerspectiveCamera(50, this.canvasContainer.clientWidth / this.canvasContainer.clientHeight, 0.0000001, 1000);
+    if (!window['$camera']) {
+      throw new Error('threejs摄像头初始化异常!');
+    } else {
+      this.camera = window['$camera'] as THREE.PerspectiveCamera;
+      this.camera.layers.enableAll();
+      if (this.canvasContainer) this.camera.aspect = this.canvasContainer.clientWidth / this.canvasContainer.clientHeight;
+      this.camera.near = 0.0000001;
+      this.camera.far = 1000;
+    }
+
     //
     // const helper = new THREE.CameraHelper(this.camera);
     // this.scene?.add(helper);
@@ -119,28 +127,19 @@ class UseThree {
   }
 
   initRenderer() {
-    this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true, logarithmicDepthBuffer: true }) as THREE.WebGLRenderer;
-    // 设置屏幕像素比
-    this.renderer?.setPixelRatio(window.devicePixelRatio);
-    // 设置渲染的尺寸
-    this.renderer?.setSize(this.canvasContainer.clientWidth, this.canvasContainer.clientHeight);
-    // 色调映射
-    this.renderer.toneMapping = THREE.ACESFilmicToneMapping;
-
-    this.renderer.outputEncoding = THREE.sRGBEncoding;
-    // this.renderer.sortObjects = false;
-
-    this.renderer.shadowMap.enabled = true;
-
-    // 曝光程度
-    this.renderer.toneMappingExposure = 1;
-
-    this.renderer.setClearAlpha(0);
-
-    // this.renderer.physicallyCorrectLights = true;
-    // this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
-
-    this.canvasContainer?.appendChild(this.renderer.domElement);
+    if (!window['$renderer']) {
+      throw new Error('threejs渲染器初始化异常!');
+    } else {
+      this.renderer = window['$renderer'];
+      if (this.canvasContainer) {
+        this.renderer.toneMappingExposure = 1.0;
+        // const gl = this.renderer?.getContext('webgl');
+        // gl && gl.getExtension('WEBGL_lose_context')?.restoreContext();
+        // this.renderer?.forceContextRestore()
+        this.renderer?.setSize(this.canvasContainer.clientWidth, this.canvasContainer.clientHeight);
+        this.canvasContainer.appendChild(this.renderer.domElement);
+      }
+    }
   }
 
   initCSS3Renderer(cssCanvas) {
@@ -171,11 +170,20 @@ class UseThree {
   }
 
   initControles() {
-    this.orbitControls = new OrbitControls(this.camera as THREE.Camera, this.renderer?.domElement) as OrbitControls;
+    if (!window['$orbitControls']) {
+      throw new Error('threejs控制器初始化异常!');
+    } else {
+      this.orbitControls = window['$orbitControls'];
+      this.orbitControls.panSpeed = 1;
+      this.orbitControls.rotateSpeed = 1;
+      this.orbitControls.maxPolarAngle = Math.PI;
+      this.orbitControls.minPolarAngle = 0;
+    }
+    // this.orbitControls = new OrbitControls(this.camera as THREE.Camera, this.renderer?.domElement) as OrbitControls;
     // this.orbitControls.update();
     // this.orbitControls.minDistance = 1;
     // this.orbitControls.maxDistance = 100;
-    // this.orbitControls.enableDamping = true;
+    // this.orbitControls.maxDistance = true;
   }
 
   setGLTFModel(modalNames, group = null) {
@@ -206,7 +214,12 @@ class UseThree {
               let modalValue;
               if (!data) {
                 const modalArr = await db.modal.where('modalName').equals(modalNameStr).toArray();
-                if (modalArr.length > 0) modalValue = modalArr[0].modalVal;
+                if (modalArr.length > 0) {
+                  modalValue = modalArr[0].modalVal;
+                } else {
+                  // 开启线程下载
+                  console.log('需要开启线程下载模型资源。。。。。');
+                }
               } else {
                 modalValue = data.modalVal;
               }
@@ -274,89 +287,89 @@ class UseThree {
     });
   }
 
-  setFBXModel(modalNames, group = null) {
-    window['startTime'] = new Date().getTime();
-    const modelStore = useModelStore();
-    return new Promise(async (resolve, reject) => {
-      try {
-        const fbxLoader = new FBXLoader();
-
-        fbxLoader.setPath('/model/fbx/');
-
-        const db = window['CustomDB'];
-        const resolvePromise: Promise<any>[] = [];
-
-        let modalNameArr = Object.prototype.toString.call(modalNames) === '[object Array]' ? modalNames : [modalNames];
-        let len = modalNameArr.length;
-
-        for (let i = 0; i < len; i++) {
-          resolvePromise[i] = new Promise(async (childResolve, reject) => {
-            try {
-              // 解析模型
-              let modalValue;
-              const modalNameStr = modalNameArr[i];
-              let data = modelStore.modelArr.get(modalNameStr) || null;
-              if (!data) {
-                const modalArr = await db.modal.where('modalName').equals(modalNameStr).toArray();
-                if (modalArr.length > 0) modalValue = modalArr[0].modalVal;
-              } else {
-                modalValue = data.modalVal;
-              }
-              if (modalValue) {
-                const object = fbxLoader.parse(modalValue, '/model/fbx/');
-                // const object = fbx.scene;
-                // setModalCenter(object);
-                if (object) {
-                  object.traverse((obj) => {
-                    if (obj instanceof THREE.Mesh) {
-                      obj.material.emissiveIntensity = 1;
-                      obj.material.emissiveMap = obj.material.map;
-                      obj.material.blending = THREE.CustomBlending;
-                      if (obj.material.opacity < 1) {
-                        obj.material.transparent = true;
-                      }
-                      if (obj.material.map) {
-                        obj.material.map.encoding = THREE.sRGBEncoding;
-                        obj.material.map.flipY = false;
-                        obj.material.map.anisotropy = 1;
-                      }
-                      if (obj.material.emissiveMap) {
-                        obj.material.emissiveMap.encoding = THREE.sRGBEncoding;
-                        obj.material.emissiveMap.flipY = false;
-                      }
-
-                      if (obj.material.map || obj.material.emissiveMap) {
-                        obj.material.needsUpdate = true;
-                      }
-
-                      // if (envMap) {
-                      //   obj.material.envMap = envMap;
-                      //   obj.material.envMapIntensity = 1;
-                      // }
-                      // obj.renderOrder = 1;
-                    }
-                  });
-                  object.animations = object.animations;
-                  object.name = modalNameStr;
-                  group?.add(object);
-                  childResolve(object);
-                }
-              }
-            } catch (error) {
-              console.log(error);
-              reject();
-            }
-          });
-        }
-
-        Promise.all(resolvePromise).then((objects) => {
-          resolve(objects);
-        });
-      } catch (error) {
-        reject('加载模型出错');
-      }
-    });
-  }
+  // setFBXModel(modalNames, group = null) {
+  //   window['startTime'] = new Date().getTime();
+  //   const modelStore = useModelStore();
+  //   return new Promise(async (resolve, reject) => {
+  //     try {
+  //       const fbxLoader = new FBXLoader();
+
+  //       fbxLoader.setPath('/model/fbx/');
+
+  //       const db = window['CustomDB'];
+  //       const resolvePromise: Promise<any>[] = [];
+
+  //       let modalNameArr = Object.prototype.toString.call(modalNames) === '[object Array]' ? modalNames : [modalNames];
+  //       let len = modalNameArr.length;
+
+  //       for (let i = 0; i < len; i++) {
+  //         resolvePromise[i] = new Promise(async (childResolve, reject) => {
+  //           try {
+  //             // 解析模型
+  //             let modalValue;
+  //             const modalNameStr = modalNameArr[i];
+  //             let data = modelStore.modelArr.get(modalNameStr) || null;
+  //             if (!data) {
+  //               const modalArr = await db.modal.where('modalName').equals(modalNameStr).toArray();
+  //               if (modalArr.length > 0) modalValue = modalArr[0].modalVal;
+  //             } else {
+  //               modalValue = data.modalVal;
+  //             }
+  //             if (modalValue) {
+  //               const object = fbxLoader.parse(modalValue, '/model/fbx/');
+  //               // const object = fbx.scene;
+  //               // setModalCenter(object);
+  //               if (object) {
+  //                 object.traverse((obj) => {
+  //                   if (obj instanceof THREE.Mesh) {
+  //                     obj.material.emissiveIntensity = 1;
+  //                     obj.material.emissiveMap = obj.material.map;
+  //                     obj.material.blending = THREE.CustomBlending;
+  //                     if (obj.material.opacity < 1) {
+  //                       obj.material.transparent = true;
+  //                     }
+  //                     if (obj.material.map) {
+  //                       obj.material.map.encoding = THREE.sRGBEncoding;
+  //                       obj.material.map.flipY = false;
+  //                       obj.material.map.anisotropy = 1;
+  //                     }
+  //                     if (obj.material.emissiveMap) {
+  //                       obj.material.emissiveMap.encoding = THREE.sRGBEncoding;
+  //                       obj.material.emissiveMap.flipY = false;
+  //                     }
+
+  //                     if (obj.material.map || obj.material.emissiveMap) {
+  //                       obj.material.needsUpdate = true;
+  //                     }
+
+  //                     // if (envMap) {
+  //                     //   obj.material.envMap = envMap;
+  //                     //   obj.material.envMapIntensity = 1;
+  //                     // }
+  //                     // obj.renderOrder = 1;
+  //                   }
+  //                 });
+  //                 object.animations = object.animations;
+  //                 object.name = modalNameStr;
+  //                 group?.add(object);
+  //                 childResolve(object);
+  //               }
+  //             }
+  //           } catch (error) {
+  //             console.log(error);
+  //             reject();
+  //           }
+  //         });
+  //       }
+
+  //       Promise.all(resolvePromise).then((objects) => {
+  //         resolve(objects);
+  //       });
+  //     } catch (error) {
+  //       reject('加载模型出错');
+  //     }
+  //   });
+  // }
 
   setTestPlane() {
     const plane = new THREE.Mesh(new THREE.PlaneGeometry(10, 10), new THREE.MeshPhongMaterial({ color: 0x999999, specular: 0x101010 }));
@@ -376,14 +389,12 @@ class UseThree {
 
   /* 场景环境背景 */
   setEnvMap(hdr) {
-    const pmremGenerator = new THREE.PMREMGenerator(this.renderer as THREE.WebGLRenderer); // 使用hdr作为背景色
-    pmremGenerator.compileEquirectangularShader();
-    new THREE.TextureLoader().setPath('/model/hdr/').load(hdr + '.jpeg', (texture) => {
-      texture.encoding = THREE.sRGBEncoding;
+    // (this.scene as THREE.Scene).environment
+    new RGBELoader().setPath('/model/hdr/').load(hdr + '.hdr', (texture) => {
+      texture.colorSpace = THREE.SRGBColorSpace;
       texture.mapping = THREE.EquirectangularReflectionMapping;
-      const envMap = pmremGenerator.fromEquirectangular(texture).texture;
-      (this.scene as THREE.Scene).environment = envMap;
-      pmremGenerator.dispose();
+      (this.scene as THREE.Scene).environment = texture;
+      texture.dispose();
     });
   }
 
@@ -417,24 +428,25 @@ class UseThree {
   renderAnimationScene() {}
 
   animate() {
-    if (this.animationId != -1) {
+    if (this.isRender) {
       this.animationId = requestAnimationFrame(this.animate.bind(this));
-      // const T = this.clock?.getDelta() || 0;
-      // this.timeS = this.timeS + T;
-      // if (this.timeS > this.renderT) {
-      //   this.stats?.update();
-      //   // this.renderAnimationScene();
-      //   if (this.renderEnabled) {
-      //     this.render();
-      //   }
-      //   this.timeS = 0;
-      // }
-      this.stats?.update();
-      TWEEN.update();
-      // this.renderAnimationScene();
-      if (this.renderEnabled) {
-        this.render();
+      const T = this.clock?.getDelta() || 0;
+      this.timeS = this.timeS + T;
+      if (this.timeS > this.renderT) {
+        // this.renderAnimationScene();
+
+        if (this.renderEnabled) {
+          this.render();
+        }
+        this.stats?.update();
+        this.timeS = 0;
       }
+      // this.stats?.update();
+      // // TWEEN.update();
+      // // this.renderAnimationScene();
+      // if (this.renderEnabled) {
+      //   this.render();
+      // }
     }
   }
 
@@ -462,60 +474,77 @@ class UseThree {
     }, 500);
   }
 
+  clearMesh(item) {
+    item.geometry?.dispose();
+    if (item.material) {
+      const material = item.material;
+
+      for (const key of Object.keys(material)) {
+        const value = material[key];
+        // if (value && typeof value === 'object' && 'minFilter' in value) {
+        //   // this.textureMap.set(value.uuid, value);
+        //   value.dispose();
+        // }
+        if (value && typeof value === 'object' && value['dispose'] && typeof value['dispose'] === 'function') {
+          value.dispose();
+        }
+      }
+      material.dispose();
+    }
+    if (item.texture) {
+      item.texture.dispose();
+    }
+  }
   clearGroup(group) {
-    const clearCache = (item) => {
-      item.geometry?.dispose();
-      item.material?.dispose();
-    };
     const removeObj = (obj) => {
-      if (obj?.children && obj?.children.length > 0) {
+      if (obj && obj?.children && obj?.children.length > 0) {
         for (let i = obj?.children.length - 1; i >= 0; i--) {
           const item = obj?.children[i];
-          if (item.children.length > 0) {
+          if (item && item.children && item.children.length > 0) {
             removeObj(item);
+            item?.clear();
           } else {
-            clearCache(item);
-            item.clear();
+            if (item) {
+              if (item.parent) item.parent.remove(item);
+              this.clearMesh(item);
+              item.clear();
+            }
           }
         }
       }
-      obj?.removeFromParent();
-      obj?.clear();
     };
     removeObj(group);
   }
 
-  deleteModal() {
+  clearScene() {
+    this.clearGroup(this.scene);
+    // console.log('场景纹理数量----------->', this.textureMap.size);
+    this.textureMap.forEach((texture) => {
+      texture?.dispose();
+    });
+    this.textureMap.clear();
+  }
+
+  destroy() {
+    TWEEN.getAll().forEach((item) => {
+      item.stop();
+    });
+    TWEEN.removeAll();
+    this.isRender = false;
     cancelAnimationFrame(this.animationId);
-    this.animationId = -1;
-    for (let i = this.scene?.children.length - 1; i > -1; i--) {
-      const obj: any = this.scene?.children[i];
-      if (obj.type === 'Group') {
-        this.clearGroup(obj);
-      } else if (obj.type === 'Mesh') {
-        if (obj.material) {
-          obj.material.dispose();
-        } else if (obj.geometry) {
-          obj.geometry.dispose();
-        }
-        obj.clear();
-      }
-      obj.removeFromParent();
-      this.scene?.remove(obj);
-    }
+    this.clearScene();
+    window.removeEventListener('resize', this.resizeRenderer);
+    // this.orbitControls?.dispose();
+    this.scene?.environment?.dispose();
+    this.scene?.clear();
+    this.renderer?.dispose();
+    this.renderer?.getRenderTarget()?.dispose();
 
+    if (this.renderer && this.canvasContainer) this.canvasContainer.innerHTML = '';
+    if (this.CSSCanvasContainer && this.css3dRender) this.CSSCanvasContainer.innerHTML = '';
+
+    // if (this.renderer) this.renderer.domElement = null;
     this.renderer?.clear();
-    this.renderer?.dispose();
-    this.renderer?.forceContextLoss();
-    const gl = this.renderer?.getContext('webgl');
-    gl && gl.getExtension('WEBGL_lose_context')?.loseContext();
-    if (this.renderer && this.canvasContainer) this.canvasContainer?.removeChild(this.renderer?.domElement as Node);
-    // const glCss = this.css3dRender?.getContext('webgl');
-    // glCss && glCss.getExtension('WEBGL_lose_context')?.loseContext();
-    if (this.CSSCanvasContainer && this.css3dRender) this.CSSCanvasContainer.removeChild(this.css3dRender?.domElement as Node);
-    this.camera = null;
-    this.orbitControls = null;
-    if (this.renderer) this.renderer.domElement = null;
 
     if (this.css3dRender) this.css3dRender.domElement = null;
     if (this.css2dRender) this.css2dRender.domElement = null;
@@ -523,17 +552,15 @@ class UseThree {
     if (this.canvasContainer) this.canvasContainer.innerHTML = '';
     if (this.CSSCanvasContainer) this.CSSCanvasContainer.innerHTML = '';
 
-    this.resourceTracker && this.resourceTracker.dispose();
-    this.scene?.environment?.dispose();
-    !!this.scene?.clear ?? this.scene?.clear();
-
+    this.camera = null;
+    this.orbitControls = null;
+    this.renderer = null;
     this.stats = null;
     this.scene = null;
     this.css3dRender = null;
     this.css2dRender = null;
-
-    this.renderer = null;
     THREE.Cache.clear();
+    console.log('场景销毁后信息----------->', window['$renderer']?.info, this.scene);
   }
 }
 

+ 13 - 7
src/utils/threejs/util.ts

@@ -4,7 +4,7 @@ import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js';
 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 TWEEN from 'three/examples/jsm/libs/tween.module.js';
 import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader.js';
 import gsap from 'gsap';
 import { useAppStore } from '/@/store/modules/app';
@@ -25,7 +25,6 @@ export const setModalCenter = (group, modal?) => {
   group.position.x = group.position.x - center.x;
   group.position.y = group.position.y - center.y;
   group.position.z = group.position.z - center.z;
-
 };
 
 // 获取一个canvas 图文纹理
@@ -116,6 +115,7 @@ export const setLineGeo = (scene) => {
     const line = new THREE.LineSegments(edges, edgesMaterial);
     // 网格模型和网格模型对应的轮廓线框插入到场景中
     scene.add(line);
+    texture.dispose();
   });
 
   box.attributes.position.array;
@@ -274,6 +274,7 @@ export const renderVideo = (group, player, playerMeshName) => {
   if (texture && group?.getObjectByName(playerMeshName)) {
     const player = group.getObjectByName(playerMeshName);
     player.material.map = texture;
+    // texture.dispose();
   } else {
     //创建网格;
     const planeGeometry = new THREE.PlaneGeometry(30, 20);
@@ -291,7 +292,7 @@ export const renderVideo = (group, player, playerMeshName) => {
 
     const mesh = new THREE.Mesh(planeGeometry, material);
     mesh.name = playerMeshName;
-
+    texture.dispose();
     // group.add(mesh);
     return mesh;
   }
@@ -306,7 +307,7 @@ export const animateCamera = (oldP, oldT, newP, newT, model, duration = 0.5, cal
   return new Promise((resolve) => {
     const camera = model.camera;
     const controls = model.orbitControls;
-    controls.enabled = false;
+    controls.renderEnabled = false;
     controls.target.set(0, 0, 0);
     const animateObj = {
       x1: oldP.x, // 相机x
@@ -345,7 +346,7 @@ export const animateCamera = (oldP, oldT, newP, newT, model, duration = 0.5, cal
         onUpdateParams: [animateObj],
         onComplete: function () {
           // 完成
-          controls.enabled = true;
+          controls.renderEnabled = true;
           resolve(null);
         },
       }
@@ -391,6 +392,8 @@ export const drawHot = (scale: number) => {
   spriteTween.yoyo(true);
   spriteTween.repeat(Infinity);
   spriteTween.start();
+  hotMap.dispose();
+
   return hotPoint;
 };
 
@@ -463,13 +466,16 @@ export const updateAxisCenter = (modal: UseThree, group: THREE.Object3D, event,
 
 export const addEnvMap = (hdr, modal) => {
   return new Promise((resolve) => {
-    new RGBELoader().setPath('/model/hdr/').load(hdr + '.hdr', (texture) => {
+    const loader = new RGBELoader().setPath('/model/hdr/').load(hdr + '.hdr', (texture) => {
       texture.mapping = THREE.EquirectangularReflectionMapping;
       const defaultEnvironment = texture;
       modal.scene.environment = defaultEnvironment;
 
-      resolve(texture);
+      resolve(null);
+      texture.dispose();
     });
+
+    loader.dispose()
   });
 };
 

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

@@ -748,6 +748,7 @@ onUnmounted(() => {
   position: absolute;
   padding-top: 0px;
   top: -9px;
+  z-index: 999;
 
   &::before {
     content: '';

+ 42 - 46
src/views/dashboard/Analysis/homePage/workerFace.vue

@@ -226,64 +226,60 @@
         name: '进风',
         type: 'line',
         smooth: true,
-        lineStyle: { normal: { width: 2 } },
+        lineStyle: { width: 2 },
         yAxisIndex: 0,
         areaStyle: {
-          normal: {
-            color: new echarts.graphic.LinearGradient(
-              0,
-              0,
-              0,
-              1,
-              [
-                {
-                  offset: 0,
-                  color: 'rgba(185,150,248,0.3)',
-                },
-                {
-                  offset: 0.8,
-                  color: 'rgba(185,150,248,0)',
-                },
-              ],
-              false
-            ),
-            shadowColor: 'rgba(0, 0, 0, 0.1)',
-            shadowBlur: 10,
-          },
+          color: new echarts.graphic.LinearGradient(
+          0,
+          0,
+          0,
+          1,
+          [
+            {
+              offset: 0,
+              color: 'rgba(185,150,248,0.3)',
+            },
+            {
+              offset: 0.8,
+              color: 'rgba(185,150,248,0)',
+            },
+          ],
+          false
+        ),
+        shadowColor: 'rgba(0, 0, 0, 0.1)',
+        shadowBlur: 10,
         },
-        itemStyle: { normal: { color: '#B996F8' } },
+        itemStyle: { color: '#B996F8' },
         data: [],
       },
       {
         name: '回风',
         type: 'line',
         smooth: true,
-        lineStyle: { normal: { width: 2 } },
+        lineStyle: { width: 2 },
         yAxisIndex: 0,
         areaStyle: {
-          normal: {
-            color: new echarts.graphic.LinearGradient(
-              0,
-              0,
-              0,
-              1,
-              [
-                {
-                  offset: 0,
-                  color: 'rgba(3, 194, 236, 0.3)',
-                },
-                {
-                  offset: 0.8,
-                  color: 'rgba(3, 194, 236, 0)',
-                },
-              ],
-              false
-            ),
-            shadowColor: 'rgba(0, 0, 0, 0.1)',
-            shadowBlur: 10,
-          },
+          color: new echarts.graphic.LinearGradient(
+          0,
+          0,
+          0,
+          1,
+          [
+            {
+              offset: 0,
+              color: 'rgba(3, 194, 236, 0.3)',
+            },
+            {
+              offset: 0.8,
+              color: 'rgba(3, 194, 236, 0)',
+            },
+          ],
+          false
+        ),
+        shadowColor: 'rgba(0, 0, 0, 0.1)',
+        shadowBlur: 10,
         },
-        itemStyle: { normal: { color: '#03C2EC' } },
+        itemStyle: { color: '#03C2EC' },
         data: [],
       },
     ],

+ 2 - 1
src/views/system/menu/menu.data.ts

@@ -3,7 +3,7 @@ import { FormSchema } from '/@/components/Table';
 import { h } from 'vue';
 import { Icon } from '/@/components/Icon';
 import { duplicateCheck } from '../user/user.api';
-import { ajaxGetDictItems ,checkPermDuplication } from './menu.api';
+import { ajaxGetDictItems, checkPermDuplication } from './menu.api';
 import { render } from '/@/utils/common/renderUtils';
 
 const isDir = (type) => type === 0;
@@ -14,6 +14,7 @@ const isButton = (type) => type === 2;
 export enum ComponentTypes {
   Default = 'layouts/default/index',
   IFrame = 'sys/iframe/FrameBlank',
+  // IFrame = 'sys/iframe/index',
 }
 
 export const columns: BasicColumn[] = [

+ 3 - 2
src/views/system/menuModal/menu.data.ts

@@ -3,7 +3,7 @@ import { FormSchema } from '/@/components/Table';
 import { h } from 'vue';
 import { Icon } from '/@/components/Icon';
 import { duplicateCheck } from '../user/user.api';
-import { ajaxGetDictItems ,checkPermDuplication } from './menu.api';
+import { ajaxGetDictItems, checkPermDuplication } from './menu.api';
 import { render } from '/@/utils/common/renderUtils';
 
 const isDir = (type) => type === 0;
@@ -13,7 +13,8 @@ const isButton = (type) => type === 2;
 // 定义可选择的组件类型
 export enum ComponentTypes {
   Default = 'layouts/default/index',
-  IFrame = 'sys/iframe/FrameBlank',
+  // IFrame = 'sys/iframe/FrameBlank',
+  IFrame = 'sys/iframe/index',
 }
 
 export const columns: BasicColumn[] = [

+ 1 - 1
src/views/vent/comment/threejs/FlyLine.ts

@@ -43,6 +43,6 @@ export const flyLine = (lineArray, imgUrl, lineWidth = 0.2) => {
     repeat: -1,
     ease: 'none',
   });
-
+  
   return mesh;
 };

+ 1 - 0
src/views/vent/comment/threejs/FlyLine1.ts

@@ -93,6 +93,7 @@ class Fly {
     if (this.frameId) return;
     const clock = new THREE.Clock(); // 时钟
     const h = () => {
+      
       this.frameId = requestAnimationFrame(h);
       const dt = clock.getDelta();
       this.progress += dt / this.circle; // 更新进度

+ 53 - 36
src/views/vent/comment/threejs/Smoke.ts

@@ -41,28 +41,30 @@ export default class Smoke {
   }
 
   setPoints() {
-    const textureLoader = new THREE.TextureLoader();
-
-    // 先创建一个空的缓冲几何体
-    this.geometry = new THREE.BufferGeometry();
-    this.geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array([]), 3)); // 一个顶点由3个坐标构成
-    this.geometry.setAttribute('a_opacity', new THREE.BufferAttribute(new Float32Array([]), 1)); // 点的透明度,用1个浮点数表示
-    this.geometry.setAttribute('a_size', new THREE.BufferAttribute(new Float32Array([]), 1)); // 点的初始大小,用1个浮点数表示
-    this.geometry.setAttribute('a_scale', new THREE.BufferAttribute(new Float32Array([]), 1)); // 点的放大量,用1个浮点数表示
-
-    // 创建材质
-    const material = new THREE.PointsMaterial({
-      color: this.color,
-      map: textureLoader.load(this.smokeTexturePath), // 纹理图
-      transparent: true, // 开启透明度
-      depthWrite: false, // 禁止深度写入
-      sizeAttenuation: true,
-      side: THREE.DoubleSide,
-    });
-
-    // 修正着色器
-    material.onBeforeCompile = function (shader) {
-      const vertexShader_attribute = `
+    return new Promise((resolve) => {
+      const textureLoader = new THREE.TextureLoader();
+
+      // 先创建一个空的缓冲几何体
+      this.geometry = new THREE.BufferGeometry();
+      this.geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array([]), 3)); // 一个顶点由3个坐标构成
+      this.geometry.setAttribute('a_opacity', new THREE.BufferAttribute(new Float32Array([]), 1)); // 点的透明度,用1个浮点数表示
+      this.geometry.setAttribute('a_size', new THREE.BufferAttribute(new Float32Array([]), 1)); // 点的初始大小,用1个浮点数表示
+      this.geometry.setAttribute('a_scale', new THREE.BufferAttribute(new Float32Array([]), 1)); // 点的放大量,用1个浮点数表示
+
+      // 创建材质
+      textureLoader.load(this.smokeTexturePath, (texture) => {
+        const material = new THREE.PointsMaterial({
+          color: this.color,
+          map: texture, // 纹理图
+          transparent: true, // 开启透明度
+          depthWrite: false, // 禁止深度写入
+          sizeAttenuation: true,
+          side: THREE.DoubleSide,
+        });
+
+        // 修正着色器
+        material.onBeforeCompile = function (shader) {
+          const vertexShader_attribute = `
         attribute float a_opacity;
         attribute float a_size;
         attribute float a_scale;
@@ -70,29 +72,35 @@ export default class Smoke {
         void main() {
           v_opacity = a_opacity;
         `;
-      const vertexShader_size = `
+          const vertexShader_size = `
         gl_PointSize = a_size * a_scale;
         `;
-      shader.vertexShader = shader.vertexShader.replace('void main() {', vertexShader_attribute);
-      shader.vertexShader = shader.vertexShader.replace('gl_PointSize = size;', vertexShader_size);
-      const fragmentShader_varying = ` 
+          shader.vertexShader = shader.vertexShader.replace('void main() {', vertexShader_attribute);
+          shader.vertexShader = shader.vertexShader.replace('gl_PointSize = size;', vertexShader_size);
+          const fragmentShader_varying = ` 
         varying float v_opacity;
         void main() {
       `;
-      const fragmentShader_opacity = `
+          const fragmentShader_opacity = `
         vec4 diffuseColor = vec4( diffuse, opacity * v_opacity );
       `;
-      shader.fragmentShader = shader.fragmentShader.replace('void main() {', fragmentShader_varying);
-      shader.fragmentShader = shader.fragmentShader.replace('vec4 diffuseColor = vec4( diffuse, opacity );', fragmentShader_opacity);
-    };
+          shader.fragmentShader = shader.fragmentShader.replace('void main() {', fragmentShader_varying);
+          shader.fragmentShader = shader.fragmentShader.replace('vec4 diffuseColor = vec4( diffuse, opacity );', fragmentShader_opacity);
+        };
 
-    // 创建点,并添加进场景
-    this.points = new THREE.Points(this.geometry, material);
-    
+        // 创建点,并添加进场景
+        this.points = new THREE.Points(this.geometry, material);
+        this.points.frustumCulled = false;
+        this.points.renderOrder = 1;
+
+        texture.dispose();
+        resolve(null);
+      });
+    });
   }
 
   startSmoke(duration = 15) {
-    if (!this.pathArr && this.frameId) {
+    if (!this.pathArr && this.frameId && !this.points && !this.points.geometry) {
       return;
     }
     this.opacityFactor = 0;
@@ -104,7 +112,6 @@ export default class Smoke {
       ease: 'easeInQuint',
     });
 
-    const self = this;
     // 创建粒子
     let particals = [] as SmokePartical[];
     const clock = new THREE.Clock();
@@ -179,7 +186,17 @@ export default class Smoke {
     });
   }
   clearSmoke() {
-    if (this.frameId) cancelAnimationFrame(this.frameId);
+    if (this.frameId) {
+      cancelAnimationFrame(this.frameId);
+    }
+    
+    const material = this.points.material;
+    for (const key of Object.keys(material)) {
+      const value = material[key];
+      if (value && typeof value === 'object' && value['dispose'] && typeof value['dispose'] === 'function') {
+        value.dispose();
+      }
+    }
     this.points.geometry.dispose();
     this.points.material.dispose();
   }

+ 1 - 1
src/views/vent/comment/threejs/SmokePath.ts

@@ -1,6 +1,6 @@
 import * as THREE from 'three';
 import gsap from 'gsap';
-import * as dat from 'dat.gui';
+// import * as dat from 'dat.gui';
 // const gui = new dat.GUI();
 
 export default class SmokePath {

+ 1 - 1
src/views/vent/comment/threejs/SmokePath1.ts

@@ -1,6 +1,6 @@
 import * as THREE from 'three';
 import gsap from 'gsap';
-import * as dat from 'dat.gui';
+// import * as dat from 'dat.gui';
 // const gui = new dat.GUI();
 
 export default class SmokePath {

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

@@ -9,7 +9,7 @@
     :footer="null"
     destroyOnClose
   >
-    <a-tabs v-if="props.showTab">
+    <a-tabs v-if="props.showTab" >
       <a-tab-pane key="1" tab="基本信息" force-render>
         <FormModal :record="record" @saveOrUpdate="(values) => emit('saveOrUpdate', values)" />
       </a-tab-pane>

+ 3 - 0
src/views/vent/deviceManager/comment/FormModal.vue

@@ -56,6 +56,9 @@
     bottom: 0px !important;
   }
   .vent-form {
+    max-height: 700px; 
+    overflow-y: auto;
+    
     .@{ventSpace}-select-selection-item {
       color: rgba(255, 255, 255, 1) !important;
     }

+ 2 - 2
src/views/vent/deviceManager/comment/pointTabel/PointTable.vue

@@ -23,7 +23,7 @@
             :fieldNames="{ label: 'deviceName', value: 'deviceID' }"
             v-model:value="record['editValueRefs']['link_id']"
             style="width: 100%"
-          />
+          ></Select>
         </div>
         <div v-if="record.editable && column.dataIndex === 'link_code'">
           <Select
@@ -32,7 +32,7 @@
             :fieldNames="{ label: 'valuename', value: 'valuecode' }"
             @change="handleChangeLinkCode($event, index)"
             v-model:value="record['editValueRefs']['link_code']"
-          />
+          ></Select>
         </div>
       </template>
     </BasicTable>

+ 20 - 0
src/views/vent/monitorManager/alarmMonitor/alarm.api.ts

@@ -0,0 +1,20 @@
+import { defHttp } from '/@/utils/http/axios';
+
+enum Api {
+  list = '/ventanaly-device/monitor/device',
+  baseList = '/safety/ventanalyWindow/list',
+  warningList = '/safety/ventanalyAlarmLog/list',
+}
+/**
+ * 列表接口
+ * @param params
+ */
+export const list = (params) => defHttp.post({ url: Api.list, params });
+
+/**
+ * 保存或者更新用户
+ * @param params
+ */
+export const getTableList = (params) => defHttp.get({ url: Api.baseList, params });
+
+export const warningList = (params) => defHttp.get({ url: Api.warningList, params });

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 112 - 0
src/views/vent/monitorManager/alarmMonitor/alarm.data.ts


+ 143 - 0
src/views/vent/monitorManager/alarmMonitor/index.vue

@@ -0,0 +1,143 @@
+<template>
+  <div class="sensor-container">
+    <div class="lr left-box">
+      <div class="">
+        <div ref="alarmCounts" style="height: 195px" id="alarmCounts"></div>
+        <div class="icons-box">
+          <div class="icon-item" v-for="(item, key) in iconsMonitor" :key="key">
+            <img :src="item.url" :alt="item.text"/>
+            <div class="level-text" :class="{ 'level-text-1': item.level == 1, 'level-text-2': item.level == 2, 'level-text-3': item.level == 3, 'level-text-4': item.level == 4, 'level-text-5': item.level == 5 }">{{ item.level == 1 ? '正常' : item.level == 2 ? '低风险' : item.level == 3 ? '中风险' : item.level == 4 ? '高风险' : item.level == 5 ? '报警' : '' }}</div>
+          </div>
+        </div>
+      </div>
+      <div class="vent-monitor">
+        
+      </div>
+    </div>
+    <div class="center-box"></div>
+    <div class="lr right-box"></div>
+  </div>
+</template>
+
+<script setup lang="ts">
+
+  import { ref, onMounted, onUnmounted, reactive } from 'vue';
+  import { warningList } from './alarm.api';
+  import { iconsMonitor, setScatterEcharts } from './alarm.data'
+  const alarmCounts = ref()
+  const dataSource = ref([]);
+
+  // https获取监测数据
+  let timer: null | NodeJS.Timeout = null;
+  const getMonitor = (flag = false) => {
+    if (Object.prototype.toString.call(timer) === '[object Null]') {
+      timer = setTimeout(async () => {
+        await getDataSource();
+        if (timer) {
+          timer = null;
+        }
+        getMonitor();
+      }, flag? 0 : 1000);
+    }
+  };
+
+  const getDataSource = async () => {
+    const res = await warningList({});
+    dataSource.value = res.list.records || [];
+    // if(dataSource.value.length > 0){
+    //   dataSource.value.map((data: any) => {
+    //     const readData = data.readData;
+    //     data = Object.assign(data, readData);
+    //     return data;
+    //   });
+    // }
+  };
+
+  onMounted(async () => {
+    getMonitor(true);
+    setScatterEcharts(alarmCounts.value)
+  });
+
+  onUnmounted(() => {
+    if (timer) {
+      clearTimeout(timer);
+      timer = undefined;
+    }
+  });
+</script>
+<style lang="less" scoped>
+  @import '/@/design/vent/color.less';
+  .sensor-container {
+    width: 100%;
+    height: calc(100% - 86px);
+    display: flex;
+    position: relative;
+    top: 78px;
+
+    .lr{
+      width: 550px;
+      height: 100%;
+
+      // background-color: #ffffff10;
+    }
+    .left-box{
+      .vent-monitor{
+        width: 100%;
+        height: 230px;
+        background: #ff0;
+      }
+      .icons-box{
+        display: flex;
+        flex-wrap: wrap;
+        padding: 0 8px;
+        .icon-item{
+          position: relative;
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          padding: 5px 0;
+          .level-text{
+            position: absolute;
+            top: 40px;
+            left: 85px;
+            color: #fff;
+            font-family: 'douyuFont';
+            font-size: 12px;
+          }
+          .level-text-1{
+            color: #2bdcff;
+            text-shadow: 2px 2px 4px #001c22;
+          }
+          .level-text-2{
+            color: #ffff35;
+            text-shadow: 2px 2px 4px #313100;
+          }
+          .level-text-3{
+            color: #ffbe69;
+            text-shadow: 2px 2px 4px #271600;
+          }
+          .level-text-4{
+            color: #ff6f00;
+            // color: #09caff;
+            text-shadow: 2px 2px 4px #060200;
+          }
+          .level-text-5{
+            color: #ff0000;
+            text-shadow: 2px 2px 4px #200000;
+          }
+          img{
+            width: 153px;
+            height: 63px;
+          }
+        }
+      }
+    }
+    .center-box{
+      width: calc(100% - 816px);
+      background-color: #ffffff10;
+      margin: 0 8px;
+    }
+  }
+  
+  
+</style>

+ 7 - 0
src/views/vent/monitorManager/balancePressMonitor/balancePress.api.ts

@@ -4,6 +4,7 @@ import { Modal } from 'ant-design-vue';
 enum Api {
   list = '/ventanaly-device/monitor/device',
   baseList = '/safety/ventanalyManageSystem/list',
+  deviceList = '/ventanaly-device/safety/ventanalyManageSystem/linkdevicelist',
 }
 /**
  * 列表接口
@@ -16,3 +17,9 @@ export const list = (params) => defHttp.post({ url: Api.list, params });
  * @param params
  */
 export const getTableList = (params) => defHttp.get({ url: Api.baseList, params });
+
+/**
+ * 关联设备列表接口
+ * @param params
+ */
+export const deviceList = (params) => defHttp.get({ url: Api.deviceList, params });

+ 287 - 41
src/views/vent/monitorManager/balancePressMonitor/balancePress.threejs.base.ts

@@ -1,83 +1,329 @@
 import * as THREE from 'three';
-import { setModalCenter } from '/@/utils/threejs/util';
-import * as dat from 'dat.gui';
-const gui = new dat.GUI();
-gui.domElement.style = 'position:absolute;top:100px;left:10px;z-index:99999999999999';
+import { setModalCenter, getTextCanvas, renderVideo } from '/@/utils/threejs/util';
+import Smoke from '/@/views/vent/comment/threejs/Smoke';
+import gsap from 'gsap';
+
+// import * as dat from 'dat.gui';
+// const gui = new dat.GUI();
+// gui.domElement.style = 'position:absolute;top:100px;left:10px;z-index:99999999999999';
 
 class balancePressBase {
   model;
   modelName = 'balancePress';
   group: THREE.Object3D | null = null;
+  topSmoke: Smoke | null = null;
+  downSmoke: Smoke | null = null;
+  outSmoke: Smoke | null = null;
 
   constructor(model) {
     this.model = model;
   }
 
   addLight() {
+
     const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
-    directionalLight.position.set(-52, -35, -26);
+    directionalLight.position.set(34, 7, -61);
     this.group?.add(directionalLight);
     directionalLight.target = this.group as THREE.Object3D;
 
-    // gui.add(directionalLight.position, 'x', -10, 20).onChange(function (value) {
-    //   directionalLight.position.x = Number(value);
-    //   _this.render();
-    // });
-    // gui.add(directionalLight.position, 'y', -50, 50).onChange(function (value) {
-    //   directionalLight.position.y = Number(value);
-    //   _this.render();
-    // });
-    // gui.add(directionalLight.position, 'z', -20, 20).onChange(function (value) {
-    //   directionalLight.position.z = Number(value);
-    //   _this.render();
-    // });
-    // const pointLight5 = new THREE.PointLight(0xffffff, 0.8, 120);
-    // pointLight5.position.set(-54, 30, 23.8);
-    // pointLight5.shadow.bias = 0.05;
-    // this.group.add(pointLight5);
+    // gui.add(directionalLight.position, 'x', -200, 200);
+    // gui.add(directionalLight.position, 'y', -200, 200);
+    // gui.add(directionalLight.position, 'z', -200, 200);
+
+    const pointLight5 = new THREE.PointLight(0xffffff, 0.8, 120);
+    pointLight5.position.set(75, -44, 75);
+    pointLight5.shadow.bias = 0.05;
+    this.group?.add(pointLight5);
 
     const pointLight7 = new THREE.PointLight(0xffffff, 1, 1000);
     pointLight7.position.set(-7, 100, 8.5);
     pointLight7.shadow.bias = 0.05;
-    this.model.scene.add(pointLight7);
+    this.group?.add(pointLight7);
 
     // gui.add(directionalLight.position, 'x', -100, 100);
     // gui.add(directionalLight.position, 'y', -100, 100);
     // gui.add(directionalLight.position, 'z', -100, 100);
-    // gui.add(pointLight7.position, 'x', -100, 100);
-    // gui.add(pointLight7.position, 'y', -100, 100);
-    // gui.add(pointLight7.position, 'z', -100, 100);
-
-    // gui.add(spotLight.position, 'x', -600, 600).onChange(function (value) {
-    //   spotLight.position.x = Number(value);
-    //   _this.render();
-    // });
-    // gui.add(spotLight.position, 'y', -600, 800).onChange(function (value) {
-    //   spotLight.position.y = Number(value);
-    //   _this.render();
-    // });
-    // gui.add(spotLight.position, 'z', -500, 1000).onChange(function (value) {
-    //   spotLight.position.z = Number(value);
-    //   _this.render();
-    // });
+    // gui.add(pointLight5.position, 'x', -500, 500);
+    // gui.add(pointLight5.position, 'y', -500, 500);
+    // gui.add(pointLight5.position, 'z', -500, 500);
+  }
+
+  /* 添加监控数据 */
+  addText(selectData) {
+    if (!this.group) {
+      return;
+    }
+    const textArr = [
+      {
+        text: `煤矿巷道远程局部风机系统`,
+        font: 'normal 30px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 50,
+        y: 105,
+      },
+      {
+        text: `进风量(m³/min):`,
+        font: 'normal 30px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 0,
+        y: 160,
+      },
+      {
+        text: `${selectData.frontRearDP}`,
+        font: 'normal 30px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 290,
+        y: 160,
+      },
+      {
+        text: `供风量(m³/min): `,
+        font: 'normal 30px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 0,
+        y: 217,
+      },
+      {
+        text: ` ${selectData.sourcePressure}`,
+        font: 'normal 30px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 280,
+        y: 217,
+      },
+      {
+        text: `故障诊断:`,
+        font: 'normal 30px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 0,
+        y: 275,
+      },
+      {
+        text: `${selectData.fault}`,
+        font: 'normal 30px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 280,
+        y: 275,
+      },
+      {
+        text: `煤炭科学技术研究院有限公司研制`,
+        font: 'normal 28px Arial',
+        color: '#009900',
+        strokeStyle: '#002200',
+        x: 20,
+        y: 325,
+      },
+    ];
+    getTextCanvas(526, 346, textArr, '').then((canvas: HTMLCanvasElement) => {
+      const textMap = new THREE.CanvasTexture(canvas); // 关键一步
+      const textMaterial = new THREE.MeshBasicMaterial({
+        // 关于材质并未讲解 实操即可熟悉                 这里是漫反射类似纸张的材质,对应的就有高光类似金属的材质.
+        map: textMap, // 设置纹理贴图
+        transparent: true,
+        side: THREE.FrontSide, // 这里是双面渲染的意思
+      });
+      textMaterial.blending = THREE.CustomBlending;
+      const monitorPlane = this.group?.getObjectByName('monitorText') as THREE.Mesh;
+      if (monitorPlane) {
+        monitorPlane.material = textMaterial;
+      } else {
+        const planeGeometry = new THREE.PlaneGeometry(526, 346); // 平面3维几何体PlaneGeometry
+        const planeMesh = new THREE.Mesh(planeGeometry, textMaterial);
+        planeMesh.name = 'monitorText';
+        planeMesh.scale.set(0.0135, 0.0135, 0.0135);
+        planeMesh.position.set(57.66, 0.81, 18.19);
+        this.group?.add(planeMesh);
+      }
+    });
+  }
+
+  addVideo() {
+    const videoPlayer1 = document.getElementById('jb-player1')?.getElementsByClassName('vjs-tech')[0];
+    if (videoPlayer1) {
+      const mesh = renderVideo(this.group, videoPlayer1, 'player1');
+      if (mesh) {
+        mesh.scale.set(0.222, 0.19, 0.2);
+        mesh.position.set(-84.87, 0.298, 24.76);
+        mesh.rotation.y = -Math.PI / 2;
+        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);
+          if (!videoPlayer1) {
+            planeMesh.name = 'noPlayer';
+            planeMesh.scale.set(0.1, 0.075, 0);
+            planeMesh.position.set(65.78, -2.68, 18.06);
+            this.group?.add(planeMesh.clone());
+          }
+        }
+      });
+    }
+  }
+
+  playSmoke = (controlType, deviceType, frequency, state, duration?) => {
+    if (frequency) {
+      this.setSmokeFrequency(deviceType, frequency);
+    }
+    if (controlType === 'startSmoke') {
+      this.runFly(deviceType, state, duration);
+    }
+  };
+
+  async initFly() {
+    // const fanObj = this.group?.getObjectByName('Equalization');
+    const mesh = new THREE.Mesh();
+    mesh.matrix = new THREE.Matrix4();
+    mesh.position.set(35.251, 0.852, -35.243);
+    mesh.scale.set(0.001, 0.001, 0.001);
+
+    mesh.updateMatrix();
+
+    if (!this.group) return;
+    const topCurve = [
+      {
+        path0: new THREE.Vector3(14485.279, 1370.746, 56053.556).applyMatrix4(mesh.matrix),
+        path1: new THREE.Vector3(7555.8, 1370.746, 54190.156).applyMatrix4(mesh.matrix),
+        isSpread: true,
+        spreadDirection: -1, //
+      },
+    ];
+
+    const downCurve = [
+      {
+        path0: new THREE.Vector3(14485.279, -1370.746, 56053.556).applyMatrix4(mesh.matrix),
+        path1: new THREE.Vector3(7555.82, -1370.746, 54190.156).applyMatrix4(mesh.matrix),
+        isSpread: true,
+        spreadDirection: -1, //
+      },
+    ];
+
+    const outCurve = [
+      {
+        path0: new THREE.Vector3(-7555.818, -23.02, -54190.152).applyMatrix4(mesh.matrix),
+        path1: new THREE.Vector3(-7555.818, -23.02, -74165.96).applyMatrix4(mesh.matrix),
+        isSpread: true,
+        spreadDirection: 1, // 1是由小变大,-1是由大变小
+      },
+    ];
+
+    if (!this.topSmoke) {
+      this.topSmoke = new Smoke('/model/img/texture-smoke.png', '#ffffff', 0, 0.8, 0.05, 20);
+      this.topSmoke.setPath(topCurve);
+      await this.topSmoke.setPoints();
+      this.group.add(this.topSmoke.points);
+    }
+    if (!this.downSmoke) {
+      this.downSmoke = new Smoke('/model/img/texture-smoke.png', '#ffffff', 0, 0.8, 0.05, 20);
+      this.downSmoke.setPath(downCurve);
+      await this.downSmoke.setPoints();
+      this.group.add(this.downSmoke.points);
+    }
+    if (!this.outSmoke) {
+      this.outSmoke = new Smoke('/model/img/texture-smoke.png', '#ffffff', 0, 0.8, 0.05, 20);
+      this.outSmoke.setPath(outCurve);
+      await this.outSmoke.setPoints();
+      this.group.add(this.outSmoke.points);
+    }
+  }
+
+  runFly(deviceType, state, duration?) {
+    debugger;
+    if (state === 'open') {
+      if (deviceType === 'top') {
+        if (this.downSmoke?.frameId) {
+          this.downSmoke.stopSmoke();
+        }
+        this.topSmoke?.startSmoke(duration);
+      } else {
+        if (this.topSmoke?.frameId) {
+          this.topSmoke.stopSmoke();
+        }
+        this.downSmoke?.startSmoke(duration);
+      }
+      this.outSmoke?.startSmoke(duration);
+    } else {
+      if (this.downSmoke?.frameId) {
+        this.downSmoke?.stopSmoke();
+      }
+      if (this.topSmoke?.frameId) {
+        this.topSmoke?.stopSmoke();
+      }
+      if (this.outSmoke?.frameId) {
+        this.outSmoke?.stopSmoke();
+      }
+    }
   }
 
+  setSmokeFrequency = (deviceType, frequency) => {
+    if (!this.topSmoke) return;
+    const life = (frequency - 30) * 25;
+    const duration = (Math.abs(life - this.topSmoke.life) / 500) * 25;
+    let smoke;
+    if (deviceType === 'top') {
+      smoke = this.topSmoke;
+    } else {
+      smoke = this.downSmoke;
+    }
+    gsap.to(smoke, {
+      life: life,
+      duration: duration,
+      ease: 'easeInCubic',
+      overwrite: true,
+    });
+  };
+
+  clearFly = () => {
+    if (this.topSmoke) this.topSmoke.clearSmoke();
+    if (this.downSmoke) this.downSmoke.clearSmoke();
+    if (this.outSmoke) this.outSmoke.clearSmoke();
+  };
+
   mountedThree() {
     return new Promise((resolve) => {
-      this.model.setGLTFModel([this.modelName]).then((gltf) => {
+      this.model.setGLTFModel([this.modelName]).then(async (gltf) => {
         this.group = gltf[0];
         if (this.group) {
-          setModalCenter(this.group);
           this.group?.scale.set(0.1, 0.1, 0.1);
-          this.group.position.set(0.445, 0.68, -0.118);
+          await this.initFly();
+          setModalCenter(this.group);
           resolve(null);
           this.addLight();
+          this.addVideo();
         }
       });
     });
   }
 
   destroy() {
+    this.clearFly();
     this.model.clearGroup(this.group);
     this.model = null;
     this.group = null;

+ 51 - 45
src/views/vent/monitorManager/balancePressMonitor/balancePress.threejs.ts

@@ -1,42 +1,52 @@
-import * as THREE from 'three';
 import UseThree from '../../../../utils/threejs/useThree';
 import balancePressBase from './balancePress.threejs.base';
-import { animateCamera, setModalCenter } from '/@/utils/threejs/util';
+import { animateCamera } from '/@/utils/threejs/util';
 import useEvent from '../../../../utils/threejs/useEvent';
 
 // 模型对象、 文字对象
 let model,
-  balancePressBaseObj: balancePressBase,
-  group,
+  balancePressBaseObj: balancePressBase | undefined,
+  group: THREE.Object3D | undefined,
   balancePressType = 'balancePressBase'; // workerFaceFiber
 
-const { mouseDownFn } = useEvent();
+const { mouseDownFn, mousemoveFn, mouseUpFn } = useEvent();
 // 鼠标点击事件
 const mouseEvent = (event) => {
-  mouseDownFn(model, group, event, (intersects) => {
-    if (balancePressType === 'balancePressType') {
-      // balancePressBaseObj.mousedownModel.call(balancePressBaseObj, model.rayCaster);
-    }
-  });
-  console.log('摄像头,控制器------>', model.camera, model.orbitControls);
+  if (event.button == 0) {
+    model.canvasContainer?.addEventListener('mousemove', mousemove);
+    mouseDownFn(model, group as THREE.Object3D, event, (intersects) => {
+      if (balancePressType === 'balancePressType') {
+        // balancePressBaseObj.mousedownModel.call(balancePressBaseObj, model.rayCaster);
+      }
+    });
+  }
+};
+
+const mouseUp = () => {
+  if (!model) return;
+  mouseUpFn(model, 1);
+  model.canvasContainer?.removeEventListener('mousemove', mousemove);
+};
+
+const mousemove = () => {
+  mousemoveFn();
 };
 
 const addMouseEvent = () => {
   // 定义鼠标点击事件
   model.canvasContainer?.addEventListener('mousedown', mouseEvent.bind(null));
+  model.canvasContainer?.addEventListener('pointerup', mouseUp);
 };
 
-const render = () => {
-  if (model.animationId != -1) {
-    model.animationId = requestAnimationFrame(render);
-    model.css3dRender?.render(model.scene as THREE.Scene, model.camera as THREE.PerspectiveCamera);
-    model.stats?.update();
+export const play = (controlType, deviceType, frequency, state, duration?) => {
+  if (balancePressType === 'balancePressBase') {
+    return balancePressBaseObj?.playSmoke.call(balancePressBaseObj, controlType, deviceType, frequency, state, duration);
   }
 };
 
-export const addbalancePressText = (selectData) => {
+export const updateText = (selectData) => {
   if (balancePressType === 'balancePressBase') {
-    return balancePressBaseObj.addbalancePressText.call(balancePressBaseObj, selectData);
+    return balancePressBaseObj?.addText.call(balancePressBaseObj, selectData);
   }
 };
 
@@ -44,23 +54,22 @@ export const addbalancePressText = (selectData) => {
 export const setModelType = (type) => {
   balancePressType = type;
   return new Promise((resolve) => {
-    if (balancePressType === 'balancePressBase') {
+    if (balancePressType === 'balancePressBase' && balancePressBaseObj && balancePressBaseObj.group) {
       group = balancePressBaseObj.group;
-      const oldCameraPosition = { x: 0, y: 0, z: 10 };
-      model.scene.add(balancePressBaseObj.group);
-      
-      model.camera.position.set(0, 0, 300);
-      setTimeout(async () => {
-        // const position = { x: 0, y: 3.8, z: 10.5 };
-        await animateCamera(
-          oldCameraPosition,
-          {x: 0, y: 0, z: 0},
-          { x: -4.701309176450354, y: 1.8413775084517353, z: 0.00649962854810722 },
-          { x: 0, y: 0, z: 0 },
-          model,
-          0.8
-        );
-      }, 300);
+      if (group) {
+        const oldCameraPosition = { x: 27.9165, y: 17.3763, z: 51.3388 };
+        setTimeout(async () => {
+          model.scene.add(balancePressBaseObj?.group);
+          await animateCamera(
+            oldCameraPosition,
+            { x: 3.9025, y: 0.7782, z: 6.6307 },
+            { x: 0.1218, y: 3.8213, z: 17.27671 },
+            { x: 0.2348, y: 0.7182, z: 6.8413 },
+            model,
+            0.8
+          );
+        }, 300);
+      }
 
       resolve(null);
     }
@@ -71,16 +80,11 @@ export const mountedThree = () => {
   return new Promise(async (resolve) => {
     model = new UseThree('#balancePress3D');
     model.setEnvMap('test1');
-    model.renderer.toneMappingExposure = 1;
-    // model.camera.position.set(100, 0, 1000);
-
+    model.renderer.toneMappingExposure = 1.0;
     balancePressBaseObj = new balancePressBase(model);
     await balancePressBaseObj.mountedThree();
 
-    // model.scene.add(balancePressBaseObj.group);
-
     addMouseEvent();
-    // render();
     model.animate();
     resolve(null);
   });
@@ -88,10 +92,12 @@ export const mountedThree = () => {
 
 export const destroy = () => {
   if (model) {
-    balancePressBaseObj.destroy();
-    model.deleteModal();
-    model = null;
-    group = null;
-    balancePressBaseObj = null;
+    model.isRender = false;
+    console.log('场景销毁前信息----------->', model.renderer?.info);
+    balancePressBaseObj?.destroy();
+    balancePressBaseObj = undefined;
+    group = undefined;
+    model.destroy();
+    model = undefined;
   }
 };

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

@@ -20,6 +20,7 @@ import { getTableList } from '../balancePress.api'
 </script>
 <style lang="less" scoped>
 .handle-history {
+  width: 100%;
   pointer-events: auto;
 }
 </style>

+ 2 - 3
src/views/vent/monitorManager/balancePressMonitor/components/balancePressHistory.vue

@@ -1,13 +1,12 @@
 <template>
   <div class="history-box">
-    <HistoryTable :columns-type="`${deviceType}`" :device-type="deviceType" :sysId="deviceId"
-      :device-list-api="getTableList.bind(null, { strtype: deviceType, sysId: deviceId })" designScope="pressurefan_history" />
+    <HistoryTable :columns-type="`${deviceType}`" :device-type="deviceType" :sysId="deviceId" designScope="pressurefan_history" />
   </div>
 </template>
 <script setup lang="ts">
 import { ref, defineProps } from 'vue'
 import HistoryTable from '../../comment/HistoryTable.vue';
-import { getTableList } from '../balancePress.api'
+// import { getTableList } from '../balancePress.api'
 
 const props = defineProps({
   deviceType: {

+ 9 - 4
src/views/vent/monitorManager/balancePressMonitor/components/balancePressHome.vue

@@ -91,7 +91,7 @@
 import { onBeforeMount, ref, onMounted, onUnmounted, reactive, defineProps, watch } from 'vue';
 import ventBox1 from '/@/components/vent/ventBox1.vue'
 import { SvgIcon } from '/@/components/Icon';
-import { mountedThree, destroy, setModelType } from '../balancePress.threejs';
+import { mountedThree, destroy, setModelType, updateText, play } from '../balancePress.threejs';
 import { settingParam1, settingParam2, settingParam3, windowParam, localFanParam } from '../balancePress.data'
 import { list } from '../balancePress.api';
 import LivePlayer from '@liveqing/liveplayer-v3';
@@ -109,7 +109,11 @@ const loading = ref(false);
 const isAutoControl = ref('1')
 
 // 监测数据
-const selectData = reactive({});
+const selectData = reactive({
+  frontRearDP: '-',
+  sourcePressure: '-',
+  fault: '-'
+});
 
 const changeType = (isAutoControl) =>{
   isAutoControl
@@ -128,7 +132,8 @@ function getMonitor() {
     timer = setTimeout(async () => {
       if (props.deviceId) {
         const data = await getDataSource(props.deviceId)
-        Object.assign(selectData, data); 
+        Object.assign(selectData, data);
+        updateText(selectData)
       }
       if (timer) {
         timer = null;
@@ -144,7 +149,6 @@ async function getDataSource(systemID) {
   const result = res.msgTxt;
   result.forEach(item => {
 
-
     if (item.type === 'sys') {
       // 硐室基本
       // fiberDataSource.value = item.filter((data: any) => {
@@ -180,6 +184,7 @@ onMounted(() => {
     loading.value = false;
     timer = null
     await getMonitor()
+    play('startSmoke', 'top', 30, 'open', 0)
   });
 });
 

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

@@ -78,6 +78,7 @@ function deviceChange(index) {
 // 查询关联设备列表
 async function getDeviceList() {
   const res = await list({ devicetype: 'sys', systemID: optionValue.value });
+  
   const result = res.msgTxt;
   const deviceArr = <DeviceType[]>[]
   result.forEach(item => {
@@ -201,9 +202,6 @@ onUnmounted(() => {
   height: calc(100% - 200px);
 }
 
-:deep(.@{ventSpace}-tabs-tabpane-active) {
-  overflow: auto;
-}
 
 .input-box {
   display: flex;

+ 49 - 57
src/views/vent/monitorManager/balancePressMonitor1/balancePress.three.ts

@@ -4,7 +4,7 @@ import { animateCamera, getTextCanvas, renderVideo, updateAxisCenter } from '/@/
 import UseThree from '../../../../utils/threejs/useThree';
 import Smoke from '/@/views/vent/comment/threejs/Smoke';
 import gsap from 'gsap';
-import { useAppStore } from '/@/store/modules/app';
+import useEvent from '../../../../utils/threejs/useEvent';
 // import * as dat from 'dat.gui';
 // const gui = new dat.GUI();
 // gui.domElement.style = 'position:absolute;top:100px;left:10px;z-index:99999999999999';
@@ -12,20 +12,20 @@ import { useAppStore } from '/@/store/modules/app';
 const modelName = 'jbfj-hd';
 // 模型对象、 文字对象
 let model,
-  group = new THREE.Object3D(),
+  group: THREE.Object3D | undefined = new THREE.Object3D(),
   player1,
-  topSmoke,
-  downSmoke,
+  topSmoke: Smoke | undefined,
+  downSmoke: Smoke | undefined,
   playerStartClickTime1 = new Date().getTime();
 
-const appStore = useAppStore();
+const { mouseDownFn } = useEvent();
 
 // 打灯光
 const addLight = (scene) => {
   const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
   directionalLight.position.set(106, -348, 19.9);
-  group.add(directionalLight);
-  directionalLight.target = group;
+  group?.add(directionalLight);
+  directionalLight.target = <THREE.Object3D>group;
 
   // gui.add(directionalLight.position, 'x', -1000, 1000);
   // gui.add(directionalLight.position, 'y', -1000, 1000);
@@ -72,7 +72,7 @@ const addLight = (scene) => {
   spotLight.shadow.camera.far = 1000; // default
   spotLight.shadow.focus = 1;
   spotLight.shadow.bias = -0.000002;
-  spotLight.target = group;
+  spotLight.target = <THREE.Object3D>group;
 
   // gui.add(pointLight6.position, 'x', -200, 200);
   // gui.add(pointLight6.position, 'y', -200, 200);
@@ -92,8 +92,10 @@ const resetCamera = () => {
 
 // 设置模型位置
 const setModalPosition = () => {
-  group.position.set(0, 13, -50);
-  group.rotation.y = Math.PI / 2;
+  if (group) {
+    group.position.set(0, 13, -50);
+    group.rotation.y = Math.PI / 2;
+  }
 };
 
 const setControls = () => {
@@ -195,7 +197,7 @@ export const addText = (selectData) => {
       side: THREE.FrontSide, // 这里是双面渲染的意思
     });
     textMaterial.blending = THREE.CustomBlending;
-    const monitorPlane = group.getObjectByName('monitorText');
+    const monitorPlane = group?.getObjectByName('monitorText');
     if (monitorPlane) {
       monitorPlane.material = textMaterial;
     } else {
@@ -205,41 +207,41 @@ export const addText = (selectData) => {
       planeMesh.scale.set(0.0135, 0.0135, 0.0135);
       planeMesh.rotation.y = -Math.PI / 2;
       planeMesh.position.set(-84.79, 0.82, 17.01);
-      group.add(planeMesh);
+      group?.add(planeMesh);
     }
   });
 };
 
 // // css3D文字
 export const addCssText = () => {
-  if (!group.getObjectByName('text1')) {
+  if (!group?.getObjectByName('text1')) {
     const element = document.getElementById('inputBox') as HTMLElement;
     const fanLocalCSS3D = new CSS3DObject(element);
     fanLocalCSS3D.name = 'text1';
     fanLocalCSS3D.scale.set(0.04, 0.04, 0.04);
     fanLocalCSS3D.rotation.y = -Math.PI / 2;
     fanLocalCSS3D.position.set(-85.68, 5.97, -17.74);
-    group.add(fanLocalCSS3D);
+    group?.add(fanLocalCSS3D);
   }
-  if (!group.getObjectByName('text2')) {
+  if (!group?.getObjectByName('text2')) {
     const element = document.getElementById('outBox') as HTMLElement;
     const fanLocalCSS3D = new CSS3DObject(element);
     fanLocalCSS3D.name = 'text2';
     fanLocalCSS3D.scale.set(0.1, 0.1, 0.1);
     fanLocalCSS3D.rotation.y = -Math.PI / 2;
     fanLocalCSS3D.position.set(74.63, 13.54, 3.84);
-    group.add(fanLocalCSS3D);
+    group?.add(fanLocalCSS3D);
   }
-  if (!group.getObjectByName('text3')) {
+  if (!group?.getObjectByName('text3')) {
     const element = document.getElementById('returnBox') as HTMLElement;
     const fanLocalCSS3D = new CSS3DObject(element);
     fanLocalCSS3D.name = 'text3';
     fanLocalCSS3D.scale.set(0.1, 0.1, 0.1);
     fanLocalCSS3D.rotation.y = -Math.PI / 2;
     fanLocalCSS3D.position.set(35.28, 10.05, -37.23);
-    group.add(fanLocalCSS3D);
+    group?.add(fanLocalCSS3D);
   }
-  if (!group.getObjectByName('text4')) {
+  if (!group?.getObjectByName('text4')) {
     const element = document.getElementById('gateBox') as HTMLElement;
     if (element) {
       element.innerHTML = '';
@@ -248,10 +250,10 @@ export const addCssText = () => {
       fanLocalCSS3D.scale.set(0.04, 0.04, 0.04);
       fanLocalCSS3D.rotation.y = -Math.PI / 2;
       fanLocalCSS3D.position.set(-73.13, 8.44, -23.52);
-      group.add(fanLocalCSS3D);
+      group?.add(fanLocalCSS3D);
     }
   }
-  if (!group.getObjectByName('text5')) {
+  if (!group?.getObjectByName('text5')) {
     const element = document.getElementById('windownBox') as HTMLElement;
     if (element) {
       // element.innerHTML = '';
@@ -260,7 +262,7 @@ export const addCssText = () => {
       fanLocalCSS3D.scale.set(0.07, 0.07, 0.07);
       fanLocalCSS3D.rotation.y = -Math.PI / 2;
       fanLocalCSS3D.position.set(-28.44, 9.78, -40.42);
-      group.add(fanLocalCSS3D);
+      group?.add(fanLocalCSS3D);
     }
   }
 };
@@ -274,7 +276,7 @@ export const playSmoke = (controlType, deviceType, frequency, state) => {
   }
 };
 
-const initFly = () => {
+const initFly = async () => {
   const topCurve = [
     {
       path0: new THREE.Vector3(-94.84, 2.359, 3.61),
@@ -372,13 +374,13 @@ const initFly = () => {
   if (!topSmoke) {
     topSmoke = new Smoke('/model/img/texture-smoke.png', '#ffffff', 0, 0.8, 0.5, 400);
     topSmoke.setPath(topCurve);
-    topSmoke.setPoints();
+    await topSmoke.setPoints();
     group?.add(topSmoke.points);
   }
   if (!downSmoke) {
     downSmoke = new Smoke('/model/img/texture-smoke.png', '#ffffff', 0, 0.8, 0.5, 400);
     downSmoke.setPath(downCurve);
-    downSmoke.setPoints();
+    await downSmoke.setPoints();
     group?.add(downSmoke.points);
   }
 
@@ -387,6 +389,7 @@ const initFly = () => {
 };
 
 const runFly = (deviceType, state) => {
+  if (!downSmoke || !topSmoke) return;
   if (state === 'open') {
     if (deviceType === 'top') {
       if (downSmoke.frameId) {
@@ -411,6 +414,7 @@ const runFly = (deviceType, state) => {
 
 // 调频 30-50 (life 300 - 800) , 25 = (800 - 300)/ 20
 const setSmokeFrequency = (deviceType, frequency) => {
+  if (!downSmoke || !topSmoke) return;
   const life = (frequency - 30) * 25;
   const duration = (Math.abs(life - topSmoke.life) / 500) * 25;
   let smoke;
@@ -428,8 +432,9 @@ const setSmokeFrequency = (deviceType, frequency) => {
 };
 
 const clearFly = () => {
-  if (topSmoke) topSmoke.clearSmoke();
-  if (downSmoke) downSmoke.clearSmoke();
+  if (!downSmoke || !topSmoke) return;
+  topSmoke.clearSmoke();
+  downSmoke.clearSmoke();
 };
 // 初始化事件
 const startAnimation = () => {
@@ -441,24 +446,8 @@ const startAnimation = () => {
 };
 // 鼠标点击、松开事件
 const mouseEvent = (event) => {
-  event.stopPropagation();
-  const widthScale = appStore.getWidthScale;
-  const heightScale = appStore.getHeightScale;
-
-  // 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)
-  model.mouse.x =
-    ((-model.canvasContainer.getBoundingClientRect().left * widthScale + event.clientX) / (model.canvasContainer.clientWidth * widthScale)) * 2 - 1;
-  model.mouse.y =
-    -((-model.canvasContainer.getBoundingClientRect().top + event.clientY) / (model.canvasContainer.clientHeight * heightScale)) * 2 + 1;
-  // model.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) {
+  if (event.button == 0) {
+    mouseDownFn(<UseThree>model, <THREE.Object3D>group, event, (intersects) => {
       intersects.find((intersect) => {
         const mesh = intersect.object;
         if (mesh.name === 'player1') {
@@ -472,7 +461,8 @@ const mouseEvent = (event) => {
           return true;
         }
       });
-    }
+    });
+    console.log('摄像头控制信息', model?.orbitControls, model?.camera);
   }
 };
 export const mountedThree = (playerVal1) => {
@@ -480,7 +470,6 @@ export const mountedThree = (playerVal1) => {
   return new Promise((resolve) => {
     model = new UseThree('#fanLocal3D', '#fanLocal3DCSS');
     model.setEnvMap('test1');
-    model.renderer.toneMappingExposure = 1;
 
     resetCamera();
     model.setGLTFModel([modelName]).then(async (gltf) => {
@@ -489,17 +478,19 @@ export const mountedThree = (playerVal1) => {
 
       setModalPosition();
       setControls();
-      initFly();
+      await initFly();
       model.animate();
       addLight(model.scene);
 
       const videoPlayer1 = document.getElementById('jb-player1')?.getElementsByClassName('vjs-tech')[0];
       if (videoPlayer1) {
         const mesh = renderVideo(group, videoPlayer1, 'player1');
-        mesh.scale.set(0.222, 0.19, 0.2);
-        mesh.position.set(-84.87, 0.298, 24.76);
-        mesh.rotation.y = -Math.PI / 2;
-        group.add(mesh);
+        if (mesh) {
+          mesh.scale.set(0.222, 0.19, 0.2);
+          mesh.position.set(-84.87, 0.298, 24.76);
+          mesh.rotation.y = -Math.PI / 2;
+          group?.add(mesh);
+        }
       } else {
         const textArr = [
           {
@@ -543,11 +534,12 @@ export const mountedThree = (playerVal1) => {
 
 export const destroy = () => {
   if (model) {
+    model.isRender = false;
     clearFly();
-    model.deleteModal();
-    model = null;
-    group = null;
-    topSmoke = null;
-    downSmoke = null;
+    topSmoke = undefined;
+    downSmoke = undefined;
+    group = undefined;
+    model.destroy();
+    model = undefined;
   }
 };

+ 56 - 54
src/views/vent/monitorManager/balancePressMonitor1/index.vue

@@ -42,54 +42,57 @@
       {{ selectData.strinstallpos }}
     </div>
     <div class="bottom-tabs-box" @mousedown="setDivHeight($event, 240, scroll)">
-      <a-tabs class="tabs-box" v-model:activeKey="activeKey" @change="tabChange">
-        <a-tab-pane key="1" tab="实时监测">
-          <GroupMonitorTable  v-if="activeKey === '1' && isRefresh" :dataSource="dataSource" columnsType="sys_surface_junya" @selectRow="getSelectRow" :scroll="scroll"/>
-        </a-tab-pane>
-        <a-tab-pane key="2" tab="实时曲线图" force-render>
-          <div class="tab-item" v-if="activeKey === '2' && isRefresh">
-            <div class="vent-flex-row-between" style="height: 100%">
-              <BarSingle
-                :xAxisData="[
-                  { key: 'T1', valueKey: 'gas1' },
-                  { key: 'T2', valueKey: 'gas2' },
-                  { key: 'T3', valueKey: 'gas3' },
-                  { key: 'T4', valueKey: 'gas4' },
-                ]"
-                :dataSource="dataSource[selectRowIndex]"
-                height="100%"
-                :chartsColumns="chartsColumns"
-                style="flex: 3"
-              />
-              <BarSingle
-                :xAxisData="[
-                  { key: 'F1', valueKey: 'windQuantity1' },
-                  { key: 'F2', valueKey: 'windQuantity2' },
-                ]"
-                :dataSource="dataSource[selectRowIndex]"
-                height="100%"
-                :chartsColumns="chartsColumns1"
-                style="flex: 2"
-              />
+      <dv-border-box8 :dur="5"  :style="`padding: 5px; height: ${scroll.y + 100}px`" >
+      
+        <a-tabs class="tabs-box" v-model:activeKey="activeKey" @change="tabChange">
+          <a-tab-pane key="1" tab="实时监测">
+            <GroupMonitorTable ref="MonitorDataTable"  v-if="activeKey === '1' " :dataSource="dataSource" columnsType="sys_surface_junya" @selectRow="getSelectRow" :scroll="scroll"/>
+          </a-tab-pane>
+          <a-tab-pane key="2" tab="实时曲线图" force-render>
+            <div class="tab-item" v-if="activeKey === '2' ">
+              <div class="vent-flex-row-between" style="height: 100%">
+                <BarSingle
+                  :xAxisData="[
+                    { key: 'T1', valueKey: 'gas1' },
+                    { key: 'T2', valueKey: 'gas2' },
+                    { key: 'T3', valueKey: 'gas3' },
+                    { key: 'T4', valueKey: 'gas4' },
+                  ]"
+                  :dataSource="dataSource[selectRowIndex]"
+                  height="100%"
+                  :chartsColumns="chartsColumns"
+                  style="flex: 3"
+                />
+                <BarSingle
+                  :xAxisData="[
+                    { key: 'F1', valueKey: 'windQuantity1' },
+                    { key: 'F2', valueKey: 'windQuantity2' },
+                  ]"
+                  :dataSource="dataSource[selectRowIndex]"
+                  height="100%"
+                  :chartsColumns="chartsColumns1"
+                  style="flex: 2"
+                />
+              </div>
             </div>
-          </div>
-        </a-tab-pane>
-        <a-tab-pane key="3" tab="历史数据">
-          <div class="tab-item" v-if="activeKey === '3' && isRefresh">
-            <HistoryTable columns-type="sys_surface_junya" device-type="sys_surface_junya" :device-list-api="baseList" designScope="sys_surface_junya-history" />
-          </div>
-        </a-tab-pane>
-        <a-tab-pane key="4" tab="报警历史">
-          <div class="tab-item" v-if="activeKey === '4' && isRefresh">
-            <AlarmHistoryTable columns-type="alarm" device-type="sys_surface_junya" :device-list-api="baseList" designScope="alarm-history" />
-          </div>
-        </a-tab-pane>
-        <a-tab-pane key="5" tab="操作历史">
-          <div class="tab-item" v-if="activeKey === '5' && isRefresh">
-            <HandlerHistoryTable columns-type="operatorhistory" device-type="sys_surface_junya" :device-list-api="baseList" designScope="alarm-history" />
-          </div>
-        </a-tab-pane>
-      </a-tabs>
+          </a-tab-pane>
+          <a-tab-pane key="3" tab="历史数据">
+            <div class="tab-item" v-if="activeKey === '3' ">
+              <HistoryTable columns-type="sys_surface_junya" device-type="sys_surface_junya" :device-list-api="baseList" designScope="sys_surface_junya-history" />
+            </div>
+          </a-tab-pane>
+          <a-tab-pane key="4" tab="报警历史">
+            <div class="tab-item" v-if="activeKey === '4' ">
+              <AlarmHistoryTable columns-type="alarm" device-type="sys_surface_junya" :device-list-api="baseList" designScope="alarm-history" />
+            </div>
+          </a-tab-pane>
+          <a-tab-pane key="5" tab="操作历史">
+            <div class="tab-item" v-if="activeKey === '5' ">
+              <HandlerHistoryTable columns-type="operatorhistory" device-type="sys_surface_junya" :device-list-api="baseList" designScope="alarm-history" />
+            </div>
+          </a-tab-pane>
+        </a-tabs>
+      </dv-border-box8>
     </div>
   </div>
   <div style="z-index: -1; position: absolute; top: 50px; right: 10px; width: 300px; height: 280px; margin: auto" class="player1">
@@ -111,8 +114,8 @@
   import { chartsColumns, chartsColumns1 } from './balancePress.data';
   import LivePlayer from '@liveqing/liveplayer-v3';
   import { setDivHeight } from '/@/utils/event';
+  import { BorderBox8 as DvBorderBox8 } from '@kjgl77/datav-vue3';
 
-  const isRefresh = ref(true)
   const scroll = reactive({
     y: 180
   })
@@ -144,6 +147,11 @@
 
   const tabChange = (activeKeyVal) => {
     activeKey.value = activeKeyVal;
+    // if (activeKeyVal == 1) {
+    //   nextTick(() => {
+    //     MonitorDataTable.value.setSelectedRowKeys([selectData.deviceID])
+    //   })
+    // }
   };
 
   const dataSource = ref([]);
@@ -210,12 +218,6 @@
     }
   };
 
-  watch(() => scroll.y, () => {
-    isRefresh.value = false
-    nextTick(() => {
-      isRefresh.value = true
-    })
-  })
 
   onBeforeMount(() => {
     getDeviceBaseList();

+ 44 - 48
src/views/vent/monitorManager/beltTunMonitor/beltTun.data.ts

@@ -39,7 +39,7 @@ export const echartsOption = reactive({
     type: 'category',
     boundaryGap: false,
     axisLine: { lineStyle: { color: '#8EAFB9' } },
-    axisLabel: { textStyle: { color: '#ffffffcc' } },
+    axisLabel: { color: '#ffffffcc' },
     splitLine: { show: true, lineStyle: { color: '#57617B22', type: 'dashed' } },
     data: [],
   },
@@ -51,7 +51,7 @@ export const echartsOption = reactive({
         show: false,
       },
       axisLine: { lineStyle: { show: true, color: '#8EAFB9' } },
-      axisLabel: { margin: 10, textStyle: { fontSize: 12, color: '#ffffffcc' } },
+      axisLabel: { margin: 10, fontSize: 12, color: '#ffffffcc' },
       splitLine: { show: true, lineStyle: { color: '#57617B22', type: 'dashed' } },
     },
   ],
@@ -60,70 +60,66 @@ export const echartsOption = reactive({
       name: '风量',
       type: 'bar',
       smooth: true,
-      lineStyle: { normal: { width: 2 } },
+      lineStyle: { width: 2 },
       yAxisIndex: 0,
       // markLine: {
       //   data: [{ yAxis: 0, name: '需风量' }],
       // },
       areaStyle: {
-        normal: {
-          color: new echarts.graphic.LinearGradient(
-            0,
-            0,
-            0,
-            1,
-            [
-              {
-                offset: 0,
-                color: 'rgba(185,150,248,0.3)',
-              },
-              {
-                offset: 0.8,
-                color: 'rgba(185,150,248,0)',
-              },
-            ],
-            false
-          ),
-          shadowColor: 'rgba(0, 0, 0, 0.1)',
-          shadowBlur: 10,
-        },
+        color: new echarts.graphic.LinearGradient(
+          0,
+          0,
+          0,
+          1,
+          [
+            {
+              offset: 0,
+              color: 'rgba(185,150,248,0.3)',
+            },
+            {
+              offset: 0.8,
+              color: 'rgba(185,150,248,0)',
+            },
+          ],
+          false
+        ),
+        shadowColor: 'rgba(0, 0, 0, 0.1)',
+        shadowBlur: 10,
       },
-      itemStyle: { normal: { color: '#B996F8' } },
+      itemStyle: { color: '#B996F8' },
       data: [],
     },
     {
       name: '风速',
       type: 'line',
       smooth: true,
-      lineStyle: { normal: { width: 2 } },
+      lineStyle: { width: 2 },
       yAxisIndex: 0,
       // markLine: {
       //   data: [{ yAxis: 0, name: '需风量' }],
       // },
       areaStyle: {
-        normal: {
-          color: new echarts.graphic.LinearGradient(
-            0,
-            0,
-            0,
-            1,
-            [
-              {
-                offset: 0,
-                color: 'rgba(3, 194, 236, 0.3)',
-              },
-              {
-                offset: 0.8,
-                color: 'rgba(3, 194, 236, 0)',
-              },
-            ],
-            false
-          ),
-          shadowColor: 'rgba(0, 0, 0, 0.1)',
-          shadowBlur: 10,
-        },
+        color: new echarts.graphic.LinearGradient(
+          0,
+          0,
+          0,
+          1,
+          [
+            {
+              offset: 0,
+              color: 'rgba(3, 194, 236, 0.3)',
+            },
+            {
+              offset: 0.8,
+              color: 'rgba(3, 194, 236, 0)',
+            },
+          ],
+          false
+        ),
+        shadowColor: 'rgba(0, 0, 0, 0.1)',
+        shadowBlur: 10,
       },
-      itemStyle: { normal: { color: '#03C2EC' } },
+      itemStyle: { color: '#03C2EC' },
       data: [],
     },
   ],

+ 21 - 18
src/views/vent/monitorManager/beltTunMonitor/beltTun.threejs.base.ts

@@ -7,9 +7,10 @@ import { FXAAShader } from 'three/examples/jsm/shaders/FXAAShader.js';
 import { UnrealBloomPass } from 'three/examples/jsm/postprocessing/UnrealBloomPass.js';
 import { GammaCorrectionShader } from 'three/examples/jsm/shaders/GammaCorrectionShader.js';
 import { CSS3DObject } from 'three/examples/jsm/renderers/CSS3DRenderer.js';
-// import * as dat from 'dat.gui';
-// const gui = new dat.GUI();
-// gui.domElement.style = 'position:absolute;top:100px;left:10px;z-index:99999999999999';
+
+import * as dat from 'dat.gui';
+const gui = new dat.GUI();
+gui.domElement.style = 'position:absolute;top:100px;left:10px;z-index:99999999999999';
 
 class WorkFace {
   model;
@@ -39,20 +40,21 @@ class WorkFace {
     this.group.name = this.modelName;
   }
   addLight() {
-    const directionalLight = new THREE.DirectionalLight(0xffffff, 1.2);
-    directionalLight.position.set(-0.8, 23, 3.9);
+    // const _this = this;
+    const directionalLight = new THREE.DirectionalLight(0xffffff, 3);
+    directionalLight.position.set(-98, 183, -131);
     this.group.add(directionalLight);
     directionalLight.target = this.group;
 
-    // gui.add(directionalLight.position, 'x', -10, 20).onChange(function (value) {
+    // gui.add(directionalLight.position, 'x', -500, 500).onChange(function (value) {
     //   directionalLight.position.x = Number(value);
     //   _this.render();
     // });
-    // gui.add(directionalLight.position, 'y', -50, 50).onChange(function (value) {
+    // gui.add(directionalLight.position, 'y', -500, 500).onChange(function (value) {
     //   directionalLight.position.y = Number(value);
     //   _this.render();
     // });
-    // gui.add(directionalLight.position, 'z', -20, 20).onChange(function (value) {
+    // gui.add(directionalLight.position, 'z', -500, 500).onChange(function (value) {
     //   directionalLight.position.z = Number(value);
     //   _this.render();
     // });
@@ -66,17 +68,17 @@ class WorkFace {
     // pointLight7.shadow.bias = 0.05;
     // this.model.scene.add(pointLight7);
 
-    const spotLight = new THREE.SpotLight();
-    spotLight.angle = Math.PI / 2;
-    spotLight.penumbra = 0;
-    spotLight.castShadow = true;
-    spotLight.intensity = 1;
+    // const spotLight = new THREE.SpotLight();
+    // spotLight.angle = Math.PI / 2;
+    // spotLight.penumbra = 0;
+    // spotLight.castShadow = true;
+    // spotLight.intensity = 1;
 
-    spotLight.shadow.camera.near = 0.5; // default
-    spotLight.shadow.focus = 1.2;
-    spotLight.shadow.bias = -0.000002;
+    // spotLight.shadow.camera.near = 0.5; // default
+    // spotLight.shadow.focus = 1.2;
+    // spotLight.shadow.bias = -0.000002;
 
-    spotLight.position.set(-7.19, 199, -68.1);
+    // spotLight.position.set(-7.19, 199, -68.1);
     // this.group.add(spotLight);
 
     // gui.add(directionalLight.position, 'x', -10, 20).onChange(function (value) {
@@ -220,7 +222,7 @@ class WorkFace {
       new THREE.TextureLoader().load('/model/img/texture-smoke.png', (texture) => {
         texture.encoding = THREE.sRGBEncoding;
         const material = new THREE.PointsMaterial({
-          color: '#FFFFAF',
+          color: '#FFFFFF',
           size: 0.03,
           map: texture,
           transparent: true, // 开启透明度
@@ -239,6 +241,7 @@ class WorkFace {
         this.group.add(pointLines);
 
         resolve(null);
+        texture.dispose();
       });
     });
   };

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

@@ -2,55 +2,38 @@ import * as THREE from 'three';
 import UseThree from '../../../../utils/threejs/useThree';
 import WorkFace from './beltTun.threejs.base';
 import { animateCamera } from '/@/utils/threejs/util';
-import { useAppStore } from '/@/store/modules/app';
+import useEvent from '../../../../utils/threejs/useEvent';
 
 // 模型对象、 文字对象
 let model,
-  beltTunObj: WorkFace,
-  group,
+  beltTunObj: WorkFace | undefined,
+  group: THREE.Object3D | undefined,
   fiberType = 'beltTun'; // workerFaceFiber
-const appStore = useAppStore();
+const { mouseDownFn } = useEvent();
 
 // 鼠标点击、松开事件
 const mouseEvent = (event) => {
-  event.stopPropagation();
-  const widthScale = appStore.getWidthScale;
-  const heightScale = appStore.getHeightScale;
-  // 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)
-  model.mouse.x =
-    ((-model.canvasContainer.getBoundingClientRect().left * widthScale + event.clientX) / (model.canvasContainer.clientWidth * widthScale)) * 2 - 1;
-  model.mouse.y =
-    -((-model.canvasContainer.getBoundingClientRect().top + event.clientY) / (model.canvasContainer.clientHeight * heightScale)) * 2 + 1;
-  (model.rayCaster as THREE.Raycaster).setFromCamera(model.mouse, model.camera as THREE.Camera);
-  if (group) {
-    if (fiberType === 'beltTun') {
-      beltTunObj.mousedownModel.call(beltTunObj, model.rayCaster);
-    }
-    console.log(model.camera, model.orbitControls);
-    // const intersects = model.rayCaster?.intersectObjects([...group.children]) as THREE.Intersection[];
-    // if (intersects.length > 0) {
-    //   if (fiberType === 'beltFiber') {
-    //     beltFiberObj.mousedownModel.call(beltFiberObj, intersects);
-    //   } else if (fiberType === 'beltTun') {
-    //     beltTunObj.mousedownModel.call(beltTunObj, intersects);
-    //   }
-    // }
+  if (event.button == 0) {
+    mouseDownFn(<UseThree>model, <THREE.Object3D>group, event, (intersects) => {
+      // beltTunObj?.mousedownModel.call(beltTunObj, model.rayCaster);
+    });
+    console.log('摄像头控制信息', model?.orbitControls, model?.camera);
   }
 };
 
 const addMouseEvent = () => {
   // 定义鼠标点击事件
   model.canvasContainer?.addEventListener('mousedown', mouseEvent.bind(null));
-  model.canvasContainer?.addEventListener('pointerup', (event) => {
-    event.stopPropagation();
-    if (fiberType === 'beltTun') {
-      beltTunObj.mouseUpModel.call(beltTunObj);
-    }
-  });
+  // model.canvasContainer?.addEventListener('pointerup', (event) => {
+  //   event.stopPropagation();
+  //   if (fiberType === 'beltTun') {
+  //     beltTunObj?.mouseUpModel.call(beltTunObj);
+  //   }
+  // });
 };
 
 const render = () => {
-  if (model.animationId != -1) {
+  if (model && model.isRender) {
     model.animationId = requestAnimationFrame(render);
     model.css3dRender?.render(model.scene as THREE.Scene, model.camera as THREE.PerspectiveCamera);
     model.stats?.update();
@@ -59,7 +42,7 @@ const render = () => {
 
 export const refreshModal = () => {
   if (fiberType === 'beltTun') {
-    beltTunObj.render();
+    beltTunObj?.render();
   }
 };
 
@@ -67,7 +50,7 @@ export const refreshModal = () => {
 export const setModelType = (type) => {
   fiberType = type;
   return new Promise((resolve) => {
-    if (fiberType === 'beltTun' && beltTunObj) {
+    if (fiberType === 'beltTun' && beltTunObj && beltTunObj.group) {
       group = beltTunObj.group;
 
       // const oldCameraPosition = { x: 124.736, y: 63.486, z: 103.337 };
@@ -87,7 +70,7 @@ export const setModelType = (type) => {
           { x: 0, y: 0, z: 0 },
           model,
           0.8,
-          beltTunObj.render.bind(beltTunObj)
+          beltTunObj?.render.bind(beltTunObj)
         );
       }, 600);
     }
@@ -98,7 +81,7 @@ export const mountedThree = () => {
   return new Promise(async (resolve) => {
     model = new UseThree('#beltTun3D', '#beltTun3DCSS');
     model.setEnvMap('test1');
-    model.renderer.toneMappingExposure = 1;
+    model.renderer.toneMappingExposure = 1.0;
     model.camera.position.set(100, 0, 1000);
     beltTunObj = new WorkFace(model);
     await beltTunObj.mountedThree();
@@ -111,10 +94,13 @@ export const mountedThree = () => {
 
 export const destroy = () => {
   if (model) {
-    beltTunObj.destroy();
-    model.deleteModal();
+    model.isRender = false;
+    console.log('场景销毁前信息----------->', model.renderer?.info);
+    group = undefined;
+
+    beltTunObj?.destroy();
+    beltTunObj = undefined;
+    model.destroy();
     model = null;
-    group = null;
-    beltTunObj = null;
   }
 };

+ 1 - 0
src/views/vent/monitorManager/beltTunMonitor/components/beltTunHandleHistory.vue

@@ -35,6 +35,7 @@ watch(() => props.deviceType, (newVal) => {
 </script>
 <style lang="less" scoped>
 .handle-history {
+  width: 100%;
   pointer-events: auto;
 }
 </style>

+ 4 - 13
src/views/vent/monitorManager/chamberMonitor/chamber.threejs.base.ts

@@ -14,22 +14,13 @@ class ChamberBase {
 
   addLight() {
     const directionalLight = new THREE.DirectionalLight(0xffffff, 1.2);
-    directionalLight.position.set(-0.8, 23, 3.9);
+    directionalLight.position.set(15, 69, -39);
     this.group?.add(directionalLight);
     directionalLight.target = this.group as THREE.Object3D;
 
-    // gui.add(directionalLight.position, 'x', -10, 20).onChange(function (value) {
-    //   directionalLight.position.x = Number(value);
-    //   _this.render();
-    // });
-    // gui.add(directionalLight.position, 'y', -50, 50).onChange(function (value) {
-    //   directionalLight.position.y = Number(value);
-    //   _this.render();
-    // });
-    // gui.add(directionalLight.position, 'z', -20, 20).onChange(function (value) {
-    //   directionalLight.position.z = Number(value);
-    //   _this.render();
-    // });
+    // gui.add(directionalLight.position, 'x', -100, 100);
+    // gui.add(directionalLight.position, 'y', -100, 100);
+    // gui.add(directionalLight.position, 'z', -100, 100);
 
     // gui.add(spotLight.position, 'x', -600, 600).onChange(function (value) {
     //   spotLight.position.x = Number(value);

+ 27 - 26
src/views/vent/monitorManager/chamberMonitor/chamber.threejs.ts

@@ -5,30 +5,32 @@ import { animateCamera, setModalCenter } from '/@/utils/threejs/util';
 import useEvent from '../../../../utils/threejs/useEvent';
 
 // 模型对象、 文字对象
-let model,
-  chamberBaseObj: ChamberBase,
-  group,
+let model: UseThree | undefined,
+  chamberBaseObj: ChamberBase | undefined,
+  group: THREE.Object3D | undefined,
   chamberType = 'chamberBase';
 
 const { mouseDownFn } = useEvent();
 
 // 鼠标点击事件
 const mouseEvent = (event) => {
-  mouseDownFn(model, group, event, (intersects) => {
-    if (chamberType === 'chamberBase') {
-      // chamberBaseObj.mousedownModel.call(chamberBaseObj, intersects);
-    }
-  });
-  console.log('摄像头控制信息', model.orbitControls, model.camera);
+  if (event.button == 0) {
+    mouseDownFn(<UseThree>model, <THREE.Object3D>group, event, (intersects) => {
+      if (chamberType === 'chamberBase') {
+        // chamberBaseObj.mousedownModel.call(chamberBaseObj, intersects);
+      }
+    });
+    console.log('摄像头控制信息', model?.orbitControls, model?.camera);
+  }
 };
 
 const addMouseEvent = () => {
   // 定义鼠标点击事件
-  model.canvasContainer?.addEventListener('mousedown', mouseEvent.bind(null));
+  model?.canvasContainer?.addEventListener('mousedown', mouseEvent.bind(null));
 };
 
 const render = () => {
-  if (model.animationId != -1) {
+  if (model && model.isRender) {
     model.animationId = requestAnimationFrame(render);
     model.css3dRender?.render(model.scene as THREE.Scene, model.camera as THREE.PerspectiveCamera);
     model.stats?.update();
@@ -45,17 +47,17 @@ export const addChamberText = (selectData) => {
 export const setModelType = (type) => {
   chamberType = type;
   return new Promise((resolve) => {
-    if (chamberType === 'chamberBase') {
+    if (chamberType === 'chamberBase' && chamberBaseObj && chamberBaseObj.group) {
       group = chamberBaseObj.group;
       const oldCameraPosition = { x: 124.736, y: 63.486, z: 103.337 };
-      model.scene.add(chamberBaseObj.group);
-      setModalCenter(model.scene);
-      model.camera.position.set(0, 0, 300);
+      model?.scene?.add(chamberBaseObj.group);
+      setModalCenter(model?.scene);
+      model?.camera?.position.set(0, 0, 300);
       setTimeout(async () => {
         await animateCamera(
           oldCameraPosition,
-          {x: 0, y: 0, z: 0},
-          { x: 11.19, y: 400.13, z: 344.20 },
+          { x: 0, y: 0, z: 0 },
+          { x: 11.19, y: 400.13, z: 344.2 },
           { x: 10.446, y: 0.875, z: -0.993 },
           model,
           0.8
@@ -71,14 +73,11 @@ export const mountedThree = () => {
   return new Promise(async (resolve) => {
     model = new UseThree('#chamber3D');
     model.setEnvMap('test1');
-    model.renderer.toneMappingExposure = 1;
-    // model.camera.position.set(100, 0, 1000);
+    model.renderer.toneMappingExposure = 1.0;
 
     chamberBaseObj = new ChamberBase(model);
     await chamberBaseObj.mountedThree();
 
-    // model.scene.add(chamberBaseObj.group);
-
     addMouseEvent();
     // render();
     model.animate();
@@ -88,10 +87,12 @@ export const mountedThree = () => {
 
 export const destroy = () => {
   if (model) {
-    chamberBaseObj.destroy();
-    model.deleteModal();
-    model = null;
-    group = null;
-    chamberBaseObj = null;
+    model.isRender = false;
+    console.log('场景销毁前信息----------->', model.renderer?.info);
+    chamberBaseObj?.destroy();
+    chamberBaseObj = undefined;
+    group = undefined;
+    model.destroy();
+    model = undefined;
   }
 };

+ 1 - 0
src/views/vent/monitorManager/chamberMonitor/components/chamberHandleHistory.vue

@@ -20,6 +20,7 @@ import { getTableList } from '../chamber.api'
 </script>
 <style lang="less" scoped>
 .handle-history {
+  width: 100%;
   pointer-events: auto;
 }
 </style>

+ 11 - 2
src/views/vent/monitorManager/comment/AlarmHistoryTable.vue

@@ -33,7 +33,7 @@
     },
     scroll: {
       type: Object,
-      default: () => { }
+      default: { y: 0 }
     },
     list: {
       type: Function,
@@ -42,6 +42,7 @@
   });
   const alarmHistory = ref()
   const columns = ref([])
+  const tableScroll = props.scroll.y ? ref({ y: props.scroll.y - 100 }) : ref({})
 
   watch(
     () => {
@@ -69,6 +70,14 @@
     }
   );
 
+  watch(() => props.scroll.y, (newVal) => {
+    if (newVal) {
+      tableScroll.value = { y: newVal - 100 }
+    } else {
+      tableScroll.value = {}
+    }}
+  )
+
   // 列表页面公共参数、方法
   const { tableContext } = useListPage({
     tableProps: {
@@ -79,7 +88,7 @@
       showActionColumn: false,
       bordered: false,
       size: 'small',
-      scroll: props.scroll,
+      scroll: tableScroll,
       formConfig: {
         labelAlign: 'left',
         showAdvancedButton: false,

+ 40 - 2
src/views/vent/monitorManager/comment/DeviceEcharts.vue

@@ -14,6 +14,7 @@
         height="100%"
         :chartsColumns="chartsColumns"
         chartsType="listMonitor"
+        :option="echartsOption"
       />
     </div>
     <div class="charts-box" v-else-if="chartsType === 'detail' && deviceListApi">
@@ -83,6 +84,7 @@
         :dataSource="resultDataSource"
         height="100%"
         :chartsColumns="chartsColumns"
+        :option="echartsOption1"
         chartsType="history"
       />
     </div>
@@ -145,9 +147,37 @@
       const currentPage = ref<number>(1);
       const pageSize = ref<number>(20);
       const total = ref(0);
+
+      const echartsOption = {
+        grid: {
+          top: '60px',
+          left: '10px',
+          right: '5px',
+          bottom: '5%',
+          containLabel: true,
+        },
+        toolbox: {
+          feature: {},
+        },
+      };
+      const echartsOption1 = {
+        grid: {
+          top: '60px',
+          left: '10px',
+          right: '5px',
+          bottom: '10%',
+          containLabel: true,
+        },
+        toolbox: {
+          feature: {},
+        },
+      };
+
+
       const onChange = (pageNumber: number) => {
         console.log('Page: ', pageNumber);
       };
+
       watch(
         [chartsType, deviceId, historyParams, pageSize, currentPage,],
         async (
@@ -204,8 +234,10 @@
 
       onMounted(async () => {
         const res = await props.deviceListApi();
-        options.value = res.records;
-        deviceId.value = options.value[0]['id'];
+        if(res && res.records){
+          options.value = res.records;
+          deviceId.value = options.value[0]['id'];
+        }
       });
 
       return {
@@ -219,6 +251,8 @@
         currentPage,
         pageSize,
         total,
+        echartsOption,
+        echartsOption1,
         onChange,
       };
     },
@@ -230,7 +264,11 @@
     position: relative;
     height: 100%;
     .charts-box {
+      width: 100%;
       height: 100%;
+      position: absolute;
+      bottom: 0;
+      top: 20px;
     }
     .@{ventSpace}-picker,
     .@{ventSpace}-select-selector {

+ 11 - 1
src/views/vent/monitorManager/comment/GroupMonitorTable.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="vent-table">
     <a-radio-group v-model:value="selectRowIndex" @change="setSelectedRowKeys" style="width: 100%">
-      <a-table :columns="columns" :pagination="false" :data-source="dataTableSource" bordered style="margin-top: 5px" :scroll="scroll">
+      <a-table :columns="columns" :pagination="false" :data-source="dataTableSource" bordered style="margin-top: 5px" :scroll="tableScroll">
         <template #bodyCell="{ column, record }">
           <template v-if="column.dataIndex === 'isCheck'">
             <a-radio :value="record.deviceID" />
@@ -49,6 +49,7 @@
   const emits = defineEmits(['selectRow']);
   const dataTableSource = ref<any[]>([]);
   const loading = ref(true);
+  const tableScroll = props.scroll.y ? ref({ y: props.scroll.y }) : ref({})
 
   // 默认初始是第一行
   const selectRowIndex = ref(0);
@@ -175,6 +176,15 @@
       loading.value = false;
     }
   );
+  
+  watch(() => props.scroll.y, (newVal) => {
+    if (newVal) {
+      tableScroll.value = { y: newVal }
+    } else {
+      tableScroll.value = {}
+    }
+  }
+  )
 
   onMounted(() => {
     // 如果是https

+ 12 - 3
src/views/vent/monitorManager/comment/HandlerHistoryTable.vue

@@ -36,13 +36,14 @@
     },
     scroll: {
       type: Object,
-      default: () => {}
+      default: { y: 0 }
     }
   });
   
   const handlerHistory = ref()
   const columns = ref([])
-
+  const tableScroll = props.scroll.y ? ref({ y: props.scroll.y - 100 }) : ref({})
+  
   watch(
     () => {
       return props.columnsType;
@@ -69,6 +70,14 @@
     }
   );
 
+  watch(() => props.scroll.y, (newVal) => {
+  if (newVal) {
+    tableScroll.value = { y: newVal - 100 }
+  } else {
+    tableScroll.value = {}
+  }
+})
+
   // 列表页面公共参数、方法
   const { tableContext } = useListPage({
     tableProps: {
@@ -79,7 +88,7 @@
       showActionColumn: false,
       bordered: false,
       size: 'small',
-      scroll: props.scroll,
+      scroll: tableScroll,
       formConfig: {
         labelAlign: 'left',
         showAdvancedButton: false,

+ 55 - 35
src/views/vent/monitorManager/comment/HistoryTable.vue

@@ -11,11 +11,13 @@
 <script lang="ts" name="system-user" setup>
   //ts语法
   import { watchEffect, ref, watch, defineExpose } from 'vue';
+  import { FormSchema } from '/@/components/Form/index';
   import { BasicTable } from '/@/components/Table';
   import { useListPage } from '/@/hooks/system/useListPage';
   import { getTableHeaderColumns } from '/@/hooks/web/useWebColumns';
   import { defHttp } from '/@/utils/http/axios';
   import dayjs from 'dayjs';
+
   const historyTable = ref();
   const list = (params) => defHttp.get({ url: '/safety/ventanalyMonitorData/list', params });
   const emit = defineEmits(['change']);
@@ -40,37 +42,49 @@
     },
     scroll: {
       type: Object,
-      default: () => { }
+      default: { y: 0 }
+    },
+    formSchemas: {
+      type: Array<FormSchema>,
+      default: () => []
     }
   });
   const columns = ref([])
+  const tableScroll = props.scroll.y ? ref({ y: props.scroll.y - 100 }) : ref({})
 
   watch(
-  () => {
-    return props.columnsType;
-  },
-  (newVal) => {
-    debugger
-    const column = getTableHeaderColumns(newVal + '_history')
-    if (column && column.length < 1) {
-      const arr = newVal.split('_')
-      const columnKey = arr.reduce((prev, cur, index) => {
-        if (index !== arr.length - 2) {
-          return prev + '_' + cur
-        } else {
-          return prev
-        }
-      })
-      columns.value = getTableHeaderColumns(arr[0] + '_history');
-    } else {
-      columns.value = column
+    () => {
+      return props.columnsType;
+    },
+    (newVal) => {
+      const column = getTableHeaderColumns(newVal + '_history')
+      if (column && column.length < 1) {
+        const arr = newVal.split('_')
+        const columnKey = arr.reduce((prev, cur, index) => {
+          if (index !== arr.length - 2) {
+            return prev + '_' + cur
+          } else {
+            return prev
+          }
+        })
+        columns.value = getTableHeaderColumns(arr[0] + '_history');
+      } else {
+        columns.value = column
+      }
+      if(historyTable.value) reload()
+    },
+    {
+      immediate: true
     }
-    if(historyTable.value) reload()
-  },
-  {
-    immediate: true
-  }
-);
+  );
+
+  watch(() => props.scroll.y, (newVal) => {
+    if(newVal){
+      tableScroll.value = {y: newVal - 100 }
+    }else{
+      tableScroll.value = {}
+    }
+  })
 
   // 列表页面公共参数、方法
   const { tableContext } = useListPage({
@@ -82,7 +96,7 @@
       showActionColumn: false,
       bordered: false,
       size: 'small',
-      scroll: props.scroll,
+      scroll: tableScroll,
       formConfig: {
         labelAlign: 'left',
         showAdvancedButton: false,
@@ -97,7 +111,7 @@
           xl: 7,
           xxl: 4,
         },
-        schemas: [
+        schemas: props.formSchemas.length > 0 ? props.formSchemas : [
           {
             label: '查询日期',
             field: 'tData',
@@ -120,11 +134,13 @@
             label: '查询设备',
             field: 'gdeviceid',
             component: 'ApiSelect',
+            required: true,
             componentProps: {
-              api: props.deviceListApi,
-              resultField: 'records',
-              labelField: 'strname',
+              api: () => defHttp.get({ url: '/safety/ventanalyManageSystem/linkdevicelist', params: { sysId: props.sysId, deviceType: props.deviceType } }),
+              // resultField: 'result',
+              labelField: 'strinstallpos',
               valueField: 'id',
+              // numberToString: true,
             },
           },
           {
@@ -161,17 +177,19 @@
       },
       fetchSetting: {
         listField: 'datalist.records',
-      },
-      pagination: {
-        current: 1,
-        pageSize: 5,
-        pageSizeOptions: ['5', '10', '20'],
+        pageField: 'datalist.pages',
+        sizeField: 'datalist.size',
+        totalField: 'datalist.total',
       },
       beforeFetch(params) {
+        debugger
         params.strtype = props.deviceType + '*';
         if(props.sysId){
           params.sysId = props.sysId;
         }
+        debugger
+        if(params['datalist.pages'])params['pages'] = params['datalist.pages']
+        if (params['datalist.size']) params['pageSize'] = params['datalist.size']
       },
       afterFetch(resultItems) {
         resultItems.map((item) => {
@@ -192,6 +210,8 @@
     }
   });
 
+  
+
   defineExpose({ setLoading })
 </script>
 

+ 23 - 4
src/views/vent/monitorManager/comment/MonitorTable.vue

@@ -24,6 +24,9 @@
   import { useListPage } from '/@/hooks/system/useListPage';
   import { getTableHeaderColumns } from '/@/hooks/web/useWebColumns';
   import { findIndex } from 'lodash-es';
+  import { FormProps } from '/@/components/Form';
+
+
   const props = defineProps({
     columnsType: {
       type: String,
@@ -53,7 +56,7 @@
     },
     scroll: {
       type: Object,
-      default: () => null
+      default: {y: 0}
     },
     title: {
       type: String,
@@ -62,6 +65,10 @@
       type: String,
       default: 'small',
     },
+    formConfig: {
+      type: Object as PropType<FormProps> | undefined,
+      default: undefined
+    }
   });
   const emits = defineEmits(['selectRow']);
   const dataTableSource = ref<any[]>([]);
@@ -71,6 +78,7 @@
 
   const tableMaxHeight = 150;
   const columns = ref([])
+  const tableScroll = props.scroll.y ?  ref({y: props.scroll.y}) : ref({})
   
   watch(
     () => {
@@ -117,6 +125,15 @@
     }
   );
 
+  watch(() => props.scroll.y, (newVal) => {
+    if (newVal) {
+      tableScroll.value = { y: newVal }
+    } else {
+      tableScroll.value = {}
+    }
+    }
+  )
+
   // 列表页面公共参数、方法
   const { prefixCls, tableContext, doRequest } = useListPage({
     designScope: props.designScope,
@@ -124,15 +141,16 @@
       title: props.title,
       dataSource: dataTableSource,
       columns: columns,
-      rowSelection: { type: props.isShowSelect? 'radio': undefined },
+      rowSelection: { type: props.isShowSelect? 'radio': undefined, columnWidth: 100 },
       size: props.size,
       useSearchForm: false,
       showTableSetting: false,
       showActionColumn: props.isShowActionColumn,
       maxHeight: tableMaxHeight,
       bordered: false,
-      scroll: props.scroll,
+      scroll: tableScroll,
       rowKey: 'deviceID',
+      formConfig: props.formConfig,
       // striped: true,
       loading: true,
       actionColumn: {
@@ -150,7 +168,7 @@
   });
 
   //注册table数据
-  const [registerTable, { reload, setLoading, setSelectedRowKeys }, { rowSelection, selectedRowKeys,  }] = tableContext;
+  const [registerTable, { reload, setLoading, setSelectedRowKeys, getSelectRowKeys }, { rowSelection, selectedRowKeys,  }] = tableContext;
   watch(
     selectedRowKeys,
     (oldKeys, newKeys) => {
@@ -165,6 +183,7 @@
   defineExpose({
     doRequest,
     setSelectedRowKeys,
+    getSelectRowKeys,
     setLoading
   });
 

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

@@ -23,7 +23,7 @@
     },
     deviceListApi: {
       type: Function,
-      required: true,
+      default: (params) => defHttp.get({ url: '/safety/ventanalyManageSystem/linkdevicelist', params })
     },
     designScope: {
       type: String,

+ 1 - 0
src/views/vent/monitorManager/compressor/components/nitrogenEcharts.vue

@@ -223,6 +223,7 @@
     color: #fff;
     overflow: scroll;
     top: 100px;
+    left: 0;
     display: flex;
     flex-direction: column;
     z-index: 99999;

+ 1 - 0
src/views/vent/monitorManager/compressor/components/nitrogenHandleHistory.vue

@@ -10,6 +10,7 @@
 </script>
 <style lang="less" scoped>
   .handle-history{
+    width: 100%;
     position: fixed;
     top: 80px;
   }

+ 2 - 2
src/views/vent/monitorManager/compressor/components/nitrogenHome.vue

@@ -130,7 +130,7 @@
   
 </template>
 <script lang="ts" setup name="nitrogenHome">
-import { onMounted, onUnmounted, ref, watch } from 'vue'
+import { onMounted, onUnmounted, ref, watch, reactive } from 'vue'
 import ventBox1 from '/@/components/vent/ventBox1.vue'
 import fourBorderBg from '../../../comment/components/fourBorderBg.vue'
 import { mountedThree, destroy } from '../nitrogen.threejs'
@@ -153,7 +153,7 @@ const flvURL1 = () => {
 
 const monitorDataGroupNum = ref(0);
 
-const airCompressorState = ref([
+const airCompressorState = reactive([
   {
     id: '',
     compressRunSigF1: false,

+ 45 - 49
src/views/vent/monitorManager/compressor/nitrogen.data.ts

@@ -48,7 +48,7 @@ export const zhudanOption = reactive({
     type: 'category',
     boundaryGap: false,
     axisLine: { lineStyle: { color: '#57617B' } },
-    axisLabel: { textStyle: { color: '#ffffffcc' } },
+    axisLabel: { color: '#ffffffcc' },
     splitLine: { show: true, lineStyle: { color: '#57617B22', type: 'dashed' } },
     data: [],
   },
@@ -62,7 +62,7 @@ export const zhudanOption = reactive({
       },
       position: 'left',
       axisLine: { lineStyle: { show: true, color: '#57617B' } },
-      axisLabel: { margin: 10, textStyle: { fontSize: 12, color: '#ffffffcc' } },
+      axisLabel: { margin: 10, fontSize: 12, color: '#ffffffcc' },
       splitLine: { show: true, lineStyle: { color: '#57617B22', type: 'dashed' } },
     },
     {
@@ -74,7 +74,7 @@ export const zhudanOption = reactive({
       },
       position: 'right',
       axisLine: { lineStyle: { show: true, color: '#57617B' } },
-      axisLabel: { margin: 10, textStyle: { fontSize: 12, color: '#ffffffcc' } },
+      axisLabel: { margin: 10, fontSize: 12, color: '#ffffffcc' },
       splitLine: { show: true, lineStyle: { color: '#57617B22', type: 'dashed' } },
     },
   ],
@@ -84,32 +84,30 @@ export const zhudanOption = reactive({
       type: 'line',
 
       smooth: true,
-      lineStyle: { normal: { width: 2 } },
+      lineStyle: { width: 2 },
       yAxisIndex: 0,
       areaStyle: {
-        normal: {
-          color: new echarts.graphic.LinearGradient(
-            0,
-            0,
-            0,
-            1,
-            [
-              {
-                offset: 0,
-                color: 'rgba(185,150,248,0.3)',
-              },
-              {
-                offset: 0.8,
-                color: 'rgba(185,150,248,0)',
-              },
-            ],
-            false
-          ),
-          shadowColor: 'rgba(0, 0, 0, 0.1)',
-          shadowBlur: 10,
-        },
+        color: new echarts.graphic.LinearGradient(
+          0,
+          0,
+          0,
+          1,
+          [
+            {
+              offset: 0,
+              color: 'rgba(185,150,248,0.3)',
+            },
+            {
+              offset: 0.8,
+              color: 'rgba(185,150,248,0)',
+            },
+          ],
+          false
+        ),
+        shadowColor: 'rgba(0, 0, 0, 0.1)',
+        shadowBlur: 10,
       },
-      itemStyle: { normal: { color: '#B996F8' } },
+      itemStyle: { color: '#B996F8' },
       data: [],
     },
     {
@@ -117,32 +115,30 @@ export const zhudanOption = reactive({
       type: 'line',
 
       smooth: true,
-      lineStyle: { normal: { width: 2 } },
+      lineStyle: { width: 2 },
       yAxisIndex: 0,
       areaStyle: {
-        normal: {
-          color: new echarts.graphic.LinearGradient(
-            0,
-            0,
-            0,
-            1,
-            [
-              {
-                offset: 0,
-                color: 'rgba(3, 194, 236, 0.3)',
-              },
-              {
-                offset: 0.8,
-                color: 'rgba(3, 194, 236, 0)',
-              },
-            ],
-            false
-          ),
-          shadowColor: 'rgba(0, 0, 0, 0.1)',
-          shadowBlur: 10,
-        },
+        color: new echarts.graphic.LinearGradient(
+          0,
+          0,
+          0,
+          1,
+          [
+            {
+              offset: 0,
+              color: 'rgba(3, 194, 236, 0.3)',
+            },
+            {
+              offset: 0.8,
+              color: 'rgba(3, 194, 236, 0)',
+            },
+          ],
+          false
+        ),
+        shadowColor: 'rgba(0, 0, 0, 0.1)',
+        shadowBlur: 10,
       },
-      itemStyle: { normal: { color: '#03C2EC' } },
+      itemStyle: { color: '#03C2EC' },
       data: [],
     },
   ],

+ 4 - 23
src/views/vent/monitorManager/compressor/nitrogen.dishang.threejs.ts

@@ -24,19 +24,13 @@ class Nitrogen {
 
   addLight() {
     const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
-    directionalLight.position.set(75, 96, 177);
+    directionalLight.position.set(32, -1, 60);
     this.group.add(directionalLight);
     directionalLight.target = this.group;
 
-    // gui.add(directionalLight.position, 'x', -500, 500).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);
-    // });
+    // gui.add(directionalLight.position, 'x', -500, 500)
+    // gui.add(directionalLight.position, 'y', -500, 500)
+    // gui.add(directionalLight.position, 'z', -200, 200)
 
     const spotLight = new THREE.SpotLight();
     spotLight.angle = Math.PI / 4;
@@ -144,19 +138,6 @@ class Nitrogen {
           if (i == 3) nitrogenMonitorCSS3D.position.set(-0.89, 0.31, 0.12);
           nitrogenModal.add(nitrogenMonitorCSS3D);
         }
-        // if (!nitrogenModal.getObjectByName('cqgMonitorText')) {
-        //   const element = document.getElementById('cqgMonitor' + (i + 1)) as HTMLElement;
-        //   element.style.top = '0px';
-        //   element.style.left = '0px';
-        //   const cqgMonitorCSS3D = new CSS3DSprite(element);
-        //   cqgMonitorCSS3D.name = 'cqgMonitorText';
-        //   cqgMonitorCSS3D.scale.set(0.003, 0.003, 0.003);
-        //   if (i == 0) cqgMonitorCSS3D.position.set(1.24, 0.49, 0.0);
-        //   if (i == 1) cqgMonitorCSS3D.position.set(1.24, 0.49, 0.04);
-        //   if (i == 2) cqgMonitorCSS3D.position.set(1.24, 0.49, 0.08);
-        //   if (i == 3) cqgMonitorCSS3D.position.set(1.24, 0.49, 0.12);
-        //   nitrogenModal.add(cqgMonitorCSS3D);
-        // }
       }
     }
   };

+ 27 - 22
src/views/vent/monitorManager/compressor/nitrogen.threejs.ts

@@ -8,49 +8,51 @@ import useEvent from '../../../../utils/threejs/useEvent';
 // gui.domElement.style = 'position:absolute;top:100px;left:10px;z-index:99999999999999';
 
 // 模型对象、 文字对象
-let model, //
-  group,
-  nitrogenObj,
+let model: UseThree | undefined, //
+  group: THREE.Object3D | undefined,
+  nitrogenObj: Nitrogen | undefined,
   modalType = 'nitrogen';
 
 const { mouseDownFn } = useEvent();
 
 // 鼠标点击、松开事件
 const mouseEvent = (event) => {
-  mouseDownFn(model, group, event, (intersects) => {
-    if (modalType === 'nitrogen') {
-      nitrogenObj.mousedownModel.call(nitrogenObj, intersects);
-    }
-    console.log('摄像头控制信息', model.orbitControls, model.camera);
-  });
+  if (event.button == 0) {
+    mouseDownFn(model as UseThree, group as THREE.Object3D, event, (intersects) => {
+      if (modalType === 'nitrogen') {
+        nitrogenObj?.mousedownModel.call(nitrogenObj, intersects);
+      }
+      console.log('摄像头控制信息', model?.orbitControls, model?.camera);
+    });
+  }
 };
 
 /* 添加监控数据 */
-export const addText = (selectData) => {
-  if (modalType === 'nitrogen') {
-    return nitrogenObj.addText.call(nitrogenObj, selectData);
-  }
-};
+// export const addText = (selectData) => {
+//   if (modalType === 'nitrogen') {
+//     return nitrogenObj?.addText?.call(nitrogenObj, selectData);
+//   }
+// };
 
 export const play = () => {
   if (modalType === 'nitrogen') {
-    return nitrogenObj.play.call(nitrogenObj);
+    return nitrogenObj?.play.call(nitrogenObj);
   }
 };
 
 // 切换风窗类型
 export const setModelType = (type) => {
   modalType = type;
-  model.camera.position.set(-1000, 100, 500);
+  model?.camera?.position.set(-1000, 100, 500);
 
   return new Promise((resolve) => {
     // 显示双道风窗
-    if (modalType === 'nitrogen') {
+    if (modalType === 'nitrogen' && nitrogenObj && nitrogenObj.group) {
       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);
+      model?.scene?.add(nitrogenObj.group);
       let newCameraPosition = { x: 0, y: 0, z: 0 },
         newControlsPosition = { x: 0, y: 0, z: 0 };
       if (group.children.length == 5) {
@@ -75,7 +77,7 @@ export const mountedThree = (nitrogenNum) => {
   return new Promise(async (resolve) => {
     model = new UseThree('#nitrogen3D', '#nitrogenCss3D');
     model.setEnvMap('test1');
-    model.renderer.toneMappingExposure = 0.8;
+    model.renderer.toneMappingExposure = 1.0;
     model.canvasContainer?.addEventListener('mousedown', mouseEvent.bind(null));
     nitrogenObj = new Nitrogen(model);
     await nitrogenObj.mountedThree(nitrogenNum);
@@ -87,9 +89,12 @@ export const mountedThree = (nitrogenNum) => {
 
 export const destroy = () => {
   if (model) {
+    model.isRender = false;
+    console.log('场景销毁前信息----------->', model.renderer?.info);
     nitrogenObj?.destroy();
-    model.deleteModal();
-    model = null;
-    group = null;
+    nitrogenObj = undefined;
+    group = undefined;
+    model.destroy();
+    model = undefined;
   }
 };

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

@@ -4,8 +4,10 @@ enum Api {
   list = '/ventanaly-device/monitor/device',
   baseList = '/safety/ventanalyDeviceInfo/list',
   // deviceTypeList = '/safety/ventanalyDeviceInfo/DeviceKind/query',
-  deviceTypeList = '/sys/dict/DeviceKind/queryBySystem',
+  // deviceTypeList = '/sys/dict/DeviceKind/queryBySystem',
+  deviceTypeList = '/safety/ventanalyDeviceInfo/DeviceKind/queryBySystem',
   itemList = '/sys/dictItem/list',
+
 }
 /**
  * 列表接口

+ 65 - 0
src/views/vent/monitorManager/deviceMonitor/components/device/device.data.ts

@@ -1,3 +1,7 @@
+
+import { FormSchema } from '/@/components/Table';
+import dayjs from 'dayjs';
+
 export const chartsColumns = (deviceType) => {
   if (deviceType === '') {
     return [];
@@ -45,3 +49,64 @@ export const locationList = [
     isVisible: 0,
   },
 ];
+
+// export const searchFormSchema: FormSchema[] = [
+//   {
+//     label: '查询日期',
+//     field: 'tData',
+//     component: 'DatePicker',
+//     defaultValue: dayjs(),
+//     componentProps: {
+//       valueFormat: 'YYYY-MM-DD',
+//     },
+//   },
+//   {
+//     label: '时间区间',
+//     field: 'tickectDate',
+//     component: 'TimeRangePicker',
+//     componentProps: {
+//       placeholder: ['开始时间', '结束时间'],
+//       valueFormat: 'HH:mm:ss',
+//     },
+//   },
+//   {
+//     label: '设备类型',
+//     field: 'gdeviceid',
+//     component: 'ApiSelect',
+//     componentProps: {
+//       api: props.deviceListApi,
+//       resultField: 'records',
+//       labelField: 'strname',
+//       valueField: 'id',
+//     },
+//   },
+//   {
+//     label: '间隔时间',
+//     field: 'skip',
+//     component: 'Select',
+//     componentProps: {
+//       options: [
+//         {
+//           label: '5秒',
+//           value: '1',
+//         },
+//         {
+//           label: '10秒',
+//           value: '2',
+//         },
+//         {
+//           label: '1分钟',
+//           value: '3',
+//         },
+//         {
+//           label: '5分钟',
+//           value: '4',
+//         },
+//         {
+//           label: '10分钟',
+//           value: '5',
+//         },
+//       ],
+//     },
+//   },
+// ];

+ 30 - 38
src/views/vent/monitorManager/deviceMonitor/components/device/index.vue

@@ -1,5 +1,6 @@
 <template>
   <div class="scene-box">
+    <!-- <div class="top-header">智能通风管理系统</div> -->
     <div class="select-node" :class="{ 'node-select-show': !treeShow, 'node-select-hide': treeShow, }"
       @click="showTree('treeShow', true)">
       <SvgIcon class="is-expansion-icon put-away-icon" size="38" name="expansion" />
@@ -45,8 +46,10 @@
         </div>
       </div>
     </div>
-    <div>
-      <div class="bottom-tabs-box" @mousedown="setDivHeight($event, 250, scroll)" id="monitorBox">
+    
+      <div class="bottom-tabs-box" @mousedown="setDivHeight($event, 230, scroll)" id="monitorBox">
+        <dv-border-box8 :dur="5"  :style="`padding: 5px; height: ${scroll.y + 100}px`" >
+
         <div class="to-small" @click="toHome"></div>
         <div class="device-button-group" v-if="deviceList.length > 0">
           <div class="device-button" :class="{ 'device-active': deviceActive == device.deviceType }"
@@ -57,12 +60,12 @@
           </div>
         </div>
 
-        <a-tabs class="tabs-box" v-model:activeKey="activeKey" @change="tabChange">
+        <a-tabs class="tabs-box" v-model:activeKey="activeKey" @change="tabChange" id="tabsBox" v-if="isRefresh">
           <a-tab-pane key="1" tab="实时监测">
-            <template v-if="deviceType == 'fan' && activeKey == '1' && isRefresh">
+            <template v-if="deviceType == 'fan' && activeKey == '1'">
               <GroupMonitorTable :dataSource="dataSource" :columnsType="`${deviceType}_monitor`" />
             </template>
-            <template v-else-if="activeKey == '1' && isRefresh">
+            <template v-else-if="activeKey == '1'">
               <MonitorTable ref="monitorTable" :columnsType="`${deviceType}_monitor`" :dataSource="dataSource"
                 design-scope="device_monitor" :isShowPagination="false" :isShowActionColumn="true" title="设备监测"
                 :scroll="scroll">
@@ -142,32 +145,32 @@
           </a-tab-pane>
           <a-tab-pane key="2" tab="历史数据">
             <div class="tab-item">
-              <HistoryTable ref="historyTable" v-if="activeKey == '2' && isRefresh" :sysId="systemID"
+              <HistoryTable ref="historyTable" v-if="activeKey == '2'" :sysId="systemID"
                 :columns-type="`${deviceType}`" :device-type="deviceType"
-                :device-list-api="getDeviceList.bind(null, { strtype: deviceType, sysId: systemID })"
+                :device-list-api="getDeviceList.bind(null, { devicekind: deviceType, sysId: systemID })"
                 designScope="device-history" :scroll="scroll" />
             </div>
           </a-tab-pane>
           <a-tab-pane key="3" tab="报警历史">
             <div class="tab-item">
-              <AlarmHistoryTable ref="alarmHistoryTable" v-if="activeKey == '3' && isRefresh" :sysId="systemID"
+              <AlarmHistoryTable ref="alarmHistoryTable" v-if="activeKey == '3'" :sysId="systemID"
                 columns-type="alarm" :device-type="deviceType"
-                :device-list-api="getDeviceList.bind(null, { strtype: deviceType, sysId: systemID })" :scroll="scroll"
+                :device-list-api="getDeviceList.bind(null, { devicekind: deviceType, sysId: systemID })" :scroll="scroll"
                 designScope="alarm-history" />
             </div>
           </a-tab-pane>
           <a-tab-pane key="4" tab="操作历史">
             <div class="tab-item">
-              <HandlerHistoryTable ref="handlerHistoryTable" v-if="activeKey == '4' && isRefresh" :sysId="systemID"
+              <HandlerHistoryTable ref="handlerHistoryTable" v-if="activeKey == '4'" :sysId="systemID"
                 columns-type="operatorhistory" :device-type="deviceType"
-                :device-list-api="getDeviceList.bind(null, { strtype: deviceType, sysId: systemID })" :scroll="scroll"
+                :device-list-api="getDeviceList.bind(null, { devicekind: deviceType, sysId: systemID })" :scroll="scroll"
                 designScope="operator-history" />
             </div>
           </a-tab-pane>
         </a-tabs>
-
+        </dv-border-box8>
       </div>
-    </div>
+    
     <component v-if="modalVisible" :is="currentModal" v-model:visible="modalVisible" :dataSource="dataSource"
       :activeID="activeID" />
   </div>
@@ -191,6 +194,7 @@ import { SvgIcon } from '/@/components/Icon';
 import { getActions } from '/@/qiankun/state';
 import { useRouter } from 'vue-router';
 import { setDivHeight } from '/@/utils/event';
+import { BorderBox8 as DvBorderBox8 } from '@kjgl77/datav-vue3';
 
 
 type DeviceType = { deviceType: string, deviceName: string, datalist: any[] };
@@ -213,7 +217,7 @@ const alarmHistoryTable = ref()
 const handlerHistoryTable = ref()
 
 // const routerParam = ref('home') // 默认进来时首页
-
+const isRefresh = ref(true)
 // 模态框
 const currentModal = shallowRef<Nullable<ComponentOptions>>(null); //模态框
 const modalVisible = ref<Boolean>(false); // 模态框是否可见
@@ -234,14 +238,14 @@ const systemType = ref('')
 const systemID = ref('') // 系统监测时,系统id
 const selectedKeys = ref<string[]>([]);
 const expandedKeys = ref<string[]>(['0-0-0-1']);
-const isRefresh = ref(true)
 const scroll = reactive({
-  y: 240
+  y: 220
 })
 const treeData = ref<TreeProps['treeData']>([]);
 
 //树形菜单选择事件
 const onSelect: TreeProps['onSelect'] = (keys, e) => {
+  
   deviceType.value = ''
   systemID.value = ''
   deviceList.value = []
@@ -255,18 +259,10 @@ const onSelect: TreeProps['onSelect'] = (keys, e) => {
     systemType.value = e.node.type
     deviceType.value = e.node.type
   }
-  selectedKeys.values = keys
+  selectedKeys.value = keys
   treeNodeTitle.value = e.node.title
-  if (timer) clearTimeout(timer)
-  timer = undefined
-  if (monitorTable.value) monitorTable.value.setLoading(true)
-  nextTick(() => {
-    setTimeout(() => {
-      timer = null
-      getMonitor()
-    }, 0)
-  })
 
+  dataSource.value = []
 };
 
 function tabChange(activeKeyVal) {
@@ -501,12 +497,7 @@ function setLocation() {
   }, 600)
 }
 
-watch(() => scroll.y, () => {
-  isRefresh.value = false
-  nextTick(() => {
-    isRefresh.value = true
-  })
-})
+
 
 onMounted(async () => {
   await getDeviceType()
@@ -537,7 +528,7 @@ onUnmounted(() => {
 @import '/@/design/vent/modal.less';
 @ventSpace: zxm;
 
-.device-header {
+.top-header{
   position: fixed;
   width: 100%;
   height: 56px;
@@ -547,9 +538,10 @@ onUnmounted(() => {
   font-size: 28px;
   color: #ffffffdd;
   font-weight: 600;
-  z-index: -1;
+  z-index: 1;
+  letter-spacing: 2px;
+  font-size: 30px;
 }
-
 .select-node {
   position: fixed;
   top: 60px;
@@ -863,6 +855,7 @@ onUnmounted(() => {
 .bottom-tabs-box {
 
   position: relative;
+  height: 320px !important;
 
   .to-small {
     width: 60px;
@@ -870,7 +863,7 @@ onUnmounted(() => {
     background: url('/@/assets/images/vent/home/tosmall.png') no-repeat center;
     background-size: auto;
     position: absolute;
-    top: -62px;
+    top: -65px;
     right: 36px;
     border-radius: 10px;
     padding: 8px;
@@ -884,8 +877,7 @@ onUnmounted(() => {
 
   .device-button-group {
     position: absolute;
-    top: -27px;
-    left: 30px;
+    top: -30px;
     display: flex;
     width: 100%;
 

+ 1 - 0
src/views/vent/monitorManager/deviceMonitor/components/device/modal/bundle.modal.vue

@@ -365,6 +365,7 @@ export default defineComponent({
               -webkit-text-fill-color: transparent;
               position: relative;
               top: -8px;
+              
               span{
                 font-family: Arial, Helvetica, sans-serif;
                 font-size: 18px;

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác