Browse Source

Merge branch 'master' of http://182.92.126.35:3000/hrx/mky-vent-base

wangkeyi 16 hours ago
parent
commit
b5f0e86685

+ 220 - 0
src/hooks/core/useAutoScroll.ts

@@ -0,0 +1,220 @@
+import { ref, watch, onUnmounted, unref, type Ref, onMounted } from 'vue';
+import { useScroll, type UseScrollReturn } from '@vueuse/core';
+import gsap from 'gsap';
+const ticker = gsap.ticker;
+
+export interface AutoScrollOptions {
+  /** 延迟(刻),滚动启动、反转、用户交互后的重新开始的延迟 */
+  delay?: number;
+  /** 滚动到底部后是否回滚(否则是回到顶部重新滚动) */
+  rollBack?: boolean;
+  /** 每一刻滚动的像素数 */
+  step?: number;
+  /** 是否自动开始 */
+  autoStart?: boolean;
+  /** 滚动方向 */
+  direction?: 'x' | 'y';
+}
+
+export interface AutoScrollReturn {
+  /** 开始/恢复滚动 */
+  start: () => void;
+  /** 暂停滚动 */
+  pause: () => void;
+  /** 重置到初始状态 */
+  reset: () => void;
+  /** 反转滚动 */
+  reverse: () => void;
+  /** 恢复滚动 */
+  resume: () => void;
+}
+
+export function useAutoScroll(container: Ref<HTMLElement | null> | HTMLElement | null, options: AutoScrollOptions = {}): AutoScrollReturn {
+  const {
+    delay = 300, // 默认60帧(约1秒)
+    rollBack = false,
+    step = 1,
+    autoStart = true,
+    direction = 'y',
+  } = options;
+
+  let cleanupListeners: (() => void) | null = null;
+
+  // 状态管理
+  const isActive = ref(false);
+  const currentDirection = ref(1); // 1: 正向, -1: 反向
+  const delayFrames = ref(0);
+
+  // 使用 VueUse 的 useScroll
+  const { arrivedState, x, y } = useScroll(container, {
+    behavior: 'smooth',
+  }) as UseScrollReturn;
+
+  // 检查是否到达边界
+  const checkBoundary = (): boolean => {
+    if (direction === 'y') {
+      return currentDirection.value > 0 ? arrivedState.bottom : arrivedState.top;
+    } else {
+      return currentDirection.value > 0 ? arrivedState.right : arrivedState.left;
+    }
+  };
+
+  // 执行滚动
+  const performScroll = () => {
+    if (!isActive.value) return;
+    if (delayFrames.value > 0) {
+      delayFrames.value--;
+      return;
+    }
+
+    // 检查边界
+    if (checkBoundary()) {
+      if (rollBack) {
+        // 回滚模式:反转方向
+        reverse();
+      } else {
+        // 循环模式:回到开始位置
+        reset();
+      }
+      return;
+    }
+
+    // 执行滚动
+    if (direction === 'y') {
+      y.value += step * currentDirection.value;
+    } else {
+      x.value += step * currentDirection.value;
+    }
+  };
+
+  // 开始/恢复滚动
+  const start = () => {
+    if (!isActive.value) {
+      ticker.remove(performScroll);
+      ticker.add(performScroll);
+      isActive.value = true;
+      delayFrames.value = delay;
+    }
+  };
+
+  // 暂停滚动
+  const pause = () => {
+    delayFrames.value = Number.MAX_SAFE_INTEGER;
+  };
+
+  // 重置到初始状态
+  const reset = () => {
+    if (direction === 'y') {
+      y.value = 0;
+    } else {
+      x.value = 0;
+    }
+    currentDirection.value = 1;
+    delayFrames.value = delay;
+  };
+
+  // 反转滚动方向
+  const reverse = () => {
+    currentDirection.value *= -1;
+    delayFrames.value = delay;
+  };
+
+  const resume = () => {
+    delayFrames.value = delay;
+  };
+
+  // 监听用户交互事件
+  const setupUserInteractionListeners = (el: HTMLElement) => {
+    // 鼠标滚轮事件
+    const handleWheel = () => {
+      resume();
+    };
+
+    // 鼠标按下事件(用于拖动滚动条)
+    const handleMouseDown = () => {
+      pause();
+    };
+
+    // 鼠标抬起事件
+    const handleMouseUp = () => {
+      resume();
+    };
+
+    // 触摸事件
+    const handleTouchStart = () => {
+      pause();
+    };
+
+    const handleTouchEnd = () => {
+      resume();
+    };
+
+    // 键盘事件(PageUp/PageDown/方向键)
+    const handleKeyDown = (e: KeyboardEvent) => {
+      const scrollKeys = ['PageUp', 'PageDown', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Space'];
+      if (scrollKeys.includes(e.key)) {
+        pause();
+      }
+    };
+
+    const handleKeyUp = () => {
+      resume();
+    };
+
+    // 添加事件监听
+    el.addEventListener('wheel', handleWheel, { passive: true });
+    el.addEventListener('mousedown', handleMouseDown);
+    el.addEventListener('mouseup', handleMouseUp);
+    el.addEventListener('touchstart', handleTouchStart, { passive: true });
+    el.addEventListener('touchend', handleTouchEnd);
+    el.addEventListener('keydown', handleKeyDown);
+    el.addEventListener('keyup', handleKeyUp);
+
+    // 返回清理函数
+    return () => {
+      el.removeEventListener('wheel', handleWheel);
+      el.removeEventListener('mousedown', handleMouseDown);
+      el.removeEventListener('mouseup', handleMouseUp);
+      el.removeEventListener('touchstart', handleTouchStart);
+      el.removeEventListener('touchend', handleTouchEnd);
+      el.removeEventListener('keydown', handleKeyDown);
+      el.removeEventListener('keyup', handleKeyUp);
+    };
+  };
+
+  // 监听容器变化
+  watch(
+    () => unref(container),
+    (newContainer) => {
+      if (cleanupListeners) {
+        cleanupListeners();
+        cleanupListeners = null;
+      }
+      if (newContainer) {
+        cleanupListeners = setupUserInteractionListeners(newContainer);
+        // 容器变化时重置状态
+        reset();
+      }
+    }
+  );
+
+  onMounted(() => {
+    // 自动开始
+    if (autoStart) {
+      start();
+    }
+  });
+
+  // 清理
+  onUnmounted(() => {
+    ticker.remove(performScroll);
+  });
+
+  return {
+    start,
+    pause,
+    reset,
+    reverse,
+    resume,
+  };
+}

+ 5 - 2
src/views/vent/deviceManager/configurationTable/types.ts

@@ -1,4 +1,3 @@
-import { data } from 'emoji-mart-vue-fast/data/apple.json';
 export interface Config {
   /** 模块的名称 */
   moduleName: string;
@@ -98,7 +97,9 @@ export interface ModuleData {
         | 'partition'
         | 'selector_dual_chart'
         | 'radio_label'
-        | 'button_list';
+        | 'button_list'
+        | 'card_list'
+        | 'generalist';
       /** 分区大小 */
       basis: string;
       overflow?: boolean;
@@ -334,6 +335,8 @@ export interface ModuleDataChart extends ReadFrom {
 export interface ModuleDataTable extends ReadFrom {
   /** 表格的预设样式 */
   type: 'A' | 'B' | 'C' | 'D';
+  /** 是否自动滚动 */
+  autoScroll?: boolean;
   /** 核心配置,每个表格列对应一项 */
   columns: {
     /** 数据说明,注意该项不支持 formatter 格式 */

+ 1 - 1
src/views/vent/home/configurable/components/MonitorBar.vue

@@ -125,7 +125,7 @@
 <style lang="less" scoped>
   .middata {
     // margin-top: 7px;
-    padding: 5px 0px 5px 50px;
+    padding: 5px 0px 5px 60px;
     width: calc(100% - 10px);
     height: 65px;
     margin-top: 4px;

+ 7 - 1
src/views/vent/home/configurable/components/content.vue

@@ -90,7 +90,13 @@
         </template>
         <!-- 表格部分,这部分通常是占一整个模块的 -->
         <template v-if="config.name === 'table'">
-          <CustomTable class="content__module text-center overflow-auto" :type="config.type" :columns="config.columns" :data="config.data" />
+          <CustomTable
+            class="content__module text-center overflow-auto"
+            :type="config.type"
+            :columns="config.columns"
+            :auto-scroll="config.autoScroll"
+            :data="config.data"
+          />
         </template>
         <template v-if="config.name === 'tabs'">
           <CustomTabs class="content__module" :type="config.type" :tab-config="config.items" :overflow="config.overflow" />

+ 10 - 2
src/views/vent/home/configurable/components/detail/CustomTable.vue

@@ -3,7 +3,7 @@
     <div class="table__content_label" :class="`table__content_label_${type}`">
       <div class="label-t" v-for="(item, index) in columns" :key="`svvhbcth-${index}`" :style="{ flexBasis }">{{ item.name }}</div>
     </div>
-    <div class="table__content_list" :class="`table__content_list_${type}`">
+    <div ref="scrollRef" class="table__content_list" :class="`table__content_list_${type}`">
       <div class="table__content_list_row" v-for="(item, index) in data" :key="`svvhbct-${index}`">
         <div v-for="(t, i) in columns" :key="`svvhbctr-${i}`" :style="{ flexBasis }" :class="`table__content__list_item_${type}`">
           <slot :name="t.prop" :scope="item">
@@ -15,13 +15,15 @@
   </div>
 </template>
 <script lang="ts" setup>
-  import { computed, defineProps } from 'vue';
+  import { computed, defineProps, ref } from 'vue';
   import _ from 'lodash';
+  import { useAutoScroll } from '/@/hooks/core/useAutoScroll';
 
   let props = withDefaults(
     defineProps<{
       /** B | C */
       type: string;
+      autoScroll: boolean;
       /** 列表表头配置,每个prop都有其对应的slot来提供定制化功能 */
       columns: { prop: string; name: string }[];
       data: any[];
@@ -29,12 +31,18 @@
     }>(),
     {
       type: 'B',
+      autoScroll: false,
       columns: () => [],
       data: () => [],
       defaultValue: '-',
     }
   );
 
+  const scrollRef = ref(null);
+  if (props.autoScroll) {
+    useAutoScroll(scrollRef);
+  }
+
   const flexBasis = computed(() => {
     return Math.fround(100 / props.columns.length) + '%';
   });

+ 508 - 12
src/views/vent/home/configurable/configurable.data.ts

@@ -4,6 +4,452 @@ import { fanControlState1 } from '../../monitorManager/fanLocalMonitor1/fanLocal
 // import { BDdustMock, BDfireMock } from './configurable.data.bd';
 import { getThemifyImagesURL } from '/@/utils/ui';
 
+export const testConfigVentSsl: Config[] = [
+  {
+    deviceType: 'fanmain',
+    moduleName: '主通风机系统',
+    pageType: 'vent',
+    moduleData: {
+      header: {
+        show: true,
+        readFrom: '',
+        selector: {
+          show: true,
+          value: '${strinstallpos}',
+        },
+        slot: {
+          show: true,
+          value: '运行风机:${readData.Fan1StartStatus}',
+          trans: {
+            '1': '一号',
+            '0': '二号',
+          },
+        },
+      },
+      background: {
+        show: true,
+        type: 'video',
+        link: '/video/video.mp4',
+      },
+      layout: {
+        direction: 'column',
+        items: [
+          {
+            name: 'board',
+            basis: '33%',
+          },
+        ],
+      },
+      board: [
+        {
+          type: 'A',
+          readFrom: '',
+          layout: 'val-top',
+          items: [
+            {
+              label: '风量(m³/min)',
+              value: '${flow_merge}',
+            },
+            {
+              label: '负压(Pa)',
+              value: '${fy_merge}',
+            },
+            {
+              label: '漏风率(%)',
+              value: '${leakage}',
+            },
+          ],
+        },
+      ],
+      list: [],
+      chart: [],
+      table: [],
+      gallery: [],
+      complex_list: [],
+      gallery_list: [],
+      preset: [],
+      to: '/micro-vent-3dModal/dashboard/analysis?type=tunMonitor&deviceType=fanmain',
+    },
+    showStyle: {
+      size: 'width:420px;height:280px;',
+      version: '原版',
+      position: 'top:60px;left:0;',
+    },
+  },
+  {
+    deviceType: 'fanlocal',
+    moduleName: '局部通风机系统',
+    pageType: 'vent',
+    moduleData: {
+      header: {
+        show: true,
+        readFrom: '',
+        selector: {
+          show: true,
+          value: '${strinstallpos}',
+        },
+        slot: {
+          show: true,
+          value: '运行风机:${readData.Fan1StartStatus}',
+          trans: {
+            '1': '一号',
+            '0': '二号',
+          },
+        },
+      },
+      background: {
+        show: true,
+        type: 'video',
+        link: '/video/video.mp4',
+      },
+      layout: {
+        direction: 'column',
+        items: [
+          {
+            name: 'board',
+            basis: '33%',
+          },
+        ],
+      },
+      board: [
+        {
+          type: 'A',
+          readFrom: '',
+          layout: 'val-top',
+          items: [
+            {
+              label: '风量(m³/min)',
+              value: '${flow_merge}',
+            },
+            {
+              label: '负压(Pa)',
+              value: '${fy_merge}',
+            },
+            {
+              label: '漏风率(%)',
+              value: '${leakage}',
+            },
+          ],
+        },
+      ],
+      list: [],
+      chart: [],
+      table: [],
+      gallery: [],
+      complex_list: [],
+      gallery_list: [],
+      preset: [],
+      to: '/micro-vent-3dModal/dashboard/analysis?type=tunMonitor&deviceType=fanlocal',
+    },
+    showStyle: {
+      size: 'width:420px;height:280px;',
+      version: '原版',
+      position: 'top:350px;left:0;',
+    },
+  },
+  {
+    deviceType: '',
+    moduleName: '通风设施远程控制',
+    pageType: 'vent',
+    moduleData: {
+      header: {
+        show: false,
+        readFrom: '',
+        selector: {
+          show: false,
+          value: '',
+        },
+        slot: {
+          show: false,
+          value: '',
+        },
+      },
+      background: {
+        show: true,
+        type: 'video',
+        link: '/video/video.mp4',
+      },
+      layout: {
+        direction: 'row',
+        items: [],
+      },
+      board: [],
+      list: [],
+      chart: [],
+      table: [],
+      gallery: [],
+      complex_list: [],
+      gallery_list: [],
+      preset: [],
+      to: '/micro-vent-3dModal/dashboard/analysis?type=tunMonitor&deviceType=gate_xinJianFuXieJin',
+    },
+    showStyle: {
+      size: 'width:420px;height:280px;',
+      version: '原版',
+      position: 'top:640px;left:0;',
+    },
+  },
+  {
+    deviceType: 'sys_wind',
+    moduleName: '风量监测',
+    pageType: 'vent_new',
+    moduleData: {
+      header: {
+        show: false,
+        readFrom: '',
+        selector: {
+          show: false,
+          value: '',
+        },
+        slot: {
+          show: false,
+          value: '',
+        },
+      },
+      background: {
+        show: false,
+        type: 'video',
+        link: '',
+      },
+      layout: {
+        direction: 'row',
+        items: [
+          {
+            name: 'chart',
+            basis: '100%',
+          },
+        ],
+      },
+      board: [],
+      list: [],
+      table: [],
+      preset: [],
+      gallery: [],
+      complex_list: [],
+      gallery_list: [],
+      chart: [
+        {
+          type: 'bar',
+          readFrom: '',
+          legend: { show: true },
+          xAxis: [{ show: true }],
+          yAxis: [
+            { show: true, name: '风量(m³/min)', position: 'left' },
+            { show: true, name: '风速(m/s)', position: 'right' },
+          ],
+          dataZoom: [
+            {
+              show: false,
+              end: 20,
+            },
+          ],
+          series: [
+            { readFrom: 'sys_wind', xprop: 'strinstallpos', yprop: 'readData.m3', label: '风量' },
+            { readFrom: 'sys_wind', xprop: 'strinstallpos', yprop: 'readData.va', label: '风速' },
+          ],
+        },
+      ],
+      to: '/micro-vent-3dModal/dashboard/analysis?type=tunMonitor&deviceType=windrect',
+    },
+    showStyle: {
+      size: 'width:1100px;height:280px;',
+      version: '原版',
+      position: 'top:640px;left:410px;',
+    },
+  },
+  {
+    deviceType: '',
+    moduleName: '风窗监测',
+    pageType: 'vent',
+    moduleData: {
+      header: {
+        show: false,
+        readFrom: '',
+        selector: {
+          show: false,
+          value: '',
+        },
+        slot: {
+          show: false,
+          value: '',
+        },
+      },
+      background: {
+        show: true,
+        type: 'video',
+        link: '/video/video.mp4',
+      },
+      layout: {
+        direction: 'row',
+        items: [],
+      },
+      board: [],
+      list: [],
+      chart: [],
+      table: [],
+      gallery: [],
+      complex_list: [],
+      gallery_list: [],
+      preset: [],
+      to: '/micro-vent-3dModal/dashboard/analysis?type=tunMonitor&deviceType=gate_xinJianFuXieJin',
+    },
+    showStyle: {
+      size: 'width:420px;height:280px;',
+      version: '原版',
+      position: 'top:60px;right:0;',
+    },
+  },
+  {
+    deviceType: 'safetymonitor',
+    moduleName: '安全监控系统',
+    pageType: 'fire',
+    moduleData: {
+      header: {
+        show: false,
+        readFrom: '',
+        selector: {
+          show: false,
+          value: '',
+        },
+        slot: {
+          show: false,
+          value: '',
+        },
+      },
+      background: {
+        show: false,
+        type: 'video',
+        link: '',
+      },
+      layout: {
+        direction: 'row',
+        items: [
+          {
+            name: 'table',
+            basis: '100%',
+          },
+        ],
+      },
+      board: [],
+      chart: [],
+      gallery: [],
+      gallery_list: [],
+      table: [
+        {
+          type: 'C',
+          readFrom: 'safetymonitor',
+          columns: [
+            {
+              name: '测点位置',
+              prop: 'strinstallpos',
+            },
+            {
+              name: '数据',
+              prop: 'readData.V',
+            },
+            {
+              name: '单位',
+              prop: 'readData.unit',
+            },
+          ],
+        },
+      ],
+      list: [],
+      complex_list: [],
+      preset: [],
+    },
+    showStyle: {
+      size: 'width:420px;height:280px;',
+      version: '原版',
+      position: 'top:350px;right:0;',
+    },
+  },
+  {
+    deviceType: 'warn',
+    moduleName: '预警监测',
+    pageType: 'vent',
+    moduleData: {
+      header: {
+        show: true,
+        readFrom: '',
+        selector: {
+          show: false,
+          value: '',
+        },
+        slot: {
+          show: true,
+          value: '网络异常:${warn[0].netstatus.val}',
+        },
+      },
+      background: {
+        show: false,
+        type: 'video',
+        link: '',
+      },
+      layout: {
+        direction: 'row',
+        items: [
+          {
+            name: 'list',
+            basis: '100%',
+          },
+        ],
+      },
+      board: [],
+      list: [
+        {
+          type: 'timeline',
+          readFrom: 'warn[0]',
+          items: [
+            {
+              label: '报警',
+              value: '${alarm.val}',
+              info: '',
+              color: 'red',
+            },
+            {
+              label: '重大风险预警',
+              value: '${red.val}',
+              info: '',
+              color: 'red',
+            },
+            {
+              label: '较大风险预警',
+              value: '${orange.val}',
+              info: '',
+              color: 'orange',
+            },
+            {
+              label: '一般风险预警',
+              value: '${yellow.val}',
+              info: '',
+              color: 'yellow',
+            },
+            {
+              label: '低风险预警',
+              value: '${blue.val}',
+              info: '',
+              color: 'blue',
+            },
+          ],
+        },
+      ],
+      preset: [],
+      table: [],
+      gallery: [],
+      chart: [],
+      gallery_list: [],
+      complex_list: [],
+      to: '/monitorChannel/monitor-alarm-home',
+    },
+    showStyle: {
+      size: 'width:420px;height:280px;',
+      version: '原版',
+      position: 'top:640px;right:0;',
+    },
+  },
+];
+
 export const testConfigVent: Config[] = [
   {
     deviceType: 'fanmain',
@@ -4408,7 +4854,7 @@ export let menuList: any[] = [
   { name: '通风预警', MenuItemList: [] },
   { name: '火灾预警', MenuItemList: [] },
   { name: '粉尘预警', MenuItemList: [] },
-]
+];
 export const testConfigBDFire: Config[] = [
   {
     deviceType: 'fireManageInfo',
@@ -5527,9 +5973,8 @@ export const testConfigElectro: Config[] = [
           show: true,
           value: '${strinstallpos}',
           toggleIcon: true,
-
         },
-        
+
         slot: {
           show: false,
           value: '',
@@ -5558,8 +6003,7 @@ export const testConfigElectro: Config[] = [
       complex_list: [],
       preset: [
         {
-          readFrom: 'cardData',
-         
+          readFrom: 'datalist',
         },
       ],
       to: '/ventilate/warn/home',
@@ -5604,10 +6048,64 @@ export const testConfigElectro: Config[] = [
             basis: '70%',
           },
         ],
-
       },
       board: [],
-      list: [],
+      list: [
+        {
+          type: 'N',
+          readFrom: 'arrayCount',
+          items: [
+            {
+              label: '分区1',
+              value: '${coVal}',
+              color: 'blue',
+              info: '',
+            },
+            {
+              label: '分区2',
+              value: '${co2Val}',
+              color: 'blue',
+              info: '',
+            },
+            {
+              label: '分区3',
+              value: '${o2Val}',
+              color: 'blue',
+              info: '',
+            },
+            {
+              label: '分区4',
+              value: '${tempVal}',
+              color: 'blue',
+              info: '',
+            },
+            {
+              label: '分区5',
+              value: '${coVal}',
+              color: 'blue',
+              info: '',
+            },
+            {
+              label: '分区6',
+              value: '${co2Val}',
+              color: 'blue',
+              info: '',
+            },
+            {
+              label: '分区7',
+              value: '${o2Val}',
+              color: 'blue',
+              info: '',
+            },
+            {
+              label: '分区8',
+              value: '${tempVal}',
+              color: 'blue',
+              info: '',
+            },
+          ],
+        },
+      ],
       chart: [
         {
           type: 'line',
@@ -5619,7 +6117,7 @@ export const testConfigElectro: Config[] = [
             { readFrom: 'chartData', xprop: 'time', yprop: 'coRealTime', label: 'CO实时值' },
             { readFrom: 'chartData', xprop: 'time', yprop: 'coWarn', label: 'CO报警阈值' },
           ],
-        }
+        },
       ],
       table: [],
       gallery: [],
@@ -5628,9 +6126,8 @@ export const testConfigElectro: Config[] = [
       preset: [
         {
           readFrom: 'tempData',
-         
-        }
-        ],
+        },
+      ],
       to: '',
     },
     showStyle: {
@@ -5639,5 +6136,4 @@ export const testConfigElectro: Config[] = [
       position: 'top:0px;right:0px;',
     },
   },
-
 ];

+ 303 - 0
src/views/vent/home/configurable/ventV6.vue

@@ -0,0 +1,303 @@
+<!-- eslint-disable vue/multi-word-component-names -->
+<template>
+  <div class="company-home">
+    <div style="width: 100%; height: 100%; position: absolute; left: 0; top: 0; z-index: 0">
+      <VentModal />
+    </div>
+    <!-- 如果是有 deviceType、type 等 query,认为是详情页,不需要展示普通模块,只需要模型 -->
+    <template v-if="!route.query.deviceType">
+      <div v-if="!route.query.embed" class="top-bg">
+        <div class="main-title">{{ mainTitle }}</div>
+      </div>
+      <a class="ant-dropdown-link module-dropdown" @click.prevent="showBar = !showBar">
+        全矿井通风检测
+        <CaretDownOutlined />
+      </a>
+      <MonitorBar
+        v-if="showBar"
+        class="module-monitor-bar"
+        :style="{ width: `${barWidth}px`, left: `calc(50% - ${Math.floor(barWidth / 2)}px)` }"
+        :is-data-real-time="isDataRealTime"
+        :data="data"
+      />
+      <!-- <a-dropdown class="module-dropdown" :class="{ 'module-dropdown-original': isOriginal }" :trigger="['click']" placement="bottomRight">
+        <template #overlay>
+        </template>
+      </a-dropdown> -->
+
+      <!-- 采用定位方式以避免出现各个模块隐藏时其他模块下移的问题 -->
+      <template v-if="isOriginal">
+        <ModuleOriginal
+          v-for="cfg in configs"
+          :key="cfg.deviceType"
+          :show-style="cfg.showStyle"
+          :module-data="cfg.moduleData"
+          :module-name="cfg.moduleName"
+          :device-type="cfg.deviceType"
+          :data="data"
+          :visible="true"
+        />
+      </template>
+      <template v-else-if="isCommon">
+        <ModuleCommon
+          v-for="cfg in configs"
+          :key="cfg.deviceType"
+          :show-style="cfg.showStyle"
+          :module-data="cfg.moduleData"
+          :module-name="cfg.moduleName"
+          :device-type="cfg.deviceType"
+          :data="data"
+          :visible="true"
+        />
+      </template>
+      <template v-else>
+        <!-- 下面是正常展示的各新版模块 -->
+        <ModuleEnhanced
+          v-for="cfg in enhancedConfigs"
+          :key="cfg.deviceType"
+          :visible="cfg.visible"
+          :show-style="cfg.showStyle"
+          :module-data="cfg.moduleData"
+          :module-name="cfg.moduleName"
+          :device-type="cfg.deviceType"
+          :data="data"
+          @close="cfg.visible = false"
+        />
+        <!-- 下面是用于呼出已隐藏的模块的按钮 -->
+        <div class="flex pos-absolute bottom-10px left-60px z-3">
+          <div v-for="(item, i) in hiddenList" :key="`vvhchg${i}`">
+            <AButton class="module-trigger-button" @click="item.visible = true">{{ item.moduleName }}</AButton>
+          </div>
+        </div>
+      </template>
+      <div
+        v-if="sysDataType === 'all'"
+        :class="{ 'realtime-mode': isDataRealTime }"
+        alt="切换数据模式"
+        class="switch-button report-mode right-525px"
+        @click="switchDataMode"
+      ></div>
+      <div class="switch-button icon-goto right-475px" @click="goMicroApp()"></div>
+    </template>
+  </div>
+</template>
+<script lang="ts" setup>
+  import { onMounted, onUnmounted, ref, watch } from 'vue';
+  // import { CaretDownOutlined } from '@ant-design/icons-vue';
+  import MonitorBar from './components/MonitorBar.vue';
+  import { useInitConfigs, useInitPage } from './hooks/useInit';
+  import ModuleEnhanced from './components/ModuleEnhanced.vue';
+  import ModuleOriginal from './components/ModuleOriginal.vue';
+  import ModuleCommon from './components/ModuleCommon.vue';
+  // import { useRoute } from 'vue-router';
+  import VentModal from '/@/components/vent/micro/ventModal.vue';
+  import { list } from './configurable.api';
+  import { useRoute, useRouter } from 'vue-router';
+  import { useGlobSetting } from '/@/hooks/setting';
+  // import { testConfigVentSsl } from './configurable.data';
+  import { computed } from 'vue';
+  // import { testConfigVent, testConfigVentRealtime } from './configurable.data';
+
+  const { sysDataType = 'monitor', title = '智能通风管控系统' } = useGlobSetting();
+  const { configs, isOriginal, isCommon, fetchConfigs } = useInitConfigs();
+  const { mainTitle, enhancedConfigs, hiddenList, data, updateData, updateEnhancedConfigs } = useInitPage(title);
+  const route = useRoute();
+  const router = useRouter();
+  const isDataRealTime = ref(sysDataType === 'monitor');
+  const showBar = ref(true);
+  /** 最长的模块的长度(一版指正下方模块) */
+  const barWidth = computed<number>(() => {
+    for (let index = 0; index < configs.value.length; index++) {
+      const element = configs.value[index];
+      const { size, position } = element.showStyle;
+      const [_, width] = size.match(/width:([0-9]+)px/) || [];
+      if (position.includes('bottom') || parseInt(width) > 800) {
+        return parseInt(width);
+      }
+    }
+    return 1000;
+  });
+  let interval: number | undefined;
+
+  function switchDataMode() {
+    isDataRealTime.value = !isDataRealTime.value;
+    refresh();
+  }
+
+  function refresh() {
+    fetchConfigs(isDataRealTime.value ? 'vent_realtime' : 'vent').then(() => {
+      // configs.value = isDataRealTime.value ? testConfigVentRealtime : testConfigVent;
+      // configs.value = testConfigVentSsl;
+      updateEnhancedConfigs(configs.value);
+
+      list({
+        types: configs.value
+          .filter((e) => e.deviceType)
+          .map((e) => e.deviceType)
+          .join(','),
+      }).then(updateData);
+    });
+  }
+
+  function initInterval() {
+    setInterval(() => {
+      list({
+        types: configs.value
+          .filter((e) => e.deviceType)
+          .map((e) => e.deviceType)
+          .join(','),
+      }).then(updateData);
+    }, 60000);
+  }
+
+  function goMicroApp() {
+    router.push({
+      path: route.path,
+      query: {
+        ...route.query,
+        type: 'model3D',
+        deviceType: 'model3D',
+      },
+    });
+  }
+
+  watch(
+    () => route.query,
+    () => {
+      if (route.query.deviceType) {
+        // 仅需要展示子应用,模拟 unmounted
+        clearInterval(interval);
+      } else {
+        // 模拟 mounted
+        refresh();
+        initInterval();
+      }
+    }
+  );
+
+  onMounted(() => {
+    refresh();
+    initInterval();
+  });
+
+  onUnmounted(() => {
+    clearInterval(interval);
+  });
+</script>
+<style lang="less" scoped>
+  @import '/@/design/theme.less';
+
+  @font-face {
+    font-family: 'douyuFont';
+    src: url('/@/assets/font/douyuFont.otf');
+  }
+
+  @{theme-deepblue} {
+    .company-home {
+      --image-modal-top: url('/@/assets/images/themify/deepblue/vent/home/modal-top.png');
+    }
+  }
+
+  .company-home {
+    --image-modal-top: url('/@/assets/images/vent/home/modal-top.png');
+    --image-monitor-realtime: url('/@/assets/images/company/monitor-realtime.png');
+    --image-monitor-doc: url('/@/assets/images/company/monitor-doc.png');
+    --image-monitor-goto: url('/@/assets/images/company/monitor-goto.png');
+
+    width: 100%;
+    height: 100%;
+    color: @white;
+    position: relative;
+    // background: url('@/assets/images/home-container/configurable/firehome/bg.png') no-repeat center;
+
+    .top-bg {
+      width: 100%;
+      height: 56px;
+      background: var(--image-modal-top) no-repeat center;
+      position: absolute;
+      z-index: 1;
+      .main-title {
+        height: 56px;
+        font-family: 'douyuFont';
+        font-size: 20px;
+        letter-spacing: 2px;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+      }
+    }
+
+    // .module-left {
+    //   position: absolute;
+    //   width: 450px;
+    //   height: 280px;
+    //   left: 0;
+    // }
+    // .module-right {
+    //   position: absolute;
+    //   width: 450px;
+    //   height: 280px;
+    //   right: 0;
+    // }
+    // .module-bottom {
+    //   position: absolute;
+    //   width: 1000px;
+    //   height: 280px;
+    // }
+    .module-dropdown {
+      padding: 5px;
+      background-image: @vent-configurable-dropdown;
+      border-bottom: 2px solid @vent-configurable-home-light-border;
+      color: @vent-font-color;
+      position: absolute;
+      top: 60px;
+      right: 480px;
+    }
+    .module-dropdown-original {
+      padding: 10px;
+      background-image: @vent-configurable-dropdown;
+      border-bottom: 2px solid @vent-configurable-home-light-border;
+      color: @vent-font-color;
+      position: absolute;
+      top: 70px;
+      right: 460px;
+    }
+    .module-trigger-button {
+      color: @vent-font-color;
+      background-image: @vent-configurable-dropdown;
+      border: none;
+      border-bottom: 2px solid @vent-configurable-home-light-border;
+    }
+
+    .switch-button {
+      width: 34px;
+      height: 34px;
+      position: absolute;
+      // right: 5px;
+      bottom: 300px;
+      z-index: 5;
+      background-repeat: no-repeat;
+      background-size: 100% 100%;
+    }
+    .report-mode {
+      background-image: var(--image-monitor-doc);
+    }
+    .realtime-mode {
+      background-image: var(--image-monitor-realtime);
+    }
+    .icon-goto {
+      background-image: var(--image-monitor-goto);
+    }
+
+    .module-monitor-bar {
+      position: absolute;
+      top: 100px;
+      width: 1000px;
+      height: 200px;
+      left: calc(50% - 500px);
+    }
+  }
+  :deep(.loading-box) {
+    position: unset;
+  }
+</style>