From 75162d9e33a2af657660802f0f6f0d94095b5ce8 Mon Sep 17 00:00:00 2001 From: yangzhe123 <2824096059@qq.com> Date: Wed, 3 Dec 2025 13:52:10 +0800 Subject: [PATCH] =?UTF-8?q?=E5=86=9C=E4=B8=9A=E9=9C=80=E6=B0=B4=20?= =?UTF-8?q?=E4=BE=9B=E9=9C=80=E5=B9=B3=E8=A1=A1=E5=88=86=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RiceSupportBalanceController.java | 65 ++++ .../hsz/entity/RiceSupportMidCaculate.java | 21 ++ .../dto/RiceSupportBalanceCaculateDto.java | 28 ++ .../so/RiceSupportBalanceCaculatePageSo.java | 21 ++ .../RiceSupportBalanceDetailMapper.java | 10 + .../hsz/mapper/RiceSupportBalanceMapper.java | 9 + .../project/hsz/model/IcWaterForecast.java | 5 + .../hsz/model/IcWaterForecastDetail.java | 4 +- .../project/hsz/model/RiceGrowConfig.java | 3 +- .../project/hsz/model/RiceIrrigationUse.java | 3 +- .../gunshi/project/hsz/model/RiceRqWater.java | 6 +- .../project/hsz/model/RiceSupportBalance.java | 7 +- .../hsz/model/RiceSupportBalanceDetail.java | 71 ++++ .../hsz/model/RiceWaterForecastCycle.java | 3 +- .../hsz/model/RiceWaterForecastMonth.java | 3 +- .../gunshi/project/hsz/model/RiceWaterKi.java | 3 +- .../hsz/service/IcWaterForecastService.java | 24 ++ .../hsz/service/RiceRqWaterService.java | 19 + .../RiceSupportBalanceDetailService.java | 28 ++ .../service/RiceSupportBalanceService.java | 338 ++++++++++++++++++ .../project/hsz/util/LocalDateTimeUtils.java | 91 +++++ 21 files changed, 752 insertions(+), 10 deletions(-) create mode 100644 src/main/java/com/gunshi/project/hsz/controller/RiceSupportBalanceController.java create mode 100644 src/main/java/com/gunshi/project/hsz/entity/RiceSupportMidCaculate.java create mode 100644 src/main/java/com/gunshi/project/hsz/entity/dto/RiceSupportBalanceCaculateDto.java create mode 100644 src/main/java/com/gunshi/project/hsz/entity/so/RiceSupportBalanceCaculatePageSo.java create mode 100644 src/main/java/com/gunshi/project/hsz/mapper/RiceSupportBalanceDetailMapper.java create mode 100644 src/main/java/com/gunshi/project/hsz/mapper/RiceSupportBalanceMapper.java create mode 100644 src/main/java/com/gunshi/project/hsz/model/RiceSupportBalanceDetail.java create mode 100644 src/main/java/com/gunshi/project/hsz/service/RiceSupportBalanceDetailService.java create mode 100644 src/main/java/com/gunshi/project/hsz/service/RiceSupportBalanceService.java diff --git a/src/main/java/com/gunshi/project/hsz/controller/RiceSupportBalanceController.java b/src/main/java/com/gunshi/project/hsz/controller/RiceSupportBalanceController.java new file mode 100644 index 0000000..9a7fca9 --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/controller/RiceSupportBalanceController.java @@ -0,0 +1,65 @@ +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.entity.dto.RiceSupportBalanceCaculateDto; +import com.gunshi.project.hsz.entity.dto.RiceWaterCaculateDto; +import com.gunshi.project.hsz.entity.so.RiceSupportBalanceCaculatePageSo; +import com.gunshi.project.hsz.entity.vo.RiceRqWaterCaculateVo; +import com.gunshi.project.hsz.model.IcWaterForecast; +import com.gunshi.project.hsz.model.RiceRqWater; +import com.gunshi.project.hsz.model.RiceSupportBalance; +import com.gunshi.project.hsz.service.IcWaterForecastService; +import com.gunshi.project.hsz.service.RiceRqWaterService; +import com.gunshi.project.hsz.service.RiceSupportBalanceService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@Tag(name = "供需平衡分析") +@RestController +@RequestMapping(value="/riceSupportBalance") +public class RiceSupportBalanceController { + + @Autowired + private RiceSupportBalanceService riceSupportBalanceService; + + @Operation(summary = "分页") + @PostMapping("/page") + public R> page(@RequestBody RiceSupportBalanceCaculatePageSo page){ + Page res = riceSupportBalanceService.queryPage(page); + return R.ok(res); + } + + @Operation(summary = "删除") + @PostMapping("/del/{id}") + public R del(@Schema(name = "id") @PathVariable("id") Long id){ + boolean flag = riceSupportBalanceService.delData(id); + return R.ok(flag); + } + + @Operation(summary = "计算") + @PostMapping("/caculate") + public R caculate(@RequestBody RiceSupportBalanceCaculateDto dto){ + riceSupportBalanceService.caculateAndSave(dto); + return R.ok(true); + } + + @Operation(summary = "来水预测-分页查询,供需平衡板") + @PostMapping("/icpage") + public R> icPage(@RequestBody RiceSupportBalanceCaculatePageSo pageSo){ + Page page = riceSupportBalanceService.icPage(pageSo); + return R.ok(page); + } + + @Operation(summary = "农业需水-分页查询,供需平衡版") + @PostMapping("/rcpage") + public R> rcPage(@RequestBody RiceSupportBalanceCaculatePageSo pageSo){ + Page page = riceSupportBalanceService.rcPage(pageSo); + return R.ok(page); + } + +} diff --git a/src/main/java/com/gunshi/project/hsz/entity/RiceSupportMidCaculate.java b/src/main/java/com/gunshi/project/hsz/entity/RiceSupportMidCaculate.java new file mode 100644 index 0000000..b8dfc4e --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/entity/RiceSupportMidCaculate.java @@ -0,0 +1,21 @@ +package com.gunshi.project.hsz.entity; + +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 供需平衡分析参数计算中间值实体类 + */ +@Data +public class RiceSupportMidCaculate { + + private String name;//灌溉生长周期 + + private LocalDateTime startTime;// 开始时间 + private LocalDateTime endTime;//结束时间 + + private BigDecimal irrigationUse;//灌溉用水万m³ + +} diff --git a/src/main/java/com/gunshi/project/hsz/entity/dto/RiceSupportBalanceCaculateDto.java b/src/main/java/com/gunshi/project/hsz/entity/dto/RiceSupportBalanceCaculateDto.java new file mode 100644 index 0000000..91fab12 --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/entity/dto/RiceSupportBalanceCaculateDto.java @@ -0,0 +1,28 @@ +package com.gunshi.project.hsz.entity.dto; + +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Data +public class RiceSupportBalanceCaculateDto { + + + + + private String planName;//方案名称 + + private LocalDateTime startTime;//开始时间 + + private LocalDateTime endTime;//结束时间 + + private Long icId;//来水方案Id + + private Long rqId;//需水方案Id + + private BigDecimal ecoQ;//生态最小径流(单位m³/s) + + private String createName;//创建人 + +} diff --git a/src/main/java/com/gunshi/project/hsz/entity/so/RiceSupportBalanceCaculatePageSo.java b/src/main/java/com/gunshi/project/hsz/entity/so/RiceSupportBalanceCaculatePageSo.java new file mode 100644 index 0000000..f85f3d8 --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/entity/so/RiceSupportBalanceCaculatePageSo.java @@ -0,0 +1,21 @@ +package com.gunshi.project.hsz.entity.so; + +import com.gunshi.db.dto.PageSo; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class RiceSupportBalanceCaculatePageSo { + + + private PageSo pageSo; + + private LocalDateTime startTime; // 开始时间 + + private LocalDateTime endTime; // 结束时间 + + private String planName; // 计划名称 + + private Integer type; // 类型 0 长期 1短期 +} diff --git a/src/main/java/com/gunshi/project/hsz/mapper/RiceSupportBalanceDetailMapper.java b/src/main/java/com/gunshi/project/hsz/mapper/RiceSupportBalanceDetailMapper.java new file mode 100644 index 0000000..66e5ac6 --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/mapper/RiceSupportBalanceDetailMapper.java @@ -0,0 +1,10 @@ +package com.gunshi.project.hsz.mapper; + + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gunshi.project.hsz.model.RiceSupportBalanceDetail; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface RiceSupportBalanceDetailMapper extends BaseMapper { +} diff --git a/src/main/java/com/gunshi/project/hsz/mapper/RiceSupportBalanceMapper.java b/src/main/java/com/gunshi/project/hsz/mapper/RiceSupportBalanceMapper.java new file mode 100644 index 0000000..7ad7910 --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/mapper/RiceSupportBalanceMapper.java @@ -0,0 +1,9 @@ +package com.gunshi.project.hsz.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gunshi.project.hsz.model.RiceSupportBalance; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface RiceSupportBalanceMapper extends BaseMapper { +} diff --git a/src/main/java/com/gunshi/project/hsz/model/IcWaterForecast.java b/src/main/java/com/gunshi/project/hsz/model/IcWaterForecast.java index 409ac85..73c034d 100644 --- a/src/main/java/com/gunshi/project/hsz/model/IcWaterForecast.java +++ b/src/main/java/com/gunshi/project/hsz/model/IcWaterForecast.java @@ -91,6 +91,11 @@ public class IcWaterForecast implements Serializable { @Schema(description = "降雨相似年") private Integer year; + + @TableField(value = "hours") + @Schema(description = "小时") + private Integer hours; + @TableField(exist = false) private List details; } \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/model/IcWaterForecastDetail.java b/src/main/java/com/gunshi/project/hsz/model/IcWaterForecastDetail.java index 204e346..21a69d4 100644 --- a/src/main/java/com/gunshi/project/hsz/model/IcWaterForecastDetail.java +++ b/src/main/java/com/gunshi/project/hsz/model/IcWaterForecastDetail.java @@ -28,12 +28,12 @@ public class IcWaterForecastDetail implements Serializable { private Long icWaterId; @TableField(value = "start_time") - @Schema(description = "预测开始时间(长期)") + @Schema(description = "预测开始时间") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private LocalDateTime startTime; @TableField(value = "end_time") - @Schema(description = "预测结束时间(长期)") + @Schema(description = "预测结束时间") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private LocalDateTime endTime; diff --git a/src/main/java/com/gunshi/project/hsz/model/RiceGrowConfig.java b/src/main/java/com/gunshi/project/hsz/model/RiceGrowConfig.java index dbe5cf2..5170639 100644 --- a/src/main/java/com/gunshi/project/hsz/model/RiceGrowConfig.java +++ b/src/main/java/com/gunshi/project/hsz/model/RiceGrowConfig.java @@ -1,5 +1,6 @@ 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; @@ -29,7 +30,7 @@ public class RiceGrowConfig implements Serializable { /** * 主键 */ - @TableId(value = "id") + @TableId(value = "id",type = IdType.AUTO) @Schema(description = "主键") @JsonSerialize(using = ToStringSerializer.class) private Long id; diff --git a/src/main/java/com/gunshi/project/hsz/model/RiceIrrigationUse.java b/src/main/java/com/gunshi/project/hsz/model/RiceIrrigationUse.java index eb5150d..902d3c6 100644 --- a/src/main/java/com/gunshi/project/hsz/model/RiceIrrigationUse.java +++ b/src/main/java/com/gunshi/project/hsz/model/RiceIrrigationUse.java @@ -1,5 +1,6 @@ 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; @@ -27,7 +28,7 @@ public class RiceIrrigationUse implements Serializable { /** * 主键id */ - @TableId(value = "id") + @TableId(value = "id",type = IdType.AUTO) @Schema(description = "主键id") @JsonSerialize(using = ToStringSerializer.class) private Long id; diff --git a/src/main/java/com/gunshi/project/hsz/model/RiceRqWater.java b/src/main/java/com/gunshi/project/hsz/model/RiceRqWater.java index c729bdc..ffed03f 100644 --- a/src/main/java/com/gunshi/project/hsz/model/RiceRqWater.java +++ b/src/main/java/com/gunshi/project/hsz/model/RiceRqWater.java @@ -1,5 +1,6 @@ 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; @@ -14,6 +15,7 @@ import lombok.Data; import java.io.Serializable; import java.math.BigDecimal; +import java.time.LocalDateTime; import java.util.Date; import java.util.List; @@ -30,7 +32,7 @@ public class RiceRqWater implements Serializable { /** * 主键ID */ - @TableId(value = "id") + @TableId(value = "id",type = IdType.AUTO) @Schema(description = "主键ID") @JsonSerialize(using = ToStringSerializer.class) private Long id; @@ -56,7 +58,7 @@ public class RiceRqWater implements Serializable { @TableField(value = "create_time") @Schema(description = "制定时间") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") - private Date createTime; + private LocalDateTime createTime; /** * 制定人 diff --git a/src/main/java/com/gunshi/project/hsz/model/RiceSupportBalance.java b/src/main/java/com/gunshi/project/hsz/model/RiceSupportBalance.java index e467124..07ad589 100644 --- a/src/main/java/com/gunshi/project/hsz/model/RiceSupportBalance.java +++ b/src/main/java/com/gunshi/project/hsz/model/RiceSupportBalance.java @@ -1,5 +1,6 @@ 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; @@ -15,6 +16,7 @@ import lombok.Data; import java.io.Serializable; import java.math.BigDecimal; import java.time.LocalDateTime; +import java.util.List; @Data @TableName(value = "rice_support_balance") @@ -23,7 +25,7 @@ public class RiceSupportBalance implements Serializable { /** * 主键ID */ - @TableId(value = "id") + @TableId(value = "id",type = IdType.AUTO) @Schema(description = "主键ID") @JsonSerialize(using = ToStringSerializer.class) private Long id; @@ -101,4 +103,7 @@ public class RiceSupportBalance implements Serializable { @TableField(value = "ic_water_id") @Schema(description = "来水预测主键") private Long icWaterId; + + @TableField(exist = false) + private List details; } \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/model/RiceSupportBalanceDetail.java b/src/main/java/com/gunshi/project/hsz/model/RiceSupportBalanceDetail.java new file mode 100644 index 0000000..b459681 --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/model/RiceSupportBalanceDetail.java @@ -0,0 +1,71 @@ +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 com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Data +@TableName(value = "rice_support_balance_detail") +public class RiceSupportBalanceDetail implements Serializable { + + /** + * 主键ID + */ + @TableId(value = "id",type = IdType.AUTO) + @Schema(description = "主键ID") + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + /** + * 水稻支持平衡主表ID + */ + @TableField(value = "rice_support_id") + @Schema(description = "水稻支持平衡主表ID") + private Long riceSupportId; + + /** + * 时间 + */ + @TableField(value = "tm") + @Schema(description = "时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime tm; + + /** + * 灌溉水量(万m³)-需水量 + */ + @TableField(value = "irrigation_use") + @Schema(description = "灌溉水量(万m³)-需水量") + private BigDecimal irrigationUse; + + /** + * 灌溉水量(万m³)-计划供水量 + */ + @TableField(value = "irrigation_plan") + @Schema(description = "灌溉水量(万m³)-计划供水量") + private BigDecimal irrigationPlan; + + /** + * 生态水量(万m³)-需水量 + */ + @TableField(value = "eco_use") + @Schema(description = "生态水量(万m³)-需水量") + private BigDecimal ecoUse; + + /** + * 生态水量(万m³)-计划供水量 + */ + @TableField(value = "eco_plan") + @Schema(description = "生态水量(万m³)-计划供水量") + private BigDecimal ecoPlan; +} \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/model/RiceWaterForecastCycle.java b/src/main/java/com/gunshi/project/hsz/model/RiceWaterForecastCycle.java index 04a5f0f..eadbc6f 100644 --- a/src/main/java/com/gunshi/project/hsz/model/RiceWaterForecastCycle.java +++ b/src/main/java/com/gunshi/project/hsz/model/RiceWaterForecastCycle.java @@ -1,5 +1,6 @@ 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; @@ -27,7 +28,7 @@ public class RiceWaterForecastCycle implements Serializable { /** * 主键id */ - @TableId(value = "id") + @TableId(value = "id",type = IdType.AUTO) @Schema(description = "主键id") @JsonSerialize(using = ToStringSerializer.class) private Long id; diff --git a/src/main/java/com/gunshi/project/hsz/model/RiceWaterForecastMonth.java b/src/main/java/com/gunshi/project/hsz/model/RiceWaterForecastMonth.java index 28d1be3..e51a181 100644 --- a/src/main/java/com/gunshi/project/hsz/model/RiceWaterForecastMonth.java +++ b/src/main/java/com/gunshi/project/hsz/model/RiceWaterForecastMonth.java @@ -1,5 +1,6 @@ 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; @@ -27,7 +28,7 @@ public class RiceWaterForecastMonth implements Serializable { /** * 主键id */ - @TableId(value = "id") + @TableId(value = "id",type = IdType.AUTO) @Schema(description = "主键id") @JsonSerialize(using = ToStringSerializer.class) private Long id; diff --git a/src/main/java/com/gunshi/project/hsz/model/RiceWaterKi.java b/src/main/java/com/gunshi/project/hsz/model/RiceWaterKi.java index 196372b..c37dbac 100644 --- a/src/main/java/com/gunshi/project/hsz/model/RiceWaterKi.java +++ b/src/main/java/com/gunshi/project/hsz/model/RiceWaterKi.java @@ -1,5 +1,6 @@ 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; @@ -30,7 +31,7 @@ public class RiceWaterKi implements Serializable { /** * 主键 */ - @TableId(value = "id") + @TableId(value = "id",type = IdType.AUTO) @Schema(description = "主键") @JsonSerialize(using = ToStringSerializer.class) private Long id; diff --git a/src/main/java/com/gunshi/project/hsz/service/IcWaterForecastService.java b/src/main/java/com/gunshi/project/hsz/service/IcWaterForecastService.java index 172d3fc..dc8087f 100644 --- a/src/main/java/com/gunshi/project/hsz/service/IcWaterForecastService.java +++ b/src/main/java/com/gunshi/project/hsz/service/IcWaterForecastService.java @@ -56,6 +56,13 @@ public class IcWaterForecastService extends ServiceImpl { item.setIcWaterId(dto.getId()); @@ -66,6 +73,16 @@ public class IcWaterForecastService extends ServiceImpl pageQuery(IcWaterForecastPageSo pageSo) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); if (pageSo.getType() != null) { @@ -99,6 +116,13 @@ public class IcWaterForecastService extends ServiceImpl { item.setIcWaterId(dto.getId()); diff --git a/src/main/java/com/gunshi/project/hsz/service/RiceRqWaterService.java b/src/main/java/com/gunshi/project/hsz/service/RiceRqWaterService.java index 16e60ca..3cf77f7 100644 --- a/src/main/java/com/gunshi/project/hsz/service/RiceRqWaterService.java +++ b/src/main/java/com/gunshi/project/hsz/service/RiceRqWaterService.java @@ -74,11 +74,28 @@ public class RiceRqWaterService extends ServiceImpl riceWaterKis = dto.getRiceWaterKis(); List riceWaterForecastCycles = dto.getRiceWaterForecastCycles(); List riceWaterForecastMonths = dto.getRiceWaterForecastMonths(); + dto.setReqWater(riceGrowConfig.getIrrigationUse()); + dto.setCreateTime(LocalDateTime.now()); save(dto); riceGrowConfig.setRiceWaterId(dto.getId()); riceWaterKis.stream().forEach(o ->{ @@ -209,6 +226,7 @@ public class RiceRqWaterService extends ServiceImpl res = new ArrayList<>(); orderByStartTimeAsc(riceWaterKis); RiceGrowConfig riceGrowConfig = dto.getRiceGrowConfig(); + riceGrowConfig.setCycle(LocalDateTimeUtils.getTotalDayByRangeDate(riceWaterKis.getFirst().getStartTime(),riceWaterKis.getLast().getEndTime())); Integer year = riceGrowConfig.getYear();//相似年 List tyYearRainfallVos = tyYearRainfallService.queryList(); List collect = tyYearRainfallVos.stream().filter(o -> { @@ -599,6 +617,7 @@ public class RiceRqWaterService extends ServiceImpl { + public List selectByRCId(Long id) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(RiceSupportBalanceDetail::getRiceSupportId,id); + return this.baseMapper.selectList(queryWrapper); + } + + public void delByRcId(Long id) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(RiceSupportBalanceDetail::getRiceSupportId,id); + baseMapper.delete(queryWrapper); + } +} diff --git a/src/main/java/com/gunshi/project/hsz/service/RiceSupportBalanceService.java b/src/main/java/com/gunshi/project/hsz/service/RiceSupportBalanceService.java new file mode 100644 index 0000000..5c6bf56 --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/service/RiceSupportBalanceService.java @@ -0,0 +1,338 @@ +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.common.model.StRsvrRReal; +import com.gunshi.project.hsz.entity.RiceSupportMidCaculate; +import com.gunshi.project.hsz.entity.dto.RiceSupportBalanceCaculateDto; +import com.gunshi.project.hsz.entity.so.RiceSupportBalanceCaculatePageSo; +import com.gunshi.project.hsz.entity.vo.TyYearRainfallVo; +import com.gunshi.project.hsz.mapper.RiceSupportBalanceMapper; +import com.gunshi.project.hsz.model.*; +import com.gunshi.project.hsz.util.LocalDateTimeUtils; +import lombok.extern.slf4j.Slf4j; +import org.jodconverter.core.util.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicBoolean; + +@Service +@Slf4j +@Transactional(rollbackFor = Exception.class) +public class RiceSupportBalanceService extends ServiceImpl { + + @Autowired + private RiceRqWaterService riceRqWaterService; + + @Autowired + private RiceSupportBalanceDetailService riceSupportBalanceDetailService; + + @Autowired + private IcWaterForecastService icWaterForecastService; + + @Autowired + private AttResBaseService attResBaseService; //水库站点 + + @Autowired + private StZvarlBService stZvarlBService;//库容曲线 + + @Autowired + private StRsvrRRealService stRsvrRRealService; + + @Autowired + private TyYearRainfallService tyYearRainfallService;//降雨相似年资料 + + public AttResBase getAttResBase(){ + return attResBaseService.list().get(0); + } + + + public void caculateAndSave(RiceSupportBalanceCaculateDto dto) { + RiceRqWater riceRqWater = riceRqWaterService.queryById(dto.getRqId()); + IcWaterForecast icWaterForecast = icWaterForecastService.queryById(dto.getIcId()); + //获取生态每天生态需水量(万m³) + BigDecimal dailyEcoWaterUse; + dailyEcoWaterUse = dto.getEcoQ().multiply(new BigDecimal("3600").multiply(new BigDecimal("24"))); + dailyEcoWaterUse = dailyEcoWaterUse.divide(new BigDecimal("10000"));//转为万m³ + List allDaysByStartAndEndTime = LocalDateTimeUtils.getAllDaysByStartAndEndTime(dto.getStartTime(), dto.getEndTime()); + LocalDateTime today = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0).withNano(0); + BigDecimal totalIcWater = BigDecimal.ZERO;//总来水量 + AttResBase attResBase = getAttResBase(); + String stcd = attResBase.getStcd();//获取站点编码 + //获取死水位 + BigDecimal deadLev = attResBase.getDeadLev(); + StRsvrRReal stRsvrRReal = stRsvrRRealService.getBaseMapper().queryRzByStcd(stcd); + List list = stZvarlBService.lambdaQuery().orderByAsc(StZvarlB::getRz).list(); + BigDecimal w = stZvarlBService.getWByZvarl(list, stRsvrRReal.getRz());//获取库容 + BigDecimal deadW = stZvarlBService.getWByZvarl(list, deadLev);//死水位库容 + Integer year = icWaterForecast.getYear();//获取相似年 + if(dto.getStartTime().isAfter(today)){ + // 总来水量 = 当前~开始时间这一段时间的来水量 + 来回方案来水 + //方案来水量的时间范围 今天1号,开始时间4号,需要计算1-3号共3天 + Integer gapDay = LocalDateTimeUtils.getTotalDayByRangeDate(today, dto.getStartTime().minusDays(1)); // 注意:这里应该是到开始时间前一天 + //获取降雨相似年资料 + BigDecimal totalRainfallWater = BigDecimal.ZERO; + for (TyYearRainfallVo tyYearRainfallVo : tyYearRainfallService.queryList()) { + if (tyYearRainfallVo.getYear().equals(year)) { + List monthData = tyYearRainfallVo.getList(); + // 获取时间范围内的所有月份 + List months = LocalDateTimeUtils.getMonthsInPeriod(today, dto.getStartTime()); + for (Integer month : months) { + // 计算该月份在时间范围内的天数 + int daysInMonthForPeriod = LocalDateTimeUtils.calculateDaysInMonthForPeriod( + today, dto.getStartTime().minusDays(1), month + ); + if (daysInMonthForPeriod > 0) { + // 找到该月份的降雨资料 + for (TyYearRainfall monthDatum : monthData) { + if (monthDatum.getMonth().equals(month)) { + BigDecimal monthRainfall = monthDatum.getDrp(); + if (monthRainfall != null) { + int totalDaysInMonth = LocalDateTimeUtils.getTotalDaysInMonth( + today.getYear(), month + ); + // 该月份的平均日降雨量 + BigDecimal avgDailyRainfall = monthRainfall.divide( + new BigDecimal(totalDaysInMonth), 4, BigDecimal.ROUND_HALF_UP + ); + // 该月份在时间范围内的总降雨量 + BigDecimal monthRainfallInPeriod = avgDailyRainfall.multiply( + new BigDecimal(daysInMonthForPeriod) + ); + + totalRainfallWater = totalRainfallWater.add(monthRainfallInPeriod); + } + break; + } + } + } + } + break; + } + } + // 总来水量 = 当前到开始时间的降雨来水量 + 方案来水 + BigDecimal currentToStartWater = totalRainfallWater; // 这里假设totalRainfallWater就是需要的来水量 + totalIcWater = totalIcWater.add(currentToStartWater).add(icWaterForecast.getForecastWater()); // 将当前到开始时间的来水量加入总来水量 + + }else{ + // 总来水量 = 当前蓄水量 + 来水方案中的来水 + BigDecimal forecastWater = icWaterForecast.getForecastWater(); + totalIcWater = w.add(forecastWater); + } + BigDecimal totalNeedWater = BigDecimal.ZERO; + //获取总需水量(需水总量 + 每日生态用水量 * 天数) + totalNeedWater = riceRqWater.getReqWater().add(dailyEcoWaterUse.multiply(new BigDecimal(allDaysByStartAndEndTime.size()))); + //总计划供水量 + BigDecimal totalPlan; + if(totalIcWater.compareTo(totalNeedWater) > 0){ + //如果来水量大于需水量 + totalPlan = totalNeedWater; + }else{ + //总计划供水量 = (当前蓄水量 + 来水) - 死水位对应库容 + totalPlan = (w.add(totalIcWater)).subtract(deadW); + } + /** + * 需要优先保障每日生态供水 + * 比如 + * 总需水8000,生态需水100,灌溉7900 来水+蓄水 = 7500 + * 那么 生态供水100,灌溉供水7400,并且每日灌溉供水按“(蓄水+来水)/需水”的比例进行等比缩放 + */ + //获取灌溉用水周期参数 + List riceWaterForecastCycles = riceRqWater.getRiceWaterForecastCycles(); + List riceSupportMidCaculates = fillData(riceWaterForecastCycles, riceRqWater.getRiceWaterKis()); + // 先计算总灌溉需水量 + BigDecimal totalIrrigationNeed = BigDecimal.ZERO; + for (RiceSupportMidCaculate caculate : riceSupportMidCaculates) { + if (caculate.getIrrigationUse() != null) { + totalIrrigationNeed = totalIrrigationNeed.add(caculate.getIrrigationUse()); + } + } + + // 计算可供灌溉的生态水量 + BigDecimal totalWaterForIrrigation; + BigDecimal totalWaterForEco = dailyEcoWaterUse.multiply(new BigDecimal(allDaysByStartAndEndTime.size())); + // 如果来水量足够供应所有生态用水和灌溉用水 + if (totalPlan.compareTo(totalNeedWater) >= 0) { + // 充足,完全满足 + totalWaterForIrrigation = totalIrrigationNeed; + }else { + // 不足,优先保障生态用水,剩余给灌溉 + if (totalPlan.compareTo(totalWaterForEco) >= 0) { + // 生态用水能完全满足,剩余给灌溉 + totalWaterForIrrigation = totalPlan.subtract(totalWaterForEco); + } else { + // 连生态用水都不能完全满足 + totalWaterForIrrigation = BigDecimal.ZERO; + totalWaterForEco = totalPlan; // 实际生态供水量调整为可用的总量 + dailyEcoWaterUse = totalWaterForEco.divide( + new BigDecimal(allDaysByStartAndEndTime.size()), 4, BigDecimal.ROUND_HALF_UP + ); + } + } + + // 计算灌溉用水的缩放比例 + BigDecimal irrigationRatio; + if (totalIrrigationNeed.compareTo(BigDecimal.ZERO) > 0) { + irrigationRatio = totalWaterForIrrigation.divide(totalIrrigationNeed, 4, BigDecimal.ROUND_HALF_UP); + } else { + irrigationRatio = BigDecimal.ZERO; + } + //首先保存主表信息 + RiceSupportBalance riceSupportBalance = new RiceSupportBalance(); + riceSupportBalance.setRiceWaterId(dto.getRqId()); + riceSupportBalance.setIcWaterId(dto.getIcId()); + riceSupportBalance.setStartTime(dto.getStartTime()); + riceSupportBalance.setEndTime(dto.getEndTime()); + riceSupportBalance.setCreateTime(LocalDateTime.now()); + riceSupportBalance.setTotalSupport(totalPlan); + riceSupportBalance.setTotalCost(totalIrrigationNeed); + riceSupportBalance.setCreateName(dto.getCreateName()); + riceSupportBalance.setStatus(0); + this.save(riceSupportBalance); + // 创建final或effectively final的局部变量副本 + final Long mainId = riceSupportBalance.getId(); + final BigDecimal finalDailyEcoWaterUse = dailyEcoWaterUse; + final BigDecimal finalIrrigationRatio = irrigationRatio; + final List finalAllDays = new ArrayList<>(allDaysByStartAndEndTime); + final List finalRiceSupportMidCaculates = new ArrayList<>(riceSupportMidCaculates); + + // 在新线程中执行计算和保存 + new Thread(() -> { + try { + List saveDetails = new ArrayList<>(); + + for (LocalDateTime localDateTime : finalAllDays) { + RiceSupportBalanceDetail entity = new RiceSupportBalanceDetail(); + entity.setTm(localDateTime); + + // 查找当前日期属于哪个生长周期,计算灌溉需水量 + BigDecimal dailyIrrigationNeed = BigDecimal.ZERO; // 灌溉需水量 + for (RiceSupportMidCaculate caculate : finalRiceSupportMidCaculates) { + if (!localDateTime.isBefore(caculate.getStartTime()) && + !localDateTime.isAfter(caculate.getEndTime())) { + // 计算该生长周期的天数 + int daysInCycle = LocalDateTimeUtils.getTotalDayByRangeDate( + caculate.getStartTime(), caculate.getEndTime() + ); + + if (daysInCycle > 0 && caculate.getIrrigationUse() != null) { + // 该生长周期每天的灌溉需水量 + dailyIrrigationNeed = caculate.getIrrigationUse() + .divide(new BigDecimal(daysInCycle), 2, BigDecimal.ROUND_HALF_UP); + } + break; + } + } + + // 设置灌溉需水量 + entity.setIrrigationUse(dailyIrrigationNeed); + + // 按比例计算灌溉计划供水量 + BigDecimal dailyIrrigationPlan = dailyIrrigationNeed.multiply(finalIrrigationRatio); + entity.setIrrigationPlan(dailyIrrigationPlan); + + // 每日生态需水量 + entity.setEcoUse(finalDailyEcoWaterUse); + + // 每日生态计划供水量 + entity.setEcoPlan(finalDailyEcoWaterUse); + + // 设置主表关联ID + entity.setRiceSupportId(mainId); + saveDetails.add(entity); + } + + if(!saveDetails.isEmpty()){ + riceSupportBalanceDetailService.saveBatch(saveDetails); + log.info("成功保存水稻平衡供水明细,主表ID:{},明细数量:{}", + mainId, saveDetails.size()); + } + riceSupportBalance.setStatus(1); + updateById(riceSupportBalance); + } catch (Exception e) { + log.error("保存水稻平衡供水明细失败", e); + // 这里可以添加异常处理,比如记录日志、发送通知等 + } + }).start(); + +// 主线程立即返回,不等待明细计算完成 + log.info("水稻平衡供水主表已保存,明细计算正在异步执行"); + } + + public Page icPage(RiceSupportBalanceCaculatePageSo pageSo) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.le(IcWaterForecast::getStartTime,pageSo.getStartTime()); + queryWrapper.ge(IcWaterForecast::getEndTime,pageSo.getEndTime()); + if(pageSo.getType() != null){ + queryWrapper.eq(IcWaterForecast::getType, pageSo.getType()); + } + if(!StringUtils.isBlank(pageSo.getPlanName())){ + queryWrapper.like(IcWaterForecast::getPlanName, pageSo.getPlanName()); + } + Page icWaterForecastPage = icWaterForecastService.getBaseMapper().selectPage(pageSo.getPageSo().toPage(), queryWrapper); + return icWaterForecastPage; + } + + public Page rcPage(RiceSupportBalanceCaculatePageSo pageSo) { + List yearByRangeDate = LocalDateTimeUtils.getYearByRangeDate(pageSo.getStartTime(), pageSo.getEndTime()); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + if(!StringUtils.isBlank(pageSo.getPlanName())){ + queryWrapper.like(RiceRqWater::getPlanName, pageSo.getPlanName()); + } + queryWrapper.in(RiceRqWater::getYear, yearByRangeDate); + Page riceRqWaterPage = riceRqWaterService.getBaseMapper().selectPage(pageSo.getPageSo().toPage(), queryWrapper); + return riceRqWaterPage; + } + + private List fillData(List riceWaterForecastCycles, List riceWaterKis){ + List res = new ArrayList<>(); + for (RiceWaterKi riceWaterKi : riceWaterKis) { + RiceSupportMidCaculate entity = new RiceSupportMidCaculate(); + entity.setStartTime(riceWaterKi.getStartTime()); + entity.setEndTime(riceWaterKi.getEndTime()); + entity.setName(riceWaterKi.getRiceGrowStage()); + // 修正:查找匹配的灌溉用水数据 + Optional matchingCycle = riceWaterForecastCycles.stream() + .filter(cycle -> cycle.getRiceGrowStage().equals(riceWaterKi.getRiceGrowStage())) + .findFirst(); + + // 根据是否找到匹配设置灌溉用水 + if (matchingCycle.isPresent()) { + // 假设RiceWaterForecastCycle中有getIrrigationUse方法 + entity.setIrrigationUse(matchingCycle.get().getIrrigationUse()); + } else { + // 如果没有匹配的,设置默认值或null + entity.setIrrigationUse(BigDecimal.ZERO); // 或者BigDecimal.ZERO等默认值 + } + res.add(entity); + } + return res; + } + + public Page queryPage(RiceSupportBalanceCaculatePageSo page) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + if(!StringUtils.isBlank(page.getPlanName())){ + queryWrapper.like(RiceSupportBalance::getPlanName, page.getPlanName()); + } + Page riceSupportBalancePage = this.baseMapper.selectPage(page.getPageSo().toPage(), queryWrapper); + for (RiceSupportBalance record : riceSupportBalancePage.getRecords()) { + List details = riceSupportBalanceDetailService.selectByRCId(record.getId()); + record.setDetails(details); + } + return riceSupportBalancePage; + } + + public boolean delData(Long id) { + riceSupportBalanceDetailService.delByRcId(id); + boolean flag = removeById(id); + return flag; + } +} diff --git a/src/main/java/com/gunshi/project/hsz/util/LocalDateTimeUtils.java b/src/main/java/com/gunshi/project/hsz/util/LocalDateTimeUtils.java index 67d4b6a..891c040 100644 --- a/src/main/java/com/gunshi/project/hsz/util/LocalDateTimeUtils.java +++ b/src/main/java/com/gunshi/project/hsz/util/LocalDateTimeUtils.java @@ -2,7 +2,10 @@ package com.gunshi.project.hsz.util; import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.IntStream; public class LocalDateTimeUtils { @@ -99,6 +102,94 @@ public class LocalDateTimeUtils { return months; } + /** + * 根据传入的时间范围,获取所有天数,从小到大排列 + * + * @param startTime 开始时间(包含) + * @param endTime 结束时间(包含) + * @return 时间范围内的所有天数列表 + */ + public static List getAllDaysByStartAndEndTime(LocalDateTime startTime, LocalDateTime endTime) { + // 1. 参数校验 + if (startTime == null || endTime == null) { + throw new IllegalArgumentException("开始时间和结束时间不能为空"); + } + + if (startTime.isAfter(endTime)) { + throw new IllegalArgumentException("开始时间不能晚于结束时间"); + } + + List result = new ArrayList<>(); + + // 2. 获取开始日期的0点 + LocalDateTime currentDay = startTime.toLocalDate().atStartOfDay(); + LocalDateTime endDay = endTime.toLocalDate().atStartOfDay(); + + // 3. 循环添加每一天 + while (!currentDay.isAfter(endDay)) { + result.add(currentDay); + currentDay = currentDay.plusDays(1); + } + + return result; + } + + /** + * 根据时间范围获取包含的所有年份 + * @param startTime 起始时间 + * @param endTime 结束时间 + * @return 年份列表(升序) + */ + public static List getYearByRangeDate(LocalDateTime startTime, LocalDateTime endTime) { + if (startTime == null || endTime == null) { + throw new IllegalArgumentException("开始时间和结束时间不能为空"); + } + + if (startTime.isAfter(endTime)) { + throw new IllegalArgumentException("开始时间不能晚于结束时间"); + } + + int startYear = startTime.getYear(); + int endYear = endTime.getYear(); + + // 使用Stream生成年份列表 + return IntStream.rangeClosed(startYear, endYear) + .boxed() + .collect(Collectors.toList()); + } + + /** + * 根据开始时间和结束时间,计算时间间隔内的总天数 + * 包含开始日期和结束日期(两头都算) + * + * @param startTime 开始时间 + * @param endTime 结束时间 + * @return 总天数(包含起止日) + */ + public static Integer getTotalDayByRangeDate(LocalDateTime startTime, LocalDateTime endTime) { + if (startTime == null || endTime == null) { + throw new IllegalArgumentException("开始时间和结束时间不能为空"); + } + + if (startTime.isAfter(endTime)) { + throw new IllegalArgumentException("开始时间不能晚于结束时间"); + } + + // 转换为LocalDate,忽略时间部分 + LocalDate startDate = startTime.toLocalDate(); + LocalDate endDate = endTime.toLocalDate(); + + // 使用ChronoUnit.DAYS.between计算天数差,+1表示包含起止日 + long days = ChronoUnit.DAYS.between(startDate, endDate) + 1; + + // 转换为Integer,注意数值范围检查 + if (days > Integer.MAX_VALUE) { + throw new ArithmeticException("天数超出Integer范围"); + } + + return (int) days; + } + }