Kaynağa Gözat

人工干预保存

xusl 10 ay önce
ebeveyn
işleme
808effd242

+ 3 - 1
ipp-ap/package.json

@@ -30,7 +30,9 @@
     "vue-router": "^3.1.3",
     "vuex": "^3.1.1",
     "vxe-table": "^2.9.18",
-    "xe-utils": "^2.7.5"
+    "xe-utils": "^2.7.5",
+    "moment": "^2.24.0",
+    "qs": "^6.11.2"
   },
   "devDependencies": {
     "@vue/cli-plugin-babel": "^3.12.0",

+ 5 - 0
ipp-ap/src/main.js

@@ -26,6 +26,11 @@ import * as echarts from 'echarts';
 import 'xe-utils'
 import VXETable from 'vxe-table'
 import 'vxe-table/lib/index.css'
+import moment from 'moment'
+import qs from  'qs'
+
+Vue.prototype.$qs = qs
+Vue.prototype.$moment = moment
 Vue.prototype.$echarts = echarts
 window.axios = axios
 Vue.use(VueAxios, axios)

+ 10 - 0
ipp-ap/src/router/page/index.js

@@ -146,6 +146,16 @@ export default [
     }],
   },
   {
+    path: '/idp/control/dqIntervene',
+    component: Layout,
+    children: [{
+      path: 'index',
+      name: '人工干预',
+      component: () =>
+        import ( /* webpackChunkName: "views" */ '@/views/idp/control/dqIntervene')
+    }],
+  },
+  {
     path: '/idp/system/sysparameter',
     component: Layout,
     children: [{

+ 15 - 0
ipp-ap/src/router/views/index.js

@@ -206,6 +206,21 @@ export default [
         sort: 1,
         spread: false
       },
+      {
+        children: [],
+        hasChildren: false,
+        icon: "icon-bangzhushouji",
+        id: "4173",
+        keepAlive: "0",
+        label: "人工干预",
+        menuType: "0",
+        name: "人工干预",
+        parentId: "4051",
+        path: "/idp/control/dqIntervene/index",
+        permission: "",
+        sort: 1,
+        spread: false
+      },
     ]
   },
   {

+ 221 - 0
ipp-ap/src/views/idp/control/dqIntervene/index.vue

@@ -0,0 +1,221 @@
+<template>
+  <div class="app-container">
+    <el-container>
+      <el-header style="padding: 0px;display:flex;justify-content:space-between;align-items: center">
+      <el-form ref="queryForm" size="small" :inline="true" label-width="100px">
+        <el-form-item label="场站名称" prop="stationCode">
+          <el-select style="width:250px" clearable v-model="stationCode" size="small">
+          <el-option
+            v-for="item in stationList"
+            :key="item.value"
+            :label="item.label"
+            :value="item.value">
+            <span style="float: left">{{ item.label }}</span>
+            <span style="float: right; color: #8492a6;font-size: 13px">{{ item.value }}</span>
+          </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="干预日期" prop="gyDate">
+          <el-date-picker
+            v-model="dateTime"
+            type="date"
+          />
+        </el-form-item>
+        <el-form-item>
+          <el-button size="small" :loading="loading" @click="getDqData">查询</el-button>
+          <el-button type="primary" size="small" style="margin-left: 5px" icon="el-icon-s-tools" @click="saveDqPresets">保存短期预设值</el-button>
+        </el-form-item>
+      </el-form>
+      </el-header>
+
+      <div style="width: 100%;height: 92%;position: absolute;top: 9%">
+        <div style="height: 100%;width: 30%;left: 0;top:0;display: inline-block">
+          <el-table
+            height="550px"
+            border
+            stripe
+            size="mini"
+            :data="tableData"
+            style="width: 90%">
+            <el-table-column
+              prop="forecastTime"
+              header-align="center"
+              align="center"
+              :formatter="dateFormat"
+              label="预测时间">
+            </el-table-column>
+            <el-table-column
+              prop="activePower"
+              header-align="center"
+              align="center"
+              label="预测值">
+            </el-table-column>
+            <el-table-column
+              prop="presetsPower"
+              :show-overflow-tooltip="true"
+              header-align="center"
+              align="center"
+              label="干预值">
+              <template slot-scope="scope">
+                <vxe-input type="number" v-model="scope.row.presetsPower" size="small" style="width:100%" min="0"
+                           :max="50" placeholder=""></vxe-input>
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+        <div style="height: 100%;width: 70%;left: 30%;top:0;display: inline-block;position: absolute">
+          <div id="gycharts" style="float:left;width: 95%;height: 550px"></div>
+        </div>
+      </div>
+    </el-container>
+  </div>
+</template>
+<script>
+
+import {getStation} from "@/api/inverterinfo";
+
+export default {
+  data() {
+    return {
+      gyDate:'',
+      stationCode: '',
+      stationList: [],
+      chart:null,
+      // 日期选择器
+      dateTime: '',
+      tableData:[],
+      tableLoading: false,
+      showTable:true,
+      loading:false,
+      capacity:'',
+    }
+  },
+  destroyed() {
+    this.chart.dispose()
+    this.chart.clear()
+  },
+  created: function() {
+  },
+  mounted() {
+    this.getStationCode()
+    // 获取装机容量
+    // this.$axios.get('/electricfield/getStationInfo').then((res) => {
+    //   this.capacity = res.data.capacity
+    // }).catch((error) => {
+    //   this.$message.error('查询装机容量出错' + error)
+    // })
+  },
+  methods: {
+    getStationCode() {
+      this.$axios.get('/electricfield/all').then((res) => {
+        this.stationList = res.data.data
+      })
+    },
+    //格式化表格时间
+    dateFormat(row,column){
+      let date = row[column.property]
+      return this.$moment(date).format('YYYY-MM-DD HH:mm:ss')
+    },
+    // 获取短期干预
+    getDqData() {
+      // 判断场站和干预日期是否选择
+      if(this.stationCode=='' || this.dateTime==''){
+        this.$message.warning('请选择场站及干预日期')
+        return
+      }
+
+      const startTime = Math.round(this.dateTime)
+      const endTime = Math.round(this.dateTime) + 60 * 60 * 24 * 1000 - 1
+      var queryParams = {
+        startTime: startTime,
+        endTime:endTime,
+        stationCode:this.stationCode
+      }
+      this.$axios.get('/dqInterveneController/getShort/',{params: queryParams}).then((res) => {
+        this.tableData = res.data.data
+        let activePower=[]
+        let presetsPower=[]
+        let time=[]
+        for (let i=0;i<this.tableData.length;i++) {
+          if (i==0){
+            this.capacity = this.tableData[i].capacity
+          }
+          activePower.push(this.tableData[i].activePower)
+          presetsPower.push(this.tableData[i].presetsPower)
+          time.push(this.$moment(this.tableData[i].forecastTime).format('YYYY-MM-DD HH:mm:ss'))
+        }
+        this.chart = this.$echarts.init(document.getElementById('gycharts'))
+        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'
+            },
+          },
+
+          xAxis: {
+            type: 'category',
+            data:time,
+          },
+          yAxis: [
+            {
+              type: 'value',
+              position: 'left',
+              name: '功率',
+              min: 0,
+              max: this.capacity,
+              axisLabel: {
+                formatter: '{value} MW'
+              },
+            }
+          ],
+          series: [
+            {
+              name:'预测值',
+              data: activePower,
+              type: 'line',
+              symbol: 'none'
+            },
+            {
+              name:'干预值',
+              data: presetsPower,
+              type: 'line',
+              symbol: 'none',
+            },
+          ]
+        }
+        this.chart.setOption(fdoption,true)
+        // window.onresize = this.chart.resize()
+      })
+    },
+    // 保存短期干预
+    saveDqPresets(){
+      var dqTempDto = {
+        list: this.tableData,
+        stationCode:this.stationCode
+      }
+      this.$axios.post('/dqInterveneController/saveIntervene',dqTempDto).then((res) => {
+        if (res==undefined){
+          this.$message.success('保存失败')
+        }
+        else{
+          this.$message.success('保存成功')
+          this.getDqData()
+        }
+      }).catch((error) => {
+      })
+    }
+  }
+}
+</script>
+<style>
+
+</style>

+ 50 - 0
ipp-common/ipp-common-data/src/main/java/com/jiayue/ipp/common/data/entity/DqIntervene.java

@@ -0,0 +1,50 @@
+package com.jiayue.ipp.common.data.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.jiayue.ipp.common.data.enums.EquipmentTypeEnum;
+import com.jiayue.ipp.common.mybatis.base.BaseDataEntity;
+import com.jiayue.ipp.common.mybatis.base.NotLogicBaseEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import javax.validation.constraints.Digits;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.util.Date;
+
+/**
+ * idp_dq_intervene
+ *
+ * @author whc
+ * @date 2022-03-18 15:49:11
+ */
+@Data
+@TableName("idp_dq_intervene")
+@EqualsAndHashCode(callSuper = true)
+@ApiModel(value = "idp_dq_intervene")
+public class DqIntervene extends NotLogicBaseEntity<DqIntervene> {
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 预测时间
+     */
+    private Date forecastTime;
+
+    /**
+     * 预测功率(MW)
+     */
+    @Digits(integer = 10, fraction = 2)
+    private BigDecimal activePower;
+
+    /**
+     * 场站编号
+     */
+    private String stationCode;
+}

+ 1 - 1
ipp-common/ipp-common-data/src/main/java/com/jiayue/ipp/common/data/entity/ForecastPowerShortTerm.java

@@ -48,7 +48,7 @@ public class ForecastPowerShortTerm extends NotLogicBaseEntity<ForecastPowerShor
      * 预测时间
      */
     @ApiModelProperty(value = "预测时间")
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+//    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Date forecastTime;
 
 

+ 64 - 0
ipp-idp/src/main/java/com/jiayue/ipp/idp/controller/DqInterveneController.java

@@ -0,0 +1,64 @@
+package com.jiayue.ipp.idp.controller;
+
+import com.jiayue.ipp.common.data.entity.DqIntervene;
+import com.jiayue.ipp.idp.dto.DqInterveneDto;
+import com.jiayue.ipp.idp.dto.DqTempDto;
+import com.jiayue.ipp.idp.service.DqInterveneService;
+import com.jiayue.ipp.idp.util.R;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+
+
+/**
+ * 短期干预
+ */
+@RestController
+@RequestMapping("/dqInterveneController")
+@Slf4j
+public class DqInterveneController {
+    @Autowired
+    DqInterveneService dqInterveneService;
+
+    /**
+     * 获取短期干预
+     */
+    @GetMapping(value = "/getShort")
+    public R getPresetsShort(Long startTime, Long endTime,String stationCode) {
+        List<DqInterveneDto> presetsShortDtoList = dqInterveneService.getShort(startTime, endTime,stationCode);
+        return R.ok(presetsShortDtoList);
+
+    }
+
+    /**
+     * 获取短期干预
+     */
+    @PostMapping(value = "/saveIntervene")
+    public R savePresets(@RequestBody DqTempDto dqTempDto) {
+        List<DqInterveneDto> list = dqTempDto.getList();
+        // 先删除干预表的数据记录
+        list.sort(Comparator.comparing(DqInterveneDto::getForecastTime));
+        Date startTime = list.get(0).getForecastTime();
+        Date endTime = list.get(list.size() - 1).getForecastTime();
+        dqInterveneService.deleteShort(startTime, endTime,dqTempDto.getStationCode());
+        // 封装干预实体,保存数据
+        List<DqIntervene> presetsShortList = new ArrayList<>();
+        for (DqInterveneDto dqInterveneDto : list) {
+            if (dqInterveneDto.getPresetsPower() != null) {
+                DqIntervene dqIntervene = new DqIntervene();
+                dqIntervene.setForecastTime(dqInterveneDto.getForecastTime());
+                dqIntervene.setActivePower(dqInterveneDto.getPresetsPower());
+                dqIntervene.setStationCode(dqTempDto.getStationCode());
+                presetsShortList.add(dqIntervene);
+            }
+        }
+        dqInterveneService.saveBatch(presetsShortList);
+        return R.ok();
+
+    }
+}

+ 35 - 0
ipp-idp/src/main/java/com/jiayue/ipp/idp/dto/DqInterveneDto.java

@@ -0,0 +1,35 @@
+package com.jiayue.ipp.idp.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.Digits;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 短期干预dto
+ */
+@Data
+public class DqInterveneDto {
+    /**
+     * 装机容量(MW)
+     */
+    @Digits(integer = 10, fraction = 2)
+    private BigDecimal capacity;
+
+    /**
+     * 预测时间
+     */
+    private Date forecastTime;
+
+    /**
+     * 预测功率(MW)
+     */
+    @Digits(integer = 10, fraction = 2)
+    private BigDecimal activePower;
+    /**
+     * 预测功率(MW)
+     */
+    @Digits(integer = 10, fraction = 2)
+    private BigDecimal presetsPower;
+}

+ 15 - 0
ipp-idp/src/main/java/com/jiayue/ipp/idp/dto/DqTempDto.java

@@ -0,0 +1,15 @@
+package com.jiayue.ipp.idp.dto;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author jy
+ * @since 2024/07/02
+ */
+@Data
+public class DqTempDto {
+    List<DqInterveneDto> list;
+    String stationCode;
+}

+ 21 - 0
ipp-idp/src/main/java/com/jiayue/ipp/idp/mapper/DqInterveneMapper.java

@@ -0,0 +1,21 @@
+package com.jiayue.ipp.idp.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.jiayue.ipp.common.data.entity.DqIntervene;
+import org.apache.ibatis.annotations.Delete;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.Date;
+
+/**
+ * idp_inverter_info
+ *
+ * @author whc
+ * @date 2022-03-18 15:49:11
+ */
+@Mapper
+public interface DqInterveneMapper extends BaseMapper<DqIntervene> {
+    @Delete("delete from idp_dq_intervene WHERE forecast_time>=#{startTime} and forecast_time<=#{endTime} and station_code=#{stationCode}")
+    void deleteShort(@Param("startTime") Date startTime, @Param("endTime") Date endTime, @Param("stationCode") String stationCode);
+}

+ 30 - 0
ipp-idp/src/main/java/com/jiayue/ipp/idp/service/DqInterveneService.java

@@ -0,0 +1,30 @@
+package com.jiayue.ipp.idp.service;
+
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.jiayue.ipp.common.data.entity.DqIntervene;
+import com.jiayue.ipp.idp.dto.DqInterveneDto;
+
+import java.util.Date;
+import java.util.List;
+
+
+/**
+ * idp_inverter_info
+ *
+ * @author whc
+ * @date 2022-03-18 15:49:11
+ */
+public interface DqInterveneService extends IService<DqIntervene> {
+    /**
+     * 获取短期干预
+     * @return
+     */
+    List<DqInterveneDto> getShort(Long startTime, Long endTime,String stationCode);
+    /**
+     * 时间段删除短期干预
+     * @param startTime
+     * @param endTime
+     */
+    void deleteShort(Date startTime, Date endTime,String stationCode);
+}

+ 93 - 0
ipp-idp/src/main/java/com/jiayue/ipp/idp/service/impl/DqInterveneServiceImpl.java

@@ -0,0 +1,93 @@
+package com.jiayue.ipp.idp.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.jiayue.ipp.common.data.entity.DqIntervene;
+import com.jiayue.ipp.common.data.entity.ElectricField;
+import com.jiayue.ipp.common.data.entity.ForecastPowerShortTerm;
+import com.jiayue.ipp.idp.dto.DqInterveneDto;
+import com.jiayue.ipp.idp.mapper.DqInterveneMapper;
+import com.jiayue.ipp.idp.service.DqInterveneService;
+import com.jiayue.ipp.idp.service.ElectricFieldService;
+import com.jiayue.ipp.idp.service.ForecastPowerShortTermService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * idp_inverter_info
+ *
+ * @author whc
+ * @date 2022-03-18 15:49:11
+ */
+@Service
+public class DqInterveneServiceImpl extends ServiceImpl<DqInterveneMapper, DqIntervene> implements DqInterveneService {
+    @Autowired
+    DqInterveneMapper dqInterveneMapper;
+    @Autowired
+    ForecastPowerShortTermService forecastPowerShortTermService;
+    @Autowired
+    ElectricFieldService electricFieldService;
+
+    public List<DqInterveneDto> getShort(Long startTime, Long endTime,String stationCode){
+        ElectricField electricField = electricFieldService.findByStationCode(stationCode);
+        // 先获取实时短期
+        QueryWrapper<ForecastPowerShortTerm> queryWrapper = new QueryWrapper<>();
+        queryWrapper.between("forecast_time", new Date(startTime), new Date(endTime));
+        queryWrapper.eq("station_code",stationCode);
+        queryWrapper.eq("forecast_manufactor","SYJY");
+        List<ForecastPowerShortTerm> ForecastPowerShortTermList = forecastPowerShortTermService.list(queryWrapper);
+        Map<Long, ForecastPowerShortTerm> ForecastPowerShortTermMap = ForecastPowerShortTermList.stream()
+                .collect(Collectors.toMap(
+                        myObject -> myObject.getForecastTime().getTime(), // keyMapper,将Date转换为long
+                        myObject -> myObject, // valueMapper,保持原对象
+                        (existing, replacement) -> existing // mergeFunction,处理重复key的情况,这里简单地保留现有的value
+                ));
+        // 再获取预设短期
+        QueryWrapper<DqIntervene> presetsWrapper = new QueryWrapper<>();
+        presetsWrapper.between("forecast_time", new Date(startTime), new Date(endTime));
+        List<DqIntervene> bizPresetsShortList = this.list(presetsWrapper);
+        Map<Long, DqIntervene> bizPresetsShortMap = bizPresetsShortList.stream()
+                .collect(Collectors.toMap(
+                        myObject -> myObject.getForecastTime().getTime(), // keyMapper,将Date转换为long
+                        myObject -> myObject, // valueMapper,保持原对象
+                        (existing, replacement) -> existing // mergeFunction,处理重复key的情况,这里简单地保留现有的value
+                ));
+        // 整合数据返给前端
+        List<DqInterveneDto> presetsShortDtoList = new ArrayList<>();
+        Long momentTime = 15 * 60 * 1000L;
+        for (Long tempTime = startTime; tempTime <= endTime; tempTime = tempTime + momentTime) {
+            DqInterveneDto dqInterveneDto = new DqInterveneDto();
+            dqInterveneDto.setForecastTime(new Date(tempTime));
+            dqInterveneDto.setCapacity(electricField.getCapacity());
+            if (ForecastPowerShortTermMap.get(tempTime)!=null){
+                // 实时值
+                dqInterveneDto.setActivePower(ForecastPowerShortTermMap.get(tempTime).getFpValue());
+            }
+            if (bizPresetsShortMap.get(tempTime)!=null){
+                // 干预值
+                dqInterveneDto.setPresetsPower(bizPresetsShortMap.get(tempTime).getActivePower());
+            }
+            else{
+                // 干预值
+                dqInterveneDto.setPresetsPower(ForecastPowerShortTermMap.get(tempTime).getFpValue());
+            }
+            presetsShortDtoList.add(dqInterveneDto);
+        }
+        return presetsShortDtoList;
+    }
+
+    /**
+     * 时间段删除短期干预
+     * @param startTime
+     * @param endTime
+     */
+    public void deleteShort(Date startTime, Date endTime,String stationCode){
+        dqInterveneMapper.deleteShort(startTime,endTime,stationCode);
+    }
+}