Bladeren bron

束管监测、定位图标对接

hongrunxia 1 jaar geleden
bovenliggende
commit
450b3738fb

+ 6 - 6
.env.production

@@ -14,9 +14,9 @@ VITE_BUILD_COMPRESS = 'gzip'
 
 # 使用压缩时是否删除原始文件,默认为false
 VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE = false
-#VITE_PROXY = [["/jeecgsystem","http://47.94.222.6:9999"],["/upload","http://localhost:3300/upload"]]
+VITE_PROXY = [["/jeecgsystem","http://47.94.222.6:9999"],["/upload","http://localhost:3300/upload"]]
 #VITE_PROXY = [["/jeecgsystem","http://192.168.1.4:9999"],["/upload","http://localhost:3300/upload"]]
-VITE_PROXY = [["/jeecgsystem","http://192.168.0.79:9999"],["/upload","http://localhost:3300/upload"]]
+#VITE_PROXY = [["/jeecgsystem","http://192.168.0.79:9999"],["/upload","http://localhost:3300/upload"]]
 #VITE_PROXY = [["/jeecgsystem","http://42.194.132.36:8099"],["/upload","http://localhost:3300/upload"]]
 #VITE_PROXY = [["/jeecgsystem","http://192.168.0.30:8086"],["/upload","http://localhost:3300/upload"]]
 #VITE_PROXY = [["/jeecgsystem","http://127.0.0.1:9999"],["/upload","http://localhost:3300/upload"]]
@@ -26,9 +26,9 @@ VITE_GLOB_API_URL=/jeecgsystem
 
 #后台接口全路径地址(必填)
 #VITE_GLOB_DOMAIN_URL=http://jeecg-boot-system:8080/jeecg-boot
-#VITE_GLOB_DOMAIN_URL=http://47.94.222.6:9999
+VITE_GLOB_DOMAIN_URL=http://47.94.222.6:9999
 #VITE_GLOB_DOMAIN_URL=http://192.168.1.4:9999
-VITE_GLOB_DOMAIN_URL=http://192.168.0.79:9999
+#VITE_GLOB_DOMAIN_URL=http://192.168.0.79:9999
 #VITE_GLOB_DOMAIN_URL=http://127.0.0.1:9999
 #VITE_GLOB_DOMAIN_URL=http://42.194.132.36:8099
 #采育服务器
@@ -48,7 +48,7 @@ VITE_USE_PWA = false
 VITE_LEGACY = false
 
 #微前端qiankun应用,命名必须以VITE_APP_SUB_开头,jeecg-app-1为子应用的项目名称,也是子应用的路由父路径
-#VITE_APP_SUB_APP = [["micro-need-air", "//47.94.222.6:7123/"], ["micro-vent-3dModal", "//47.94.222.6:7121/"],["micro-fire-front", "//47.94.222.6:7124/"]]
+VITE_APP_SUB_APP = [["micro-need-air", "//47.94.222.6:7123/"], ["micro-vent-3dModal", "//47.94.222.6:7121/"],["micro-fire-front", "//47.94.222.6:7124/"]]
 #VITE_APP_SUB_APP = [["micro-vent-3dModal", "//192.168.0.79:7121/"]]
 #VITE_APP_SUB_APP = [["micro-need-air", "//127.0.0.1:20000/"], ["micro-vent-3dModal", "//127.0.0.1:30000/"], ["micro-fire-front", "//127.0.0.1:40000/"]]
-VITE_APP_SUB_APP = [["micro-need-air", "//127.0.0.1:7123/"], ["micro-vent-3dModal", "//127.0.0.1:7121/"]]
+#VITE_APP_SUB_APP = [["micro-need-air", "//127.0.0.1:7123/"], ["micro-vent-3dModal", "//127.0.0.1:7121/"]]

+ 11 - 2
src/App.vue

@@ -9,17 +9,18 @@
 </template>
 
 <script lang="ts" setup>
-  import { ref } from 'vue';
+  import { ref, watch } from 'vue';
   import { ConfigProvider } from 'ant-design-vue';
   import { AppProvider } from '/@/components/Application';
   import { useTitle } from '/@/hooks/web/useTitle';
   import { useLocale } from '/@/locales/useLocale';
   import AdaptiveContainer from '/@/components/Container/src/Adaptive.vue';
+  import { useAppStore } from '/@/store/modules/app';
 
   // 解决日期时间国际化问题
   import 'dayjs/locale/zh-cn';
 
-
+  const appStore = useAppStore();
   // support Multi-language
   const { getAntdLocale } = useLocale();
   const width = ref(1920);
@@ -30,6 +31,14 @@
     height.value = 1080;
   }
 
+  watch([()=> appStore.getWidthScale, () => appStore.getHeightScale], () => {
+    const popoverDomList = document.getElementsByClassName('zxm-popover')
+    Array.prototype.map.call(popoverDomList, dom => {
+      console.log('弹窗节点------>',dom,);
+      
+    })
+  })
+
   useTitle();
 </script>
 <style lang="less" scoped>

+ 3 - 0
src/assets/icons/alarm-warning.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="95.859" height="95.946" viewBox="0 0 95.859 95.946">
+  <path id="路径_55451" data-name="路径 55451" d="M79.592,91.7a5.946,5.946,0,0,0-3.036-1.63,1.484,1.484,0,0,1-1.209-1.452V54.176a26.985,26.985,0,1,0-53.969-.206V88.619a1.484,1.484,0,0,1-1.209,1.452,6,6,0,0,0-4.788,5.875H81.344A6.015,6.015,0,0,0,79.592,91.7ZM53.544,43.475,51.726,59.713h7.13L43.191,82.453l1.818-16.238h-7.14ZM48.363,19.489a3,3,0,0,1-3-3V3a3,3,0,1,1,6,0V16.491A3,3,0,0,1,48.363,19.489ZM26.625,27.744a3,3,0,0,1-4.095-1.1L15.784,14.963a3,3,0,1,1,5.191-3l6.746,11.684A3,3,0,0,1,26.625,27.744Zm43.475,0a3,3,0,0,0,4.095-1.1l6.746-11.684a3,3,0,1,0-5.191-3L69,23.649A3,3,0,0,0,70.1,27.744ZM19.363,41.686A2.993,2.993,0,0,1,15.691,43.8L2.657,40.318A3,3,0,1,1,4.2,34.527l13.033,3.495A2.992,2.992,0,0,1,19.363,41.686Zm58,0A2.993,2.993,0,0,0,81.035,43.8l13.033-3.495a3,3,0,0,0-1.555-5.79L79.479,38.013A3.008,3.008,0,0,0,77.362,41.686Z" transform="translate(-0.43)" fill="#fff"/>
+</svg>

+ 3 - 0
src/assets/icons/ch2val.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="158" height="104" viewBox="0 0 158 104">
+  <text id="C_H_" data-name="C₂H₄" transform="translate(0 84)" fill="#fff" font-size="78" font-family="Kingsoft_Cloud_Font"><tspan x="0" y="0">C</tspan><tspan y="0" font-family="SegoeUI-Bold, Segoe UI" font-weight="700">₂</tspan><tspan y="0">H</tspan><tspan y="0" font-family="SegoeUI-Bold, Segoe UI" font-weight="700">₄</tspan></text>
+</svg>

+ 3 - 0
src/assets/icons/chval.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="157" height="104" viewBox="0 0 157 104">
+  <text id="C_H_" data-name="C₂H₂" transform="translate(0 84)" fill="#fff" font-size="78" font-family="Kingsoft_Cloud_Font"><tspan x="0" y="0">C</tspan><tspan y="0" font-family="SegoeUI-Bold, Segoe UI" font-weight="700">₂</tspan><tspan y="0">H</tspan><tspan y="0" font-family="SegoeUI-Bold, Segoe UI" font-weight="700">₂</tspan></text>
+</svg>

+ 3 - 0
src/assets/icons/co2val.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="127" height="104" viewBox="0 0 127 104">
+  <text id="CO_" data-name="CO₂" transform="translate(0 84)" fill="#fff" font-size="78" font-family="Kingsoft_Cloud_Font"><tspan x="0" y="0">CO</tspan><tspan y="0" font-family="SegoeUI-Bold, Segoe UI" font-weight="700">₂</tspan></text>
+</svg>

+ 3 - 0
src/assets/icons/coval.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="96" height="78" viewBox="0 0 96 78">
+  <text id="CO" transform="translate(0 62)" fill="#fff" font-size="78" font-family="Kingsoft_Cloud_Font"><tspan x="0" y="0">CO</tspan></text>
+</svg>

+ 3 - 0
src/assets/icons/gasval.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="127" height="104" viewBox="0 0 127 104">
+  <text id="CH_" data-name="CH₄" transform="translate(0 84)" fill="#fff" font-size="78" font-family="Kingsoft_Cloud_Font"><tspan x="0" y="0">CH</tspan><tspan y="0" font-family="SegoeUI-Bold, Segoe UI" font-weight="700">₄</tspan></text>
+</svg>

+ 6 - 0
src/assets/icons/link.svg

@@ -0,0 +1,6 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="82.862" height="101.264" viewBox="0 0 82.862 101.264">
+  <g id="组_13471" data-name="组 13471" transform="translate(-200.867 -201.069) rotate(30)">
+    <path id="路径_55452" data-name="路径 55452" d="M356.783,72.866a21.128,21.128,0,1,0-42.191,0V86.43a24.389,24.389,0,0,1,9.782-9.521V72.866a11.347,11.347,0,1,1,22.628,0V93.342a11.347,11.347,0,0,1-11.347,11.347,11.216,11.216,0,0,1-7.108-2.608v11.086a20.737,20.737,0,0,0,7.108,1.3,21.128,21.128,0,0,0,21.128-21.128Z" transform="translate(0 0)" fill="#fff"/>
+    <path id="路径_55453" data-name="路径 55453" d="M347,350.391v6a11.347,11.347,0,1,1-22.628,0v-22.3a11.347,11.347,0,0,1,11.282-11.347,11.216,11.216,0,0,1,4.369.913,11.476,11.476,0,0,1,2.739,1.7V314.264a20.867,20.867,0,0,0-7.108-1.3,21.128,21.128,0,0,0-21.063,21.128v22.367a21.128,21.128,0,1,0,42.191,0V341a24.324,24.324,0,0,1-9.782,9.39Z" transform="translate(0 -235.66)" fill="#fff"/>
+  </g>
+</svg>

+ 3 - 0
src/assets/icons/o2val.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="80" height="104" viewBox="0 0 80 104">
+  <text id="O_" data-name="O₂" transform="translate(0 84)" fill="#fff" font-size="78" font-family="Kingsoft_Cloud_Font"><tspan x="0" y="0">O</tspan><tspan y="0" font-family="SegoeUI-Bold, Segoe UI" font-weight="700">₂</tspan></text>
+</svg>

+ 0 - 2
src/components/chart/BarAndLine.vue

@@ -94,8 +94,6 @@
       });
 
       function initChartsOption() {
-        debugger
-
         optionUtil = new EchartsUtil(Object.assign(option, props.option));
         optionUtil.initChartOption(props.chartsType, chartsColumns);
       }

+ 18 - 9
src/views/system/dict/index.vue

@@ -27,7 +27,16 @@
       </template>
       <!--操作栏-->
       <template #action="{ record }">
-        <TableAction :actions="getTableAction(record)" />
+        <!-- <TableAction :actions="getTableAction(record)" /> -->
+        <a class="table-action-link" @click="handleEdit(record)">编辑</a>
+        <a class="table-action-link" @click="handleItem(record)">字典配置</a>
+        <a-popconfirm
+          title="确定删除?"
+          @confirm="handleDelete(record)"
+          style="display: inline-block"
+        >
+          <a class="table-action-link">删除</a>
+        </a-popconfirm>
       </template>
     </BasicTable>
   </div>
@@ -75,7 +84,7 @@
         schemas: searchFormSchema,
       },
       actionColumn: {
-        width: 240,
+        width: 280,
       },
     },
     //update-begin---author:wangshuai ---date:20220616  for:[issues/I5AMDD]导入/导出功能,操作后提示没有传递 export.url/import.url 参数------------
@@ -175,13 +184,13 @@
         label: '字典配置',
         onClick: handleItem.bind(null, record),
       },
-      {
-        label: '删除',
-        popConfirm: {
-          title: '确定删除吗?',
-          confirm: handleDelete.bind(null, record),
-        },
-      },
+      // {
+      //   label: '删除',
+      //   popConfirm: {
+      //     title: '确定删除吗?',
+      //     confirm: handleDelete.bind(null, record),
+      //   },
+      // },
     ];
   }
 </script>

+ 32 - 0
src/views/vent/comment/EditRowTable.vue

@@ -180,7 +180,39 @@
 </script>
 <style scoped lang="less">
   @ventSpace: zxm;
+  @vent-table-no-hover: #00bfff10;
+  
   :deep(.@{ventSpace}-table-body) {
     height: auto !important;
   }
+
+  :deep(.@{ventSpace}-table-cell-row-hover) {
+    background: #264d8833 !important;
+  }
+  :deep(.@{ventSpace}-table-row-selected) {
+    background: #268bc522 !important;
+  }
+
+  :deep(.@{ventSpace}-table-tbody > tr > td) {
+    background-color: #0dc3ff05;
+  }
+  :deep(.jeecg-basic-table-row__striped) {
+    td {
+      background-color: @vent-table-no-hover !important;
+    }
+  }
+  :deep(.@{ventSpace}-select-dropdown) {
+    .@{ventSpace}-select-item {
+      color: #fff !important;
+    }
+
+    .@{ventSpace}-select-item-option-selected,
+    .@{ventSpace}-select-item-option-active {
+      background-color: #00678b66 !important;
+    }
+
+    .@{ventSpace}-select-item:hover {
+      background-color: #008fc366 !important;
+    }
+  }
 </style>

+ 15 - 2
src/views/vent/deviceManager/comment/NormalTable.vue

@@ -264,9 +264,8 @@
 
 <style scoped lang="less">
   @ventSpace: zxm;
- 
-
   @vent-table-no-hover: #00bfff10;
+
   :deep(.@{ventSpace}-table-cell-row-hover) {
     background: #264d8833 !important;
   }
@@ -282,4 +281,18 @@
       background-color: @vent-table-no-hover !important;
     }
   }
+  :deep(.@{ventSpace}-select-dropdown) {
+    .@{ventSpace}-select-item {
+      color: #fff !important;
+    }
+
+    .@{ventSpace}-select-item-option-selected,
+    .@{ventSpace}-select-item-option-active {
+      background-color: #00678b66 !important;
+    }
+
+    .@{ventSpace}-select-item:hover {
+      background-color: #008fc366 !important;
+    }
+  }
 </style>

+ 66 - 21
src/views/vent/monitorManager/deviceMonitor/index.vue

@@ -29,13 +29,17 @@
             <div  class="location-item">
               <div class="item-title">{{ location.title }}&nbsp;:</div>
               <div>
-                <a-radio-group v-model:value="location.isVisible" :name="location.deviceType">
+                <a-radio-group v-model:value="location.Visible" :name="location.deviceType">
                   <a-radio :value="1">是</a-radio>
                   <a-radio :value="0">否</a-radio>
                 </a-radio-group>
               </div>
             </div>
           </template>
+          <div class="location-bottom-btn">
+            <span @click="setLocation">提交</span>
+            <span @click="resetLocation">重置</span>
+          </div>
         </div>
       </div>
     </div>
@@ -107,7 +111,6 @@
 import { ref, onMounted, onUnmounted, ComponentOptions, shallowRef, nextTick } from 'vue'
 import { SendOutlined } from '@ant-design/icons-vue';
 import { list, getDeviceList, getDeviceTypeList } from './device.api'
-// import { locationList } from './device.data'
 import AlarmHistoryTable from '../comment/AlarmHistoryTable.vue';
 import HistoryTable from '../comment/HistoryTable.vue';
 import HandlerHistoryTable from '../comment/HandlerHistoryTable.vue';
@@ -116,11 +119,11 @@ import GroupMonitorTable from '../comment/GroupMonitorTable.vue';
 import { TreeProps, message } from 'ant-design-vue';
 import { TableAction } from '/@/components/Table';
 import FiberModal from './modal/fiber.modal.vue';
+import BundleModal from './modal/bundle.modal.vue'
 import DustModal from './modal/dust.modal.vue'
 import { SvgIcon } from '/@/components/Icon';
 import { getActions } from '/@/qiankun/state';
 import { useRouter } from 'vue-router';
-import { initDictOptions } from '/@/utils/dict/index';
 
 
 type DeviceType = { deviceType: string, deviceName: string, datalist: any[] };
@@ -147,8 +150,9 @@ const treeShow = ref(true) //是否显示树形菜单
 const locationSettingShow = ref(false) //是否显示树形菜单
 const treeNodeTitle = ref('') // 选中的树形标题
 
-const locationList = ref([])
-const deviceList = ref<DeviceType[]>([])
+const locationList = ref([]) //巷道定位图标显示列表
+let locationListTemp = []
+const deviceList = ref<DeviceType[]>([]) //关联设备列表
 const deviceActive = ref('')
 const activeKey = ref('1'); // tab key
 const dataSource = shallowRef([]) // 实时监测数据
@@ -180,13 +184,14 @@ const onSelect: TreeProps['onSelect'] = (keys, e) => {
   }
   selectedKeys.values = keys
   treeNodeTitle.value = e.node.title
-  debugger
   if(timer) clearTimeout(timer)
   timer = undefined
   if (monitorTable.value) monitorTable.value.setLoading(true)
   nextTick(() => {
-    timer = null
-    getMonitor()
+    setTimeout(() => {
+      timer = null
+      getMonitor()
+    }, 0)
   })
   
 };
@@ -227,9 +232,7 @@ async function getDeviceType() {
       });
       return dataSourceList
     }
-    console.log('树形菜单-------------->', treeData.value)
     treeData.value = getData(result, dataSource, key)
-
   }
 }
 
@@ -261,7 +264,7 @@ async function getDataSource() {
         deviceArr.unshift({ deviceType: item.type, deviceName: item['typeName'] ? item['typeName'] : item['datalist'][0]['typeName'], datalist: data })
       }
     })
-    console.log('关联设备列表', deviceArr)
+
     deviceList.value = deviceArr
     deviceActive.value = deviceArr[1].deviceType
     monitorChange(1)
@@ -301,10 +304,6 @@ function setDivHeight(e: MouseEvent) {
     document.onmousemove = null
     if (scroll.value.y != drawerHeight.value - 100) {
       scroll.value = { y: drawerHeight.value - 100 }
-
-      // const tableBody =  document.getElementsByClassName('zxm-table-container')[0].children[1] as HTMLElement
-      // debugger
-      // tableBody.style.height = `${drawerHeight.value - 350}px`
     }
   }
 }
@@ -312,6 +311,7 @@ function setDivHeight(e: MouseEvent) {
 function goLocation(record) {
   actions.setGlobalState({ locationId: record.deviceID, locationObj: null, pageObj: null });
 }
+
 function goDetail(record?) {
 
   if (record) {
@@ -319,10 +319,14 @@ function goDetail(record?) {
       activeID.value = record.deviceID
       currentModal.value = FiberModal
       modalVisible.value = true;
-    } else if (deviceType.value.startsWith('dusting')) {
+    } else if (deviceType.value.startsWith('dusting')) { //bundletube
       activeID.value = record.deviceID
       currentModal.value = DustModal
       modalVisible.value = true;
+    } else if (deviceType.value.startsWith('bundletube')) {
+      activeID.value = record.deviceID
+      currentModal.value = BundleModal
+      modalVisible.value = true;
     } else if (deviceType.value.indexOf("gate") != -1) {
       const newPage = router.resolve({ path: '/monitorChannel/monitor-gate' })
       window.open(newPage.href, '_blank')
@@ -393,7 +397,6 @@ async function findTreeDataValue(data: [], obj) {
     })
   }
   findDeviceType(data, obj)
-  debugger
   if (timer === undefined) {
     timer = null
     await getDataSource()
@@ -419,7 +422,27 @@ function monitorChange(index) {
     handlerHistoryTable.value.setLoading(true)
   }
 }
-
+/**
+ * 设置巷道设备定位图标的显示与隐藏
+ */
+function setLocation() {
+  let locationStr = ''
+  locationList.value.forEach((item: any) => {
+    if(item.Visible) {
+       locationStr = locationStr ? locationStr +','+ item.value : item.value
+    }
+  })
+  actions.setGlobalState({ locationId: null, locationObj: null, pageObj:null, locationPlane: locationStr });
+  setTimeout(() => {
+    message.success('设置成功')
+  }, 600)
+}
+/**
+ * 巷道设备定位图标重置
+ */
+function resetLocation() {
+  locationList.value = locationListTemp
+}
 
 onMounted(async () => {
   actions.onGlobalStateChange((newState, prev) => {
@@ -435,15 +458,18 @@ onMounted(async () => {
               findTreeDataValue(treeData.value, { deviceType: pageObj.pageType })
             }
           }
+          const posShowData = pageObj.locationPlane
+          if (posShowData) {
+            locationList.value = posShowData
+            locationListTemp = posShowData
+          }
         }
       }
     }
   })
   await getDeviceType()
-  locationList.value = await initDictOptions('devPosVisible')
-  console.log('定位列表------------>', locationList.value)
-  // getMonitor()
 })
+
 onUnmounted(() => {
   if (timer) {
     clearTimeout(timer);
@@ -706,6 +732,25 @@ onUnmounted(() => {
         color: #87f1ff;
       }
     }
+    .location-bottom-btn{
+      width: 100%;
+      color: #fff;
+      display: flex;
+      padding: 0 10px;
+      justify-content: space-between;
+      margin-top: 20px;
+      span{
+        display: inline-block;
+        padding: 2px 16px;
+        background: #007099;
+        border-radius: 4px;
+        border: 1px solid rgb(125, 230, 249);
+        cursor: pointer;
+        &:hover{
+          background: #005574;
+        }
+      }
+    }
   }
 }
 .location-select-show{

+ 446 - 0
src/views/vent/monitorManager/deviceMonitor/modal/bundle.modal.vue

@@ -0,0 +1,446 @@
+<template>
+  <BasicModal v-bind="$attrs" @register="register" :title="`束管监测详情    ${currentTime}`" width="1200px" @ok="handleOk" @cancel="handleCancel" >
+    <div class="fiber-modal">
+      <div class="modal-left">
+        <div v-for="device in deviceList" class="link-item" :class="{'active-device-title': device.deviceID === activeDeviceID }" :key="device.deviceID">
+          <span class="" @click="selectDevice(device.deviceID)">{{ device.strinstallpos }}</span>
+        </div>
+      </div>
+      <div class="modal-right">
+        <span class="base-title">实时监测参数</span>
+        <div class="right-top">
+          <div class="top-item">
+            <div class="icon">
+              <SvgIcon class="icon-style" name="coval" style="width: 62px; height: 38px; margin-top: 10px;" />
+            </div>
+            <div class="item-container">
+              <div class="title">一氧化碳</div>
+              <div class="value">{{ posMonitor.coval }} <span>ppm</span> </div>
+            </div>
+          </div>
+          <div class="top-item">
+            <div class="icon">
+              <SvgIcon class="icon-style" name="co2val"  style="width: 72px; height: 46px;" />
+            </div>
+            <div class="item-container">
+              <div class="title">二氧化碳</div>
+              <div class="value">{{ posMonitor.co2val }} <span>%</span></div>
+            </div>
+          </div>
+          <div class="top-item">
+            <div class="icon">
+              <SvgIcon class="icon-style" name="gasval"  style="width: 72px; height: 46px;"/>
+            </div>
+            <div class="item-container">
+              <div class="title">甲烷</div>
+              <div class="value">{{ posMonitor.gasval }} <span>%</span></div>
+            </div>
+          </div>
+          <div class="top-item">
+            <div class="icon">
+              <SvgIcon class="icon-style" name="ch2val"  style="width: 76px; height: 42px;"/>
+            </div>
+            <div class="item-container">
+              <div class="title">乙烯</div>
+              <div class="value">{{ posMonitor.ch2val }} <span>ppm</span></div>
+            </div>
+          </div>
+          <div class="top-item">
+            <div class="icon">
+              <SvgIcon class="icon-style" name="chval" style="width: 76px; height: 42px;" />
+            </div>
+            <div class="item-container">
+              <div class="title">乙炔</div>
+              <div class="value">{{ posMonitor.chval }} <span>ppm</span></div>
+            </div>
+          </div>
+          <div class="top-item">
+            <div class="icon">
+              <SvgIcon class="icon-style" name="o2val"  style="width: 76px; height: 50px;"/>
+            </div>
+            <div class="item-container">
+              <div class="title">氧气</div>
+              <div class="value">{{ posMonitor.o2val }} <span>%</span></div>
+            </div>
+          </div>
+          <div class="top-item warning-box">
+            <div class="icon">
+              <SvgIcon class="icon-style" size="42" name="alarm-warning" style="margin-top: 5px;" />
+            </div>
+            <div class="item-container">
+              <div class="title">风险等级</div>
+              <div class="warning-value">低风险</div>
+            </div>
+          </div>
+          <div class="top-item warning-box">
+            <div class="icon">
+              <SvgIcon class="icon-style" size="42" name="link" style="margin-top: 5px;"/>
+            </div>
+            <div class="item-container">
+              <div class="title">连接状态</div>
+              <div class="warning-value">连接</div>
+            </div>
+          </div>
+        </div>
+        <div class="right-bottom">
+          <span class="base-title">设备监测曲线</span>
+          <div class="echarts-box">
+            <BarAndLine
+              class="echarts-line"
+              xAxisPropType="readTime"
+              :dataSource="deviceList"
+              height="100%"
+              :chartsColumns="chartsColumns"
+              :option="echatsOption"
+              chartsType="listMonitor" />
+          </div>
+        </div>
+      </div>
+    </div>
+  </BasicModal>
+</template>
+<script lang="ts">
+import { defineComponent, ref, watch, shallowRef, reactive } from 'vue';
+import { BasicModal, useModalInner } from '/@/components/Modal';
+import BarAndLine from '/@/components/chart/BarAndLine.vue';
+import { SvgIcon } from '/@/components/Icon';
+import { Decoration7 as DvDecoration7, ScrollBoard as DvScrollBoard } from '@kjgl77/datav-vue3';
+import dayjs from 'dayjs'
+
+export default defineComponent({
+  components: { BasicModal, BarAndLine, SvgIcon, DvScrollBoard, DvDecoration7 },
+  props: {
+    dataSource: {type: Array},
+    activeID: {type: String}
+  },
+  setup(props) {
+    const currentTime = ref(dayjs().format('YYYY-MM-DD HH:mm:ss'))
+    const modelRef = ref({});
+    const loading = ref(true);
+    const activeDeviceID = ref('');
+    const deviceList = ref<any[]>([])
+    const posList = ref<any[]>([])
+    const posMonitor = shallowRef({})
+
+    const echatsOption = {
+      grid: {
+        top: '25%',
+        left: '0%',
+        right: '0%',
+        bottom: '3%',
+        containLabel: true
+      },
+      toolbox: {
+        feature: {}
+      }
+    }
+
+    const chartsColumns = [
+      {
+        legend: '一氧化碳',
+        seriesName: '(ppm)',
+        ymax: 20,
+        yname: 'ppm',
+        linetype: 'line',
+        yaxispos: 'left',
+        color: '#FDB146',
+        sort: 1,
+        xRotate: 0,
+        dataIndex: 'coval',
+      },
+      {
+        legend: '二氧化碳',
+        seriesName: '(%)',
+        ymax: 10,
+        yname: '%',
+        linetype: 'line',
+        yaxispos: 'right',
+        color: '#9C83D9',
+        sort: 2,
+        xRotate: 0,
+        dataIndex: 'co2val',
+      },
+      {
+        legend: '甲烷',
+        seriesName: '(%)',
+        ymax: 10,
+        yname: '%',
+        linetype: 'line',
+        yaxispos: 'right',
+        color: '#DA3914',
+        sort: 2,
+        xRotate: 0,
+        dataIndex: 'gasval',
+      },
+      {
+        legend: '氧气',
+        seriesName: '(%)',
+        ymax: 10,
+        yname: '%',
+        linetype: 'line',
+        yaxispos: 'right',
+        color: '#03C2EC',
+        sort: 2,
+        xRotate: 0,
+        dataIndex: 'o2val',
+      },
+      {
+        legend: '乙炔',
+        seriesName: '(ppm)',
+        ymax: 20,
+        yname: 'ppm',
+        linetype: 'line',
+        yaxispos: 'left',
+        color: '#00FFA8',
+        sort: 1,
+        xRotate: 0,
+        dataIndex: 'chval',
+      },
+      {
+        legend: '乙烯',
+        seriesName: '(ppm)',
+        ymax: 20,
+        yname: 'ppm',
+        linetype: 'line',
+        yaxispos: 'left',
+        color: '#AE19FF',
+        sort: 1,
+        xRotate: 0,
+        dataIndex: 'ch2val',
+      },
+    ]
+    const [register, { setModalProps, closeModal }] = useModalInner();
+
+    function handleVisibleChange(visible) {
+      if (visible) {
+        loading.value = true;
+        setModalProps({ loading: true, confirmLoading: true });
+
+        setTimeout(() => {
+          loading.value = false;
+          setModalProps({ loading: false, confirmLoading: false });
+        }, 1000);
+      }
+    }
+
+    // 选择监测
+    function selectDevice (id){
+      loading.value = true;
+      setModalProps({ loading: true, confirmLoading: true });
+       setTimeout(() => {
+        loading.value = false;
+        activeDeviceID.value = id
+        setModalProps({ loading: false, confirmLoading: false });
+      }, 300);
+    }
+
+    function handleOk(e) {
+      e.preventDefault()
+      closeModal()
+    }
+
+    function handleCancel(e) {
+      e.preventDefault()
+      closeModal()
+    }
+
+    watch([() => props.dataSource, () => props.activeID], ([newDataSource, newActiveID], [oldDataSource, oldActiveID]) => {
+      if(newActiveID != oldActiveID){
+        activeDeviceID.value = newActiveID as string
+      }
+      deviceList.value = newDataSource?.filter((item:any, index) => {
+        if((!activeDeviceID.value && index == 0) || item.deviceID === activeDeviceID.value){
+          activeDeviceID.value = item.deviceID
+          posMonitor.value = item.readData
+        }
+        item.readTime = item.readTime?.substring(11)
+        return item
+      })
+    })
+
+    return { register, model: modelRef, currentTime, handleVisibleChange, selectDevice, handleOk, handleCancel, deviceList, activeDeviceID, posMonitor, echatsOption, posList, chartsColumns };
+  },
+  
+});
+</script>
+<style lang="less" scoped>
+  .fiber-modal{
+    width: 100%;
+    height: 650px;
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    
+    .modal-left{
+      width: 200px;
+      height: 100%;
+      overflow-y: auto;
+      background: #ffffff11;
+      padding: 5px;
+      border-radius: 5px;
+      .active-device-title {
+        color: aqua;
+      }
+      .link-item{
+        position: relative;
+        cursor: pointer;
+        line-height: 30px;
+        padding-left: 30px;
+        span:hover{
+          color: #89ffff;
+        }
+        &::after{
+          content: '';
+          position: absolute;
+          display: block;
+          width: 8px;
+          height: 8px;
+          top: 12px;
+          left: 10px;
+          transform: rotateZ(45deg) skew(10deg, 10deg);
+          background: #45d3fd;
+        }
+      }
+    }
+    .modal-right{
+      width: calc(100% - 220px);
+      .base-title{
+        line-height: 32px;
+        position: relative;
+        padding-left: 20px;
+        &::after{
+          content: '';
+          position: absolute;
+          display: block;
+          width: 4px;
+          height: 12px;
+          top: 4px;
+          left: 10px;
+          background: #45d3fd;
+          border-radius: 4px;
+        }
+      }
+      .right-top{
+        display: flex;
+        flex-direction: row;
+        justify-content: space-between;
+        flex-wrap: wrap;
+        margin-bottom: 10px;
+        .top-item{
+          width: 220px;
+          height: 100px;
+          display: flex;
+          flex-direction: row;
+          justify-content: center;
+          border: 1px solid rgba(25,237,255,.4);
+          box-shadow: inset 0 0 10px rgba(0,197,255,.6);
+          background: rgba(0,0,0,.06666666666666667);
+          padding-top: 20px;
+          margin: 10px 0;
+          .icon{
+            margin-right: 10px;
+            margin-top: 5px;
+            color: #FDB146;
+          }
+          .item-container{
+            width: 100px;
+            display: flex;
+            flex-direction: column;
+            justify-content: center;
+            div{
+              text-align: center;
+            }
+            .title{
+              font-size: 18px;
+            }
+            .value{
+              text-shadow: 0 0 25px #00fbfe;
+              background: linear-gradient( 0deg,#45d3fd, #45d3fd, #61ddb1,#61ddb1);
+              font-style: normal;
+              background-size: cover;
+              font-family: electronicFont;
+              font-size: 30px;
+              -webkit-background-clip: text;
+              background-clip: text;
+              -webkit-text-fill-color: transparent;
+              position: relative;
+              top: -8px;
+              span{
+                font-family: Arial, Helvetica, sans-serif;
+                font-size: 18px;
+                color: aliceblue;
+              }
+              
+            }
+            
+          }
+        }
+        .warning-box{
+          padding-top: 0px;
+          .icon{
+            margin-top: 20px;
+            :deep(.icon-style){
+              width: auto;
+              color: #FDB146;
+            }
+          }
+          .warning-value{
+            font-size: 18px;
+            color: #61ddb1;
+          }
+        }
+      }
+      .right-center{
+        margin-top: 20px;
+        display: flex;
+        flex-direction: row;
+        justify-content: space-between;
+        .table-box{
+          position: relative;
+          width: 500px;
+          height: 250px;
+        }
+        .warning-box{
+          width: calc(100% - 520px);
+          .warning-container{
+            width: 100%;
+            height: convert;
+            background: #009acd00;
+            :deep(.dv-scroll-board){
+              .row-item{
+                height: 40px !important;
+                line-height: 40px !important;
+              }
+              .header-item{
+                border-top: 1px solid #91e9fe !important;
+                border-bottom: 1px solid #91e9fe !important;
+              }
+            }
+
+          }
+        }
+      }
+      .right-bottom{
+        margin-top: 20px;
+        .echarts-box{
+          width: 100%;
+          height: 320px;
+          position: relative;
+          .echarts-line{
+            width: calc(100% + 80px);
+            position: absolute
+          }
+        }
+      }      
+    }
+  }
+  :deep(.zxm-table-body){
+    border: 1px solid rgba(57, 232, 255, 0.2) !important;
+    .zxm-table-tbody > tr > td{
+      border: none !important;
+    }
+  }
+  :deep(.zxm-table-cell){
+    border-right: none !important;
+  }
+</style>