Ver código fonte

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

lxh 8 meses atrás
pai
commit
d5a912fb0d
26 arquivos alterados com 327 adições e 260 exclusões
  1. 8 3
      src/hooks/vent/useThree.ts
  2. 9 4
      src/utils/threejs/useThree.ts
  3. 5 5
      src/views/system/menu/menu.data.ts
  4. 18 8
      src/views/vent/deviceManager/comment/warningTabel/BaseModal.vue
  5. 1 1
      src/views/vent/deviceManager/comment/warningTabel/BaseModal1.vue
  6. 2 1
      src/views/vent/deviceManager/comment/warningTabel/index2.vue
  7. 6 4
      src/views/vent/deviceManager/comment/warningTabel/index3.vue
  8. 22 3
      src/views/vent/deviceManager/comment/warningTabel/warning.data.ts
  9. 3 0
      src/views/vent/deviceManager/configurationTable/adapters.ts
  10. 10 10
      src/views/vent/deviceManager/configurationTable/configuration.api.ts
  11. 13 0
      src/views/vent/deviceManager/configurationTable/configuration.data.ts
  12. 1 1
      src/views/vent/deviceManager/configurationTable/index.vue
  13. 1 0
      src/views/vent/deviceManager/configurationTable/types.ts
  14. 21 28
      src/views/vent/home/configurable/components/AirVolumeMonitor.vue
  15. 35 33
      src/views/vent/home/configurable/components/DeviceWarning.vue
  16. 30 31
      src/views/vent/home/configurable/components/VentilateAnalysis.vue
  17. 12 14
      src/views/vent/home/configurable/components/VentilateControl.vue
  18. 26 30
      src/views/vent/home/configurable/components/WorkSurface.vue
  19. 17 1
      src/views/vent/home/configurable/configurable.api.ts
  20. 41 8
      src/views/vent/home/configurable/hooks/useInit.ts
  21. 2 2
      src/views/vent/monitorManager/fanLocalMonitor/index.vue
  22. 40 57
      src/views/vent/monitorManager/gateMonitor/gate.threejs.xr.ts
  23. 0 6
      src/views/vent/monitorManager/gateMonitor/index.vue
  24. 1 1
      src/views/vent/monitorManager/nitrogen/components/nitrogenHome.vue
  25. 1 1
      src/views/vent/monitorManager/nitrogen/components/nitrogenHome1.vue
  26. 2 8
      src/views/vent/monitorManager/windrectMonitor/index.vue

+ 8 - 3
src/hooks/vent/useThree.ts

@@ -164,7 +164,7 @@ class UseThree {
     // this.orbitControls.maxDistance = true;
   }
 
-  setGLTFModel(modalNames, group = null) {
+  setGLTFModel(modalNames, group = null, isBlender = false) {
     window['startTime'] = new Date().getTime();
     const modelStore = useModelStore();
     return new Promise(async (resolve, reject) => {
@@ -181,7 +181,7 @@ class UseThree {
 
         const modalNameArr = Object.prototype.toString.call(modalNames) === '[object Array]' ? modalNames : [modalNames];
         const len = modalNameArr.length;
-
+        debugger;
         for (let i = 0; i < len; i++) {
           resolvePromise[i] = new Promise(async (childResolve, reject) => {
             try {
@@ -202,7 +202,7 @@ class UseThree {
                   modalValue,
                   '/model/glft/',
                   (gltf) => {
-                    const object = gltf.scene;
+                    let object: THREE.Object3D = gltf.scene;
                     // setModalCenter(object);
                     object.traverse((obj) => {
                       if (obj instanceof THREE.Mesh) {
@@ -234,6 +234,11 @@ class UseThree {
                         // obj.renderOrder = 1;
                       }
                     });
+
+                    debugger;
+                    if (isBlender) {
+                      object = object.children[0];
+                    }
                     object.animations = gltf.animations;
                     object.name = modalNameStr;
                     group?.add(object);

+ 9 - 4
src/utils/threejs/useThree.ts

@@ -193,7 +193,7 @@ class UseThree {
     // this.orbitControls.maxDistance = true;
   }
 
-  setGLTFModel(modalNames, group = null) {
+  setGLTFModel(modalNames, group = null, isBlender = false) {
     window['startTime'] = new Date().getTime();
     const modelStore = useModelStore();
     return new Promise(async (resolve, reject) => {
@@ -210,7 +210,6 @@ class UseThree {
 
         const modalNameArr = Object.prototype.toString.call(modalNames) === '[object Array]' ? modalNames : [modalNames];
         const len = modalNameArr.length;
-
         for (let i = 0; i < len; i++) {
           resolvePromise[i] = new Promise(async (childResolve, reject) => {
             try {
@@ -231,7 +230,7 @@ class UseThree {
                   modalValue,
                   '/model/glft/',
                   (gltf) => {
-                    const object = gltf.scene;
+                    let object: THREE.Object3D = gltf.scene;
                     // setModalCenter(object);
                     object.traverse((obj) => {
                       if (obj instanceof THREE.Mesh) {
@@ -263,6 +262,9 @@ class UseThree {
                         // obj.renderOrder = 1;
                       }
                     });
+                    if (isBlender) {
+                      object = object.children[0];
+                    }
                     object.animations = gltf.animations;
                     object.name = modalNameStr;
                     group?.add(object);
@@ -280,7 +282,10 @@ class UseThree {
                 if (file && file.path) {
                   gltfLoader.load(`${baseApiUrl}/sys/common/static/${file.path}`, async (glft) => {
                     if (glft) {
-                      const object = glft.scene;
+                      let object: THREE.Object3D = glft.scene;
+                      if (isBlender) {
+                        object = object.children[0];
+                      }
                       object.name = modalNameStr;
                       if (glft.animations.length > 0) {
                         object.animations = glft.animations;

+ 5 - 5
src/views/system/menu/menu.data.ts

@@ -3,7 +3,7 @@ import { FormSchema } from '/@/components/Table';
 import { h } from 'vue';
 import { Icon } from '/@/components/Icon';
 import { duplicateCheck } from '../user/user.api';
-import { ajaxGetDictItems ,checkPermDuplication } from './menu.api';
+import { ajaxGetDictItems, checkPermDuplication } from './menu.api';
 import { render } from '/@/utils/common/renderUtils';
 
 const isDir = (type) => type === 0;
@@ -103,7 +103,7 @@ export const formSchema: FormSchema[] = [
             },
           ]);
           //update-begin---author:wangshuai ---date:20220729  for:[VUEN-1834]只有一级菜单,才默认值,子菜单的时候,清空------------
-          if (isMenu(e) && !formModel.id && (formModel.component=='layouts/default/index' || formModel.component=='layouts/RouteView')) {
+          if (isMenu(e) && !formModel.id && (formModel.component == 'layouts/default/index' || formModel.component == 'layouts/RouteView')) {
             formModel.component = '';
           }
           //update-end---author:wangshuai ---date:20220729  for:[VUEN-1834]只有一级菜单,才默认值,子菜单的时候,清空------------
@@ -145,8 +145,8 @@ export const formSchema: FormSchema[] = [
     //update-begin-author:liusq date:2023-06-06 for: [issues/5008]子表数据权限设置不生效
     ifShow: ({ values }) => !(values.component === ComponentTypes.IFrame && values.internalOrExternal),
     //update-begin-author:zyf date:2022-11-02 for: 聚合路由允许路径重复
-     dynamicRules: ({ model, schema,values }) => {
-       return checkPermDuplication(model, schema,  values.menuType !== 2?true:false);
+    dynamicRules: ({ model, schema, values }) => {
+      return checkPermDuplication(model, schema, values.menuType !== 2 ? true : false);
     },
     //update-end-author:zyf date:2022-11-02 for: 聚合路由允许路径重复
     //update-end-author:liusq date:2022-06-06 for:  [issues/5008]子表数据权限设置不生效
@@ -158,7 +158,7 @@ export const formSchema: FormSchema[] = [
     componentProps: {
       placeholder: '请输入前端组件',
     },
-    defaultValue:'layouts/default/index',
+    defaultValue: 'layouts/default/index',
     required: true,
     ifShow: ({ values }) => !isButton(values.menuType),
   },

+ 18 - 8
src/views/vent/deviceManager/comment/warningTabel/BaseModal.vue

@@ -4,7 +4,7 @@
       <template #monitor="{ model, field }">
         <div class="vent-flex-row-between">
           <Select ref="selectRef" disabled v-model:value="pointData" :options="option" style="width: calc(100% - 65px)" />
-          <a-button class="vent-margin-b-5" type="primary" @click="selectPoint(model['strtype'])" style="position: absolute; right: 0; top: 1px"
+          <a-button class="vent-margin-b-5" type="primary" @click="selectPoint(model['deviceType'])" style="position: absolute; right: 0; top: 1px"
             >选择</a-button
           >
         </div>
@@ -36,7 +36,7 @@
   const emit = defineEmits(['add', 'update', 'register']);
   const option = ref<any[]>([]);
   const devicePointList = ref<any[]>([]);
-  const pointData = ref<String[]>([]);
+  const pointData = ref<string[]>([]);
   const title = ref('');
   const isUpdate = ref(false);
   // 注册 form
@@ -50,18 +50,27 @@
     isUpdate.value = unref(data.isUpdate);
     title.value = unref(data.title);
     await resetFields();
+    pointData.value = [];
     if (data.isUpdate) {
+      //
+      await getDevicePointList(data.record['deviceType']);
+      devicePointList.value.forEach((item) => {
+        if (item['id'] == data.record['monitorId']) {
+          setPoint([item]);
+        }
+      });
       await setFieldsValue({ ...data.record });
       pointData.value = [data.record['monitorId']];
-
-      await getDevicePointList(data.record['deviceId']);
+      // 初始打开有数据时候要查点表
+    }
+    if (data.record) {
+      await getDevicePointList(data.record['deviceType']);
       devicePointList.value.forEach((item) => {
-        if (item['id'] == pointData.value) {
+        if (item['id'] == data.record['monitorId']) {
           setPoint([item]);
         }
       });
-      // 初始打开有数据时候要查点表
-    } else if (data.record) {
+      pointData.value = [data.record['monitorId']];
       await setFieldsValue({ relId: data.record['relId'] || data.record['id'], monitorId: '' });
     }
   });
@@ -70,7 +79,7 @@
 
   async function getDevicePointList(strtype) {
     try {
-      const result = await workFacePointList({ deviceType: strtype, valueType: props.monitorType });
+      const result = await workFacePointList({ deviceType: strtype, valueTypes: '2,3,9' });
       devicePointList.value = result;
     } catch (error) {
       devicePointList.value = [];
@@ -109,6 +118,7 @@
   }
 
   function setPoint(value) {
+    debugger;
     const data = value[0];
     option.value = [
       {

+ 1 - 1
src/views/vent/deviceManager/comment/warningTabel/BaseModal1.vue

@@ -71,7 +71,7 @@
 
   async function getDevicePointList(strtype) {
     try {
-      const result = await workFacePointList({ deviceType: strtype, valueType: props.monitorType });
+      const result = await workFacePointList({ deviceType: strtype, valueTypes: '2,3,9' });
       devicePointList.value = result;
     } catch (error) {
       devicePointList.value = [];

+ 2 - 1
src/views/vent/deviceManager/comment/warningTabel/index2.vue

@@ -1,8 +1,9 @@
 <template>
+  <!-- 预警条目管理 -->
   <div class="">
     <BasicTable @register="registerTable" :columns="workFaceWarningColumns">
       <template #tableTitle>
-        <a-button preIcon="ant-design:plus-outlined" type="primary" @click="openModal()">新增</a-button>
+        <a-button preIcon="ant-design:plus-outlined" type="primary" @click="openModal(true, {})">新增</a-button>
       </template>
       <template #action="{ record }">
         <a class="table-action-link" @click="openModalFn(record)">编辑</a>

+ 6 - 4
src/views/vent/deviceManager/comment/warningTabel/index3.vue

@@ -1,4 +1,5 @@
 <template>
+  <!-- 配置预警设备 -->
   <div class="warning-device-box">
     <div class="warning-box">
       <div v-for="item in warningList" class="link-item" :class="{ 'active-device-title': item.id == activeID }" :key="item.id">
@@ -6,9 +7,9 @@
       </div>
     </div>
     <div class="device-box">
-      <a-button class="vent-margin-b-5" type="primary" @click="handleOpen"> 新增 </a-button>
-      <a-table v-if="show" :columns="MonitorColumns" :data-source="dataSource" bordered :scroll="{ y: 500 }" :pagination="false">
-        <template #bodyCell="{ column, record }">
+      <a-button class="vent-margin-b-5" type="primary" @click="handleOpen(true, {})"> 新增 </a-button>
+      <a-table :columns="MonitorColumns" :data-source="dataSource" bordered :scroll="{ y: 500 }" :pagination="false">
+        <template v-if="show" #bodyCell="{ column, record }">
           <template v-if="column.dataIndex === 'operation'">
             <a class="action-link" @click="handleOpen('update', record)">编辑</a>
             <a class="action-link vent-margin-l-10" @click="handleDelete(record)">删除</a>
@@ -45,12 +46,13 @@
 
   function selectWarning(id) {
     activeID.value = id;
+    // 查询该条目的下预警设备列表
+    getDataSource();
   }
 
   async function getWarningList() {
     const result = await warningLogList({ sysId: props.deviceId, pageSize: 100000 }); //id: props.deviceId
     warningList.value = result.records;
-
     activeID.value = warningList.value[0]['id'];
   }
 

+ 22 - 3
src/views/vent/deviceManager/comment/warningTabel/warning.data.ts

@@ -2,6 +2,7 @@ import { BasicColumn, FormSchema } from '/@/components/Table';
 import { initDictOptions } from '/@/utils/dict';
 import type { TableColumnType } from 'ant-design-vue';
 import { workFaceDeviceList } from './warning.api';
+import { render } from '/@/utils/common/renderUtils';
 
 export const levelColumns: BasicColumn[] = [
   {
@@ -197,12 +198,17 @@ export const workFaceWarningColumns: BasicColumn[] = [
   },
   {
     title: '预警等级',
-    dataIndex: 'alarmLevel',
+    dataIndex: 'alarmLevel_dictText',
     align: 'center',
   },
   {
     title: '所属系统',
-    dataIndex: 'systemType',
+    dataIndex: 'systemType_dictText',
+    align: 'center',
+  },
+  {
+    title: '预警类型',
+    dataIndex: 'alarmType_dictText',
     align: 'center',
   },
   {
@@ -231,10 +237,17 @@ export const workFaceWarningFormSchemas: FormSchema[] = [
     required: true,
   },
   {
+    label: '预警类型',
+    field: 'alarmType',
+    component: 'JDictSelectTag',
+    componentProps: { dictCode: 'alarmType' },
+  },
+  {
     label: '预警等级',
     field: 'alarmLevel',
     component: 'JDictSelectTag',
     componentProps: { dictCode: 'leveltype' },
+    required: true,
   },
   {
     label: '所属系统',
@@ -401,6 +414,12 @@ export const monitorWarningFormSchemas = (param) =>
       show: false,
     },
     {
+      label: 'deviceType',
+      field: 'deviceType',
+      component: 'Input',
+      show: false,
+    },
+    {
       label: '点表',
       field: 'strtype',
       component: 'Input',
@@ -433,7 +452,7 @@ export const monitorWarningFormSchemas = (param) =>
       field: 'monitorId',
       component: 'Select',
       slot: 'monitor',
-      required: true,
+      // required: true,
     },
     {
       label: '报警上限值',

+ 3 - 0
src/views/vent/deviceManager/configurationTable/adapters.ts

@@ -21,6 +21,9 @@ export function parseModuleData(listData: { moduleData: ModuleData; showStyle: S
   _.forEach(listData.moduleData, (v, k) => {
     listData[`moduleData.${k}`] = JSON.stringify(v);
   });
+  _.forEach(listData.showStyle, (v, k) => {
+    listData[`showStyle.${k}`] = v;
+  });
 
   return listData;
 }

+ 10 - 10
src/views/vent/deviceManager/configurationTable/configuration.api.ts

@@ -1,6 +1,7 @@
-import { parseFormDataToParams } from './adapters';
+import { parseFormDataToParams, parseModuleData } from './adapters';
 import { Config } from './types';
 import { defHttp } from '/@/utils/http/axios';
+import _ from 'lodash-es';
 
 enum Api {
   list = '/safety/configurationData/getConfigurationDataList',
@@ -13,16 +14,15 @@ enum Api {
  * 列表接口
  * @param params
  */
-export function list(params: unknown): Promise<{ records: Config[] }> {
-  return defHttp.post({ url: Api.list, data: params }, { joinParamsToUrl: true });
-}
-// defHttp.post({ url: Api.list, params }).then((result) => {
-//   result.records.forEach((item) => {
-//     parseModuleData(item);
-//   });
+export function list(params: any): Promise<{ records: Config[] }> {
+  return defHttp.post({ url: Api.list, params: _.omitBy(params, _.isNil) }).then((result) => {
+    result.records.forEach((item) => {
+      parseModuleData(item);
+    });
 
-//   return result;
-// });
+    return result;
+  });
+}
 
 /**
  * 删除配置项

+ 13 - 0
src/views/vent/deviceManager/configurationTable/configuration.data.ts

@@ -21,6 +21,10 @@ export const columns: BasicColumn[] = [
     dataIndex: 'moduleData.main',
   },
   {
+    title: '模块页头配置',
+    dataIndex: 'moduleData.header',
+  },
+  {
     title: '模块图表配置',
     dataIndex: 'moduleData.chart',
   },
@@ -107,6 +111,15 @@ export const formSchema: FormSchema[] = [
     },
   },
   {
+    label: '模块页头配置',
+    field: 'moduleData.header',
+    component: 'JAddInput',
+    componentProps: {
+      min: 0,
+      placeholders: ['请输入点位', '请输入名称'],
+    },
+  },
+  {
     label: '模块图表配置',
     field: 'moduleData.chart',
     component: 'JAddInput',

+ 1 - 1
src/views/vent/deviceManager/configurationTable/index.vue

@@ -9,7 +9,7 @@
       :deleteById="deleteById"
       :saveOrUpdate="saveOrUpdate"
       title="配置列表"
-      :showTab="true"
+      :showTab="false"
       :deviceType="deviceType"
     >
       <template #filterCell="{ column, record }">

+ 1 - 0
src/views/vent/deviceManager/configurationTable/types.ts

@@ -6,6 +6,7 @@ export interface Config {
   showStyle: ShowStyle;
 }
 export interface ModuleData {
+  header?: Record<string, string>;
   main?: Record<string, string>;
   chart?: Record<string, string>;
 }

+ 21 - 28
src/views/vent/home/configurable/components/AirVolumeMonitor.vue

@@ -9,7 +9,7 @@
       </div>
     </div>
   </CostumeHeader> -->
-    <PictorialBar :option="chartOption" :series-prop-type="seriesPropType" x-axis-prop-type="x" :chart-data="chartData" height="100%" />
+    <PictorialBar :option="chartOption" series-prop-type="y" x-axis-prop-type="x" :chart-data="chartData" height="100%" />
     <!-- <div class="flex justify-around mt-10px">
     <MiniBoard v-for="item in configs" :key="item.prop" :label="item.label" :value="selectedDevice[item.prop]" />
   </div> -->
@@ -19,51 +19,44 @@
   import { computed, onMounted, ref } from 'vue';
   import PictorialBar from '/@/components/chart/PictorialBar.vue';
   import { EChartsOption, graphic } from 'echarts';
-  import { useInitConfig } from '../hooks/useInit';
+  import { useInitScene } from '../hooks/useInit';
   import _ from 'lodash-es';
+  import { get } from '../../billboard/utils';
   import ModuleBasic from './moduleBasic.vue';
   // import mapComponent from './components/3Dmap/index.vue';
 
   // 设备类别,是个枚举 TODO: 将手动换为自动获取类别
-  const devicekind = 'fanlocal';
+  const devicekind = 'sys_wind';
 
   const config = ref({
     moduleName: '矿井风量实时监测',
+    moduleData: {
+      chart: {
+        x: 'stationname',
+        y: 'readData.m3',
+      },
+    },
     showStyle: {
       size: 'width:1000px;height:280px;',
       position: 'left:460px;top:640px;',
       version: 'enhanced',
     },
   });
-  const { config: remoteConfig, fetchConfig } = useInitConfig(devicekind);
+  // const { config: remoteConfig, fetchConfig } = useInitConfig(devicekind);
+  const { scene, fetchScene } = useInitScene(devicekind);
 
-  onMounted(() => {
-    fetchConfig();
+  const chartData = computed(() => {
+    return scene.value.map((ele) => {
+      return {
+        x: get(ele, get(config.value, 'moduleData.chart.x', 'x')),
+        y: get(ele, get(config.value, 'moduleData.chart.y', 'y')),
+      };
+    });
   });
 
-  // 适用于 PictorialBar 的 prop,即从配置中选取第一项作取值依赖
-  const seriesPropType = computed(() => {
-    if (remoteConfig.value.moduleData?.chart) {
-      return Object.keys(remoteConfig.value.moduleData?.chart)[0];
-    } else {
-      return 'y';
-    }
-  });
-
-  const chartData = ref<any[]>([
-    { valueA: 1, y: 1, x: 2 },
-    { valueA: 1, y: 1, x: 3 },
-    { valueA: 1, y: 1, x: 4 },
-    { valueA: 1, y: 1, x: 5 },
-    { valueA: 2, y: 2, x: 6 },
-    { valueA: 3, y: 1, x: 7 },
-    { valueA: 1, y: 1, x: 8 },
-  ]);
-
-  function fetchChartData() {}
-
   onMounted(() => {
-    fetchChartData();
+    // fetchConfig();
+    fetchScene();
   });
 
   // 图表的配置项

+ 35 - 33
src/views/vent/home/configurable/components/DeviceWarning.vue

@@ -8,9 +8,9 @@
       </template>
       <div class="w-200px flex flex-items-center">
         <RightCircleOutlined class="w-30px" />
-        <div class="flex-grow-1">
-          网络断开
-          <span> {{ warns.length }}条 </span>
+        <div v-for="(label, prop) in config.moduleData.header" :key="prop" class="flex-grow-1">
+          {{ label }}
+          <span> {{ get(scene, prop) }}条 </span>
         </div>
       </div>
     </CostumeHeader>
@@ -26,17 +26,20 @@
   </ModuleBasic>
 </template>
 <script lang="ts" setup>
-  import { onMounted, ref } from 'vue';
+  import { computed, onMounted, ref } from 'vue';
   // import { list as cfgList } from '@/views/vent/deviceManager/configurationTable/configuration.api';
   // import { list } from '@/views/vent/deviceManager/deviceTable/device.api';
   import ModuleBasic from './moduleBasic.vue';
   import CostumeHeader from './CostumeHeader.vue';
   import { RightCircleOutlined } from '@ant-design/icons-vue';
+  import { useInitScene } from '../hooks/useInit';
+  import { get } from '../../billboard/utils';
+  import _ from 'lodash-es';
   // import MiniBoard from './MiniBoard.vue';
   // import mapComponent from './components/3Dmap/index.vue';
 
   // 设备类别,是个枚举 TODO: 将手动换为自动获取类别
-  // const devicekind = 'fanlocal';
+  const devicekind = 'warn';
 
   // const configs = ref<{ prop: string; label: string }[]>([]);
   // function fetchConfig() {
@@ -53,7 +56,19 @@
   //   });
   // }
   const config = ref({
-    moduleName: '采煤工作面智能管控',
+    moduleName: '设备告警',
+    moduleData: {
+      header: {
+        'netstatus.val': '网络断开',
+      },
+      main: {
+        'red.val': '严重',
+        'orange.val': '非常严重',
+        'yellow.val': '较严重',
+        'blue.val': '一般严重',
+        'alarm.val': '报警',
+      },
+    },
     showStyle: {
       size: 'width:450px;height:280px;',
       position: 'right:0px;top:640px;',
@@ -61,36 +76,23 @@
     },
   });
   // const { config: remoteConfig, fetchConfig } = useInitConfig(devicekind);
+  const { scene, fetchScene } = useInitScene(devicekind);
 
-  const warns = ref([
-    {
-      label: 'test',
-      count: 0,
-      color: 'red',
-    },
-    {
-      label: 'test',
-      count: 0,
-      color: 'orange',
-    },
-    {
-      label: 'test',
-      count: 0,
-      color: 'yellow',
-    },
-    {
-      label: 'test',
-      count: 0,
-      color: 'green',
-    },
-    {
-      label: 'test',
-      count: 0,
-      color: 'blue',
-    },
-  ]);
+  const warns = computed(() => {
+    const colors = ['red', 'orange', 'yellow', 'green', 'blue'];
+    let i = -1;
+    return _.map(config.value.moduleData.main || [], (label, prop) => {
+      i += 1;
+      return {
+        label,
+        count: get(scene, prop),
+        color: colors[i],
+      };
+    });
+  });
 
   onMounted(() => {
+    fetchScene();
     // fetchConfig();
   });
 </script>

+ 30 - 31
src/views/vent/home/configurable/components/VentilateAnalysis.vue

@@ -12,7 +12,7 @@
     <Pie :option="chartOption" :chart-data="chartData" height="140px" />
     <div class="flex justify-around mt-10px">
       <MiniBoard
-        v-for="(label, prop) in remoteConfig.moduleData?.main"
+        v-for="(label, prop) in config.moduleData?.main"
         :key="`vhccva-${prop}`"
         :label="label"
         :value="get(selectedDevice, prop)"
@@ -24,10 +24,10 @@
 </template>
 <script lang="ts" setup>
   import CostumeHeader from './CostumeHeader.vue';
-  import { onMounted, ref } from 'vue';
+  import { computed, onMounted, ref } from 'vue';
   import Pie from '/@/components/chart/Pie.vue';
   import { EChartsOption } from 'echarts';
-  import { useInitConfig, useInitDevices } from '../hooks/useInit';
+  import { useInitDevices } from '../hooks/useInit';
   import { get } from '../../billboard/utils';
   import _ from 'lodash-es';
   import MiniBoard from './MiniBoard.vue';
@@ -35,51 +35,50 @@
   // import mapComponent from './components/3Dmap/index.vue';
 
   // 设备类别,是个枚举 TODO: 将手动换为自动获取类别
-  const devicekind = 'fanlocal';
+  const devicekind = 'sys_majorpath';
 
   const config = ref({
-    moduleName: '通风系统监测与分析',
+    moduleName: '关键通风路线', // 通风系统监测与分析
+    moduleData: {
+      main: {
+        // m3_total: '总风量',
+        // drag_total: '总阻力',
+        // dengjikong: '等积孔',
+        'majorpath.drag_1': '阻力1',
+        'majorpath.drag_2': '阻力2',
+        'majorpath.drag_3': '阻力3',
+      },
+      chart: {
+        'majorpath.drag_1': '阻力1',
+        'majorpath.drag_2': '阻力2',
+        'majorpath.drag_3': '阻力3',
+      },
+    },
     showStyle: {
       size: 'width:450px;height:280px;',
       position: 'right:0px;top:60px;',
       version: 'enhanced',
     },
   });
-  const { config: remoteConfig, fetchConfig } = useInitConfig(devicekind);
+  // const { config: remoteConfig, fetchConfig } = useInitConfig(devicekind);
   const { options, selectedDevice, selectedDeviceID, fetchDevices } = useInitDevices(devicekind);
 
   onMounted(() => {
-    fetchConfig();
+    // fetchConfig();
     fetchDevices();
   });
 
-  const chartData = ref<any[]>([
-    {
-      value: 70,
-      name: 'A',
-    },
-    {
-      value: 30,
-      name: 'B',
-    },
-  ]);
-
-  function fetchChartData() {
-    return;
-    Promise.resolve({ a: 3, b: 7 }).then((res) => {
-      chartData.value = _.map(remoteConfig.value.moduleData?.chart || [], (label, prop) => {
-        return {
-          value: _.get(res, prop),
-          name: label,
-        };
-      });
+  const chartData = computed(() => {
+    return _.map(config.value.moduleData?.chart || [], (label, prop) => {
+      return {
+        value: parseInt(get(selectedDevice.value, prop, 0)),
+        name: label,
+      };
     });
-  }
-
-  onMounted(() => {
-    fetchChartData();
   });
 
+  onMounted(() => {});
+
   // 图表配置项
   const chartOption: EChartsOption = {
     series: [

+ 12 - 14
src/views/vent/home/configurable/components/VentilateControl.vue

@@ -1,14 +1,12 @@
 <!-- eslint-disable vue/multi-word-component-names -->
 <template>
   <ModuleBasic :title="config.moduleName" :version="config.showStyle?.version" :size="config.showStyle?.size" :position="config.showStyle?.position">
-    <CostumeHeader v-model:value="selectedDeviceID" :options="options">
-      <div class="w-200px flex flex-items-center">
-        <RightCircleOutlined class="w-30px" />
-        <div class="flex-grow-1">
-          {{ selectedDevice.strinstallpos }}
-        </div>
-      </div>
-    </CostumeHeader>
+    <!-- <CostumeHeader v-model:value="selectedDeviceID" :options="options">
+      <template #select>
+        <div></div>
+      </template>
+      <div> </div>
+    </CostumeHeader> -->
     <!-- <div class="flex justify-around mt-10px">
     <MiniBoard v-for="item in configs" :key="item.prop" :label="item.label" :value="selectedDevice[item.prop]" />
   </div> -->
@@ -16,16 +14,16 @@
 </template>
 <script lang="ts" setup>
   import { onMounted, ref } from 'vue';
-  import CostumeHeader from './CostumeHeader.vue';
-  import { RightCircleOutlined } from '@ant-design/icons-vue';
+  // import CostumeHeader from './CostumeHeader.vue';
+  // import { RightCircleOutlined } from '@ant-design/icons-vue';
   import ModuleBasic from './moduleBasic.vue';
   // import MiniBoard from './MiniBoard.vue';
-  import { useInitDevices } from '../hooks/useInit';
+  // import { useInitDevices } from '../hooks/useInit';
   // import { get } from '../../billboard/utils';
   // import mapComponent from './components/3Dmap/index.vue';
 
   // 设备类别,是个枚举 TODO: 将手动换为自动获取类别
-  const devicekind = 'fanlocal';
+  // const devicekind = 'fanlocal';
 
   const config = ref({
     moduleName: '通风设施远程控制',
@@ -36,11 +34,11 @@
     },
   });
   // const { configs, fetchConfig } = useInitConfig(devicekind);
-  const { options, selectedDevice, selectedDeviceID, fetchDevices } = useInitDevices(devicekind);
+  // const { options, selectedDevice, selectedDeviceID, fetchDevices } = useInitDevices(devicekind);
 
   onMounted(() => {
     // fetchConfig();
-    fetchDevices();
+    // fetchDevices();
   });
 </script>
 <style scoped></style>

+ 26 - 30
src/views/vent/home/configurable/components/WorkSurface.vue

@@ -12,14 +12,14 @@
     <LineMulti
       :option="chartOption"
       :prop-type-arr="propTypeArr"
-      x-axis-prop-type="x"
+      x-axis-prop-type="time"
       :chart-data="chartData"
       height="140px"
       class="worksurface-chart"
     />
     <div class="flex justify-around">
       <MiniBoard
-        v-for="(label, prop) in remoteConfig.moduleData?.main"
+        v-for="(label, prop) in config.moduleData?.main"
         :key="`vhccws-${prop}`"
         :label="label"
         :value="get(selectedDevice, prop)"
@@ -34,7 +34,7 @@
   import CostumeHeader from './CostumeHeader.vue';
   import { computed, onMounted, ref } from 'vue';
   import { EChartsOption } from 'echarts';
-  import { useInitConfig, useInitDevices } from '../hooks/useInit';
+  import { useInitDevices } from '../hooks/useInit';
   import { get } from '../../billboard/utils';
   import _ from 'lodash-es';
   import MiniBoard from './MiniBoard.vue';
@@ -42,53 +42,49 @@
   // import mapComponent from './components/3Dmap/index.vue';
 
   // 设备类别,是个枚举 TODO: 将手动换为自动获取类别
-  const devicekind = 'fanlocal';
+  const devicekind = 'sys_surface_caimei';
 
   const config = ref({
     moduleName: '采煤工作面智能管控',
+    moduleData: {
+      main: {
+        jin: '进风',
+        hui: '回风',
+        xufengliang: '需风量',
+      },
+      // 这里的配置比较特殊,需要配置为数据中 history 对象下的取值路径。无法针对 x 轴进行配置
+      // 例如数据为 { history: [ jin: 10 ] },那么需要配置为 jin
+      chart: {
+        hui: '回风量',
+        jin: '进风量',
+      },
+    },
     showStyle: {
       size: 'width:450px;height:280px;',
       position: 'right:0px;top:350px;',
       version: 'enhanced',
     },
   });
-  const { config: remoteConfig, fetchConfig } = useInitConfig(devicekind);
+  // const { config: remoteConfig, fetchConfig } = useInitConfig(devicekind);
   const { options, selectedDevice, selectedDeviceID, fetchDevices } = useInitDevices(devicekind);
 
   onMounted(() => {
-    fetchConfig();
+    // fetchConfig();
     fetchDevices();
   });
 
-  const chartData = ref<any[]>([
-    { valueA: 1, valueB: 3, x: 2 },
-    { valueA: 2, valueB: 1, x: 3 },
-    { valueA: 1, valueB: 1, x: 4 },
-    { valueA: 3, valueB: 2, x: 5 },
-    { valueA: 2, valueB: 1, x: 6 },
-    { valueA: 1, valueB: 2, x: 7 },
-  ]);
+  const chartData = computed(() => {
+    return selectedDevice.value.history || [];
+  });
 
   const propTypeArr = computed(() => {
-    if (remoteConfig.value.moduleData?.chart) {
-      const map = new Map();
-      _.forEach(remoteConfig.value.moduleData?.chart || [], (label, prop) => {
+    const map = new Map();
+    if (config.value.moduleData?.chart) {
+      _.forEach(config.value.moduleData?.chart || [], (label, prop) => {
         map.set(prop, label);
       });
-
-      return map;
-    } else {
-      return new Map([
-        ['valueA', '值A'],
-        ['valueB', '值B'],
-      ]);
     }
-  });
-
-  function fetchChartData() {}
-
-  onMounted(() => {
-    fetchChartData();
+    return map;
   });
 
   // 图表相关

+ 17 - 1
src/views/vent/home/configurable/configurable.api.ts

@@ -4,10 +4,26 @@ enum Api {
   list = '/ventanaly-device/safety/ventanalyDevice/homedata2',
   getHomeData = '/ventanaly-device/safety/ventanalyDevice/homedata',
 }
+
+// 搞这个缓存是由于:目前代码上的设计是多个模块发出多次请求,每个模块自己负责消费前者的响应。
+// 这会导致相同的请求被同时发送多次。
+const cache = new Map<string, Promise<any>>();
+
 /**
  * 列表接口
  * @param params
  */
 export const list = (params) => defHttp.post({ url: Api.list, params });
 
-export const getHomeData = (params) => defHttp.post({ url: Api.getHomeData, params });
+export const getHomeData = (params) => {
+  const key = `${Api.getHomeData}?${JSON.stringify(params)}`;
+  if (!cache.has(key)) {
+    cache.set(
+      key,
+      defHttp.post({ url: Api.getHomeData, params }).finally(() => {
+        cache.delete(key);
+      })
+    );
+  }
+  return cache.get(key) as Promise<any>;
+};

+ 41 - 8
src/views/vent/home/configurable/hooks/useInit.ts

@@ -1,7 +1,8 @@
 import { computed, ref } from 'vue';
 import { list as cfgList } from '@/views/vent/deviceManager/configurationTable/configuration.api';
-import { list } from '@/views/vent/deviceManager/deviceTable/device.api';
+// import { list } from '@/views/vent/deviceManager/deviceTable/device.api';
 import { Config } from '@/views/vent/deviceManager/configurationTable/types';
+import { getHomeData } from '../configurable.api';
 // import mapComponent from './components/3Dmap/index.vue';
 
 export function useInitConfig(deviceType: string) {
@@ -28,25 +29,38 @@ export function useInitDevices(devicekind: string) {
   const selectedDevice = computed(() => {
     return (
       devices.value.find((e) => {
-        return e.id === selectedDeviceID.value;
+        return e.deviceID === selectedDeviceID.value;
       }) || {}
     );
   });
 
   // 获取设备数据,赋值并以选项格式返回给 Header 消费
   function fetchDevices() {
-    return list({
-      devicekind,
-    }).then(({ records }) => {
+    return getHomeData({}).then((result) => {
+      if (!result[devicekind]) return;
+      // 如果数据只有一条,转为数据
+      const records: { strinstallpos?: string; deviceID: string; devicePos?: string }[] = result[devicekind];
       devices.value = records;
-      selectedDeviceID.value = records[0]?.id;
+      selectedDeviceID.value = records[0]?.deviceID;
       options.value = records.map((e) => {
         return {
-          label: e.strinstallpos,
-          value: e.id,
+          label: e.strinstallpos || e.devicePos || '/',
+          value: e.deviceID,
         };
       });
     });
+    // return list({
+    //   // devicekind,
+    // }).then(({ records }) => {
+    //   devices.value = records;
+    //   selectedDeviceID.value = records[0]?.id;
+    //   options.value = records.map((e) => {
+    //     return {
+    //       label: e.strinstallpos,
+    //       value: e.id,
+    //     };
+    //   });
+    // });
   }
 
   return {
@@ -56,3 +70,22 @@ export function useInitDevices(devicekind: string) {
     options,
   };
 }
+
+export function useInitScene(scenekind: string) {
+  const scene = ref<Record<string, any>[]>([]);
+
+  // 获取设备数据,赋值并以选项格式返回给 Header 消费
+  function fetchScene() {
+    return getHomeData({}).then((result) => {
+      if (!result[scenekind]) return;
+      // 如果数据只有一条,转为数据
+      const records: { strinstallpos: string; deviceID: string }[] = result[scenekind];
+      scene.value = records;
+    });
+  }
+
+  return {
+    fetchScene,
+    scene,
+  };
+}

+ 2 - 2
src/views/vent/monitorManager/fanLocalMonitor/index.vue

@@ -571,12 +571,12 @@
       {
         key: 'windPower',
         value: '风电闭锁',
-        permission: 'fanLocal:control',
+        permission: 'fanLocal:fdbs',
       },
       {
         key: 'gasPower',
         value: '瓦斯电闭锁',
-        permission: 'fanLocal:control',
+        permission: 'fanLocal:wsdbs',
       },
       {
         key: 'needAir',

+ 40 - 57
src/views/vent/monitorManager/gateMonitor/gate.threejs.xr.ts

@@ -41,46 +41,18 @@ class FmXR {
   }
 
   addLight() {
-    const directionalLight = new THREE.DirectionalLight(0xffffff, 1.5);
-    directionalLight.position.set(344, 690, 344);
-    this.group?.add(directionalLight);
-    directionalLight.target = this.group as THREE.Object3D;
-
-    const pointLight2 = new THREE.PointLight(0xffeeee, 1, 300);
-    pointLight2.position.set(-4, 10, 1.8);
-    pointLight2.shadow.bias = 0.05;
-    this.group?.add(pointLight2);
-
-    const pointLight3 = new THREE.PointLight(0xffeeee, 1, 200);
-    pointLight3.position.set(-0.5, -0.5, 0.75);
-    pointLight3.shadow.bias = 0.05;
-    this.group?.add(pointLight3);
-
-    // const pointLight4 = new THREE.PointLight(0xffeeee, 1, 150);
-    // pointLight4.position.set(4.3, 1, -0.9);
-    // pointLight4.shadow.bias = 0.05;
-    // this.group?.add(pointLight4);
-
-    // const pointLight5 = new THREE.PointLight(0xffeeee, 1, 150);
-    // pointLight5.position.set(4.3, 1, -0.9);
-    // pointLight5.shadow.bias = 0.05;
-    // this.group?.add(pointLight5);
-
-    // const pointLight6 = new THREE.PointLight(0xffeeee, 1, 150);
-    // pointLight6.position.set(-4.4, 1, -0.9);
-    // pointLight6.shadow.bias = 0.05;
-    // this.group?.add(pointLight6);
-
-    // const pointLightHelper2 = new THREE.PointLightHelper(pointLight2, 1);
-    // this.model.scene?.add(pointLightHelper2);
-
-    // gui.add(pointLight2.position, 'x', -300, 300);
-    // gui.add(pointLight2.position, 'y', -300, 300);
-    // gui.add(pointLight2.position, 'z', -300, 300);
-
-    // gui.add(pointLight3.position, 'x', -300, 300);
-    // gui.add(pointLight3.position, 'y', -300, 300);
-    // gui.add(pointLight3.position, 'z', -300, 300);
+    // const directionalLight = new THREE.DirectionalLight(0xffffff, 1.5);
+    // directionalLight.position.set(344, 690, 344);
+    // this.group?.add(directionalLight);
+    // directionalLight.target = this.group as THREE.Object3D;
+    // const pointLight2 = new THREE.PointLight(0xffeeee, 1, 300);
+    // pointLight2.position.set(-4, 10, 1.8);
+    // pointLight2.shadow.bias = 0.05;
+    // this.group?.add(pointLight2);
+    // const pointLight3 = new THREE.PointLight(0xffeeee, 1, 200);
+    // pointLight3.position.set(-0.5, -0.5, 0.75);
+    // pointLight3.shadow.bias = 0.05;
+    // this.group?.add(pointLight3);
   }
   // 重置摄像头
   resetCamera() {
@@ -106,7 +78,7 @@ class FmXR {
         color: '#00FF00',
         strokeStyle: '#007400',
         x: 120,
-        y: 100,
+        y: 95,
       },
       {
         text: `净通行高度(m):`,
@@ -162,7 +134,7 @@ class FmXR {
         color: '#00FF00',
         strokeStyle: '#007400',
         x: History_Type['type'] == 'remote' ? 80 : 20,
-        y: 325,
+        y: 330,
       },
     ];
 
@@ -184,8 +156,8 @@ class FmXR {
         const planeGeometry = new THREE.PlaneGeometry(526, 346); // 平面3维几何体PlaneGeometry
         const planeMesh = new THREE.Mesh(planeGeometry, textMaterial);
         planeMesh.name = 'monitorText';
-        planeMesh.scale.set(0.002, 0.002, 0.002);
-        planeMesh.position.set(3.685, 0.09, -0.41);
+        planeMesh.scale.set(0.0018, 0.0015, 0.0015);
+        planeMesh.position.set(2.975, 0.46, -0.33);
         this.group.add(planeMesh);
       }
       textMap.dispose();
@@ -284,16 +256,16 @@ class FmXR {
 
   /* 提取风门序列帧,初始化前后门动画 */
   initAnimation() {
-    const fmGroup = this.group?.getObjectByName('fmXr-door');
+    const fmGroup = this.group?.getObjectByName('fmXr-all');
     if (fmGroup) {
       const tracks = fmGroup.animations[0].tracks;
       const fontTracks: any[] = [],
         backTracks: any[] = [];
       for (let i = 0; i < tracks.length; i++) {
         const track = tracks[i];
-        if (track.name.startsWith('qianmen')) {
+        if (track.name.startsWith('Men_1')) {
           fontTracks.push(track);
-        } else if (track.name.startsWith('houmen')) {
+        } else if (track.name.startsWith('Men_2')) {
           backTracks.push(track);
         }
       }
@@ -335,7 +307,7 @@ class FmXR {
           handler = () => {
             this.clipActionArr.frontDoor.paused = true;
             this.clipActionArr.frontDoor.reset();
-            this.clipActionArr.frontDoor.time = 1.2;
+            this.clipActionArr.frontDoor.time = 0.5;
             this.clipActionArr.frontDoor.timeScale = timeScale;
             // this.clipActionArr.frontDoor.clampWhenFinished = true;
             this.clipActionArr.frontDoor.play();
@@ -364,7 +336,7 @@ class FmXR {
           handler = () => {
             this.clipActionArr.backDoor.paused = true;
             this.clipActionArr.backDoor.reset();
-            this.clipActionArr.backDoor.time = 1.2;
+            this.clipActionArr.backDoor.time = 0.5;
             this.clipActionArr.backDoor.timeScale = timeScale;
             // this.clipActionArr.backDoor.clampWhenFinished = true;
             this.clipActionArr.backDoor.play();
@@ -514,10 +486,17 @@ class FmXR {
   }
 
   setMeshHide() {
-    const wire = this.group.getObjectByName('fmXr-wire');
-    if (wire) {
-      if (wire.getObjectByName('对象192')) wire.getObjectByName('对象192').visible = false;
-      if (wire.getObjectByName('Box595')) wire.getObjectByName('Box595').visible = false;
+    const doorWire = this.group.getObjectByName('JuXingHangDao');
+    if (doorWire) {
+      this.backDamperOpenMesh = doorWire.getObjectByName('Dampler_open_1');
+      if (this.backDamperOpenMesh) this.backDamperOpenMesh.visible = false;
+      this.backDamperClosedMesh = doorWire.getObjectByName('Damper_Closed_1');
+      if (this.backDamperClosedMesh) this.backDamperClosedMesh.visible = true;
+
+      this.frontDamperOpenMesh = doorWire.getObjectByName('Damper_Open_2');
+      if (this.frontDamperOpenMesh) this.frontDamperOpenMesh.visible = false;
+      this.frontDamperClosedMesh = doorWire.getObjectByName('Damper_Closed_2');
+      if (this.frontDamperClosedMesh) this.frontDamperClosedMesh.visible = true;
     }
   }
 
@@ -525,13 +504,17 @@ class FmXR {
     this.group = new THREE.Object3D();
     this.group.name = this.modelName;
     return new Promise((resolve) => {
-      this.model.setGLTFModel(['fmXr-door', 'fmXr-wire', 'fmXr-wall'], this.group).then(() => {
+      // 小史行人风门 'fmXr-door', 'fmXr-wire', 'fmXr-wall
+      // this.model.setGLTFModel(['fmXr-door', 'fmXr-wire', 'fmXr-wall'], this.group).then(() => {
+      // 白工行人风门 'fmXr-all'
+      this.model.setGLTFModel(['fmXr-all'], this.group, true).then(() => {
+        console.log(this.group);
         this.setModalPosition();
-        // 初始化左右摇摆动画;
+        // // 初始化左右摇摆动画;
         this.initAnimation();
-        // this.drawHots();
+        // // this.drawHots();
         this.addLight();
-        // this.deviceDetailCard();
+        // // this.deviceDetailCard();
         this.model.animate();
         this.setMeshHide();
         resolve(this.model);

+ 0 - 6
src/views/vent/monitorManager/gateMonitor/index.vue

@@ -220,12 +220,6 @@
                     <a-tag v-else-if="record.warnLevel == '1001'" color="default">网络中断</a-tag>
                     <a-tag v-else color="green">正常</a-tag>
                   </template>
-                  <a-tag v-else-if="column.dataIndex === 'warnFlag'" :color="record.warnFlag == '0' ? 'green' : 'red'">{{
-                    record.warnFlag == '0' ? '正常' : '报警'
-                  }}</a-tag>
-                  <a-tag v-if="column.dataIndex === 'netStatus'" :color="record.netStatus == '0' ? '#f00' : 'green'">{{
-                    record.netStatus == '0' ? '断开' : '连接'
-                  }}</a-tag>
                 </template>
               </HistoryTable>
             </div>

+ 1 - 1
src/views/vent/monitorManager/nitrogen/components/nitrogenHome.vue

@@ -340,7 +340,7 @@
       mountedThree(monitorDataGroupArr).then(async () => {
         setMonitorGroupNum(1);
         getMonitor(true).then(async () => {
-          if (monitorData.value && monitorData.value['deviceID']) await getCamera(monitorData.value['deviceID'], playerRef.value, 'forcFan');
+          if (monitorData.value && monitorData.value['deviceID']) await getCamera(monitorData.value['deviceID'], playerRef.value);
         });
       });
     }, 0);

+ 1 - 1
src/views/vent/monitorManager/nitrogen/components/nitrogenHome1.vue

@@ -387,7 +387,7 @@
       mountedThree(deviceProperty.value.monitorDataGroupArr).then(async () => {
         setMonitorGroupNum(1);
         getMonitor(true).then(async () => {
-          if (selectData.value && selectData.value['deviceID']) await getCamera(selectData.value['deviceID'], playerRef.value, 'forcFan');
+          if (selectData.value && selectData.value['deviceID']) await getCamera(selectData.value['deviceID'], playerRef.value);
         });
       });
     }, 0);

+ 2 - 8
src/views/vent/monitorManager/windrectMonitor/index.vue

@@ -45,7 +45,7 @@
     </div>
     <div class="bottom-tabs-box" @mousedown="setDivHeight($event, 350, scroll)">
       <dv-border-box8 :dur="5" :style="`padding: 5px; height: ${scroll.y + 120}px`">
-        <div class="tabs-button-group">
+        <div v-if="hasPermission('windrect:handler')" class="tabs-button-group">
           <a-button class="tabs-button" type="primary" @click="openModel">一键测风</a-button>
           <a-button class="tabs-button" type="primary" @click="resetHandle">一键复位</a-button>
         </div>
@@ -107,13 +107,7 @@
           </a-tab-pane>
           <a-tab-pane key="4" tab="报警历史">
             <div class="tab-item" v-if="activeKey === '4'">
-              <AlarmHistoryTable
-                columns-type="alarm"
-                device-type="windrect"
-                designScope="alarm-history"
-                :device-list-api="getTableList"
-                :scroll="scroll"
-              />
+              <AlarmHistoryTable columns-type="alarm" device-type="windrect" designScope="alarm-history" :scroll="scroll" />
             </div>
           </a-tab-pane>
           <a-tab-pane v-if="hasPermission('windrect:result')" key="6" tab="测风结果">