Kaynağa Gözat

Merge branch 'master' of http://39.97.59.228:8013/hrx/mky-vent-base

bobo04052021@163.com 2 gün önce
ebeveyn
işleme
f9bbafafd8

+ 1 - 0
build/vite/plugin/styleImport.ts

@@ -58,6 +58,7 @@ export function configStyleImportPlugin(_isBuild: boolean) {
             'input-password': 'input',
             'input-search': 'input',
             'input-group': 'input',
+            'textarea': 'input',
             'radio-group': 'radio',
             'checkbox-group': 'checkbox',
             'layout-sider': 'layout',

+ 6 - 3
src/api/sys/modelFile.ts

@@ -5,7 +5,10 @@ enum Api {
 }
 
 export const getAllModelFileJsonApi = () => {
-  return defHttp.get<Record<string, { fileName: string; filePath: string }[]>>({
-    url: Api.getAllModelFileJson,
-  });
+  return defHttp.get<Record<string, { fileName: string; filePath: string }[]>>(
+    {
+      url: Api.getAllModelFileJson,
+    },
+    { errorMessageMode: 'none' }
+  );
 };

+ 103 - 19
src/views/vent/home/configurable/firedoor/components/fireDoorBoard.vue

@@ -12,7 +12,7 @@
       <div class="left-panel">
         <!-- 风门数据列表 -->
         <div class="door-list">
-          <div class="door-card" v-for="(item, index) in props.data" :key="index">
+          <div class="door-card" v-for="(item, index) in displayData" :key="index">
             <div class="door-position">
               <div class="position"></div>
               <div class="door-name">
@@ -56,7 +56,12 @@
 
             <div class="model-placeholder">
               <!-- <img :src="gatePng" alt="风门" class="model-img" /> -->
-              <pidaihangSVG :ref="(el) => setChildRef(el, index)" :identify="String(index)" />
+              <template v-if="item.readData?.MBOpen?.value">
+                <pidaihangSVG :ref="(el) => setChildRef(el, index)" :identify="String(index)" />
+              </template>
+              <template v-else>
+                <fireDoorSVG :ref="(el) => setChildRef(el, index)" :identify="String(index)" />
+              </template>
             </div>
           </div>
         </div>
@@ -74,9 +79,10 @@
 </template>
 
 <script setup lang="ts">
-  import { ref, onMounted, watch, inject } from 'vue';
+  import { ref, computed, onMounted, watch, inject } from 'vue';
   import { getFormattedText } from '../../hooks/helper';
   import pidaihangSVG from '/@/views/vent/monitorManager/fireDoorMonitor/components/pidaihangSVG.vue';
+  import fireDoorSVG from '/@/views/vent/monitorManager/fireDoorMonitor/components/fireDoorSVG.vue';
   import HandleModal from '/@/views/vent/monitorManager/gateMonitor/modal.vue';
   import { message } from 'ant-design-vue';
   import { doorControlApi } from '/@/views/vent/home/configurable/firedoor/configurable.api.fireDoorMonitor';
@@ -110,6 +116,36 @@
   const paramcode = ref(''); // 模态框操作代码
   const childRefs = ref<(InstanceType<typeof pidaihangSVG> | null)[]>([]);
   const selectData = ref<any>({});
+
+  // 模拟数据开关 - 设为 true 启用模拟数据
+  const useMockData = ref(false);
+  // 模拟数据
+  const mockData = ref([
+    {
+      devicePos: '防火门2号(无皮带)',
+      deviceID: 'FD002',
+      systemDeviceId: 'SYS002',
+      deviceType: 'fireDoor',
+      readData: {
+        frontGateOpen: { value: '0' },
+      },
+    },
+    // {
+    //   devicePos: '防火门1号(有皮带)',
+    //   deviceID: 'FD001',
+    //   systemDeviceId: 'SYS001',
+    //   deviceType: 'fireDoor',
+    //   readData: {
+    //     frontGateOpen: { value: '0' },
+    //     MBOpen: { value: '0' },
+    //   },
+    // },
+  ]);
+
+  // 实际显示的数据
+  const displayData = computed(() => {
+    return useMockData.value ? mockData.value : props.data;
+  });
   const setChildRef = (el, index) => {
     if (el) {
       childRefs.value[index] = el;
@@ -120,21 +156,31 @@
   function executeAnimation(targetIndex: number, code: string) {
     if (targetIndex === -1) return;
     const isOpen = code.includes('Open');
+    const targetItem = displayData.value[targetIndex];
+    if (!targetItem) return;
+    const hasBelt = targetItem.readData?.MBOpen?.value !== undefined;
 
     // 2D SVG 动画
-    if (childRefs.value[targetIndex]) {
-      if (code === 'AllOpen_S' || code === 'AllClose_S') {
-        childRefs.value[targetIndex].animate(isOpen, isOpen, isOpen);
-      } else if (code === 'frontGateOpen_S' || code === 'frontGateClose_S') {
-        childRefs.value[targetIndex].animateFireDoor(isOpen);
-      } else if (code === 'MBOpen_S' || code === 'MBClose_S') {
-        childRefs.value[targetIndex].animateBeltDoor(isOpen);
+    const svgRef = childRefs.value[targetIndex];
+    if (svgRef) {
+      if (hasBelt) {
+        // pidaihangSVG 动画逻辑
+        if (code === 'AllOpen_S' || code === 'AllClose_S') {
+          svgRef.animate(isOpen, isOpen, isOpen);
+        } else if (code === 'frontGateOpen_S' || code === 'frontGateClose_S') {
+          svgRef.animateFireDoor(isOpen);
+        } else if (code === 'MBOpen_S' || code === 'MBClose_S') {
+          svgRef.animateBeltDoor(isOpen);
+        }
+      } else {
+        // fireDoorSVG 动画逻辑
+        svgRef.animate(isOpen, false, false);
       }
     }
 
     // 3D 动画:构造期望状态的门数据并触发
-    if (props.data && Array.isArray(props.data)) {
-      const doors = props.data.map((door: any, i: number) => {
+    if (displayData.value && Array.isArray(displayData.value)) {
+      const doors = displayData.value.map((door: any, i: number) => {
         if (i === targetIndex && door.readData) {
           const updated = {
             ...door,
@@ -143,7 +189,8 @@
           if (code === 'AllOpen_S' || code === 'AllClose_S' || code === 'frontGateOpen_S' || code === 'frontGateClose_S') {
             updated.readData.frontGateOpen = { ...updated.readData.frontGateOpen, value: isOpen ? '1' : '0' };
           }
-          if (code === 'AllOpen_S' || code === 'AllClose_S' || code === 'MBOpen_S' || code === 'MBClose_S') {
+          // 只有原数据有 MBOpen 时才更新
+          if (hasBelt && (code === 'AllOpen_S' || code === 'AllClose_S' || code === 'MBOpen_S' || code === 'MBClose_S')) {
             updated.readData.MBOpen = { ...updated.readData.MBOpen, value: isOpen ? '1' : '0' };
           }
           return updated;
@@ -158,9 +205,16 @@
     if (!selectData?.readData) return;
     const frontOpen = selectData.readData?.frontGateOpen?.value === '1';
     const beltOpen = selectData.readData?.MBOpen?.value === '1';
-    if (childRefs.value[index]) {
-      childRefs.value[index].animateFireDoor(frontOpen);
-      childRefs.value[index].animateBeltDoor(beltOpen);
+    const svgRef = childRefs.value[index];
+    if (svgRef) {
+      if (selectData.readData?.MBOpen?.value) {
+        // pidaihangSVG 动画逻辑
+        svgRef.animateFireDoor(frontOpen);
+        svgRef.animateBeltDoor(beltOpen);
+      } else {
+        // fireDoorSVG 动画逻辑
+        svgRef.animate(frontOpen, false, false);
+      }
     }
   }
 
@@ -178,6 +232,30 @@
   }
 
   function handleOK(passWord, handlerState, value?) {
+    if (useMockData.value) {
+      // 测试模式:跳过 API,直接执行动画
+      modalIsShow.value = false;
+      message.success('【测试模式】动画已触发');
+
+      // 更新模拟数据中的状态
+      const targetItem = displayData.value.find((item: any) => item.deviceID === selectData.value.deviceID);
+      if (targetItem?.readData) {
+        const isOpen = paramcode.value.includes('Open');
+        if (paramcode.value.includes('frontGate') || paramcode.value.includes('All')) {
+          targetItem.readData.frontGateOpen = { value: isOpen ? '1' : '0' };
+        }
+        if (paramcode.value.includes('MB') || paramcode.value.includes('All')) {
+          if (targetItem.readData.MBOpen) {
+            targetItem.readData.MBOpen = { value: isOpen ? '1' : '0' };
+          }
+        }
+      }
+
+      const targetIndex = displayData.value.findIndex((item: any) => item.deviceID === selectData.value.deviceID);
+      executeAnimation(targetIndex, paramcode.value);
+      return;
+    }
+
     if (!passWord && !globalConfig?.simulatedPassword) {
       message.warning('请输入密码');
       return;
@@ -202,7 +280,7 @@
             message.success('指令已下发成功!');
           }
 
-          const targetIndex = props.data.findIndex((item) => item.deviceID === selectData.value.deviceID);
+          const targetIndex = displayData.value.findIndex((item: any) => item.deviceID === selectData.value.deviceID);
           executeAnimation(targetIndex, paramcode.value);
           // 触发刷新事件
           emit('refresh');
@@ -221,10 +299,10 @@
   }
 
   watch(
-    () => props.data,
+    () => displayData.value,
     (newData) => {
       if (!newData || !newData.length) return;
-      newData.forEach((item, index) => {
+      newData.forEach((item: any, index: number) => {
         monitorAnimation(item, index);
       });
     },
@@ -467,6 +545,12 @@
     top: -140%;
     left: -110%;
   }
+  .fire-door-svg {
+    width: 100% !important;
+    height: 100% !important;
+    top: 0 !important;
+    left: 0 !important;
+  }
   .model-img {
     width: 100%;
     display: flex;

+ 62 - 16
src/views/vent/home/configurable/firedoor/threejs/firedoor.threejs.ts

@@ -12,6 +12,8 @@ let currentHandleGateAnimate: ((doors: any[]) => void) | null = null;
 export function trigger3DAnimation(doors: any[]) {
   if (currentHandleGateAnimate) {
     currentHandleGateAnimate(doors);
+  } else {
+    console.warn('[3D动画] currentHandleGateAnimate 未初始化,请确保 modalAnimate 已调用');
   }
 }
 
@@ -100,37 +102,45 @@ export async function modalAnimate(modal: any, modalMonitorData: Ref<any, any>)
     if (!doors || doors.length === 0) return;
 
     doors.forEach((gateData: any, index: number) => {
-      // 根据门的索引查找对应的 3D 模型对象 (men_1, men_2, ...)
-      const doorSuffix = index + 1;
-      const fireDoorMesh = findMesh(doorContainer, [`men_${doorSuffix}`, `men_1`, 'men']);
-      const beltCoverMesh = findMesh(doorContainer, [`gaiban_${doorSuffix}`, 'gaiban', 'gaiban_1']);
-
       // 获取状态值
       const frontGateOpenVal = gateData['readData']?.['frontGateOpen']?.value;
       const mbOpenVal = gateData['readData']?.['MBOpen']?.value;
-
-      // 判断状态 (与 2D 动画保持一致:'1' 为打开)
       const isFireDoorOpen = frontGateOpenVal == '1' || frontGateOpenVal == 1;
       const isBeltCoverOpen = mbOpenVal == '1' || mbOpenVal == 1;
+      const hasBelt = mbOpenVal !== undefined && mbOpenVal !== null;
 
-      // 执行防火门动画
-      if (fireDoorMesh) {
-        animateFireDoor(fireDoorMesh, isFireDoorOpen);
-      }
+      if (hasBelt) {
+        // 有皮带:控制 men_1(防火门)+ gaiban(皮带盖)
+        const fireDoorMesh = findMesh(doorContainer, [`men_${index + 1}`, 'men_1', 'men']);
+        const beltCoverMesh = findMesh(doorContainer, [`gaiban_${index + 1}`, 'gaiban', 'gaiban_1']);
 
-      // 执行皮带密闭动画
-      if (beltCoverMesh) {
-        animateBeltCover(beltCoverMesh, isBeltCoverOpen);
+        if (fireDoorMesh) {
+          animateFireDoorWithBelt(fireDoorMesh, isFireDoorOpen);
+        }
+        if (beltCoverMesh) {
+          animateBeltCover(beltCoverMesh, isBeltCoverOpen);
+        }
+      } else {
+        // 无皮带:控制 men_2 + men3(两扇防火门向两边开)
+        const leftDoorMesh = findMesh(doorContainer, ['men_2']);
+        const rightDoorMesh = findMesh(doorContainer, ['men3']);
+
+        if (leftDoorMesh) {
+          animateFireDoorLeft(leftDoorMesh, isFireDoorOpen);
+        }
+        if (rightDoorMesh) {
+          animateFireDoorRight(rightDoorMesh, isFireDoorOpen);
+        }
       }
     });
   };
 
   /**
-   * 防火门动画
+   * 有皮带时的防火门动画
    * 关闭: (0, 0, 0)
    * 开启: (0, 0, 85度) -> 绕 Z 轴旋转
    */
-  const animateFireDoor = (mesh: THREE.Object3D, isOpen: boolean) => {
+  const animateFireDoorWithBelt = (mesh: THREE.Object3D, isOpen: boolean) => {
     const targetRotationZ = isOpen ? THREE.MathUtils.degToRad(85) : 0;
 
     gsap.to(mesh.rotation, {
@@ -143,6 +153,42 @@ export async function modalAnimate(modal: any, modalMonitorData: Ref<any, any>)
     });
   };
 
+  /**
+   * 无皮带时左侧防火门动画 (men_2)
+   * 关闭: (0, 0, 0)
+   * 开启: (0, 0, -90度) -> 绕 Z 轴旋转
+   */
+  const animateFireDoorLeft = (mesh: THREE.Object3D, isOpen: boolean) => {
+    const targetRotationZ = isOpen ? THREE.MathUtils.degToRad(-90) : 0;
+
+    gsap.to(mesh.rotation, {
+      x: 0,
+      y: 0,
+      z: targetRotationZ,
+      duration: 1.5,
+      ease: 'power2.inOut',
+      overwrite: true,
+    });
+  };
+
+  /**
+   * 无皮带时右侧防火门动画 (men_3)
+   * 关闭: (0, 0, 0)
+   * 开启: (0, 0, 90度) -> 绕 Z 轴旋转
+   */
+  const animateFireDoorRight = (mesh: THREE.Object3D, isOpen: boolean) => {
+    const targetRotationZ = isOpen ? THREE.MathUtils.degToRad(90) : 0;
+
+    gsap.to(mesh.rotation, {
+      x: 0,
+      y: 0,
+      z: targetRotationZ,
+      duration: 1.5,
+      ease: 'power2.inOut',
+      overwrite: true,
+    });
+  };
+
   /**
    * 皮带密闭动画
    * 关闭: (0, 0, 0)

Dosya farkı çok büyük olduğundan ihmal edildi
+ 2927 - 0
src/views/vent/monitorManager/fireDoorMonitor/components/fireDoorSVG.vue


Dosya farkı çok büyük olduğundan ihmal edildi
+ 364 - 0
src/views/vent/monitorManager/gateMonitor/components/GateShrinkSVG.vue


Dosya farkı çok büyük olduğundan ihmal edildi
+ 384 - 0
src/views/vent/monitorManager/gateMonitor/components/GateYeYaSVG.vue


Dosya farkı çok büyük olduğundan ihmal edildi
+ 396 - 0
src/views/vent/monitorManager/windowMonitor/components/windowDoorBltSVG.vue


Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor