lxh 7 ساعت پیش
والد
کامیت
c1d9668a4f

+ 277 - 0
src/views/vent/monitorManager/fanLocalMonitor/components/deviceFaultDetailModal.vue

@@ -0,0 +1,277 @@
+<template>
+  <a-modal v-model:visible="visible" width="1200px" :title="title" centered destroyOnClose :footer="null"
+    @cancel="handleCancel">
+    <div class="basic-top">
+      <div class="top-l">
+        <faultEchartPie :normalNum="normalNum" :abnormalNum="abnormalNum"></faultEchartPie>
+      </div>
+      <div class="top-r">
+        <div class="basic-title">异常测点信息</div>
+        <div class="list-r">
+          <div class="list-item" v-for="(item, index) in faultList" :key="index">
+            <span style="margin-right: 5px;">{{ `${index + 1}.` }}</span>
+            <span>{{ item.label }}</span>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="basic-bot">
+      <div class="basic-content">
+        <div class="basic-title">风速监测曲线</div>
+        <div class="echart-box">
+          <faultEchartLine :selectData="selectData" :warningMonitorRowIndex="warningMonitorRowIndex"
+            :deviceId="deviceID" :deviceType="deviceType" :Type="'windSpeed'" :addData="windsValue" :legendName="'风速'"
+            :echartColor="'#ff0000'"></faultEchartLine>
+        </div>
+      </div>
+      <div class="basic-content">
+        <div class="basic-title">风量监测曲线</div>
+        <div class="echart-box">
+          <faultEchartLine :selectData="selectData" :warningMonitorRowIndex="warningMonitorRowIndex"
+            :deviceId="deviceID" :deviceType="deviceType" :Type="'wind'" :addData="windValue" :legendName="'风量'"
+            :echartColor="'#2ec1dd'"></faultEchartLine>
+        </div>
+      </div>
+      <div class="basic-content">
+        <div class="basic-title">电流监测曲线</div>
+        <div class="echart-box">
+          <faultEchartLine :selectData="selectData" :warningMonitorRowIndex="warningMonitorRowIndex"
+            :deviceId="deviceID" :deviceType="deviceType" :Type="'Dl'" :addData="dlValue" :legendName="'电流'"
+            :echartColor="'#fbc21c'">
+          </faultEchartLine>
+        </div>
+      </div>
+      <div class="basic-content">
+        <div class="basic-title">电压监测曲线</div>
+        <div class="echart-box">
+          <faultEchartLine :selectData="selectData" :warningMonitorRowIndex="warningMonitorRowIndex"
+            :deviceId="deviceID" :deviceType="deviceType" :Type="'Dy'" :addData="dyValue" :legendName="'电压'"
+            :echartColor="'#259745'">
+          </faultEchartLine>
+        </div>
+      </div>
+      <div class="basic-content">
+        <div class="basic-title">瓦斯浓度监测曲线</div>
+        <div class="echart-box">
+          <faultEchartLine :selectData="selectData" :warningMonitorRowIndex="warningMonitorRowIndex"
+            :deviceId="deviceID" :deviceType="deviceType" :Type="'wsnd'" :addData="wsndValue" :legendName="'瓦斯浓度'"
+            :echartColor="'#0fcb74'">
+          </faultEchartLine>
+        </div>
+      </div>
+      <div class="basic-content">
+        <div class="basic-title">振动监测曲线</div>
+        <div class="echart-box">
+          <faultEchartLine :selectData="selectData" :warningMonitorRowIndex="warningMonitorRowIndex"
+            :deviceId="deviceID" :deviceType="deviceType" :Type="'Zd'" :addData="zdValue" :legendName="'振动'"
+            :echartColor="'#00a9ff'">
+          </faultEchartLine>
+        </div>
+      </div>
+    </div>
+  </a-modal>
+</template>
+
+<script setup lang="ts">
+import { computed, reactive, ref, watch } from 'vue'
+import faultEchartPie from './faultEchartPie.vue'
+import faultEchartLine from './faultEchartLine.vue'
+
+let props = defineProps({
+  //是否显示弹窗
+  isShowModal: {
+    type: Boolean
+  },
+  //当前激活风机索引
+  warningMonitorRowIndex: {
+    type: Number
+  },
+  rightColumns: {
+    type: Array as any
+  },
+  selectData: {
+    type: Object as any
+  },
+  deviceID: {
+    type: String
+  },
+  deviceType: {
+    type: String
+  }
+})
+
+let visible = ref(false)
+let title = ref('风机故障诊断分析')
+let faultList = ref<any[]>([])//异常信息列表
+let normalNum = ref(0)//正常测点数量
+let abnormalNum = ref(0)//
+
+let windsValue = computed(() => {
+  return {
+    y: props.warningMonitorRowIndex == 0 ? props.selectData['Fan1WindSpeed'] : props.warningMonitorRowIndex == 1 ? props.selectData['Fan2WindSpeed'] : '',
+    x: props.selectData['tTime'].substring(props.selectData['tTime'].lastIndexOf(' '))
+  }
+}) //实时风速
+let windValue = computed(() => {
+  return {
+    y: props.warningMonitorRowIndex == 0 ? props.selectData['Fan1Wind'] : props.warningMonitorRowIndex == 1 ? props.selectData['Fan2Wind'] : '',
+    x: props.selectData['tTime'].substring(props.selectData['tTime'].lastIndexOf(' '))
+  }
+
+}) //实时风量
+let dlValue = computed(() => {
+  return {
+    y: props.warningMonitorRowIndex == 0 ? props.selectData['Fan1Dl'] : props.warningMonitorRowIndex == 1 ? props.selectData['Fan2Dl'] : '',
+    x: props.selectData['tTime'].substring(props.selectData['tTime'].lastIndexOf(' '))
+  }
+
+}) //实时电流
+let dyValue = computed(() => {
+  return {
+    y: props.warningMonitorRowIndex == 0 ? props.selectData['Fan1Dy'] : props.warningMonitorRowIndex == 1 ? props.selectData['Fan2Dy'] : '',
+    x: props.selectData['tTime'].substring(props.selectData['tTime'].lastIndexOf(' '))
+  }
+
+}) //实时电压
+let wsndValue = computed(() => {
+  return {
+    y: props.warningMonitorRowIndex == 0 ? props.selectData['Fan1Wsnd'] : props.warningMonitorRowIndex == 1 ? props.selectData['Fan2Wsnd'] : '',
+    x: props.selectData['tTime'].substring(props.selectData['tTime'].lastIndexOf(' '))
+  }
+
+}) //实时瓦斯浓度
+let zdValue = computed(() => {
+  return {
+    y: props.warningMonitorRowIndex == 0 ? props.selectData['Fan1Zd'] : props.warningMonitorRowIndex == 1 ? props.selectData['Fan2Zd'] : '',
+    x: props.selectData['tTime'].substring(props.selectData['tTime'].lastIndexOf(' '))
+  }
+
+}) //实时振动
+
+let $emit = defineEmits(['handlerClose'])
+
+
+//弹窗关闭
+function handleCancel() {
+  $emit('handlerClose', false)
+}
+
+watch(() => props.isShowModal, (newV, oldV) => {
+  visible.value = newV
+})
+
+watch(() => props.warningMonitorRowIndex, (newV, oldV) => {
+  // if (props.rightColumns.length) {
+  //   let dataList: any[] = []
+  //   props.rightColumns.forEach((el) => {
+  //     if (el.dataIndex.startsWith('Fan')) {
+  //       if (newV == 0 && props.selectData[el.dataIndex.replace('Fan', 'Fan1')] != undefined) {
+  //         dataList.push({ label: el.title })
+  //       } else if (newV == 1 && props.selectData[el.dataIndex.replace('Fan', 'Fan2')] != undefined && props.selectData[el.dataIndex.replace('Fan', 'Fan2')] != '0') {
+  //         dataList.push({ label: el.title })
+  //       } else if (newV == 2 && props.selectData[el.dataIndex.replace('Fan', 'Fan3')] != undefined && props.selectData[el.dataIndex.replace('Fan', 'Fan3')] != '0') {
+  //         dataList.push({ label: el.title })
+  //       }
+  //     } else {
+  //       if (props.selectData[el.dataIndex] != undefined && props.selectData[el.dataIndex] != '0') {
+  //         dataList.push({ label: el.title })
+  //       }
+  //     }
+  //   })
+  //   faultList.value = dataList
+  //   abnormalNum.value = dataList.length
+  //   normalNum.value = props.rightColumns.length - dataList.length
+  //   console.log(dataList, 'dataList===')
+  // }
+  if (newV == 0) {
+    faultList.value = [
+      { label: '2025年7月12日,风速超限' },
+      { label: '2025年7月21日,风量波动' },
+      { label: '2025年8月4日,轴温偏高' },
+      { label: '2025年8月17日,径向振动过大' },
+      { label: '2025年8月23日,油温高' },
+      { label: '2025年8月26日,电机故障' },
+    ]
+  } else if (newV == 1) {
+    faultList.value = [
+      { label: '2025年8月2日,风速超限' },
+      { label: '2025年8月11日,振动过高' },
+      { label: '2025年8月24日,轴温偏高' },
+      { label: '2025年9月17日,径向振动过大' },
+      { label: '2025年9月23日,油温高' },
+      { label: '2025年9月26日,蝶阀故障' },
+    ]
+  } else {
+    faultList.value = [
+      { label: '2025年8月2日,风门故障' },
+      { label: '2025年8月11日,风量波动' },
+      { label: '2025年8月24日,轴温偏高' },
+      { label: '2025年9月17日,径向振动过大' },
+      { label: '2025年9月23日,变频故障反馈' },
+      { label: '2025年9月26日,电机故障' },
+    ]
+  }
+  abnormalNum.value = faultList.value.length
+  normalNum.value = Math.ceil(Math.random() * 10)
+}, { immediate: true })
+</script>
+
+<style lang="less" scoped>
+.basic-top {
+  width: calc(100% - 30px);
+  height: 220px;
+  margin: 10px;
+  display: flex;
+
+  .top-l {
+    width: 320px;
+    margin-right: 10px;
+  }
+
+  .top-r {
+    width: calc(100% - 330px);
+  }
+
+  .list-r {
+    height: calc(100% - 25px);
+    padding: 0px 10px;
+    box-sizing: border-box;
+    overflow-y: auto;
+    border: 1px solid #3062a2;
+  }
+
+  .list-item {
+    margin: 5px 0px;
+  }
+}
+
+.basic-title {
+  height: 20px;
+  line-height: 20px;
+  font-weight: bold;
+  margin-bottom: 5px;
+}
+
+.basic-bot {
+  width: calc(100% - 30px);
+  height: 600px;
+  margin: 10px;
+  display: flex;
+  justify-content: space-between;
+  flex-wrap: wrap;
+  overflow-y: auto;
+
+  .basic-content {
+    width: calc(50% - 5px);
+    height: 240px;
+    margin-bottom: 10px;
+    padding: 5px 10px;
+    box-sizing: border-box;
+    border: 1px solid #3062a2;
+  }
+
+  .echart-box {
+    height: calc(100% - 25px);
+  }
+}
+</style>

+ 331 - 0
src/views/vent/monitorManager/fanLocalMonitor/components/faultEchartLine.vue

@@ -0,0 +1,331 @@
+<template>
+  <div class="faultEchartLine">
+    <div class="box-search">
+      <a-date-picker v-model:value="historyParams.startTime" valueFormat="YYYY-MM-DD HH:mm:ss" placeholder="开始时间"
+        size="small" :showTime="true" style="position: absolute; z-index: 99; left: 0px; width: 170px; top: 2px"
+        @change="changeStart" />
+      <a-date-picker v-model:value="historyParams.endTime" valueFormat="YYYY-MM-DD HH:mm:ss" placeholder="结束时间"
+        size="small" :showTime="true" style="position: absolute; z-index: 99; left: 175px; width: 170px; top: 2px"
+        @change="changeEnd" />
+      <a-select ref="select" v-model:value="historyParams.interval" placeholder="请选择间隔时间" size="small"
+        style="position: absolute; z-index: 99; top: 2px; left: 350px; width: 150px">
+        <a-select-option v-for="(item, index) in skipOption" :key="index" :value="item.value">{{ item.label
+          }}</a-select-option>
+      </a-select>
+    </div>
+    <div ref="echartline" class="echart-line"></div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import dayjs from 'dayjs';
+import { ref, reactive, onMounted, nextTick, watch } from 'vue'
+import * as echarts from 'echarts';
+import { listdays, getHistoryData } from '../fanLocal.api'
+
+let props = defineProps({
+  //当前激活风机索引
+  warningMonitorRowIndex: {
+    type: Number
+  },
+  deviceId: {
+    type: String
+  },
+  deviceType: {
+    type: String
+  },
+  Type: {
+    type: String
+  },
+  addData: {
+    type: Object as any
+  },
+  legendName: {
+    type: String
+  },
+  echartColor: {
+    type: String
+  },
+  selectData: {
+    type: Object as any
+  }
+})
+
+let skipOption = ref<any[]>([
+  { label: '1秒', value: '1' },
+  { label: '5秒', value: '2' },
+  { label: '10秒', value: '3' },
+  { label: '30秒', value: '4' },
+  { label: '1分钟', value: '5' },
+  { label: '10分钟', value: '6' },
+  { label: '30分钟', value: '7' },
+  { label: '1小时', value: '8' },
+  { label: '1天', value: '9' },
+])
+let historyParams = reactive({
+  skip: '8',
+  startTime: dayjs().startOf('date').subtract(1, 'day').format('YYYY-MM-DD HH:mm:ss'),
+  endTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
+  interval: '1h',
+})
+let echartline = ref(null)
+let xData = ref<any[]>([])
+let yData = ref<any[]>([])
+
+function changeStart(val) {
+  historyParams.startTime = val
+  getData()
+}
+function changeEnd(val) {
+  historyParams.endTime = val
+  getData()
+}
+function getOption() {
+  nextTick(() => {
+    let myChart = echarts.init(echartline.value);
+    let option = {
+      grid: {
+        top: '22%',
+        left: '5%',
+        bottom: '13%',
+        right: '5%',
+        //   containLabel: true,
+      },
+      tooltip: {
+        trigger: 'axis',
+        backgroundColor: 'rgba(0, 0, 0, .6)',
+        textStyle: {
+          color: '#fff',
+          fontSize: 12,
+        },
+      },
+      legend: {
+        align: 'left',
+        right: 'center',
+        top: '10',
+        type: 'plain',
+        textStyle: {
+          color: '#7ec7ff',
+          fontSize: 14,
+        },
+        // icon:'rect',
+        itemGap: 25,
+        itemWidth: 18,
+        icon: 'path://M0 2a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v0a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2z',
+        data: [
+          {
+            name: props.legendName,
+          },
+        ],
+      },
+      xAxis: [
+        {
+          type: 'category',
+          boundaryGap: false,
+          axisLabel: {
+            // formatter: '{value}',
+            fontSize: 14,
+            margin: 20,
+            textStyle: {
+              color: '#b3b8cc',
+            },
+          },
+          axisLine: {
+            lineStyle: {
+              color: 'rgba(48, 98, 162,.4)',
+            },
+          },
+          splitLine: {
+            show: false,
+          },
+          axisTick: {
+            show: false,
+          },
+          data: xData.value,
+        },
+      ],
+      yAxis: [
+        {
+          boundaryGap: false,
+          type: 'value',
+          // max: props.maxY,
+          // min: props.minY,
+          axisLabel: {
+            textStyle: {
+              color: '#b3b8cc',
+            },
+            formatter: '{value}',
+          },
+          name: '',
+          nameTextStyle: {
+            color: '#fff',
+            fontSize: 12,
+            lineHeight: 10,
+          },
+          splitLine: {
+            lineStyle: {
+              color: 'rgba(48, 98, 162,.4)',
+            },
+          },
+          axisLine: {
+            show: true,
+            lineStyle: {
+              color: 'rgba(48, 98, 162,.4)',
+            },
+          },
+          axisTick: {
+            show: false,
+          },
+        },
+      ],
+      series: [
+        {
+          name: props.legendName,
+          type: 'line',
+          smooth: true,
+          symbol: 'none',
+          zlevel: 3,
+          itemStyle: {
+            color: props.echartColor,
+            borderColor: props.echartColor,
+          },
+          lineStyle: {
+            normal: {
+              width: 2,
+              color: props.echartColor,
+            },
+          },
+          data: yData.value,
+        },
+      ],
+    };
+    myChart.setOption(option);
+    window.onresize = function () {
+      myChart.resize();
+    };
+  });
+}
+
+async function getData() {
+  if (props.selectData.stationtype && props.selectData.stationtype != 'redis') {
+    let res = await listdays({ ttime_begin: historyParams.startTime, ttime_end: historyParams.endTime, strtype: props.deviceType, gdeviceid: props.deviceId, skip: historyParams.skip, pageSize: 100, pageNo: 1 })
+    let data = res.datalist.records
+    xData.value = res.xlist
+    if (props.Type == 'windSpeed') {
+      yData.value = props.warningMonitorRowIndex == 0 ? data.map(el => el.readData.Fan1WindSpeed) : data.map(el => el.readData.Fan2WindSpeed)
+    } else if (props.Type == 'wind') {
+      yData.value = props.warningMonitorRowIndex == 0 ? data.map(el => el.readData.Fan1Wind) : data.map(el => el.readData.Fan2Wind)
+    } else if (props.Type == 'Dl') {
+      yData.value = props.warningMonitorRowIndex == 0 ? data.map(el => el.readData.Fan1Dl) : data.map(el => el.readData.Fan2Dl)
+    } else if (props.Type == 'Dy') {
+      yData.value = props.warningMonitorRowIndex == 0 ? data.map(el => el.readData.Fan1Dy) : data.map(el => el.readData.Fan2Dy)
+    } else if (props.Type == 'wsnd') {
+      yData.value = props.warningMonitorRowIndex == 0 ? data.map(el => el.readData.Fan1Wsnd) : data.map(el => el.readData.Fan2Wsnd)
+    } else if (props.Type == 'Zd') {
+      yData.value = props.warningMonitorRowIndex == 0 ? data.map(el => el.readData.Fan1Zd) : data.map(el => el.readData.Fan2Zd)
+    }
+    getOption()
+  } else {
+    let res = await getHistoryData({ pageNum: 1, pageSize: 100, startTime: historyParams.startTime, endTime: historyParams.endTime, deviceId: props.deviceId, interval: '1h', isEmployee: true, })
+    let data = res.records
+    xData.value = res.xlist
+    if (props.Type == 'windSpeed') {
+      yData.value = props.warningMonitorRowIndex == 0 ? data.map(el => el.readData.Fan1WindSpeed) : data.map(el => el.readData.Fan2WindSpeed)
+    } else if (props.Type == 'wind') {
+      yData.value = props.warningMonitorRowIndex == 0 ? data.map(el => el.readData.Fan1Wind) : data.map(el => el.readData.Fan2Wind)
+    } else if (props.Type == 'Dl') {
+      yData.value = props.warningMonitorRowIndex == 0 ? data.map(el => el.readData.Fan1Dl) : data.map(el => el.readData.Fan2Dl)
+    } else if (props.Type == 'Dy') {
+      yData.value = props.warningMonitorRowIndex == 0 ? data.map(el => el.readData.Fan1Dy) : data.map(el => el.readData.Fan2Dy)
+    } else if (props.Type == 'wsnd') {
+      yData.value = props.warningMonitorRowIndex == 0 ? data.map(el => el.readData.Fan1Wsnd) : data.map(el => el.readData.Fan2Wsnd)
+    } else if (props.Type == 'Zd') {
+      yData.value = props.warningMonitorRowIndex == 0 ? data.map(el => el.readData.Fan1Zd) : data.map(el => el.readData.Fan2Zd)
+    }
+    getOption()
+  }
+
+}
+
+watch(() => props.addData, (newV, oldV) => {
+  if (yData.value.length >= 20) {
+    yData.value.push(newV.y)
+    yData.value.shift()
+    xData.value.push(newV.x)
+    xData.value.shift()
+  } else {
+    yData.value.push(newV.y)
+    xData.value.push(newV.x)
+  }
+  getOption()
+}, { immediate: true })
+onMounted(() => {
+  getData()
+})
+
+</script>
+
+<style lang="less" scoped>
+@import '/@/design/theme.less';
+
+.faultEchartLine {
+  position: relative;
+  width: 100%;
+  height: 100%;
+}
+
+.box-search {
+  width: 100%;
+  height: 30px;
+}
+
+.echart-line {
+  width: 100%;
+  height: calc(100% - 30px);
+}
+
+.@{ventSpace}-picker {
+  background: #00000017 !important;
+  border: 1px solid @vent-form-item-border !important;
+
+  input,
+  .@{ventSpace}-select-selection-item,
+  .@{ventSpace}-picker-suffix {
+    color: #fff !important;
+  }
+
+  .@{ventSpace}-select-selection-placeholder {
+    color: #b7b7b7 !important;
+  }
+}
+
+.@{ventSpace}-picker-separator {
+  color: #fff !important;
+}
+
+:deep(.@{ventSpace}-select-dropdown) {
+  color: #000 !important;
+
+  .@{ventSpace}-select-item {
+    color: #000 !important;
+  }
+}
+
+:deep(.@{ventSpace}-picker-input > input) {
+  color: #fff !important;
+}
+
+:deep(.@{ventSpace}-picker-suffix) {
+  color: #fff !important;
+}
+
+:deep(.@{ventSpace}-select-selector) {
+  color: #fff !important;
+  background: #00000017 !important;
+  border: 1px solid @vent-form-item-border !important;
+}
+
+:deep(.@{ventSpace}-select-arrow) {
+  color: #fff !important;
+}
+</style>

+ 110 - 0
src/views/vent/monitorManager/fanLocalMonitor/components/faultEchartPie.vue

@@ -0,0 +1,110 @@
+<template>
+  <div ref="faultPie" class="faultPie"></div>
+</template>
+
+<script setup lang="ts">
+import { nextTick, onMounted, ref } from 'vue'
+import * as echarts from 'echarts';
+
+let props = defineProps({
+  //正常测点
+  normalNum: {
+    type: Number
+  },
+  //异常测点
+  abnormalNum: {
+    type: Number
+  }
+})
+let faultPie = ref(null)
+
+function getOption() {
+  nextTick(() => {
+    let myChart = echarts.init(faultPie.value);
+    let option = {
+      tooltip: {
+        trigger: "item",
+        formatter: "{b} : {c}",
+        backgroundColor: 'rgba(0, 0, 0, .6)',
+        textStyle: {
+          color: '#fff',
+          fontSize: 12,
+        },
+      },
+
+      // 图例移到右边(竖排)
+      legend: {
+        right: 'center',
+        top: "bottom",
+        type: 'plain',
+        textStyle: {
+          color: '#fff',
+          fontSize: 12,
+        },
+        // icon:'rect',
+        itemGap: 10,
+        itemWidth: 10,
+        // icon: 'path://M0 2a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v0a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2z',
+      },
+
+      series: [
+        {
+          name: "",
+          type: "pie",
+          radius: ["50%", "75%"],
+          center: ["50%", "47%"],  // ⭐ 为让位图例,整体饼图左移
+          label: {
+            color: "#fff",
+            fontSize: 12,
+            show: false
+          },
+
+          data: [
+            {
+              name: '正常测点',
+              value: props.normalNum || 0,
+              itemStyle: {
+                borderRadius: 10, // ⭐ 扇形圆角
+                color: new echarts.graphic.LinearGradient(0, 0, 1, 1, [
+                  { offset: 0, color: '#14ee59' },
+                  { offset: 1, color: '#14ee59' },
+                ]),
+                shadowBlur: 18,
+                shadowColor: "rgba(0,0,0,0.25)",
+              },
+            },
+            {
+              name: '异常测点',
+              value: props.abnormalNum || 0,
+              itemStyle: {
+                borderRadius: 10, // ⭐ 扇形圆角
+                color: new echarts.graphic.LinearGradient(0, 0, 1, 1, [
+                  { offset: 0, color: '#f20707' },
+                  { offset: 1, color: '#f20707' },
+                ]),
+                shadowBlur: 18,
+                shadowColor: "rgba(0,0,0,0.25)",
+              },
+            }
+          ],
+        },
+      ],
+    };
+    myChart.setOption(option);
+    window.onresize = function () {
+      myChart.resize();
+    };
+  });
+}
+
+onMounted(() => {
+  getOption()
+})
+</script>
+
+<style lang="less" scoped>
+.faultPie {
+  width: 100%;
+  height: 100%;
+}
+</style>

+ 8 - 0
src/views/vent/monitorManager/fanLocalMonitor/fanLocal.api.ts

@@ -11,6 +11,8 @@ enum Api {
   importExcel = '/sys/user/importExcel',
   exportXls = '/sys/user/exportXls',
   autoAdjust = '/safety/ventanalyFan/updateFanlocalAutoAdjustStatus',
+  listdays = '/safety/ventanalyMonitorData/listdays',
+   getHistoryData = '/monitor/history/getHistoryData',
 }
 /**
  * 导出api
@@ -63,3 +65,9 @@ export const saveOrUpdate = (params, isUpdate) => {
   const url = isUpdate ? Api.edit : Api.save;
   return defHttp.put({ url: url, params });
 };
+
+/**
+ * 历史数据
+ */
+export const listdays = (params) => defHttp.get({ url: Api.listdays, params });
+export const getHistoryData = (params) => defHttp.post({ url: Api.getHistoryData, params });

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 810 - 937
src/views/vent/monitorManager/fanLocalMonitor/index.vue


+ 98 - 42
src/views/vent/monitorManager/mainFanMonitor/components/deviceFaultDetailModal.vue

@@ -9,7 +9,7 @@
         <div class="basic-title">异常测点信息</div>
         <div class="list-r">
           <div class="list-item" v-for="(item, index) in faultList" :key="index">
-            <span>{{ `${index + 1}.` }}</span>
+            <span style="margin-right: 5px;">{{ `${index + 1}.` }}</span>
             <span>{{ item.label }}</span>
           </div>
         </div>
@@ -19,48 +19,52 @@
       <div class="basic-content">
         <div class="basic-title">轴温监测曲线</div>
         <div class="echart-box">
-          <faultEchartLine :warningMonitorRowIndex="warningMonitorRowIndex" :deviceId="deviceID"
-            :deviceType="deviceType" :Type="'tempZw'" :addData="tempzwValue" :legendName="'轴温'"
+          <faultEchartLine :selectData="selectData" :warningMonitorRowIndex="warningMonitorRowIndex"
+            :deviceId="deviceID" :deviceType="deviceType" :Type="'tempZw'" :addData="tempzwValue" :legendName="'轴温'"
             :echartColor="'#ff0000'"></faultEchartLine>
         </div>
       </div>
       <div class="basic-content">
         <div class="basic-title">电机温度监测曲线</div>
         <div class="echart-box">
-          <faultEchartLine :warningMonitorRowIndex="warningMonitorRowIndex" :deviceId="deviceID"
-            :deviceType="deviceType" :Type="'tempDj'" :addData="tempdjValue" :legendName="'电机温度'"
+          <faultEchartLine :selectData="selectData" :warningMonitorRowIndex="warningMonitorRowIndex"
+            :deviceId="deviceID" :deviceType="deviceType" :Type="'tempDj'" :addData="tempdjValue" :legendName="'电机温度'"
             :echartColor="'#2ec1dd'"></faultEchartLine>
         </div>
       </div>
       <div class="basic-content">
         <div class="basic-title">电流监测曲线</div>
         <div class="echart-box">
-          <faultEchartLine :warningMonitorRowIndex="warningMonitorRowIndex" :deviceId="deviceID"
-            :deviceType="deviceType" :Type="'Dl'" :addData="dlValue" :legendName="'电流'" :echartColor="'#fbc21c'">
+          <faultEchartLine :selectData="selectData" :warningMonitorRowIndex="warningMonitorRowIndex"
+            :deviceId="deviceID" :deviceType="deviceType" :Type="'Dl'" :addData="dlValue" :legendName="'电流'"
+            :echartColor="'#fbc21c'">
           </faultEchartLine>
         </div>
       </div>
       <div class="basic-content">
         <div class="basic-title">电压监测曲线</div>
         <div class="echart-box">
-          <faultEchartLine :warningMonitorRowIndex="warningMonitorRowIndex" :deviceId="deviceID"
-            :deviceType="deviceType" :Type="'Dy'" :addData="dyValue" :legendName="'电压'" :echartColor="'#259745'">
+          <faultEchartLine :selectData="selectData" :warningMonitorRowIndex="warningMonitorRowIndex"
+            :deviceId="deviceID" :deviceType="deviceType" :Type="'Dy'" :addData="dyValue" :legendName="'电压'"
+            :echartColor="'#259745'">
           </faultEchartLine>
         </div>
       </div>
       <div class="basic-content">
         <div class="basic-title">径向振动监测曲线</div>
         <div class="echart-box">
-          <faultEchartLine :warningMonitorRowIndex="warningMonitorRowIndex" :deviceId="deviceID"
-            :deviceType="deviceType" :Type="'jxzd'" :addData="jxzdValue" :legendName="'径向振动'" :echartColor="'#0fcb74'">
+          <faultEchartLine :selectData="selectData" :warningMonitorRowIndex="warningMonitorRowIndex"
+            :deviceId="deviceID" :deviceType="deviceType" :Type="'jxzd'" :addData="jxzdValue" :legendName="'径向振动'"
+            :echartColor="'#0fcb74'">
           </faultEchartLine>
         </div>
       </div>
       <div class="basic-content">
         <div class="basic-title">垂直振动监测曲线</div>
         <div class="echart-box">
-          <faultEchartLine :warningMonitorRowIndex="warningMonitorRowIndex" :deviceId="deviceID"
-            :deviceType="deviceType" :Type="'czzd'" :addData="czzdValue" :legendName="'垂直振动'" :echartColor="'#00a9ff'">
+          <faultEchartLine :selectData="selectData" :warningMonitorRowIndex="warningMonitorRowIndex"
+            :deviceId="deviceID" :deviceType="deviceType" :Type="'czzd'" :addData="czzdValue" :legendName="'垂直振动'"
+            :echartColor="'#00a9ff'">
           </faultEchartLine>
         </div>
       </div>
@@ -103,22 +107,46 @@ let normalNum = ref(0)//正常测点数量
 let abnormalNum = ref(0)//
 
 let tempzwValue = computed(() => {
-  return props.warningMonitorRowIndex == 0 ? props.selectData['Fan1Tempzw'] : props.warningMonitorRowIndex == 1 ? props.selectData['Fan2Tempzw'] : ''
+  return {
+    y: props.warningMonitorRowIndex == 0 ? props.selectData['Fan1Tempzw'] : props.warningMonitorRowIndex == 1 ? props.selectData['Fan2Tempzw'] : '',
+    x: props.selectData['tTime'].substring(props.selectData['tTime'].lastIndexOf(' '))
+  }
+
 }) //实时轴温
 let tempdjValue = computed(() => {
-  return props.warningMonitorRowIndex == 0 ? props.selectData['Fan1Tempdj'] : props.warningMonitorRowIndex == 1 ? props.selectData['Fan2Tempdj'] : ''
+  return {
+    y: props.warningMonitorRowIndex == 0 ? props.selectData['Fan1Tempdj'] : props.warningMonitorRowIndex == 1 ? props.selectData['Fan2Tempdj'] : '',
+    x: props.selectData['tTime'].substring(props.selectData['tTime'].lastIndexOf(' '))
+  }
+
 }) //实时电机温度
 let dlValue = computed(() => {
-  return props.warningMonitorRowIndex == 0 ? props.selectData['Fan1Dl'] : props.warningMonitorRowIndex == 1 ? props.selectData['Fan2Dl'] : ''
+  return {
+    y: props.warningMonitorRowIndex == 0 ? props.selectData['Fan1Dl'] : props.warningMonitorRowIndex == 1 ? props.selectData['Fan2Dl'] : '',
+    x: props.selectData['tTime'].substring(props.selectData['tTime'].lastIndexOf(' '))
+  }
+
 }) //实时电流
 let dyValue = computed(() => {
-  return props.warningMonitorRowIndex == 0 ? props.selectData['Fan1Dy'] : props.warningMonitorRowIndex == 1 ? props.selectData['Fan2Dy'] : ''
+  return {
+    y: props.warningMonitorRowIndex == 0 ? props.selectData['Fan1Dy'] : props.warningMonitorRowIndex == 1 ? props.selectData['Fan2Dy'] : '',
+    x: props.selectData['tTime'].substring(props.selectData['tTime'].lastIndexOf(' '))
+  }
+
 }) //实时电压
 let jxzdValue = computed(() => {
-  return props.warningMonitorRowIndex == 0 ? props.selectData['Fan1Jxzd'] : props.warningMonitorRowIndex == 1 ? props.selectData['Fan2Jxzd'] : ''
+  return {
+    y: props.warningMonitorRowIndex == 0 ? props.selectData['Fan1Jxzd'] : props.warningMonitorRowIndex == 1 ? props.selectData['Fan2Jxzd'] : '',
+    x: props.selectData['tTime'].substring(props.selectData['tTime'].lastIndexOf(' '))
+  }
+
 }) //实时径向振动
 let czzdValue = computed(() => {
-  return props.warningMonitorRowIndex == 0 ? props.selectData['Fan1Czzd'] : props.warningMonitorRowIndex == 1 ? props.selectData['Fan2Czzd'] : ''
+  return {
+    y: props.warningMonitorRowIndex == 0 ? props.selectData['Fan1Czzd'] : props.warningMonitorRowIndex == 1 ? props.selectData['Fan2Czzd'] : '',
+    x: props.selectData['tTime'].substring(props.selectData['tTime'].lastIndexOf(' '))
+  }
+
 }) //实时垂直振动
 
 let $emit = defineEmits(['handlerClose'])
@@ -134,30 +162,58 @@ watch(() => props.isShowModal, (newV, oldV) => {
 })
 
 watch(() => props.warningMonitorRowIndex, (newV, oldV) => {
-  if (props.rightColumns.length) {
-    let dataList: any[] = []
-    console.log(newV, 'new===')
-    props.rightColumns.forEach((el) => {
-      if (el.dataIndex.startsWith('Fan')) {
-        if (newV == 0 && props.selectData[el.dataIndex.replace('Fan', 'Fan1')] == '0') {
-          //&& props.selectData[el.dataIndex.replace('Fan', 'Fan1')] != undefined
-          dataList.push({ label: el.title })
-        } else if (newV == 1 && props.selectData[el.dataIndex.replace('Fan', 'Fan2')] != undefined && props.selectData[el.dataIndex.replace('Fan', 'Fan2')] != '0') {
-          dataList.push({ label: el.title })
-        } else if (newV == 2 && props.selectData[el.dataIndex.replace('Fan', 'Fan3')] != undefined && props.selectData[el.dataIndex.replace('Fan', 'Fan3')] != '0') {
-          dataList.push({ label: el.title })
-        }
-      } else {
-        if (props.selectData[el.dataIndex] != undefined && props.selectData[el.dataIndex] != '0') {
-          dataList.push({ label: el.title })
-        }
-      }
-    })
-    faultList.value = dataList
-    abnormalNum.value = dataList.length
-    normalNum.value = props.rightColumns.length - dataList.length
-    console.log(dataList, 'dataList===')
+  // if (props.rightColumns.length) {
+  //   let dataList: any[] = []
+  //   props.rightColumns.forEach((el) => {
+  //     if (el.dataIndex.startsWith('Fan')) {
+  //       if (newV == 0 && props.selectData[el.dataIndex.replace('Fan', 'Fan1')] != undefined) {
+  //         dataList.push({ label: el.title })
+  //       } else if (newV == 1 && props.selectData[el.dataIndex.replace('Fan', 'Fan2')] != undefined && props.selectData[el.dataIndex.replace('Fan', 'Fan2')] != '0') {
+  //         dataList.push({ label: el.title })
+  //       } else if (newV == 2 && props.selectData[el.dataIndex.replace('Fan', 'Fan3')] != undefined && props.selectData[el.dataIndex.replace('Fan', 'Fan3')] != '0') {
+  //         dataList.push({ label: el.title })
+  //       }
+  //     } else {
+  //       if (props.selectData[el.dataIndex] != undefined && props.selectData[el.dataIndex] != '0') {
+  //         dataList.push({ label: el.title })
+  //       }
+  //     }
+  //   })
+  //   faultList.value = dataList
+  //   abnormalNum.value = dataList.length
+  //   normalNum.value = props.rightColumns.length - dataList.length
+  //   console.log(dataList, 'dataList===')
+  // }
+  if (newV == 0) {
+    faultList.value = [
+      { label: '2025年7月12日,风速超限' },
+      { label: '2025年7月21日,风量波动' },
+      { label: '2025年8月4日,轴温偏高' },
+      { label: '2025年8月17日,径向振动过大' },
+      { label: '2025年8月23日,油温高' },
+      { label: '2025年8月26日,电机故障' },
+    ]
+  } else if (newV == 1) {
+    faultList.value = [
+      { label: '2025年8月2日,风速超限' },
+      { label: '2025年8月11日,振动过高' },
+      { label: '2025年8月24日,轴温偏高' },
+      { label: '2025年9月17日,径向振动过大' },
+      { label: '2025年9月23日,油温高' },
+      { label: '2025年9月26日,蝶阀故障' },
+    ]
+  } else {
+    faultList.value = [
+      { label: '2025年8月2日,风门故障' },
+      { label: '2025年8月11日,风量波动' },
+      { label: '2025年8月24日,轴温偏高' },
+      { label: '2025年9月17日,径向振动过大' },
+      { label: '2025年9月23日,变频故障反馈' },
+      { label: '2025年9月26日,电机故障' },
+    ]
   }
+  abnormalNum.value = faultList.value.length
+  normalNum.value = Math.ceil(Math.random() * 10)
 }, { immediate: true })
 </script>
 

+ 49 - 22
src/views/vent/monitorManager/mainFanMonitor/components/faultEchartLine.vue

@@ -21,7 +21,7 @@
 import dayjs from 'dayjs';
 import { ref, reactive, onMounted, nextTick, watch } from 'vue'
 import * as echarts from 'echarts';
-import { listdays } from '../main.api'
+import { listdays, getHistoryData } from '../main.api'
 
 let props = defineProps({
   //当前激活风机索引
@@ -38,13 +38,16 @@ let props = defineProps({
     type: String
   },
   addData: {
-    type: String
+    type: Object as any
   },
   legendName: {
     type: String
   },
   echartColor: {
     type: String
+  },
+  selectData: {
+    type: Object as any
   }
 })
 
@@ -61,7 +64,7 @@ let skipOption = ref<any[]>([
 ])
 let historyParams = reactive({
   skip: '8',
-  startTime: dayjs().startOf('date').format('YYYY-MM-DD HH:mm:ss'),
+  startTime: dayjs().startOf('date').subtract(1, 'day').format('YYYY-MM-DD HH:mm:ss'),
   endTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
   interval: '1h',
 })
@@ -204,31 +207,55 @@ function getOption() {
 }
 
 async function getData() {
-  let res = await listdays({ ttime_begin: historyParams.startTime, ttime_end: historyParams.endTime, strtype: props.deviceType, gdeviceid: props.deviceId, skip: historyParams.skip, pageSize: 100, pageNo: 1 })
-  let data = res.datalist.records
-  xData.value = res.xlist
-  if (props.Type == 'tempZw') {
-    yData.value = props.warningMonitorRowIndex == 0 ? data.map(el => el.readData.Fan1Tempzw) : data.map(el => el.readData.Fan2Tempzw)
-  } else if (props.Type == 'tempDj') {
-    yData.value = props.warningMonitorRowIndex == 0 ? data.map(el => el.readData.Fan1Tempdj) : data.map(el => el.readData.Fan2Tempdj)
-  } else if (props.Type == 'Dl') {
-    yData.value = props.warningMonitorRowIndex == 0 ? data.map(el => el.readData.Fan1Dl) : data.map(el => el.readData.Fan2Dl)
-  } else if (props.Type == 'Dy') {
-    yData.value = props.warningMonitorRowIndex == 0 ? data.map(el => el.readData.Fan1Dy) : data.map(el => el.readData.Fan2Dy)
-  } else if (props.Type == 'jxzd') {
-    yData.value = props.warningMonitorRowIndex == 0 ? data.map(el => el.readData.Fan1Jxzd) : data.map(el => el.readData.Fan2Jxzd)
-  } else if (props.Type == 'czzd') {
-    yData.value = props.warningMonitorRowIndex == 0 ? data.map(el => el.readData.Fan1Czzd) : data.map(el => el.readData.Fan2Czzd)
+  if (props.selectData.stationtype && props.selectData.stationtype != 'redis') {
+    let res = await listdays({ ttime_begin: historyParams.startTime, ttime_end: historyParams.endTime, strtype: props.deviceType, gdeviceid: props.deviceId, skip: historyParams.skip, pageSize: 100, pageNo: 1 })
+    let data = res.datalist.records
+    xData.value = res.xlist
+    if (props.Type == 'tempZw') {
+      yData.value = props.warningMonitorRowIndex == 0 ? data.map(el => el.readData.Fan1Tempzw) : data.map(el => el.readData.Fan2Tempzw)
+    } else if (props.Type == 'tempDj') {
+      yData.value = props.warningMonitorRowIndex == 0 ? data.map(el => el.readData.Fan1Tempdj) : data.map(el => el.readData.Fan2Tempdj)
+    } else if (props.Type == 'Dl') {
+      yData.value = props.warningMonitorRowIndex == 0 ? data.map(el => el.readData.Fan1Dl) : data.map(el => el.readData.Fan2Dl)
+    } else if (props.Type == 'Dy') {
+      yData.value = props.warningMonitorRowIndex == 0 ? data.map(el => el.readData.Fan1Dy) : data.map(el => el.readData.Fan2Dy)
+    } else if (props.Type == 'jxzd') {
+      yData.value = props.warningMonitorRowIndex == 0 ? data.map(el => el.readData.Fan1Jxzd) : data.map(el => el.readData.Fan2Jxzd)
+    } else if (props.Type == 'czzd') {
+      yData.value = props.warningMonitorRowIndex == 0 ? data.map(el => el.readData.Fan1Czzd) : data.map(el => el.readData.Fan2Czzd)
+    }
+    getOption()
+  } else {
+    let res = await getHistoryData({ pageNum: 1, pageSize: 100, startTime: historyParams.startTime, endTime: historyParams.endTime, deviceId: props.deviceId, interval: '1h', isEmployee: true, })
+    let data = res.records
+    xData.value = res.xlist
+    if (props.Type == 'tempZw') {
+      yData.value = props.warningMonitorRowIndex == 0 ? data.map(el => el.readData.Fan1Tempzw) : data.map(el => el.readData.Fan2Tempzw)
+    } else if (props.Type == 'tempDj') {
+      yData.value = props.warningMonitorRowIndex == 0 ? data.map(el => el.readData.Fan1Tempdj) : data.map(el => el.readData.Fan2Tempdj)
+    } else if (props.Type == 'Dl') {
+      yData.value = props.warningMonitorRowIndex == 0 ? data.map(el => el.readData.Fan1Dl) : data.map(el => el.readData.Fan2Dl)
+    } else if (props.Type == 'Dy') {
+      yData.value = props.warningMonitorRowIndex == 0 ? data.map(el => el.readData.Fan1Dy) : data.map(el => el.readData.Fan2Dy)
+    } else if (props.Type == 'jxzd') {
+      yData.value = props.warningMonitorRowIndex == 0 ? data.map(el => el.readData.Fan1Jxzd) : data.map(el => el.readData.Fan2Jxzd)
+    } else if (props.Type == 'czzd') {
+      yData.value = props.warningMonitorRowIndex == 0 ? data.map(el => el.readData.Fan1Czzd) : data.map(el => el.readData.Fan2Czzd)
+    }
+    getOption()
   }
-  getOption()
+
 }
 
 watch(() => props.addData, (newV, oldV) => {
-  if (yData.value.length>=10) {
-    yData.value.push(newV)
+  if (yData.value.length >= 20) {
+    yData.value.push(newV.y)
     yData.value.shift()
+    xData.value.push(newV.x)
+    xData.value.shift()
   } else {
-    yData.value.push(newV)
+    yData.value.push(newV.y)
+    xData.value.push(newV.x)
   }
   getOption()
 }, { immediate: true })

+ 3 - 1
src/views/vent/monitorManager/mainFanMonitor/main.api.ts

@@ -14,7 +14,8 @@ enum Api {
   pointMonitor = '/monitor/onedevice',
   getFaultDiagnosis = '/monitor/getFaultDiagnosis',
   exportMonitorData = '/ventanaly-device/monitor/exportDeviceMonitorData',
-  listdays = '/safety/ventanalyMonitorData/listdays'
+  listdays = '/safety/ventanalyMonitorData/listdays',
+   getHistoryData = '/monitor/history/getHistoryData',
 }
 /**
  * 导出api
@@ -51,6 +52,7 @@ export const deviceList = (params) => defHttp.get({ url: Api.deviceList, params
  * 历史数据
  */
 export const listdays = (params) => defHttp.get({ url: Api.listdays, params });
+export const getHistoryData = (params) => defHttp.post({ url: Api.getHistoryData, params });
 
 // 风机曲线方程
 export const lineList = (params) => defHttp.get({ url: Api.lineList, params });

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است