Selaa lähdekoodia

首页,设备监测详情跳转修改提交

lxh 1 vuosi sitten
vanhempi
commit
0ded4c7c04

+ 1 - 1
src/design/vent/antCss.less

@@ -142,7 +142,7 @@ tr.@{ventSpace}-table-expanded-row:hover > td {
 
 /* modal 组件 */
 .zxm-modal{
-  top: 320px !important;//lxh
+  top: 120px !important;//lxh
 }
 
 

+ 1 - 1
src/views/vent/home/clique/components/device-warn.vue

@@ -53,7 +53,7 @@
   //跳转详情
   function getDetail() {
     console.log('跳转详情');
-    emit('goDetail', 'deviceMo');
+    emit('goDetail', 'sheb');
   }
   watch(
     () => props.warnData,

+ 1 - 1
src/views/vent/home/clique/components/fan-monitor.vue

@@ -53,7 +53,7 @@
   });
   //跳转详情
   function getDetail() {
-    emit('goDetail', 'fanlocal');
+    emit('goDetail', 'ju');
   }
   //选项切换
   function changeSelect(val) {

+ 1 - 1
src/views/vent/home/clique/components/main-monitor.vue

@@ -54,7 +54,7 @@
   //跳转详情
   function getDetail() {
     console.log('跳转详情');
-    emit('goDetail', 'fanmain');
+    emit('goDetail', 'zhu');
   }
   //选项切换
   function changeSelect(val) {

+ 1 - 1
src/views/vent/home/clique/components/wind-device.vue

@@ -125,7 +125,7 @@
   //跳转详情
   function getDetail() {
     console.log('跳转详情');
-    emit('goDetail', 'gate')
+    emit('goDetail', 'fl')
   }
 
   watch(

+ 1 - 1
src/views/vent/home/clique/components/wind-line.vue

@@ -79,7 +79,7 @@
   //跳转详情
   function getDetail() {
     console.log('跳转详情');
-    emit('goDetail', 'obfurage')
+    emit('goDetail', 'line')
   }
   //选项切换
   function changeSelect(val) {

+ 1 - 1
src/views/vent/home/clique/components/wind-monitor.vue

@@ -22,7 +22,7 @@
   let echartData = reactive<any>({ ydata: [], xdata: [] });
   //跳转详情
   function getDetail() {
-    emit('goDetail', 'windrect')
+    emit('goDetail', 'wind')
   }
   function getOption() {
     nextTick(() => {

+ 1 - 1
src/views/vent/home/clique/components/work-monitor.vue

@@ -55,7 +55,7 @@
   //跳转详情
   function getDetail() {
     console.log('跳转详情');
-    emit('goDetail', 'workMo');
+    emit('goDetail', 'work');
   }
   //选项切换
   function changeSelect(val) {

+ 15 - 4
src/views/vent/home/clique/index.vue

@@ -40,7 +40,7 @@
               </div>
             </div>
             <div class="three-modal" id="modalBox">
-              <!-- <iframe
+              <iframe
                 id="iframe"
                 ref="iframe"
                 src="http://182.92.126.35:8091/user/autologin"
@@ -48,7 +48,7 @@
                 frameborder="0"
                 width="100%"
                 height="100%"
-              ></iframe> -->
+              ></iframe>
             </div>
           </div>
           <!-- 风量监测 -->
@@ -88,6 +88,7 @@
   import { useGlobSetting } from '/@/hooks/setting';
   import { list } from './clique.api';
   import DeviceMonitor from '../../monitorManager/deviceMonitor/index.vue';
+  import { useRouter } from 'vue-router';
   // import { Modal } from 'ant-design-vue';
   // import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
   import moment from 'moment';
@@ -114,6 +115,7 @@
   const openQianKun = globSetting.openQianKun;
   let actions;
   const pageType = ref('home');
+  let router = useRouter();
 
   function goDetail(deviceType) {
     // Modal.confirm({
@@ -130,8 +132,17 @@
     //     Modal.destroyAll();
     //   },
     // });
-    pageType.value = deviceType;
-    changeModalBox();
+
+    //lxh
+    // pageType.value = deviceType;
+    // changeModalBox();
+    if (deviceType == 'zhu') {
+      router.push('/monitorChannel/monitor-fan-main');
+    } else if (deviceType == 'ju') {
+      router.push('/monitorChannel/monitor-fan-local');
+    } else {
+      router.push('/monitorChannel/monitor-gate');
+    }
   }
   function goHome() {
     pageType.value = 'home';

+ 9 - 1
src/views/vent/monitorManager/comment/MonitorTable.vue

@@ -11,6 +11,8 @@
         <slot name="filterCell" v-bind="{ column, record }"></slot>
       </template>
       <template #action="{ record }">
+
+        <a class="table-action-link" @click="handleDetail(record)">详情</a>
           <slot name="action" v-bind="{ record }"></slot>
         </template>
     </BasicTable>
@@ -74,7 +76,7 @@
       default: undefined
     }
   });
-  const emits = defineEmits(['selectRow']);
+  const emits = defineEmits(['selectRow','getDetail']);
   const dataTableSource = ref<any[]>([]);
   // const loading = ref(true);
 
@@ -83,6 +85,12 @@
   const tableMaxHeight = 150;
   const columns = ref([])
   const tableScroll = props.scroll.y ?  ref({y: props.scroll.y}) : ref({})
+
+
+  //查看详情
+  function handleDetail(data){
+    emits('getDetail', data.strinstallpos);
+  }
   
   watch(
     () => {

+ 448 - 0
src/views/vent/monitorManager/deviceTypeMonitor/components/bundle-modal.vue

@@ -0,0 +1,448 @@
+<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 !== undefined && posMonitor.coval !== null) ? 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 !== undefined && posMonitor.co2val !== null) ? 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 !== undefined && posMonitor.gasval !== null) ? 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 !== undefined && posMonitor.ch2val !== null) ? 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 !== undefined && posMonitor.chval !== null) ? 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 !== undefined && posMonitor.o2val !== null) ? 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>
+  

+ 455 - 0
src/views/vent/monitorManager/deviceTypeMonitor/components/dust-modal.vue

@@ -0,0 +1,455 @@
+<template>
+    <BasicModal v-bind="$attrs" destroyOnClose @register="register" :title="`粉尘监测详情    ${currentTime}`" width="1200px" >
+      <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.stationname }}</span>
+          </div>
+        </div>
+        <div class="modal-right">
+          <div class="right-top">
+            <div class="top-item">
+              <div class="icon">
+                <SvgIcon class="icon-style max-temperature" size="30" name="hd-wd" />
+              </div>
+              <div class="item-container">
+                <div class="title">巷道温度</div>
+                <div class="value"><span class="data">{{ dustMonitor.temperature }}</span> <span>℃</span> </div>
+              </div>
+            </div>
+            <div class="top-item">
+              <div class="icon">
+                <SvgIcon class="icon-style min-temperature" size="30" name="dust-nd" />
+              </div>
+              <div class="item-container">
+                <div class="title">粉尘浓度</div>
+                <div class="value"><span class="data">{{ dustMonitor.humidity }}</span> <span>mg/m³</span></div>
+              </div>
+            </div>
+            <div class="top-item">
+              <div class="icon">
+                <SvgIcon class="icon-style aveg-temperature" size="30" name="pw-sy" />
+              </div>
+              <div class="item-container">
+                <div class="title">喷雾水压</div>
+                <div class="value"><span class="data">{{ dustMonitor.waterPressure }}</span> <span>MPa</span></div>
+              </div>
+            </div>
+            <div class="top-item warning-box">
+              <div class="icon">
+                <SvgIcon class="icon-style" size="30" name="pw-zz" />
+              </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="40" name="kg" />
+              </div>
+              <div class="item-container">
+                <div class="title">喷雾开关</div>
+                <div class="warning-value">
+                  <a-switch checked-children="开" un-checked-children="关" v-model:checked="dustSwitch" />
+                </div>
+              </div>
+            </div>
+          </div>
+          <div class="right-center">
+            <span class="base-title">粉尘实时监测</span>
+            <div class="dust-group">
+              <div class="dust-item">
+                <div class="title">粉尘浓度(实时)</div>
+                <div class="value">{{ dustMonitor.breathWeighted }}<span>mg/m³</span></div>
+              </div>
+              <div class="dust-item">
+                <div class="title">总尘浓度(时间加权)</div>
+                <div class="value">{{ dustMonitor.totalDust }}<span>mg/m³</span></div>
+              </div>
+              <div class="dust-item">
+                <div class="title">呼吸加权容许浓度</div>
+                <div class="value">{{ dustMonitor.breathWeighted }}<span>mg/m³</span></div>
+              </div>
+              <div class="dust-item">
+                <div class="title">爆炸浓度(煤尘)</div>
+                <div class="value">{{ dustMonitor.dustval }}<span>mg/m³</span></div>
+              </div>
+            </div> 
+          </div>
+          <div class="right-bottom">
+            <span class="base-title">粉尘预测曲线</span>
+            <div class="echarts-box">
+              <BarAndLine
+                xAxisPropType="readTime"
+                :dataSource="posList"
+                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 dustMonitor = shallowRef({})
+      const dustSwitch = ref(false)
+  
+      const echatsOption = {
+        grid: {
+          top: '20%',
+          left: '2px',
+          right: '10px',
+          bottom: '3%',
+          containLabel: true
+        },
+        toolbox: {
+          feature: {}
+        }
+      }
+  
+      const chartsColumns = [
+        {
+          legend: '粉尘平均浓度',
+          seriesName: '(mg/m³)',
+          ymax: 5,
+          yname: 'mg/m³',
+          linetype: 'line',
+          yaxispos: 'left',
+          color: '#FDB146',
+          sort: 1,
+          xRotate: 0,
+          dataIndex: 'hourAvg',
+        },
+        {
+          legend: '粉尘最大浓度',
+          seriesName: '(mg/m³)',
+          ymax: 5,
+          yname: 'mg/m³',
+          linetype: 'line',
+          yaxispos: 'left',
+          color: '#EE6666',
+          sort: 1,
+          xRotate: 0,
+          dataIndex: 'hourMax',
+        },
+        {
+          legend: '粉尘最小浓度',
+          seriesName: '(mg/m³)',
+          ymax: 5,
+          yname: 'mg/m³',
+          linetype: 'line',
+          yaxispos: 'left',
+          color: '#9BCB75',
+          sort: 1,
+          xRotate: 0,
+          dataIndex: 'hourMin',
+        },
+      ]
+  
+      const columns = [
+        {
+          title: '安装位置',
+          dataIndex: 'position',
+          width: 60,
+          align: 'center',
+          customRender: ({ index }) => {
+            return `测点${index}`
+          }
+        },
+        {
+          title: '安装距离(m)',
+          dataIndex: 'pos',
+          align: 'center',
+          width: 60,
+        },
+        {
+          title: '测点温度',
+          dataIndex: 'value',
+          align: 'center',
+          width: 50,
+        },
+        {
+          title: '测点状态',
+          dataIndex: 'state',
+          align: 'center',
+          width: 50,
+          customRender: () => {
+            return `正常`
+          }
+        },
+      ];
+  
+      const warningConfig = reactive({
+        data: [
+          ['测点6', '318℃', '严重报警'],
+          ['测点43', '142℃', '一般预警'],
+          ['测点23', '167℃', '一版预警'],
+          ['测点6', '198℃', '超高预警'],
+          ['测点65', '197℃', '超高预警'],
+          ['测点78', '154℃', '一般预警'],
+          ['测点61', '104℃', '一般预警'],
+          ['测点87', '150℃', '一般信息'],
+        ],
+        index: false,
+        columnWidth: [150],
+        oddRowBGC: '#009acd10',
+        evenRowBGC: '#009acd05',
+        align: ['center', 'center', 'center'],
+      });
+      
+      const [register, { setModalProps }] = 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);
+      }
+  
+      watch([() => props.dataSource, () => props.activeID], ([newDataSource, newActiveID], [oldDataSource, oldActiveID]) => {
+        deviceList.value = newDataSource as any[]
+        if(newActiveID != oldActiveID){
+          activeDeviceID.value = newActiveID as string
+        }
+        newDataSource?.forEach((item:any, index) => {
+          if((!activeDeviceID.value && index == 0) || item.deviceID === activeDeviceID.value){
+            activeDeviceID.value = item.deviceID
+            const list = item.summaryHour
+            list.filter(data => {
+              const date = new Date();     //1. js获取当前时间
+              const min = date.getMinutes();  //2. 获取当前分钟
+              return Object.assign(data, data.dustval, { readTime: (dayjs(date.setMinutes(min + 10))).format('YYYY-MM-DD HH:mm:ss') })
+            })
+            if(list.length > 0) posList.value = list
+            dustMonitor.value = item.readData
+          }
+        })
+      })
+  
+      return { register, model: modelRef, currentTime, dustSwitch, handleVisibleChange, selectDevice, deviceList, activeDeviceID, dustMonitor, echatsOption, posList, chartsColumns, columns, warningConfig };
+    },
+    
+  });
+  </script>
+  <style lang="less" scoped>
+    .fiber-modal{
+      width: 100%;
+      height: 600px;
+      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;
+          margin-bottom: 30px;
+          padding: 0 10px;
+          .top-item{
+            width: 155px;
+            height: 60px;
+            display: flex;
+            flex-direction: row;
+            justify-content: center;
+            align-items: center;
+            background: url('/@/assets/images/vent/model_image/dust-monitor-bg.png') no-repeat;
+            padding-top: 16px;
+            .icon{
+              width: 58px;
+              height: 60px;
+              display: flex;
+              justify-content: center;
+              align-items: center;
+              position: relative;
+              top: -8px;
+            }
+            .item-container{
+              width: 100px;
+              display: flex;
+              flex-direction: column;
+              // justify-content: start;
+              div{
+                padding-left: 8px;
+              }
+              .title{
+                font-size: 14px;
+                margin-bottom: 8px;
+              }
+              .value{
+                position: relative;
+                width: 110px;
+                top: -8px;
+                .data{
+                  display: inline-block;
+                  width: 50px;
+                  font-family: douyuFont;
+                  font-weight: 600;
+                  font-size: 14px;
+                  -webkit-background-clip: text;
+                  background-clip: text;
+                  color: #28DCE4;
+                }
+                span{
+                  font-family: Arial, Helvetica, sans-serif;
+                  font-size: 14px;
+                  color: #ffffffdd;
+                }
+              }
+              
+            }
+          }
+          .warning-box{
+            padding-top: 0px;
+            .icon{
+              margin-top: 20px;
+              .icon-style{
+                color: #FDB146;
+              }
+            }
+            .title{
+              padding-top: 0px;
+            }
+            .warning-value{
+              font-family: electronicFont;
+              font-size: 18px;
+              color: #61ddb1;
+            }
+          }
+        }
+        .right-center{
+          margin-top: 20px;
+          .dust-group{
+            display: flex;
+            flex-direction: row;
+            justify-content: space-between;
+            .dust-item{
+              width: 238px;
+              height: 148px;
+              background: url('/@/assets/images/vent/model_image/dust-bg.png') no-repeat;
+              scale: 0.9;
+              .title{
+                position: absolute;
+                top: 80px;
+                left: 70px;
+                font-size: 16px;
+              }
+              .value{
+                position: absolute;
+                top: 50px;
+                left: 50px;
+                font-family: 'douyuFont';
+                color: #20dbfd;
+                text-shadow: 0 0 25px #00d8ff;
+                font-size: 18px;
+                font-weight: bolder;
+                span{
+                  font-family: Arial, Helvetica, sans-serif;
+                  font-size: 16px;
+                  color: aliceblue;
+                  margin-left: 8px;
+                }
+              }
+            }
+          }
+        }
+        .right-bottom{
+          margin-top: 20px;
+          .echarts-box{
+            width: 100%;
+            height: 270px;
+          }
+        }
+  
+        
+      }
+    }
+  </style>
+  

+ 419 - 0
src/views/vent/monitorManager/deviceTypeMonitor/components/fiber-modal.vue

@@ -0,0 +1,419 @@
+<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.stationname }}</span>
+          </div>
+        </div>
+        <div class="modal-right">
+          <div class="right-top">
+            <div class="top-item">
+              <div class="icon">
+                <SvgIcon class="icon-style max-temperature" size="38" name="max-temperature" />
+              </div>
+              <div class="item-container">
+                <div class="title">最高温度</div>
+                <div class="value">{{ posMonitor.fmax }} <span>℃</span> </div>
+              </div>
+            </div>
+            <div class="top-item">
+              <div class="icon">
+                <SvgIcon class="icon-style min-temperature" size="38" name="min-temperature" />
+              </div>
+              <div class="item-container">
+                <div class="title">最低温度</div>
+                <div class="value">{{ posMonitor.fmin }} <span>℃</span></div>
+              </div>
+            </div>
+            <div class="top-item">
+              <div class="icon">
+                <SvgIcon class="icon-style aveg-temperature" size="38" name="aveg-temperature" />
+              </div>
+              <div class="item-container">
+                <div class="title">平均温度</div>
+                <div class="value">{{ posMonitor.favg }} <span>℃</span></div>
+              </div>
+            </div>
+            <div class="top-item warning-box">
+              <div class="icon">
+                <SvgIcon class="icon-style" size="38" name="risk-level" />
+              </div>
+              <div class="item-container">
+                <div class="title">风险等级</div>
+                <div class="warning-value">低风险</div>
+              </div>
+            </div>
+          </div>
+          <div class="right-center">
+            <div class="table-box">
+              <span class="base-title">测点监测详情</span>
+              <a-table
+                size="small"
+                :columns="columns"
+                :data-source="posList"
+                :pagination="false"
+                :scroll="{ y: 200 }"
+              />
+            </div>
+            <div class="warning-box">
+              <span class="base-title">预警历史详情</span>
+              <div class="warning-container">
+                <dv-scroll-board ref="scrollBoard" :config="warningConfig" style="width: 100%; height: 240px; overflow-y: auto; border: 1px solid #39e8ff33;" />
+              </div>
+            </div>
+          </div>
+          <div class="right-bottom">
+            <span class="base-title">测点监测曲线</span>
+            <div class="echarts-box">
+              <BarAndLine
+                xAxisPropType="pos"
+                :dataSource="posList"
+                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: '20%',
+          left: '2px',
+          right: '10px',
+          bottom: '3%',
+          containLabel: true
+        },
+        toolbox: {
+          feature: {}
+        }
+      }
+  
+      const chartsColumns = [
+        {
+          legend: '测点温度',
+          seriesName: '(℃)',
+          ymax: 200,
+          yname: '℃',
+          linetype: 'line',
+          yaxispos: 'left',
+          color: '#FDB146',
+          sort: 1,
+          xRotate: 0,
+          dataIndex: 'value',
+        },
+      ]
+  
+      const columns = [
+        {
+          title: '安装位置',
+          dataIndex: 'position',
+          width: 60,
+          align: 'center',
+          customRender: ({ index }) => {
+            return `测点${index}`
+          }
+        },
+        {
+          title: '安装距离(m)',
+          dataIndex: 'pos',
+          align: 'center',
+          width: 60,
+        },
+        {
+          title: '测点温度',
+          dataIndex: 'value',
+          align: 'center',
+          width: 50,
+        },
+        {
+          title: '测点状态',
+          dataIndex: 'state',
+          align: 'center',
+          width: 50,
+          customRender: () => {
+            return `正常`
+          }
+        },
+      ];
+  
+      const warningConfig = reactive({
+        header: ['测点', '温度', '预警信息'],
+        data: [
+          ['测点6', '318℃', '严重报警'],
+          ['测点43', '142℃', '一般预警'],
+          ['测点23', '167℃', '一版预警'],
+          ['测点6', '198℃', '超高预警'],
+          ['测点65', '197℃', '超高预警'],
+          ['测点78', '154℃', '一般预警'],
+          ['测点61', '104℃', '一般预警'],
+          ['测点87', '150℃', '一般信息'],
+        ],
+        index: false,
+        columnWidth: [150],
+        headerHeight: 38,
+        headerBGC: '#3d9dd45d',
+        oddRowBGC: '#009acd10',
+        evenRowBGC: '#009acd05',
+        align: ['center', 'center', 'center'],
+      });
+      
+      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]) => {
+        deviceList.value = newDataSource as any[]
+        if(newActiveID != oldActiveID){
+          activeDeviceID.value = newActiveID as string
+        }
+        newDataSource?.forEach((item:any, index) => {
+          if((!activeDeviceID.value && index == 0) || item.deviceID === activeDeviceID.value){
+            activeDeviceID.value = item.deviceID
+            if(item.readData.fibreTemperature){
+              const list = JSON.parse(item.readData.fibreTemperature)
+              if (list.length > 0) posList.value = list
+            }
+            posMonitor.value = item.readData
+          }
+        })
+      })
+  
+      return { register, model: modelRef, currentTime, handleVisibleChange, selectDevice, handleOk, handleCancel, deviceList, activeDeviceID, posMonitor, echatsOption, posList, chartsColumns, columns, warningConfig };
+    },
+    
+  });
+  </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;
+          margin-bottom: 10px;
+          .top-item{
+            width: 200px;
+            height: 80px;
+            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: 16px;
+            .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;
+              .icon-style{
+                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: 230px;
+          }
+        }
+  
+        
+      }
+    }
+    :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>
+  

+ 34 - 5
src/views/vent/monitorManager/deviceTypeMonitor/index.vue

@@ -2,7 +2,7 @@
   <div class="device-box" id="monitorBox">
     <a-tabs class="tabs-box" type="card" v-model:activeKey="activeKey" @change="tabChange" id="tabsBox" v-if="isRefresh">
       <a-tab-pane key="1" tab="实时监测">
-        <div style="height: calc(100% - 320px);">
+        <div style="height: calc(100% - 320px)">
           <template v-if="deviceType == 'fan' && activeKey == '1'">
             <GroupMonitorTable :dataSource="dataSource" :columnsType="`${deviceType}_monitor`" />
           </template>
@@ -17,6 +17,7 @@
               title="设备监测"
               :form-config="deviceType == 'safetymonitor' ? formConfig : undefined"
               :scroll="scroll"
+              @getDetail="getDetail"
             >
               <template #filterCell="{ column, record }">
                 <template v-if="deviceType.startsWith('gate')">
@@ -145,7 +146,7 @@
         </div>
       </a-tab-pane>
       <a-tab-pane key="2" tab="历史数据">
-        <div class="tab-item" style="height: calc(100% - 320px);">
+        <div class="tab-item" style="height: calc(100% - 320px)">
           <HistoryTable
             ref="historyTable"
             v-if="activeKey == '2'"
@@ -225,7 +226,7 @@
         </div>
       </a-tab-pane>
       <a-tab-pane key="3" tab="报警历史">
-        <div class="tab-item" >
+        <div class="tab-item">
           <AlarmHistoryTable
             ref="alarmHistoryTable"
             v-if="activeKey == '3'"
@@ -252,10 +253,11 @@
       </a-tab-pane>
     </a-tabs>
   </div>
+  <component v-if="modalVisible" :is="currentModal" v-model:visible="modalVisible" :dataSource="tableData" :activeID="activeID" />
 </template>
 
 <script setup lang="ts">
-  import { ref, onMounted, onUnmounted, shallowRef, defineProps, watch, nextTick } from 'vue';
+  import { ref, onMounted, onUnmounted, shallowRef, defineProps, watch, nextTick, reactive } from 'vue';
   import BarAndLine from '/@/components/chart/BarAndLine.vue';
   import { list, getDeviceList } from './safety.api';
   import AlarmHistoryTable from '../comment/AlarmHistoryTable.vue';
@@ -265,6 +267,11 @@
   import GroupMonitorTable from '../comment/GroupMonitorTable.vue';
   import { Progress } from 'ant-design-vue';
   import { useRouter } from 'vue-router';
+
+  import FiberModal from './components/fiber-modal.vue';
+  import bundleModal from './components/bundle-modal.vue';
+  import dustModal from './components/dust-modal.vue';
+
   import {
     formConfig,
     chartsColumnsreal,
@@ -317,6 +324,28 @@
 
   let dataSourceHis = shallowRef([]); //历史数据
 
+  let modalVisible = ref<Boolean>(false); // 模态框是否可见
+  let currentModal = shallowRef<Nullable<ComponentOptions>>(null); //模态框
+  let activeID = ref('');
+  let tableData = reactive<any[]>([]);
+
+  //查看详情
+  function getDetail(data) {
+    tableData = dataSource.value.filter((v) => v.strinstallpos == data);
+    activeID.value = tableData[0].deviceID;
+    console.log(tableData, '详情数据-------');
+    if (deviceType.value == 'fiber') {
+      currentModal.value = FiberModal;
+      modalVisible.value = true;
+    } else if (deviceType.value == 'bundletube') {
+      currentModal.value = bundleModal;
+      modalVisible.value = true;
+    } else if (deviceType.value == 'dustdev') {
+      currentModal.value = dustModal;
+      modalVisible.value = true;
+    }
+  }
+
   //历史数据
   async function changeHis(data) {
     alive.value = false;
@@ -397,7 +426,7 @@
     margin-top: 20px;
     display: flex;
     justify-content: center;
-    
+
 
     .tabs-box {
       width: calc(100% - 12px) !important;