فهرست منبع

开发首页录波展示

xusl 1 سال پیش
والد
کامیت
9b3c6179a6

+ 50 - 0
backend/src/main/java/com/jiayue/pfr/controller/alg/FaultRecorderDataController.java

@@ -0,0 +1,50 @@
+package com.jiayue.pfr.controller.alg;
+
+import cn.hutool.core.date.DateUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.jiayue.pfr.constant.CustomException;
+import com.jiayue.pfr.dto.DzFormDto;
+import com.jiayue.pfr.entity.FaultRecorderData;
+import com.jiayue.pfr.entity.ProtocolGatherDataPoint;
+import com.jiayue.pfr.entity.SysParameter;
+import com.jiayue.pfr.service.alg.FaultRecorderDataService;
+import com.jiayue.pfr.util.SaResultRefit;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * 录波数据类
+ *
+ * @author jy
+ * @since 2023/11/10
+ */
+@RestController
+@RequestMapping("/faultRecorderDataController")
+@Slf4j
+public class FaultRecorderDataController {
+    @Autowired
+    FaultRecorderDataService faultRecorderDataService;
+
+    /**
+     * 获取当日录波数据
+     */
+    @GetMapping(value = "/getFdList")
+    public SaResultRefit getFdList() throws CustomException {
+        try {
+            QueryWrapper<FaultRecorderData> wrapper = new QueryWrapper<>();
+            wrapper.lambda().between(FaultRecorderData::getCreateTime, DateUtil.beginOfDay(new Date()),DateUtil.endOfDay(new Date()));
+            List<FaultRecorderData> faultRecorderDataList = faultRecorderDataService.list(wrapper);
+            return SaResultRefit.data(faultRecorderDataList);
+        } catch (Exception e) {
+            throw new CustomException("获取当日录波数据异常", e);
+        }
+    }
+}

+ 55 - 0
backend/src/main/java/com/jiayue/pfr/controller/alg/FaultRecorderDetailController.java

@@ -0,0 +1,55 @@
+package com.jiayue.pfr.controller.alg;
+
+import cn.hutool.core.date.DateUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.jiayue.pfr.constant.CustomException;
+import com.jiayue.pfr.entity.FaultRecorderData;
+import com.jiayue.pfr.entity.FaultRecorderDetail;
+import com.jiayue.pfr.entity.ProtocolSenderDataPoint;
+import com.jiayue.pfr.service.alg.FaultRecorderDetailService;
+import com.jiayue.pfr.util.SaResultRefit;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang.time.DateFormatUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 录波明细数据类
+ *
+ * @author jy
+ * @since 2023/11/10
+ */
+@RestController
+@RequestMapping("/faultRecorderDetailController")
+@Slf4j
+public class FaultRecorderDetailController {
+    @Autowired
+    FaultRecorderDetailService faultRecorderDetailService;
+
+    /**
+     *
+     * 获取录波明细数据
+     */
+    @GetMapping(value = "/getFdDetailList")
+    public SaResultRefit getFdDetailList(String eventId) throws CustomException {
+        try {
+            QueryWrapper<FaultRecorderDetail> wrapper = new QueryWrapper<>();
+            wrapper.eq("event_id",eventId);
+            List<FaultRecorderDetail> faultRecorderDataList = faultRecorderDetailService.list(wrapper);
+            for (FaultRecorderDetail faultRecorderDetail:faultRecorderDataList){
+                String time = DateFormatUtils.format(faultRecorderDetail.getDataTime(), "HH:mm:ss.SSS");
+                faultRecorderDetail.setFormatDataTime(time);
+            }
+            faultRecorderDataList.sort(Comparator.comparing(FaultRecorderDetail::getDataTime));
+            return SaResultRefit.data(faultRecorderDataList);
+        } catch (Exception e) {
+            throw new CustomException("获取录波明细异常", e);
+        }
+    }
+}

+ 4 - 0
backend/src/main/java/com/jiayue/pfr/entity/FaultRecorderDetail.java

@@ -1,6 +1,7 @@
 package com.jiayue.pfr.entity;
 
 import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
@@ -34,4 +35,7 @@ public class FaultRecorderDetail extends BaseEntity {
      * 有功
      */
     private BigDecimal activePower;
+    /** 时间格式化 */
+    @TableField(exist = false)
+    private String formatDataTime;
 }

BIN
ui/src/assets/images/line.png


+ 192 - 37
ui/src/views/largeScreen/index.vue

@@ -71,24 +71,38 @@
                 <td style="border:0px;">EMS通讯</td>
               </tr>
             </table>
-
-<!--            <table>-->
-<!--              <tr style="border:0px;">-->
-<!--                <td style="border:0px;"><div id="yctptr" class="breathe-yc"></div></td>-->
-<!--                <td style="border:0px;"><div id="agctx" class="breathe-yc"></div></td>-->
-<!--                <td style="border:0px;"><div id="ydtx" class="breathe-yc"></div></td>-->
-<!--                <td style="border:0px;"><div id="emstx" class="breathe-yc"></div></td>-->
-<!--              </tr>-->
-<!--              <tr style="border:0px;">-->
-<!--                <td style="border:0px;">一次调频投入</td>-->
-<!--                <td style="border:0px;">AGC通讯</td>-->
-<!--                <td style="border:0px;">远动通讯</td>-->
-<!--                <td style="border:0px;">能管通讯</td>-->
-<!--              </tr>-->
-<!--            </table>-->
+          </div>
+        </div>
+        <div class="box" style="top: 5%;width: 90%;left:5%;height: 200px">
+          <div class="tit">当日录波事件区</div>
+          <div class="boxnav" style="height: 100%">
+            <table class="table1" width="100%" border="0" cellspacing="0" cellpadding="0">
+              <tbody>
+              <tr>
+                <th>事件名称</th>
+                <th>频率异常时间点</th>
+                <th>频率恢复时间点</th>
+                <th>调频耗时(秒)</th>
+                <th>操作</th>
+              </tr>
+              <tr v-for="(item,index) in fdList" :key="index" >
+                <td>{{item.eventName}}</td>
+                <td>{{formatTime(item.exceptionStartTime)}}</td>
+                <td>{{formatTime(item.restoreTime)}}</td>
+                <td>{{Math.round((item.restoreTime-item.exceptionStartTime)/1000)}}</td>
+                <td><a href="javascript:void(0);"  @click="fdDetail(item.id,item.exceptionStartTime,item.restoreTime)">详细</a></td>
+              </tr>
+              </tbody>
+            </table>
           </div>
         </div>
 
+        <!-- 录波详细数据 -->
+        <el-dialog title="录波详细数据" :visible.sync="open" width="900px" @close='closeDetailDialog'>
+<!--          <div style="width: 100%;height: 100%;">-->
+            <div id="fdDetailCharts" style="height: 500px"></div>
+<!--          </div>-->
+        </el-dialog>
       </div>
   </div>
   </div>
@@ -96,19 +110,21 @@
 
 <script>
 import resize from '../../components/Charts/mixins/resize'
-
-
 export default {
   mixins: [resize],
   name: "index",
   data() {
     return {
+      open: false,
+      timer: "",
+      fdList:[],
       fmMinTime:new Date().toTimeString(),
       fmMaxTime:new Date().toTimeString(),
       fms:[],
       activePower:[],
       datas:[],
       chart: null,
+      detailChart:null,
       time: '',
       dialogShow: false,
       componentName: 'loadForecasting',
@@ -135,31 +151,23 @@ export default {
       capacity:0
     }
   },
-  // computed: {
-  //   fmOption(){
-  //     return {
-  //       color: ['#FF0000', '#00fe3b'],
-  //       tooltip: {
-  //         trigger: 'axis',
-  //         axisPointer: {
-  //           type: 'cross',
-  //           crossStyle: {
-  //             color: '#999'
-  //           }
-  //         }
-  //       }
-  //     }
-  //   }
-  // },
-
   created() {
     // 获取装机容量
     this.getCapacity()
     this.getDzForm()
+    this.getFdList()
   },
   mounted() {
     //页面刚进入时开启长连接
     window.addEventListener("resize", this.handleResize);
+
+    this.timer = setInterval(() => {
+      this.getFdList()
+    }, 5000);
+  },
+  beforeDestroy() {
+    //清除定时器
+    clearInterval(this.timer);
   },
   destroyed() {
     //页面销毁时关闭长连接
@@ -167,9 +175,153 @@ export default {
     console.log('数据大屏销毁websocket')
     // console.log('销毁页面')
     this.websocketclose();
+    this.chart.dispose()
     this.chart.clear()
   },
   methods: {
+    closeDetailDialog(){
+      this.detailChart.dispose()
+      this.detailChart.clear()
+      this.detailChart = null
+    },
+    renderFdDetailChart(fdDetailList,exceptionStartTime,restoreTime){
+      let fdfm = []
+      let fdap = []
+      let times = []
+
+      for (let t=0;t<fdDetailList.length;t++){
+        times.push(fdDetailList[t].formatDataTime)
+        fdfm.push(fdDetailList[t].fm)
+        fdap.push(fdDetailList[t].activePower)
+      }
+      exceptionStartTime = this.formatTimeHHMMSSsss(exceptionStartTime)
+      restoreTime = this.formatTimeHHMMSSsss(restoreTime)
+
+      this.detailChart = this.$echarts.init(document.getElementById('fdDetailCharts'))
+      var fmColors= ['#FF0000', '#00fe3b']
+      var fdoption= {
+        color: fmColors,
+        legend: {
+          icon:'roundRect',
+          data: ['功率', '频率'],
+          selectedMode:false,
+          padding: [0, 0, 0, 0]
+        },
+        tooltip: {
+          trigger: 'axis',
+          axisPointer: {
+            type: 'cross'
+          },
+          formatter: function(params) {
+            return '时间:'+params[0].name+"<br/>"+'功率:'+params[0].value+' MW'+"<br/>"+'频率:'+params[1].value+' Hz';
+          },
+        },
+
+        xAxis: {
+          type: 'category',
+          data: times,
+          min: times[0],
+          max: times[times.length-1],
+          // interval: 200,
+        },
+        yAxis: [
+          {
+            type: 'value',
+            position: 'left',
+            name: '功率',
+            min: 0,
+            max: this.capacity,
+            axisLabel: {
+              formatter: '{value} MW'
+            },
+          },
+          {
+            type: 'value',
+            splitLine: {show: false},
+            position: 'right',
+            name: '频率',
+            min: 49.8,
+            max: 50.2,
+            interval: 0.1,
+            axisLabel: {
+              formatter: '{value} Hz'
+            },
+          },
+
+        ],
+        series: [
+          {
+            name:'功率',
+            data: fdap,
+            type: 'line',
+            symbol: 'none',
+            markArea: {
+              itemStyle: {
+                color: 'rgba(255, 173, 177, 0.4)'
+              },
+              data: [
+                [
+                  {
+                    name: '频率异常区',
+                    xAxis: exceptionStartTime
+                  },
+                  {
+                    xAxis: restoreTime
+                  }
+                ]
+              ]
+            }
+          },
+          {
+            name:'频率',
+            yAxisIndex: 1,
+            data: fdfm,
+            type: 'line',
+            symbol: 'none',
+          },
+        ]
+      }
+      this.detailChart.setOption(fdoption,true)
+      window.onresize = this.detailChart.resize()
+    },
+    fdDetail(id,exceptionStartTime,restoreTime){
+      // 弹出详细页面
+      this.open = true;
+      var searchParams = {
+        eventId: id
+      }
+      // 获取后端明细数据
+      this.$axios.get('/faultRecorderDetailController/getFdDetailList',{params: searchParams}).then((res) => {
+        // 渲染明细图表
+        this.renderFdDetailChart(res.data,exceptionStartTime,restoreTime)
+      }).catch((error) => {
+      })
+    },
+    formatTimeHHMMSSsss(timestr){
+      const date = new Date(timestr) // 时间戳为10位需*1000,时间戳为13位的话不需乘1000
+      const H = (date.getHours() < 10 ? '0' + (date.getHours()) : date.getHours()) + ':'
+      const m = (date.getMinutes() < 10 ? '0' + (date.getMinutes()) : date.getMinutes()) + ':'
+      const s = (date.getSeconds() < 10 ? '0' + (date.getSeconds()) : date.getSeconds())+ '.'
+      const sss = date.getMilliseconds()
+      return H + m + s + sss
+    },
+    formatTime(timestr){
+      const date = new Date(timestr) // 时间戳为10位需*1000,时间戳为13位的话不需乘1000
+      const Y = date.getFullYear() + '-'
+      const M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-'
+      const D = (date.getDate() < 10 ? '0' + (date.getDate()) : date.getDate()) + ' '
+      const H = (date.getHours() < 10 ? '0' + (date.getHours()) : date.getHours()) + ':'
+      const m = (date.getMinutes() < 10 ? '0' + (date.getMinutes()) : date.getMinutes()) + ':'
+      const s = (date.getSeconds() < 10 ? '0' + (date.getSeconds()) : date.getSeconds())+ '.'
+      const sss = date.getMilliseconds()
+      return Y + M + D + H + m + s + sss
+    },
+    getFdList(){
+      this.$axios.get('/faultRecorderDataController/getFdList').then((res) => {
+        this.fdList = res.data
+      }).catch((error) => {
+      })
+    },
     fnW(str) {
       var num;
       str >= 10 ? num = str : num = "0" + str;
@@ -186,9 +338,7 @@ export default {
       if(date.getDay()==6) week="周六"
       return week;
     },
-
-
-//获取当前时间
+    //获取当前时间
     createDate(timeStr) {
         var date = new Date(timeStr);
         var year = date.getFullYear(); //当前年份
@@ -701,4 +851,9 @@ export default {
   line-height: 25px;
 }
 
+
+.table1 th{ border-bottom: 1px solid #407abd; font-size: 14px; text-align: center; padding: 6px 0; color: rgba(255,255,255,.8)}
+.table1 td{ border-bottom: 1px dotted#407abd;font-size: 12px; padding:6px 0;text-align: center; color: rgba(255,255,255,.6)}
+.table1 tr:last-child td{border: none;}
+
 </style>