1.完成天气预报计算任务执行接口
2.修改系统全局form-data请求编码格式 3.完成输运模拟贡献分析功能
This commit is contained in:
parent
259604d42a
commit
27e24880b8
|
|
@ -270,7 +270,7 @@ public interface CommonConstant {
|
||||||
/**
|
/**
|
||||||
* 报表允许设计开发的角色
|
* 报表允许设计开发的角色
|
||||||
*/
|
*/
|
||||||
public static String[] allowDevRoles = new String[]{"lowdeveloper", "admin"};
|
String[] allowDevRoles = new String[]{"lowdeveloper", "admin"};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 缓存用户最后一次收到消息通知的时间 KEY
|
* 缓存用户最后一次收到消息通知的时间 KEY
|
||||||
|
|
@ -286,4 +286,14 @@ public interface CommonConstant {
|
||||||
* 缓存所有核设施key
|
* 缓存所有核设施key
|
||||||
*/
|
*/
|
||||||
String ALL_NUCLEARFACILITY = "nuclearfacility";
|
String ALL_NUCLEARFACILITY = "nuclearfacility";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 输运模拟贡献分析数据KEY
|
||||||
|
*/
|
||||||
|
String TRANSPORT_CONTRIBUTION_ANALYSIS = "transport:contribution_analysis:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 输运模拟时序分析数据KEY
|
||||||
|
*/
|
||||||
|
String TRANSPORT_TIMING_ANALYSIS = "transport:timing_analysis:";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ public enum TransportTaskStatusEnum {
|
||||||
/**
|
/**
|
||||||
* 执行失败
|
* 执行失败
|
||||||
*/
|
*/
|
||||||
ERROR(-1),
|
FAILURE(-1),
|
||||||
/**
|
/**
|
||||||
* 未开始
|
* 未开始
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
package org.jeecg.common.constant.enums;
|
||||||
|
|
||||||
|
public enum TransportTimingAnalysisEnum {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 3小时
|
||||||
|
*/
|
||||||
|
THREE_HOURS(3),
|
||||||
|
/**
|
||||||
|
* 6小时
|
||||||
|
*/
|
||||||
|
SIX_HOURS(-1),
|
||||||
|
/**
|
||||||
|
* 12小时
|
||||||
|
*/
|
||||||
|
TWELVE_HOURS(-1),
|
||||||
|
/**
|
||||||
|
* 24小时
|
||||||
|
*/
|
||||||
|
TWENTY_FOUR_HOURS(-1);
|
||||||
|
|
||||||
|
private Integer key;
|
||||||
|
|
||||||
|
TransportTimingAnalysisEnum(Integer key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getKey(){
|
||||||
|
return this.key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
package org.jeecg.common.constant.enums;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 盘古和Graphcast气象预测模型使用的数据源
|
||||||
|
*/
|
||||||
|
public enum WeatherForecastDatasourceEnum {
|
||||||
|
|
||||||
|
|
||||||
|
CDS(1),
|
||||||
|
LOCATION_FILE(2);
|
||||||
|
|
||||||
|
private Integer key;
|
||||||
|
|
||||||
|
WeatherForecastDatasourceEnum(Integer key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getKey(){
|
||||||
|
return this.key;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
package org.jeecg.common.constant.enums;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 预测模型说明枚举
|
|
||||||
*/
|
|
||||||
public enum WeatherModelEnum {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 盘古模型
|
|
||||||
*/
|
|
||||||
PANGU(1),
|
|
||||||
/**
|
|
||||||
* Graphcast
|
|
||||||
*/
|
|
||||||
GRAPHCAST(2);
|
|
||||||
|
|
||||||
private Integer key;
|
|
||||||
|
|
||||||
WeatherModelEnum(Integer key) {
|
|
||||||
this.key = key;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getKey(){
|
|
||||||
return this.key;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -5,6 +5,10 @@ package org.jeecg.common.constant.enums;
|
||||||
*/
|
*/
|
||||||
public enum WeatherTaskStatusEnum {
|
public enum WeatherTaskStatusEnum {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行失败
|
||||||
|
*/
|
||||||
|
FAILURE(-1),
|
||||||
/**
|
/**
|
||||||
* 未开始
|
* 未开始
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -53,4 +53,19 @@ public class SystemStorageProperties {
|
||||||
* CMAQ数据存储路径
|
* CMAQ数据存储路径
|
||||||
*/
|
*/
|
||||||
private String cmaqPath;
|
private String cmaqPath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ai-models 安装地址
|
||||||
|
*/
|
||||||
|
private String aiModelsPath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 盘古模型执行路径
|
||||||
|
*/
|
||||||
|
private String panguModelExecPath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* graphcast模型执行路径
|
||||||
|
*/
|
||||||
|
private String graphcastModelExecPath;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import java.io.IOException;
|
||||||
public class CopyTokenFilter extends OncePerRequestFilter {
|
public class CopyTokenFilter extends OncePerRequestFilter {
|
||||||
@Override
|
@Override
|
||||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
|
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
|
||||||
|
request.setCharacterEncoding("UTF-8");
|
||||||
// 以下为undertow定制代码,如切换其它servlet容器,需要同步更换
|
// 以下为undertow定制代码,如切换其它servlet容器,需要同步更换
|
||||||
HttpServletRequestImpl undertowRequest = (HttpServletRequestImpl) request;
|
HttpServletRequestImpl undertowRequest = (HttpServletRequestImpl) request;
|
||||||
String token = request.getHeader("Authorization");
|
String token = request.getHeader("Authorization");
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ public class WeatherData implements Serializable {
|
||||||
private LocalDateTime dataStartTime;
|
private LocalDateTime dataStartTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数据来源(1-盘古模型,2-graphcast,3-cra40,4-ncep,5-t1h,6-fnl)
|
* 数据来源(1-盘古模型,2-graphcast,3-cra40,4-ncep,5-fnl,6-t1h)
|
||||||
*/
|
*/
|
||||||
@TableField(value = "data_source")
|
@TableField(value = "data_source")
|
||||||
private Integer dataSource;
|
private Integer dataSource;
|
||||||
|
|
@ -62,12 +62,6 @@ public class WeatherData implements Serializable {
|
||||||
@TableField(value = "file_path")
|
@TableField(value = "file_path")
|
||||||
private String filePath;
|
private String filePath;
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建人
|
|
||||||
*/
|
|
||||||
@TableField(value = "create_by")
|
|
||||||
private String createBy;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建时间
|
* 创建时间
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,37 @@
|
||||||
package org.jeecg.modules.base.entity;
|
package org.jeecg.modules.base.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
import jakarta.validation.constraints.Null;
|
import jakarta.validation.constraints.Null;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.jeecg.common.system.base.entity.BaseEntity;
|
|
||||||
import org.jeecg.common.validgroup.InsertGroup;
|
import org.jeecg.common.validgroup.InsertGroup;
|
||||||
import org.jeecg.common.validgroup.UpdateGroup;
|
import org.jeecg.common.validgroup.UpdateGroup;
|
||||||
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 天气预测任务表
|
* 天气预测任务表
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@TableName("stas_weather_task")
|
@TableName("stas_weather_task")
|
||||||
public class WeatherTask extends BaseEntity {
|
public class WeatherTask{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ID
|
||||||
|
*/
|
||||||
|
@Null(message = "ID必须为空",groups = { InsertGroup.class})
|
||||||
|
@NotNull(message = "ID不能为空",groups = { UpdateGroup.class})
|
||||||
|
@TableId(type = IdType.INPUT)
|
||||||
|
@Schema(description = "ID")
|
||||||
|
private java.lang.String id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 任务名称
|
* 任务名称
|
||||||
|
|
@ -27,18 +41,18 @@ public class WeatherTask extends BaseEntity {
|
||||||
private String taskName;
|
private String taskName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 任务状态(0-未开始,1-运行中,2-已完成)
|
* 任务状态(-1失败,0-未开始,1-运行中,2-已完成)
|
||||||
*/
|
*/
|
||||||
@Null(message = "任务状态必须为空",groups = {InsertGroup.class, UpdateGroup.class})
|
@Null(message = "任务状态必须为空",groups = {InsertGroup.class, UpdateGroup.class})
|
||||||
@TableField(value = "task_status")
|
@TableField(value = "task_status")
|
||||||
private Integer taskStatus;
|
private Integer taskStatus;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 耗时(小时),默认0
|
* 耗时(分钟),默认0
|
||||||
*/
|
*/
|
||||||
@Null(message = "耗时参数必须为空",groups = {InsertGroup.class, UpdateGroup.class})
|
@Null(message = "耗时参数必须为空",groups = {InsertGroup.class, UpdateGroup.class})
|
||||||
@TableField(value = "time_consuming")
|
@TableField(value = "time_consuming")
|
||||||
private Integer timeConsuming;
|
private Double timeConsuming;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 预测模型(1-盘古、2-Graphcast)
|
* 预测模型(1-盘古、2-Graphcast)
|
||||||
|
|
@ -79,7 +93,38 @@ public class WeatherTask extends BaseEntity {
|
||||||
/**
|
/**
|
||||||
* 如果data_sources为2,则存储本地文件路径
|
* 如果data_sources为2,则存储本地文件路径
|
||||||
*/
|
*/
|
||||||
|
@Null(message = "预测文件本地路径必须为空",groups = {InsertGroup.class, UpdateGroup.class})
|
||||||
@TableField(value = "input_file")
|
@TableField(value = "input_file")
|
||||||
private String inputFile;
|
private String inputFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预测文件
|
||||||
|
*/
|
||||||
|
@TableField(exist = false)
|
||||||
|
private MultipartFile file;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建人
|
||||||
|
*/
|
||||||
|
private String createBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新人
|
||||||
|
*/
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新时间
|
||||||
|
*/
|
||||||
|
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date updateTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -7,9 +7,8 @@ import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.time.LocalDateTime;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 天气预测任务日志表
|
* 天气预测任务日志表
|
||||||
|
|
@ -41,6 +40,6 @@ public class WeatherTaskLog implements Serializable {
|
||||||
* 创建时间
|
* 创建时间
|
||||||
*/
|
*/
|
||||||
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
|
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private LocalDateTime createTime;
|
private Date createTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -25,7 +25,7 @@ public class StationDataController {
|
||||||
return Result.OK(stationDataService.getAllStations());
|
return Result.OK(stationDataService.getAllStations());
|
||||||
}
|
}
|
||||||
|
|
||||||
@AutoLog(value = "查询所有台站")
|
@AutoLog(value = "查询所有设施")
|
||||||
@Operation(summary = "查询所有设施")
|
@Operation(summary = "查询所有设施")
|
||||||
@GetMapping("getAllNuclearfacility")
|
@GetMapping("getAllNuclearfacility")
|
||||||
public Result<?> getAllNuclearfacility(){
|
public Result<?> getAllNuclearfacility(){
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package org.jeecg.controller;
|
package org.jeecg.controller;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.jeecg.common.api.vo.Result;
|
import org.jeecg.common.api.vo.Result;
|
||||||
|
|
@ -43,6 +44,40 @@ public class TransportResultDataController {
|
||||||
return Result.OK(transportResultDataService.getConformityAnalysis(taskId,stationId,nuclideName,facilityName));
|
return Result.OK(transportResultDataService.getConformityAnalysis(taskId,stationId,nuclideName,facilityName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AutoLog(value = "查询贡献分析数据")
|
||||||
|
@Operation(summary = "查询贡献分析数据")
|
||||||
|
@GetMapping("getContributionAnalysis")
|
||||||
|
public Result<?> getContributionAnalysis(@NotNull(message = "任务id不能为空") Integer taskId,
|
||||||
|
@NotBlank(message = "台站编码不能为空") String stationCode) {
|
||||||
|
return Result.OK(transportResultDataService.getContributionAnalysis(taskId,stationCode));
|
||||||
|
}
|
||||||
|
|
||||||
|
@AutoLog(value = "处理贡献分析数据-测试接口")
|
||||||
|
@Operation(summary = "处理贡献分析数据-测试接口")
|
||||||
|
@GetMapping("handleContributionAnalysis")
|
||||||
|
public Result<?> handleContributionAnalysis(@NotNull(message = "任务id不能为空") Integer taskId) {
|
||||||
|
transportResultDataService.handleContributionAnalysis(taskId);
|
||||||
|
return Result.OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AutoLog(value = "查询反演核设施时序数据接口")
|
||||||
|
@Operation(summary = "查询反演核设施时序数据接口")
|
||||||
|
@GetMapping("getTimingAnalysis")
|
||||||
|
public Result<?> getTimingAnalysis(@NotNull(message = "任务id不能为空") Integer taskId,
|
||||||
|
@NotBlank(message = "台站编码不能为空") String stationCode,
|
||||||
|
@NotBlank(message = "核设施名称不能为空") String facilityName,
|
||||||
|
@NotNull(message = "时间序号不能为空") Integer timeNum) {
|
||||||
|
return Result.OK(transportResultDataService.getTimingAnalysis(taskId,stationCode,facilityName,timeNum));
|
||||||
|
}
|
||||||
|
|
||||||
|
@AutoLog(value = "处理反演核设施时序数据-测试接口")
|
||||||
|
@Operation(summary = "处理反演核设施时序数据-测试接口")
|
||||||
|
@GetMapping("handleTimingAnalysis")
|
||||||
|
public Result<?> handleTimingAnalysis(@NotNull(message = "任务id不能为空") Integer taskId) {
|
||||||
|
transportResultDataService.handleTimingAnalysis(taskId);
|
||||||
|
return Result.OK();
|
||||||
|
}
|
||||||
|
|
||||||
@AutoLog(value = "查询任务所属核设施数据")
|
@AutoLog(value = "查询任务所属核设施数据")
|
||||||
@Operation(summary = "查询任务所属核设施数据")
|
@Operation(summary = "查询任务所属核设施数据")
|
||||||
@GetMapping("getTaskFacility")
|
@GetMapping("getTaskFacility")
|
||||||
|
|
@ -50,4 +85,18 @@ public class TransportResultDataController {
|
||||||
return Result.OK(transportResultDataService.getTaskFacility(taskId));
|
return Result.OK(transportResultDataService.getTaskFacility(taskId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AutoLog(value = "查询任务所属台站数据")
|
||||||
|
@Operation(summary = "查询任务所属台站数据")
|
||||||
|
@GetMapping("getTaskStations")
|
||||||
|
public Result<?> getTaskStations(@NotNull(message = "任务id不能为空") Integer taskId) {
|
||||||
|
return Result.OK(transportResultDataService.getTaskStations(taskId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@AutoLog(value = "查询任务所属NC层级数据")
|
||||||
|
@Operation(summary = "查询任务所属NC层级数据")
|
||||||
|
@GetMapping("getTaskNCHeightLevel")
|
||||||
|
public Result<?> getTaskNCHeightLevel(@NotNull(message = "任务id不能为空") Integer taskId) {
|
||||||
|
return Result.OK(transportResultDataService.getTaskNCHeightLevel(taskId));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
package org.jeecg.service;
|
package org.jeecg.service;
|
||||||
|
|
||||||
|
import org.jeecg.vo.ContributionAnalysisVO;
|
||||||
import org.jeecg.vo.QueryDiffusionVO;
|
import org.jeecg.vo.QueryDiffusionVO;
|
||||||
|
import org.jeecg.vo.TaskStationsVO;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
@ -37,4 +39,49 @@ public interface TransportResultDataService {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
List<String> getTaskFacility(Integer taskId);
|
List<String> getTaskFacility(Integer taskId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取贡献分析数据
|
||||||
|
* @param taskId
|
||||||
|
* @param stationCode
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
ContributionAnalysisVO getContributionAnalysis(Integer taskId, String stationCode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理贡献分析数据存入缓存
|
||||||
|
* @param taskId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
void handleContributionAnalysis(Integer taskId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询任务所属台站数据
|
||||||
|
* @param taskId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
List<TaskStationsVO> getTaskStations(Integer taskId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询任务所属NC层级数据
|
||||||
|
* @param taskId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Map<Integer, Object> getTaskNCHeightLevel(Integer taskId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询反演核设施时序数据接口
|
||||||
|
* @param taskId
|
||||||
|
* @param stationCode
|
||||||
|
* @param facilityName
|
||||||
|
* @param timeNum
|
||||||
|
*/
|
||||||
|
Map<String,Double> getTimingAnalysis(Integer taskId,String stationCode,String facilityName,Integer timeNum);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理反演核设施时序数据存入缓存
|
||||||
|
* @param taskId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
void handleTimingAnalysis(Integer taskId);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ public interface TransportTaskService extends IService<TransportTask> {
|
||||||
* @param taskId
|
* @param taskId
|
||||||
* @param minute
|
* @param minute
|
||||||
*/
|
*/
|
||||||
void updateTaskTimeConsuming(Integer taskId, Double minute);
|
void updateTaskStatusToCompleted(Integer taskId, Double minute);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除任务日志
|
* 删除任务日志
|
||||||
|
|
|
||||||
|
|
@ -2,22 +2,31 @@ package org.jeecg.service.impl;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.date.DateUtil;
|
import cn.hutool.core.date.DateUtil;
|
||||||
|
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||||
import cn.hutool.core.io.FileUtil;
|
import cn.hutool.core.io.FileUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.jeecg.common.constant.CommonConstant;
|
||||||
import org.jeecg.common.constant.enums.TransportTaskModeEnum;
|
import org.jeecg.common.constant.enums.TransportTaskModeEnum;
|
||||||
|
import org.jeecg.common.constant.enums.TransportTimingAnalysisEnum;
|
||||||
import org.jeecg.common.properties.TransportSimulationProperties;
|
import org.jeecg.common.properties.TransportSimulationProperties;
|
||||||
import org.jeecg.common.util.NcUtil;
|
import org.jeecg.common.util.NcUtil;
|
||||||
|
import org.jeecg.common.util.RedisUtil;
|
||||||
import org.jeecg.modules.base.entity.TransportTask;
|
import org.jeecg.modules.base.entity.TransportTask;
|
||||||
import org.jeecg.modules.base.entity.TransportTaskChild;
|
import org.jeecg.modules.base.entity.TransportTaskChild;
|
||||||
|
import org.jeecg.modules.base.entity.configuration.GardsNuclearfacility;
|
||||||
import org.jeecg.modules.base.entity.configuration.GardsStations;
|
import org.jeecg.modules.base.entity.configuration.GardsStations;
|
||||||
import org.jeecg.modules.base.mapper.TransportTaskChildMapper;
|
import org.jeecg.modules.base.mapper.TransportTaskChildMapper;
|
||||||
import org.jeecg.modules.base.mapper.TransportTaskMapper;
|
import org.jeecg.modules.base.mapper.TransportTaskMapper;
|
||||||
import org.jeecg.service.StationDataService;
|
import org.jeecg.service.StationDataService;
|
||||||
import org.jeecg.service.TransportResultDataService;
|
import org.jeecg.service.TransportResultDataService;
|
||||||
|
import org.jeecg.util.BilinearInterpolatorWithMath;
|
||||||
import org.jeecg.vo.ConcModValVo;
|
import org.jeecg.vo.ConcModValVo;
|
||||||
|
import org.jeecg.vo.ContributionAnalysisVO;
|
||||||
import org.jeecg.vo.QueryDiffusionVO;
|
import org.jeecg.vo.QueryDiffusionVO;
|
||||||
|
import org.jeecg.vo.TaskStationsVO;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import ucar.ma2.Array;
|
import ucar.ma2.Array;
|
||||||
import ucar.ma2.DataType;
|
import ucar.ma2.DataType;
|
||||||
|
|
@ -36,6 +45,7 @@ import java.time.ZoneId;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class TransportResultDataServiceImpl implements TransportResultDataService {
|
public class TransportResultDataServiceImpl implements TransportResultDataService {
|
||||||
|
|
@ -44,6 +54,7 @@ public class TransportResultDataServiceImpl implements TransportResultDataServic
|
||||||
private final TransportSimulationProperties simulationProperties;
|
private final TransportSimulationProperties simulationProperties;
|
||||||
private final TransportTaskChildMapper transportTaskChildMapper;
|
private final TransportTaskChildMapper transportTaskChildMapper;
|
||||||
private final StationDataService stationDataService;
|
private final StationDataService stationDataService;
|
||||||
|
private final RedisUtil redisUtil;
|
||||||
private final static String FORWARD="forward";
|
private final static String FORWARD="forward";
|
||||||
private final static String BACK_FORWARD="backward";
|
private final static String BACK_FORWARD="backward";
|
||||||
|
|
||||||
|
|
@ -236,7 +247,6 @@ public class TransportResultDataServiceImpl implements TransportResultDataServic
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Map<String, Object>> xeResults = stationDataService.getXeResults(stationId, transportTask.getStartTime(), transportTask.getEndTime(), nuclideName);
|
List<Map<String, Object>> xeResults = stationDataService.getXeResults(stationId, transportTask.getStartTime(), transportTask.getEndTime(), nuclideName);
|
||||||
System.out.println(xeResults);
|
|
||||||
//获取nc文件路径
|
//获取nc文件路径
|
||||||
String path = this.getForwardTaskNCPath(transportTask);
|
String path = this.getForwardTaskNCPath(transportTask);
|
||||||
try (NetcdfFile ncFile = NetcdfFile.open(path.toString())) {
|
try (NetcdfFile ncFile = NetcdfFile.open(path.toString())) {
|
||||||
|
|
@ -273,6 +283,7 @@ public class TransportResultDataServiceImpl implements TransportResultDataServic
|
||||||
List<ConcModValVo> modValList = new ArrayList<>();
|
List<ConcModValVo> modValList = new ArrayList<>();
|
||||||
for(int i=pointNum;i<=maxPointNum;i++){
|
for(int i=pointNum;i<=maxPointNum;i++){
|
||||||
for(int k=0;k<timeData.size();k++){
|
for(int k=0;k<timeData.size();k++){
|
||||||
|
//nageclass=1, pointspec=1, time=30, height=6, latitude=710, longitude=1430
|
||||||
int[] origin = {0, i,k,0, latBestIndex,lonBestIndex};
|
int[] origin = {0, i,k,0, latBestIndex,lonBestIndex};
|
||||||
int[] section = {1, 1,1,1,1,1};
|
int[] section = {1, 1,1,1,1,1};
|
||||||
Array levelData = spec001Mr.read(origin,section);
|
Array levelData = spec001Mr.read(origin,section);
|
||||||
|
|
@ -341,6 +352,326 @@ public class TransportResultDataServiceImpl implements TransportResultDataServic
|
||||||
return transportTaskChildren.stream().map(TransportTaskChild::getStationCode).collect(Collectors.toList());
|
return transportTaskChildren.stream().map(TransportTaskChild::getStationCode).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取贡献分析数据
|
||||||
|
* @param taskId
|
||||||
|
* @param stationCode
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public ContributionAnalysisVO getContributionAnalysis(Integer taskId,String stationCode) {
|
||||||
|
TransportTask transportTask = transportTaskMapper.selectById(taskId);
|
||||||
|
if(Objects.isNull(transportTask)){
|
||||||
|
throw new RuntimeException("此任务不存在");
|
||||||
|
}
|
||||||
|
//包含从缓存中拿
|
||||||
|
if(redisUtil.hasKey(CommonConstant.TRANSPORT_CONTRIBUTION_ANALYSIS+transportTask.getId()+":"+stationCode)){
|
||||||
|
return (ContributionAnalysisVO) redisUtil.get(CommonConstant.TRANSPORT_CONTRIBUTION_ANALYSIS+transportTask.getId()+":"+stationCode);
|
||||||
|
}
|
||||||
|
throw new RuntimeException("此站点贡献分析数据不存在或未处理");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理贡献分析数据存入缓存
|
||||||
|
* @param taskId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void handleContributionAnalysis(Integer taskId) {
|
||||||
|
//查询任务数据
|
||||||
|
TransportTask transportTask = transportTaskMapper.selectById(taskId);
|
||||||
|
//查询需要处理贡献分析数据的台站
|
||||||
|
LambdaQueryWrapper<TransportTaskChild> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
queryWrapper.eq(TransportTaskChild::getTaskId,taskId);
|
||||||
|
List<TransportTaskChild> stationInfos = this.transportTaskChildMapper.selectList(queryWrapper);
|
||||||
|
|
||||||
|
//所以核设施数据
|
||||||
|
List<GardsNuclearfacility> facilitys = stationDataService.getAllNuclearfacility();
|
||||||
|
|
||||||
|
NetcdfFile ncFile = null;
|
||||||
|
try {
|
||||||
|
for(TransportTaskChild stationInfo :stationInfos) {
|
||||||
|
//每个台站的结果数据
|
||||||
|
ContributionAnalysisVO contributionAnalysisVO = new ContributionAnalysisVO();
|
||||||
|
//存储台站每天的浓度值数据
|
||||||
|
Map<String,Double> stationEveryDayConcDatas = new LinkedHashMap<>();
|
||||||
|
//存储核设施每天的浓度值数据
|
||||||
|
Map<String,Map<String,Double>> facilityEveryDayConcDatas = new HashMap<>();
|
||||||
|
//饼图数据
|
||||||
|
Map<String,Double> pipeChartData = new HashMap<>();
|
||||||
|
//总浓度值
|
||||||
|
Double totalConc = 0D;
|
||||||
|
//获取nc文件路径
|
||||||
|
String path = this.getBackForwardTaskNCPath(transportTask,stationInfo.getStationCode());
|
||||||
|
ncFile = NetcdfFile.open(path.toString());
|
||||||
|
List<Double> lonData = NcUtil.getNCList(ncFile, "longitude");
|
||||||
|
List<Double> latData = NcUtil.getNCList(ncFile, "latitude");
|
||||||
|
List<Double> timeData = NcUtil.getNCList(ncFile, "time");
|
||||||
|
Variable spec001Mr = ncFile.findVariable("spec001_mr");
|
||||||
|
for(int k=0;k<timeData.size();k++){
|
||||||
|
System.out.println(stationInfo.getStationCode()+"循环:"+k+",共"+timeData.size()+"次");
|
||||||
|
//处理日期数据
|
||||||
|
Instant instant = transportTask.getEndTime().toInstant();
|
||||||
|
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
|
||||||
|
localDateTime = localDateTime.plusSeconds(timeData.get(k).intValue());
|
||||||
|
String dayStr = LocalDateTimeUtil.format(localDateTime, "yyyy-MM-dd");
|
||||||
|
if (!stationEveryDayConcDatas.containsKey(dayStr)) {
|
||||||
|
stationEveryDayConcDatas.put(dayStr,0D);
|
||||||
|
}
|
||||||
|
//获取台站点位取整后±1.5度内的点坐标及数据,使用插值算法求,台站点位的值
|
||||||
|
Double stationConc = this.getTargetSiteConc(lonData,latData,stationInfo.getLon(),stationInfo.getLat(),k,spec001Mr);
|
||||||
|
//累加台站位置当前天的浓度数据
|
||||||
|
stationEveryDayConcDatas.put(dayStr,stationEveryDayConcDatas.get(dayStr)+stationConc);
|
||||||
|
|
||||||
|
for (GardsNuclearfacility facility : facilitys){
|
||||||
|
Double facilityConc = this.getTargetSiteConc(lonData,latData,facility.getLonValue(),facility.getLatValue(),k,spec001Mr);
|
||||||
|
if (facilityConc>0){
|
||||||
|
if (!facilityEveryDayConcDatas.containsKey(dayStr)) {
|
||||||
|
Map<String,Double> facilityConcMap = new HashMap<>();
|
||||||
|
facilityConcMap.put(facility.getFacilityName(),facilityConc);
|
||||||
|
facilityEveryDayConcDatas.put(dayStr,facilityConcMap);
|
||||||
|
}else {
|
||||||
|
Map<String,Double> facilityConcMap = facilityEveryDayConcDatas.get(dayStr);
|
||||||
|
if (!facilityConcMap.containsKey(facility.getFacilityName())) {
|
||||||
|
facilityConcMap.put(facility.getFacilityName(),facilityConc);
|
||||||
|
}else {
|
||||||
|
facilityConcMap.put(facility.getFacilityName(),facilityConcMap.get(facility.getFacilityName())+facilityConc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//计算本模拟时间内总浓度数据
|
||||||
|
totalConc = stationEveryDayConcDatas.values().stream().mapToDouble(Double::doubleValue).sum();
|
||||||
|
//处理饼图数据
|
||||||
|
if(CollUtil.isNotEmpty(facilityEveryDayConcDatas)){
|
||||||
|
for (Map<String,Double> facilityConcMap : facilityEveryDayConcDatas.values()) {
|
||||||
|
Set<Map.Entry<String, Double>> entries = facilityConcMap.entrySet();
|
||||||
|
for (Map.Entry<String, Double> entry : entries) {
|
||||||
|
if (!pipeChartData.containsKey(entry.getKey())) {
|
||||||
|
pipeChartData.put(entry.getKey(),entry.getValue());
|
||||||
|
}else {
|
||||||
|
pipeChartData.put(entry.getKey(),pipeChartData.get(entry.getKey())+entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//处理返回值
|
||||||
|
contributionAnalysisVO.setTotalConc(totalConc);
|
||||||
|
contributionAnalysisVO.setStationEveryDayConcDatas(stationEveryDayConcDatas);
|
||||||
|
contributionAnalysisVO.setFacilityEveryDayConcDatas(facilityEveryDayConcDatas);
|
||||||
|
contributionAnalysisVO.setNuclideNames(new ArrayList<>(pipeChartData.keySet()));
|
||||||
|
contributionAnalysisVO.setPipeChartData(pipeChartData);
|
||||||
|
redisUtil.set(CommonConstant.TRANSPORT_CONTRIBUTION_ANALYSIS+transportTask.getId()+":"+stationInfo.getStationCode(), contributionAnalysisVO);
|
||||||
|
ncFile.close();
|
||||||
|
}
|
||||||
|
}catch (IOException | InvalidRangeException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}finally {
|
||||||
|
try {
|
||||||
|
if(ncFile !=null){
|
||||||
|
ncFile.close();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询任务所属台站数据
|
||||||
|
* @param taskId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<TaskStationsVO> getTaskStations(Integer taskId) {
|
||||||
|
TransportTask transportTask = this.transportTaskMapper.selectById(taskId);
|
||||||
|
if(Objects.isNull(transportTask)){
|
||||||
|
throw new RuntimeException("此任务不存在");
|
||||||
|
}
|
||||||
|
LambdaQueryWrapper<TransportTaskChild> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
queryWrapper.eq(TransportTaskChild::getTaskId,taskId);
|
||||||
|
queryWrapper.select(TransportTaskChild::getId,TransportTaskChild::getStationCode);
|
||||||
|
queryWrapper.orderByAsc(TransportTaskChild::getId);
|
||||||
|
List<TransportTaskChild> transportTaskChildren = transportTaskChildMapper.selectList(queryWrapper);
|
||||||
|
if(CollUtil.isEmpty(transportTaskChildren)){
|
||||||
|
throw new RuntimeException("此任务站点信息不存在,请确认任务配置信息");
|
||||||
|
}
|
||||||
|
//本任务模拟的台站数据
|
||||||
|
List<TaskStationsVO> taskStationsVOList = new ArrayList<>();
|
||||||
|
for (int i = 0; i<transportTaskChildren.size();i++) {
|
||||||
|
TaskStationsVO taskStationsVO = new TaskStationsVO();
|
||||||
|
taskStationsVO.setStationNum(i+1);
|
||||||
|
taskStationsVO.setStationCode(transportTaskChildren.get(i).getStationCode());
|
||||||
|
taskStationsVOList.add(taskStationsVO);
|
||||||
|
}
|
||||||
|
return taskStationsVOList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询任务所属NC层级数据
|
||||||
|
*
|
||||||
|
* @param taskId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Map<Integer, Object> getTaskNCHeightLevel(Integer taskId) {
|
||||||
|
Map<Integer,Object> resultMap = new HashMap<>();
|
||||||
|
|
||||||
|
TransportTask transportTask = this.transportTaskMapper.selectById(taskId);
|
||||||
|
if(Objects.isNull(transportTask)){
|
||||||
|
throw new RuntimeException("此任务不存在");
|
||||||
|
}
|
||||||
|
LambdaQueryWrapper<TransportTaskChild> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
queryWrapper.eq(TransportTaskChild::getTaskId,taskId);
|
||||||
|
queryWrapper.select(TransportTaskChild::getId,TransportTaskChild::getStationCode);
|
||||||
|
queryWrapper.orderByAsc(TransportTaskChild::getId);
|
||||||
|
List<TransportTaskChild> transportTaskChildren = transportTaskChildMapper.selectList(queryWrapper);
|
||||||
|
if(CollUtil.isEmpty(transportTaskChildren)){
|
||||||
|
throw new RuntimeException("此任务站点信息不存在,请确认任务配置信息");
|
||||||
|
}
|
||||||
|
//获取nc文件路径
|
||||||
|
String path = "";
|
||||||
|
if(TransportTaskModeEnum.FORWARD.getKey().equals(transportTask.getTaskMode())){
|
||||||
|
path = this.getForwardTaskNCPath(transportTask);
|
||||||
|
}else if(TransportTaskModeEnum.BACK_FORWARD.getKey().equals(transportTask.getTaskMode())){
|
||||||
|
path = this.getBackForwardTaskNCPath(transportTask,transportTaskChildren.get(0).getStationCode());
|
||||||
|
}
|
||||||
|
if(!FileUtil.exist(path)){
|
||||||
|
throw new RuntimeException("此任务模拟结果不存在,请确认任务运行状态");
|
||||||
|
}
|
||||||
|
//全局属性
|
||||||
|
try (NetcdfFile ncFile = NetcdfFile.open(path.toString())) {
|
||||||
|
Variable heightVar = ncFile.findVariable("height");
|
||||||
|
Array data = heightVar.read();
|
||||||
|
int[] shape = data.getShape();
|
||||||
|
Index index = data.getIndex();
|
||||||
|
for(int i=0;i<shape[0];i++){
|
||||||
|
resultMap.put((i),data.getDouble(index.set(i)));
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return resultMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询反演核设施时序数据接口
|
||||||
|
* @param taskId
|
||||||
|
* @param stationCode
|
||||||
|
* @param facilityName
|
||||||
|
* @param timeNum
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Map<String,Double> getTimingAnalysis(Integer taskId,String stationCode,String facilityName,Integer timeNum) {
|
||||||
|
TransportTask transportTask = transportTaskMapper.selectById(taskId);
|
||||||
|
if(Objects.isNull(transportTask)){
|
||||||
|
throw new RuntimeException("此任务不存在");
|
||||||
|
}
|
||||||
|
//包含从缓存中拿
|
||||||
|
String key = CommonConstant.TRANSPORT_TIMING_ANALYSIS+transportTask.getId()+":"+stationCode+":"+facilityName;
|
||||||
|
if(redisUtil.hasKey(key)){
|
||||||
|
Map<String,Double> concValMap = (LinkedHashMap)redisUtil.get(key);
|
||||||
|
//如果是3小时纬度,直接范围,因为最小是3小时
|
||||||
|
if (TransportTimingAnalysisEnum.THREE_HOURS.getKey().equals(timeNum)) {
|
||||||
|
concValMap.forEach((k,v)->{
|
||||||
|
//纳克转换为毫克需除以1000000
|
||||||
|
BigDecimal concValue = new BigDecimal(v);
|
||||||
|
BigDecimal finalValue = concValue.divide(new BigDecimal(1000000)).setScale(5,BigDecimal.ROUND_HALF_UP);
|
||||||
|
concValMap.put(k,finalValue.doubleValue());
|
||||||
|
});
|
||||||
|
return concValMap;
|
||||||
|
}else{
|
||||||
|
Map<String,Double> resultMap = new LinkedHashMap<>();
|
||||||
|
Instant endTimeInstant = transportTask.getEndTime().toInstant();
|
||||||
|
LocalDateTime endTime = LocalDateTime.ofInstant(endTimeInstant, ZoneId.systemDefault());
|
||||||
|
|
||||||
|
Instant startTimeInstant = transportTask.getStartTime().toInstant();
|
||||||
|
LocalDateTime startTime = LocalDateTime.ofInstant(startTimeInstant, ZoneId.systemDefault());
|
||||||
|
|
||||||
|
boolean flag = true;
|
||||||
|
while(flag){
|
||||||
|
String dayTimeStr = LocalDateTimeUtil.format(startTime, "yyyy-MM-dd HH:mm:ss");
|
||||||
|
//纳克转换为毫克需除以1000000
|
||||||
|
BigDecimal concValue = new BigDecimal(concValMap.get(dayTimeStr));
|
||||||
|
BigDecimal finalValue = concValue.divide(new BigDecimal(1000000)).setScale(5,BigDecimal.ROUND_HALF_UP);
|
||||||
|
resultMap.put(dayTimeStr,finalValue.doubleValue());
|
||||||
|
startTime = startTime.plusHours(timeNum);
|
||||||
|
if(startTime.isEqual(endTime)){
|
||||||
|
flag = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resultMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Map.of();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理反演核设施时序数据存入缓存
|
||||||
|
* @param taskId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void handleTimingAnalysis(Integer taskId) {
|
||||||
|
TransportTask transportTask = this.transportTaskMapper.selectById(taskId);
|
||||||
|
|
||||||
|
//查询需要处理数据的台站
|
||||||
|
LambdaQueryWrapper<TransportTaskChild> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
queryWrapper.eq(TransportTaskChild::getTaskId,taskId);
|
||||||
|
List<TransportTaskChild> stationInfos = this.transportTaskChildMapper.selectList(queryWrapper);
|
||||||
|
|
||||||
|
//所以核设施数据
|
||||||
|
List<GardsNuclearfacility> facilitys = stationDataService.getAllNuclearfacility();
|
||||||
|
|
||||||
|
NetcdfFile ncFile = null;
|
||||||
|
try {
|
||||||
|
for(TransportTaskChild stationInfo :stationInfos) {
|
||||||
|
log.info("处理"+stationInfo.getStationCode()+"台站数据");
|
||||||
|
Map<String,Map<String,Double>> everyFacilityConcDatas = new HashMap<>();
|
||||||
|
//获取nc文件路径
|
||||||
|
String path = this.getBackForwardTaskNCPath(transportTask,stationInfo.getStationCode());
|
||||||
|
ncFile = NetcdfFile.open(path.toString());
|
||||||
|
List<Double> lonData = NcUtil.getNCList(ncFile, "longitude");
|
||||||
|
List<Double> latData = NcUtil.getNCList(ncFile, "latitude");
|
||||||
|
List<Double> timeData = NcUtil.getNCList(ncFile, "time");
|
||||||
|
Variable spec001Mr = ncFile.findVariable("spec001_mr");
|
||||||
|
for (GardsNuclearfacility facility : facilitys){
|
||||||
|
//存储台站每步的浓度值数据
|
||||||
|
Map<String,Double> everyStepConcDatas = new LinkedHashMap<>();
|
||||||
|
for(int k=0;k<timeData.size();k++){
|
||||||
|
//处理日期数据
|
||||||
|
Instant instant = transportTask.getEndTime().toInstant();
|
||||||
|
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
|
||||||
|
localDateTime = localDateTime.plusSeconds(timeData.get(k).intValue());
|
||||||
|
String dayTimeStr = LocalDateTimeUtil.format(localDateTime, "yyyy-MM-dd HH:mm:ss");
|
||||||
|
//获取台站点位取整后±1.5度内的点坐标及数据,使用插值算法求,台站点位的值
|
||||||
|
Double facilityConc = this.getTargetSiteConc(lonData,latData,facility.getLonValue(),facility.getLatValue(),k,spec001Mr);
|
||||||
|
everyStepConcDatas.put(dayTimeStr,facilityConc);
|
||||||
|
}
|
||||||
|
everyFacilityConcDatas.put(facility.getFacilityName(),everyStepConcDatas);
|
||||||
|
}
|
||||||
|
if(CollUtil.isNotEmpty(everyFacilityConcDatas)){
|
||||||
|
everyFacilityConcDatas.forEach((facilityName,facilityConcData)->{
|
||||||
|
String key = CommonConstant.TRANSPORT_TIMING_ANALYSIS+transportTask.getId()+":"+stationInfo.getStationCode()+":"+facilityName;
|
||||||
|
redisUtil.set(key, facilityConcData);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
ncFile.close();
|
||||||
|
}
|
||||||
|
}catch (IOException | InvalidRangeException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}finally {
|
||||||
|
try {
|
||||||
|
if(ncFile !=null){
|
||||||
|
ncFile.close();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 找到集合中里最接近目标值的值
|
* 找到集合中里最接近目标值的值
|
||||||
* @param data
|
* @param data
|
||||||
|
|
@ -406,4 +737,63 @@ public class TransportResultDataServiceImpl implements TransportResultDataServic
|
||||||
path.append("grid_time_"+DateUtil.format(transportTask.getEndTime(),"yyyyMMddHHmmss")+".nc");
|
path.append("grid_time_"+DateUtil.format(transportTask.getEndTime(),"yyyyMMddHHmmss")+".nc");
|
||||||
return path.toString();
|
return path.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在步长为 0.25° 的递增经纬度数组中,查找指定位置的索引
|
||||||
|
* - lons[0] 是起始经度
|
||||||
|
* - 步长严格为 0.25
|
||||||
|
* - target 一定存在
|
||||||
|
*/
|
||||||
|
public int findTargetIndex(List<Double> datas, double target) {
|
||||||
|
// 计算偏移量(单位:0.25°)
|
||||||
|
double offset = (target - datas.get(0)) / 0.25;
|
||||||
|
|
||||||
|
// 四舍五入取整(抵抗浮点误差,如 166.5 - 166.0 = 0.5000000001 → 2.000...)
|
||||||
|
int index = (int) Math.round(offset);
|
||||||
|
|
||||||
|
// 安全检查(可选)
|
||||||
|
if (index < 0 || index >= datas.size() || Math.abs(datas.get(index) - target) > 1e-5) {
|
||||||
|
System.out.println(datas);
|
||||||
|
throw new IllegalArgumentException("经度 " + target + " 不在数组中");
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取指定位置的浓度数据
|
||||||
|
* @param lonData nc文件的经度数据
|
||||||
|
* @param latData nc文件的纬度数据
|
||||||
|
* @param targetLon 目标位置的经度
|
||||||
|
* @param targetLat 目标位置的纬度
|
||||||
|
* @param k 时间索引
|
||||||
|
* @param spec001Mr nc文件浓度数据变量
|
||||||
|
* @return
|
||||||
|
* @throws InvalidRangeException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private Double getTargetSiteConc(List<Double> lonData,List<Double> latData,Double targetLon,Double targetLat,int k,Variable spec001Mr) throws InvalidRangeException, IOException {
|
||||||
|
int lonIndex = this.findTargetIndex(lonData, targetLon.intValue()-0.125);
|
||||||
|
int latIndex = this.findTargetIndex(latData, targetLat.intValue()-0.125);
|
||||||
|
//nageclass=1, pointspec=1, time=30, height=6, latitude=710, longitude=1430
|
||||||
|
int[] origin = {0,0,k,0, (latIndex-6),(lonIndex-6)};
|
||||||
|
int[] section = {1, 1,1,1,12,12};
|
||||||
|
Array levelData = spec001Mr.read(origin,section);
|
||||||
|
double[] pointData = (double[]) levelData.get1DJavaArray(DataType.DOUBLE);
|
||||||
|
Map<BilinearInterpolatorWithMath.Point,Double> siteData = new LinkedHashMap<>();
|
||||||
|
int nlon_patch = 12,patchLatStart = latIndex - 6,patchLonStart = lonIndex - 6;
|
||||||
|
for(int i=0;i<pointData.length;i++){
|
||||||
|
int iy_patch = i / nlon_patch; // 在子区域内的纬度偏移(0~11)
|
||||||
|
int ix_patch = i % nlon_patch; // 在子区域内的经度偏移(0~11)
|
||||||
|
// 转为全局索引(用于查 lonData/latData)
|
||||||
|
int global_iy = patchLatStart + iy_patch;
|
||||||
|
int global_ix = patchLonStart + ix_patch;
|
||||||
|
// 获取真实经纬度
|
||||||
|
double lon = lonData.get(global_ix);
|
||||||
|
double lat = latData.get(global_iy);
|
||||||
|
BilinearInterpolatorWithMath.Point point = new BilinearInterpolatorWithMath.Point(lon,lat);
|
||||||
|
siteData.put(point,pointData[i]);
|
||||||
|
}
|
||||||
|
BilinearInterpolatorWithMath.GridData grid = new BilinearInterpolatorWithMath.GridData(siteData, 0.25, 0.125);
|
||||||
|
return grid.interpolate(targetLon,targetLat);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,13 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.jeecg.common.constant.CommonConstant;
|
||||||
import org.jeecg.common.constant.enums.TransportTaskStatusEnum;
|
import org.jeecg.common.constant.enums.TransportTaskStatusEnum;
|
||||||
import org.jeecg.common.constant.enums.TransportTaskTypeEnum;
|
import org.jeecg.common.constant.enums.TransportTaskTypeEnum;
|
||||||
import org.jeecg.common.properties.SystemStorageProperties;
|
import org.jeecg.common.properties.SystemStorageProperties;
|
||||||
import org.jeecg.common.properties.TransportSimulationProperties;
|
import org.jeecg.common.properties.TransportSimulationProperties;
|
||||||
import org.jeecg.common.system.query.PageRequest;
|
import org.jeecg.common.system.query.PageRequest;
|
||||||
|
import org.jeecg.common.util.RedisUtil;
|
||||||
import org.jeecg.modules.base.entity.TransportTask;
|
import org.jeecg.modules.base.entity.TransportTask;
|
||||||
import org.jeecg.modules.base.entity.TransportTaskChild;
|
import org.jeecg.modules.base.entity.TransportTaskChild;
|
||||||
import org.jeecg.modules.base.entity.TransportTaskLog;
|
import org.jeecg.modules.base.entity.TransportTaskLog;
|
||||||
|
|
@ -40,6 +42,7 @@ public class TransportTaskServiceImpl extends ServiceImpl<TransportTaskMapper,Tr
|
||||||
private final WeatherDataMapper weatherDataMapper;
|
private final WeatherDataMapper weatherDataMapper;
|
||||||
private final TransportSimulationProperties simulationProperties;
|
private final TransportSimulationProperties simulationProperties;
|
||||||
private final SystemStorageProperties systemStorageProperties;
|
private final SystemStorageProperties systemStorageProperties;
|
||||||
|
private final RedisUtil redisUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分页查询任务列表
|
* 分页查询任务列表
|
||||||
|
|
@ -169,6 +172,9 @@ public class TransportTaskServiceImpl extends ServiceImpl<TransportTaskMapper,Tr
|
||||||
queryWrapper.eq(TransportTaskChild::getTaskId,id);
|
queryWrapper.eq(TransportTaskChild::getTaskId,id);
|
||||||
transportTaskChildMapper.delete(queryWrapper);
|
transportTaskChildMapper.delete(queryWrapper);
|
||||||
this.baseMapper.deleteById(id);
|
this.baseMapper.deleteById(id);
|
||||||
|
//删除存储的贡献分析数据和时序分析数据
|
||||||
|
redisUtil.del(CommonConstant.TRANSPORT_CONTRIBUTION_ANALYSIS+id);
|
||||||
|
redisUtil.del(CommonConstant.TRANSPORT_TIMING_ANALYSIS+id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -231,10 +237,11 @@ public class TransportTaskServiceImpl extends ServiceImpl<TransportTaskMapper,Tr
|
||||||
*/
|
*/
|
||||||
@Transactional(rollbackFor = RuntimeException.class)
|
@Transactional(rollbackFor = RuntimeException.class)
|
||||||
@Override
|
@Override
|
||||||
public void updateTaskTimeConsuming(Integer taskId, Double minute) {
|
public void updateTaskStatusToCompleted(Integer taskId, Double minute) {
|
||||||
TransportTask transportTask = this.baseMapper.selectById(taskId);
|
TransportTask transportTask = this.baseMapper.selectById(taskId);
|
||||||
|
transportTask.setTaskStatus(TransportTaskStatusEnum.FAILURE.getValue());
|
||||||
transportTask.setTimeConsuming(minute);
|
transportTask.setTimeConsuming(minute);
|
||||||
|
this.baseMapper.updateById(transportTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
package org.jeecg.task;
|
package org.jeecg.task;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
|
||||||
import cn.hutool.core.date.DateUtil;
|
import cn.hutool.core.date.DateUtil;
|
||||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
|
||||||
import cn.hutool.core.io.FileUtil;
|
import cn.hutool.core.io.FileUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
|
@ -74,14 +72,15 @@ public class TransportTaskExec extends Thread{
|
||||||
}catch (Exception e){
|
}catch (Exception e){
|
||||||
String taskErrorLog = "任务执行失败,原因:"+e.getMessage();
|
String taskErrorLog = "任务执行失败,原因:"+e.getMessage();
|
||||||
ProgressQueue.getInstance().offer(new ProgressEvent(this.transportTask.getId(),taskErrorLog));
|
ProgressQueue.getInstance().offer(new ProgressEvent(this.transportTask.getId(),taskErrorLog));
|
||||||
e.printStackTrace();
|
|
||||||
throw e;
|
throw e;
|
||||||
}finally {
|
}finally {
|
||||||
//添加任务耗时
|
//添加任务耗时
|
||||||
stopWatch.stop();
|
stopWatch.stop();
|
||||||
long seconds = stopWatch.getTime(TimeUnit.SECONDS);
|
long seconds = stopWatch.getTime(TimeUnit.SECONDS);
|
||||||
Double min = seconds/60D;
|
Double min = seconds/60D;
|
||||||
this.transportTaskService.updateTaskTimeConsuming(this.transportTask.getId(),min);
|
this.transportTaskService.updateTaskStatusToCompleted(this.transportTask.getId(),min);
|
||||||
|
String taskCompletedLog = "任务执行完成,耗时:"+min+"分钟";
|
||||||
|
ProgressQueue.getInstance().offer(new ProgressEvent(this.transportTask.getId(),taskCompletedLog));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,175 @@
|
||||||
|
package org.jeecg.util;
|
||||||
|
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class BilinearInterpolatorWithMath {
|
||||||
|
|
||||||
|
public static class Point {
|
||||||
|
public final double lon;
|
||||||
|
public final double lat;
|
||||||
|
|
||||||
|
public Point(double lon, double lat) {
|
||||||
|
this.lon = lon;
|
||||||
|
this.lat = lat;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
Point p = (Point) o;
|
||||||
|
// 使用 Math.abs 做浮点容差比较
|
||||||
|
double tol = 1e-9;
|
||||||
|
return Math.abs(p.lon - lon) < tol && Math.abs(p.lat - lat) < tol;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
// 使用 Math.floor + longBitsToDouble 生成稳定哈希(可选优化)
|
||||||
|
return java.util.Objects.hash(
|
||||||
|
Double.doubleToLongBits(Math.floor(lon * 1e6 + 0.5) / 1e6),
|
||||||
|
Double.doubleToLongBits(Math.floor(lat * 1e6 + 0.5) / 1e6)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class GridData {
|
||||||
|
private final Map<Point, Double> data;
|
||||||
|
private final double delta;
|
||||||
|
private final double offset;
|
||||||
|
|
||||||
|
public GridData(Map<Point, Double> data, double delta, double offset) {
|
||||||
|
this.data = data;
|
||||||
|
this.delta = delta;
|
||||||
|
this.offset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算双线性插值
|
||||||
|
*/
|
||||||
|
public Double interpolate(double lon, double lat) {
|
||||||
|
//精确匹配格点(避免边界问题)
|
||||||
|
Point target = new Point(lon, lat);
|
||||||
|
Double exactValue = data.get(target);
|
||||||
|
if (exactValue != null && !Double.isNaN(exactValue)) {
|
||||||
|
return exactValue; // 直接返回,不插值
|
||||||
|
}
|
||||||
|
|
||||||
|
//1. 定位网格单元:使用 Math.floor 确保负数正确处理
|
||||||
|
// 关键:避免 (int) 强转的 truncation 问题
|
||||||
|
int i = (int) Math.floor((lon - offset) / delta);
|
||||||
|
int j = (int) Math.floor((lat - offset) / delta);
|
||||||
|
|
||||||
|
// 计算四个角点坐标
|
||||||
|
double lon0 = i * delta + offset;
|
||||||
|
double lon1 = lon0 + delta;
|
||||||
|
double lat0 = j * delta + offset;
|
||||||
|
double lat1 = lat0 + delta;
|
||||||
|
|
||||||
|
//2. 防御性检查:目标点是否真的在 [lon0, lon1) × [lat0, lat1) 内?
|
||||||
|
// 使用 Math.abs + 容差避免浮点误差导致误判
|
||||||
|
final double TOL = 1e-10;
|
||||||
|
if (lon < lon0 - TOL || lon > lon1 + TOL ||
|
||||||
|
lat < lat0 - TOL || lat > lat1 + TOL) {
|
||||||
|
System.err.printf("Warning: (%.6f, %.6f) is outside computed cell [%.3f~%.3f]×[%.3f~%.3f]%n",
|
||||||
|
lon, lat, lon0, lon1, lat0, lat1);
|
||||||
|
// 可选:自动修正索引
|
||||||
|
i = (int) Math.floor((lon - offset) / delta); // 再算一次
|
||||||
|
j = (int) Math.floor((lat - offset) / delta);
|
||||||
|
lon0 = i * delta + offset;
|
||||||
|
lon1 = lon0 + delta;
|
||||||
|
lat0 = j * delta + offset;
|
||||||
|
lat1 = lat0 + delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
//3. 构造四邻点并查值
|
||||||
|
Point[] points = {
|
||||||
|
new Point(lon0, lat0), // SW
|
||||||
|
new Point(lon1, lat0), // SE
|
||||||
|
new Point(lon0, lat1), // NW
|
||||||
|
new Point(lon1, lat1) // NE
|
||||||
|
};
|
||||||
|
Double[] values = new Double[4];
|
||||||
|
boolean hasMissing = false;
|
||||||
|
for (int k = 0; k < 4; k++) {
|
||||||
|
values[k] = data.get(points[k]);
|
||||||
|
if (values[k] == null || Double.isNaN(values[k])) {
|
||||||
|
hasMissing = true;
|
||||||
|
System.err.println("Missing/NaN at: " + points[k].lon + ", " + points[k].lat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasMissing) return null;
|
||||||
|
|
||||||
|
//4. 计算权重:使用 Math.max/Math.min 裁剪到 [0,1](防浮点误差溢出)
|
||||||
|
double wx = (lon - lon0) / delta;
|
||||||
|
double wy = (lat - lat0) / delta;
|
||||||
|
|
||||||
|
// 关键增强:防止 wx/wy 因浮点误差略超 [0,1]
|
||||||
|
wx = Math.max(0.0, Math.min(1.0, wx)); // 等价于 clamp(wx, 0, 1)
|
||||||
|
wy = Math.max(0.0, Math.min(1.0, wy));
|
||||||
|
|
||||||
|
//5. 双线性插值公式(核心,无需 Math 复杂函数)
|
||||||
|
double v00 = values[0], v10 = values[1], v01 = values[2], v11 = values[3];
|
||||||
|
double val = (1 - wx) * (1 - wy) * v00 +
|
||||||
|
wx * (1 - wy) * v10 +
|
||||||
|
(1 - wx) * wy * v01 +
|
||||||
|
wx * wy * v11;
|
||||||
|
|
||||||
|
//6. 最终检查:结果是否合理?
|
||||||
|
// 使用 Math.abs + isFinite 防 NaN/Inf
|
||||||
|
if (!Double.isFinite(val)) {
|
||||||
|
System.err.println("Interpolation produced invalid value: " + val);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量插值(高效处理多个点)
|
||||||
|
* 展示 Math.copySign / Math.IEEEremainder 等高级用法(可选场景)
|
||||||
|
*/
|
||||||
|
public double[] interpolateBatch(double[] lons, double[] lats) {
|
||||||
|
if (lons.length != lats.length)
|
||||||
|
throw new IllegalArgumentException("Length mismatch");
|
||||||
|
|
||||||
|
double[] results = new double[lons.length];
|
||||||
|
|
||||||
|
for (int idx = 0; idx < lons.length; idx++) {
|
||||||
|
Double val = interpolate(lons[idx], lats[idx]);
|
||||||
|
results[idx] = (val != null) ? val : Double.NaN;
|
||||||
|
|
||||||
|
// 可选:对经度做环绕处理(全球数据常见)
|
||||||
|
// 例如:将 -181° 映射到 179°
|
||||||
|
double adjustedLon = lons[idx];
|
||||||
|
if (Math.abs(adjustedLon) > 180.0) {
|
||||||
|
// 使用 IEEE 754 标准取余(比 % 更可靠)
|
||||||
|
adjustedLon = Math.IEEEremainder(adjustedLon + 180.0, 360.0) - 180.0;
|
||||||
|
// 保持符号一致性(-0.0 → 0.0)
|
||||||
|
adjustedLon = Math.copySign(adjustedLon, adjustedLon);
|
||||||
|
}
|
||||||
|
// 然后用 adjustedLon 重新插值...
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== 演示:Math 库增强版用法 =====
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Map<Point, Double> data = new LinkedHashMap<>();
|
||||||
|
data.put(new Point(7.875, 47.875), 195.53140258789062);
|
||||||
|
data.put(new Point(8.125, 47.875), 9.2166166305542);
|
||||||
|
data.put(new Point(7.875, 48.125), 40.02995681762695);
|
||||||
|
data.put(new Point(8.125, 48.125), 11.597820281982422);
|
||||||
|
|
||||||
|
GridData grid = new GridData(data, 0.25, 0.125);
|
||||||
|
|
||||||
|
// 测试正常点
|
||||||
|
System.out.printf("Normal: %.8f%n",
|
||||||
|
grid.interpolate(7.9, 47.9));
|
||||||
|
|
||||||
|
// 测试边界点(wx/wy 接近 1)
|
||||||
|
// System.out.printf("Edge case: %.8f%n",
|
||||||
|
// grid.interpolate(-53.625, -36.375)); // 应等于 NE 点值
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
package org.jeecg.vo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 贡献分析数据VO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ContributionAnalysisVO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* X轴台站每天的浓度值数据
|
||||||
|
*/
|
||||||
|
private Map<String,Double> stationEveryDayConcDatas;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 核设施每天的浓度值数据
|
||||||
|
*/
|
||||||
|
private Map<String,Map<String,Double>> facilityEveryDayConcDatas;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 涉及的核设施名称
|
||||||
|
*/
|
||||||
|
private List<String> nuclideNames;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 饼图数据
|
||||||
|
*/
|
||||||
|
private Map<String,Double> pipeChartData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 总浓度值
|
||||||
|
*/
|
||||||
|
private Double totalConc;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
package org.jeecg.vo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class TaskStationsVO {
|
||||||
|
|
||||||
|
private Integer stationId;
|
||||||
|
|
||||||
|
private Integer stationNum;
|
||||||
|
|
||||||
|
private String stationCode;
|
||||||
|
|
||||||
|
private Double lon;
|
||||||
|
|
||||||
|
private Double lat;
|
||||||
|
}
|
||||||
|
|
@ -12,6 +12,7 @@ import org.jeecg.common.validgroup.InsertGroup;
|
||||||
import org.jeecg.common.validgroup.UpdateGroup;
|
import org.jeecg.common.validgroup.UpdateGroup;
|
||||||
import org.jeecg.modules.base.entity.WeatherTask;
|
import org.jeecg.modules.base.entity.WeatherTask;
|
||||||
import org.jeecg.service.WeatherTaskService;
|
import org.jeecg.service.WeatherTaskService;
|
||||||
|
import org.jeecg.vo.ForecastFileVO;
|
||||||
import org.springframework.format.annotation.DateTimeFormat;
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
@ -44,7 +45,8 @@ public class WeatherTaskController {
|
||||||
@AutoLog(value = "新增天气预测任务")
|
@AutoLog(value = "新增天气预测任务")
|
||||||
@Operation(summary = "新增天气预测任务")
|
@Operation(summary = "新增天气预测任务")
|
||||||
@PostMapping("create")
|
@PostMapping("create")
|
||||||
public Result<?> create(@RequestBody @Validated(value = InsertGroup.class) WeatherTask weatherTask){
|
public Result<?> create(@Validated(value = InsertGroup.class) WeatherTask weatherTask){
|
||||||
|
System.out.println(weatherTask);
|
||||||
weatherTaskService.cteate(weatherTask);
|
weatherTaskService.cteate(weatherTask);
|
||||||
return Result.OK();
|
return Result.OK();
|
||||||
}
|
}
|
||||||
|
|
@ -59,7 +61,7 @@ public class WeatherTaskController {
|
||||||
@AutoLog(value = "修改天气预测任务")
|
@AutoLog(value = "修改天气预测任务")
|
||||||
@Operation(summary = "修改天气预测任务")
|
@Operation(summary = "修改天气预测任务")
|
||||||
@PutMapping("update")
|
@PutMapping("update")
|
||||||
public Result<?> update(@RequestBody @Validated(value = UpdateGroup.class) WeatherTask weatherTask){
|
public Result<?> update(@Validated(value = UpdateGroup.class) WeatherTask weatherTask){
|
||||||
weatherTaskService.update(weatherTask);
|
weatherTaskService.update(weatherTask);
|
||||||
return Result.OK();
|
return Result.OK();
|
||||||
}
|
}
|
||||||
|
|
@ -72,6 +74,14 @@ public class WeatherTaskController {
|
||||||
return Result.OK();
|
return Result.OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AutoLog(value = "启动任务")
|
||||||
|
@Operation(summary = "启动任务")
|
||||||
|
@PutMapping("runTask")
|
||||||
|
public Result<?> runTask(@NotBlank(message = "任务ID不能为空") String taskId){
|
||||||
|
weatherTaskService.runTask(taskId);
|
||||||
|
return Result.OK();
|
||||||
|
}
|
||||||
|
|
||||||
@AutoLog(value = "获取天气预测任务过程日志")
|
@AutoLog(value = "获取天气预测任务过程日志")
|
||||||
@Operation(summary = "获取天气预测任务过程日志")
|
@Operation(summary = "获取天气预测任务过程日志")
|
||||||
@GetMapping("getTaskLog")
|
@GetMapping("getTaskLog")
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,11 @@ package org.jeecg.service;
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
import org.jeecg.common.system.query.PageRequest;
|
import org.jeecg.common.system.query.PageRequest;
|
||||||
import org.jeecg.modules.base.entity.StasDataSource;
|
|
||||||
import org.jeecg.modules.base.entity.WeatherData;
|
import org.jeecg.modules.base.entity.WeatherData;
|
||||||
import org.jeecg.vo.*;
|
import org.jeecg.vo.*;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public interface WeatherDataService extends IService<WeatherData> {
|
public interface WeatherDataService extends IService<WeatherData> {
|
||||||
|
|
||||||
|
|
@ -54,4 +50,10 @@ public interface WeatherDataService extends IService<WeatherData> {
|
||||||
* 处理静态气象数据入库接口,比上传快
|
* 处理静态气象数据入库接口,比上传快
|
||||||
*/
|
*/
|
||||||
void handleStaticDataToDB(String path,Integer dataSource);
|
void handleStaticDataToDB(String path,Integer dataSource);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存模型预测好的文件信息到WeatherData
|
||||||
|
* @param weatherData
|
||||||
|
*/
|
||||||
|
void saveFileInfo(WeatherData weatherData);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ public interface WeatherTaskService extends IService<WeatherTask> {
|
||||||
* 运行任务
|
* 运行任务
|
||||||
* @param id
|
* @param id
|
||||||
*/
|
*/
|
||||||
void runTask(Integer id);
|
void runTask(String id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取任务运行日志
|
* 获取任务运行日志
|
||||||
|
|
@ -61,4 +61,31 @@ public interface WeatherTaskService extends IService<WeatherTask> {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
List<WeatherTaskLog> getTaskLog(String taskId);
|
List<WeatherTaskLog> getTaskLog(String taskId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存任务过程日志
|
||||||
|
* @param log
|
||||||
|
*/
|
||||||
|
void saveLog(WeatherTaskLog log);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改任务运行状态
|
||||||
|
* @param taskId
|
||||||
|
* @param taskStatus
|
||||||
|
*/
|
||||||
|
void updateTaskStatus(String taskId,Integer taskStatus);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据任务id删除任务日志
|
||||||
|
* @param taskId
|
||||||
|
*/
|
||||||
|
void deleteTaskLog(String taskId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改任务状态为结束
|
||||||
|
* @param taskId
|
||||||
|
* @param timeConsuming
|
||||||
|
*/
|
||||||
|
void updateTaskStatusToCompleted(String taskId, Double timeConsuming);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package org.jeecg.service.impl;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.io.FileUtil;
|
import cn.hutool.core.io.FileUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||||
|
|
@ -435,8 +436,7 @@ public class WeatherDataServiceImpl extends ServiceImpl<WeatherDataMapper, Weath
|
||||||
BigDecimal fileSize = bg.divide(divideVal).divide(divideVal).setScale(2, RoundingMode.HALF_UP);
|
BigDecimal fileSize = bg.divide(divideVal).divide(divideVal).setScale(2, RoundingMode.HALF_UP);
|
||||||
queryResult.setFileSize(fileSize.doubleValue());
|
queryResult.setFileSize(fileSize.doubleValue());
|
||||||
//把文件移入新路径
|
//把文件移入新路径
|
||||||
int year = utcDateTime.getYear();
|
String newFileDirPath = dataFile.getParentFile().getParent()+File.separator+File.separator;
|
||||||
String newFileDirPath = dataFile.getParentFile().getParent()+File.separator+year+File.separator;
|
|
||||||
String newFilePath = newFileDirPath+File.separator+dataFile.getName();
|
String newFilePath = newFileDirPath+File.separator+dataFile.getName();
|
||||||
FileUtil.mkdir(newFileDirPath);
|
FileUtil.mkdir(newFileDirPath);
|
||||||
File parentDir = dataFile.getParentFile();
|
File parentDir = dataFile.getParentFile();
|
||||||
|
|
@ -557,6 +557,17 @@ public class WeatherDataServiceImpl extends ServiceImpl<WeatherDataMapper, Weath
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存模型预测好的文件信息到WeatherData
|
||||||
|
*
|
||||||
|
* @param weatherData
|
||||||
|
*/
|
||||||
|
@Transactional(rollbackFor = RuntimeException.class)
|
||||||
|
@Override
|
||||||
|
public void saveFileInfo(WeatherData weatherData) {
|
||||||
|
this.save(weatherData);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文件合并
|
* 文件合并
|
||||||
* @param fileVo
|
* @param fileVo
|
||||||
|
|
|
||||||
|
|
@ -2,20 +2,29 @@ package org.jeecg.service.impl;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.logging.log4j.util.Strings;
|
||||||
|
import org.jeecg.common.constant.enums.WeatherFileSuffixEnum;
|
||||||
|
import org.jeecg.common.constant.enums.WeatherForecastDatasourceEnum;
|
||||||
import org.jeecg.common.constant.enums.WeatherTaskStatusEnum;
|
import org.jeecg.common.constant.enums.WeatherTaskStatusEnum;
|
||||||
|
import org.jeecg.common.properties.SystemStorageProperties;
|
||||||
import org.jeecg.common.system.query.PageRequest;
|
import org.jeecg.common.system.query.PageRequest;
|
||||||
import org.jeecg.modules.base.entity.WeatherTask;
|
import org.jeecg.modules.base.entity.WeatherTask;
|
||||||
import org.jeecg.modules.base.entity.WeatherTaskLog;
|
import org.jeecg.modules.base.entity.WeatherTaskLog;
|
||||||
|
import org.jeecg.modules.base.mapper.WeatherDataMapper;
|
||||||
import org.jeecg.modules.base.mapper.WeatherTaskLogMapper;
|
import org.jeecg.modules.base.mapper.WeatherTaskLogMapper;
|
||||||
import org.jeecg.modules.base.mapper.WeatherTaskMapper;
|
import org.jeecg.modules.base.mapper.WeatherTaskMapper;
|
||||||
import org.jeecg.service.WeatherTaskService;
|
import org.jeecg.service.WeatherTaskService;
|
||||||
|
import org.jeecg.task.WeatherTaskExec;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -29,6 +38,8 @@ import java.util.Objects;
|
||||||
public class WeatherTaskServiceImpl extends ServiceImpl<WeatherTaskMapper, WeatherTask> implements WeatherTaskService {
|
public class WeatherTaskServiceImpl extends ServiceImpl<WeatherTaskMapper, WeatherTask> implements WeatherTaskService {
|
||||||
|
|
||||||
private final WeatherTaskLogMapper weatherTaskLogMapper;
|
private final WeatherTaskLogMapper weatherTaskLogMapper;
|
||||||
|
private final SystemStorageProperties systemStorageProperties;
|
||||||
|
private final WeatherDataMapper weatherDataMapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分页查询任务列表
|
* 分页查询任务列表
|
||||||
|
|
@ -73,11 +84,40 @@ public class WeatherTaskServiceImpl extends ServiceImpl<WeatherTaskMapper, Weath
|
||||||
LambdaQueryWrapper<WeatherTask> checkDateWrapper = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<WeatherTask> checkDateWrapper = new LambdaQueryWrapper<>();
|
||||||
checkDateWrapper.eq(WeatherTask::getStartDate,weatherTask.getStartDate());
|
checkDateWrapper.eq(WeatherTask::getStartDate,weatherTask.getStartDate());
|
||||||
checkDateWrapper.eq(WeatherTask::getStartTime,weatherTask.getStartTime());
|
checkDateWrapper.eq(WeatherTask::getStartTime,weatherTask.getStartTime());
|
||||||
|
checkDateWrapper.eq(WeatherTask::getPredictionModel,weatherTask.getPredictionModel());
|
||||||
WeatherTask checkDateResult = this.getOne(checkDateWrapper);
|
WeatherTask checkDateResult = this.getOne(checkDateWrapper);
|
||||||
if(Objects.nonNull(checkDateResult)){
|
if(Objects.nonNull(checkDateResult)){
|
||||||
throw new RuntimeException("此当前预测时间为参数的任务已存在");
|
throw new RuntimeException("此当前预测时间为参数的任务已存在");
|
||||||
}
|
}
|
||||||
|
//手动获取id
|
||||||
|
String id = IdWorker.getIdStr();
|
||||||
|
weatherTask.setId(id);
|
||||||
weatherTask.setTaskStatus(WeatherTaskStatusEnum.NOT_STARTED.getKey());
|
weatherTask.setTaskStatus(WeatherTaskStatusEnum.NOT_STARTED.getKey());
|
||||||
|
if (WeatherForecastDatasourceEnum.LOCATION_FILE.getKey().equals(weatherTask.getDataSources())){
|
||||||
|
try {
|
||||||
|
MultipartFile file = weatherTask.getFile();
|
||||||
|
//构造文件名称
|
||||||
|
StringBuilder fileName = new StringBuilder();
|
||||||
|
fileName.append(file.getOriginalFilename().substring(0,file.getOriginalFilename().lastIndexOf(".")));
|
||||||
|
fileName.append("_"+id+".");
|
||||||
|
fileName.append(WeatherFileSuffixEnum.GRIB.getValue());
|
||||||
|
|
||||||
|
//文件保存路径
|
||||||
|
StringBuilder filePath = new StringBuilder();
|
||||||
|
filePath.append(this.systemStorageProperties.getPanguModelExecPath());
|
||||||
|
filePath.append(File.separator);
|
||||||
|
filePath.append(fileName);
|
||||||
|
|
||||||
|
File storageFile = new File(filePath.toString());
|
||||||
|
if (storageFile.exists()){
|
||||||
|
storageFile.delete();
|
||||||
|
}
|
||||||
|
file.transferTo(storageFile);
|
||||||
|
weatherTask.setInputFile(fileName.toString());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
this.save(weatherTask);
|
this.save(weatherTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,8 +155,9 @@ public class WeatherTaskServiceImpl extends ServiceImpl<WeatherTaskMapper, Weath
|
||||||
LambdaQueryWrapper<WeatherTask> checkDateWrapper = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<WeatherTask> checkDateWrapper = new LambdaQueryWrapper<>();
|
||||||
checkDateWrapper.eq(WeatherTask::getStartDate,weatherTask.getStartDate());
|
checkDateWrapper.eq(WeatherTask::getStartDate,weatherTask.getStartDate());
|
||||||
checkDateWrapper.eq(WeatherTask::getStartTime,weatherTask.getStartTime());
|
checkDateWrapper.eq(WeatherTask::getStartTime,weatherTask.getStartTime());
|
||||||
|
checkDateWrapper.eq(WeatherTask::getPredictionModel,weatherTask.getPredictionModel());
|
||||||
WeatherTask checkDateResult = this.getOne(checkDateWrapper);
|
WeatherTask checkDateResult = this.getOne(checkDateWrapper);
|
||||||
if(Objects.nonNull(checkDateResult) && !weatherTask.getId().equals(checkNameResult.getId())){
|
if(Objects.nonNull(checkDateResult) && Objects.nonNull(checkNameResult) && !weatherTask.getId().equals(checkNameResult.getId())){
|
||||||
throw new RuntimeException("此当前预测时间为参数的任务已存在");
|
throw new RuntimeException("此当前预测时间为参数的任务已存在");
|
||||||
}
|
}
|
||||||
queryResult.setTaskName(weatherTask.getTaskName());
|
queryResult.setTaskName(weatherTask.getTaskName());
|
||||||
|
|
@ -125,7 +166,35 @@ public class WeatherTaskServiceImpl extends ServiceImpl<WeatherTaskMapper, Weath
|
||||||
queryResult.setStartTime(weatherTask.getStartTime());
|
queryResult.setStartTime(weatherTask.getStartTime());
|
||||||
queryResult.setLeadTime(weatherTask.getLeadTime());
|
queryResult.setLeadTime(weatherTask.getLeadTime());
|
||||||
queryResult.setDataSources(weatherTask.getDataSources());
|
queryResult.setDataSources(weatherTask.getDataSources());
|
||||||
queryResult.setInputFile(weatherTask.getInputFile());
|
if (WeatherForecastDatasourceEnum.LOCATION_FILE.getKey().equals(weatherTask.getDataSources())){
|
||||||
|
if (Objects.nonNull(weatherTask.getFile())){
|
||||||
|
try {
|
||||||
|
MultipartFile file = weatherTask.getFile();
|
||||||
|
//构造文件名称
|
||||||
|
StringBuilder fileName = new StringBuilder();
|
||||||
|
fileName.append(file.getOriginalFilename().substring(0,file.getOriginalFilename().lastIndexOf(".")));
|
||||||
|
fileName.append("_"+queryResult.getId()+".");
|
||||||
|
fileName.append(WeatherFileSuffixEnum.GRIB.getValue());
|
||||||
|
|
||||||
|
//文件保存路径
|
||||||
|
StringBuilder filePath = new StringBuilder();
|
||||||
|
filePath.append(this.systemStorageProperties.getPanguModelExecPath());
|
||||||
|
filePath.append(File.separator);
|
||||||
|
filePath.append(fileName);
|
||||||
|
|
||||||
|
File storageFile = new File(filePath.toString());
|
||||||
|
if (storageFile.exists()){
|
||||||
|
storageFile.delete();
|
||||||
|
}
|
||||||
|
file.transferTo(storageFile);
|
||||||
|
queryResult.setInputFile(fileName.toString());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
queryResult.setInputFile(Strings.EMPTY);
|
||||||
|
}
|
||||||
this.updateById(queryResult);
|
this.updateById(queryResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -145,8 +214,15 @@ public class WeatherTaskServiceImpl extends ServiceImpl<WeatherTaskMapper, Weath
|
||||||
* @param id
|
* @param id
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void runTask(Integer id) {
|
public void runTask(String id) {
|
||||||
|
WeatherTask task = this.baseMapper.selectById(id);
|
||||||
|
if(Objects.isNull(task)){
|
||||||
|
throw new RuntimeException("此任务不存在");
|
||||||
|
}
|
||||||
|
WeatherTaskExec exec = new WeatherTaskExec();
|
||||||
|
exec.init(task,this,systemStorageProperties,weatherDataMapper);
|
||||||
|
exec.setName("天气预测任务线程");
|
||||||
|
exec.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -163,4 +239,57 @@ public class WeatherTaskServiceImpl extends ServiceImpl<WeatherTaskMapper, Weath
|
||||||
queryWrapper.orderByAsc(WeatherTaskLog::getCreateTime);
|
queryWrapper.orderByAsc(WeatherTaskLog::getCreateTime);
|
||||||
return this.weatherTaskLogMapper.selectList(queryWrapper);
|
return this.weatherTaskLogMapper.selectList(queryWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存任务过程日志
|
||||||
|
*
|
||||||
|
* @param log
|
||||||
|
*/
|
||||||
|
@Transactional(rollbackFor = RuntimeException.class)
|
||||||
|
@Override
|
||||||
|
public void saveLog(WeatherTaskLog log) {
|
||||||
|
this.weatherTaskLogMapper.insert(log);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改任务运行状态
|
||||||
|
*
|
||||||
|
* @param taskId
|
||||||
|
* @param taskStatus
|
||||||
|
*/
|
||||||
|
@Transactional(rollbackFor = RuntimeException.class)
|
||||||
|
@Override
|
||||||
|
public void updateTaskStatus(String taskId, Integer taskStatus) {
|
||||||
|
WeatherTask weatherTask = this.baseMapper.selectById(taskId);
|
||||||
|
weatherTask.setTaskStatus(taskStatus);
|
||||||
|
this.updateById(weatherTask);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据任务id删除任务日志
|
||||||
|
*
|
||||||
|
* @param taskId
|
||||||
|
*/
|
||||||
|
@Transactional(rollbackFor = RuntimeException.class)
|
||||||
|
@Override
|
||||||
|
public void deleteTaskLog(String taskId) {
|
||||||
|
LambdaQueryWrapper<WeatherTaskLog> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
queryWrapper.eq(WeatherTaskLog::getTaskId,taskId);
|
||||||
|
this.weatherTaskLogMapper.delete(queryWrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改任务状态为结束
|
||||||
|
*
|
||||||
|
* @param taskId
|
||||||
|
* @param timeConsuming
|
||||||
|
*/
|
||||||
|
@Transactional(rollbackFor = RuntimeException.class)
|
||||||
|
@Override
|
||||||
|
public void updateTaskStatusToCompleted(String taskId, Double timeConsuming) {
|
||||||
|
WeatherTask weatherTask = this.baseMapper.selectById(taskId);
|
||||||
|
weatherTask.setTaskStatus(WeatherTaskStatusEnum.COMPLETED.getKey());
|
||||||
|
weatherTask.setTimeConsuming(timeConsuming);
|
||||||
|
this.updateById(weatherTask);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
package org.jeecg.task;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日志事件
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class ProgressEvent implements Serializable{
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private String taskId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过程日志
|
||||||
|
*/
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
public ProgressEvent(String taskId, String content) {
|
||||||
|
this.taskId = taskId;
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
package org.jeecg.task;
|
||||||
|
|
||||||
|
import jakarta.annotation.PostConstruct;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.jeecg.modules.base.entity.WeatherTaskLog;
|
||||||
|
import org.jeecg.service.WeatherTaskService;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日志监测线程
|
||||||
|
* @author 86187
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Slf4j
|
||||||
|
public class ProgressMonitor{
|
||||||
|
|
||||||
|
private final WeatherTaskService weatherTaskService;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void start() {
|
||||||
|
ProgressMonitorThread monitor = new ProgressMonitorThread();
|
||||||
|
monitor.setName("气象预测日志监测线程");
|
||||||
|
monitor.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ProgressMonitorThread extends Thread{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
for(;;) {
|
||||||
|
try {
|
||||||
|
ProgressEvent event = ProgressQueue.getInstance().take();
|
||||||
|
if(Objects.nonNull(event)) {
|
||||||
|
WeatherTaskLog log = new WeatherTaskLog();
|
||||||
|
log.setTaskId(event.getTaskId());
|
||||||
|
log.setLogContent(event.getContent());
|
||||||
|
weatherTaskService.saveLog(log);
|
||||||
|
}
|
||||||
|
}catch (Exception e){
|
||||||
|
log.error("气象预测日志存储线程异常,日志存储失败,原因为:{}",e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
package org.jeecg.task;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日志队列
|
||||||
|
*/
|
||||||
|
public class ProgressQueue {
|
||||||
|
|
||||||
|
private final LinkedList<ProgressEvent> queue = new LinkedList<>();
|
||||||
|
|
||||||
|
private static ProgressQueue progressQueue = new ProgressQueue();
|
||||||
|
|
||||||
|
public static ProgressQueue getInstance() {
|
||||||
|
return progressQueue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void offer(ProgressEvent event) {
|
||||||
|
synchronized (queue) {
|
||||||
|
queue.addLast(event);
|
||||||
|
queue.notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProgressEvent take(){
|
||||||
|
synchronized (queue) {
|
||||||
|
if(queue.isEmpty()) {
|
||||||
|
try {
|
||||||
|
queue.wait();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ProgressEvent event = queue.removeFirst();
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,321 @@
|
||||||
|
package org.jeecg.task;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||||
|
import cn.hutool.core.io.FileUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.commons.lang3.time.StopWatch;
|
||||||
|
import org.jeecg.common.constant.enums.WeatherDataSourceEnum;
|
||||||
|
import org.jeecg.common.constant.enums.WeatherForecastDatasourceEnum;
|
||||||
|
import org.jeecg.common.constant.enums.WeatherTaskStatusEnum;
|
||||||
|
import org.jeecg.common.exception.JeecgFileUploadException;
|
||||||
|
import org.jeecg.common.properties.SystemStorageProperties;
|
||||||
|
import org.jeecg.common.util.NcUtil;
|
||||||
|
import org.jeecg.modules.base.entity.WeatherData;
|
||||||
|
import org.jeecg.modules.base.entity.WeatherTask;
|
||||||
|
import org.jeecg.modules.base.entity.WeatherTaskLog;
|
||||||
|
import org.jeecg.modules.base.mapper.WeatherDataMapper;
|
||||||
|
import org.jeecg.service.WeatherDataService;
|
||||||
|
import org.jeecg.service.WeatherTaskService;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 气象预测任务执行线程
|
||||||
|
*/
|
||||||
|
public class WeatherTaskExec extends Thread{
|
||||||
|
|
||||||
|
private WeatherTask weatherTask;
|
||||||
|
private WeatherTaskService weatherTaskService;
|
||||||
|
private SystemStorageProperties systemStorageProperties;
|
||||||
|
private WeatherDataMapper weatherDataMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化
|
||||||
|
*/
|
||||||
|
public void init(WeatherTask weatherTask,
|
||||||
|
WeatherTaskService weatherTaskService,
|
||||||
|
SystemStorageProperties systemStorageProperties,
|
||||||
|
WeatherDataMapper weatherDataMapper){
|
||||||
|
this.weatherTask = weatherTask;
|
||||||
|
this.weatherTaskService = weatherTaskService;
|
||||||
|
this.systemStorageProperties = systemStorageProperties;
|
||||||
|
this.weatherDataMapper = weatherDataMapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
this.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行任务
|
||||||
|
*/
|
||||||
|
public void execute() {
|
||||||
|
StopWatch stopWatch = new StopWatch();
|
||||||
|
stopWatch.start();
|
||||||
|
try{
|
||||||
|
//修改任务状态为执行中
|
||||||
|
this.weatherTaskService.updateTaskStatus(this.weatherTask.getId(), WeatherTaskStatusEnum.IN_OPERATION.getKey());
|
||||||
|
//如果此任务已存在历史日志,先清除
|
||||||
|
this.weatherTaskService.deleteTaskLog(this.weatherTask.getId());
|
||||||
|
//执行模拟
|
||||||
|
this.execSimulation();
|
||||||
|
}catch (Exception e){
|
||||||
|
String taskErrorLog = "任务执行失败,原因:"+e.getMessage();
|
||||||
|
ProgressQueue.getInstance().offer(new ProgressEvent(this.weatherTask.getId(),taskErrorLog));
|
||||||
|
throw e;
|
||||||
|
}finally {
|
||||||
|
//添加任务耗时
|
||||||
|
stopWatch.stop();
|
||||||
|
long seconds = stopWatch.getTime(TimeUnit.SECONDS);
|
||||||
|
double min = seconds/60D;
|
||||||
|
BigDecimal bgMin = new BigDecimal(min);
|
||||||
|
BigDecimal result = bgMin.setScale(2, RoundingMode.HALF_UP);
|
||||||
|
this.weatherTaskService.updateTaskStatusToCompleted(this.weatherTask.getId(),result.doubleValue());
|
||||||
|
String taskCompletedLog = "任务执行完成,耗时:"+result+"分钟";
|
||||||
|
ProgressQueue.getInstance().offer(new ProgressEvent(this.weatherTask.getId(),taskCompletedLog));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行模拟
|
||||||
|
*/
|
||||||
|
private void execSimulation(){
|
||||||
|
try {
|
||||||
|
//处理开始日志
|
||||||
|
String forecastModel = "";
|
||||||
|
String startLogFormat = "";
|
||||||
|
String startTimeFormat = LocalDateTimeUtil.format(this.weatherTask.getStartDate(),"yyyy-MM-dd HH:mm:ss");
|
||||||
|
String forecastTime = this.weatherTask.getLeadTime().toString();
|
||||||
|
if (WeatherDataSourceEnum.GRAPHCAST.getKey().equals(this.weatherTask.getPredictionModel())){
|
||||||
|
forecastModel = WeatherDataSourceEnum.GRAPHCAST.getValue();
|
||||||
|
}else if(WeatherDataSourceEnum.PANGU.getKey().equals(this.weatherTask.getPredictionModel())){
|
||||||
|
forecastModel = WeatherDataSourceEnum.PANGU.getValue();
|
||||||
|
}
|
||||||
|
if(this.weatherTask.getDataSources().equals(WeatherForecastDatasourceEnum.CDS.getKey())){
|
||||||
|
startLogFormat = "任务开始,本次使用预测模型为:%s,预测开始时间为:%s,预测时长为:%s,前置数据采用CDS在线数据";
|
||||||
|
}else {
|
||||||
|
startLogFormat = "任务开始,本次使用预测模型为:%s,预测开始时间为:%s,预测时长为:%s,前置数据采用离线数据:"+this.weatherTask.getInputFile();
|
||||||
|
}
|
||||||
|
String startLog = String.format(startLogFormat,forecastModel,startTimeFormat,forecastTime);
|
||||||
|
ProgressQueue.getInstance().offer(new ProgressEvent(this.weatherTask.getId(),startLog));
|
||||||
|
|
||||||
|
//处理运行命令
|
||||||
|
List<String> command = new ArrayList<>();
|
||||||
|
String aiModelsPath = systemStorageProperties.getAiModelsPath()+File.separator+"ai-models";
|
||||||
|
String fileName = "panguweather_output_"+this.weatherTask.getId()+".grib";
|
||||||
|
if(this.weatherTask.getDataSources().equals(WeatherForecastDatasourceEnum.CDS.getKey())){
|
||||||
|
command.add(aiModelsPath);
|
||||||
|
command.add("--input");
|
||||||
|
command.add("cds");
|
||||||
|
command.add("--date");
|
||||||
|
command.add(LocalDateTimeUtil.format(this.weatherTask.getStartDate(),"yyyyMMdd"));
|
||||||
|
command.add("--time");
|
||||||
|
command.add(this.weatherTask.getStartTime().toString());
|
||||||
|
command.add("--lead-time");
|
||||||
|
command.add(this.weatherTask.getLeadTime().toString());
|
||||||
|
command.add("--path");
|
||||||
|
command.add(fileName);
|
||||||
|
command.add("--assets");
|
||||||
|
command.add("assets-panguweather");
|
||||||
|
command.add("panguweather");
|
||||||
|
}else if (this.weatherTask.getDataSources().equals(WeatherForecastDatasourceEnum.LOCATION_FILE.getKey())){
|
||||||
|
//离线文件还需处理
|
||||||
|
command.add(aiModelsPath);
|
||||||
|
command.add("--file");
|
||||||
|
command.add(this.weatherTask.getInputFile());
|
||||||
|
command.add("--lead-time");
|
||||||
|
command.add(this.weatherTask.getLeadTime().toString());
|
||||||
|
command.add("--path");
|
||||||
|
command.add(fileName);
|
||||||
|
command.add("--assets");
|
||||||
|
command.add("assets-panguweather");
|
||||||
|
command.add("panguweather");
|
||||||
|
}
|
||||||
|
String execLog = "执行任务命令,开始模拟,命令为:"+command;
|
||||||
|
ProgressQueue.getInstance().offer(new ProgressEvent(this.weatherTask.getId(),execLog));
|
||||||
|
ProcessBuilder processBuilder = new ProcessBuilder(command);
|
||||||
|
processBuilder.directory(new File(systemStorageProperties.getPanguModelExecPath()));
|
||||||
|
processBuilder.redirectErrorStream(true);
|
||||||
|
Process process = processBuilder.start();
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8"));
|
||||||
|
//读取输出日志
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
if(StrUtil.isNotBlank(line)){
|
||||||
|
ProgressQueue.getInstance().offer(new ProgressEvent(this.weatherTask.getId(),line));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//等待进程结束
|
||||||
|
process.waitFor();
|
||||||
|
|
||||||
|
String handleGribLog = "预测结束,开始处理grib文件";
|
||||||
|
ProgressQueue.getInstance().offer(new ProgressEvent(this.weatherTask.getId(),handleGribLog));
|
||||||
|
LocalDateTime startTime = this.weatherTask.getStartDate().atTime(this.weatherTask.getStartTime(), 0, 0);
|
||||||
|
//grib_copy命令
|
||||||
|
String gribCopyCommandPath = systemStorageProperties.getAiModelsPath()+File.separator+"grib_copy";
|
||||||
|
//grib_set命令
|
||||||
|
String gribSetCommandPath = systemStorageProperties.getAiModelsPath()+File.separator+"grib_set";
|
||||||
|
//需删除文件
|
||||||
|
List<String> delFiles = new ArrayList<>();
|
||||||
|
//需移动文件
|
||||||
|
List<String> moveFiles = new ArrayList<>();
|
||||||
|
//公用gribProcessBuilder
|
||||||
|
ProcessBuilder gribProcessBuilder = new ProcessBuilder();
|
||||||
|
gribProcessBuilder.directory(new File(systemStorageProperties.getPanguModelExecPath()));
|
||||||
|
//定义名称后缀,执行grib_set命令时去除,否则命名会冲突
|
||||||
|
String gribFileSuffix = "_not_grib_set";
|
||||||
|
//把grib文件切割成每6小时一份
|
||||||
|
int step = 6;
|
||||||
|
int i=this.weatherTask.getStartTime();
|
||||||
|
while(i <= this.weatherTask.getLeadTime()){
|
||||||
|
String gribCopyFileName = "panguweather_"+LocalDateTimeUtil.format(startTime,"yyyyMMddHH")+gribFileSuffix+".grib";
|
||||||
|
delFiles.add(gribCopyFileName);
|
||||||
|
//切割grib文件命令
|
||||||
|
List<String> gribCopyCommand = new ArrayList<>();
|
||||||
|
gribCopyCommand.add(gribCopyCommandPath);
|
||||||
|
gribCopyCommand.add("-w");
|
||||||
|
gribCopyCommand.add("step="+i);
|
||||||
|
gribCopyCommand.add(fileName);
|
||||||
|
gribCopyCommand.add(gribCopyFileName);
|
||||||
|
gribProcessBuilder.command(gribCopyCommand);
|
||||||
|
Process gribCopyProcess = gribProcessBuilder.start();
|
||||||
|
gribCopyProcess.waitFor();
|
||||||
|
|
||||||
|
//重新设置reftime信息
|
||||||
|
String gribSetFileName = "panguweather_"+LocalDateTimeUtil.format(startTime,"yyyyMMddHH")+".grib";
|
||||||
|
moveFiles.add(gribSetFileName);
|
||||||
|
String date = LocalDateTimeUtil.format(startTime,"yyyyMMdd");
|
||||||
|
String time = LocalDateTimeUtil.format(startTime,"HHmm");
|
||||||
|
List<String> gribSetCommand = new ArrayList<>();
|
||||||
|
gribSetCommand.add(gribSetCommandPath);
|
||||||
|
gribSetCommand.add("-s");
|
||||||
|
gribSetCommand.add("dataDate="+date+",dataTime="+time+",endStep="+0);
|
||||||
|
gribSetCommand.add(gribCopyFileName);
|
||||||
|
gribSetCommand.add(gribSetFileName);
|
||||||
|
gribProcessBuilder.command(gribSetCommand);
|
||||||
|
Process gribSetProcess = gribProcessBuilder.start();
|
||||||
|
gribSetProcess.waitFor();
|
||||||
|
i+=step;
|
||||||
|
startTime = startTime.plusHours(step);
|
||||||
|
}
|
||||||
|
if (CollUtil.isNotEmpty(moveFiles)) {
|
||||||
|
for (String moveFile : moveFiles) {
|
||||||
|
File srcFile = new File(systemStorageProperties.getPanguModelExecPath()+File.separator+moveFile);
|
||||||
|
if (srcFile.exists()) {
|
||||||
|
File targetFile = new File(this.getPanguWeatherPath()+File.separator+File.separator+moveFile);
|
||||||
|
FileUtil.move(srcFile,targetFile,true);
|
||||||
|
//保存生成的气象数据存储到数据库
|
||||||
|
this.saveGribInfoToDB(targetFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//删除gribCopy产生的文件
|
||||||
|
for (String delFile : delFiles) {
|
||||||
|
File srcFile = new File(systemStorageProperties.getPanguModelExecPath()+File.separator+delFile);
|
||||||
|
if (srcFile.exists()) {
|
||||||
|
srcFile.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//删除预测的结果文件
|
||||||
|
String outputFilePath = systemStorageProperties.getPanguModelExecPath()+File.separator+fileName;
|
||||||
|
File outputFile = new File(outputFilePath);
|
||||||
|
if(outputFile.exists()){
|
||||||
|
outputFile.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
//如果是本地文件进行预测,预测结束后删除文件
|
||||||
|
if(this.weatherTask.getDataSources().equals(WeatherForecastDatasourceEnum.LOCATION_FILE.getKey())){
|
||||||
|
String inputFilePath = systemStorageProperties.getPanguModelExecPath()+File.separator+this.weatherTask.getInputFile();
|
||||||
|
File inputFile = new File(inputFilePath);
|
||||||
|
if(inputFile.exists()){
|
||||||
|
inputFile.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存生成的气象数据存储到数据库
|
||||||
|
* @param file
|
||||||
|
*/
|
||||||
|
private void saveGribInfoToDB(File file){
|
||||||
|
//获取文件数据开始日期
|
||||||
|
String reftime = NcUtil.getReftime(file.getAbsolutePath());
|
||||||
|
if(StringUtils.isBlank(reftime)) {
|
||||||
|
throw new JeecgFileUploadException("解析气象文件起始时间数据异常,此文件可能损坏");
|
||||||
|
}
|
||||||
|
//计算文件大小M
|
||||||
|
BigDecimal divideVal = new BigDecimal("1024");
|
||||||
|
BigDecimal bg = new BigDecimal(file.length());
|
||||||
|
BigDecimal fileSize = bg.divide(divideVal).divide(divideVal).setScale(2, RoundingMode.HALF_UP);
|
||||||
|
//处理文件数据开始时间
|
||||||
|
Instant instant = Instant.parse(reftime);
|
||||||
|
LocalDateTime utcDateTime = LocalDateTime.ofInstant(instant, ZoneId.of("UTC"));
|
||||||
|
//计算文件MD5值
|
||||||
|
String md5Val = "";
|
||||||
|
try (InputStream is = new FileInputStream(file.getAbsolutePath())) {
|
||||||
|
md5Val = DigestUtils.md5Hex(is);
|
||||||
|
}catch (Exception e){
|
||||||
|
throw new RuntimeException(file.getName()+"MD5值计算失败");
|
||||||
|
}
|
||||||
|
//校验文件是否存在,存在删除从新新增
|
||||||
|
LambdaQueryWrapper<WeatherData> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
queryWrapper.eq(WeatherData::getFileName,file.getName());
|
||||||
|
WeatherData queryResult = weatherDataMapper.selectOne(queryWrapper);
|
||||||
|
if(Objects.nonNull(queryResult)){
|
||||||
|
weatherDataMapper.deleteById(queryResult.getId());
|
||||||
|
}
|
||||||
|
//构建文件信息
|
||||||
|
WeatherData weatherData = new WeatherData();
|
||||||
|
weatherData.setFileName(file.getName());
|
||||||
|
weatherData.setFileSize(fileSize.doubleValue());
|
||||||
|
weatherData.setFileExt(file.getName().substring(file.getName().lastIndexOf(".")+1));
|
||||||
|
weatherData.setDataStartTime(utcDateTime);
|
||||||
|
weatherData.setDataSource(weatherTask.getPredictionModel());
|
||||||
|
weatherData.setFilePath(file.getAbsolutePath());
|
||||||
|
weatherData.setMd5Value(md5Val);
|
||||||
|
weatherData.setShareTotal(1);
|
||||||
|
weatherDataMapper.insert(weatherData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取盘古数据存储路径
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private String getPanguWeatherPath(){
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(this.systemStorageProperties.getRootPath());
|
||||||
|
sb.append(File.separator);
|
||||||
|
sb.append(this.systemStorageProperties.getPangu());
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取盘古数据存储路径
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private String getGraphcastWeatherPath(){
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(this.systemStorageProperties.getRootPath());
|
||||||
|
sb.append(File.separator);
|
||||||
|
sb.append(this.systemStorageProperties.getGraphcast());
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
package org.jeecg.vo;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预测文件上传VO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ForecastFileVO implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 任务id
|
||||||
|
*/
|
||||||
|
private String taskId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传文件
|
||||||
|
*/
|
||||||
|
@JSONField(serialize = false)
|
||||||
|
private MultipartFile file;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user