Ver código fonte

Merge remote-tracking branch 'origin/master'

tl 1 ano atrás
pai
commit
1e5705f0eb
25 arquivos alterados com 1721 adições e 8 exclusões
  1. 2 2
      in-client-qn-ui/src/config/setting.config.js
  2. 8 2
      in-client-qn/pom.xml
  3. 75 0
      in-client-qn/src/main/java/com/jiayue/insu/inclientqn/entity/BJZYYJYSDCorrfore.java
  4. 115 0
      in-client-qn/src/main/java/com/jiayue/insu/inclientqn/entity/ForecastData.java
  5. 86 0
      in-client-qn/src/main/java/com/jiayue/insu/inclientqn/inenum/BJZYYJYSDEnum.java
  6. 32 0
      in-client-qn/src/main/java/com/jiayue/insu/inclientqn/job/BJZYYJYSDComPermissonJob.java
  7. 65 0
      in-client-qn/src/main/java/com/jiayue/insu/inclientqn/job/BJZYYJYSDCorrforeDataJob.java
  8. 17 0
      in-client-qn/src/main/java/com/jiayue/insu/inclientqn/mapper/BJZYYJYSDCorrforeMapper.java
  9. 12 0
      in-client-qn/src/main/java/com/jiayue/insu/inclientqn/mapper/ForecastDataMapper.java
  10. 33 0
      in-client-qn/src/main/java/com/jiayue/insu/inclientqn/model/BJZYYJYSDResponseVo.java
  11. 44 0
      in-client-qn/src/main/java/com/jiayue/insu/inclientqn/model/BJZYYJYSDTokenVo.java
  12. 109 0
      in-client-qn/src/main/java/com/jiayue/insu/inclientqn/permisson/com/BJZYYJYSDComPermisson.java
  13. 21 0
      in-client-qn/src/main/java/com/jiayue/insu/inclientqn/pulldata/IPullInitForecastData.java
  14. 239 0
      in-client-qn/src/main/java/com/jiayue/insu/inclientqn/pulldata/PullInitData.java
  15. 23 0
      in-client-qn/src/main/java/com/jiayue/insu/inclientqn/service/ApiService.java
  16. 21 0
      in-client-qn/src/main/java/com/jiayue/insu/inclientqn/service/BJZYYJYSDCorrforeService.java
  17. 33 0
      in-client-qn/src/main/java/com/jiayue/insu/inclientqn/service/ForecastDataService.java
  18. 398 0
      in-client-qn/src/main/java/com/jiayue/insu/inclientqn/service/client/BJZYYJYCorrforeService.java
  19. 7 1
      in-client-qn/src/main/java/com/jiayue/insu/inclientqn/service/client/BackDataAnalysisService.java
  20. 5 3
      in-client-qn/src/main/java/com/jiayue/insu/inclientqn/service/client/InitRunner.java
  21. 60 0
      in-client-qn/src/main/java/com/jiayue/insu/inclientqn/service/impl/ApiServiceImpl.java
  22. 41 0
      in-client-qn/src/main/java/com/jiayue/insu/inclientqn/service/impl/BJZYYJYSDCorrforeServiceImpl.java
  23. 52 0
      in-client-qn/src/main/java/com/jiayue/insu/inclientqn/service/impl/ForecastDataServiceImpl.java
  24. 208 0
      in-client-qn/src/main/java/com/jiayue/insu/inclientqn/util/JsonResultUtil.java
  25. 15 0
      in-client-qn/src/main/java/com/jiayue/insu/inclientqn/util/SystermUtils.java

+ 2 - 2
in-client-qn-ui/src/config/setting.config.js

@@ -12,8 +12,8 @@ const setting = {
   lintOnSave: true,
   // 进行编译的依赖
   transpileDependencies: [],
-  //标题 (包括初次加载雪花屏的标题 页面的标题 浏览器的标题)
-  title: '清能客户端',
+  //标题 (包括初次加载雪花屏的标题 页面的标题 浏览器的标题)--- 因山东不属于清能,修改title为一体化客户端
+  title: '一体化客户端',
   //简写
   abbreviation: 'vab',
   //开发环境端口号

+ 8 - 2
in-client-qn/pom.xml

@@ -85,7 +85,13 @@
         <dependency>
             <groupId>cn.hutool</groupId>
             <artifactId>hutool-all</artifactId>
-            <version>5.7.15</version>
+            <version>5.8.1</version>
+        </dependency>
+        <!--添加jackson依赖-->
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+            <version>2.13.3</version> <!-- 使用当前最新版本 -->
         </dependency>
         <dependency>
             <groupId>org.apache.commons</groupId>
@@ -138,7 +144,7 @@
             <groupId>io.jsonwebtoken</groupId>
             <artifactId>jjwt</artifactId>
             <version>0.9.0</version>
-            <scope>test</scope>
+            <scope>compile</scope>
         </dependency>
 
 

+ 75 - 0
in-client-qn/src/main/java/com/jiayue/insu/inclientqn/entity/BJZYYJYSDCorrfore.java

@@ -0,0 +1,75 @@
+package com.jiayue.insu.inclientqn.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import lombok.Getter;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * 修正数据(山东国家研究院)
+ *
+ * @author fxy
+ * @date 2023-12-15 19:33:02
+ */
+@Data
+@TableName("bjzyyjysd_corrfore")
+public class BJZYYJYSDCorrfore implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID
+     */
+    @TableId(type = IdType.AUTO)
+    private String id;
+
+    /**
+     * 预测时间
+     */
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime timeFormat;
+
+    /**
+     * 预测时间
+     */
+    private Long forecastTime;
+    /**
+     * 预测值
+     */
+    private BigDecimal fpValue;
+
+    /**
+     *  数据最后一次修改时间
+     */
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime updateTime;
+
+    /**
+     * 创建时间
+     */
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime correctTime;
+
+    @TableField( exist = false)
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Long startTime;
+
+    @TableField( exist = false)
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Long endTime;
+
+    /**
+     * 场站编码
+     */
+    String stationCode;
+}

+ 115 - 0
in-client-qn/src/main/java/com/jiayue/insu/inclientqn/entity/ForecastData.java

@@ -0,0 +1,115 @@
+package com.jiayue.insu.inclientqn.entity;
+
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+
+/**
+ * 预测数据实体
+ *
+ * @author yh
+ * @version 1.0
+ * @since 2020/7/8 10:56
+ */
+
+@TableName(value = "in_forecast_data")
+@Data
+public class ForecastData {
+    /**
+     * Id
+     */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+
+    private String stationCode;
+
+
+    private String inCode;
+
+    //下载时间
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime initTime;
+
+    //上送时间
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime uploadTime;
+
+    //修正时间
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime correctTime;
+
+    //预测时间
+    private Long forecastTime;
+    /**
+     * 预测功率(MW)
+     */
+    private BigDecimal fpValue;
+    private BigDecimal fpValueCorrect;
+
+
+    /**
+     * 总辐射
+     */
+    private BigDecimal swr;
+    private BigDecimal swrCorrect;
+
+
+    /**
+     * 直辐射
+     */
+    private BigDecimal directRadiation;
+    private BigDecimal directRadiationCorrect;
+
+    /**
+     * 散辐射
+     */
+    private BigDecimal diffuseRadiation;
+    private BigDecimal diffuseRadiationCorrect;
+
+
+    //风速
+    private BigDecimal windSpeed;
+    private BigDecimal windSpeedCorrect;
+
+
+    //风向
+    private BigDecimal windDir;
+    private BigDecimal windDirCorrect;
+
+
+    //气温
+    private BigDecimal temperature;
+    private BigDecimal temperatureCorrect;
+
+
+    //相对湿度
+    private BigDecimal humidity;
+    private BigDecimal humidityCorrect;
+
+
+    //压力
+    private BigDecimal pressure;
+    private BigDecimal pressureCorrect;
+
+
+    @TableField( exist = false)
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Long startTime;
+
+    @TableField( exist = false)
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Long endTime;
+}

+ 86 - 0
in-client-qn/src/main/java/com/jiayue/insu/inclientqn/inenum/BJZYYJYSDEnum.java

@@ -0,0 +1,86 @@
+package com.jiayue.insu.inclientqn.inenum;
+/**
+ * 山东国家研究院 ENUM
+ *
+ * @author fxy
+ * @version 1.0
+ * @since 2023/12/15 11:29
+ */
+public enum BJZYYJYSDEnum {
+
+    REQUEST_SUCCESS("0","success","请求成功"),
+    REQUEST_FAIL("T000","fail","请求失败"),
+
+    PERMISSON_TOKEN_EXPIRE("I101","TOKEN_EXPIRE","token已过期"),
+    PERMISSON_TOKEN_INVALID("I102","TOKEN_INVALID","无效token"),
+    PERMISSON_AUTOGRAPH_FAIL("I103","AUTOGRAPH_FAIL","签名失败"),
+    PERMISSON_LOGIN_NOT("I104","LOGIN_NOT","用户未登录"),
+
+    /**
+     * 传输类型
+     */
+    TRANSFER_TYPE_DOWNLOAD("download","download","数据传输类型:功率预测主站下发"),
+    TRANSFER_TYPE_UPLOAD("upload","upload","数据传输类型:功率预测子站回传"),
+    TRANSFER_TYPE_CORRECT("correct","correct","数据传输类型:一体化平台修正下发"),
+
+    /**
+     * 数据类型
+     */
+    DATA_FORE_TYPE("FORE","FORE","预测"),
+    DATA_PROBDIST_TYPE("PROBDIST","PROBDIST","概率分布"),
+    DATA_STAT_TYPE("STAT","STAT","统计"),
+    DATA_CORRFORE_TYPE("CORRFORE","CORRFORE","优化后预测"),
+    DATA_TODAYFORE_TYPE("TODAYFORE","TODAYFORE","优化后当日预测"),
+    DATA_CORRULTRSHOR_TYPE("CORRULTRSHOR","CORRULTRSHOR","超短期修正"),
+    DATA_REPAPLAN_TYPE("REPAPLAN","REPAPLAN","检修计划"),
+    /**
+     * 回传数据类型划分
+     */
+    DATA_FORE_TYPE_UltraShortTermForecast("UltraShortTermForecast","UltraShortTermForecast","超短期功率预测上报回传"),
+    DATA_FORE_TYPE_ForecastPower("ForecastPower","ForecastPower","短期功率预测上报回传"),
+    DATA_STAT_TYPE_RealPower("RealPower","RealPower","实发功率回传"),
+    DATA_STAT_TYPE_RealWeather("RealWeather","RealWeather","实际气象回传"),
+    DATA_STAT_TYPE_ForecastPowerReport("ForecastPowerReport","ForecastPowerReport","短期上报状态回传"),
+    DATA_STAT_TYPE_UltraShortTermForecastReport("UltraShortTermForecastReport","UltraShortTermForecastReport","超短期上报状态回传"),
+
+    DATA_STAT_ALL("BACK_STAT_ALL","BACK_STAT_ALL","统计数据回传"),
+
+    DATA_FORE_ALL("BACK_FORE_ALL","BACK_FORE_ALL","预测数据回传")
+            ;
+
+    private String code;
+    private String sign;
+    private String msg;
+
+    BJZYYJYSDEnum(String code, String sign, String msg) {
+        this.code = code;
+        this.sign = sign;
+        this.msg  =msg;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+
+    public String getSign() {
+        return sign;
+    }
+
+    public void setSign(String sign) {
+        this.sign = sign;
+    }
+
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public void setMsg(String msg) {
+        this.msg = msg;
+    }
+}

+ 32 - 0
in-client-qn/src/main/java/com/jiayue/insu/inclientqn/job/BJZYYJYSDComPermissonJob.java

@@ -0,0 +1,32 @@
+package com.jiayue.insu.inclientqn.job;
+
+import com.jiayue.insu.inclientqn.entity.Station;
+import com.jiayue.insu.inclientqn.permisson.com.BJZYYJYSDComPermisson;
+import com.jiayue.insu.inclientqn.service.StationService;
+import org.quartz.Job;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.util.List;
+
+/**
+ * @description:  请求一体化 交互权限(山东国家研究院)
+ * @author: yuanhao
+ * @createDate: 2023/12/15
+ * @version: 1.0
+ */
+public class BJZYYJYSDComPermissonJob implements Job {
+
+    @Autowired
+    private BJZYYJYSDComPermisson bjzyyjysdComPermisson;
+    @Autowired
+    private StationService stationService;
+    @Override
+    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
+        List<Station> stationList = stationService.findAll();
+        for(Station station : stationList){
+            bjzyyjysdComPermisson.generateKey(station);
+        }
+    }
+}

+ 65 - 0
in-client-qn/src/main/java/com/jiayue/insu/inclientqn/job/BJZYYJYSDCorrforeDataJob.java

@@ -0,0 +1,65 @@
+package com.jiayue.insu.inclientqn.job;
+
+import cn.hutool.core.date.LocalDateTimeUtil;
+import com.jiayue.insu.inclientqn.constant.CommonStant;
+import com.jiayue.insu.inclientqn.entity.Record;
+import com.jiayue.insu.inclientqn.entity.Station;
+import com.jiayue.insu.inclientqn.inenum.StatusEnum;
+import com.jiayue.insu.inclientqn.service.RecordService;
+import com.jiayue.insu.inclientqn.service.StationService;
+import com.jiayue.insu.inclientqn.service.client.BJZYYJYCorrforeService;
+import com.jiayue.insu.inclientqn.service.client.CorrforeService;
+import org.quartz.Job;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * @description: 请求一体化 修正数据
+ * @author: yuanhao
+ * @createDate: 2022/6/17
+ * @version: 1.0
+ */
+public class BJZYYJYSDCorrforeDataJob implements Job {
+
+    @Autowired
+    private BJZYYJYCorrforeService bjzyyjysdCorrforeService;
+    @Autowired
+    private StationService stationService;
+    @Autowired
+    private RecordService recordService;
+
+    @Override
+    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
+        //查询是否有今天成功记录 (为提高稳定性,该定时任务采取在规定时间段内 重复循环执行的定时策略,故:需要查询是否存在成功记录)
+        Record successRecord;
+        LocalDateTime localDateTime = LocalDateTimeUtil.beginOfDay(LocalDateTime.now());
+        // 查询全部场站信息
+        List<Station> stationList = stationService.findAll();
+        // 如果场站大于1个,则循环请求一体化修正数据
+        if (stationList != null && stationList.size() > 1) {
+            for (Station station : stationList) {
+                // 如果有执行记录,则不再执行
+                successRecord = recordService.findTimeAndTypeAndStateAndStationCode(localDateTime, CommonStant.RECORD_TYPE_PULL_CORRECT, StatusEnum.SUCCESS.getCode(), station.getStationCode());
+                if (successRecord != null) {
+                    return;
+                }
+                // 山东国家研究院 下载并生成修正后短期数据
+                bjzyyjysdCorrforeService.downLoadCorrforeData(station);
+            }
+            // 如果场站大于1个,则直接请求一体化修正数据
+        } else if (stationList != null && stationList.size() == 1) {
+            successRecord = recordService.findTimeAndTypeAndState(localDateTime, CommonStant.RECORD_TYPE_PULL_CORRECT, StatusEnum.SUCCESS.getCode());
+            // 如果有执行记录,则不再执行
+            if (successRecord != null) {
+                return;
+            }
+            // 山东国家研究院 下载并生成修正后短期数据
+            bjzyyjysdCorrforeService.downLoadCorrforeData(stationList.get(0));
+        }
+
+    }
+}

+ 17 - 0
in-client-qn/src/main/java/com/jiayue/insu/inclientqn/mapper/BJZYYJYSDCorrforeMapper.java

@@ -0,0 +1,17 @@
+package com.jiayue.insu.inclientqn.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.jiayue.insu.inclientqn.entity.BJZYYJYSDCorrfore;
+import com.jiayue.insu.inclientqn.entity.CorrforeSt;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 修正数据mapper
+ *
+ * @author xsl
+ * @date 2022-04-12 19:33:02
+ */
+@Mapper
+public interface BJZYYJYSDCorrforeMapper extends BaseMapper<BJZYYJYSDCorrfore> {
+
+}

+ 12 - 0
in-client-qn/src/main/java/com/jiayue/insu/inclientqn/mapper/ForecastDataMapper.java

@@ -0,0 +1,12 @@
+package com.jiayue.insu.inclientqn.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+import com.jiayue.insu.inclientqn.entity.ForecastData;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface ForecastDataMapper extends BaseMapper<ForecastData> {
+
+
+}

+ 33 - 0
in-client-qn/src/main/java/com/jiayue/insu/inclientqn/model/BJZYYJYSDResponseVo.java

@@ -0,0 +1,33 @@
+package com.jiayue.insu.inclientqn.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.SuperBuilder;
+
+/**
+ * @description: 山东国家研究院一体化响应VO
+ * @author: fxy
+ * @createDate: 2023/12/15
+ * @version: 1.0
+ */
+@Data
+@SuperBuilder
+@NoArgsConstructor
+@AllArgsConstructor
+public class BJZYYJYSDResponseVo {
+
+    /**
+     * 响应码
+     */
+    private String code;
+    /**
+     * 响应信息
+     */
+    private String msg;
+
+    /**
+     * 响应数据
+     */
+    private String data;
+}

+ 44 - 0
in-client-qn/src/main/java/com/jiayue/insu/inclientqn/model/BJZYYJYSDTokenVo.java

@@ -0,0 +1,44 @@
+package com.jiayue.insu.inclientqn.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.SuperBuilder;
+
+import java.io.Serializable;
+
+/**
+ * @description:
+ * @author: yuanhao
+ * @createDate: 2021/8/23
+ * @version: 1.0
+ */
+@Data
+@SuperBuilder
+@NoArgsConstructor
+@AllArgsConstructor
+public class BJZYYJYSDTokenVo implements Serializable {
+
+    /**
+     * 访问令牌
+     */
+    private String access_token;
+
+    /**
+     * 刷新 token
+     */
+    private String refresh_token;
+
+    /**
+     * 过期时间,12 小时
+     */
+    private Long expires_in;
+    /**
+     * 授权范围
+     */
+    private String scope;
+    /**
+     * 用户详细信息
+     */
+    private String user_info;;
+}

+ 109 - 0
in-client-qn/src/main/java/com/jiayue/insu/inclientqn/permisson/com/BJZYYJYSDComPermisson.java

@@ -0,0 +1,109 @@
+package com.jiayue.insu.inclientqn.permisson.com;
+
+import cn.hutool.core.date.LocalDateTimeUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.HttpRequest;
+import cn.hutool.json.JSONUtil;
+import com.jiayue.insu.inclientqn.constant.CommonStant;
+import com.jiayue.insu.inclientqn.entity.Record;
+import com.jiayue.insu.inclientqn.entity.Station;
+import com.jiayue.insu.inclientqn.inenum.BJZYYJYSDEnum;
+import com.jiayue.insu.inclientqn.model.BJZYYJYSDTokenVo;
+import com.jiayue.insu.inclientqn.service.RecordService;
+import com.jiayue.insu.inclientqn.service.StationService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+
+/**
+ * 山东国家研究院生成通讯token
+ *
+ * @author fxy
+ * @version 1.0
+ * @since 2023/12/14 11:29
+ */
+@Component
+@Slf4j
+public class BJZYYJYSDComPermisson {
+
+    @Autowired
+    private StationService stationService;
+    @Autowired
+    private RecordService recordService;
+
+    /**
+     * 生成山东国家研究院token
+     *
+     * @param station
+     * @return
+     */
+    public Boolean generateKey(Station station) {
+        // 记录
+        Record record = new Record();
+        record.setType(CommonStant.RECORD_TYPE_COM_PERMISSON);
+        LocalDateTime localDateTime = LocalDateTimeUtil.beginOfDay(LocalDateTime.now());
+        record.setTime(localDateTime);
+        record.setCreateTime(LocalDateTime.now());
+        record.setState(BJZYYJYSDEnum.REQUEST_FAIL.getSign());
+        record.setStationCode(station.getStationCode());
+
+        boolean result = false;
+        // 用户名
+        String username = station.getUsername();
+        // 密码
+        String password = station.getPassword();
+        // 身份验证
+        String auth = "Basic dGVzdDp0ZXN0";
+        // token地址
+        String tokenUrl = station.getComurl();
+        String response;
+        String token;
+        // 请求token
+        try {
+            HttpRequest httpRequest = HttpRequest.post(tokenUrl)
+                    .header("Content-Type", "application/x-www-form-urlencoded")
+                    .header("Authorization", auth)
+                    .header("TENANT-ID", "4").
+                            form("username",username).
+                            form("password",password).
+                            form("scope","server");
+            httpRequest.setGlobalTimeout(20000);
+            response = httpRequest.execute().body();
+            // 判断响应内容
+            if (StrUtil.isNotEmpty(response)) {
+                boolean isJson = JSONUtil.isJsonObj(response);
+                if (isJson) {
+                    BJZYYJYSDTokenVo sdTokenVo = JSONUtil.toBean(response, BJZYYJYSDTokenVo.class);
+                    if (sdTokenVo.getAccess_token() != null) {
+                        token = sdTokenVo.getAccess_token();
+                        log.info("========== 山东国家研究院一体化token请求成功: {} token=" + token + "  ==========", station.getStationCode());
+                        station.setComKey(token);
+                        station.setKeyTime(Instant.ofEpochMilli(System.currentTimeMillis() + sdTokenVo.getExpires_in() * 1000).atZone(ZoneId.systemDefault()).toLocalDateTime());
+                        stationService.updateById(station);
+                        record.setState(BJZYYJYSDEnum.REQUEST_SUCCESS.getSign());
+                        result = true;
+                    } else {
+                        log.error("========== 未成功获取到鉴权令牌 ========== ");
+                        log.info("========== 请求参数 账号密码:" + username + ":" + password + " MD5加密:" + auth + " ==========");
+                    }
+                } else {
+                    log.error("========== 山东国家研究院一体化token请求异常: {} 接收响应字符串非json格式 ==========", station.getStationCode());
+                }
+            } else {
+                log.error("========== 山东国家研究院一体化token请求异常: {} 接收响应字符串为空 ==========", station.getStationCode());
+            }
+
+        } catch (Exception e) {
+            log.error("========== 山东国家研究院一体化token请求异常: {} 连接断开或请求超时 ==========", station.getStationCode());
+            e.printStackTrace();
+
+        }
+        // 保存记录
+        recordService.save(record);
+        return result;
+    }
+}

+ 21 - 0
in-client-qn/src/main/java/com/jiayue/insu/inclientqn/pulldata/IPullInitForecastData.java

@@ -0,0 +1,21 @@
+package com.jiayue.insu.inclientqn.pulldata;
+
+import com.jiayue.insu.inclientqn.entity.BJZYYJYSDCorrfore;
+import com.jiayue.insu.inclientqn.entity.Station;
+import java.util.List;
+
+/**
+ * 拉取预测原始数据接口
+ *
+ * @author yh
+ * @version 1.0
+ * @since 2022/5/22 11:29
+ */
+public interface IPullInitForecastData {
+
+    /**
+     * 拉取短期预测原始数据
+     */
+    List<BJZYYJYSDCorrfore> pullDQData(Station station);
+
+}

+ 239 - 0
in-client-qn/src/main/java/com/jiayue/insu/inclientqn/pulldata/PullInitData.java

@@ -0,0 +1,239 @@
+package com.jiayue.insu.inclientqn.pulldata;
+
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.date.LocalDateTimeUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.HttpRequest;
+import cn.hutool.http.HttpUtil;
+import cn.hutool.json.JSONArray;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import com.jiayue.insu.inclientqn.constant.CommonStant;
+import com.jiayue.insu.inclientqn.entity.BJZYYJYSDCorrfore;
+import com.jiayue.insu.inclientqn.entity.Record;
+import com.jiayue.insu.inclientqn.entity.Station;
+import com.jiayue.insu.inclientqn.inenum.StatusEnum;
+import com.jiayue.insu.inclientqn.model.FileCreateLog;
+import com.jiayue.insu.inclientqn.service.ApiService;
+import com.jiayue.insu.inclientqn.service.ForecastDataService;
+import com.jiayue.insu.inclientqn.service.RecordService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.cloud.context.config.annotation.RefreshScope;
+import org.springframework.stereotype.Component;
+
+import java.io.*;
+import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 拉取原始预测数据业务
+ *
+ * @author yh
+ * @version 1.0
+ * @since 2022/5/22 11:29
+ */
+@Component
+@Slf4j
+@RefreshScope
+public class PullInitData implements IPullInitForecastData {
+
+    @Autowired
+    private RecordService recordService;
+    @Autowired
+    private ForecastDataService forecastDataService;
+    @Autowired
+    private ApiService apiService;
+    @Value("${minio.pull.url}")
+    String url;
+    @Value("${minio.pull.fileurl}")
+    String fileurl;
+    @Value("${minio.fileurl}")
+    String fileDir;
+
+    /**
+     * 拉取短期原始预测数据
+     * @param station 场站信息
+     */
+    @Override
+    public List<BJZYYJYSDCorrfore> pullDQData(Station station) {
+
+        Record record = new Record();
+        LocalDateTime localDateTime = LocalDateTimeUtil.beginOfDay(LocalDateTime.now());
+        record.setStationCode(station.getStationCode());
+        record.setTime(localDateTime);
+        record.setCreateTime(LocalDateTime.now());
+        record.setType(CommonStant.RECORD_TYPE_PULL_INIT);
+        log.info("下载minio原始RB文件 --> {}" + station.getStationCode());
+        List<BJZYYJYSDCorrfore> listNow = new ArrayList<>();
+        try {
+            HttpRequest httpRequest = HttpRequest.get(url + station.getStationCode());
+            httpRequest.setGlobalTimeout(20000);
+            String body = httpRequest.execute().body();
+            JSONObject json = JSONUtil.parseObj(body);
+            String code = json.get("code").toString();
+            String data = json.get("data").toString();
+            if (code.equals("0") && data.length() > 0) {
+                JSONArray array = JSONUtil.parseArray(data);
+                List<FileCreateLog> list = array.toList(FileCreateLog.class);
+                List<FileCreateLog> dqListNow = new ArrayList<>();
+                String dateNow = DateUtil.format(new Date(), "yyyyMMdd");
+                if (CollectionUtil.isNotEmpty(list)) {
+                    dqListNow = list.stream().filter(f -> f.getFileName().contains("DQ_" + dateNow)).collect(Collectors.toList());
+                    if (CollectionUtil.isNotEmpty(dqListNow)) {
+                        // 降序
+                        dqListNow.sort(Comparator.comparing(FileCreateLog::getFileName).reversed());
+                        File dqNowFile = null;
+                        String fileSaveUrl = fileDir + File.separatorChar + "init" + File.separatorChar + station.getStationCode();
+                        log.info(fileSaveUrl);
+                        File dir = new File(fileSaveUrl);
+                        // 判断目录是否存在
+                        if (!dir.exists()) {
+                            dir.mkdirs();
+                            log.info("创建目录:" + fileSaveUrl);
+                        }
+
+                        try {
+                            String dqNowUrl = fileurl + dqListNow.get(0).getId();
+                            dqNowFile = HttpUtil.downloadFileFromUrl(dqNowUrl, fileSaveUrl + File.separatorChar + dqListNow.get(0).getFileName());
+
+                            if (dqNowFile != null) {
+                                // 回传dq文件状态
+                                apiService.postBackMinIoState(station.getStationCode(), dqNowFile.getName(), "down", "是");
+                                //解析
+                                listNow = fileAnalysis(dqNowFile, station, localDateTime);
+
+                                if (CollectionUtil.isNotEmpty(listNow)) {
+//                                    //删除该时间段内数据
+//                                    forecastDataService.removeBetweenTimeByStation(station.getStationCode(),listNow.get(0).getForecastTime(),listNow.get(listNow.size() - 1).getForecastTime());
+//                                    forecastDataService.saveBatch(listNow);
+                                    String fileName = dqNowFile.getName();
+                                    record.setContent(fileName);
+                                    record.setState(StatusEnum.SUCCESS.getCode());
+                                    record.setStateContent(String.valueOf(listNow.size()));
+                                    log.info(station.getStationCode() + " 存入初始化数据:" + listNow.size() + "条");
+                                } else {
+                                    record.setState(StatusEnum.DOWNLOAD_FILE_ERROR.getCode());
+                                    log.error("下载minio原始RB文件 --> {} 失败,失败原因:{}", station.getStationCode(), StatusEnum.DOWNLOAD_FILE_ERROR.getMsg());
+                                }
+
+                            } else {
+                                record.setState(StatusEnum.DOWNLOAD_FILE_ERROR.getCode());
+                                log.error("下载minio原始RB文件 --> {} 失败,失败原因:{}", station.getStationCode(), StatusEnum.DOWNLOAD_FILE_ERROR.getMsg());
+                            }
+
+
+                        } catch (Exception e) {
+                            record.setState(StatusEnum.DOWNLOAD_FILE_FAIL.getCode());
+                            log.error("下载minio原始RB文件 --> {} 失败,失败原因:{}", station.getStationCode(), StatusEnum.DOWNLOAD_FILE_FAIL.getMsg());
+                            e.printStackTrace();
+                        }
+
+                    } else {
+
+                        record.setState(StatusEnum.FILE_NULL.getCode());
+                        log.error("下载minio原始RB文件 --> {} 失败,失败原因:{}", station.getStationCode(), StatusEnum.FILE_NULL.getMsg());
+
+                    }
+                } else {
+                    record.setState(StatusEnum.FILE_NULL.getCode());
+                    log.error("下载minio原始RB文件 --> {} 失败,失败原因:{}", station.getStationCode(), StatusEnum.FILE_NULL.getMsg());
+                }
+
+
+            } else {
+                record.setState(StatusEnum.RESPONSE_FAIL.getCode());
+                log.error("下载minio原始RB文件 --> {} 失败,失败原因:{}", station.getStationCode(), StatusEnum.RESPONSE_FAIL.getMsg());
+            }
+        } catch (Exception e) {
+            record.setState(StatusEnum.RESPONSE_FAIL.getCode());
+            log.error("下载minio原始RB文件 --> {} 失败,失败原因:{}", station.getStationCode(), StatusEnum.RESPONSE_FAIL.getMsg());
+            e.printStackTrace();
+
+        }
+
+        recordService.save(record);
+        return listNow;
+    }
+
+
+    /**
+     * 解析原始dq文件并返回ForecastDataList
+     *
+     * @param dqFile
+     * @param station
+     * @param localDateTime
+     * @return
+     */
+    public List<BJZYYJYSDCorrfore> fileAnalysis(File dqFile, Station station, LocalDateTime localDateTime) {
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        List<BJZYYJYSDCorrfore> aioList = new ArrayList<>();
+        boolean jx = true;
+        if (dqFile.renameTo(dqFile)) {
+            InputStreamReader dqRead = null;
+            BufferedReader dqBufferedReader = null;
+            String stringLine;
+            BJZYYJYSDCorrfore stf;
+            try {
+                dqRead = new InputStreamReader(new FileInputStream(dqFile), "utf-8");
+                dqBufferedReader = new BufferedReader(dqRead);
+                // 循环解析dq文件并放入aioList
+                while ((stringLine = dqBufferedReader.readLine()) != null) {
+                    String[] string_arr = stringLine.split("\t");
+                    if (string_arr.length == 4 && string_arr[0].startsWith("#")) {
+                        if (StrUtil.isNotEmpty(string_arr[2])) {
+                            stf = new BJZYYJYSDCorrfore();
+                            stf.setFpValue(new BigDecimal(string_arr[3] + ""));
+                            stf.setForecastTime(sdf.parse(string_arr[2]).getTime());
+                            stf.setStationCode(station.getStationCode());
+                            aioList.add(stf);
+                        }
+                    }
+                }
+            } catch (Exception e) {
+                jx = false;
+                log.error(station.getStationCode() + " 解析当天DQ文件错误:", e);
+            } finally {
+                close(dqBufferedReader, dqRead);
+            }
+        }
+
+        if (jx) {
+            aioList.sort(Comparator.comparing(BJZYYJYSDCorrfore::getForecastTime));
+            return aioList;
+        } else {
+            return null;
+        }
+
+    }
+
+
+    /**
+     * 关闭文件流
+     *
+     * @param bufferedReader 字符数据
+     * @param read           字节流
+     */
+    private void close(BufferedReader bufferedReader, InputStreamReader read) {
+        try {
+            if (bufferedReader != null) {
+                bufferedReader.close();
+            }
+            if (read != null) {
+                read.close();
+            }
+        } catch (IOException e) {
+            log.error("关闭文件流失败:", e);
+        }
+    }
+
+
+}

+ 23 - 0
in-client-qn/src/main/java/com/jiayue/insu/inclientqn/service/ApiService.java

@@ -0,0 +1,23 @@
+package com.jiayue.insu.inclientqn.service;
+
+
+/**
+ * 预测数据业务接口
+ *
+ * @author yh
+ * @version 1.0
+ * @since 2022/5/22 11:29
+ */
+public interface ApiService  {
+
+    /**
+     * 从minIo下载文件后,回传状态
+     * @param stationCode
+     * @param fileName
+     * @param type
+     * @param status
+     */
+    void postBackMinIoState(String stationCode ,String fileName,String type,String status);
+
+
+}

+ 21 - 0
in-client-qn/src/main/java/com/jiayue/insu/inclientqn/service/BJZYYJYSDCorrforeService.java

@@ -0,0 +1,21 @@
+package com.jiayue.insu.inclientqn.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.jiayue.insu.inclientqn.entity.BJZYYJYSDCorrfore;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * 定时任务初始业务接口
+ *
+ * @author yh
+ * @version 1.0
+ * @since 2022/5/22 11:29
+ */
+public interface BJZYYJYSDCorrforeService extends IService<BJZYYJYSDCorrfore> {
+
+    boolean updateBetweenForecastTime(LocalDateTime statTime, LocalDateTime endTime, List<BJZYYJYSDCorrfore> list);
+
+
+}

+ 33 - 0
in-client-qn/src/main/java/com/jiayue/insu/inclientqn/service/ForecastDataService.java

@@ -0,0 +1,33 @@
+package com.jiayue.insu.inclientqn.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.jiayue.insu.inclientqn.entity.ForecastData;
+
+
+import java.util.List;
+
+/**
+ * 预测数据业务接口
+ *
+ * @author yh
+ * @version 1.0
+ * @since 2022/5/22 11:29
+ */
+public interface ForecastDataService extends IService<ForecastData> {
+    /**
+     * 删除数据 通过场站编码和时间
+     * @param station 场站编码
+     * @param startTime 开始时间
+     * @param endTime 结束时间
+     * @return 结果
+     */
+    boolean removeBetweenTimeByStation(String station,Long startTime,Long endTime);
+    /**
+     * 查询数据 通过场站编码和时间
+     * @param station 场站编码
+     * @param startTime 开始时间
+     * @param endTime 结束时间
+     * @return 结果
+     */
+    List<ForecastData>  findTimeByStation(String station,Long startTime,Long endTime);
+}

+ 398 - 0
in-client-qn/src/main/java/com/jiayue/insu/inclientqn/service/client/BJZYYJYCorrforeService.java

@@ -0,0 +1,398 @@
+package com.jiayue.insu.inclientqn.service.client;
+
+
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.date.LocalDateTimeUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.HttpRequest;
+import cn.hutool.json.JSONUtil;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.jiayue.insu.inclientqn.constant.CommonStant;
+import com.jiayue.insu.inclientqn.entity.*;
+import com.jiayue.insu.inclientqn.inenum.BJZYYJYSDEnum;
+import com.jiayue.insu.inclientqn.inenum.StatusEnum;
+import com.jiayue.insu.inclientqn.mapper.BJZYYJYSDCorrforeMapper;
+import com.jiayue.insu.inclientqn.model.BJZYYJYSDResponseVo;
+import com.jiayue.insu.inclientqn.permisson.com.BJZYYJYSDComPermisson;
+import com.jiayue.insu.inclientqn.pulldata.IPullInitForecastData;
+import com.jiayue.insu.inclientqn.service.*;
+import com.jiayue.insu.inclientqn.util.SystermUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @description:
+ * @author: yuanhao
+ * @createDate: 2021/9/27
+ * @version: 1.0
+ */
+@Service
+@Slf4j
+@RequiredArgsConstructor
+public class BJZYYJYCorrforeService extends ServiceImpl<BJZYYJYSDCorrforeMapper, BJZYYJYSDCorrfore> {
+
+    private final RecordService recordService;
+    private final StationService stationService;
+    private final BJZYYJYSDCorrforeService bjzyyjysdCorrforeService;
+    private final VelocityEngine velocityEngine;
+    private final BJZYYJYSDComPermisson bjzyyjysdComPermisson;
+    private final IPullInitForecastData iPullInitForecastData;
+
+
+    @Value("${minio.bucketname}")
+    private String bucketName;
+
+
+    /**
+     * 山东国家研究院下载修正短期预测数据,从一体化上
+     *
+     * @param station
+     * @return
+     */
+    public boolean downLoadCorrforeData(Station station) {
+        // 初始化操作记录
+        Record record = new Record();
+        record.setType(CommonStant.RECORD_TYPE_PULL_CORRECT);
+        record.setStationCode(station.getStationCode());
+        LocalDateTime localDateTime = LocalDateTimeUtil.beginOfDay(LocalDateTime.now());
+        record.setTime(localDateTime);
+        record.setCreateTime(LocalDateTime.now());
+        // 获取token
+        String token = station.getComKey();
+        // 获取下载路径
+        String dataPullUrl = station.getDownloadurl();
+        // 获取场站标识
+        String signCode = station.getSignCode();
+
+        boolean result = false;
+        boolean isUpload = false;
+        String response;
+        List<BJZYYJYSDCorrfore> list = new ArrayList<>();
+        List<BJZYYJYSDCorrfore> listMinio = new ArrayList<>();
+
+        // 如果token为空或者token失效,从新获取token
+        LocalDateTime tokenTime = station.getKeyTime();
+        if (StrUtil.isEmpty(token) || LocalDateTime.now().isAfter(tokenTime)) {
+            if (bjzyyjysdComPermisson.generateKey(station)) {
+                station = stationService.findThis();
+                token = station.getComKey();
+                tokenTime = station.getKeyTime();
+            }
+        }
+
+        // 如果token为不为空并且者token未失效
+        if (StrUtil.isNotEmpty(token) && LocalDateTime.now().isBefore(tokenTime)) {
+
+            try {
+                // 实装请求参数
+                DateTime dateTime = DateUtil.parse(DateUtil.today());
+                DateTime tomorrow = DateUtil.offsetDay(dateTime, 1);
+                // 拼接请求地址
+                // dataPullUrl = dataPullUrl + "?pdate=" + dateTime.toString("yyyy-MM-dd") + "&farm_id=SD0015";
+                dataPullUrl = dataPullUrl + "?pdate="+tomorrow.toString("yyyy-MM-dd")+"&farm_id="+ signCode;
+
+                //https://www.dljyfzjc.spic.com.cn:20280/sdapi/powerforecast/txnypowerforecast/getPowerForecastByFarmAndPdate?pdate=2023-12-15&farm_id=SD0015
+                // 发送请求
+                HttpRequest httpRequest = HttpRequest.get(dataPullUrl)
+                        .header("TENANT-ID", "4")
+                        .header("Authorization", "Bearer " + token);
+                httpRequest.setGlobalTimeout(20000);
+
+                response = httpRequest.execute().body();
+
+                // 如果响应不为空
+                if (StrUtil.isNotEmpty(response)) {
+                    boolean isJson = JSONUtil.isJsonObj(response);
+                    // 如果返回结果是json类型
+                    if (isJson) {
+                        BJZYYJYSDResponseVo bjzyyjysdResponseVo = JSONUtil.toBean(response, BJZYYJYSDResponseVo.class);
+                        String code = bjzyyjysdResponseVo.getCode();
+                        // 如果调用结果成功
+                        if (code.equals(BJZYYJYSDEnum.REQUEST_SUCCESS.getCode())) {
+                            log.info(station.getStationCode() + " 请求短期修正数据返回内容:{}", response);
+                            try {
+                                // 如果data = null 则用原始数据进行上报
+                                if (!"[]".equals(bjzyyjysdResponseVo.getData())) {
+                                    list = correctData(bjzyyjysdResponseVo.getData());
+                                    /**************检测解析数据完整性*******************/
+                                    BigDecimal one = new BigDecimal("1");
+                                    BigDecimal checkCount = new BigDecimal(station.getDays().toString()).add(one).multiply(new BigDecimal("96")).add(one);
+                                    // 如果修正后短期数据不为0
+                                    if (list.size() > 0) {
+                                        if (list.size() < checkCount.intValue()) {
+                                            log.warn("========== 请求短期修正数据缺数: {}", list.size());
+                                        }
+                                        // 将修正数据存库
+                                        bjzyyjysdCorrforeService.updateBetweenForecastTime(list.get(0).getTimeFormat(), list.get(list.size() - 1).getTimeFormat(), list);
+
+                                        // 山东六六巨光需要从minio上请求最新短期文件进行拼接
+                                        listMinio = iPullInitForecastData.pullDQData(station);
+
+                                        // 将一体化修正数据存入map
+                                        Map<Long, BJZYYJYSDCorrfore> map = new HashMap<>();
+                                        for (BJZYYJYSDCorrfore bjzyyjysdCorrfore : list) {
+                                            map.put(bjzyyjysdCorrfore.getForecastTime(), bjzyyjysdCorrfore);
+                                        }
+                                        // 根据关联字段进行替换
+                                        for (int i = 0; i < listMinio.size(); i++) {
+                                            BJZYYJYSDCorrfore bjzyyjysdCorrfore = listMinio.get(i);
+                                            BJZYYJYSDCorrfore bjzyyjysdCorrforeReplace = map.get(bjzyyjysdCorrfore.getForecastTime());
+                                            if (bjzyyjysdCorrforeReplace != null) {
+                                                // 根据关联字段进行替换
+                                                listMinio.set(i, bjzyyjysdCorrforeReplace);
+                                            }
+                                        }
+                                        // 生成短期修正后文件
+                                        if (genFile(station, listMinio)) {
+                                            result = true;
+                                            // 存入记录文件已经生成过
+                                            record.setState(CommonStant.RECORD_TYPE_PULL_CORRECT);
+                                            record.setStateContent(StatusEnum.SUCCESS.getCode());
+                                        }
+                                    }
+                                    // 如果短期数据为空
+                                } else {
+                                    // 存入记录
+                                    record.setState(StatusEnum.CONNECT_RESPONSE_CONTENT_NULL.getCode());
+                                    record.setStateContent(StatusEnum.CONNECT_RESPONSE_CONTENT_NULL.getMsg());
+                                }
+                            } catch (Exception e) {
+                                e.printStackTrace();
+                                record.setState(StatusEnum.CONNECT_RESPONSE_FORMAT_ERROR.getSign());
+                                record.setStateContent("解析短期或生成文件失败");
+                                log.error("========== 解析短期或生成文件失败 ");
+                            }
+
+                            if (result) {
+                                log.info("========== 拉取短期修正数据成功! ==========");
+                                record.setState(StatusEnum.SUCCESS.getSign());
+                                record.setStateContent(String.valueOf(list.size()));
+                            }
+
+                        } else {
+                            record.setState(StatusEnum.RESPONSE_FAIL.getSign());
+                            record.setStateContent(StatusEnum.RESPONSE_FAIL.getMsg());
+                            log.error("========== 拉取短期修正数据失败 响应码异常 " + station.getStationCode() + " :请求短期修正数据返回内容:" + response);
+                        }
+                    } else {
+                        record.setState(StatusEnum.CONNECT_RESPONSE_FORMAT_ERROR.getSign());
+                        record.setStateContent(StatusEnum.CONNECT_RESPONSE_FORMAT_ERROR.getMsg());
+                        log.error("========== 拉取短期修正数据失败 接收响应字符串非json格式 ");
+                    }
+                } else {
+                    record.setState(StatusEnum.CONNECT_RESPONSE_CONTENT_NULL.getSign());
+                    record.setStateContent(StatusEnum.CONNECT_RESPONSE_CONTENT_NULL.getMsg());
+                    log.error("========== 拉取短期修正数据失败  返回响应内容为空 ==========");
+                }
+
+            } catch (Exception e) {
+                record.setState(StatusEnum.CONNECT_ERROR.getSign());
+                record.setStateContent(StatusEnum.CONNECT_ERROR.getMsg());
+                log.error("========== 请求短期修正数据失败 连接断开或请求超时 ==========");
+                e.printStackTrace();
+
+            }
+        }
+        recordService.save(record);
+        return isUpload;
+    }
+
+
+    /**
+     * 数据解析
+     *
+     * @param data 待解析数据
+     * @return
+     * @throws Exception
+     */
+    public List<BJZYYJYSDCorrfore> correctData(String data) throws Exception {
+
+        List<BJZYYJYSDCorrfore> list = new ArrayList<>();
+        data = data.substring(1, data.length() - 1);
+        String[] content = data.split("(?<=})\\s*,\\s*");
+
+        for (int i = 0; i < content.length; i++) {
+            BJZYYJYSDCorrfore bjzyyjysdCorrfore = new BJZYYJYSDCorrfore();
+            String column = content[i];
+            //JSON 字符串转换为一个树状结构
+            ObjectMapper objectMapper = new ObjectMapper();
+            JsonNode rootNode = objectMapper.readTree(column);
+            // 通过键名获取相应的值
+            String updateTime = rootNode.get("updateTime").asText();
+            String forecastTime = rootNode.get("pdate").asText();
+            double ageValue = rootNode.get("forecast").asDouble();
+            // 将预测时间转换为时间戳格式
+            Long forecast = DateUtil.parse(forecastTime, "yyyy-MM-dd HH:mm:ss").getTime() + 15*60*1000L +15*60*1000L*i;
+            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+            String forecastDateFormat = dateFormat.format(new Date(forecast));
+            // 存入实体
+            bjzyyjysdCorrfore.setForecastTime(forecast);
+            bjzyyjysdCorrfore.setTimeFormat(DateUtil.parse(forecastDateFormat, "yyyy-MM-dd HH:mm:ss").toTimestamp().toLocalDateTime());
+            bjzyyjysdCorrfore.setUpdateTime(DateUtil.parse(updateTime, "yyyy-MM-dd HH:mm:ss").toTimestamp().toLocalDateTime());
+            bjzyyjysdCorrfore.setFpValue(isNumberOrNull(String.valueOf(ageValue)));
+            // 排序
+            Collections.sort(list, Comparator.comparing(BJZYYJYSDCorrfore::getForecastTime));
+            list.add(bjzyyjysdCorrfore);
+        }
+        return list;
+    }
+
+    /**
+     * 判断是否是NULL 和是否是数值
+     *
+     * @param data
+     * @return
+     */
+    public BigDecimal isNumberOrNull(String data) {
+        BigDecimal bigDecimal = new BigDecimal("-99");
+        if (!data.contains("null") && !data.contains("NULL")) {
+            Pattern pattern = Pattern.compile("-[0-9]+(.[0-9]+)?|[0-9]+(.[0-9]+)?");
+            Matcher isNum = pattern.matcher(data);
+            try {
+                if (isNum.matches()) {
+                    bigDecimal = new BigDecimal(data).setScale(2, BigDecimal.ROUND_DOWN);
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        return bigDecimal;
+    }
+
+    /**
+     * 生成修正后的短期文件(山东中央研究院)
+     *
+     * @param station
+     * @param list
+     * @return
+     */
+    public boolean genFile(Station station, List<BJZYYJYSDCorrfore> list) {
+        boolean result = true;
+        // 初始化模板
+        String vmsPath = SystermUtils.getResourceBasePath() + "/vms/DQ.vm";
+        File file;
+        Template template = this.velocityEngine.getTemplate(vmsPath);
+        // 如果模板不为空
+        if (template != null) {
+            VelocityContext velocityContext;
+            StringWriter writer;
+            // 将修正后的短期数据按照预测时间排序
+            list.sort(Comparator.comparing(BJZYYJYSDCorrfore::getForecastTime));
+            // 根据修正后的数据,拼接需要的数据
+            List<Map<String, Object>> vList = new ArrayList<>();
+            for (BJZYYJYSDCorrfore a : list) {
+                Map<String, Object> map = new HashMap<>();
+                map.put("id", a.getId());
+                map.put("stationName", station.getName());
+                map.put("forecastTime", DateUtil.format(new Date(a.getForecastTime()), "yyyy-MM-dd HH:mm:ss"));
+                map.put("fpValue", a.getFpValue() == null ? "-99" : a.getFpValue());
+                vList.add(map);
+            }
+            // 格式化模板数据
+            writer = new StringWriter();
+            velocityContext = new VelocityContext();
+            velocityContext.put("stationName", station.getName());
+            velocityContext.put("date", DateUtil.format(new Date(), "yyyy-MM-dd"));
+            velocityContext.put("vList", vList);
+            template.merge(velocityContext, writer);
+            // 山东场站分为AB机,需拆分文件生成路径
+            String[] filePath = station.getLocalFilePath().split(";");
+            for (int i = 0; i < filePath.length; i++) {
+                // 获取文件路径
+                File fileUrl = new File(filePath[i]);
+                // 判断目录是否存在
+                if (!fileUrl.exists()) {
+                    fileUrl.mkdirs();
+                }
+                // 获取文件名
+                String fileName = "DQ_" + DateUtil.format(DateUtil.beginOfDay(new Date()), "yyyyMMddHHmmss") + "0.RB";
+                file = new File(filePath[i] + File.separatorChar + fileName);
+                // 写入文件
+                result = writeFile(file, station, writer, fileName, filePath[i]);
+            }
+        }
+        return result;
+    }
+
+
+    /**
+     *  写入文件
+     * @param file
+     * @param station
+     * @param writer
+     * @param fileName
+     * @param filePath
+     * @return
+     */
+    private boolean writeFile(File file, Station station, StringWriter writer, String fileName,String filePath) {
+        boolean result = true;
+        // 获取文件路径
+        File fileUrl = new File(filePath);
+        // 判断目录是否存在
+        if (!fileUrl.exists()) {
+            fileUrl.mkdirs();
+        }
+        // 检查文件是否存在
+        File existingFile = new File(filePath + File.separator + fileName);
+        if (existingFile.exists()) {
+            // 如果存在同名文件,尝试删除
+            boolean deleted = existingFile.delete();
+            if (!deleted) {
+                // 如果无法删除,记录警告并返回false
+                log.warn("无法删除文件:" + fileName);
+                return false;
+            }
+        }
+
+        // 创建流
+        FileOutputStream os = null;
+        try {
+            boolean res = file.createNewFile();
+            // 如果创建成功
+            if (res) {
+                os = new FileOutputStream(file);
+                // 采用UTF-8字符集
+                os.write(writer.toString().getBytes("UTF-8"));
+                os.flush();
+                // 创建文件失败
+            } else {
+                result = false;
+                log.warn(station.getStationCode() + "文件名:" + fileName + " 生成失败");
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+            result = false;
+            log.warn(station.getStationCode() + " 创建" + "文件名:" + fileName + "失败");
+        } finally {
+            // 如果流不为空,关闭流
+            if (os != null) {
+                try {
+                    os.close();
+                } catch (IOException e) {
+                    log.error("文件生成关闭流失败", e);
+                }
+            }
+            log.info("执行生成文件完毕:" + filePath + File.separatorChar + fileName);
+            return result;
+        }
+    }
+}

+ 7 - 1
in-client-qn/src/main/java/com/jiayue/insu/inclientqn/service/client/BackDataAnalysisService.java

@@ -118,6 +118,12 @@ public class BackDataAnalysisService {
                 this.analysisAndSave(time,file,stationCode);
             }
         }else{
+
+            List<Station> stationList = stationService.findAll();
+            String stationCode = "";
+            if(stationList!=null && stationList.size()>0){
+                stationCode = stationList.get(0).getStationCode();
+            }
             // 查询操作记录
             Record record = recordService.findTimeAndTypeAndState(LocalDateTimeUtil.of(time), CommonStant.RECORD_TYPE_BACK_DATA_FILE, StatusEnum.SUCCESS.getSign());
             // 如果操作记录不存在,则进行解析文件
@@ -127,7 +133,7 @@ public class BackDataAnalysisService {
             }
             file = FileUtil.file(backFilePath + File.separatorChar + fileName);
             // 根据文件及场站信息,解析文件
-            this.analysisAndSave(time,file,null);
+            this.analysisAndSave(time,file,stationCode);
         }
     }
 

+ 5 - 3
in-client-qn/src/main/java/com/jiayue/insu/inclientqn/service/client/InitRunner.java

@@ -1,8 +1,8 @@
 package com.jiayue.insu.inclientqn.service.client;
 
 import cn.hutool.core.date.DateUtil;
-import cn.hutool.core.date.LocalDateTimeUtil;
 import com.jiayue.insu.inclientqn.entity.Station;
+import com.jiayue.insu.inclientqn.permisson.com.BJZYYJYSDComPermisson;
 import com.jiayue.insu.inclientqn.permisson.com.ComPermisson;
 import com.jiayue.insu.inclientqn.service.StationService;
 import com.jiayue.insu.inclientqn.util.DateTimeUtils;
@@ -10,7 +10,6 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.CommandLineRunner;
 import org.springframework.stereotype.Component;
 
-import java.time.LocalDateTime;
 import java.util.List;
 
 @Component
@@ -18,6 +17,8 @@ public class InitRunner implements CommandLineRunner {
     @Autowired
     private ComPermisson comPermisson;
     @Autowired
+    private BJZYYJYSDComPermisson bjzyyjysdComPermisson;
+    @Autowired
     private StationService stationService;
     @Autowired
     private BackDataAnalysisService backDataAnalysisService;
@@ -26,8 +27,9 @@ public class InitRunner implements CommandLineRunner {
         List<Station> stationList = stationService.findAll();
         for(Station station :stationList){
             comPermisson.generateKey(station);
+            // 山东国家研究院
+            bjzyyjysdComPermisson.generateKey(station);
         }
-
         long time = DateTimeUtils.get15min(DateUtil.date().getTime());
         backDataAnalysisService.watchFile(time);
     }

+ 60 - 0
in-client-qn/src/main/java/com/jiayue/insu/inclientqn/service/impl/ApiServiceImpl.java

@@ -0,0 +1,60 @@
+package com.jiayue.insu.inclientqn.service.impl;
+
+import cn.hutool.http.HttpUtil;
+import cn.hutool.json.JSONUtil;
+import com.jiayue.insu.inclientqn.service.ApiService;
+import com.jiayue.insu.inclientqn.service.RecordService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import java.util.*;
+
+
+/**
+ * 预测数据业务实现
+ *
+ * @author yh
+ * @version 1.0
+ * @since 2022/5/22 11:29
+ */
+@Slf4j
+@Service
+public class ApiServiceImpl implements ApiService {
+
+    @Value("${minio.pull.url}")
+    String url;
+    @Value("${minio.pull.fileurl}")
+    String fileurl;
+    @Value("${minio.fileurl}")
+    String fileDir;
+    @Value("${minio.bucketname}")
+    private String bucketName;
+    @Value("${minio.postBackUrl}")
+    private String postBackUrl;
+
+
+    @Autowired
+    public RecordService recordService;
+
+    /**
+     * 从minIo下载文件后,回传状态
+     *
+     * @param stationCode
+     * @param fileName
+     * @param type
+     * @param status
+     */
+    @Override
+    public void postBackMinIoState(String stationCode, String fileName, String type, String status) {
+        Map urlParams = new HashMap(4);
+        urlParams.put("stationCode", stationCode);
+        urlParams.put("forecastFileName", fileName);
+        urlParams.put("type", type);
+        urlParams.put("status", status);
+        log.debug("回传文件状态给新平台,请求参数", JSONUtil.toJsonStr(urlParams));
+        String repose = HttpUtil.post(postBackUrl, urlParams, 10000);
+        log.info("回传文件状态给新平台,请求相应 {}", repose);
+    }
+
+}

+ 41 - 0
in-client-qn/src/main/java/com/jiayue/insu/inclientqn/service/impl/BJZYYJYSDCorrforeServiceImpl.java

@@ -0,0 +1,41 @@
+package com.jiayue.insu.inclientqn.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.jiayue.insu.inclientqn.entity.BJZYYJYSDCorrfore;
+import com.jiayue.insu.inclientqn.mapper.BJZYYJYSDCorrforeMapper;
+import com.jiayue.insu.inclientqn.service.BJZYYJYSDCorrforeService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * 修正数据业务实现(山东国家研究院)
+ *
+ * @author yh
+ * @version 1.0
+ * @since 2022/5/22 11:29
+ */
+@Service
+@Slf4j
+public class BJZYYJYSDCorrforeServiceImpl extends ServiceImpl<BJZYYJYSDCorrforeMapper, BJZYYJYSDCorrfore> implements BJZYYJYSDCorrforeService {
+
+
+    @Override
+    public boolean updateBetweenForecastTime(LocalDateTime statTime, LocalDateTime endTime, List<BJZYYJYSDCorrfore> list) {
+
+        try {
+            LambdaQueryWrapper<BJZYYJYSDCorrfore> remove = new LambdaQueryWrapper<>();
+            remove.between(BJZYYJYSDCorrfore::getTimeFormat,statTime,endTime);
+            this.remove(remove);
+            this.saveBatch(list);
+            log.info("========== 数据入库成功");
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+        return Boolean.TRUE;
+
+    }
+}

+ 52 - 0
in-client-qn/src/main/java/com/jiayue/insu/inclientqn/service/impl/ForecastDataServiceImpl.java

@@ -0,0 +1,52 @@
+package com.jiayue.insu.inclientqn.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.jiayue.insu.inclientqn.entity.ForecastData;
+import com.jiayue.insu.inclientqn.mapper.ForecastDataMapper;
+import com.jiayue.insu.inclientqn.service.ForecastDataService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 预测数据业务实现
+ *
+ * @author yh
+ * @version 1.0
+ * @since 2022/5/22 11:29
+ */
+@Service
+public class ForecastDataServiceImpl extends ServiceImpl<ForecastDataMapper, ForecastData> implements ForecastDataService {
+
+    /**
+     * 删除数据 通过场站编码和时间
+     * @param station 场站编码
+     * @param startTime 开始时间
+     * @param endTime 结束时间
+     * @return 结果
+     */
+    @Override
+    public boolean removeBetweenTimeByStation(String station, Long startTime, Long endTime) {
+        LambdaQueryWrapper<ForecastData> lambdaQueryWrapper = new LambdaQueryWrapper<>();
+        lambdaQueryWrapper.between(ForecastData::getForecastTime,startTime, endTime);
+        lambdaQueryWrapper.eq(ForecastData::getStationCode,station);
+        this.remove(lambdaQueryWrapper);
+        return Boolean.TRUE;
+    }
+
+    /**
+     * 查询数据 通过场站编码和时间
+     * @param station 场站编码
+     * @param startTime 开始时间
+     * @param endTime 结束时间
+     * @return 结果
+     */
+    @Override
+    public List<ForecastData> findTimeByStation(String station, Long startTime, Long endTime) {
+        LambdaQueryWrapper<ForecastData> lambdaQueryWrapper = new LambdaQueryWrapper<>();
+        lambdaQueryWrapper.between(ForecastData::getForecastTime,startTime, endTime);
+        lambdaQueryWrapper.eq(ForecastData::getStationCode,station);
+        return this.list(lambdaQueryWrapper);
+    }
+}

+ 208 - 0
in-client-qn/src/main/java/com/jiayue/insu/inclientqn/util/JsonResultUtil.java

@@ -0,0 +1,208 @@
+package com.jiayue.insu.inclientqn.util;
+
+import cn.hutool.json.JSONObject;
+
+/**
+ * 返回json结果记录
+ *
+ * @author zcl
+ * @version 1.0
+ * @since 2023/3/28 16:22
+ */
+
+public class JsonResultUtil {
+
+    /** 状态码 */
+    public static final String CODE_TAG = "code";
+
+    /** 返回内容 */
+    public static final String MSG_TAG = "msg";
+
+    /** 返回内容 */
+    public static final String DETAIL_TAG = "detail";
+
+    /** 数据对象 */
+    public static final String DATA_TAG = "data";
+
+    /**
+     * 状态类型
+     */
+    public enum Type
+    {
+        /** 成功 */
+        success("1","success",""),
+        /** 忽略 */
+        ignore("666","ignore",""),
+        /** 警告 */
+        warn("301","warn",""),
+        /** 失败 */
+        failure("0","failure",""),
+        /** 错误 */
+        error("-1","error","");
+
+        private final String value;
+        private final String msg;
+        private final String detail;
+
+        Type(String value , String msg ,String detail)
+        {
+            this.value = value;
+            this.msg = msg;
+            this.detail = detail;
+        }
+
+        public String value()
+        {
+            return this.value;
+        }
+
+        public String msg()
+        {
+            return this.msg;
+        }
+
+        public String detail()
+        {
+            return this.detail;
+        }
+    }
+
+    /**
+     * 存入code和msg
+     *
+     * @param type 状态类型
+     */
+    public static JSONObject jsonResult(Type type)
+    {
+        JSONObject result = new JSONObject();
+        result.set(CODE_TAG,type.value);
+        result.set(MSG_TAG,type.msg);
+        return result;
+    }
+
+    /**
+     * 存入code、data
+     *
+     * @param type 状态类型
+     * @param data 数据对象
+     */
+    public static JSONObject jsonResult(Type type, Object data)
+    {
+        JSONObject result = new JSONObject();
+        result.set(MSG_TAG, type.msg);
+        result.set(CODE_TAG, type.value);
+        if (data != null) {
+            result.set(DATA_TAG, data);
+        }
+        return result;
+    }
+
+    /**
+     * 存入code、data
+     *
+     * @param type 状态类型
+     * @param detail 数据对象
+     */
+    public static JSONObject jsonResult(Type type, String detail)
+    {
+        JSONObject result = new JSONObject();
+        result.set(MSG_TAG, type.msg);
+        result.set(CODE_TAG, type.value);
+        result.set(DETAIL_TAG, detail);
+        return result;
+    }
+
+    /**
+     * 返回成功消息
+     *
+     * @return 成功消息
+     */
+    public static JSONObject success()
+    {
+        return success(null);
+    }
+
+    /**
+     * 返回成功数据
+     *
+     * @return 成功消息
+     */
+    public static JSONObject success(Object data)
+    {
+        return jsonResult(Type.success, data);
+    }
+
+    /**
+     * 返回警告消息
+     *
+     * @return 警告消息
+     */
+    public static JSONObject warn()
+    {
+        return warn(null);
+    }
+
+    /**
+     * 返回警告消息
+     *
+     * @param data 数据对象
+     * @return 警告消息
+     */
+    public static JSONObject warn(Object data)
+    {
+        return jsonResult(Type.warn, data);
+    }
+
+    /**
+     * 返回错误消息
+     *
+     * @return
+     */
+    public static JSONObject error()
+    {
+        return error(null);
+    }
+
+    /**
+     * 返回错误消息
+     *
+     * @param data 数据对象
+     * @return 警告消息
+     */
+    public static JSONObject error(Object data)
+    {
+        return jsonResult(Type.error,data);
+    }
+
+    /**
+     * 返回错误消息
+     *
+     * @return
+     */
+    public static JSONObject failure()
+    {
+        return failure(null);
+    }
+
+    /**
+     * 返回错误消息
+     *
+     * @param data 数据对象
+     * @return 警告消息
+     */
+    public static JSONObject failure(Object data)
+    {
+        return jsonResult(Type.failure,data);
+    }
+
+    /**
+     * 返回错误消息
+     *
+     * @param detail 错误信息
+     * @return 警告消息
+     */
+    public static JSONObject failure(String detail)
+    {
+        return jsonResult(Type.failure,detail);
+    }
+}

+ 15 - 0
in-client-qn/src/main/java/com/jiayue/insu/inclientqn/util/SystermUtils.java

@@ -2,6 +2,8 @@ package com.jiayue.insu.inclientqn.util;
 
 import cn.hutool.core.date.DateUtil;
 
+import cn.hutool.crypto.digest.HMac;
+import cn.hutool.crypto.digest.HmacAlgorithm;
 import com.jiayue.insu.inclientqn.constant.CommonStant;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.util.ResourceUtils;
@@ -133,4 +135,17 @@ public class SystermUtils {
         return fileNames;
     }
 
+    /**
+     * 获取签名
+     * @param signOrg
+     * @return
+     */
+    public static String caluMd5Sign(String signOrg) {
+        //签名密钥
+        byte[] key = "123456789".getBytes();
+        HMac mac = new HMac(HmacAlgorithm.HmacMD5, key);
+
+        String macHexSign = mac.digestHex(signOrg);
+        return macHexSign;
+    }
 }