1:预警信息
2:预警规则配置
3:历史水库水量资料
master
yangzhe123 2025-11-20 16:22:07 +08:00
parent 1b02203a6c
commit 2dd3bd46e0
18 changed files with 991 additions and 13 deletions

View File

@ -3,6 +3,7 @@ package com.gunshi.project.hsz.controller;
import com.gunshi.core.result.R;
import com.gunshi.project.hsz.timetask.JcskDataTask;
import com.gunshi.project.hsz.timetask.PaDataTask;
import com.gunshi.project.hsz.timetask.WarningRuleTask;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
@ -24,6 +25,19 @@ public class DebugController {
@Autowired
private JcskDataTask jcskDataTask;
@Autowired
private WarningRuleTask warningRuleTask;
@GetMapping("/warnRule")
public String warningRuleTast(){
try {
warningRuleTask.warningRuleExecute();
return "success";
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@GetMapping("/patask")
public String patask(){

View File

@ -0,0 +1,74 @@
package com.gunshi.project.hsz.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gunshi.core.result.R;
import com.gunshi.project.hsz.common.model.JcskSlB;
import com.gunshi.project.hsz.common.model.so.JcskSlBPageSo;
import com.gunshi.project.hsz.common.validate.markers.Insert;
import com.gunshi.project.hsz.common.validate.markers.Update;
import com.gunshi.project.hsz.entity.so.HisWaterDataPageSo;
import com.gunshi.project.hsz.mapper.HisWaterDataMapper;
import com.gunshi.project.hsz.model.HisWaterData;
import com.gunshi.project.hsz.service.HisWaterDataService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
@Tag(name = "预警-历史水库水量资料")
@RestController
@RequestMapping(value="/hiswater")
public class HisWaterDataController {
@Autowired
private HisWaterDataService hisWaterDataService;
@Operation(summary = "分页")
@PostMapping("/page")
public R<Page<HisWaterData>> page(@RequestBody @Validated HisWaterDataPageSo page) {
return R.ok(hisWaterDataService.pageQuery(page));
}
@Operation(summary = "新增")
@PostMapping("/insert")
public R<HisWaterData> insert(@Validated(Insert.class) @RequestBody HisWaterData dto) {
boolean result = hisWaterDataService.saveData(dto);
return R.ok(result ? dto : null);
}
@Operation(summary = "修改")
@PostMapping("/update")
public R<HisWaterData> update(@Validated(Update.class) @RequestBody HisWaterData dto) {
boolean result = hisWaterDataService.updateById(dto);
return R.ok(result ? dto : null);
}
@Operation(summary = "删除")
@GetMapping("/del/{id}")
public R<Boolean> del(@Schema(name = "id") @PathVariable("id") Serializable id) {
if (Objects.isNull(hisWaterDataService.getById(id))) {
throw new IllegalArgumentException("当前数据不存在");
}
return R.ok(hisWaterDataService.removeById(id));
}
@Operation(summary = "导出")
@PostMapping("/export")
public void export(@RequestBody @Validated HisWaterDataPageSo pageSo, HttpServletResponse response) {
pageSo.getPageSo().setPageSize(99999);
Page<HisWaterData> hisWaterDataPage = hisWaterDataService.pageQuery(pageSo);
List<HisWaterData> records = hisWaterDataPage.getRecords();
hisWaterDataService.export(records,response);
}
}

View File

@ -3,24 +3,30 @@ package com.gunshi.project.hsz.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gunshi.core.result.R;
import com.gunshi.core.session.entity.SessionUser;
import com.gunshi.project.hsz.common.validate.markers.Update;
import com.gunshi.project.hsz.entity.so.TermiteSurveyPageSo;
import com.gunshi.project.hsz.entity.so.WarningRulePageSo;
import com.gunshi.project.hsz.model.TermiteSurvey;
import com.gunshi.project.hsz.model.WarningRule;
import com.gunshi.project.hsz.model.WarningRuleInfo;
import com.gunshi.project.hsz.model.WaterAlarm;
import com.gunshi.project.hsz.service.WarningRuleInfoService;
import com.gunshi.project.hsz.service.WarningRuleService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import java.io.Serializable;
@Tag(name = "预警规则")
@RestController
@RequestMapping(value="/warn/rule")
public class WarningRuleController {
@RequestMapping(value="/warnRule")
public class WarningRuleController extends AbstractCommonFileController {
@Autowired
private WarningRuleService warningRuleService;
@ -35,7 +41,44 @@ public class WarningRuleController {
@Operation(summary = "新增")
@PostMapping("/insert")
public R<WarningRule> insert(@RequestBody @Validated WarningRule dto) {
public R<WarningRule> insert(@RequestBody @Validated WarningRule dto, HttpServletRequest request) {
SessionUser sessionUser = checkLogin(request);
if(sessionUser == null){
throw new IllegalArgumentException("未登录");
}
Long userId = sessionUser.getUserId();
dto.setCreateName(userId.toString());
return R.ok(warningRuleService.saveData(dto));
}
@Operation(summary = "修改")
@PostMapping("/update")
public R<WarningRule> update(@Validated(Update.class) @RequestBody WarningRule dto) {
boolean result = warningRuleService.updateData(dto);
return R.ok(result ? dto : null);
}
@Operation(summary = "删除")
@GetMapping("/del/{id}")
public R<Boolean> del(@Schema(name = "id") @PathVariable("id") Serializable id) {
boolean b = warningRuleService.deleteById(id);
return R.ok(b);
}
@Autowired
private WarningRuleInfoService warningRuleInfoService;
@Operation(summary = "预警信息分页")
@PostMapping("/info/page")
public R<Page<WarningRuleInfo>> infoPage(@RequestBody @Validated WarningRulePageSo page) {
return R.ok(warningRuleInfoService.pageQuery(page));
}
@Override
public String getGroupId() {
return "warningRule";
}
}

View File

@ -0,0 +1,17 @@
package com.gunshi.project.hsz.entity.so;
import com.gunshi.db.dto.PageSo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Data
public class HisWaterDataPageSo {
@NotNull(message = "分页参数不能为空")
@Schema(description = "分页参数")
private PageSo pageSo;
}

View File

@ -1,6 +1,7 @@
package com.gunshi.project.hsz.entity.so;
import com.gunshi.db.dto.DateTimeRangeSo;
import com.gunshi.db.dto.PageSo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
@ -16,4 +17,6 @@ public class WarningRulePageSo {
private String ruleName;
private String warningType;
private DateTimeRangeSo dateTimeRangeSo;
}

View File

@ -0,0 +1,9 @@
package com.gunshi.project.hsz.entity.vo;
import com.gunshi.project.hsz.model.HisWaterData;
import lombok.Data;
@Data
public class HisWaterDataVo {
}

View File

@ -0,0 +1,9 @@
package com.gunshi.project.hsz.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.gunshi.project.hsz.model.HisWaterData;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface HisWaterDataMapper extends BaseMapper<HisWaterData> {
}

View File

@ -0,0 +1,9 @@
package com.gunshi.project.hsz.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.gunshi.project.hsz.model.WarningRuleInfo;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface WarningRuleInfoMapper extends BaseMapper<WarningRuleInfo> {
}

View File

@ -0,0 +1,38 @@
package com.gunshi.project.hsz.model;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
@Data
@TableName("his_water_data")
public class HisWaterData {
@TableId(value = "id",type = IdType.AUTO)
private Long id;
@TableField("year")
@Schema(description = "年度")
private String year;
@TableField("month")
@Schema(description = "月份")
private String month;
@TableField("avg_water")
@Schema(description = "月份平均蓄水量")
private BigDecimal avgWater;
@TableField(exist = false)
@Schema(description = "年度总蓄水量")
private BigDecimal totalWater;
}

View File

@ -31,9 +31,20 @@ public class WarningCondition {
/**
*
* REAL_WATER_LEVEL
* PEAK_FLOW
* RAINFALL
* WATER_STORAGE
* FORECAST_RAINFALL
*/
@TableField("indicator_type")
private String indicatorType;
/**
* FLOOD-DROUGHT-
*/
@TableField("warning_type")
private String warningType;
/**
*
@ -64,4 +75,13 @@ public class WarningCondition {
*/
@TableField("relation_type")
private String relationType;
@TableField("warning_level")
private Integer warningLevel;
@TableField("year")
private String year;
@TableField(exist = false)
private Boolean isEnjoy = false;//该预警规则是否满足条件,默认不满足
}

View File

@ -18,6 +18,7 @@ public class WarningRule {
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
*
@ -49,10 +50,15 @@ public class WarningRule {
@TableField("create_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
@TableField("warning_level")
private Integer warningLevel;
/**
*
*/
@TableField(exist = false)
private List<WarningCondition> conditions;
}

View File

@ -0,0 +1,69 @@
package com.gunshi.project.hsz.model;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
@Data
@TableName("warning_rule_info")
public class WarningRuleInfo {
/**
* ID
*/
@TableId(type = IdType.AUTO)
private Long id;
@TableField("rule_id")
private Long ruleId;
/**
*
*/
@TableField("rule_name")
private String ruleName;
/**
* FLOOD-DROUGHT-
*/
@TableField("warning_type")
private String warningType;
/**
* 0-1-
*/
@TableField("status")
private Integer status;
/**
*
*/
@TableField("create_name")
private String createName;
/**
*
*/
@TableField("create_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
@TableField("rule_info")
private String ruleInfo;
@TableField("warning_level")
private Integer warningLevel;
/**
*
*/
@TableField(exist = false)
private List<WarningCondition> conditions;
}

View File

@ -0,0 +1,129 @@
package com.gunshi.project.hsz.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gunshi.project.hsz.entity.so.HisWaterDataPageSo;
import com.gunshi.project.hsz.mapper.HisWaterDataMapper;
import com.gunshi.project.hsz.model.HisWaterData;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class HisWaterDataService extends ServiceImpl<HisWaterDataMapper, HisWaterData> {
public Page<HisWaterData> pageQuery(HisWaterDataPageSo page) {
LambdaQueryWrapper<HisWaterData> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.last("order by year desc,month asc");
Page<HisWaterData> hisWaterDataPage = this.baseMapper.selectPage(page.getPageSo().toPage(), queryWrapper);
List<HisWaterData> records = hisWaterDataPage.getRecords();
// 按年度分组
Map<String, List<HisWaterData>> groupedByYear = records.stream()
.collect(Collectors.groupingBy(HisWaterData::getYear));
// 遍历每个年度,计算并设置年度总蓄水量
for (Map.Entry<String, List<HisWaterData>> entry : groupedByYear.entrySet()) {
String year = entry.getKey();
List<HisWaterData> yearData = entry.getValue();
// 计算年度总蓄水量
BigDecimal totalWater = yearData.stream()
.map(HisWaterData::getAvgWater)
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
// 为每个该年度的数据设置总蓄水量
for (HisWaterData data : yearData) {
data.setTotalWater(totalWater);
}
}
return hisWaterDataPage;
}
public boolean saveData(HisWaterData dto) {
LambdaQueryWrapper<HisWaterData> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(HisWaterData::getYear,dto.getYear());
queryWrapper.eq(HisWaterData::getMonth,dto.getMonth());
HisWaterData hisWaterData = this.baseMapper.selectOne(queryWrapper);
if (hisWaterData != null) {
throw new IllegalArgumentException(dto.getYear() + "年-" + dto.getMonth() +"月,数据已存在,请勿重复添加");
}
return this.baseMapper.insert(dto) > 0;
}
public void export(List<HisWaterData> records, HttpServletResponse response) {
try {
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet("蓄水量数据");
int rowNum = 0;
// 按年度分组
Map<String, List<HisWaterData>> groupedByYear = records.stream()
.collect(Collectors.groupingBy(HisWaterData::getYear));
// 遍历每个年度
for (Map.Entry<String, List<HisWaterData>> entry : groupedByYear.entrySet()) {
String year = entry.getKey();
List<HisWaterData> yearData = entry.getValue();
// 计算年度总蓄水量
BigDecimal totalWater = yearData.stream()
.map(HisWaterData::getAvgWater)
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
// 写入年度和总蓄水量(每个值单独单元格)
Row yearRow = sheet.createRow(rowNum++);
yearRow.createCell(0).setCellValue("年:");
yearRow.createCell(1).setCellValue(year);
yearRow.createCell(2).setCellValue("总蓄水量(万m³)");
yearRow.createCell(3).setCellValue(totalWater.toString());
// 写入月份数据
for (HisWaterData data : yearData) {
Row monthRow = sheet.createRow(rowNum++);
monthRow.createCell(0).setCellValue("月份:");
monthRow.createCell(1).setCellValue(data.getMonth());
monthRow.createCell(2).setCellValue("平均蓄水量(万m³)");
if (data.getAvgWater() != null) {
monthRow.createCell(3).setCellValue(data.getAvgWater().toString());
} else {
monthRow.createCell(3).setCellValue("");
}
}
// 年度之间空一行
rowNum++;
}
// 简单自适应列宽
for (int i = 0; i < 4; i++) {
sheet.autoSizeColumn(i);
}
// 设置响应头
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename=water_data.xlsx");
// 写入响应流
workbook.write(response.getOutputStream());
workbook.close();
} catch (Exception e) {
throw new RuntimeException("导出Excel失败", e);
}
}
}

View File

@ -823,9 +823,11 @@ public class JcskSyRService extends ServiceImpl<JcskSyRMapper, JcskSyR> {
));
//组合成为 时间 库水位 管道水位的数据
List<OsmoticPressDetailVo> data = new ArrayList<>();
for (JcskSyREightAm eightAm : jcskSyREightAms) {
Iterator<JcskSyREightAm> iterator = jcskSyREightAms.iterator();
while (iterator.hasNext()) {
JcskSyREightAm eightAm = iterator.next();
if(eightAm.getMstm() == null || eightAm.getSpprwl() == null){
continue;
iterator.remove();
}
OsmoticPressDetailVo detailVo = new OsmoticPressDetailVo();
@ -837,7 +839,7 @@ public class JcskSyRService extends ServiceImpl<JcskSyRMapper, JcskSyR> {
// 查找对应的库水位
BigDecimal rzValue = findClosestRzValue(rzMap, mstmStr);
if(rzValue == null){
continue;
iterator.remove();
}
detailVo.setRz(rzValue);
//获取数据清洗规则
@ -846,11 +848,11 @@ public class JcskSyRService extends ServiceImpl<JcskSyRMapper, JcskSyR> {
//校验这条数据是否符合规则
if(rzValue.compareTo(rule.getRz()) >=0){
//如果当前库水位大于等于设置库水位,则跳过这条数据
continue;
iterator.remove();
}
if(eightAm.getSpprwl().compareTo(rule.getSyValue()) <=0){
//如果当前监测值小于等于设置值,则跳过这套数据
continue;
iterator.remove();
}
}
data.add(detailVo);

View File

@ -25,4 +25,44 @@ public class WarningConditionService extends ServiceImpl<WarningConditionMapper,
queryWrapper.eq(WarningCondition::getRuleId,id);
return this.list(queryWrapper);
}
public WarningCondition checkConditionExists(WarningCondition dto) {
LambdaQueryWrapper<WarningCondition> queryWrapper = new LambdaQueryWrapper<>();
if(dto.getId() != null){
queryWrapper.ne(WarningCondition::getId, dto.getId());
}
if(dto.getIndicatorType() != null){
//预警指标类型
queryWrapper.eq(WarningCondition::getIndicatorType,dto.getIndicatorType());
}
if(dto.getWarningLevel() != null){
//预警等级
queryWrapper.eq(WarningCondition::getWarningLevel,dto.getWarningLevel());
}
if(dto.getWarningType() != null){
//预警类型
queryWrapper.eq(WarningCondition::getWarningType,dto.getWarningType());
}
if(dto.getOperator() != null){
//比较符
queryWrapper.eq(WarningCondition::getOperator,dto.getOperator());
}
if(dto.getThresholdValue() != null){
//阈值
queryWrapper.eq(WarningCondition::getThresholdValue,dto.getThresholdValue());
}
if(dto.getDurationHours() != null){
//时长/时段(小时)
queryWrapper.eq(WarningCondition::getDurationHours,dto.getDurationHours());
}
WarningCondition warningCondition = this.baseMapper.selectOne(queryWrapper);
return warningCondition;
}
public boolean removeByRuleId(Long ruleId){
LambdaQueryWrapper<WarningCondition> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(WarningCondition::getRuleId,ruleId);
return this.remove(queryWrapper);
}
}

View File

@ -0,0 +1,35 @@
package com.gunshi.project.hsz.service;
import com.alibaba.excel.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gunshi.core.result.R;
import com.gunshi.project.hsz.entity.so.WarningRulePageSo;
import com.gunshi.project.hsz.mapper.WarningRuleInfoMapper;
import com.gunshi.project.hsz.model.WarningRuleInfo;
import kotlin.jvm.internal.Lambda;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class WarningRuleInfoService extends ServiceImpl<WarningRuleInfoMapper,WarningRuleInfo> {
public Page<WarningRuleInfo> pageQuery(WarningRulePageSo page) {
LambdaQueryWrapper<WarningRuleInfo> queryWrapper = new LambdaQueryWrapper<>();
if(!StringUtils.isBlank(page.getRuleName())){
queryWrapper.like(WarningRuleInfo::getRuleName, page.getRuleName());
}
if(!StringUtils.isBlank(page.getWarningType())){
queryWrapper.eq(WarningRuleInfo::getWarningType, page.getWarningType());
}
if(page.getDateTimeRangeSo() != null){
queryWrapper.ge(WarningRuleInfo::getCreateTime,page.getDateTimeRangeSo().getStart());
queryWrapper.le(WarningRuleInfo::getCreateTime,page.getDateTimeRangeSo().getEnd());
}
Page<WarningRuleInfo> warningRuleInfoPage = this.baseMapper.selectPage(page.getPageSo().toPage(), queryWrapper);
return warningRuleInfoPage;
}
}

View File

@ -16,7 +16,9 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
@Service
@Slf4j
@ -34,6 +36,7 @@ public class WarningRuleService extends ServiceImpl<WarningRuleMapper, WarningRu
if(!StringUtils.isBlank(page.getRuleName())){
queryWrapper.eq(WarningRule::getWarningType, page.getWarningType());
}
queryWrapper.orderByDesc(WarningRule::getCreateTime);
Page<WarningRule> warningRulePage = this.baseMapper.selectPage(page.getPageSo().toPage(), queryWrapper);
for (WarningRule record : warningRulePage.getRecords()) {
@ -43,7 +46,55 @@ public class WarningRuleService extends ServiceImpl<WarningRuleMapper, WarningRu
return warningRulePage;
}
public List<WarningRule> listData(){
List<WarningRule> warningRules = this.baseMapper.selectList(null);
for (WarningRule warningRule : warningRules) {
List<WarningCondition> listByRuleId = warningConditionService.getListByRuleId(warningRule.getId());
warningRule.setConditions(listByRuleId);
}
return warningRules;
}
public WarningRule saveData(WarningRule dto) {
return null;
if(dto.getConditions() == null || dto.getConditions().isEmpty()){
throw new IllegalArgumentException("请至少配置一条预警规则");
}
save(dto);
List<WarningCondition> conditions = dto.getConditions();
for (WarningCondition condition : conditions) {
WarningCondition warningCondition = warningConditionService.checkConditionExists(condition);
if(warningCondition != null){
throw new IllegalArgumentException("对不起,该预警规则已配置");
}
condition.setRuleId(dto.getId());
condition.setWarningType(dto.getWarningType());
condition.setWarningLevel(dto.getWarningLevel());
}
warningConditionService.saveBatch(conditions);
return dto;
}
public boolean updateData(WarningRule dto) {
if(dto.getConditions() == null || dto.getConditions().isEmpty()){
throw new IllegalArgumentException("请至少配置一条预警规则");
}
updateById(dto);
List<WarningCondition> conditions = dto.getConditions();
for (WarningCondition condition : conditions) {
WarningCondition warningCondition = warningConditionService.checkConditionExists(condition);
if(warningCondition != null){
throw new IllegalArgumentException("对不起,该预警规则已配置");
}
condition.setRuleId(dto.getId());
}
warningConditionService.updateBatchById(conditions);
return true;
}
public boolean deleteById(Serializable id) {
removeById(id);
warningConditionService.removeByRuleId(Long.valueOf(id.toString()));
return true;
}
}

View File

@ -0,0 +1,410 @@
package com.gunshi.project.hsz.timetask;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gunshi.project.hsz.common.model.StRiverRReal;
import com.gunshi.project.hsz.common.model.StRsvrRReal;
import com.gunshi.project.hsz.common.util.LocalDateTimeConverter;
import com.gunshi.project.hsz.entity.so.WeatherSo;
import com.gunshi.project.hsz.entity.vo.*;
import com.gunshi.project.hsz.model.*;
import com.gunshi.project.hsz.service.*;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@EnableScheduling//开启定时任务
@Component
@Slf4j
@Profile({"prod","dev","local"})
public class WarningRuleTask {
@Autowired
private WarningRuleService warningRuleService;
@Autowired
private WarningRuleInfoService warningRuleInfoService;
//河道水位
@Autowired
private RiverWaterService riverWaterService;
@Autowired
private StRiverRRealService stRiverRRealService;
//水库水位
@Autowired
private ReservoirWaterService reservoirWaterService;
@Autowired
private StRsvrRRealService stRsvrRRealService;
@Autowired
private ForecastResultsService forecastResultsService;
@Resource
private ForecastService forecastService;
@Autowired
private RainBasinDivisionService rainBasinDivisionService;
public void warningRuleExecute(){
//获取配置的预警规则
List<WarningRule> warningRules = warningRuleService.listData();
//过滤出启动了的预警规则
warningRules = warningRules.stream().filter(o ->{
return o.getStatus() != null && o.getStatus() == 1;
}).collect(Collectors.toList());
for (WarningRule warningRule : warningRules) {
//获取预警类型
String warningType = warningRule.getWarningType();
//获取预警的规则细节
List<WarningCondition> conditions = warningRule.getConditions();
if (conditions == null || conditions.isEmpty()) {
continue;
}
// 为每个条件计算实际值并设置是否满足
for (WarningCondition condition : conditions) {
BigDecimal actualValue = calculateActualValue(condition, warningType);
condition.setIsEnjoy(compareValue(actualValue, condition));
}
// 根据条件关系判断整个规则是否满足
boolean isRuleSatisfied = evaluateConditions(conditions);
// 这里可以根据 isRuleSatisfied 进行后续处理,比如触发预警等
if (isRuleSatisfied) {
log.info("预警规则 {} 满足条件,触发预警", warningRule.getRuleName());
// 生成规则信息
String ruleInfo = generateRuleInfo(conditions);
WarningRuleInfo warningRuleInfo = new WarningRuleInfo();
warningRuleInfo.setRuleId(warningRule.getId());
warningRuleInfo.setRuleName(warningRule.getRuleName());
warningRuleInfo.setConditions(conditions);
warningRuleInfo.setStatus(1);
warningRuleInfo.setCreateTime(LocalDateTime.now());
warningRuleInfo.setRuleInfo(ruleInfo);
warningRuleInfo.setWarningType(warningType);
warningRuleInfoService.save(warningRuleInfo);
}
}
}
/**
*
*/
private String generateRuleInfo(List<WarningCondition> conditions) {
List<String> conditionInfos = new ArrayList<>();
for (WarningCondition condition : conditions) {
if (condition.getIsEnjoy()) { // 只记录满足条件的报警信息
String conditionInfo = generateSingleConditionInfo(condition);
if (conditionInfo != null && !conditionInfo.isEmpty()) {
conditionInfos.add(conditionInfo);
}
}
}
return String.join("", conditionInfos);
}
/**
* -
*/
private String generateSingleConditionInfo(WarningCondition condition) {
String indicatorType = condition.getIndicatorType();
String stcd = condition.getStcd();
BigDecimal thresholdValue = condition.getThresholdValue();
Integer durationHours = condition.getDurationHours();
switch (indicatorType) {
case "REAL_WATER_LEVEL":
BigDecimal currentWaterLevel = getRzByStcd(stcd);
return String.format("%s测点监测水位%sm %s %sm",
stcd, currentWaterLevel, condition.getOperator(), thresholdValue);
case "PEAK_FLOW":
return String.format("未来%dh预报洪峰流量 %s %s m³/s",
durationHours != null ? durationHours : 24, condition.getOperator(), thresholdValue);
case "RAINFALL":
BigDecimal currentRainfall = getRealRainFall(stcd, durationHours);
return String.format("%s测点过去%dh降雨量%smm %s %smm",
stcd, durationHours != null ? durationHours : 24,
currentRainfall, condition.getOperator(), thresholdValue);
case "WATER_STORAGE":
BigDecimal currentStoragePercent = getWaterStorage(condition.getYear());
return String.format("蓄水量 %s 同期%s%%",
condition.getOperator(), thresholdValue);
case "FORECAST_RAINFALL":
return String.format("%s测点未来%dh降雨量 %s %smm",
stcd, durationHours != null ? durationHours : 24,
condition.getOperator(), thresholdValue);
default:
return String.format("未知指标类型%s %s %s", stcd, condition.getOperator(), thresholdValue);
}
}
/**
*
*/
private BigDecimal calculateActualValue(WarningCondition condition, String warningType) {
String indicatorType = condition.getIndicatorType();
String stcd = condition.getStcd();
Integer durationHours = condition.getDurationHours();
switch (indicatorType) {
case "REAL_WATER_LEVEL":
return getRzByStcd(stcd);
case "PEAK_FLOW":
return getFloowMaxQ(durationHours);
case "RAINFALL":
return getRealRainFall(stcd, durationHours);
case "WATER_STORAGE":
return getWaterStorage(condition.getYear());
case "FORECAST_RAINFALL":
return getForecastRainFall(stcd, durationHours);
default:
return BigDecimal.ZERO;
}
}
/**
*
*/
private boolean compareValue(BigDecimal actualValue, WarningCondition condition) {
if (actualValue == null || condition.getThresholdValue() == null) {
return false;
}
String operator = condition.getOperator();
BigDecimal threshold = condition.getThresholdValue();
switch (operator) {
case ">":
return actualValue.compareTo(threshold) > 0;
case ">=":
return actualValue.compareTo(threshold) >= 0;
case "<":
return actualValue.compareTo(threshold) < 0;
case "<=":
return actualValue.compareTo(threshold) <= 0;
default:
return false;
}
}
/**
*
* AND/OR
*/
private boolean evaluateConditions(List<WarningCondition> conditions) {
if (conditions.isEmpty()) {
return false;
}
boolean result = false;
boolean currentGroup = conditions.get(0).getIsEnjoy();
for (int i = 0; i < conditions.size() - 1; i++) {
WarningCondition current = conditions.get(i);
WarningCondition next = conditions.get(i + 1);
String relation = current.getRelationType();
if ("AND".equals(relation)) {
// AND 关系:当前组与下一个条件进行与运算
currentGroup = currentGroup && next.getIsEnjoy();
} else if ("OR".equals(relation)) {
// OR 关系:当前结果与当前组进行或运算,然后开始新的组
result = result || currentGroup;
currentGroup = next.getIsEnjoy();
}
}
// 处理最后一个条件
result = result || currentGroup;
return result;
}
//获取实时水位
private BigDecimal getRzByStcd(String stcd){
//获取河道水位的站点编码
List<String> riverStcd = riverWaterService.getRiverStcd();
if(riverStcd.contains(stcd)){
LambdaQueryWrapper<StRiverRReal> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(StRiverRReal::getStcd,stcd);
StRiverRReal stRiverRReal = stRiverRRealService.getBaseMapper().selectOne(queryWrapper);
if(stRiverRReal != null){
return stRiverRReal.getZ();
}
return BigDecimal.ZERO;
}else{
LambdaQueryWrapper<StRsvrRReal> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(StRsvrRReal::getStcd,stcd);
StRsvrRReal stRsvrRReal = stRsvrRRealService.getBaseMapper().selectOne(queryWrapper);
if(stRsvrRReal != null){
return stRsvrRReal.getRz();
}
return BigDecimal.ZERO;
}
}
//获取预报洪峰流量
private BigDecimal getFloowMaxQ(Integer durationHours){
ForecastTask forecastTask = new ForecastTask();
// 设置当前时间整点
LocalDateTime now = LocalDateTime.now();
LocalDateTime nowHour = now.withMinute(0).withSecond(0).withNano(0);
forecastTask.setNowTime(LocalDateTimeConverter.toDate(nowHour));
// 设置开始时间(当前时间减去一天)
LocalDateTime startTime = nowHour.minusDays(1);
forecastTask.setStartTime(LocalDateTimeConverter.toDate(startTime));
// 设置结束时间当前时间加上durationHours
LocalDateTime endTime = nowHour.plusHours(durationHours);
forecastTask.setEndTime(LocalDateTimeConverter.toDate(endTime));
forecastTask.setForecastWarm(1);
forecastTask.setForecastPeriod(durationHours); // 设置预报时长
List<ForecastResultVo> humanForecastResult = forecastResultsService.getHumanForecastResult(forecastTask);
//过滤出预报的数据
humanForecastResult = humanForecastResult.stream().filter(o ->{
return o.getIspreDrp().equals("1") && o.getYcRkQValue() != null;
}).collect(Collectors.toList());
BigDecimal totalQ = BigDecimal.ZERO;
for (ForecastResultVo forecastResultVo : humanForecastResult) {
totalQ = totalQ.add(forecastResultVo.getYcRkQValue());
}
return totalQ;
}
//获取降雨量的值
public BigDecimal getRealRainFall(String stcd,Integer durationHours){
StPptnDetailsVo stPptnDetailsVo = rainBasinDivisionService.queryStPptnDetailsByStcd(stcd);
if (stPptnDetailsVo == null) {
return BigDecimal.ZERO; // 或返回 BigDecimal.ZERO根据业务需求调整
}
BigDecimal result = switch (durationHours) {
case 1 -> stPptnDetailsVo.getH1();
case 3 -> stPptnDetailsVo.getH3();
case 6 -> stPptnDetailsVo.getH6();
case 12 -> stPptnDetailsVo.getH12();
case 24 -> stPptnDetailsVo.getH24();
case 48 -> stPptnDetailsVo.getH48();
// 3. 未匹配的时长如2、5等返回null或默认值
default -> BigDecimal.ZERO; // 或 throw new IllegalArgumentException("不支持的时长:" + durationHours);
};
return result == null?BigDecimal.ZERO:result;
}
@Autowired
private HisWaterDataService hisWaterDataService;
//获取蓄水量 - 修改后的逻辑
private BigDecimal getWaterStorage(String year){
List<AttResBaseVo> list = reservoirWaterService.list();
if (list == null || list.isEmpty()) {
return BigDecimal.ZERO;
}
AttResBaseVo reservoir = list.get(0);
BigDecimal nowCap = reservoir.getNowCap() == null ? BigDecimal.ZERO : reservoir.getNowCap();
BigDecimal deadCap = reservoir.getDeadCap() == null ? BigDecimal.ZERO : reservoir.getDeadCap();
BigDecimal availableWater = nowCap.subtract(deadCap); // 当前可用水量
// 获取当前月份
int currentMonth = LocalDateTime.now().getMonthValue();
String month = String.valueOf(currentMonth);
// 获取某年同月的蓄水量作为基准值
List<HisWaterData> hisWaterDataList = hisWaterDataService.lambdaQuery()
.eq(HisWaterData::getYear, year)
.eq(HisWaterData::getMonth, month)
.list();
BigDecimal baseWaterStorage = BigDecimal.ZERO;
if (!hisWaterDataList.isEmpty()) {
HisWaterData hisWaterData = hisWaterDataList.get(0);
baseWaterStorage = hisWaterData.getAvgWater() == null ? BigDecimal.ZERO : hisWaterData.getAvgWater();
}
// 如果基准值为0避免除零错误返回0
if (baseWaterStorage.compareTo(BigDecimal.ZERO) == 0) {
return BigDecimal.ZERO;
}
// 计算当前可用水量占同期蓄水量的百分比
BigDecimal percentage = availableWater.divide(baseWaterStorage, 4, RoundingMode.HALF_UP)
.multiply(new BigDecimal("100"));
return percentage;
}
//获取预测降雨量
private BigDecimal getForecastRainFall(String stcd,Integer durationHours) {
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
// 获取当前日期默认系统时区可指定时区如ZoneId.of("UTC")
LocalDate today = LocalDate.now(ZoneId.systemDefault());
String todayDateStr = today.format(dateFormatter); // 结果示例20251120
String tm = todayDateStr + "08"; // 拼接固定小时最终格式2025112008
WeatherSo weatherSo = new WeatherSo();
weatherSo.setTm(tm);
List<ForeRainVo> fore = forecastService.fore(weatherSo);
for (ForeRainVo foreRainVo : fore) {
if (stcd.equals(foreRainVo.getStcd())) {
BigDecimal forecastRain = BigDecimal.ZERO;
switch (durationHours) {
case 1:
forecastRain = foreRainVo.getH1();
return forecastRain;
case 3:
forecastRain = foreRainVo.getH3();
return forecastRain;
case 6:
forecastRain = foreRainVo.getH6();
return forecastRain;
case 12:
forecastRain = foreRainVo.getH12();
return forecastRain;
case 24:
forecastRain = new BigDecimal(foreRainVo.getH24());
return forecastRain;
default:
return BigDecimal.ZERO;
}
}
}
return BigDecimal.ZERO;
}
}