Преглед изворни кода

[Mod 0000] 皮带三级防灭火系统模型完成了接口对接,并优化了模型是监测数据弹框

hongrunxia пре 1 месец
родитељ
комит
56b3b55c91

+ 318 - 318
src/views/vent/home/configurable/belt/belt-new.vue

@@ -40,298 +40,252 @@
 </template>
 
 <script setup lang="ts">
-import { onMounted, ref, watch, nextTick } from 'vue';
-import customHeader from './components/customHeader-belt.vue';
-import { useInitConfigs, useInitPage } from '../hooks/useInit';
-import { testBeltNew, testYjkf, testSpary } from './configurable.data';
-import ModuleCommon from './components/ModuleCommon.vue';
-import Three3D from '/@/views/vent/home/configurable/components/three3D.vue';
-import BeltNav from './components/BeltNav.vue';
-import { useRouter, useRoute } from 'vue-router';
-import { getSystem, getMonitorAndAlertBelt, getDevice, getDataHome, getWarnResult } from './configurable.api';
-import { modalAnimate } from './threejs/belt.threejs';
-import History from './components/detail/history.vue';
-import sys from '/@/locales/lang/en/sys';
-// 初始化配置
-const { configs, fetchConfigs } = useInitConfigs();
-const { updateEnhancedConfigs, updateData, data } = useInitPage('矿井全域皮带巷三级防灭火系统');
-const isInitModal = ref(false);
-const pageCache = ref({
-  fire_risk_warn: { configs: testBeltNew },
-  emergencyControl: { configs: testYjkf },
-  sprayControl: { configs: testSpary },
-});
+  import { onMounted, ref, watch, nextTick } from 'vue';
+  import customHeader from './components/customHeader-belt.vue';
+  import { useInitConfigs, useInitPage } from '../hooks/useInit';
+  import { testBeltNew, testYjkf, testSpary } from './configurable.data';
+  import ModuleCommon from './components/ModuleCommon.vue';
+  import Three3D from '/@/views/vent/home/configurable/components/three3D.vue';
+  import BeltNav from './components/BeltNav.vue';
+  import { useRouter, useRoute } from 'vue-router';
+  import { getSystem, getMonitorAndAlertBelt, getDevice, getDataHome, getWarnResult } from './configurable.api';
+  import { modalAnimate } from './threejs/belt.threejs';
+  import History from './components/detail/history.vue';
+  import sys from '/@/locales/lang/en/sys';
+  // 初始化配置
+  const { configs, fetchConfigs } = useInitConfigs();
+  const { updateEnhancedConfigs, updateData, data } = useInitPage('矿井全域皮带巷三级防灭火系统');
+  const isInitModal = ref(false);
+  const pageCache = ref({
+    fire_risk_warn: { configs: testBeltNew },
+    emergencyControl: { configs: testYjkf },
+    sprayControl: { configs: testSpary },
+  });
 
-const pageType = ref('fire_risk_warn');
-const route = useRoute();
-const modalMonitorData = ref({});
-// 下拉框选项
-/** 场景选项 */
-const options = ref([]);
-const optionValue = ref('');
-async function getSysDataSource() {
-  const res = await getDataHome({ dataList: 'risk_evaluator' }).catch(() => {});
-  options.value = res.risk_evaluator || [];
-  await nextTick();
-  if (options.value.length > 0 && !optionValue.value) {
-    const firstId = options.value[0].sys_id;
-    changeSelectRow(firstId);
+  const pageType = ref('fire_risk_warn');
+  const route = useRoute();
+  const modalMonitorData = ref({});
+  // 下拉框选项
+  /** 场景选项 */
+  const options = ref([]);
+  const optionValue = ref('');
+  async function getSysDataSource() {
+    const res = await getDataHome({ dataList: 'risk_evaluator' }).catch(() => {});
+    options.value = res.risk_evaluator || [];
+    await nextTick();
+    if (options.value.length > 0 && !optionValue.value) {
+      const firstId = options.value[0].sys_id;
+      changeSelectRow(firstId);
+    }
   }
-}
-// 切换检测数据
-function changeSelectRow(deviceID) {
-  optionValue.value = deviceID;
-  refresh();
-}
-function goToHistory() {
-  if (pageType.value === 'history') {
-    // 当前是历史页 → 切回默认页
-    pageType.value = 'fire_risk_warn';
-  } else {
-    // 当前不是 → 打开历史页
-    pageType.value = 'history';
+  // 切换检测数据
+  function changeSelectRow(deviceID) {
+    optionValue.value = deviceID;
+    refresh();
   }
-}
-// 刷新数据
-async function refresh() {
-  // await fetchConfigs('sys_Leather');
+  function goToHistory() {
+    if (pageType.value === 'history') {
+      // 当前是历史页 → 切回默认页
+      pageType.value = 'fire_risk_warn';
+    } else {
+      // 当前不是 → 打开历史页
+      pageType.value = 'history';
+    }
+  }
+  // 刷新数据
+  async function refresh() {
+    // await fetchConfigs('sys_Leather');
 
-  //   if (pageType.value === 'fire_risk_warn') {
-  //     configs.value = testBeltNew;
-  //     const res = await getMonitorAndAlertBelt({
-  //       sysId: '2028657172566073346',
-  //       dataList: 'fire_risk_warn,warn_result,vehicle_co_correlate',
-  //     });
-  //     updateData(res);
-  //   } else if (pageType.value === 'emergencyControl') {
-  //     configs.value = testYjkf;
-  //     const res = await getSystem({
-  //       devicetype: 'sys',
-  //       systemID: '2028657172566073346',
-  //       type: 'ventS',
-  //     });
-  //     updateData(res);
-  //   } else if (pageType.value === 'sprayControl') {
-  //     const params = {
-  //       devicetype: 'sys',
-  //       systemID: '2028657172566073346',
-  //     };
-  //     Promise.resolve(getDevice(params)).then((originalData) => {
-  //       updateData(originalData);
-  //       const sprayData: any[] = [];
-  //       if (data.value?.msgTxt) {
-  //         data.value.msgTxt.forEach((item) => {
-  //           const hasSprayAuto = item.type && item.type.toLowerCase().includes('spray_auto');
-  //           if (hasSprayAuto) {
-  //             sprayData.push({
-  //               ...item,
-  //               ...item.readData,
-  //             });
-  //           }
-  //         });
-  //       }
-  //       data.value.sprayData = sprayData;
-  //       updateData(data.value);
-  //     });
-  //     configs.value = testSpary;
-  //   }
-  //   if (isFirst) initialized.value = true;
+    //   if (pageType.value === 'fire_risk_warn') {
+    //     configs.value = testBeltNew;
+    //     const res = await getMonitorAndAlertBelt({
+    //       sysId: '2028657172566073346',
+    //       dataList: 'fire_risk_warn,warn_result,vehicle_co_correlate',
+    //     });
+    //     updateData(res);
+    //   } else if (pageType.value === 'emergencyControl') {
+    //     configs.value = testYjkf;
+    //     const res = await getSystem({
+    //       devicetype: 'sys',
+    //       systemID: '2028657172566073346',
+    //       type: 'ventS',
+    //     });
+    //     updateData(res);
+    //   } else if (pageType.value === 'sprayControl') {
+    //     const params = {
+    //       devicetype: 'sys',
+    //       systemID: '2028657172566073346',
+    //     };
+    //     Promise.resolve(getDevice(params)).then((originalData) => {
+    //       updateData(originalData);
+    //       const sprayData: any[] = [];
+    //       if (data.value?.msgTxt) {
+    //         data.value.msgTxt.forEach((item) => {
+    //           const hasSprayAuto = item.type && item.type.toLowerCase().includes('spray_auto');
+    //           if (hasSprayAuto) {
+    //             sprayData.push({
+    //               ...item,
+    //               ...item.readData,
+    //             });
+    //           }
+    //         });
+    //       }
+    //       data.value.sprayData = sprayData;
+    //       updateData(data.value);
+    //     });
+    //     configs.value = testSpary;
+    //   }
+    //   if (isFirst) initialized.value = true;
 
-  // 由于模型中需要用到风门的监测数据,这里进行公共调用(后期精确调用风门)
-  const modalRes = {};
-  const systemParams = {
-    devicetype: 'sys',
-    systemID: optionValue.value,
-  };
-  const resSys = await getSystem(systemParams);
-  Object.assign(modalRes, resSys);
-  if (pageType.value == 'fire_risk_warn') {
-    configs.value = [...testBeltNew];
-    const params = {
-      sysId: optionValue.value,
-      dataList: 'fire_risk_warn,warn_result,vehicle_co_correlate',
-      alarmLevel: '102,103,104',
+    // 由于模型中需要用到风门的监测数据,这里进行公共调用(后期精确调用风门)
+    const modalRes = {};
+    const systemParams = {
+      devicetype: 'sys',
+      systemID: optionValue.value,
     };
-    const resWarn = await getMonitorAndAlertBelt(params);
-    updateData(resWarn);
-    Object.assign(modalRes, resWarn);
-  } else if (pageType.value == 'emergencyControl') {
-    updateData(resSys);
-    configs.value = [...testYjkf];
-    const alarmParams = {
-      sysId: optionValue.value,
-      alarmLevel: '104',
-    };
-    const alarmRes = await getWarnResult(alarmParams);
-    if (alarmRes.warn_result) {
-      data.value.warn_result = alarmRes.warn_result;
-    }
-    updateData(data.value);
-  } else if (pageType.value == 'sprayControl') {
-    updateData(resSys);
-    const params1 = {
-      sysId: optionValue.value,
-      alarmLevel: '103,104',
-    };
-    const sprayData = [];
-    console.log(data.value, '=======');
-    if (data.value?.deviceInfo) {
-      // 遍历对象的所有 value
-      Object.values(data.value.deviceInfo).forEach((item) => {
-        const hasSprayAuto = item.type && item.type.toLowerCase().includes('spray');
-        if (hasSprayAuto) {
-          sprayData.push({ ...item, ...item.readData });
-        }
-      });
-    }
-    data.value.sprayData = sprayData;
-    const alarmRes = await getWarnResult(params1);
-    if (alarmRes.warn_result) {
-      data.value.warn_result = alarmRes.warn_result;
+    const resSys = await getSystem(systemParams);
+    Object.assign(modalRes, resSys);
+    if (pageType.value == 'fire_risk_warn') {
+      configs.value = [...testBeltNew];
+      const params = {
+        sysId: optionValue.value,
+        dataList: 'fire_risk_warn,warn_result,vehicle_co_correlate',
+        alarmLevel: '102,103,104',
+      };
+      const resWarn = await getMonitorAndAlertBelt(params);
+      updateData(resWarn);
+      Object.assign(modalRes, resWarn);
+    } else if (pageType.value == 'emergencyControl') {
+      updateData(resSys);
+      configs.value = [...testYjkf];
+      const alarmParams = {
+        sysId: optionValue.value,
+        alarmLevel: '104',
+      };
+      const alarmRes = await getWarnResult(alarmParams);
+      if (alarmRes.warn_result) {
+        data.value.warn_result = alarmRes.warn_result;
+      }
+      updateData(data.value);
+    } else if (pageType.value == 'sprayControl') {
+      updateData(resSys);
+      const params1 = {
+        sysId: optionValue.value,
+        alarmLevel: '103,104',
+      };
+      const sprayData = [];
+      console.log(data.value, '=======');
+      if (data.value?.deviceInfo) {
+        // 遍历对象的所有 value
+        Object.values(data.value.deviceInfo).forEach((item) => {
+          const hasSprayAuto = item.type && item.type.toLowerCase().includes('spray');
+          if (hasSprayAuto) {
+            sprayData.push({ ...item, ...item.readData });
+          }
+        });
+      }
+      data.value.sprayData = sprayData;
+      const alarmRes = await getWarnResult(params1);
+      if (alarmRes.warn_result) {
+        data.value.warn_result = alarmRes.warn_result;
+      }
+      configs.value = [...testSpary];
+    } else {
+      configs.value = testBeltNew;
     }
-    configs.value = [...testSpary];
-  } else {
-    configs.value = testBeltNew;
+    modalMonitorData.value = modalRes;
   }
-  modalMonitorData.value = modalRes;
-}
 
-// // 定时刷新
-function initInterval() {
-  setInterval(() => {
-    refresh();
-  }, 60000);
-}
+  // // 定时刷新
+  function initInterval() {
+    setInterval(() => {
+      refresh();
+    }, 60000);
+  }
 
-async function changePage(pageTypeStr) {
-  const target = pageTypeStr || route.query.pageType || 'fire_risk_warn';
-  if (pageType.value === target) return;
-  pageType.value = target;
-  configs.value = pageCache.value[target]?.configs || testBeltNew;
-  await nextTick();
-  await refresh();
-}
+  async function changePage(pageTypeStr) {
+    const target = pageTypeStr || route.query.pageType || 'fire_risk_warn';
+    if (pageType.value === target) return;
+    pageType.value = target;
+    configs.value = pageCache.value[target]?.configs || testBeltNew;
+    await nextTick();
+    await refresh();
+  }
 
-// watch(
-//   // 监听动态路由参数 :type
-//   () => route.params.type,
-//   (newVal) => {
-//     if (newVal) {
-//       console.log('切换页面类型:', newVal);
-//       refresh(); // 切换路由自动刷新
-//     }
-//   }
-// );
+  // watch(
+  //   // 监听动态路由参数 :type
+  //   () => route.params.type,
+  //   (newVal) => {
+  //     if (newVal) {
+  //       console.log('切换页面类型:', newVal);
+  //       refresh(); // 切换路由自动刷新
+  //     }
+  //   }
+  // );
 
-function initModalAnimate(modal) {
-  console.log('初始化模型', modal);
-  modal.isRender = true;
-  modalAnimate(modal, modalMonitorData);
-}
+  async function initModalAnimate(modal) {
+    console.log('初始化模型', modal);
+    modal.isRender = true;
+    await modalAnimate(modal, modalMonitorData);
+  }
 
-watch(
-  () => route.query.pageType,
-  (newQueryType) => {
-    if (newQueryType) {
-      changePage(newQueryType as string);
-    }
-  },
-  { immediate: true } // 初始化立刻执行
-);
+  watch(
+    () => route.query.pageType,
+    (newQueryType) => {
+      if (newQueryType) {
+        changePage(newQueryType as string);
+      }
+    },
+    { immediate: true } // 初始化立刻执行
+  );
 
-watch(
-  () => modalMonitorData.value,
-  (newData, oldData) => {
-    if (newData && !Object.keys(oldData).length) {
-      isInitModal.value = true;
+  watch(
+    () => modalMonitorData.value,
+    (newData, oldData) => {
+      if (newData && !Object.keys(oldData).length) {
+        isInitModal.value = true;
+      }
     }
-  }
-);
+  );
 
-onMounted(async () => {
-  await getSysDataSource();
-  await refresh();
-  initInterval();
-});
+  onMounted(async () => {
+    await getSysDataSource();
+    await refresh();
+    initInterval();
+  });
 </script>
 <style lang="less" scoped>
-.company-home {
-  background: url('/@/assets/images/beltFire/baseMap.png') no-repeat center;
-  width: 100%;
-  height: 100%;
-  color: @white;
-  position: relative;
-  font-family: 'Microsoft YaHei', sans-serif;
-  .top-bg {
-    width: 100%;
-    height: 56px;
-    position: absolute;
-    margin-top: 10px;
-    z-index: 1;
-  }
-  .header-container {
-    position: absolute;
-    top: 20px;
-    left: 20px;
-    z-index: 10;
-  }
-
-  .border {
-    width: 100%;
-    height: 94%;
-    background: url('/@/assets/images/beltFire/mainbj.png') no-repeat;
-    background-size: 100% 100%;
-    position: relative;
-    width: 100%;
-  }
-}
-
-.center-warning-container {
-  position: absolute;
-  left: 50%;
-  transform: translateX(-50%);
-  top: 50%;
-  width: 600px;
-  height: 200px;
-  background-color: rgba(0, 0, 0, 0.7);
-  border-radius: 10px;
-  padding: 15px;
-  box-shadow: 0 0 20px rgba(0, 255, 255, 0.3);
-  z-index: 5;
-  color: #fff;
-
-  .warning-header {
-    font-size: 18px;
-    font-weight: bold;
-    margin-bottom: 10px;
-    color: #ff6b6b;
-  }
-
-  .warning-list {
+  .company-home {
+    background: url('/@/assets/images/beltFire/baseMap.png') no-repeat center;
     width: 100%;
     height: 100%;
-    overflow-y: auto;
-    display: flex;
-    flex-direction: column;
-    gap: 8px;
-  }
-
-  .warning-item {
-    display: flex;
-    justify-content: space-between;
-    align-items: center;
-    padding: 8px;
-    background-color: rgba(0, 0, 0, 0.5);
-    border-radius: 5px;
-    border-left: 4px solid #ff6b6b;
+    color: @white;
+    position: relative;
+    font-family: 'Microsoft YaHei', sans-serif;
+    .top-bg {
+      width: 100%;
+      height: 56px;
+      position: absolute;
+      margin-top: 10px;
+      z-index: 1;
+    }
+    .header-container {
+      position: absolute;
+      top: 20px;
+      left: 20px;
+      z-index: 10;
+    }
 
-    .warning-time {
-      font-size: 14px;
-      color: #ccc;
+    .border {
+      width: 100%;
+      height: 94%;
+      background: url('/@/assets/images/beltFire/mainbj.png') no-repeat;
+      background-size: 100% 100%;
+      position: relative;
+      width: 100%;
     }
   }
 
-  // 中间预警结果区
   .center-warning-container {
     position: absolute;
     left: 50%;
@@ -375,67 +329,113 @@ onMounted(async () => {
         font-size: 14px;
         color: #ccc;
       }
+    }
 
-      .warning-level {
-        font-size: 14px;
+    // 中间预警结果区
+    .center-warning-container {
+      position: absolute;
+      left: 50%;
+      transform: translateX(-50%);
+      top: 50%;
+      width: 600px;
+      height: 200px;
+      background-color: rgba(0, 0, 0, 0.7);
+      border-radius: 10px;
+      padding: 15px;
+      box-shadow: 0 0 20px rgba(0, 255, 255, 0.3);
+      z-index: 5;
+      color: #fff;
+
+      .warning-header {
+        font-size: 18px;
         font-weight: bold;
-        padding: 4px 8px;
-        border-radius: 4px;
-        &.level-critical {
-          background-color: #ff6b6b;
-          color: white;
-        }
-        &.level-high {
-          background-color: #ffcc00;
-          color: black;
-        }
-        &.level-normal {
-          background-color: #66cc66;
-          color: white;
-        }
+        margin-bottom: 10px;
+        color: #ff6b6b;
       }
 
-      .warning-action {
-        .btn-start-spray {
-          background-color: #00e1ff;
-          color: #000;
-          border: none;
-          padding: 4px 10px;
+      .warning-list {
+        width: 100%;
+        height: 100%;
+        overflow-y: auto;
+        display: flex;
+        flex-direction: column;
+        gap: 8px;
+      }
+
+      .warning-item {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        padding: 8px;
+        background-color: rgba(0, 0, 0, 0.5);
+        border-radius: 5px;
+        border-left: 4px solid #ff6b6b;
+
+        .warning-time {
+          font-size: 14px;
+          color: #ccc;
+        }
+
+        .warning-level {
+          font-size: 14px;
+          font-weight: bold;
+          padding: 4px 8px;
           border-radius: 4px;
-          cursor: pointer;
-          font-size: 12px;
-          transition: all 0.3s;
-          &:hover {
-            background-color: #00c3e6;
+          &.level-critical {
+            background-color: #ff6b6b;
+            color: white;
+          }
+          &.level-high {
+            background-color: #ffcc00;
+            color: black;
+          }
+          &.level-normal {
+            background-color: #66cc66;
+            color: white;
+          }
+        }
+
+        .warning-action {
+          .btn-start-spray {
+            background-color: #00e1ff;
+            color: #000;
+            border: none;
+            padding: 4px 10px;
+            border-radius: 4px;
+            cursor: pointer;
+            font-size: 12px;
+            transition: all 0.3s;
+            &:hover {
+              background-color: #00c3e6;
+            }
           }
         }
       }
     }
-  }
 
-  // 巷道示意图
-  .belt-diagram {
-    position: absolute;
-    left: 50%;
-    transform: translateX(-50%);
-    bottom: 50px;
-    width: 800px;
-    height: 100px;
-    display: flex;
-    justify-content: center;
-    align-items: center;
+    // 巷道示意图
+    .belt-diagram {
+      position: absolute;
+      left: 50%;
+      transform: translateX(-50%);
+      bottom: 50px;
+      width: 800px;
+      height: 100px;
+      display: flex;
+      justify-content: center;
+      align-items: center;
 
-    img {
-      width: 100%;
-      height: 100%;
-      object-fit: contain;
+      img {
+        width: 100%;
+        height: 100%;
+        object-fit: contain;
+      }
     }
   }
-}
-.modal-box {
-  width: 100%;
-  height: 100%;
-  position: absolute;
-  z-index: 1;
-}
+  .modal-box {
+    width: 100%;
+    height: 100%;
+    position: absolute;
+    z-index: 1;
+  }
 </style>

+ 125 - 125
src/views/vent/home/configurable/belt/belt.vue

@@ -19,7 +19,7 @@
             :page-type="cfg.pageType"
             :data="data"
             :visible="true"
-            @clickItem="handleItemClick"
+            @click-item="handleItemClick"
             :active-id="currentSelectedId"
           />
         </template>
@@ -28,149 +28,149 @@
   </div>
 </template>
 <script setup lang="ts">
-import { onMounted, onUnmounted, ref } from 'vue';
-import customHeader from './components/customHeader-belt.vue';
-import { useInitConfigs, useInitPage } from '../hooks/useInit';
-import { testBeltLaneFire } from './configurable.data';
-import ModuleCommon from './components/ModuleCommon.vue';
-import SubApp from '/@/components/vent/micro/createSubApp.vue';
-import History from './components/detail/history.vue';
-import { getDataHome } from './configurable.api';
+  import { onMounted, onUnmounted, ref } from 'vue';
+  import customHeader from './components/customHeader-belt.vue';
+  import { useInitConfigs, useInitPage } from '../hooks/useInit';
+  import { testBeltLaneFire } from './configurable.data';
+  import ModuleCommon from './components/ModuleCommon.vue';
+  import SubApp from '/@/components/vent/micro/createSubApp.vue';
+  import History from './components/detail/history.vue';
+  import { getDataHome } from './configurable.api';
 
-const { configs, devicesTypes, fetchConfigs } = useInitConfigs();
-const { updateEnhancedConfigs, updateData, data } = useInitPage('矿井全域皮带巷三级防灭火系统');
+  const { configs, devicesTypes, fetchConfigs } = useInitConfigs();
+  const { updateEnhancedConfigs, updateData, data } = useInitPage('矿井全域皮带巷三级防灭火系统');
 
-const currentSelectedId = ref<string | number>('');
+  const currentSelectedId = ref<string | number>('');
 
-let timer = null;
-const showHistory = ref(false);
-// 接收子组件上报的点击事件,更新全局选中状态
-const handleItemClick = (item) => {
-  const clickId = item.id;
-  if (!clickId) return;
-  currentSelectedId.value = clickId;
-  console.log('爷组件已更新选中ID:', clickId);
-};
-function goToHistory() {
-  showHistory.value = !showHistory.value;
-}
+  let timer = null;
+  const showHistory = ref(false);
+  // 接收子组件上报的点击事件,更新全局选中状态
+  const handleItemClick = (item) => {
+    const clickId = item.id;
+    if (!clickId) return;
+    currentSelectedId.value = clickId;
+    console.log('爷组件已更新选中ID:', clickId);
+  };
+  function goToHistory() {
+    showHistory.value = !showHistory.value;
+  }
 
-// 数据筛选
-const filterDataById = (sourceData, clickId: string | number) => {
-  if (!sourceData || !clickId) return sourceData;
-  const id = String(clickId);
-  const monitor = sourceData.monitor_alert?.find((item) => String(item.sysId) === id);
-  const spray = sourceData.spray_control?.find((item) => String(item.sysId) === id);
-  const gate = sourceData.gate_control?.find((item) => String(item.sysId) === id);
-  return {
-    ...sourceData,
-    monitor_alert: monitor ? [monitor] : [],
-    spray_control: spray ? [spray] : [],
-    gate_control: gate ? [gate] : [],
+  // 数据筛选
+  const filterDataById = (sourceData, clickId: string | number) => {
+    if (!sourceData || !clickId) return sourceData;
+    const id = String(clickId);
+    const monitor = sourceData.monitor_alert?.find((item) => String(item.sysId) === id);
+    const spray = sourceData.spray_control?.find((item) => String(item.sysId) === id);
+    const gate = sourceData.gate_control?.find((item) => String(item.sysId) === id);
+    return {
+      ...sourceData,
+      monitor_alert: monitor ? [monitor] : [],
+      spray_control: spray ? [spray] : [],
+      gate_control: gate ? [gate] : [],
+    };
   };
-};
 
-// ==============================
-// 🔥 修复:正常拉取config,但不覆盖!保证 dataList 正常传参
-// ==============================
-function refresh() {
-  fetchConfigs('belt').then(() => {
-    // 🔥 关键:只有为空时才赋值,不重复覆盖!
-    if (!configs.value || configs.value.length === 0) {
-      configs.value = testBeltLaneFire;
-    }
+  // ==============================
+  // 🔥 修复:正常拉取config,但不覆盖!保证 dataList 正常传参
+  // ==============================
+  function refresh() {
+    fetchConfigs('belt').then(() => {
+      // 🔥 关键:只有为空时才赋值,不重复覆盖!
+      if (!configs.value || configs.value.length === 0) {
+        configs.value = testBeltLaneFire;
+      }
 
-    const dataListStr = configs.value
-      .filter((e) => e.deviceType)
-      .map((e) => e.deviceType)
-      .join(',');
+      const dataListStr = configs.value
+        .filter((e) => e.deviceType)
+        .map((e) => e.deviceType)
+        .join(',');
 
-    getDataHome({ dataList: dataListStr }).then((res: any) => {
-      res.spray_control = [
-        {
-          systemName: '东翼胶带运输大巷',
-          sysId: '2028657172566073346',
-          sysList: [{ netstatus: '1', deviceStatus: '1', plsy: '1#区域 1.4MPa', kzms: '手动' }],
-        },
-        {
-          sysId: '2046500718274756609',
-          systemName: '1101胶带运输顺槽',
-          sysList: [{ netstatus: '1', deviceStatus: '1', plqy: '2#区域', plsy: '1.6MPa', kzms: '自动' }],
-        },
-      ];
-      let showData = res;
+      getDataHome({ dataList: dataListStr }).then((res: any) => {
+        res.spray_control = [
+          {
+            systemName: '东翼胶带运输大巷',
+            sysId: '2028657172566073346',
+            sysList: [{ netstatus: '1', deviceStatus: '1', plsy: '1#区域 1.4MPa', kzms: '手动' }],
+          },
+          {
+            sysId: '2046500718274756609',
+            systemName: '1101胶带运输顺槽',
+            sysList: [{ netstatus: '1', deviceStatus: '1', plqy: '2#区域', plsy: '1.6MPa', kzms: '自动' }],
+          },
+        ];
+        let showData = res;
 
-      // 只要用户选过,就永远保持选中,绝不自动切走
-      if (currentSelectedId.value) {
-        showData = filterDataById(res, currentSelectedId.value);
-      }
-      // 从未选过 → 默认第一个
-      else {
-        const firstId = res.monitor_alert?.[0]?.sysId;
-        if (firstId) {
-          currentSelectedId.value = firstId;
-          showData = filterDataById(res, firstId);
+        // 只要用户选过,就永远保持选中,绝不自动切走
+        if (currentSelectedId.value) {
+          showData = filterDataById(res, currentSelectedId.value);
+        }
+        // 从未选过 → 默认第一个
+        else {
+          const firstId = res.monitor_alert?.[0]?.sysId;
+          if (firstId) {
+            currentSelectedId.value = firstId;
+            showData = filterDataById(res, firstId);
+          }
         }
-      }
 
-      updateData(showData);
+        updateData(showData);
+      });
     });
-  });
-}
-// 轮询
-function initInterval() {
-  if (timer) clearInterval(timer);
-  timer = setInterval(() => {
+  }
+  // 轮询
+  function initInterval() {
+    if (timer) clearInterval(timer);
+    timer = setInterval(() => {
+      refresh();
+    }, 5000);
+  }
+  onMounted(() => {
     refresh();
-  }, 5000);
-}
-onMounted(() => {
-  refresh();
-  initInterval();
-});
+    initInterval();
+  });
 
-onUnmounted(() => {
-  clearInterval(timer);
-  timer = null;
-});
+  onUnmounted(() => {
+    clearInterval(timer);
+    timer = null;
+  });
 </script>
 <style lang="less" scoped>
-.spray-wrapper {
-  width: 100%;
-  height: 100%;
-  background-image: url('/@/assets/images/beltFire/baseMap.png');
-  background-size: cover;
-}
+  .spray-wrapper {
+    width: 100%;
+    height: 100%;
+    background-image: url('/@/assets/images/beltFire/baseMap.png');
+    background-size: cover;
+  }
 
-#spray3D {
-  pointer-events: all;
-}
+  #spray3D {
+    pointer-events: all;
+  }
 
-.spray-wrapper :deep(.list-item_L .list-item__icon_L) {
-  background-image: url('/@/assets/images/home-container/configurable/minehome/list-icon-file.png');
-}
-.spray-wrapper :deep(.list-item_N:nth-child(1)) {
-  background-image: url('/@/assets/images/home-container/configurable/minehome/list-bg-n5.png');
-}
-.spray-wrapper :deep(.list-item_N:nth-child(2)) {
-  background-image: url('/@/assets/images/home-container/configurable/minehome/list-bg-n6.png');
-}
-.company-home {
-  background: url('/@/assets/images/beltFire/baseMap.png') no-repeat center;
-  width: 100%;
-  height: 100%;
-  color: @white;
-  position: relative;
-  .border {
+  .spray-wrapper :deep(.list-item_L .list-item__icon_L) {
+    background-image: url('/@/assets/images/home-container/configurable/minehome/list-icon-file.png');
+  }
+  .spray-wrapper :deep(.list-item_N:nth-child(1)) {
+    background-image: url('/@/assets/images/home-container/configurable/minehome/list-bg-n5.png');
+  }
+  .spray-wrapper :deep(.list-item_N:nth-child(2)) {
+    background-image: url('/@/assets/images/home-container/configurable/minehome/list-bg-n6.png');
+  }
+  .company-home {
+    background: url('/@/assets/images/beltFire/baseMap.png') no-repeat center;
     width: 100%;
-    height: 94%;
-    background: url('/@/assets/images/beltFire/mainbj.png') no-repeat;
-    background-size: 100% 100%;
-    margin-top: 50px;
-    .test {
-      background: url('./test.png') no-repeat;
+    height: 100%;
+    color: @white;
+    position: relative;
+    .border {
+      width: 100%;
+      height: 94%;
+      background: url('/@/assets/images/beltFire/mainbj.png') no-repeat;
       background-size: 100% 100%;
+      margin-top: 50px;
+      .test {
+        background: url('./test.png') no-repeat;
+        background-size: 100% 100%;
+      }
     }
   }
-}
-</style>
+</style>

+ 21 - 15
src/views/vent/home/configurable/belt/threejs/MonitorPanel.vue

@@ -2,62 +2,61 @@
 <template>
   <!-- 外层动画包裹层 -->
   <div class="panel-wrapper">
-    <div class="monitor-panel" ref="panelRef" :class="{ alarm: hasAlarm }">
-      <div class="panel-title">{{ sensorData.positionName || 'XXXXX位置' }}</div>
+    <div class="monitor-panel" ref="panelRef" :class="{ alarm: monitorData.alarmLevel > 102 }">
+      <div class="panel-title">{{ monitorData.positionName || 'XXXXX位置' }}</div>
       <div class="panel-grid">
         <div class="panel-item">
           <span class="item-label">▸ 微震测声</span>
           <span class="item-value" :class="getStatusClass('microseism')">
-            {{ sensorData.microseism ?? 'XXXX' }}
+            {{ monitorData.microseism ?? '-' }}
           </span>
         </div>
         <div class="panel-item">
           <span class="item-label">▸ 光纤测温</span>
           <span class="item-value" :class="getStatusClass('fiberTemp')">
-            {{ sensorData.fiberTemp ?? 'XXXX' }}
+            {{ monitorData.fiberTemp ?? '-' }}
           </span>
         </div>
         <div class="panel-item">
           <span class="item-label">▸ 温度</span>
           <span class="item-value" :class="getStatusClass('temperature')">
-            {{ sensorData.temperature ?? 'XXXX' }}
+            {{ monitorData.temperature ?? '-' }}
           </span>
         </div>
         <div class="panel-item">
           <span class="item-label">▸ 火焰</span>
           <span class="item-value" :class="getStatusClass('flame')">
-            {{ sensorData.flame ?? 'XXXX' }}
+            {{ monitorData.flame ?? '-' }}
           </span>
         </div>
-        <div class="panel-item item-full">
+        <!-- <div class="panel-item item-full">
           <span class="item-label ai-label">▸ AI视频火焰识别</span>
           <span class="item-value" :class="getStatusClass('aiFlame')">
-            {{ sensorData.aiFlame ?? 'XXXX' }}
+            {{ sensorData.aiFlame ?? '-' }}
           </span>
-        </div>
-
+        </div> -->
         <div class="panel-item">
           <span class="item-label">▸ HCl</span>
           <span class="item-value" :class="getStatusClass('hcl')">
-            {{ sensorData.hcl ?? 'XXXX' }}
+            {{ monitorData.hcl ?? '-' }}
           </span>
         </div>
         <div class="panel-item">
           <span class="item-label">▸ CO</span>
           <span class="item-value" :class="getStatusClass('co')">
-            {{ sensorData.co ?? 'XXXX' }}
+            {{ monitorData.co ?? '-' }}
           </span>
         </div>
         <div class="panel-item">
           <span class="item-label">▸ 烟雾</span>
           <span class="item-value" :class="getStatusClass('smoke')">
-            {{ sensorData.smoke ?? 'XXXX' }}
+            {{ monitorData.smoke ?? '-' }}
           </span>
         </div>
         <div class="panel-item">
           <span class="item-label">▸ 多参数</span>
           <span class="item-value" :class="getStatusClass('multiParam')">
-            {{ sensorData.multiParam ?? 'XXXX' }}
+            {{ monitorData.multiParam ?? '-' }}
           </span>
         </div>
       </div>
@@ -94,6 +93,7 @@
     flame?: number;
     multiParam?: number;
     aiFlame?: number;
+    alarmLevel: number;
   }
 
   const props = defineProps({
@@ -125,6 +125,7 @@
 
   const panelRef = ref<HTMLElement | null>(null);
   const cssObject = ref<CSS3DObject | null>(null);
+  const monitorData = ref<SensorData>(props.sensorData);
 
   // 默认阈值
   const defaultThreshold: Required<AlarmThreshold> = {
@@ -150,7 +151,7 @@
     const value = props.sensorData[key];
     if (value == null) return 'normal';
     const threshold = currentThreshold.value[key]!;
-    if (value > threshold) return 'alarm';
+    if (threshold > 102) return 'alarm';
     return 'normal';
   };
 
@@ -172,6 +173,10 @@
     }
   };
 
+  const updateMonitorData = (data: SensorData) => {
+    monitorData.value = data;
+  };
+
   onMounted(() => {
     if (!panelRef.value) return;
     cssObject.value = new CSS3DObject(panelRef.value);
@@ -204,6 +209,7 @@
     cssObject: cssObject,
     update,
     destroy,
+    updateMonitorData,
   });
 </script>
 

+ 96 - 28
src/views/vent/home/configurable/belt/threejs/belt.threejs.ts

@@ -5,6 +5,8 @@ import { ref, watch } from 'vue';
 import { modelMouseHandler } from '/@/utils/threejs/useEvent';
 import { panelManager } from './PanelManager';
 import { Ref } from 'vue';
+import { defHttp } from '/@/utils/http/axios';
+import { animateCamera } from '/@/utils/threejs/util';
 
 const gateList = ref([]);
 const panelApp = [];
@@ -13,8 +15,10 @@ const normalColor = new THREE.Color(0xff0000);
 const warningColor = new THREE.Color(0xfc5f2e);
 const color = new THREE.Color(0x00ff00);
 let clickSelecteObject;
+const modalData = ref(null);
+const warningPartitionIndex = ref('-1');
 
-export function modalAnimate(modal, modalMonitorData: Ref<any, any>) {
+export async function modalAnimate(modal, modalMonitorData: Ref<any, any>) {
   // const data = modalMonitorData.value;
   const warningPartition: THREE.Object3D[] = [];
 
@@ -29,12 +33,34 @@ export function modalAnimate(modal, modalMonitorData: Ref<any, any>) {
   const { inGates, outGates } = getGateModal(beltModal);
   // 绘制风流路径
   const { jinfenghangPath, huifenghangPath, jinfenglianhangPath, huifenglianhangPath, pidaihangPath } = getTunPath(beltModal);
-  const { partitionList, blinkAnimationList } = drawPartition(beltModal, 100, 5000);
+
+  // const api = '/ventanaly-device/monitor/disaster/findDeviceInfoBySystem';
+  // const res = await defHttp.post({ url: api, params: { sysId: '2028657172566073346' } });
+  // modalData.value = res?.device;
+  // const len = Object.keys(res?.device).length;
+  const { partitionList, blinkAnimationList } = drawPartition(beltModal, 100, 2000);
 
   watch(
     modalMonitorData,
-    (data) => {
+    async (data) => {
       gateList.value = data.deviceInfo['gate']?.datalist as [];
+
+      const api = '/ventanaly-device/monitor/disaster/findDeviceInfoBySystem';
+      const res = await defHttp.post({ url: api, params: { sysId: '2028657172566073346' } });
+      modalData.value = res?.device;
+      updateMonitorPanel3D();
+      const alarminfo = res?.alarminfo;
+      if (Object.keys(alarminfo).length > 0) {
+        for (const key in alarminfo) {
+          if (!Object.hasOwn(alarminfo, key)) continue;
+          if (alarminfo[key] > 102) {
+            if (modalData.value && modalData.value[key]) modalData.value[key]['alarmLevel'] = alarminfo[key];
+            warningPartitionIndex.value = key;
+            setPartitionAnimate();
+            break;
+          }
+        }
+      }
       // 根据监测数据进行风门模型动画控制(前提条件:模型上的风门与实际风门设备建立了映射关系)
       handleGateAnimate(gateList.value);
     },
@@ -44,11 +70,6 @@ export function modalAnimate(modal, modalMonitorData: Ref<any, any>) {
   // 添加鼠标拾取
   initMouseEvent(modal, beltModal, partitionList);
 
-  setTimeout(() => {
-    // 添加风门模型
-    setPartitionAnimate([12]);
-  }, 3000);
-
   // setTimeout(() => {
   //   // 添加风门模型
   //   setPartitionAnimate([]);
@@ -65,7 +86,6 @@ export function modalAnimate(modal, modalMonitorData: Ref<any, any>) {
 
       const houmen1 = houmenObj?.getObjectByName(`${fengmenName}FengMen2_1`) as THREE.Object3D;
       const houmen2 = houmenObj?.getObjectByName(`${fengmenName}FengMen2_4`) as THREE.Object3D;
-      debugger;
       const frontState = gateData['readData']['frontGateOpen'] == 1 ? true : gateData['readData']['frontGateClose'] == 1 ? false : null;
       const backState = gateData['readData']['rearGateOpen'] == 1 ? true : gateData['readData']['rearGateClose'] == 1 ? false : null;
       if (qianmen1 && qianmen2 && houmen1 && houmen2) {
@@ -197,14 +217,14 @@ export function modalAnimate(modal, modalMonitorData: Ref<any, any>) {
     handlePathAnimate(jinfenghangPath, huifenghangPath, jinfenglianhangPath, huifenglianhangPath, jinfenglianhangList, huifenglianhangList);
   }
 
-  function setPartitionAnimate(partitionIndexList: number[]) {
+  function setPartitionAnimate() {
+    if (Number(warningPartitionIndex.value) > -1) panelManager.destroyPanel(`partition${Number(warningPartitionIndex.value)}`);
     warningPartition.length = 0;
-
     partitionList.forEach((partition, index) => {
       const solidBox = partition.getObjectByName(partition.name + '_solid') as THREE.Mesh;
       const line = partition.getObjectByName(partition.name + '_line') as THREE.LineSegments;
       if (solidBox && line) {
-        if (partitionIndexList.includes(index + 1)) {
+        if (Number(warningPartitionIndex.value) == index + 1) {
           if (!solidBox.material.color.equals(warningColor)) solidBox.material.color.setHex(0xfc5f2e);
           if (solidBox.material.opacity !== 0.3) solidBox.material.opacity = 0.3;
           if (!line.material.color.equals(warningColor)) line.material.color.setHex(0xfc5f2e);
@@ -223,7 +243,7 @@ export function modalAnimate(modal, modalMonitorData: Ref<any, any>) {
     const warningOpacity = 0.9;
     const normalOpacity = 0.05;
     for (let i = 0; i < blinkAnimationList.length; i++) {
-      if (partitionIndexList.includes(i + 1)) {
+      if (Number(warningPartitionIndex.value) == i + 1) {
         // 开始动画
         if (!blinkAnimationList[i]) {
           const partition = partitionList[i];
@@ -245,7 +265,25 @@ export function modalAnimate(modal, modalMonitorData: Ref<any, any>) {
             },
           });
 
-          createMonitorPanel3D(modal, partition);
+          const pos = createMonitorPanel3D(modal, partition);
+
+          // 这里进行重新定位
+          console.log(pos);
+          gsap.fromTo(
+            modal.camera.position,
+            { x: modal.camera.position.x, y: modal.camera.position.y, z: modal.camera.position.z },
+            {
+              x: pos.x,
+              y: modal.camera.position.y,
+              z: pos.y,
+              duration: 1,
+              onUpdate: () => {
+                modal.orbitControls.target.set(modal.camera.position.x, pos.z, -modal.camera.position.z);
+                modal.orbitControls.update();
+                modal.renderer?.render(modal.scene, modal.camera);
+              },
+            }
+          );
         }
       } else {
         // 停止动画
@@ -297,18 +335,48 @@ function createMonitorPanel3D(modal, partition) {
   const box = new THREE.Box3();
   box.setFromObject(partition);
   const center = box.getCenter(new THREE.Vector3());
+  const partitionIndex = partition.name.split('_')[0];
+  const index = Number(partitionIndex.split('partition')[1]) + 1;
+  const data = modalData.value[index + ''];
+  if (data) {
+    panelManager.createPanel(modal.scene, {
+      instanceId: partition.name,
+      sensorData: {
+        positionName: `分区#${index}`,
+        temperature: data['温度传感器'] ? data['温度传感器'][0]?.value : null,
+        smoke: data['烟雾传感器'] ? data['烟雾传感器'][0]?.value : null,
+        co: data['CO传感器'] ? data['CO传感器'][0]?.value : null,
+        microseism: data['微震测声传感器'] ? data['微震测声传感器'][0]?.value : null,
+        fiberTemp: data['光纤测温'] ? data['光纤测温'][0]?.value : null,
+        flame: data['火焰传感器'] ? data['火焰传感器'][0]?.value : null,
+        hcl: data['HCl传感器'] ? data['HCl传感器'][0]?.value : null,
+        alarmLevel: data['alarmLevel'] ? data['alarmLevel'] : null,
+      },
+      threshold: {
+        temperature: data['温度传感器'] ? data['温度传感器'][0]?.alarmLevel : null,
+        smoke: data['烟雾传感器'] ? data['烟雾传感器'][0]?.alarmLevel : null,
+        co: data['CO传感器'] ? data['CO传感器'][0]?.alarmLevel : null,
+        microseism: data['微震测声传感器'] ? data['微震测声传感器'][0]?.alarmLevel : null,
+        fiberTemp: data['光纤测温'] ? data['光纤测温'][0]?.alarmLevel : null,
+        flame: data['火焰传感器'] ? data['火焰传感器'][0]?.alarmLevel : null,
+        hcl: data['HCl传感器'] ? data['HCl传感器'][0]?.alarmLevel : null,
+      },
+      position: [center.x, center.y, center.z],
+      scale: 0.0125,
+    });
+  }
+  return center;
+}
 
-  panelManager.createPanel(modal.scene, {
-    instanceId: partition.name,
-    sensorData: {
-      positionName: '分区#X',
-      temperature: 80,
-      smoke: 0,
-      co: 0,
-    },
-    threshold: { temperature: 70 },
-    position: [center.x, center.y, center.z],
-    scale: 0.0125,
+function updateMonitorPanel3D() {
+  panelManager.getAllPanelIds().forEach((id) => {
+    const instance = panelManager.getPanel(id);
+    if (instance?.vm?.update && modalData.value) {
+      const partitionIndex = id.split('_')[0];
+      const index = Number(partitionIndex.split('partition')[1]) + 1;
+      const data = modalData.value[index + ''];
+      instance.vm.updateMonitorData(data);
+    }
   });
 }
 
@@ -513,7 +581,7 @@ function getTunPath(beltModal) {
         pathPointList.set(posList, 0, 0, up, false);
         const geometry = new PathGeometry(posList.length, false);
         geometry.update(pathPointList, {
-          width: 60,
+          width: 40,
           arrow: false,
         });
         const mesh = new THREE.Mesh(geometry, tubeMaterial.clone());
@@ -522,10 +590,10 @@ function getTunPath(beltModal) {
         beltModal.add(mesh);
         if (objName == 'pidaihang') {
           (mesh.material as THREE.MeshPhongMaterial).visible = true;
-          mesh.position.z = 30;
+          mesh.position.z = -5;
           mesh.position.y = -20;
         } else {
-          mesh.position.z = 30;
+          mesh.position.z = -5;
         }
       } else {
         break;

+ 2 - 2
src/views/vent/home/configurable/fireDoorMonitor.vue

@@ -109,11 +109,11 @@
   //   }
   // );
 
-  function initModalAnimate(modal) {
+  async function initModalAnimate(modal) {
     console.log('初始化模型', modal);
     modal.isRender = true;
 
-    modalAnimate(modal);
+    await modalAnimate(modal);
   }
 
   onMounted(() => {

+ 1 - 1
src/views/vent/monitorManager/mainFanMonitor/components/entryThree.vue

@@ -6,7 +6,7 @@
       class="threejs-Object-CSS"
       style="width: 100%; height: 100%; position: absolute; pointer-events: none; overflow: hidden; z-index: 1; top: 0"
     >
-      <div style="position: relative" v-if="selectData['modalTyoe']">
+      <div style="position: relative" v-if="selectData['modalTyoe'] && selectData['modalTyoe'] !== 'mainWindRect-Inverse'">
         <div class="elementTag" id="inputBox1" v-if="backMonitorIsShow">
           <div class="elementContent elementContent-r">
             <!-- <div class="element-item"><span class="data-title">风机气压(Pa):</span><span>{{ selectData.DataPa ? selectData.DataPa : '-' }}</span></div> -->

+ 5 - 1
src/views/vent/monitorManager/mainFanMonitor/index.vue

@@ -1102,7 +1102,11 @@
               ? 'mainWindRect3'
               : selectData['modalTyoe'] === 'lijing_1'
                 ? 'mainLjDtWindRect'
-                : 'mainWindRect';
+                : selectData['modalTyoe'] === 'lijing'
+                  ? 'mainWindRect'
+                  : selectData['modalTyoe']
+                    ? selectData['modalTyoe']
+                    : 'mainWindRect';
 
       frontMonitorIsShow.value = false;
       centerMonitorIsShow.value = false;

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

@@ -74,7 +74,7 @@ const mouseEvent = (event) => {
   if (event.button == 0) {
     model?.canvasContainer?.addEventListener('mousemove', mousemove);
     mouseDownFn(<UseThree>model, <THREE.Object3D>group, event, (intersects) => {
-      if (modalType === 'mainWindRect' && mainWindObj) {
+      if (modalType.includes('mainWindRect') && mainWindObj) {
         mainWindObj?.mousedownModel.call(mainWindObj, intersects);
       } else if (modalType === 'mainXjWindRect' && mainXjWindObj) {
         mainXjWindObj?.mousedownModel.call(mainXjWindObj, intersects);
@@ -100,7 +100,7 @@ const mousemove = () => {
 /* 添加监控数据 */
 export const addText = () => {
   if (!mainWindObj) return;
-  if (modalType === 'mainWindRect' && mainWindObj) {
+  if (modalType.includes('mainWindRect') && mainWindObj) {
     return mainWindObj.addCssText.call(mainWindObj);
   } else if (modalType === 'mainXjWindRect' && mainXjWindObj) {
     return mainXjWindObj.addCssText.call(mainXjWindObj);
@@ -116,7 +116,7 @@ export const addText = () => {
 /* 刷新echarts曲线图 */
 export const resetEcharts = (selectData) => {
   if (!mainWindObj) return;
-  if (modalType === 'mainWindRect' && mainWindObj) {
+  if (modalType.includes('mainWindRect') && mainWindObj) {
     return mainWindObj.addEcharts.call(mainWindObj);
   } else if (modalType === 'mainXjWindRect' && mainXjWindObj) {
     return mainXjWindObj.addEcharts.call(mainXjWindObj);
@@ -138,7 +138,7 @@ export const resetEcharts = (selectData) => {
  */
 export const play = (controlType, deviceType, frequencyVal?, state?, smokeDirection?) => {
   if (!mainWindObj) return;
-  if (modalType === 'mainWindRect' && mainWindObj) {
+  if (modalType.includes('mainWindRect') && mainWindObj) {
     return mainWindObj.playSmoke.call(mainWindObj, controlType, deviceType, frequencyVal, state, smokeDirection);
   } else if (modalType === 'mainXjWindRect' && mainXjWindObj) {
     return mainXjWindObj.playSmoke.call(mainXjWindObj, controlType, deviceType, frequencyVal, state, smokeDirection);
@@ -155,7 +155,7 @@ export const playAnimate1 = async (selectData, duration?) => {
   if (!mainWindObj) return;
   let mainObj: mainWindRect | mainXjWindRect | undefined;
 
-  if (modalType === 'mainWindRect') {
+  if (modalType.includes('mainWindRect')) {
     mainObj = mainWindObj;
   } else if (modalType === 'mainXjWindRect') {
     mainObj = mainXjWindObj;
@@ -249,7 +249,7 @@ export const playAnimate = async (selectData, duration?) => {
 
   let mainObj: mainWindRect | mainXjWindRect | mainWindLj3 | mainWindLjDt | undefined;
 
-  if (modalType === 'mainWindRect') {
+  if (modalType.includes('mainWindRect')) {
     mainObj = mainWindObj;
   } else if (modalType === 'mainXjWindRect') {
     mainObj = mainXjWindObj;
@@ -345,6 +345,95 @@ export const playAnimate = async (selectData, duration?) => {
       }
     } else if (modalType === 'mainLjDtWindRect') {
       (mainObj as mainWindLjDt).playSmoke(selectData.Fan1StartStatus == 1, selectData.Fan2FreqForwardRun == 1, selectData.Fan2FreqReverseRun == 1);
+    } else if (modalType === 'mainWindRect-Inverse') {
+      mainObj.resetSmokeParam('back', selectData.Fan2FreqHz, duration);
+      mainObj.resetSmokeParam('front', selectData.Fan1FreqHz, duration);
+      if (selectData.Fan1StartStatus == 1) {
+        // 主风机开启
+        mainObj?.lookMotor('front', 'open', duration);
+        mainObj?.openOrCloseValve('front', 'open', duration);
+        // 1. 已经运行,首次切入动画
+        // 2. 在页面上,切换动画
+        if (selectData.Fan1FreqForwardRun == 1 && selectData.Fan1FreqReverseRun == 0) {
+          // 主风机正转
+          if (mainObj['airChu2'] && !mainObj['airChu2'].visible) {
+            mainObj['airJin1'].visible = false;
+            mainObj['airJin2'].visible = false;
+            mainObj['airChu1'].visible = false;
+            mainObj['airChu2'].visible = true;
+          }
+          mainObj.startGearAnimation('front', 'open', 'tubPositivePath', selectData.Fan1FreqHz, duration);
+          await mainObj.setSmokeDirection('front', 'tubPositivePath');
+        } else if (selectData.Fan1FreqReverseRun == 1 && selectData.Fan1FreqForwardRun == 0) {
+          // 主风机反转
+          if (mainObj['airJin2'] && !mainObj['airJin2'].visible) {
+            mainObj['airJin1'].visible = false;
+            mainObj['airJin2'].visible = true;
+            mainObj['airChu1'].visible = false;
+            mainObj['airChu2'].visible = false;
+          }
+          mainObj.startGearAnimation('front', 'open', 'tubInversePath', selectData.Fan1FreqHz, duration);
+          await mainObj.setSmokeDirection('front', 'tubInversePath');
+        } else {
+          // 默认主风机正转
+          if (mainObj['airChu2'] && !mainObj['airChu2'].visible) {
+            mainObj['airJin1'].visible = false;
+            mainObj['airJin2'].visible = false;
+            mainObj['airChu1'].visible = false;
+            mainObj['airChu2'].visible = true;
+          }
+          mainObj.startGearAnimation('front', 'open', 'tubPositivePath', selectData.Fan1FreqHz, duration);
+          await mainObj.setSmokeDirection('front', 'tubPositivePath');
+        }
+
+        if (!mainObj?.frontSmoke?.frameId) mainObj?.frontSmoke?.startSmoke(duration);
+      } else {
+        // 主风机停止
+        mainObj.closeDevice('front');
+      }
+      if (selectData.Fan2StartStatus == 1) {
+        // 主风机开启
+        mainObj.lookMotor('back', 'open', duration);
+        mainObj.openOrCloseValve('back', 'open', duration);
+        // 1. 已经运行,首次切入动画
+        // 2. 在页面上,切换动画
+        if (selectData.Fan2FreqForwardRun == 1 && selectData.Fan2FreqReverseRun == 0) {
+          // 主风机正转
+          // 主风机正转
+          if (mainObj['airChu1'] && !mainObj['airChu1'].visible) {
+            mainObj['airJin1'].visible = false;
+            mainObj['airJin2'].visible = false;
+            mainObj['airChu1'].visible = true;
+            mainObj['airChu2'].visible = false;
+          }
+          mainObj.startGearAnimation('back', 'open', 'tubPositivePath', selectData.Fan2FreqHz, duration);
+          await mainObj.setSmokeDirection('back', 'tubPositivePath');
+        } else if (selectData.Fan2FreqReverseRun == 1 && selectData.Fan2FreqForwardRun == 0) {
+          // 主风机反转
+          if (mainObj['airJin1'] && !mainObj['airJin1'].visible) {
+            mainObj['airJin1'].visible = true;
+            mainObj['airJin2'].visible = false;
+            mainObj['airChu1'].visible = false;
+            mainObj['airChu2'].visible = false;
+          }
+          mainObj.startGearAnimation('back', 'open', 'tubInversePath', selectData.Fan2FreqHz, duration);
+          await mainObj.setSmokeDirection('back', 'tubInversePath');
+        } else {
+          if (mainObj['airChu1'] && !mainObj['airChu1'].visible) {
+            mainObj['airJin1'].visible = false;
+            mainObj['airJin2'].visible = false;
+            mainObj['airChu1'].visible = true;
+            mainObj['airChu2'].visible = false;
+          }
+          mainObj.startGearAnimation('back', 'open', 'tubPositivePath', selectData.Fan2FreqHz, duration);
+          await mainObj.setSmokeDirection('back', 'tubPositivePath');
+        }
+
+        if (!mainObj?.backSmoke?.frameId) mainObj?.backSmoke?.startSmoke(duration);
+      } else {
+        // 主风机停止
+        mainObj.closeDevice('back');
+      }
     } else {
       mainObj.resetSmokeParam('front', selectData.Fan2FreqHz, duration);
       mainObj.resetSmokeParam('back', selectData.Fan1FreqHz, duration);
@@ -437,7 +526,7 @@ export const playAnimate = async (selectData, duration?) => {
     }
 
     // 防爆门动画
-    if (modalType === 'mainWindRect' && selectData['ExplosionVentOpen'] == 1 && explosionVentOpen !== 1) {
+    if (modalType.includes('mainWindRect') && selectData['ExplosionVentOpen'] == 1 && explosionVentOpen !== 1) {
       if (explosionVentOpen == -1) {
         // 直接打开
         mainObj.playAnimation('open', 0);
@@ -447,7 +536,7 @@ export const playAnimate = async (selectData, duration?) => {
       explosionVentOpen = 1;
       explosionVentClose = 0;
     }
-    if (modalType === 'mainWindRect' && selectData['ExplosionVentClose'] == 1 && explosionVentClose !== 1) {
+    if (modalType.includes('mainWindRect') && selectData['ExplosionVentClose'] == 1 && explosionVentClose !== 1) {
       if (explosionVentOpen == -1) {
         // 直接关闭
         mainObj.playAnimation('close', 0);
@@ -473,7 +562,7 @@ export const setModelType = (type) => {
     mainFanLjDtObj?.stopSmoke();
     mainLjWindObj?.stopSmoke();
     if (group) model?.scene?.remove(group);
-    if (modalType === 'mainWindRect' && mainWindObj && mainWindObj.group) {
+    if (modalType.includes('mainWindRect') && mainWindObj && mainWindObj.group) {
       (<UseThree>model).startAnimation = mainWindObj.render.bind(mainWindObj);
       group = mainWindObj.group;
       setTimeout(async () => {

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

@@ -799,7 +799,6 @@ class mainWindRect {
     this.group = new THREE.Group();
     return new Promise(async (resolve) => {
       this.model.setGLTFModel(['bg1', 'fbm', 'ztfj', 'ztfj-fc'], this.group).then(async () => {
-        // this.group = gltf[0];
         this.group?.position.set(-0.44, 19.88, 22.37);
         this.initSmokeMass();
         await this.setSmokePosition();