Explorar o código

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

hongrunxia hai 7 meses
pai
achega
a016f278e2
Modificáronse 41 ficheiros con 3369 adicións e 1268 borrados
  1. BIN=BIN
      src/assets/images/company/list-item-9.png
  2. BIN=BIN
      src/assets/images/vent/dust-icon-2.png
  3. BIN=BIN
      src/assets/images/vent/dust-icon.png
  4. BIN=BIN
      src/assets/images/vent/fanlocal-page/arrow-button-hover.png
  5. BIN=BIN
      src/assets/images/vent/fanlocal-page/arrow-button.png
  6. BIN=BIN
      src/assets/images/vent/fanlocal-page/card.png
  7. BIN=BIN
      src/assets/images/vent/fanlocal-page/is-txzt.png
  8. BIN=BIN
      src/assets/images/vent/fanlocal-page/is-txzt1.png
  9. BIN=BIN
      src/assets/images/vent/fanlocal-page/is-warn.png
  10. BIN=BIN
      src/assets/images/vent/fanlocal-page/is-warn1.png
  11. BIN=BIN
      src/assets/images/vent/fanlocal-page/one-bg.png
  12. BIN=BIN
      src/assets/images/vent/fire-icon-2.png
  13. BIN=BIN
      src/assets/images/vent/fire-icon.png
  14. BIN=BIN
      src/assets/images/vent/gas-icon-2.png
  15. BIN=BIN
      src/assets/images/vent/gas-icon.png
  16. BIN=BIN
      src/assets/images/vent/safety-icon-2.png
  17. BIN=BIN
      src/assets/images/vent/safety-icon.png
  18. BIN=BIN
      src/assets/images/vent/vent-icon-2.png
  19. BIN=BIN
      src/assets/images/vent/vent-icon.png
  20. 7 1
      src/router/guard/permissionGuard.ts
  21. 209 171
      src/views/vent/home/billboard/billboard.data.ts
  22. 141 0
      src/views/vent/home/billboard/components/Warning.vue
  23. 2 0
      src/views/vent/home/billboard/index.vue
  24. 7 0
      src/views/vent/home/billboard/warn.vue
  25. 3 2
      src/views/vent/home/configurable/components/ModuleBD.vue
  26. 23 4
      src/views/vent/home/configurable/components/detail/ComplexList.vue
  27. 3 0
      src/views/vent/home/configurable/components/detail/CustomGallery.vue
  28. 88 177
      src/views/vent/home/configurable/configurable.data.ts
  29. 10 4
      src/views/vent/home/configurable/dustBD.vue
  30. 8 2
      src/views/vent/home/configurable/fireBD.vue
  31. 14 9
      src/views/vent/home/configurable/hooks/useInit.ts
  32. 18 12
      src/views/vent/home/configurable/index.vue
  33. 54 0
      src/views/vent/monitorManager/fanLocalMonitor/components/fanlocal-echart-line.vue
  34. 59 0
      src/views/vent/monitorManager/fanLocalMonitor/components/fanlocal-history.vue
  35. 36 0
      src/views/vent/monitorManager/fanLocalMonitor/components/fanlocal-operate-history.vue
  36. 29 0
      src/views/vent/monitorManager/fanLocalMonitor/components/fanlocal-warn-history.vue
  37. 27 0
      src/views/vent/monitorManager/fanLocalMonitor/fanLocal.data.ts
  38. 1795 0
      src/views/vent/monitorManager/fanLocalMonitor/index-copy.vue
  39. 545 886
      src/views/vent/monitorManager/fanLocalMonitor/index.vue
  40. 12 0
      src/views/vent/monitorManager/fanlocalPage/fanlocal.api.ts
  41. 279 0
      src/views/vent/monitorManager/fanlocalPage/index.vue

BIN=BIN
src/assets/images/company/list-item-9.png


BIN=BIN
src/assets/images/vent/dust-icon-2.png


BIN=BIN
src/assets/images/vent/dust-icon.png


BIN=BIN
src/assets/images/vent/fanlocal-page/arrow-button-hover.png


BIN=BIN
src/assets/images/vent/fanlocal-page/arrow-button.png


BIN=BIN
src/assets/images/vent/fanlocal-page/card.png


BIN=BIN
src/assets/images/vent/fanlocal-page/is-txzt.png


BIN=BIN
src/assets/images/vent/fanlocal-page/is-txzt1.png


BIN=BIN
src/assets/images/vent/fanlocal-page/is-warn.png


BIN=BIN
src/assets/images/vent/fanlocal-page/is-warn1.png


BIN=BIN
src/assets/images/vent/fanlocal-page/one-bg.png


BIN=BIN
src/assets/images/vent/fire-icon-2.png


BIN=BIN
src/assets/images/vent/fire-icon.png


BIN=BIN
src/assets/images/vent/gas-icon-2.png


BIN=BIN
src/assets/images/vent/gas-icon.png


BIN=BIN
src/assets/images/vent/safety-icon-2.png


BIN=BIN
src/assets/images/vent/safety-icon.png


BIN=BIN
src/assets/images/vent/vent-icon-2.png


BIN=BIN
src/assets/images/vent/vent-icon.png


+ 7 - 1
src/router/guard/permissionGuard.ts

@@ -15,7 +15,7 @@ import { OAUTH2_THIRD_LOGIN_TENANT_ID } from '/@/enums/cacheEnum';
 import { useGlobSetting } from '/@/hooks/setting';
 
 import _ from 'lodash';
-import { AUTO_LOGIN_URL_QUERY, SKIP_SSO_URL_QUERY } from '../constant';
+import { MOCK_LOGIN_URL_QUERY, SKIP_SSO_URL_QUERY } from '../constant';
 import { useSso } from '/@/hooks/web/useSso';
 import { useAutoLogin } from '/@/hooks/vent/useAutoLogin';
 
@@ -67,6 +67,12 @@ export function createPermissionGuard(router: Router) {
       // 自动登录后会动态添加路由,此处应当重定向到fullPath,否则会加载404页面内容
       return next({ path: to.fullPath, replace: true, query: to.query });
     }
+    // 如果指定了需要模拟登录则执行模拟登录,覆盖原有的登录信息
+    if (to.query[MOCK_LOGIN_URL_QUERY.key] === MOCK_LOGIN_URL_QUERY.val) {
+      await userStore.mockLogin({ goHome: false });
+      delete to.query[MOCK_LOGIN_URL_QUERY.key];
+      return next({ path: to.fullPath, replace: true, query: to.query });
+    }
 
     const token = userStore.getToken;
 

+ 209 - 171
src/views/vent/home/billboard/billboard.data.ts

@@ -1,178 +1,192 @@
 import leftImg from '/@/assets/images/files/homes/file.svg';
 import rightImg from '/@/assets/images/files/homes/sp.svg';
+import GasIcon from '/@/assets/images/vent/gas-icon-2.png';
+import FireIcon from '/@/assets/images/vent/fire-icon-2.png';
+import VentIcon from '/@/assets/images/vent/vent-icon-2.png';
+import SafetyIcon from '/@/assets/images/vent/safety-icon-2.png';
+import DustIcon from '/@/assets/images/vent/dust-icon-2.png';
 
-export type Translation = Record<string | number, string>;
-export interface TitleConfig {
-  label: string;
-  prop: string;
-  translation?: Translation;
-}
-export interface HeaderConfig {
-  label: string;
-  prop: string;
-  translation?: Translation;
-}
-export interface TableConfig {
-  prop: string;
-  columns: { label: string; prop: string; _t?: boolean }[];
-  collapses: { label: string; prop: string; _t?: boolean }[];
-  translation?: Translation;
-}
-export interface ListConfig {
-  icon: string;
-  label: string;
-  prop: string;
-  translation?: Translation;
-  collapses: { label: string; prop: string; _t?: boolean }[];
-}
-export interface OverviewConfig {
-  label: string;
-  prop: string;
-  src: string;
-}
-export interface TreeConfig {
-  prefix: string;
-  prop: string;
-  suffix: string;
-  children: {
-    prefix: string;
-    prop: string;
-    suffix: string;
-  }[];
-  translation?: Record<string | number, string>;
-}
+// export type Translation = Record<string | number, string>;
+// export interface TitleConfig {
+//   label: string;
+//   prop: string;
+//   translation?: Translation;
+// }
+// export interface HeaderConfig {
+//   label: string;
+//   prop: string;
+//   translation?: Translation;
+// }
+// export interface TableConfig {
+//   prop: string;
+//   columns: { label: string; prop: string; _t?: boolean }[];
+//   collapses: { label: string; prop: string; _t?: boolean }[];
+//   translation?: Translation;
+// }
+// export interface ListConfig {
+//   icon: string;
+//   label: string;
+//   prop: string;
+//   translation?: Translation;
+//   collapses: { label: string; prop: string; _t?: boolean }[];
+// }
+// export interface OverviewConfig {
+//   label: string;
+//   prop: string;
+//   src: string;
+// }
+// export interface TreeConfig {
+//   prefix: string;
+//   prop: string;
+//   suffix: string;
+//   children: {
+//     prefix: string;
+//     prop: string;
+//     suffix: string;
+//   }[];
+//   translation?: Record<string | number, string>;
+// }
 
-/** 看板的总配置 */
-export const BillboardConfig: {
-  DustStatus: {
-    title: TitleConfig;
-    table: TableConfig;
-  };
-  FileOverview: {
-    contents: OverviewConfig[];
-  };
-  FireStatus: {
-    title: TitleConfig;
-    lists: ListConfig[];
-  };
-  GasStauts: {
-    headers: HeaderConfig[];
-    table: TableConfig;
-  };
-  Summary: {
-    headers: HeaderConfig[];
-    table: TableConfig;
-  };
-  VentilationStauts: {
-    headers: HeaderConfig[];
-    tree: TreeConfig;
-  };
-} = {
-  DustStatus: {
-    title: {
-      text: '',
-      prop: '',
-      translation: {},
-    },
-    table: {
-      columns: [{ label: '', prop: '' }],
-      collapses: [{ label: '', prop: '' }],
-      translation: {},
-    },
-  },
-  FileOverview: {
-    content: [
-      { src: leftImg, text: '文档总数', prop: 'totalNum' },
-      { src: rightImg, text: '待审批数', prop: 'approvalNum' },
-    ],
-  },
-  FireStatus: {
-    title: {
-      text: '',
-      prop: '',
-      translation: {},
-    },
-    list: [
-      {
-        icon: '',
-        label: '',
-        prop: '',
-        type: '',
-        translation: {},
-        collapses: [{ label: '', prop: '' }],
-      },
-    ],
-  },
-  GasStatus: {
-    header: [
-      {
-        label: '',
-        prop: '',
-        translation: {},
-      },
-    ],
-    table: {
-      columns: [],
-      collapses: [],
-      translation: {},
-    },
-  },
-  Summary: {
-    header: [
-      {
-        label: '',
-        prop: '',
-        translation: {},
-      },
-    ],
-    table: {
-      columns: [],
-      translation: {},
-    },
-  },
-  VentilationStatus: {
-    header: [
-      {
-        label: '',
-        prop: '',
-        filte: '',
-        translation: {},
-      },
-    ],
-    tree: {
-      prefix: '',
-      prop: 'strname',
-      suffix: '',
-      children: [
-        {
-          prefix: '名称:',
-          prop: 'strinstallpos',
-          suffix: '',
-        },
-        {
-          prefix: '1号风机风量:',
-          prop: 'Fan1m3',
-          suffix: '(m³/min)',
-        },
-        {
-          prefix: '2号风机风量:',
-          prop: 'Fan2m3',
-          suffix: '(m³/min)',
-        },
-        {
-          prefix: '频率:',
-          prop: 'FanFreqHz',
-          suffix: 'Hz',
-        },
-        {
-          prefix: '三区阻力分布:',
-          prop: 'sqzlfb',
-          suffix: '',
-        },
-      ],
-    },
-  },
-};
+// /** 看板的总配置 */
+// export const BillboardConfig: {
+//   DustStatus: {
+//     title: TitleConfig;
+//     table: TableConfig;
+//   };
+//   FileOverview: {
+//     contents: OverviewConfig[];
+//   };
+//   FireStatus: {
+//     title: TitleConfig;
+//     lists: ListConfig[];
+//   };
+//   GasStauts: {
+//     headers: HeaderConfig[];
+//     table: TableConfig;
+//   };
+//   Summary: {
+//     headers: HeaderConfig[];
+//     table: TableConfig;
+//   };
+//   VentilationStauts: {
+//     headers: HeaderConfig[];
+//     tree: TreeConfig;
+//   };
+//   Warning: {
+//     contents: OverviewConfig[];
+//   };
+// } = {
+//   DustStatus: {
+//     title: {
+//       text: '',
+//       prop: '',
+//       translation: {},
+//     },
+//     table: {
+//       columns: [{ label: '', prop: '' }],
+//       collapses: [{ label: '', prop: '' }],
+//       translation: {},
+//     },
+//   },
+//   FileOverview: {
+//     content: [
+//       { src: leftImg, text: '文档总数', prop: 'totalNum' },
+//       { src: rightImg, text: '待审批数', prop: 'approvalNum' },
+//     ],
+//   },
+//   FireStatus: {
+//     title: {
+//       text: '',
+//       prop: '',
+//       translation: {},
+//     },
+//     list: [
+//       {
+//         icon: '',
+//         label: '',
+//         prop: '',
+//         type: '',
+//         translation: {},
+//         collapses: [{ label: '', prop: '' }],
+//       },
+//     ],
+//   },
+//   GasStatus: {
+//     header: [
+//       {
+//         label: '',
+//         prop: '',
+//         translation: {},
+//       },
+//     ],
+//     table: {
+//       columns: [],
+//       collapses: [],
+//       translation: {},
+//     },
+//   },
+//   Summary: {
+//     header: [
+//       {
+//         label: '',
+//         prop: '',
+//         translation: {},
+//       },
+//     ],
+//     table: {
+//       columns: [],
+//       translation: {},
+//     },
+//   },
+//   VentilationStatus: {
+//     header: [
+//       {
+//         label: '',
+//         prop: '',
+//         filte: '',
+//         translation: {},
+//       },
+//     ],
+//     tree: {
+//       prefix: '',
+//       prop: 'strname',
+//       suffix: '',
+//       children: [
+//         {
+//           prefix: '名称:',
+//           prop: 'strinstallpos',
+//           suffix: '',
+//         },
+//         {
+//           prefix: '1号风机风量:',
+//           prop: 'Fan1m3',
+//           suffix: '(m³/min)',
+//         },
+//         {
+//           prefix: '2号风机风量:',
+//           prop: 'Fan2m3',
+//           suffix: '(m³/min)',
+//         },
+//         {
+//           prefix: '频率:',
+//           prop: 'FanFreqHz',
+//           suffix: 'Hz',
+//         },
+//         {
+//           prefix: '三区阻力分布:',
+//           prop: 'sqzlfb',
+//           suffix: '',
+//         },
+//       ],
+//     },
+//   },
+//   Warning: {
+//     content: [
+//       { src: leftImg, text: '文档总数', prop: 'totalNum' },
+//       { src: rightImg, text: '待审批数', prop: 'approvalNum' },
+//     ],
+//   },
+// };
 
 // 基础的表格列配置,针对普通设备
 export const GAS_STATUS_COLUMN = [
@@ -426,6 +440,16 @@ export const SUMMARY_COLUMN = [
   },
 ];
 
+// 预警总览相关的内容配置项
+export const WARNING_CONFIG = [
+  { src: '', text: '监测总数', prop: 'total', prop2: 'total', id: 'warning_cfg_000' },
+  { src: SafetyIcon, text: '安全监测', prop: 'safety', prop2: 'safetyRisk', id: 'warning_cfg_005' },
+  { src: VentIcon, text: '通风', prop: 'vent', prop2: 'ventRisk', id: 'warning_cfg_004' },
+  { src: DustIcon, text: '粉尘', prop: 'dust', prop2: 'dustRisk', id: 'warning_cfg_003' },
+  { src: GasIcon, text: '瓦斯', prop: 'gas', prop2: 'gasRisk', id: 'warning_cfg_001' },
+  { src: FireIcon, text: '火灾', prop: 'fire', prop2: 'fireRisk', id: 'warning_cfg_002' },
+];
+
 export const DEFAULT_TEST_DATA = {
   dustInfo: {
     // 矿井粉尘风险信息
@@ -593,6 +617,20 @@ export const DEFAULT_TEST_DATA = {
       },
     },
   },
+  warningInfo: {
+    total: 5,
+    vent: 1,
+    ventRisk: '低风险',
+    gas: 1,
+    gasRisk: '低风险',
+    dust: 1,
+    dustRisk: '低风险',
+    fire: 1,
+    fireRisk: '低风险',
+    safety: 1,
+    safetyRisk: '低风险',
+    maxLevel: 5,
+  },
   orgname: '/',
   orgcode: '/',
   ip: 'localhost',

+ 141 - 0
src/views/vent/home/billboard/components/Warning.vue

@@ -0,0 +1,141 @@
+<!-- eslint-disable vue/multi-word-component-names -->
+<template>
+  <div class="warning">
+    <div class="warning-item" v-for="item in WARNING_CONFIG" :key="item.id" @click="$emit('click', item)">
+      <div class="img"> <img :src="item.src" alt="" /> </div>
+      <div class="text">{{ item.text }}</div>
+      <div class="extra">监测数量</div>
+      <div class="num" :class="`warning-level_${warnData.maxLevel}`">{{ warnData[item.prop] }}</div>
+      <div class="risk" :class="`warning-level_${warnData.maxLevel}`">{{ warnData[item.prop2] }}</div>
+    </div>
+  </div>
+</template>
+<script lang="ts" setup>
+  import { shallowRef, onMounted } from 'vue';
+  import { BillboardType, DEFAULT_TEST_DATA, WARNING_CONFIG } from '../billboard.data';
+  import _ from 'lodash-es';
+
+  const props = withDefaults(
+    defineProps<{
+      data?: BillboardType;
+    }>(),
+    {
+      data: () => DEFAULT_TEST_DATA,
+    }
+  );
+  defineEmits(['click']);
+
+  const warnData = shallowRef<BillboardType['warningInfo']>({
+    total: 5,
+    vent: 1,
+    ventRisk: '低风险',
+    gas: 1,
+    gasRisk: '低风险',
+    dust: 1,
+    dustRisk: '低风险',
+    fire: 1,
+    fireRisk: '低风险',
+    safety: 1,
+    safetyRisk: '低风险',
+    maxLevel: 5,
+  });
+
+  function fetchData() {
+    const info = props.data.warningInfo;
+    if (!info) return;
+    warnData.value = info;
+  }
+
+  onMounted(() => {
+    fetchData();
+  });
+</script>
+
+<style lang="less" scoped>
+  @import '@/design/vent/color.less';
+  @font-face {
+    font-family: 'douyuFont';
+    src: url(/@/assets/images/files/douyuFont.otf);
+  }
+
+  .warning {
+    height: 100%;
+    // display: flex;
+    // justify-content: space-evenly;
+    // align-items: center;
+    // flex-wrap: wrap;
+  }
+
+  .warning-item:first-of-type {
+    background-image: url(/@/assets/images/vent/home/select-bg.png);
+    background-size: auto 100%;
+    background-position: left center;
+    padding-left: 60px;
+
+    .text {
+      width: 100px;
+      text-align: left;
+    }
+    .risk {
+      display: none;
+    }
+    .extra {
+      display: none;
+    }
+    .num {
+      text-align: right;
+      flex-grow: 1;
+    }
+
+    // .warning-level_5 {
+    //   color: red;
+    // }
+    // .warning-level_4 {
+    //   color: orange;
+    // }
+    // .warning-level_3 {
+    //   color: yellow;
+    // }
+    // .warning-level_2 {
+    //   color: green;
+    // }
+  }
+  .warning-item {
+    display: flex;
+    align-items: center;
+    background-image: url(/@/assets/images/company/list-item-9.png);
+    background-size: auto 80%;
+    background-repeat: no-repeat;
+    background-position: right center;
+    height: 40px;
+    margin-top: 10px;
+
+    .text {
+      text-align: center;
+      width: 60px;
+    }
+    .extra {
+      text-align: center;
+      width: 100px;
+    }
+    .num {
+      text-align: center;
+      width: 100px;
+    }
+    .risk {
+      text-align: right;
+      width: 80px;
+    }
+  }
+
+  .num {
+    font-size: 20px;
+    font-family: douyuFont;
+    color: @vent-gas-primary-text;
+  }
+  .risk {
+    font-size: 20px;
+    font-family: douyuFont;
+    color: @vent-gas-primary-text;
+  }
+</style>

+ 2 - 0
src/views/vent/home/billboard/index.vue

@@ -57,6 +57,7 @@
   import VentilationStatus from './components/VentilationStatus.vue';
   import GasStatus from './components/GasStatus.vue';
   import Summary from './components/Summary.vue';
+  import Warning from './components/Warning.vue';
   import _ from 'lodash-es';
   import { useRouter } from 'vue-router';
   // import mapComponent from './components/3Dmap/index.vue';
@@ -77,6 +78,7 @@
     GasStatus,
     FireStatus,
     Summary,
+    Warning,
   };
 
   const mainTitle = '国能神东一通三防管控平台';

+ 7 - 0
src/views/vent/home/billboard/warn.vue

@@ -0,0 +1,7 @@
+<!-- eslint-disable vue/multi-word-component-names -->
+<template>
+  <Billboard billboard-type="Warning" />
+</template>
+<script lang="ts" setup>
+  import Billboard from './index.vue';
+</script>

+ 3 - 2
src/views/vent/home/configurable/components/ModuleBD.vue

@@ -91,8 +91,8 @@
   // }
 
   //下拉框选项切换
-  function selectHandler({ key }) {
-    selectedDeviceID.value = key;
+  function selectHandler(id) {
+    selectedDeviceID.value = id;
     emit('select', selectedDevice);
   }
 
@@ -110,6 +110,7 @@
     background-repeat: no-repeat;
     background-position: center top;
     background-size: 100% auto;
+    z-index: 2;
 
     .dane-title {
       display: flex;

+ 23 - 4
src/views/vent/home/configurable/components/detail/ComplexList.vue

@@ -136,14 +136,16 @@
   .list-item_B {
     // height: 155px;
     background-repeat: no-repeat;
-    background-size: 100% auto;
+    // background-size: 100% 100%;
+    // background-size: auto 100%;
+    background-size: 87% auto;
     background-position: center;
-    background-image: url(/@/assets/images/home-container/configurable/firehome/fiber-jc.png);
+    background-image: url(/@/assets/images/home-container/configurable/firehome/img-7.png);
     display: flex;
     align-items: center;
     justify-content: space-between;
     text-align: center;
-    padding-right: 50px;
+    padding: 0 10%;
     margin-top: 15px;
     height: 40px;
 
@@ -160,12 +162,29 @@
       align-items: center;
     }
     .list-item__title_B {
-      flex-basis: 24%;
+      width: 40px;
+      text-align: center;
+      // height: 30px;
+      // background-size: auto 80%;
+      // background-position: center;
+      // background-repeat: no-repeat;
     }
     .list-item__info {
       display: none;
     }
   }
+  // .list-item__title_B_O2 {
+  //   background-image: url(/@/assets/images/home-container/configurable/firehome/O₂.png);
+  // }
+  // .list-item__title_B_CH4 {
+  //   background-image: url(/@/assets/images/home-container/configurable/firehome/CH₄.png);
+  // }
+  // .list-item__title_B_CO {
+  //   background-image: url(/@/assets/images/home-container/configurable/firehome/CO.png);
+  // }
+  // .list-item__title_B_CO2 {
+  //   background-image: url(/@/assets/images/home-container/configurable/firehome/CO₂.png);
+  // }
 
   // .list-item__label {
   //   flex-basis: 55%;

+ 3 - 0
src/views/vent/home/configurable/components/detail/CustomGallery.vue

@@ -236,6 +236,9 @@
 
   // .gallery-item_center_F {
   // }
+  .gallery_F {
+    height: 150px;
+  }
   .gallery > .gallery-item_F {
     width: 120px;
     height: 60px;

+ 88 - 177
src/views/vent/home/configurable/configurable.data.ts

@@ -1349,127 +1349,72 @@ export const testConfigA: Config[] = [
 ];
 
 const BDdustMock = {
-  // 工作面风险监测
-  worksurface: {
-    risk: [
-      {
-        name: '低风险',
-        count: 3,
-      },
-      {
-        name: '一般风险',
-        count: 0,
-      },
-      {
-        name: '较大风险',
-        count: 0,
-      },
-      {
-        name: '重大风险',
-        count: 2,
-      },
-    ],
-    count: 5,
-    contents: [
-      {
-        risk: '低',
-        name: '81202综放工作面',
-        tmax: '30',
-      },
-      {
-        risk: '低',
-        name: '81205主运掘进面',
-        tmax: '30',
-      },
-      {
-        risk: '低',
-        name: '81202综放工作面',
-        tmax: '30',
-      },
+  allMineWarn: '低风险', //全矿井风险级别
+  dustManageInfo: {
+    //工作面风险监测
+    totalNum: '5', //工作面总数
+    dfxNum: '5', //工作面低风险数
+    ybNum: '5', //工作面一般风险数
+    jdNum: '5', //工作面较大风险数
+    zdNum: '5', //工作面重大风险
+    sysList: [
       {
-        risk: '低',
-        name: '81205主运掘进面',
-        tmax: '30',
+        sysNamme: '工作面名称1', //工作面名称
+        warnLevel: '低风险', //预警级别
+        maxVal: '1.88', //最高粉尘浓度
       },
       {
-        risk: '低',
-        name: '81202综放工作面',
-        tmax: '30',
+        sysNamme: '工作面名称2', //工作面名称
+        warnLevel: '低风险', //预警级别
+        maxVal: '1.88', //最高粉尘浓度
       },
     ],
   },
-  // 粉尘浓度
-  dust: [
+  dustDustGraph: [
+    //粉尘传感器曲线图(综放工作面粉尘浓度)
     {
-      name: '82101综放',
-      deviceID: '82101',
-      history: [
-        {
-          val: '40',
-        },
-        {
-          val: '30',
-        },
+      strinstallpos: '81202工作面', //安装位置
+      historyList: [
+        //历史数据
         {
-          val: '40',
+          dustval: '0.86', //粉尘浓度值
+          time: '2024-09-12 15:33:50', //时间
         },
         {
-          val: '50',
-        },
-        {
-          val: '20',
+          dustval: '0.96', //粉尘浓度值
+          time: '2024-09-12 15:34:50', //时间
         },
+      ],
+    },
+    {
+      strinstallpos: '81203工作面', //安装位置
+      historyList: [
+        //历史数据
         {
-          val: '30',
+          dustval: '0.86', //粉尘浓度值
+          time: '2024-09-12 15:33:50', //时间
         },
         {
-          val: '50',
+          dustval: '1.00', //粉尘浓度值
+          time: '2024-09-12 15:34:50', //时间
         },
       ],
     },
   ],
-  // 降尘装置
-  jczz: {
-    devicetotal: '10',
-    forgetotal: '10',
-    onlinetotal: '24',
-    offlinetotal: '0',
+  atomObj: {
+    //智能喷雾降尘装置
+    totalNum: '5', //喷雾设备总数
+    openNum: '5', //喷雾设备连接数
+    breakNum: '0', //喷雾设备断开数
+    atomOpenNum: '1', //喷雾设备开启数
   },
-  // 粉尘关联指标
-  glzb: [
+  dustRelArray: [
+    //粉尘关联指标
     {
-      pos: '81202综采工作面隅角',
-      temp: '20',
-      ws: '1.8',
-      status: '打开',
-    },
-    {
-      pos: '81202综采工作面隅角',
-      temp: '20',
-      ws: '1.8',
-      status: '打开',
-    },
-    {
-      pos: '81202综采工作面隅角',
-      temp: '20',
-      ws: '1.8',
-      status: '打开',
-    },
-    {
-      pos: '81202综采工作面隅角',
-      temp: '20',
-      ws: '1.8',
-      status: '打开',
-    },
-  ],
-  // 静态指标
-  statics: [
-    {
-      name: '10#煤层',
-      flameLength: '400',
-      min: '75',
-      con: '有爆炸性',
-      deviceID: '1',
+      strinstallpos: '81202工作面', //安装位置
+      temp: '23.3', //温度
+      windSpeed: '10.5', //风速
+      atomState: '打开', //喷雾状态
     },
   ],
 };
@@ -1501,31 +1446,31 @@ export const testConfigBDDust: Config[] = [
       gallery: [
         {
           type: 'F',
-          readFrom: 'worksurface',
+          readFrom: 'dustManageInfo',
           items: [
             {
               label: '',
-              value: '${count}',
+              value: '${totalNum}',
               color: 'blue',
             },
             {
-              label: '${risk[0].name}',
-              value: '${risk[0].count}',
+              label: '低风险',
+              value: '${dfxNum}',
               color: 'blue',
             },
             {
-              label: '${risk[1].name}',
-              value: '${risk[1].count}',
+              label: '一般风险',
+              value: '${ybNum}',
               color: 'blue',
             },
             {
-              label: '${risk[2].name}',
-              value: '${risk[2].count}',
+              label: '较大风险',
+              value: '${jdNum}',
               color: 'blue',
             },
             {
-              label: '${risk[3].name}',
-              value: '${risk[3].count}',
+              label: '重大风险',
+              value: '${zdNum}',
               color: 'blue',
             },
           ],
@@ -1537,71 +1482,37 @@ export const testConfigBDDust: Config[] = [
       complex_list: [
         {
           type: 'A',
-          readFrom: 'worksurface.contents',
+          readFrom: 'dustManageInfo.sysList',
           items: [
             {
-              title: '${[0].name}',
+              title: '${[0].sysNamme}',
               contents: [
                 {
                   label: '风险监测',
-                  value: '${[0].risk}',
+                  value: '${[0].warnLevel}',
                   color: 'blue',
                   info: '',
                 },
                 {
-                  label: '温度最大值',
-                  value: '${[0].tmax}',
+                  label: '最高粉尘浓度',
+                  value: '${[0].maxVal}',
                   color: 'blue',
                   info: '',
                 },
               ],
             },
             {
-              title: '${[1].name}',
+              title: '${[1].sysNamme}',
               contents: [
                 {
                   label: '风险监测',
-                  value: '${[1].risk}',
+                  value: '${[1].warnLevel}',
                   color: 'blue',
                   info: '',
                 },
                 {
-                  label: '温度最大值',
-                  value: '${[1].tmax}℃',
-                  color: 'blue',
-                  info: '',
-                },
-              ],
-            },
-            {
-              title: '${[2].name}',
-              contents: [
-                {
-                  label: '风险监测',
-                  value: '${[2].risk}',
-                  color: 'blue',
-                  info: '',
-                },
-                {
-                  label: '温度最大值',
-                  value: '${[2].tmax}℃',
-                  color: 'blue',
-                  info: '',
-                },
-              ],
-            },
-            {
-              title: '${[3].name}',
-              contents: [
-                {
-                  label: '风险监测',
-                  value: '${[3].risk}',
-                  color: 'blue',
-                  info: '',
-                },
-                {
-                  label: '温度最大值',
-                  value: '${[3].tmax}℃',
+                  label: '最高粉尘浓度',
+                  value: '${[1].maxVal}',
                   color: 'blue',
                   info: '',
                 },
@@ -1620,7 +1531,7 @@ export const testConfigBDDust: Config[] = [
     },
   },
   {
-    deviceType: 'dust',
+    deviceType: 'dustDustGraph',
     moduleName: '综放工作面粉尘浓度',
     pageType: '',
     moduleData: {
@@ -1629,7 +1540,7 @@ export const testConfigBDDust: Config[] = [
         showSelector: true,
         showSlot: false,
         selector: {
-          value: '${name}',
+          value: '${strinstallpos}',
         },
         slot: {
           value: '',
@@ -1645,7 +1556,7 @@ export const testConfigBDDust: Config[] = [
       chart: [
         {
           type: 'line_area',
-          readFrom: 'history',
+          readFrom: 'historyList',
           xAxis: [
             {
               label: 'null',
@@ -1659,8 +1570,8 @@ export const testConfigBDDust: Config[] = [
           ],
           series: [
             {
-              label: 'A',
-              prop: 'val',
+              label: '粉尘浓度',
+              prop: 'dustval',
             },
           ],
         },
@@ -1706,26 +1617,26 @@ export const testConfigBDDust: Config[] = [
       gallery: [
         {
           type: 'E',
-          readFrom: 'jczz',
+          readFrom: 'atomObj',
           items: [
             {
               label: '设备总数',
-              value: '${devicetotal}',
+              value: '${totalNum}',
               color: 'blue',
             },
             {
               label: '喷雾开启数',
-              value: '${forgetotal}',
+              value: '${atomOpenNum}',
               color: 'blue',
             },
             {
               label: '连网数量',
-              value: '${onlinetotal}',
+              value: '${openNum}',
               color: 'blue',
             },
             {
               label: '断网数量',
-              value: '${offlinetotal}',
+              value: '${breakNum}',
               color: 'blue',
             },
           ],
@@ -1773,11 +1684,11 @@ export const testConfigBDDust: Config[] = [
       table: [
         {
           type: 'C',
-          readFrom: 'glzb',
+          readFrom: 'dustRelArray',
           columns: [
             {
               name: '类别',
-              prop: 'pos',
+              prop: 'strinstallpos',
             },
             {
               name: '温度',
@@ -1785,11 +1696,11 @@ export const testConfigBDDust: Config[] = [
             },
             {
               name: '风速',
-              prop: 'ws',
+              prop: 'windSpeed',
             },
             {
               name: '状态',
-              prop: 'status',
+              prop: 'atomState',
             },
           ],
         },
@@ -1811,8 +1722,8 @@ export const testConfigBDDust: Config[] = [
     pageType: '',
     moduleData: {
       header: {
-        show: true,
-        showSelector: true,
+        show: false,
+        showSelector: false,
         showSlot: false,
         selector: {
           value: '${name}',
@@ -1835,15 +1746,15 @@ export const testConfigBDDust: Config[] = [
           items: [
             {
               label: '火焰长度',
-              value: '>${flameLength}mm',
+              value: '>400mm',
             },
             {
               label: '抑制煤层爆炸最低岩粉量',
-              value: '${min}%',
+              value: '75%',
             },
             {
               label: '鉴定结论',
-              value: '${con}',
+              value: '有煤层爆炸性',
             },
           ],
         },
@@ -1906,25 +1817,25 @@ const BDfireMock = {
   fiber: {
     contents: [
       {
-        name: '氧气',
+        name: 'O₂',
         max: '20',
         pos: '81202综采工作面隅角',
         time: '2024-08-13 12:00:00',
       },
       {
-        name: '一氧化碳',
+        name: 'CH₄',
         max: '20',
         pos: '81202综采工作面隅角',
         time: '2024-08-13 12:00:00',
       },
       {
-        name: '甲烷',
+        name: 'CO',
         max: '20',
         pos: '81202综采工作面隅角',
         time: '2024-08-13 12:00:00',
       },
       {
-        name: '二氧化碳',
+        name: 'CO₂',
         max: '20',
         pos: '81202综采工作面隅角',
         time: '2024-08-13 12:00:00',

+ 10 - 4
src/views/vent/home/configurable/dustBD.vue

@@ -220,7 +220,10 @@
     height: 115px;
     top: 30px;
     width: 450px;
-    background: url('/@/assets/images/home-container/configurable/firehome/qkjaq.png') no-repeat center;
+    background-image: url('/@/assets/images/home-container/configurable/firehome/qkjaq.png');
+    background-color: #000723;
+    background-repeat: no-repeat;
+    background-position: center;
     background-size: 100% 100%;
 
     .tcontent-area {
@@ -274,11 +277,14 @@
   }
   .right-t {
     position: absolute;
-    height: 200px;
+    height: 160px;
     right: 0;
-    margin-bottom: 10px;
+    top: 40px;
     width: 450px;
-    background: url('/@/assets/images/home-container/configurable/firehome/common-border2.png') no-repeat center;
+    background-image: url('/@/assets/images/home-container/configurable/firehome/common-border2.png');
+    background-color: #000723;
+    background-repeat: no-repeat;
+    background-position: center;
     background-size: 100% 100%;
     display: flex;
     align-items: center;

+ 8 - 2
src/views/vent/home/configurable/fireBD.vue

@@ -220,7 +220,10 @@
     height: 115px;
     top: 30px;
     width: 450px;
-    background: url('/@/assets/images/home-container/configurable/firehome/qkjaq.png') no-repeat center;
+    background-image: url('/@/assets/images/home-container/configurable/firehome/qkjaq.png');
+    background-color: #000723;
+    background-repeat: no-repeat;
+    background-position: center;
     background-size: 100% 100%;
 
     .tcontent-area {
@@ -278,7 +281,10 @@
     right: 0;
     top: 40px;
     width: 450px;
-    background: url('/@/assets/images/home-container/configurable/firehome/common-border2.png') no-repeat center;
+    background-image: url('/@/assets/images/home-container/configurable/firehome/common-border2.png');
+    background-color: #000723;
+    background-repeat: no-repeat;
+    background-position: center;
     background-size: 100% 100%;
     display: flex;
     align-items: center;

+ 14 - 9
src/views/vent/home/configurable/hooks/useInit.ts

@@ -65,7 +65,7 @@ export function useInitDevices(devicekind: string, config: Config['moduleData'])
   const selectedDevice = computed(() => {
     return (
       devices.value.find((e) => {
-        return e.deviceID === selectedDeviceID.value;
+        return e.id === selectedDeviceID.value;
       }) || {}
     );
   });
@@ -86,23 +86,28 @@ export function useInitDevices(devicekind: string, config: Config['moduleData'])
     return promise.then((result) => {
       if (header.show && header.showSelector && result[devicekind]) {
         // 如果配置里指明需要 header,检验后初始化设备信息
-        const records: { deviceID: string }[] = result[devicekind];
-        devices.value = records;
-        selectedDeviceID.value = records[0]?.deviceID;
-        options.value = records.map((e) => {
+        const records: Record<string, any>[] = result[devicekind];
+        devices.value = records.map((e, i) => {
+          return {
+            id: i,
+            ...e,
+          };
+        });
+        options.value = devices.value.map((e) => {
           return {
             label: getFormattedText(e, value),
-            value: e.deviceID,
+            value: e.id,
           };
         });
+        selectedDeviceID.value = options.value[0]?.value;
       } else {
         // 没有的话按默认的,将返回结果直接作为一整个设备信息供模块使用
         const record = {
           ...result,
-          deviceID: 'isthisthereallife',
+          id: '00000000',
         };
         devices.value = [record];
-        selectedDeviceID.value = record.deviceID;
+        selectedDeviceID.value = record.id;
       }
     });
   }
@@ -125,7 +130,7 @@ export function useInitScene(scenekind: string) {
     return getHomeData({}).then((result) => {
       if (!result[scenekind]) return;
       // 如果数据只有一条,转为数据
-      const records: { strinstallpos: string; deviceID: string }[] = result[scenekind];
+      const records: { strinstallpos: string; id: string }[] = result[scenekind];
       scene.value = records;
     });
   }

+ 18 - 12
src/views/vent/home/configurable/index.vue

@@ -23,7 +23,7 @@
         </div>
         <div class="tcontent-c">
           <div style="margin-bottom: 15px; color: #009bff; font-size: 24px; font-weight: bolder; letter-spacing: 10px">低风险</div>
-          <div style="color: #fff; font-size: 12px">自燃倾向性等级 : 容易自燃</div>
+          <!-- <div style="color: #fff; font-size: 12px">自燃倾向性等级 : 容易自燃</div> -->
         </div>
         <div class="tcontent-r">
           <div>火灾</div>
@@ -31,7 +31,7 @@
         </div>
       </div>
     </div>
-    <div class="right-t">
+    <!-- <div class="right-t">
       <div class="tcontent-l" @click="redirectTo('https://bing.cn')">
         <div>智能</div>
         <div>灌浆系统</div>
@@ -40,7 +40,7 @@
         <div>智能</div>
         <div>注氟系统</div>
       </div>
-    </div>
+    </div> -->
     <template v-if="isOriginal">
       <ModuleOriginal
         v-for="cfg in configs"
@@ -106,14 +106,14 @@
   import ModuleOriginal from './components/ModuleOriginal.vue';
   import ModuleCommon from './components/ModuleCommon.vue';
   import ModuleBD from './components/ModuleBD.vue';
-  import { testConfigBDFire } from './configurable.data';
+  import { testConfigBDDust } from './configurable.data';
   import VentModal from '/@/components/vent/micro/ventModal.vue';
 
   interface EnhancedConfig extends Config {
     visible: boolean;
   }
 
-  const mainTitle = ref('保德煤矿火灾预警系统');
+  const mainTitle = ref('保德煤矿粉尘灾害预警系统');
 
   // const moduleCodes = ['fanlocal', 'fanmain' /** 'vc', 'ar', 'va', 'ws', 'dw' */];
 
@@ -127,8 +127,8 @@
   onMounted(() => {
     // configs.value = testConfigB;
     fetchConfigs().then(() => {
-      configs.value = testConfigBDFire;
-      // configs.value.push(...testConfigBDFire);
+      configs.value = testConfigBDDust;
+      // configs.value.push(...testConfigBDDust);
       enhancedConfigs.value = configs.value.map((c) => {
         return {
           visible: true,
@@ -138,9 +138,9 @@
     });
   });
 
-  function redirectTo(url) {
-    window.open(url);
-  }
+  // function redirectTo(url) {
+  //   window.open(url);
+  // }
 </script>
 <style lang="less" scoped>
   @font-face {
@@ -220,7 +220,10 @@
     height: 115px;
     top: 30px;
     width: 450px;
-    background: url('/@/assets/images/home-container/configurable/firehome/qkjaq.png') no-repeat center;
+    background-image: url('/@/assets/images/home-container/configurable/firehome/qkjaq.png');
+    background-color: #000723;
+    background-repeat: no-repeat;
+    background-position: center;
     background-size: 100% 100%;
 
     .tcontent-area {
@@ -278,7 +281,10 @@
     right: 0;
     top: 40px;
     width: 450px;
-    background: url('/@/assets/images/home-container/configurable/firehome/common-border2.png') no-repeat center;
+    background-image: url('/@/assets/images/home-container/configurable/firehome/common-border2.png');
+    background-color: #000723;
+    background-repeat: no-repeat;
+    background-position: center;
     background-size: 100% 100%;
     display: flex;
     align-items: center;

+ 54 - 0
src/views/vent/monitorManager/fanLocalMonitor/components/fanlocal-echart-line.vue

@@ -0,0 +1,54 @@
+<template>
+    <div class="alarm-history">
+        <BarAndLine class="echarts-line" xAxisPropType="time" :dataSource="historyLists" height="90%" width="100%"
+            :chartsColumns="chartsColumn" :option="echatsOption" chartsType="listMonitor" />
+    </div>
+</template>
+<script setup lang="ts">
+import { onBeforeMount, ref, watch, onMounted, nextTick, defineAsyncComponent, reactive, onUnmounted, inject, unref } from 'vue';
+import BarAndLine from '../../../../../components/chart/BarAndLine.vue';
+import { echatsOption } from '../fanLocal.data';
+const props = defineProps({
+    devicekide: {
+        type: String,
+        default: '',
+    },
+    historyList: {
+        type: Array,
+        default: () => {
+            return []
+        }
+    },
+    chartsColumns: {
+        type: Array,
+        default: () => {
+            return []
+        }
+    }
+});
+let scroll = reactive({
+    y: 700,
+});
+let historyLists = ref<any[]>([])
+let chartsColumn = ref<any[]>([])
+
+watch(() => props.historyList, (newH, oldH) => {
+    historyLists.value = newH
+},
+    { immediate: true })
+watch(() => props.chartsColumns, (newC, oldC) => {
+    chartsColumn.value = newC
+}, {
+    immediate: true
+})
+
+
+</script>
+<style lang="less" scoped>
+.alarm-history {
+    width: 100%;
+    height: 730px;
+    position: fixed;
+    top: 100px;
+}
+</style>

+ 59 - 0
src/views/vent/monitorManager/fanLocalMonitor/components/fanlocal-history.vue

@@ -0,0 +1,59 @@
+<template>
+    <div class="alarm-history">
+        <template v-if="globalConfig.History_Type == 'remote'">
+                <HistoryTable
+                  :columns-type="`${selectDatas.deviceType}`"
+                  :device-type="`${devicekide}`"
+                  designScope="fanlocal-history"
+                  :scroll="scroll"
+                />
+              </template>
+              <template v-else>
+                <HistoryTable1 class="w-100% h-100%" :device-code="`${devicekide}`" :scroll="scroll" dict-code="fanlocal_dict" />
+              </template>
+    </div>
+</template>
+<script setup lang="ts">
+import { onBeforeMount, ref, watch, onMounted, nextTick, defineAsyncComponent, reactive, onUnmounted, inject, unref } from 'vue';
+import HistoryTable from '../../comment/HistoryTable.vue'
+import HistoryTable1 from '../../../../vent/comment/history/HistoryTable.vue'
+
+const props = defineProps({
+    selectData: {
+        type: Object,
+        default: () => {
+            return {}
+        }
+    },
+    devicekide:{
+        type:String,
+        default:'',
+    },
+    globalConfig:{
+        type:Object,
+        default:()=>{
+            return {}
+        },
+    }
+});
+
+let selectDatas = reactive({})
+let scroll = reactive({
+  y: 700,
+});
+
+watch(() => props.selectData, (newS, oldS) => {
+    selectDatas = Object.assign({}, newS)
+}, {
+    immediate: true,
+    deep: true
+})
+</script>
+<style lang="less" scoped>
+.alarm-history {
+    width: 100%;
+    height: 730px;
+    position: fixed;
+    top: 100px;
+}
+</style>

+ 36 - 0
src/views/vent/monitorManager/fanLocalMonitor/components/fanlocal-operate-history.vue

@@ -0,0 +1,36 @@
+<template>
+    <div class="alarm-history">
+        <HandlerHistoryTable
+                columns-type="operator_history"
+                :device-type="`${devicekide}`"
+                :device-list-api="baseList"
+                designScope="alarm-history"
+                :scroll="scroll"
+              />
+    </div>
+</template>
+<script setup lang="ts">
+import { onBeforeMount, ref, watch, onMounted, nextTick, defineAsyncComponent, reactive, onUnmounted, inject, unref } from 'vue';
+import HandlerHistoryTable from '../../comment/HandlerHistoryTable.vue';
+import { list as baseList } from '../../../deviceManager/fanTabel/fan.api';
+
+const props = defineProps({
+    devicekide:{
+        type:String,
+        default:'',
+    },
+});
+let scroll = reactive({
+  y: 700,
+});
+
+
+</script>
+<style lang="less" scoped>
+.alarm-history {
+    width: 100%;
+    height: 730px;
+    position: fixed;
+    top: 100px;
+}
+</style>

+ 29 - 0
src/views/vent/monitorManager/fanLocalMonitor/components/fanlocal-warn-history.vue

@@ -0,0 +1,29 @@
+<template>
+    <div class="alarm-history">
+        <AlarmHistoryTable columns-type="alarm" :device-type="`${devicekide}`" designScope="alarm-history" :scroll="scroll" />
+    </div>
+</template>
+<script setup lang="ts">
+import { onBeforeMount, ref, watch, onMounted, nextTick, defineAsyncComponent, reactive, onUnmounted, inject, unref } from 'vue';
+import AlarmHistoryTable from '../../comment/AlarmHistoryTable.vue';
+
+const props = defineProps({
+    devicekide:{
+        type:String,
+        default:'',
+    },
+});
+let scroll = reactive({
+  y: 700,
+});
+
+
+</script>
+<style lang="less" scoped>
+.alarm-history {
+    width: 100%;
+    height: 730px;
+    position: fixed;
+    top: 100px;
+}
+</style>

+ 27 - 0
src/views/vent/monitorManager/fanLocalMonitor/fanLocal.data.ts

@@ -3,6 +3,33 @@ import { FormSchema } from '/@/components/Table';
 import { rules } from '/@/utils/helper/validator';
 import { ref, reactive } from 'vue';
 import { cloneDeep } from 'lodash-es';
+export const navList = ref([
+  {
+    title: '实时监测',
+    pathName: 'fanLocal-ssjc',
+    isHover: false,
+  },
+  {
+    title: '历史监测记录',
+    pathName: 'fanLocal-history',
+    isHover: false,
+  },
+  {
+    title: '报警历史记录',
+    pathName: 'fanLocal-warn',
+    isHover: false,
+  },
+  {
+    title: '操作历史记录',
+    pathName: 'fanLocal-operate',
+    isHover: false,
+  },
+  {
+    title: '风量实时曲线',
+    pathName: 'fanLocal-wind',
+    isHover: false,
+  },
+]);
 export const columns: BasicColumn[] = [
   {
     title: '名称',

+ 1795 - 0
src/views/vent/monitorManager/fanLocalMonitor/index-copy.vue

@@ -0,0 +1,1795 @@
+<template>
+  <div class="bg" style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; overflow: hidden">
+    <a-spin :spinning="loading" />
+    <div id="fanLocal3D" style="width: 100%; height: 100%; position: absolute; overflow: hidden"> </div>
+    <div id="fanLocal3DCSS" class="threejs-Object-CSS" style="width: 100%; height: 100%; position: absolute; overflow: hidden; pointer-events: none">
+      <div style="z-index: -1; position: relative" v-if="hasPermission('show:sensorMonitor')">
+        <div class="elementTag" id="inputBox1">
+          <div class="elementContent" v-if="selectData.windSpeed1 || selectData.gas3 || selectData.windSpeed_merge">
+            <p v-if="selectData.windSpeed1 || selectData.windSpeed_merge"
+              >风筒入口风速:<span class="value">{{
+                selectData.windSpeed1 ? selectData.windSpeed1 : selectData.windSpeed_merge ? selectData.windSpeed_merge : '-'
+              }}</span>
+              <span class="unit"> m/s</span></p
+            >
+            <p v-if="selectData.windInputSpeed1 || selectData.windInputSpeed_merge"
+              >风筒入口风速:<span class="value">{{
+                selectData.windInputSpeed1 ? selectData.windInputSpeed1 : selectData.windInputSpeed_merge ? selectData.windInputSpeed_merge : '-'
+              }}</span>
+              <span class="unit"> m/s</span></p
+            >
+            <p v-if="selectData.windQuantity1 || selectData.inletAirVolume_merge"
+              >风筒入口风量:<span class="value">{{
+                selectData.windQuantity1 ? selectData.windQuantity1 : selectData.inletAirVolume_merge ? selectData.inletAirVolume_merge : '-'
+              }}</span>
+              <span class="unit"> m³/min</span></p
+            >
+            <p v-if="selectData.gas3"
+              >风筒入口瓦斯浓度: <span class="value">{{ selectData.gas3 ? selectData.gas3 : '-' }}</span> <span class="unit"> %</span></p
+            >
+          </div>
+        </div>
+        <div class="elementTag" id="outBox">
+          <div
+            class="elementContent elementContent-r"
+            v-if="
+              selectData.windQuantity2 ||
+              selectData.gas1 ||
+              (selectData.windOutSpeed1 && selectData.windOutSpeed_merge) ||
+              selectData.ductOutletAirVolume_merge
+            "
+          >
+            <p v-if="selectData.windQuantity2 || selectData.m3 || selectData.ductOutletAirVolume_merge || selectData.windOutSpeed_merge"
+              >迎头供风量:<span class="value">{{
+                selectData.windQuantity2
+                  ? selectData.windQuantity2
+                  : selectData.m3
+                  ? selectData.m3
+                  : selectData.ductOutletAirVolume_merge
+                  ? selectData.ductOutletAirVolume_merge
+                  : '-'
+              }}</span>
+              <span class="unit"> m³/min</span></p
+            >
+            <p v-if="selectData.gas1"
+              >迎头瓦斯浓度:<span class="value">{{ selectData.gas1 ? selectData.gas1 : '-' }}</span> <span class="unit"> %</span></p
+            >
+            <p v-if="selectData.windOutSpeed1 || selectData.windOutSpeed_merge"
+              >风筒出口风速<span class="value">{{
+                selectData.windOutSpeed1 ? selectData.windOutSpeed1 : selectData.windOutSpeed_merge ? selectData.windOutSpeed_merge : '-'
+              }}</span>
+              <span class="unit"> %</span></p
+            >
+          </div>
+        </div>
+        <div class="elementTag" id="returnBox">
+          <div class="elementContent elementContent-r" v-if="selectData.gas2">
+            <p v-if="selectData.gas2"
+              >回风流瓦斯浓度:<span class="value">{{ selectData.gas2 ? selectData.gas2 : '-' }}</span> <span class="unit"> %</span></p
+            >
+          </div>
+        </div>
+        <div class="elementTag" id="gateBox">
+          <div class="elementContent">
+            <p>风门状态:关</p>
+            <p>风门过风面积:{{ selectData.gas1 ? selectData.gas1 : '-' }}</p>
+          </div>
+        </div>
+        <div class="elementTag" id="windownBox">
+          <div class="elementContent" v-if="modalType == 'fc'">
+            <p style="pointer-events: auto"
+              ><a class="action-link" @click="goDetailDevice('window_fWindowM3')">风窗详情</a> <ArrowRightOutlined :style="{ color: '#157DC8' }"
+            /></p>
+            <p v-if="selectData.windSpeed"
+              >风窗风流风速:<span class="value">{{ selectData.windSpeed ? selectData.windSpeed : '-' }}</span> <span class="unit"> m/s</span></p
+            >
+            <p v-if="selectData.fWindowM3"
+              >风窗过风量:<span class="value">{{ selectData.fWindowM3 ? selectData.fWindowM3 : '-' }}</span> <span class="unit"> m³/min</span></p
+            >
+            <p v-if="selectData.OpenDegree"
+              >风窗开度值:<span class="value">{{ selectData.OpenDegree ? selectData.OpenDegree : '-' }}</span> <span class="unit"> %</span></p
+            >
+            <p v-if="selectData.OpenDegree"
+              >风窗过风面积:<span class="value">{{ selectData.forntArea ? selectData.forntArea : '-' }}</span> <span class="unit"> ㎡</span></p
+            >
+          </div>
+        </div>
+        <!-- <div class="elementTag" id="inputBox1">
+          <div class="elementContent" v-if="selectData.windInputSpeed1 || selectData.windInputSpeed_merge">
+            <p v-if="selectData.windInputSpeed1 || selectData.windInputSpeed_merge"
+              >风筒入口风速:<span class="value">{{
+                selectData.windInputSpeed1 ? selectData.windInputSpeed1 : selectData.windInputSpeed_merge ? selectData.windInputSpeed_merge : '-'
+              }}</span>
+              <span class="unit"> m/s</span></p
+            >
+          </div>
+        </div> -->
+      </div>
+    </div>
+  </div>
+
+  <div class="scene-box">
+    <div class="top-box" v-if="!loading">
+      <div class="top-center row">
+        <div class="vent-flex-row" id="fanLocalSelectDom" v-if="!globalConfig?.simulatedPassword && getDictItemsByCode('fanlocaltype')">
+          <span style="color: #00f5fe; margin-left: 5px">风机类型:</span>
+          <JDictSelectTag
+            style="width: 180px"
+            v-model:value="devicekide"
+            dictCode="fanlocaltype"
+            :showChooseOption="false"
+            :getPopupContainer="getPopupContainer"
+            @change="changeDeviceKind"
+          />
+        </div>
+        <!-- fanlocal_systeml_zj 模拟局部风机,不显示操作按钮 -->
+        <template v-for="(item, index) in modalTypeArr.leftBtnArr" :key="index">
+          <div
+            v-if="!(selectData.fanFrequencyType == 'fandp' && item.permission.startsWith('btn:frequency')) && hasPermission(item.permission)"
+            :class="{ 'button-box': btnClick, 'button-disable': !btnClick }"
+            @click="showModal(item)"
+            >{{ item.value }}</div
+          >
+        </template>
+      </div>
+      <div class="top-right row">
+        <template v-for="(item, index) in modalTypeArr.rightBtnArr" :key="index">
+          <div
+            v-if="
+              !(selectData.fanFrequencyType == 'fandp' && (item.permission === 'fanLocal:gasAlarmSet' || item.permission === 'fanLocal:kkjc')) &&
+              hasPermission(item.permission)
+            "
+            :class="{ 'button-box': btnClick, 'button-disable': !btnClick }"
+            @click="showModal(item)"
+            >{{ item.value }}</div
+          >
+        </template>
+      </div>
+    </div>
+    <div class="title-text">
+      {{ selectData.supplyAirAddr || selectData.strinstallpos || selectData.stationname }}
+    </div>
+    <div class="data-show-box" v-if="!loading">
+      <div class="data-item" v-if="leftColumns.length > 0">
+        <div class="item-header">设备监测</div>
+        <div class="item-container">
+          <div class="tab">
+            <div class="tab-item" :class="{ 'tab-item-active-r': warningMonitorRowIndex === 0 }" @click="selectDevice('warningMonitorRowIndex', 0)"
+              >主机</div
+            >
+            <div class="tab-item" :class="{ 'tab-item-active-r': warningMonitorRowIndex === 1 }" @click="selectDevice('warningMonitorRowIndex', 1)"
+              >备机</div
+            >
+          </div>
+          <div class="container-group">
+            <!-- <div class="warning-header">
+              <div class="header-item">
+                <div class="header-title">报警总数</div>
+                <div class="header-value">0</div>
+              </div>
+              <div class="header-item">
+                <div class="header-title">未处理数</div>
+                <div class="header-value">0</div>
+              </div>
+            </div> -->
+            <div class="warning-group">
+              <template v-if="selectData.deviceType">
+                <!-- <div class="warning-item" v-for="(state, index) in leftColumns" :key="index">
+                <div class="item-name"><div class="icon"></div> {{ state.title }}</div>
+                <div v-if="state.dataIndex.startsWith('Fan')">
+                  <div class="signal-item" v-if="warningMonitorRowIndex == 0">
+                    <div
+                      class="signal-round"
+                      :class="{
+                        'signal-round-run': selectData[state.dataIndex.replace('Fan', 'Fan1')],
+                        'signal-round-warning':
+                          selectData[state.dataIndex.replace('Fan', 'Fan1')] !== undefined && !selectData[state.dataIndex.replace('Fan', 'Fan1')],
+                        'signal-round-gry': selectData[state.dataIndex.replace('Fan', 'Fan1')] === undefined,
+                      }"
+                    ></div>
+                    <div class="vent-margin-l-8">{{
+                      selectData[state.dataIndex.replace('Fan', 'Fan1')] === undefined
+                      ? '无状态'
+                      : selectData[state.dataIndex.replace('Fan', 'Fan1')]
+                        ? '正常'
+                        : '异常'
+                    }}</div>
+                  </div>
+                  <div class="signal-item" v-if="warningMonitorRowIndex == 1">
+                    <div
+                      class="signal-round"
+                      :class="{
+                        'signal-round-run': selectData[state.dataIndex.replace('Fan', 'Fan2')],
+                        'signal-round-warning':
+                          selectData[state.dataIndex.replace('Fan', 'Fan2')] !== undefined && !selectData[state.dataIndex.replace('Fan', 'Fan2')],
+                        'signal-round-gry': selectData[state.dataIndex.replace('Fan', 'Fan2')] === undefined,
+                      }"
+                    ></div>
+                    <div class="vent-margin-l-8">{{
+                      selectData[state.dataIndex.replace('Fan', 'Fan2')] === undefined
+                      ? '无状态'
+                      : selectData[state.dataIndex.replace('Fan', 'Fan2')]
+                        ? '正常'
+                        : '异常'
+                    }}</div>
+                  </div>
+                </div>
+                <div v-else>
+                  <div class="signal-item">
+                    <div
+                      class="signal-round vent-margin-l-8"
+                      :class="{
+                              'signal-round-run': selectData[state.dataIndex],
+                              'signal-round-warning': selectData[state.dataIndex] !== undefined && !selectData[state.dataIndex],
+                              'signal-round-gry': selectData[state.dataIndex] === undefined,
+                            }"
+                    ></div>
+                    <div class="vent-margin-l-8">{{ selectData[state.dataIndex] === undefined ? '无状态' : selectData[state.dataIndex] ? '正常' : '异常' }}</div>
+                  </div>
+                </div>
+              </div> -->
+                <div class="container-item" v-for="(data, index) in leftColumns" :key="index">
+                  <div class="item-icon">
+                    <!-- <SvgIcon class="icon-style" size="18" name="temperature" /> -->
+                    <CaretRightOutlined class="icon-style" />
+                  </div>
+                  <div class="item-name">{{ data.title }}</div>
+                  <div v-if="data.dataIndex.startsWith('Fan')">
+                    <div class="item-value" v-if="warningMonitorRowIndex == 0">{{
+                      selectData[data.dataIndex.replace('Fan', 'Fan1')] ? selectData[data.dataIndex.replace('Fan', 'Fan1')] : '-'
+                    }}</div>
+                    <div class="item-value" v-if="warningMonitorRowIndex == 1">{{
+                      selectData[data.dataIndex.replace('Fan', 'Fan2')] ? selectData[data.dataIndex.replace('Fan', 'Fan2')] : '-'
+                    }}</div>
+                  </div>
+                  <div v-else>
+                    <div class="item-value">{{ selectData[data.dataIndex] ? selectData[data.dataIndex] : '-' }}</div>
+                  </div>
+                </div>
+              </template>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div>
+        <div class="data-item" v-if="rightColumns.length > 0">
+          <div class="item-header">环境监测/设备报警</div>
+          <div class="item-container">
+            <div class="tab">
+              <div class="tab-item" :class="{ 'tab-item-active-r': dataMonitorRowIndex == 0 }" @click="selectDevice('dataMonitorRowIndex', 0)"
+                >主机</div
+              >
+              <div class="tab-item" :class="{ 'tab-item-active-r': dataMonitorRowIndex == 1 }" @click="selectDevice('dataMonitorRowIndex', 1)"
+                >备机</div
+              >
+            </div>
+            <div class="container-group container-group-l">
+              <div class="warning-group" style="max-height: 200px; overflow-y: auto">
+                <template v-if="deviceType">
+                  <div v-for="(state, index) in rightColumns" :key="index">
+                    <template v-if="!state.dataIndex.endsWith('_w')">
+                      <div class="container-item">
+                        <div class="item-icon">
+                          <CaretRightOutlined class="icon-style" />
+                        </div>
+                        <div class="item-name">{{ state.title }}</div>
+                        <div v-if="state.dataIndex.startsWith('Fan')">
+                          <div class="item-value" v-if="dataMonitorRowIndex == 0">{{
+                            selectData[state.dataIndex.replace('Fan', 'Fan1')] ? selectData[state.dataIndex.replace('Fan', 'Fan1')] : '-'
+                          }}</div>
+                          <div class="item-value" v-if="dataMonitorRowIndex == 1">{{
+                            selectData[state.dataIndex.replace('Fan', 'Fan2')] ? selectData[state.dataIndex.replace('Fan', 'Fan2')] : '-'
+                          }}</div>
+                        </div>
+                        <div v-else>
+                          <div class="item-value">{{ selectData[state.dataIndex] ? selectData[state.dataIndex] : '-' }}</div>
+                        </div>
+                      </div>
+                    </template>
+                  </div>
+                </template>
+              </div>
+              <div class="warning-group" style="max-height: 200px; overflow-y: auto">
+                <div class="warning-header">
+                  <div class="header-item">
+                    <div class="header-title">报警数量</div>
+                    <div class="header-value">{{ selectData['warnLogNotOkCount'] }} </div>
+                  </div>
+                </div>
+                <template v-if="deviceType">
+                  <div v-for="(state, index) in leftColumns" :key="index">
+                    <template v-if="state.dataIndex.endsWith('_w')">
+                      <div class="warning-item">
+                        <div class="item-name"> <div class="icon"></div> {{ state.title }} </div>
+                        <div v-if="state.dataIndex.startsWith('Fan')">
+                          <div class="signal-item" v-if="warningMonitorRowIndex == 0">
+                            <div
+                              class="signal-round"
+                              :class="{
+                                'signal-round-run': selectData[state.dataIndex.replace('Fan', 'Fan1')] == '0',
+                                'signal-round-warning':
+                                  selectData[state.dataIndex.replace('Fan', 'Fan1')] !== undefined &&
+                                  selectData[state.dataIndex.replace('Fan', 'Fan1')] == '1',
+                                'signal-round-gry': selectData[state.dataIndex.replace('Fan', 'Fan1')] === undefined,
+                              }"
+                            ></div>
+                            <div class="vent-margin-l-8">{{
+                              selectData[state.dataIndex.replace('Fan', 'Fan1')] === undefined
+                                ? '无状态'
+                                : selectData[state.dataIndex.replace('Fan', 'Fan1')] == '0'
+                                ? '正常'
+                                : '异常'
+                            }}</div>
+                          </div>
+                          <div class="signal-item" v-if="warningMonitorRowIndex == 1">
+                            <div
+                              class="signal-round"
+                              :class="{
+                                'signal-round-run': selectData[state.dataIndex.replace('Fan', 'Fan2')] == '0',
+                                'signal-round-warning':
+                                  selectData[state.dataIndex.replace('Fan', 'Fan2')] != undefined &&
+                                  selectData[state.dataIndex.replace('Fan', 'Fan2')] == '1',
+                                'signal-round-gry': selectData[state.dataIndex.replace('Fan', 'Fan2')] == undefined,
+                              }"
+                            ></div>
+                            <div class="vent-margin-l-8">{{
+                              selectData[state.dataIndex.replace('Fan', 'Fan2')] == undefined
+                                ? '无状态'
+                                : selectData[state.dataIndex.replace('Fan', 'Fan2')] == '0'
+                                ? '正常'
+                                : '异常'
+                            }}</div>
+                          </div>
+                        </div>
+                        <div v-else>
+                          <div class="signal-item">
+                            <div
+                              class="signal-round vent-margin-l-8"
+                              :class="{
+                                'signal-round-run': selectData[state.dataIndex] == '0',
+                                'signal-round-warning': selectData[state.dataIndex] !== undefined && selectData[state.dataIndex] == '1',
+                                'signal-round-gry': selectData[state.dataIndex] === undefined,
+                              }"
+                            ></div>
+                            <div class="vent-margin-l-8">{{
+                              selectData[state.dataIndex] === undefined ? '无状态' : selectData[state.dataIndex] == '0' ? '正常' : '异常'
+                            }}</div>
+                          </div>
+                        </div>
+                      </div>
+                    </template>
+                  </div>
+                </template>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="bottom-tabs-box" @mousedown="setDivHeight($event, 170, scroll, 180)">
+      <dv-border-box8 :dur="5" class="dv_border_8" :style="`bottom: 20px; padding: 5px; height: ${scroll.y + 140}px`">
+        <!-- <div class="enter-detail" @click="goDetail()">
+          <send-outlined class=""/>风机运行详情
+        </div> -->
+        <a-tabs class="tabs-box" v-model:activeKey="activeKey" @change="tabChange">
+          <a-tab-pane key="1" tab="实时监测">
+            <GroupMonitorTable
+              v-if="activeKey === '1'"
+              ref="MonitorDataTable"
+              :dataSource="dataSource"
+              :columnsType="`${selectData.deviceType}_monitor`"
+              @selectRow="getSelectRow"
+              :scroll="scroll"
+              :is-action="true"
+            >
+              <template #action="{ record }">
+                <a v-if="globalConfig?.showReport" class="table-action-link" @click="deviceEdit($event, 'reportInfo', record)">报表录入</a>
+                <a class="table-action-link" @click="deviceEdit($event, 'deviceInfo', record)">设备编辑</a>
+              </template>
+            </GroupMonitorTable>
+          </a-tab-pane>
+          <a-tab-pane key="3" tab="历史数据">
+            <div class="tab-item" v-if="activeKey === '3'">
+              <template v-if="globalConfig.History_Type == 'remote'">
+                <HistoryTable
+                  :columns-type="`${selectData.deviceType}`"
+                  :device-type="`${devicekide}`"
+                  designScope="fanlocal-history"
+                  :scroll="scroll"
+                />
+              </template>
+              <template v-else>
+                <HistoryTable class="w-100% h-100%" :device-code="`${devicekide}`" :scroll="scroll" dict-code="fanlocal_dict" />
+              </template>
+            </div>
+          </a-tab-pane>
+          <a-tab-pane key="4" tab="报警历史">
+            <div class="tab-item" v-if="activeKey === '4'">
+              <AlarmHistoryTable columns-type="alarm" :device-type="`${devicekide}`" designScope="alarm-history" :scroll="scroll" />
+            </div>
+          </a-tab-pane>
+          <a-tab-pane key="5" tab="操作历史">
+            <div class="tab-item" v-if="activeKey === '5'">
+              <HandlerHistoryTable
+                columns-type="operator_history"
+                :device-type="`${devicekide}`"
+                :device-list-api="baseList"
+                designScope="alarm-history"
+                :scroll="scroll"
+              />
+            </div>
+          </a-tab-pane>
+          <a-tab-pane key="2" tab="风量实时曲线图" force-render v-if="hasPermission('echart:show')">
+            <!-- <a-tab-pane key="2" tab="风量实时曲线图" force-render> -->
+            <div class="tab-item" v-if="activeKey === '2'">
+              <!-- <div class="vent-flex-row-between" style="height: 100%">
+                <BarSingle
+                  :xAxisData="xAxisDataGas"
+                  :dataSource="dataSource[selectRowIndex]"
+                  height="100%"
+                  :chartsColumns="chartsColumns"
+                  style="flex: 3"
+                />
+                <BarSingle
+                  v-if="globalConfig?.simulatedPassword"
+                  :xAxisData="[
+                    { key: 'F1', valueKey: 'windQuantity1' },
+                    { key: 'F2', valueKey: 'windQuantity2' },
+                  ]"
+                  :dataSource="dataSource[selectRowIndex]"
+                  height="100%"
+                  :chartsColumns="chartsColumns1"
+                  style="flex: 2"
+                />
+              </div> -->
+              <div class="vent-flex-row-between" style="height: 100%">
+                <BarAndLine
+                  class="echarts-line"
+                  xAxisPropType="time"
+                  :dataSource="historyList"
+                  height="90%"
+                  width="100%"
+                  :chartsColumns="chartsColumns"
+                  :option="echatsOption"
+                  chartsType="listMonitor"
+                />
+              </div>
+            </div>
+          </a-tab-pane>
+        </a-tabs>
+        <a-button
+          v-if="hasPermission('btn:reportDown')"
+          type="primary"
+          size="small"
+          preIcon="ant-design:download-outlined"
+          style="position: absolute; right: 15px; top: 10px"
+          @click="reportDown"
+        >
+          报表导出
+        </a-button>
+      </dv-border-box8>
+    </div>
+  </div>
+  <div
+    ref="playerRef"
+    :class="{ 'to-right': rightColumns.length < 1 || leftColumns.length < 1, 'to-no-right': rightColumns.length > 0 && leftColumns.length > 0 }"
+    style="z-index: 999; position: absolute; top: 100px; right: 15px; width: 100%; height: 100%; margin: auto; pointer-events: none"
+  >
+  </div>
+  <a-modal v-model:visible="modalIsShow" :title="modalTitle" :maskStyle="{ backgroundColor: '#000000aa', backdropFilter: 'blur(3px)' }">
+    <template #footer>
+      <div v-if="controlType != 'startFan'">
+        <a-button key="back" @click="cancel">返回</a-button>
+        <a-button key="submit" type="primary" :loading="loading" @click="handleOk">确定</a-button>
+      </div>
+    </template>
+    <div class="modal-container">
+      <div class="vent-flex-row">
+        <ExclamationCircleFilled style="color: #ffb700; font-size: 30px" />
+        <div class="warning-text">您是否要进行{{ modalTitle }}操作?</div>
+      </div>
+      <div class="" v-if="controlType == 'startSmoke'">
+        <!-- 互斥控制 -->
+        <div class="startSmoke-select">
+          <div class="label">主机:</div>
+          <a-radio-group v-model:value="mainWindIsShow1" @change="changeMotor" name="localWind1">
+            <a-radio value="open">开启</a-radio>
+            <a-radio value="stop">停止</a-radio>
+          </a-radio-group>
+        </div>
+        <div class="startSmoke-select">
+          <div class="label">备机:</div>
+          <a-radio-group v-model:value="mainWindIsShow2" @change="changeMotor" name="localWind2">
+            <a-radio value="open">开启</a-radio>
+            <a-radio value="stop">停止</a-radio>
+          </a-radio-group>
+        </div>
+      </div>
+      <div class="" v-if="controlType == 'startFan'">
+        <!-- 不互斥控制 -->
+        <div class="startSmoke-select">
+          <div class="label">主机:</div>
+          <div :class="{ 'button-box': true, 'button-disable': false }" @click="handleOk('Fan1Open')">开启</div>
+          <div :class="{ 'button-box': true, 'button-disable': false }" @click="handleOk('Fan1Stop')">停止</div>
+          <div :class="{ 'button-box': true, 'button-disable': false }" @click="handleOk('Fan1Reset')">复位</div>
+        </div>
+        <div class="startSmoke-select">
+          <div class="label">备机:</div>
+          <div :class="{ 'button-box': true, 'button-disable': false }" @click="handleOk('Fan2Open')">开启</div>
+          <div :class="{ 'button-box': true, 'button-disable': false }" @click="handleOk('Fan2Stop')">停止</div>
+          <div :class="{ 'button-box': true, 'button-disable': false }" @click="handleOk('Fan2Reset')">复位</div>
+        </div>
+      </div>
+      <!-- 调频 -->
+      <div class="vent-flex-row input-box" v-if="controlType == 'Fan1Frequency'">
+        <div class="label">主风机运行频率(Hz):</div>
+        <a-input-number size="small" v-model:value="fan1FrequencyVal" :min="20" :max="50" :step="0.1" />
+      </div>
+      <div class="vent-flex-row input-box" v-if="controlType == 'Fan2Frequency'">
+        <div class="label">备风机运行频率(Hz):</div>
+        <a-input-number size="small" v-model:value="fan2FrequencyVal" :min="20" :max="50" :step="0.1" />
+      </div>
+      <div class="vent-flex-row input-box" v-if="controlType == 'FanFrequency'">
+        <div class="label">风机运行频率(Hz):</div>
+        <a-input-number size="small" v-model:value="fan1FrequencyVal" :min="20" :max="50" :step="0.1" />
+      </div>
+
+      <div class="vent-flex-row input-box" v-if="controlType == 'disAirAlarm'">
+        <div class="label">漏风率(%):</div>
+        <a-input-number size="small" v-model:value="frequencyVal" :min="0" :max="50" :step="0.1" />
+      </div>
+      <div class="vent-flex-row input-box" v-if="controlType == 'diameter'">
+        <div class="label">风筒直径(m):</div>
+        <a-input-number size="small" v-model:value="frequencyVal" :min="0" :max="50" :step="0.1" />
+      </div>
+      <div class="vent-flex-row input-box" v-if="controlType == 'len'">
+        <div class="label">风筒长度(m):</div>
+        <a-input-number size="small" v-model:value="frequencyVal" :min="0" :max="50" :step="0.1" />
+      </div>
+      <div class="vent-flex-row input-box" v-if="controlType == 'windPowerLimit'">
+        <div class="label">风电闭锁限值(m³/min):</div>
+        <a-input-number size="small" v-model:value="frequencyVal" :min="0" :max="50" :step="0.1" />
+      </div>
+      <div class="vent-flex-row input-box" v-if="controlType == 'gasPowerLimit'">
+        <div class="label">瓦斯电闭锁限值(m³/min):</div>
+        <a-input-number size="small" v-model:value="frequencyVal" :min="0" :max="50" :step="0.1" />
+      </div>
+      <div v-if="controlType == 'gasAlarmSet'">
+        <div class="vent-flex-row input-box">
+          <div class="label">设置瓦斯超限浓度:</div>
+          <a-input-number size="small" v-model:value="gasWarningVal" :min="0" :max="1" :step="0.01" />
+        </div>
+      </div>
+      <div v-if="controlType == 'gasAlarm'">
+        <div class="vent-flex-row input-box">
+          <div class="label">传感器名称:</div>
+          <a-select placeholder="传感器" @change="handleChangeSensor" :options="sensorList" v-model:value="modalSensor" />
+        </div>
+        <div class="vent-flex-row input-box">
+          <div class="label">传感器值:</div>
+          <a-input-number size="small" v-model:value="frequencyVal" :min="0" :max="50" :step="0.1" />
+        </div>
+      </div>
+      <div v-if="controlType == 'airVolumeAlarm'">
+        <div class="vent-flex-row input-box">
+          <div class="label">风量上限(m³/min):</div>
+          <a-input-number size="small" v-model:value="modalTypeArr.rightBtnArr[3].min" :min="0" :max="50" :step="0.1" />
+        </div>
+        <div class="vent-flex-row input-box">
+          <div class="label">风量下限(m³/min):</div>
+          <a-input-number size="small" v-model:value="modalTypeArr.rightBtnArr[3].max" :min="0" :max="50" :step="0.1" />
+        </div>
+      </div>
+      <div class="vent-flex-row input-box" v-if="controlType == 'zhlk'">
+        <div class="label">目标风量(m³/min):</div>
+        <a-input-number size="small" v-model:value="targetVolume" />
+      </div>
+      <div v-if="controlType == 'gasOverSet'">
+        <div class="vent-flex-row input-box">
+          <div class="label">设置瓦斯超限浓度:</div>
+          <a-input-number size="small" v-model:value="gasWarningVal" :min="0" :max="1" :step="0.01" />
+        </div>
+      </div>
+      <!-- 启动或停止 -->
+      <div class="" v-if="controlType == 'startSmoke'"> </div>
+      <div v-if="!globalConfig?.simulatedPassword" class="vent-flex-row input-box">
+        <div class="label">操作密码:</div>
+        <a-input size="small" type="password" v-model:value="passWord" />
+      </div>
+    </div>
+  </a-modal>
+  <ConditionAssistance @register="registerModalAssistance" :dataSource="historySource" />
+  <DeviceBaseInfo @register="registerModal" :device-type="selectData['deviceType']" />
+  <reportInfo @register="registerModal1" :editID="editID" :fileType="fileType" />
+</template>
+
+<script setup lang="ts">
+  import { ExclamationCircleFilled, ArrowRightOutlined } from '@ant-design/icons-vue';
+  import { onBeforeMount, ref, watch, onMounted, nextTick, defineAsyncComponent, reactive, onUnmounted, inject, unref } from 'vue';
+  // import BarSingle from '../../../../components/chart/BarSingle.vue';
+  import BarAndLine from '../../../../components/chart/BarAndLine.vue';
+  import GroupMonitorTable from '../comment/GroupMonitorTable.vue';
+  import AlarmHistoryTable from '../comment/AlarmHistoryTable.vue';
+  import HandlerHistoryTable from '../comment/HandlerHistoryTable.vue';
+  import DeviceBaseInfo from '../comment/components/DeviceBaseInfo.vue';
+  import { mountedThree, setModelType, destroy, addCssText, addText, playSmoke } from './fanLocal.three';
+  import lodash from 'lodash';
+  import { getTableList, list, autoAdjust } from '/@/views/vent/monitorManager/fanLocalMonitor/fanLocal.api';
+  import { list as baseList } from '../../deviceManager/fanTabel/fan.api';
+  import { chartsColumns1, echatsOption } from './fanLocal.data';
+  import { deviceControlApi } from '/@/api/vent/index';
+  import { setDivHeight } from '/@/utils/event';
+  import { BorderBox8 as DvBorderBox8 } from '@kjgl77/datav-vue3';
+  import { getTableHeaderColumns } from '/@/hooks/web/useWebColumns';
+  import { useRouter } from 'vue-router';
+  import { useModal } from '/@/components/Modal';
+  import type { BasicColumn } from '/@/components/Table/src/types/table';
+  import JDictSelectTag from '/@/components/Form/src/jeecg/components/JDictSelectTag.vue';
+  import { getPopupContainer } from '/@/utils';
+  import { getDictItemsByCode } from '/@/utils/dict';
+  import { message } from 'ant-design-vue';
+  import { useCamera } from '/@/hooks/system/useCamera';
+  import { CaretRightOutlined } from '@ant-design/icons-vue';
+  import ConditionAssistance from './components/conditionAssistance.vue';
+  import reportInfo from '../comment/components/reportInfo.vue';
+  import { save, reportList } from '../../reportManager/reportManager.api';
+  import { usePermission } from '/@/hooks/web/usePermission';
+  import { useGlobSetting } from '/@/hooks/setting';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  const globalConfig = inject('globalConfig');
+  const HistoryTable =
+    globalConfig.History_Type == 'remote'
+      ? defineAsyncComponent(() => import('../comment/HistoryTable.vue'))
+      : defineAsyncComponent(() => import('../../../vent/comment/history/HistoryTable.vue'));
+  const { hasPermission } = usePermission();
+
+  const [registerModal, { openModal, closeModal }] = useModal();
+  const [registerModal1, { openModal: openModal1, closeModal: closeModal1 }] = useModal();
+  const [registerModalAssistance, { openModal: openAssistance, closeModal: closeAssistance }] = useModal();
+  const { currentRoute } = useRouter();
+  const router = useRouter();
+  const { createConfirm } = useMessage();
+  const globSetting = useGlobSetting();
+
+  const modalTypeArr = reactive({
+    leftBtnArr: [
+      {
+        key: 'startSmoke',
+        value: '启停风机',
+        permission: 'btn:openclose',
+      },
+      {
+        key: 'startFan',
+        value: '启停风机',
+        permission: 'btn:openclose1',
+      },
+      {
+        key: 'changeSmoke', // 主备两个点位
+        value: '一键倒机',
+        permission: 'btn:change',
+      },
+      {
+        key: 'changeFan', // 主备一个点位
+        value: '一键倒机',
+        permission: 'btn:CtrlFanChange',
+      },
+      {
+        key: 'fan1ToFan2',
+        value: '主机倒备机',
+        permission: 'btn:ctrlFan1ToFan2',
+      },
+      {
+        key: 'fan2ToFan1',
+        value: '备机倒主机',
+        permission: 'btn:ctrlFan2ToFan1',
+      },
+      {
+        key: 'Fan1Frequency',
+        value: '主机调频',
+        permission: 'btn:frequency',
+      },
+      {
+        key: 'Fan2Frequency',
+        value: '备机调频',
+        permission: 'btn:frequency',
+      },
+      {
+        key: 'FanFrequency',
+        value: '风机调频',
+        permission: 'btn:frequencyMerge',
+      },
+      {
+        key: 'windPower',
+        value: '风电闭锁',
+        permission: 'fanLocal:fdbs',
+      },
+      {
+        key: 'gasPower',
+        value: '瓦斯电闭锁',
+        permission: 'fanLocal:wsdbs',
+      },
+      {
+        key: 'needAir',
+        value: '需风量',
+        permission: 'fanLocal:control',
+      },
+    ],
+    rightBtnArr: [
+      {
+        key: 'gasAlarmSet',
+        value: '瓦斯限值设定',
+        permission: 'fanLocal:gasAlarmSet',
+      },
+      {
+        key: 'gasOverSet', //
+        value: '瓦斯限值设定',
+        permission: 'fanLocal:gasOverSet',
+      },
+      {
+        key: 'kkjc',
+        value: '工况辅助决策',
+        permission: 'fanLocal:kkjc',
+      },
+      {
+        key: 'zhlk',
+        value: '自主联控',
+        permission: 'fanLocal:zhlk',
+      },
+      {
+        key: 'diameter',
+        value: '风筒直径',
+        permission: 'fanLocal:control',
+      },
+      {
+        key: 'diameter',
+        value: '风筒直径',
+        permission: 'fanLocal:control',
+      },
+      {
+        key: 'len',
+        value: '风筒长度',
+        permission: 'fanLocal:control',
+      },
+      // {
+      //   key: 'frequency',
+      //   value: '调频',
+      //   permission: 'fanLocal:control',
+      // },
+      {
+        key: 'windPowerLimit',
+        value: '风电闭锁限值',
+        permission: 'fanLocal:control',
+      },
+      {
+        key: 'gasPowerLimit',
+        value: '瓦斯电闭锁限值',
+        permission: 'fanLocal:control',
+      },
+      {
+        key: 'airVolumeAlarm',
+        value: '风量报警',
+        permission: 'fanLocal:control',
+        min: 0,
+        max: 100,
+      },
+      {
+        key: 'disAirAlarm',
+        value: '漏风率报警',
+        permission: 'fanLocal:control',
+      },
+      // {
+      //   key: 'gasAlarm',
+      //   value: '瓦斯报警',
+      //   permission: 'fanLocal:control',
+      // },
+    ],
+  });
+  const sensorList = ref<any[]>([
+    {
+      value: '1',
+      label: 'T1',
+    },
+    {
+      value: '2',
+      label: 'T2',
+    },
+    {
+      value: '3',
+      label: 'T3',
+    },
+  ]);
+
+  const scroll = reactive({
+    y: 180,
+  });
+  const deviceTypeDicts = getDictItemsByCode('fanlocaltype');
+  const gasWarningVal = ref(0.6); // 瓦斯最大报警值
+  const playerRef = ref();
+  const MonitorDataTable = ref();
+  const modalSensor = ref(null);
+  const loading = ref(false);
+  const activeKey = ref('1');
+  const player1 = ref();
+  const modalIsShow = ref<boolean>(false); // 是否显示模态框
+  const modalTitle = ref(''); // 模态框标题显示内容,根据设备操作类型决定
+  const fan1FrequencyVal = ref(40); //主机频率
+  const fan2FrequencyVal = ref(40); //备机频率
+  const mainWindIsShow1 = ref('open'); // 主机默认启动leftColumns
+  const mainWindIsShow2 = ref('stop'); // 备机默认不启动
+  const fanControl = ref('');
+  const targetVolume = ref(600);
+  const historyList = ref([]);
+  const remoteChartsColumns = getTableHeaderColumns('fanlocal_chart');
+  const chartsColumns = remoteChartsColumns && remoteChartsColumns.length > 0 ? remoteChartsColumns : chartsColumns1;
+
+  const passWord = ref('');
+  // 默认初始是第一行
+  const selectRowIndex = ref(-1);
+  const dataMonitorRowIndex = ref(0);
+  // 默认数据右边监测的是主机
+  const warningMonitorRowIndex = ref(0);
+
+  const xAxisDataGas = ref([]);
+  // 设备数据
+  const controlType = ref('');
+  const modalType = ref('');
+  // 监测数据
+  const initData = {
+    deviceID: '',
+    deviceType: '',
+    strname: '',
+    dataDh: '-', //压差
+    dataDtestq: '-', //测试风量
+    sourcePressure: '-', //气源压力
+    dataDequivalarea: '-',
+    netStatus: '0', //通信状态
+    warnLevel_str: '',
+    stationname: '',
+    fanFrequencyType: '',
+  };
+  const frequencyVal = ref(0);
+  const dataSource = ref([]);
+  const historySource = ref([]);
+  // 关联设备信息
+  const linkDeviceInfo = ref({});
+  // 监测数据
+  let selectData = reactive(lodash.cloneDeep(initData));
+  const rightColumns = ref<BasicColumn[]>([]);
+  const leftColumns = ref<BasicColumn[]>([]);
+  const devicekide = ref(deviceTypeDicts && deviceTypeDicts.length > 0 ? deviceTypeDicts[0]['value'] : 'fanlocal');
+  const deviceType = ref(selectData.deviceType);
+  const headElHeight = ref(0);
+  let btnClick = ref(true); // 判断按钮是否可点
+
+  //报表导出
+  let editID = ref<any>('');
+  let fileType = ref('');
+
+  const { getCamera, removeCamera } = useCamera();
+
+  watch(deviceType, (type) => {
+    rightColumns.value = getTableHeaderColumns(type + '_monitor_right') as [];
+    if (rightColumns.value && rightColumns.value.length < 1) {
+      rightColumns.value = getTableHeaderColumns(type.split('_')[0] + '_monitor_right') as [];
+    }
+    leftColumns.value = getTableHeaderColumns(type + '_monitor_left') as [];
+    if (leftColumns.value && leftColumns.value.length < 1) {
+      leftColumns.value = getTableHeaderColumns(type.split('_')[0] + '_monitor_left') as [];
+    }
+  });
+
+  const flvURL1 = () => {
+    // return `https://sf1-hscdn-tos.pstatp.com/obj/media-fe/xgplayer_doc_video/flv/xgplayer-demo-360p.flv`;
+    return '';
+  };
+
+  const changeDeviceKind = (e) => {
+    devicekide.value = e;
+    loading.value = true;
+    selectRowIndex.value = -1;
+    nextTick(() => {
+      selectData = lodash.cloneDeep(initData);
+      loading.value = false;
+      if (selectData.deviceID) MonitorDataTable.value.setSelectedRowKeys([selectData.deviceID]);
+      const headEl = document.querySelector(`.zxm-table-thead`);
+      if (headEl) {
+        headElHeight.value = headEl.clientHeight;
+      }
+    });
+  };
+
+  const tabChange = (activeKeyVal) => {
+    activeKey.value = activeKeyVal;
+    if (activeKeyVal == 1) {
+      nextTick(() => {
+        MonitorDataTable.value.setSelectedRowKeys([selectData.deviceID]);
+      });
+    }
+  };
+
+  const selectDevice = (key, val) => {
+    if (key === 'dataMonitorRowIndex') {
+      dataMonitorRowIndex.value = val;
+    } else {
+      warningMonitorRowIndex.value = val;
+    }
+  };
+
+  //报表导出点击
+  async function reportDown() {
+    openModal1();
+    let res = await save({ reportType: 'fanlocal' });
+    console.log(res, 'res-----------');
+    let list = await reportList({ id: res.id });
+    console.log(list, 'list-----------');
+    let index = list.records[0].fileName.indexOf('.');
+    fileType.value = list.records[0].fileName.substring(index + 1);
+    editID.value = list.records[0].id;
+    openModal1();
+  }
+
+  //详情
+  function goDetail() {
+    openModal();
+  }
+
+  function goDetailDevice(linkDeviceCode) {
+    let linkDeviceId = '';
+    if (linkDeviceCode.startsWith('window')) {
+      linkDeviceId = linkDeviceInfo.value[linkDeviceCode] ? linkDeviceInfo.value[linkDeviceCode]['id'] : '';
+      router.push({ path: '/monitorChannel/monitor-window', query: { id: linkDeviceId } });
+    }
+  }
+
+  //
+  async function getDataSource() {
+    if (devicekide.value) {
+      const res = await list({ devicetype: devicekide.value, pagetype: 'normal' });
+      // const res = await list({ devicetype: 'fanlocal', pagetype: 'normal' });
+      if (res.msgTxt && res.msgTxt[0] && res.msgTxt[0].datalist && res.msgTxt[0].datalist.length > 0) {
+        const dataArr = res.msgTxt[0].datalist || [];
+        dataSource.value = [];
+        dataArr.forEach((data) => {
+          const readData = data.readData;
+          data = Object.assign(data, readData);
+          if (data['Fan1StartStatus'] && data['Fan1StartStatus'] === '1.0') data['Fan1StartStatus'] = '1';
+          if (data['Fan2StartStatus'] && data['Fan2StartStatus'] === '1.0') data['Fan2StartStatus'] = '1';
+          if (data['Fan1StartStatus'] && data['Fan1StartStatus'] === '0.0') data['Fan1StartStatus'] = '0';
+          if (data['Fan2StartStatus'] && data['Fan2StartStatus'] === '0.0') data['Fan2StartStatus'] = '0';
+          data['windQuantity2'] =
+            data['windQuantity2'] ||
+            data['m3'] ||
+            data['ductOutletAirVolume_merge'] ||
+            data['windOutSpeed_merge'] ||
+            data['windOutSpeed1'] ||
+            data['windOutSpeed2'] ||
+            data['windOutSpeed_merge'];
+          // if (globSetting.sysOrgCode === 'sdmtjtbetmk') {
+          //   if (data['m3']) data['ductOutletAirVolume_merge'] = data['m3'];
+          //   if (data['m3']) data['inletAirVolume_merge'] = (Number(data['m3']) * 1.08).toFixed(2);
+          // }
+          dataSource.value.push(data);
+          if (selectRowIndex.value > -1) {
+            let echartsData = dataArr[selectRowIndex.value]['history'] || [];
+            echartsData = echartsData.filter((item) => {
+              item['FanfHz'] = data['Fan1StartStatus'] == '1' ? item['Fan1fHz'] : data['Fan2StartStatus'] == '1' ? item['Fan2fHz'] : 0;
+              item['windQuantity2'] =
+                item['windQuantity2'] ||
+                item['m3'] ||
+                item['ductOutletAirVolume_merge'] ||
+                item['windOutSpeed_merge'] ||
+                item['windOutSpeed1'] ||
+                item['windOutSpeed2'] ||
+                item['windOutSpeed_merge'];
+              return true;
+            });
+            historyList.value = echartsData;
+          }
+        });
+      } else {
+        return (dataSource.value = []);
+      }
+    } else {
+      dataSource.value = [];
+    }
+  }
+
+  // https获取监测数据
+  let timer: null | NodeJS.Timeout = null;
+  async function getMonitor(flag?) {
+    if (Object.prototype.toString.call(timer) === '[object Null]') {
+      timer = await setTimeout(
+        async () => {
+          // debugger;
+          await getDataSource();
+          if (dataSource.value.length > 0 && selectRowIndex.value == -1 && MonitorDataTable.value) {
+            // 初始打开页面
+            if (flag && currentRoute.value && currentRoute.value['query'] && currentRoute.value['query']['id']) {
+              MonitorDataTable.value.setSelectedRowKeys(currentRoute.value['query']['id']);
+            } else {
+              MonitorDataTable.value.setSelectedRowKeys(dataSource.value[0]['deviceID']);
+            }
+          }
+          for (const key in selectData) {
+            selectData[key] = '';
+          }
+          if (dataSource.value.length > 0 && dataSource.value[selectRowIndex.value]) {
+            deviceType.value = dataSource.value[selectRowIndex.value]['deviceType'];
+            if (dataSource.value.length > 0 && dataSource.value[selectRowIndex.value]) {
+              Object.assign(selectData, dataSource.value[selectRowIndex.value]);
+            }
+            playSmoke(selectData);
+            addText(selectData);
+          }
+          historySource.value = selectData.history;
+          if (timer) {
+            timer = null;
+          }
+          getMonitor();
+        },
+        flag ? 0 : 1000
+      );
+    }
+  }
+
+  // 获取设备基本信息列表
+  const deviceBaseList = ref([]);
+  function getDeviceBaseList() {
+    getTableList({ pageSize: 1000 }).then((res) => {
+      deviceBaseList.value = res.records;
+    });
+  }
+
+  // 切换检测数据
+  async function getSelectRow(id) {
+    console.log('选中的设备id------->', id);
+
+    if (!id || id == selectData['deviceID']) return;
+    // loading.value = true;
+    const selectIndex: any = dataSource.value.findIndex((baseData: any) => baseData.deviceID == id);
+    selectRowIndex.value = selectIndex;
+    nextTick(() => {
+      const headEl = document.querySelector(`.zxm-table-thead`);
+      if (headEl) {
+        headElHeight.value = headEl.clientHeight;
+      }
+
+      const data = dataSource.value[selectIndex];
+      if (data) {
+        if (selectData['linkInfo']) linkDeviceInfo.value = JSON.parse(selectData['linkInfo']);
+
+        if (linkDeviceInfo.value['window_fWindowM3']) {
+          modalType.value = 'fc';
+        }
+        // 主备互斥控制
+        if (data['Fan1StartStatus'] == '1') {
+          mainWindIsShow1.value = 'open';
+          mainWindIsShow2.value = 'stop';
+          selectDevice('warningMonitorRowIndex', 0);
+          selectDevice('dataMonitorRowIndex', 0);
+        } else if (data['Fan2StartStatus'] == '1') {
+          mainWindIsShow2.value = 'open';
+          mainWindIsShow1.value = 'stop';
+          selectDevice('warningMonitorRowIndex', 1);
+          selectDevice('dataMonitorRowIndex', 1);
+        }
+        const xAxisDataGasArr = [];
+        for (const key in selectData) {
+          if (key.startsWith('gas') && key.length < 5) {
+            xAxisDataGasArr.push({ key: 'T' + key.substring(3), valueKey: key });
+          }
+        }
+        xAxisDataGas.value = xAxisDataGasArr;
+      }
+      setModelType(modalType.value);
+    });
+
+    await getCamera(id, playerRef.value);
+    return;
+  }
+
+  // 打开并设置modal的标题
+  function showModal(obj) {
+    if (!btnClick.value) return;
+    if (obj.key == 'kkjc') {
+      gasWarningVal.value = 0.6;
+      // 工况辅助决策
+      openAssistance(true, {});
+      return;
+    }
+    controlType.value = obj.key;
+    modalTitle.value = obj.value;
+    passWord.value = '';
+    modalIsShow.value = true;
+  }
+
+  function changeMotor(e) {
+    const target = e.target;
+    if (target.name === 'localWind1') {
+      if (target.value === 'open') {
+        mainWindIsShow2.value = 'stop';
+      }
+    } else if (target.name === 'localWind2') {
+      if (target.value === 'open') {
+        mainWindIsShow1.value = 'stop';
+      }
+    }
+  }
+
+  function handleOk(control?) {
+    if (passWord.value == '') {
+      message.warning('请输入密码!');
+      return;
+    }
+
+    createConfirm({
+      iconType: 'warning',
+      title: '控制',
+      content: '您确定要控制吗?',
+      onOk: () => handerFn(),
+    });
+    const handerFn = () => {
+      const handType = controlType.value;
+      const data = {
+        deviceid: selectData.deviceID,
+        devicetype: selectData.deviceType,
+        paramcode: '',
+        password: passWord.value || globalConfig?.simulatedPassword,
+        value: null,
+      };
+      if (handType === 'startSmoke') {
+        // 启动风机
+        // 以下是互斥
+        if (mainWindIsShow1.value === 'open' && mainWindIsShow2.value === 'stop') {
+          // playSmoke(handType, 'top', frequency, 'open');
+          data.paramcode = 'CtrlFan1Start';
+          deviceControlApi(data)
+            .then((res) => {
+              if (res.success) {
+                if (globalConfig.History_Type == 'remote') {
+                  message.success('指令已下发至生产管控平台成功!');
+                } else {
+                  message.success('指令已下发成功!');
+                }
+                modalTitle.value = '';
+                modalIsShow.value = false;
+              } else {
+                message.error(res.message);
+              }
+            })
+            .catch((err) => {
+              // modalIsShow.value = true;
+            });
+        } else if (mainWindIsShow2.value === 'open' && mainWindIsShow1.value === 'stop') {
+          // playSmoke(handType, 'down', frequency, 'open');
+          data.paramcode = 'CtrlFan2Start';
+          deviceControlApi(data)
+            .then(() => {
+              if (res.success) {
+                if (globalConfig.History_Type == 'remote') {
+                  message.success('指令已下发至生产管控平台成功!');
+                } else {
+                  message.success('指令已下发成功!');
+                }
+                modalTitle.value = '';
+                modalIsShow.value = false;
+              } else {
+                message.error(res.message);
+              }
+            })
+            .catch((err) => {});
+        } else if (mainWindIsShow1.value === 'stop' && mainWindIsShow2.value === 'stop') {
+          // playSmoke(handType, '', frequency, 'stop');
+        }
+      } else if (handType === 'startFan') {
+        if (control === 'Fan1Open') {
+          data.paramcode = 'CtrlFan1Start';
+        } else if (control === 'Fan2Open') {
+          data.paramcode = 'CtrlFan2Start';
+        } else if (control === 'Fan1Stop') {
+          data.paramcode = 'Fan1Stop';
+        } else if (control === 'Fan2Stop') {
+          data.paramcode = 'Fan2Stop';
+        } else if (control === 'Fan1Reset') {
+          data.paramcode = 'Fan1Reset';
+        } else if (control === 'Fan2Reset') {
+          data.paramcode = 'Fan2Reset';
+        }
+        deviceControlApi(data)
+          .then((res) => {
+            if (res.success) {
+              if (globalConfig.History_Type == 'remote') {
+                message.success('指令已下发至生产管控平台成功!');
+              } else {
+                message.success('指令已下发成功!');
+              }
+              modalTitle.value = '';
+              modalIsShow.value = false;
+            } else {
+              message.error(res.message);
+            }
+          })
+          .catch((err) => {
+            btnClick.value = true;
+          });
+      } else if (handType === 'Fan1Frequency' || handType === 'Fan2Frequency' || handType === 'FanFrequency') {
+        // 调频
+        if (handType === 'Fan1Frequency') {
+          data.paramcode = 'Fan1FreqHz';
+          data.value = fan1FrequencyVal.value;
+        } else if (handType === 'Fan2Frequency') {
+          data.paramcode = 'Fan2FreqHz';
+          data.value = fan2FrequencyVal.value;
+        } else if (handType === 'FanFrequency') {
+          data.paramcode = 'FreqHz_merge';
+          data.value = fan1FrequencyVal.value;
+        }
+
+        deviceControlApi(data)
+          .then((res) => {
+            if (res.success) {
+              if (globalConfig.History_Type == 'remote') {
+                message.success('指令已下发至生产管控平台成功!');
+              } else {
+                message.success('指令已下发成功!');
+              }
+              modalTitle.value = '';
+              modalIsShow.value = false;
+            } else {
+              message.error(res.message);
+            }
+          })
+          .catch((err) => {});
+      } else if (handType === 'changeSmoke') {
+        if (selectData['Fan1StartStatus'] == '0' || !selectData['Fan1StartStatus']) {
+          data.paramcode = 'CtrlFan1Start';
+          deviceControlApi(data)
+            .then((res) => {
+              if (res.success) {
+                if (globalConfig.History_Type == 'remote') {
+                  message.success('指令已下发至生产管控平台成功!');
+                } else {
+                  message.success('指令已下发成功!');
+                }
+                modalTitle.value = '';
+                modalIsShow.value = false;
+              } else {
+                message.error(res.message);
+              }
+
+              mainWindIsShow1.value = 'stop';
+              mainWindIsShow2.value = 'open';
+            })
+            .catch((err) => {});
+        } else if (selectData['Fan2StartStatus'] == '0' || !selectData['Fan2StartStatus']) {
+          data.paramcode = 'CtrlFan2Start';
+          deviceControlApi(data)
+            .then((res) => {
+              if (res.success) {
+                if (globalConfig.History_Type == 'remote') {
+                  message.success('指令已下发至生产管控平台成功!');
+                } else {
+                  message.success('指令已下发成功!');
+                }
+                modalTitle.value = '';
+                modalIsShow.value = false;
+              } else {
+                message.error(res.message);
+              }
+              mainWindIsShow1.value = 'open';
+              mainWindIsShow2.value = 'stop';
+            })
+            .catch((err) => {});
+        }
+        // // 一键倒机
+        // if (mainWindIsShow1.value === 'open' && mainWindIsShow2.value === 'stop') {
+        //   // playSmoke('startSmoke', 'down', frequency, 'open');
+        //   data.paramcode = 'CtrlFan2Start';
+        //   deviceControlApi(data).then((res) => {
+        //     console.log('设备操作结果', res);
+        //     modalTitle.value = '';
+        //     modalIsShow.value = false;
+        //   }).catch((err) => {
+
+        //   });
+        //   mainWindIsShow1.value = 'stop';
+        //   mainWindIsShow2.value = 'open';
+        // } else if (mainWindIsShow2.value === 'open' && mainWindIsShow1.value === 'stop') {
+        //   // playSmoke('startSmoke', 'top', frequency, 'open');
+        //   data.paramcode = 'CtrlFan1Start';
+        //   deviceControlApi(data).then((res) => {
+        //     console.log('设备操作结果', res);
+        //     modalTitle.value = '';
+        //     modalIsShow.value = false;
+        //   }).catch((err) => {
+
+        //   });
+        //   mainWindIsShow1.value = 'open';
+        //   mainWindIsShow2.value = 'stop';
+        // } else if (mainWindIsShow1.value === 'stop' && mainWindIsShow2.value === 'stop') {
+        //   // playSmoke(handType, '', frequency, 'stop');
+        // }
+      } else if (handType === 'changeFan') {
+        data.paramcode = 'CtrlFanStart';
+        deviceControlApi(data)
+          .then((res) => {
+            if (res.success) {
+              if (globalConfig.History_Type == 'remote') {
+                message.success('指令已下发至生产管控平台成功!');
+              } else {
+                message.success('指令已下发成功!');
+              }
+            } else {
+              message.error(res.message);
+            }
+            modalTitle.value = '';
+            modalIsShow.value = false;
+          })
+          .catch((err) => {});
+      } else if (handType === 'fan1ToFan2') {
+        data.paramcode = 'CtrlFan1ToFan2';
+        deviceControlApi(data).then((res) => {
+          if (res.success) {
+            if (globalConfig.History_Type == 'remote') {
+              message.success('指令已下发至生产管控平台成功!');
+            } else {
+              message.success('指令已下发成功!');
+            }
+            modalTitle.value = '';
+            modalIsShow.value = false;
+          } else {
+            message.error(res.message);
+          }
+        });
+      } else if (handType === 'fan2ToFan1') {
+        data.paramcode = 'CtrlFan2ToFan1';
+        deviceControlApi(data).then((res) => {
+          if (res.success) {
+            if (globalConfig.History_Type == 'remote') {
+              message.success('指令已下发至生产管控平台成功!');
+            } else {
+              message.success('指令已下发成功!');
+            }
+            modalTitle.value = '';
+            modalIsShow.value = false;
+          } else {
+            message.error(res.message);
+          }
+        });
+      } else if (handType === 'gasAlarmSet') {
+        if (passWord.value != '123456') {
+          message.error('密码错误,请重新输入!');
+          return;
+        }
+        if (gasWarningVal.value) {
+          modalTitle.value = '';
+          modalIsShow.value = false;
+          setTimeout(() => {
+            passWord.value = '';
+            modalIsShow.value = true;
+            controlType.value = 'toGkjc';
+            modalTitle.value = '工况决策辅助';
+          }, 500);
+        } else {
+          message.error('请核对瓦斯超限浓度值!');
+        }
+      } else if (handType === 'toGkjc') {
+        if (passWord.value != '123456') {
+          message.error('密码错误,请重新输入!');
+          return;
+        }
+        //进行工况决策
+        if (selectData.Fan1StartStatus == '1') {
+          openAssistance(true, {
+            // m3: selectData.m3 || 675.87,
+            m3: 675.87,
+            frequency: 30,
+            // m3: 525.87,  //5.0测试数据
+            // frequency: 35,
+            // frequency: selectData.Fan1fHz || selectData.Fan1FreqHz || selectData.Fan1Loop_Frequency,
+            gasWarningVal: gasWarningVal.value,
+            isCompute: false,
+          });
+        } else if (selectData.Fan2StartStatus == '1') {
+          openAssistance(true, {
+            // m3: selectData.m3 || 675.87,
+            m3: 675.87,
+            frequency: 30,
+            // frequency: selectData.Fan2fHz || selectData.Fan2FreqHz || selectData.Fan2Loop_Frequency,
+            gasWarningVal: gasWarningVal.value,
+            isCompute: false,
+          });
+        } else {
+          // openAssistance(true, { m3: 635.04, dataDh: 5748 });
+          openAssistance(true);
+        }
+        modalTitle.value = '';
+        modalIsShow.value = false;
+      } else if (handType === 'zhlk' || handType === 'gasOverSet') {
+        if (targetVolume.value) {
+          const params =
+            handType === 'zhlk'
+              ? { auto: 1, fanlocalId: selectData.deviceID, xufengliang: targetVolume.value }
+              : { auto: 1, fanlocalId: selectData.deviceID, gasMax: gasWarningVal.value };
+          autoAdjust(params).then(() => {
+            if (res.success) {
+              if (globalConfig.History_Type == 'remote') {
+                message.success('指令已下发至生产管控平台成功!');
+              } else {
+                message.success('指令已下发成功!');
+              }
+              modalTitle.value = '';
+              modalIsShow.value = false;
+            } else {
+              message.error(res.message);
+            }
+          });
+        }
+      }
+    };
+  }
+
+  function cancel() {
+    modalTitle.value = '';
+    modalIsShow.value = false;
+    gasWarningVal.value = 0;
+  }
+
+  function handleChangeSensor(value: string) {
+    console.log(value);
+  }
+
+  function addPlayVideo() {
+    if (player1.value && player1.value.play) {
+      if (!player1.value.paused()) player1.value.play();
+      document.body.removeEventListener('mousedown', addPlayVideo);
+    }
+  }
+
+  function deviceEdit(e: Event, type: string, record) {
+    e.stopPropagation();
+    openModal(true, {
+      type,
+      deviceId: record['deviceID'],
+    });
+  }
+
+  onBeforeMount(() => {
+    getDeviceBaseList();
+  });
+
+  onMounted(() => {
+    const { query } = unref(currentRoute);
+    if (query['deviceType']) devicekide.value = query['deviceType'] as string;
+    mountedThree(player1.value).then(async () => {
+      await getMonitor(true);
+      nextTick(async () => {
+        addCssText();
+      });
+    });
+
+    document.body.addEventListener('mousedown', addPlayVideo, false);
+  });
+
+  onUnmounted(() => {
+    destroy();
+    removeCamera();
+    if (timer) {
+      clearTimeout(timer);
+      timer = undefined;
+    }
+  });
+</script>
+<style scoped lang="less">
+  @import '/@/design/vent/modal.less';
+  :deep(.@{ventSpace}-tabs-tabpane-active) {
+    height: 100%;
+  }
+  .scene-box {
+    .title-text {
+      height: 32px;
+    }
+    .bottom-tabs-box {
+      height: 280px;
+      .tabs-box {
+        position: relative !important;
+      }
+    }
+  }
+
+  .data-show-box {
+    position: relative;
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    padding: 10px 5px;
+    color: #ffffff;
+    z-index: 999;
+    top: 60px;
+    .data-item {
+      pointer-events: auto;
+      .item-header {
+        width: 374px;
+        background: url('/@/assets/images/vent/lr-top-bg.png') no-repeat;
+        background-size: auto;
+        height: 32px;
+        text-align: center;
+        line-height: 34px;
+        font-size: 15px;
+        font-weight: 600;
+        color: #fafafa;
+      }
+      .item-container {
+        width: 346px;
+        margin: 0 14px;
+        padding: 10px;
+        background: #00377c33;
+        backdrop-filter: blur(2px);
+        .tab {
+          width: 323px;
+          background: url('/@/assets/images/vent/lr-tab-bg.png') no-repeat;
+          display: flex;
+          .tab-item {
+            flex: 1;
+            text-align: center;
+            padding-top: 2px;
+            color: #ffffff99;
+            cursor: pointer;
+          }
+          .tab-item-active-l {
+            color: #00ffea;
+            background-image: url('/@/assets/images/vent/l-tab-active.png');
+            background-repeat: no-repeat;
+            background-size: auto;
+            background-position: 6px 3px;
+          }
+          .tab-item-active-r {
+            color: #00ffea;
+            background-image: url('/@/assets/images/vent/r-tab-active.png');
+            background-repeat: no-repeat;
+            background-position: 0 3px;
+          }
+        }
+        .container-group {
+          width: 314px;
+          margin: 0px 4px;
+          padding: 10px 0;
+          min-height: 432px;
+          background: linear-gradient(to right, #00deff22, #2081ff05);
+          max-height: 440px;
+          overflow-y: auto;
+        }
+        .container-item {
+          width: 100%;
+          height: 60px;
+          display: flex;
+          padding: 10px 0 0 20px;
+          margin-bottom: 5px;
+          position: relative;
+          background: url('/@/assets/images/vent/plane-bottom.png') no-repeat;
+          background-size: auto;
+          background-position: bottom;
+          &::before {
+            content: '';
+            display: block;
+            width: 100%;
+            height: 5px;
+            position: absolute;
+            top: 62px;
+            left: 0;
+            background-color: #73f4ff66;
+            backdrop-filter: blur(5px);
+          }
+          .item-icon {
+            width: 54px;
+            height: 45px;
+            background: url('/@/assets/images/vent/plane-icon-bg.png') no-repeat;
+            background-size: cover;
+            .icon-style {
+              font-size: 18px;
+              margin: 10px 0 0 20px;
+              color: #ffc800;
+            }
+          }
+          .item-name {
+            width: 180px;
+            line-height: 60px;
+          }
+          .item-value {
+            position: relative;
+            height: 26px;
+            line-height: 24px;
+            margin: 15px 0;
+            text-align: center;
+            width: 80px;
+            border: 1px solid #00f5fe;
+            border-radius: 13px;
+            background: linear-gradient(to right, #00f5fe44, #0090ff44);
+            &::before {
+              width: 6px;
+              height: 6px;
+              content: '';
+              position: absolute;
+              left: -3px;
+              top: 8px;
+              background: #ffa500;
+              border-radius: 3px;
+            }
+          }
+        }
+        .warning-header {
+          display: flex;
+          font-size: 14px;
+          .header-item {
+            flex: 1;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            .header-title {
+              color: #39e7fe;
+              margin-top: 10px;
+            }
+            .header-value {
+              // width: 133px;
+              height: 36px;
+              font-weight: 600;
+              font-family: 'douyuFont';
+              font-size: 16px;
+              color: #ffa500;
+              display: flex;
+              justify-content: center;
+              align-items: center;
+              margin-top: 15px;
+              margin-left: 8px;
+              // background: url('/@/assets/images/vent/count-header-bg.png') no-repeat;
+            }
+          }
+        }
+        .warning-group {
+          padding: 0 10px;
+          position: relative;
+
+          .warning-item {
+            display: flex;
+            flex-direction: row;
+            justify-content: space-between;
+            align-items: center;
+            height: 38px;
+            .item-name {
+              display: flex;
+              align-items: center;
+              // padding-left: 5px;
+              .icon {
+                width: 6px;
+                height: 6px;
+                display: inline-block;
+                background-color: #1cd5ff;
+                border-radius: 3px;
+                position: relative;
+                margin-right: 8px;
+                &::before {
+                  content: '';
+                  width: 10px;
+                  height: 10px;
+                  display: block;
+                  border: 1px solid #34edff99;
+                  border-radius: 5px;
+                  position: absolute;
+                  top: -2px;
+                  left: -2px;
+                }
+              }
+              &::before {
+                content: '';
+                display: block;
+                width: 1px;
+                height: 38px;
+                position: absolute;
+                left: 12px;
+                background-color: #00f5fe;
+              }
+            }
+          }
+        }
+        .warning-group-r {
+          &::before {
+            content: '';
+            display: block;
+            width: 1px;
+            height: 100%;
+            position: absolute;
+            left: 12px;
+            background-color: #00f5fe;
+          }
+        }
+      }
+    }
+  }
+  .input-box {
+    display: flex;
+    align-items: center;
+    .input-title {
+      color: #73e8fe;
+      width: auto;
+    }
+    margin-right: 10px;
+  }
+  .label {
+    max-width: 220px;
+  }
+  #fanLocalSelectDom {
+    :deep(.@{ventSpace}-select-dropdown) {
+      left: 0px !important;
+      top: 35px !important;
+    }
+  }
+  .@{ventSpace}-input {
+    width: 150px;
+  }
+  :deep(#LivePlayerBox) {
+    display: flex;
+    flex-direction: row;
+    justify-content: flex-end;
+    padding-right: 380px;
+    pointer-events: none;
+    .video-parent {
+      height: 208px;
+      pointer-events: auto !important;
+    }
+  }
+  .to-right {
+    :deep(#LivePlayerBox) {
+      padding-right: 0px;
+    }
+  }
+
+  :deep(.button-box) {
+    position: relative;
+    padding: 5px;
+    // border: 1px transparent solid;
+    border-radius: 5px;
+    margin-left: 8px;
+    margin-right: 8px;
+    width: auto;
+    // height: 40px;
+    // border: 1px solid #65dbea;
+    height: 35px !important;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    color: #fff;
+    padding: 0 15px 5px 15px;
+    cursor: pointer;
+    &:hover {
+      background: linear-gradient(#2cd1ff55, #1eb0ff55);
+    }
+    &::before {
+      width: calc(100% - 6px);
+      height: 27px;
+      content: '';
+      position: absolute;
+      top: 3px;
+      right: 0;
+      left: 3px;
+      bottom: 0;
+      z-index: -1;
+      border-radius: inherit; /*important*/
+      background: linear-gradient(#1fa6cb, #127cb5);
+    }
+    &::after {
+      width: calc(100% + 32px);
+      height: 10px;
+      content: '';
+      position: absolute;
+      top: 28px;
+      right: 0;
+      left: -16px;
+      bottom: 0;
+      z-index: -1;
+      border-radius: inherit; /*important*/
+      background-position: center;
+      background-size: 100%;
+      z-index: 999;
+    }
+  }
+</style>

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 545 - 886
src/views/vent/monitorManager/fanLocalMonitor/index.vue


+ 12 - 0
src/views/vent/monitorManager/fanlocalPage/fanlocal.api.ts

@@ -0,0 +1,12 @@
+import { defHttp } from '/@/utils/http/axios';
+
+enum Api {
+    device = '/monitor/device',
+}
+/**
+ * 列表接口
+ * @param params
+ */
+export const device = (params) => defHttp.post({ url: Api.device, params });
+
+

+ 279 - 0
src/views/vent/monitorManager/fanlocalPage/index.vue

@@ -0,0 +1,279 @@
+<template>
+    <div class="fanlocalPage">
+        <customHeader>局部风机监测</customHeader>
+        <div class="left-icon">
+            <img src="../../../../assets/images/vent/fanlocal-page/arrow-button.png" alt="">
+        </div>
+        <div class="right-icon">
+            <img class="img1" src="../../../../assets/images/vent/fanlocal-page/arrow-button.png" alt="">
+        </div>
+        <div class="fanlocal-container">
+            <div class="card-box" v-for="(item, index) in cardList" :key="index">
+                <div class="card-title" @click="getClick(item)">{{ item.label }}</div>
+                <div class="card-box-item">
+                    <div class="left-box-item">
+                        <div class="item-icon">
+                            <img src="../../../../assets/images/vent/fanlocal-page/is-txzt1.png" alt="">
+                        </div>
+                        <div class="item-content">
+                            <div class="item-content-value">{{ item.txVal }}</div>
+                            <div class="item-content-text">{{ item.txLable }}</div>
+                        </div>
+                    </div>
+                    <div class="right-box-item">
+                        <div class="item-icon">
+                            <img src="../../../../assets/images/vent/fanlocal-page/is-warn1.png" alt="">
+                        </div>
+                        <div class="item-content">
+                            <div class="item-content-value">{{ item.warnVal }}</div>
+                            <div class="item-content-text">{{ item.warnLabel }}</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="card-box-list">
+                    <div class="list-item" v-for="(ite, ind) in item.listData" :key="ind">
+                        <div class="list-item-label">{{ ite.label }}</div>
+                        <div class="list-item-value">{{ `${ite.value}${ite.dw}` }}</div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+<script setup lang="ts">
+import { onBeforeMount, ref, watch, onMounted, nextTick, defineAsyncComponent, reactive, onUnmounted, inject, unref } from 'vue';
+import customHeader from '/@/components/vent/customHeader.vue';
+import { device } from './fanlocal.api'
+import { useRouter } from 'vue-router';
+
+const props = defineProps({});
+
+let router = useRouter();
+let cardList = reactive<any[]>([])
+
+// https获取监测数据
+let timer: null | NodeJS.Timeout = null;
+function getMonitor(flag?) {
+    timer = setTimeout(
+        async () => {
+            await getList()
+            if (timer) {
+                timer = null;
+            }
+            getMonitor();
+        },
+        flag ? 0 : 3000
+    );
+}
+//点击标题页面跳转
+function getClick(item){
+    router.push('/monitorChannel/monitor-fanlocal?id='+ item.deviceID + '&deviceType=fanlocal')
+}
+//获取列表数据
+async function getList() {
+    let res = await device({ devicetype: "fanlocal", pagetype: "normal" })
+    let data = res.msgTxt[0].datalist
+    cardList.length = 0
+    if (data.length != 0) {
+        data.forEach(el => {
+            cardList.push(
+                {
+                    deviceID:el.deviceID,
+                    label: el.strinstallpos,
+                    txVal: el.netStatus==1 ? '连接' : '未连接',
+                    txLable: '通讯状态',
+                    warnVal: el.warnLevel_str,
+                    warnLabel: '是否报警',
+                    listData: [
+                        { label: '运行风机', value: el.readData.Fan1StartStatus=='1' ? '主机' : el.readData.Fan2StartStatus=='1' ? '备机' : '--', dw: '' },
+                        { label: '风量', value: el.readData.window_fWindowM3, dw: 'm³/min' },
+                        { label: '迎头风速', value:el.readData.windSpeed1, dw: 'm/s' },
+                        { label: '迎头瓦斯', value: el.readData.gas1, dw: 'm/s' },
+                        { label: '时间', value: el.readTime, dw: '' },
+                    ]
+                },
+            )
+        })
+    }
+
+}
+
+onMounted(() => {
+    getList()
+    getMonitor()
+})
+onUnmounted(() => {
+    if (timer) {
+        clearTimeout(timer);
+        timer = undefined;
+    }
+});
+
+
+</script>
+<style lang="less" scoped>
+.fanlocalPage {
+    width: 100%;
+    height: 100%;
+    padding: 100px 60px 20px 60px;
+    box-sizing: border-box;
+    position: relative;
+
+    .left-icon {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        width: 60px;
+        height: calc(100% - 100px);
+        position: absolute;
+        left: 0;
+        top: 100px;
+
+    }
+
+    .right-icon {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        width: 60px;
+        height: calc(100% - 100px);
+        position: absolute;
+        right: 0;
+        top: 100px;
+    }
+
+    img {
+        width: 60px;
+        height: 60px;
+    }
+
+    .img1 {
+        transform: rotate(180deg);
+    }
+
+    .fanlocal-container {
+        height: 100%;
+        display: flex;
+        flex-wrap: wrap;
+
+        .card-box {
+            position: relative;
+            width: 417px;
+            height: 380px;
+            margin: 0px 15px;
+            background: url(/src/assets/images/vent/fanlocal-page/card.png) no-repeat center;
+            background-size: 100% 100%;
+
+            .card-title {
+                position: absolute;
+                left: 50%;
+                top: 6px;
+                transform: translate(-50%, 0);
+                font-size: 14px;
+                font-family: 'douyuFont';
+                color: #fff;
+                cursor: pointer;
+            }
+
+            .card-box-item {
+                width: 100%;
+                height: 64px;
+                position: absolute;
+                left: 0;
+                top: 55px;
+                display: flex;
+                justify-content: space-around;
+
+                .left-box-item {
+                    display: flex;
+                    justify-content: space-between;
+                    align-items: center;
+                    width: 45%;
+                    height: 100%;
+                    padding: 5px 10px;
+                    background: url('../../../../assets/images/vent/fanlocal-page/is-txzt.png') no-repeat center;
+                    background-size: 100% 100%;
+                    box-sizing: border-box;
+                }
+
+                .right-box-item {
+                    display: flex;
+                    justify-content: space-between;
+                    align-items: center;
+                    width: 45%;
+                    height: 100%;
+                    padding: 5px 10px;
+                    background: url('../../../../assets/images/vent/fanlocal-page/is-warn.png') no-repeat center;
+                    background-size: 100% 100%;
+                    box-sizing: border-box;
+                }
+
+                .item-icon {
+                    width: 60px;
+                    height: 100%;
+                    margin-right: 15px;
+                    display: flex;
+                    justify-content: center;
+                    align-items: center
+                }
+
+                .item-content {
+                    width: calc(100% - 60px);
+                    height: 100%;
+                    display: flex;
+                    flex-direction: column;
+                    justify-content: center;
+                    color: #fff;
+                    font-size: 14px;
+                    padding-top: 10px;
+                    box-sizing: border-box;
+
+                    .item-content-value {
+                        font-family: 'douyuFont';
+                        color: #01fefc;
+                    }
+
+
+
+                }
+
+
+            }
+
+            .card-box-list {
+                width: 100%;
+                height: 245px;
+                padding: 0px 15px;
+                box-sizing: border-box;
+                position: absolute;
+                left: 0;
+                top: 130px;
+                display: flex;
+                flex-direction: column;
+                justify-content: space-around;
+                overflow-y: auto;
+
+                .list-item {
+                    height: 30px;
+                    padding: 0px 25px;
+                    box-sizing: border-box;
+                    color: #fff;
+                    display: flex;
+                    justify-content: space-between;
+                    align-items: center;
+                    background: url('../../../../assets/images/vent/fanlocal-page/one-bg.png') no-repeat center;
+                    background-size: 100% 100%;
+
+                    .list-item-value {
+                        color: #01fefc;
+                    }
+                }
+
+            }
+        }
+
+
+    }
+
+}
+</style>

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio