From cfd8dda8700415b69de217c0afee64d4110ab06b Mon Sep 17 00:00:00 2001 From: yangzhe123 <2824096059@qq.com> Date: Mon, 17 Nov 2025 09:21:51 +0800 Subject: [PATCH] =?UTF-8?q?=E9=A2=84=E6=8A=A5-=E8=B0=83=E5=BA=A6=E6=96=B9?= =?UTF-8?q?=E6=A1=88=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ForecastDispatchPlanController.java | 59 +++ .../entity/so/ForecastDispatchPlanPageSo.java | 16 + .../mapper/ForecastDispatchCommandMapper.java | 15 + .../mapper/ForecastDispatchPlanMapper.java | 15 + .../mapper/ForecastDispatchResultMapper.java | 16 + .../hsz/model/ForecastDispatchCommand.java | 86 +++++ .../hsz/model/ForecastDispatchPlan.java | 99 +++++ .../hsz/model/ForecastDispatchResult.java | 101 +++++ .../ForecastDispatchCommandService.java | 20 + .../service/ForecastDispatchPlanService.java | 345 ++++++++++++++++++ .../ForecastDispatchResultService.java | 20 + 11 files changed, 792 insertions(+) create mode 100644 src/main/java/com/gunshi/project/hsz/controller/ForecastDispatchPlanController.java create mode 100644 src/main/java/com/gunshi/project/hsz/entity/so/ForecastDispatchPlanPageSo.java create mode 100644 src/main/java/com/gunshi/project/hsz/mapper/ForecastDispatchCommandMapper.java create mode 100644 src/main/java/com/gunshi/project/hsz/mapper/ForecastDispatchPlanMapper.java create mode 100644 src/main/java/com/gunshi/project/hsz/mapper/ForecastDispatchResultMapper.java create mode 100644 src/main/java/com/gunshi/project/hsz/model/ForecastDispatchCommand.java create mode 100644 src/main/java/com/gunshi/project/hsz/model/ForecastDispatchPlan.java create mode 100644 src/main/java/com/gunshi/project/hsz/model/ForecastDispatchResult.java create mode 100644 src/main/java/com/gunshi/project/hsz/service/ForecastDispatchCommandService.java create mode 100644 src/main/java/com/gunshi/project/hsz/service/ForecastDispatchPlanService.java create mode 100644 src/main/java/com/gunshi/project/hsz/service/ForecastDispatchResultService.java diff --git a/src/main/java/com/gunshi/project/hsz/controller/ForecastDispatchPlanController.java b/src/main/java/com/gunshi/project/hsz/controller/ForecastDispatchPlanController.java new file mode 100644 index 0000000..c372933 --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/controller/ForecastDispatchPlanController.java @@ -0,0 +1,59 @@ +package com.gunshi.project.hsz.controller; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.gunshi.core.result.R; +import com.gunshi.project.hsz.entity.so.CommonDataPageSo; +import com.gunshi.project.hsz.entity.so.ForecastDispatchPlanPageSo; +import com.gunshi.project.hsz.model.ForecastDispatchPlan; +import com.gunshi.project.hsz.model.ForecastK; +import com.gunshi.project.hsz.service.ForecastDispatchPlanService; +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.util.List; + + +@Tag(name = "预报-调度方案管理") +@RestController +@RequestMapping(value="/forecastDispatchPlan") +public class ForecastDispatchPlanController { + + @Autowired + private ForecastDispatchPlanService forecastDispatchPlanService; + + @Operation(summary = "插入") + @PostMapping("/insert") + public R insert(@RequestBody ForecastDispatchPlan dto) { + return R.ok(forecastDispatchPlanService.saveData(dto)); + } + + @Operation(summary = "分页") + @PostMapping("/page") + public R> page(@RequestBody @Validated ForecastDispatchPlanPageSo pageSo) { + return R.ok(forecastDispatchPlanService.pageDetail(pageSo)); + } + + @Operation(summary = "删除") + @PostMapping("/delete/{id}") + public R delete(@Schema(name = "id") @PathVariable Serializable id) { + return R.ok(forecastDispatchPlanService.deleteById(id)); + } + + @Operation(summary = "导出") + @PostMapping("/export") + public void export(@RequestBody @Validated ForecastDispatchPlanPageSo page, HttpServletResponse response) { + page.getPageSo().setPageSize(90000); + Page forecastDispatchPlanPage = forecastDispatchPlanService.pageDetail(page); + List records = forecastDispatchPlanPage.getRecords(); + forecastDispatchPlanService.export(records,response); + } +} diff --git a/src/main/java/com/gunshi/project/hsz/entity/so/ForecastDispatchPlanPageSo.java b/src/main/java/com/gunshi/project/hsz/entity/so/ForecastDispatchPlanPageSo.java new file mode 100644 index 0000000..4651b0a --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/entity/so/ForecastDispatchPlanPageSo.java @@ -0,0 +1,16 @@ +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 ForecastDispatchPlanPageSo { + @NotNull(message = "分页参数不能为空") + @Schema(description = "分页参数") + private PageSo pageSo; + + + private String planName; +} diff --git a/src/main/java/com/gunshi/project/hsz/mapper/ForecastDispatchCommandMapper.java b/src/main/java/com/gunshi/project/hsz/mapper/ForecastDispatchCommandMapper.java new file mode 100644 index 0000000..e29d4b5 --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/mapper/ForecastDispatchCommandMapper.java @@ -0,0 +1,15 @@ +package com.gunshi.project.hsz.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gunshi.project.hsz.model.ForecastDispatchCommand; +import org.apache.ibatis.annotations.Mapper; + +/** + * 描述: 调度指令表 + * author: xusan + * date: 2024-12-19 + */ +@Mapper +public interface ForecastDispatchCommandMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/mapper/ForecastDispatchPlanMapper.java b/src/main/java/com/gunshi/project/hsz/mapper/ForecastDispatchPlanMapper.java new file mode 100644 index 0000000..668d139 --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/mapper/ForecastDispatchPlanMapper.java @@ -0,0 +1,15 @@ +package com.gunshi.project.hsz.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gunshi.project.hsz.model.ForecastDispatchPlan; +import org.apache.ibatis.annotations.Mapper; + +/** + * 描述: 调度方案主表 + * author: xusan + * date: 2024-12-19 + */ +@Mapper +public interface ForecastDispatchPlanMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/mapper/ForecastDispatchResultMapper.java b/src/main/java/com/gunshi/project/hsz/mapper/ForecastDispatchResultMapper.java new file mode 100644 index 0000000..138c22d --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/mapper/ForecastDispatchResultMapper.java @@ -0,0 +1,16 @@ +package com.gunshi.project.hsz.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +import com.gunshi.project.hsz.model.ForecastDispatchResult; +import org.apache.ibatis.annotations.Mapper; + +/** + * 描述: 调度结果表 + * author: xusan + * date: 2024-12-19 + */ +@Mapper +public interface ForecastDispatchResultMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/model/ForecastDispatchCommand.java b/src/main/java/com/gunshi/project/hsz/model/ForecastDispatchCommand.java new file mode 100644 index 0000000..48d3780 --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/model/ForecastDispatchCommand.java @@ -0,0 +1,86 @@ +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 com.gunshi.project.hsz.common.validate.markers.Update; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * 描述: 调度指令表 + * author: xusan + * date: 2024-12-19 + */ +@Schema(description = "调度指令表") +@Data +@TableName("public.forecast_dispatch_command") +public class ForecastDispatchCommand implements Serializable { + + public final static String THIS_TABLE_NAME = "forecast_dispatch_command"; + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @TableId(value = "id", type = IdType.AUTO) + @Schema(description = "主键") + @NotNull(message = "id不能为空", groups = {Update.class}) + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + /** + * 调度方案ID + */ + @TableField(value = "plan_id") + @Schema(description = "调度方案ID") + @NotNull(message = "调度方案ID不能为空") + @JsonSerialize(using = ToStringSerializer.class) + private Long planId; + + /** + * 指令时间 + */ + @TableField(value = "command_time") + @Schema(description = "指令时间") + @NotNull(message = "指令时间不能为空") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime commandTime; + + /** + * 泄洪闸(0:关, 1:开) + */ + @TableField(value = "flood_gate") + @Schema(description = "泄洪闸(0:关, 1:开)") + private Integer floodGate; + + /** + * 节制闸(0:关, 1:开) + */ + @TableField(value = "control_gate") + @Schema(description = "节制闸(0:关, 1:开)") + private Integer controlGate; + + /** + * 分水闸(0:关, 1:开) + */ + @TableField(value = "diversion_gate") + @Schema(description = "分水闸(0:关, 1:开)") + private Integer diversionGate; + + /** + * 输水灌溉闸(0:关, 1:开) + */ + @TableField(value = "irrigation_gate") + @Schema(description = "输水灌溉闸(0:关, 1:开)") + private Integer irrigationGate; +} \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/model/ForecastDispatchPlan.java b/src/main/java/com/gunshi/project/hsz/model/ForecastDispatchPlan.java new file mode 100644 index 0000000..1d4873a --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/model/ForecastDispatchPlan.java @@ -0,0 +1,99 @@ +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 com.gunshi.project.hsz.common.validate.markers.Update; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.List; + +/** + * 描述: 调度方案主表 + * author: xusan + * date: 2024-12-19 + */ +@Schema(description = "调度方案主表") +@Data +@TableName("public.forecast_dispatch_plan") +public class ForecastDispatchPlan implements Serializable { + + public final static String THIS_TABLE_NAME = "forecast_dispatch_plan"; + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @TableId(value = "id", type = IdType.AUTO) + @Schema(description = "主键") + @NotNull(message = "id不能为空", groups = {Update.class}) + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + /** + * 方案名称 + */ + @TableField(value = "plan_name") + @Schema(description = "方案名称") + @Size(max = 255, message = "方案名称最大长度要小于 255") + @NotNull(message = "方案名称不能为空") + private String planName; + + /** + * 开始时间 + */ + @TableField(value = "start_time") + @Schema(description = "开始时间") + @NotNull(message = "开始时间不能为空") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime startTime; + + /** + * 结束时间 + */ + @TableField(value = "end_time") + @Schema(description = "结束时间") + @NotNull(message = "结束时间不能为空") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime endTime; + + /** + * 制定时间 + */ + @TableField(value = "create_time") + @Schema(description = "制定时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime createTime; + + /** + * 制定人 + */ + @TableField(value = "creator") + @Schema(description = "制定人") + @Size(max = 100, message = "制定人最大长度要小于 100") + private String creator; + + /** + * 水库控制水位(m) + */ + @TableField(value = "reservoir_control_level") + @Schema(description = "水库控制水位(m)") + @NotNull(message = "水库控制水位不能为空") + private java.math.BigDecimal reservoirControlLevel; + + @TableField(exist = false) + private ForecastDispatchResult forecastDispatchResult; + + @TableField(exist = false) + private List forecastDispatchCommands; +} \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/model/ForecastDispatchResult.java b/src/main/java/com/gunshi/project/hsz/model/ForecastDispatchResult.java new file mode 100644 index 0000000..9e7425f --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/model/ForecastDispatchResult.java @@ -0,0 +1,101 @@ +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 com.gunshi.project.hsz.common.validate.markers.Update; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * 描述: 调度结果表 + * author: xusan + * date: 2024-12-19 + */ +@Schema(description = "调度结果表") +@Data +@TableName("public.forecast_dispatch_result") +public class ForecastDispatchResult implements Serializable { + + public final static String THIS_TABLE_NAME = "forecast_dispatch_result"; + + private static final long serialVersionUID = 1L; + + /** + * 主键 + */ + @TableId(value = "id", type = IdType.AUTO) + @Schema(description = "主键") + @NotNull(message = "id不能为空", groups = {Update.class}) + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + /** + * 调度方案ID + */ + @TableField(value = "plan_id") + @Schema(description = "调度方案ID") + @NotNull(message = "调度方案ID不能为空") + @JsonSerialize(using = ToStringSerializer.class) + private Long planId; + + /** + * 最大入库流量(m³/s) + */ + @TableField(value = "max_inflow") + @Schema(description = "最大入库流量(m³/s)") + @NotNull(message = "最大入库流量不能为空") + private java.math.BigDecimal maxInflow; + + /** + * 总入库水量(万m³) + */ + @TableField(value = "total_inflow_volume") + @Schema(description = "总入库水量(万m³)") + private java.math.BigDecimal totalInflowVolume; + + /** + * 总出库水量(万m³) + */ + @TableField(value = "total_outflow_volume") + @Schema(description = "总出库水量(万m³)") + private java.math.BigDecimal totalOutflowVolume; + + /** + * 最高库水位(m) + */ + @TableField(value = "max_reservoir_level") + @Schema(description = "最高库水位(m)") + private java.math.BigDecimal maxReservoirLevel; + + /** + * 超汛限水位值(m) + */ + @TableField(value = "exceed_limit_value") + @Schema(description = "超汛限水位值(m)") + private java.math.BigDecimal exceedLimitValue; + + /** + * 超汛限开始时间 + */ + @TableField(value = "exceed_limit_start") + @Schema(description = "超汛限开始时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime exceedLimitStart; + + /** + * 超汛限结束时间 + */ + @TableField(value = "exceed_limit_end") + @Schema(description = "超汛限结束时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime exceedLimitEnd; +} \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/service/ForecastDispatchCommandService.java b/src/main/java/com/gunshi/project/hsz/service/ForecastDispatchCommandService.java new file mode 100644 index 0000000..17fc278 --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/service/ForecastDispatchCommandService.java @@ -0,0 +1,20 @@ +package com.gunshi.project.hsz.service; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gunshi.project.hsz.mapper.ForecastDispatchCommandMapper; +import com.gunshi.project.hsz.model.ForecastDispatchCommand; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * 描述: 调度指令表 + * author: xusan + * date: 2024-12-19 + */ +@Service +@Slf4j +@Transactional(rollbackFor = Exception.class) +public class ForecastDispatchCommandService extends ServiceImpl { + +} \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/service/ForecastDispatchPlanService.java b/src/main/java/com/gunshi/project/hsz/service/ForecastDispatchPlanService.java new file mode 100644 index 0000000..f22c9da --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/service/ForecastDispatchPlanService.java @@ -0,0 +1,345 @@ +package com.gunshi.project.hsz.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gunshi.project.hsz.entity.so.ForecastDispatchPlanPageSo; +import com.gunshi.project.hsz.mapper.ForecastDispatchPlanMapper; +import com.gunshi.project.hsz.model.ForecastDispatchCommand; +import com.gunshi.project.hsz.model.ForecastDispatchPlan; +import com.gunshi.project.hsz.model.ForecastDispatchResult; +import com.ruoyi.common.utils.StringUtils; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.Serializable; +import java.net.URLEncoder; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.List; + +/** + * 描述: 调度方案主表 + * author: xusan + * date: 2024-12-19 + */ +@Service +@Slf4j +@Transactional(rollbackFor = Exception.class) +public class ForecastDispatchPlanService extends ServiceImpl { + + @Autowired + private ForecastDispatchPlanMapper forecastDispatchPlanMapper; + + @Autowired + private ForecastDispatchResultService forecastDispatchResultService; + + @Autowired + private ForecastDispatchCommandService forecastDispatchCommandService; + + public Page pageDetail(ForecastDispatchPlanPageSo pageSo) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + if(!StringUtils.isBlank(pageSo.getPlanName())){ + queryWrapper.like(ForecastDispatchPlan::getPlanName, pageSo.getPlanName()); + } + Page forecastDispatchPlanPage = this.baseMapper.selectPage(pageSo.getPageSo().toPage(), queryWrapper); + for (ForecastDispatchPlan record : forecastDispatchPlanPage.getRecords()) { + List forecastDispatchCommandList = forecastDispatchCommandService.lambdaQuery().eq(ForecastDispatchCommand::getPlanId, record.getId()).list(); + record.setForecastDispatchCommands(forecastDispatchCommandList); + ForecastDispatchResult forecastDispatchResult = forecastDispatchResultService.lambdaQuery().eq(ForecastDispatchResult::getPlanId, record.getId()).one(); + record.setForecastDispatchResult(forecastDispatchResult); + } + return forecastDispatchPlanPage; + } + + public Boolean deleteById(Serializable id) { + boolean flag = removeById(id); + if(flag){ + LambdaQueryChainWrapper eq = forecastDispatchResultService.lambdaQuery().eq(ForecastDispatchResult::getPlanId, id); + boolean remove = forecastDispatchResultService.remove(eq); + LambdaQueryChainWrapper eq2 = forecastDispatchCommandService.lambdaQuery().eq(ForecastDispatchCommand::getPlanId, id); + boolean remove2 = forecastDispatchCommandService.remove(eq2); + } + return true; + } + + public Boolean saveData(ForecastDispatchPlan dto) { + ForecastDispatchResult forecastDispatchResult = dto.getForecastDispatchResult(); + List forecastDispatchCommands = dto.getForecastDispatchCommands(); + save(dto); + forecastDispatchResult.setPlanId(dto.getId()); + forecastDispatchCommands.stream().forEach(o ->{ + o.setPlanId(dto.getId()); + }); + forecastDispatchResultService.save(forecastDispatchResult); + forecastDispatchCommandService.saveBatch(forecastDispatchCommands); + return true; + } + + public void export(List page, HttpServletResponse response) { + try { + // 设置响应头 + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + response.setCharacterEncoding("utf-8"); + String fileName = URLEncoder.encode("调度方案数据导出", "UTF-8").replaceAll("\\+", "%20"); + response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); + + // 创建Excel工作簿 + Workbook workbook = new XSSFWorkbook(); + + // 创建单元格样式 + CellStyle headerStyle = createHeaderStyle(workbook); + CellStyle dataStyle = createDataStyle(workbook); + CellStyle titleStyle = createTitleStyle(workbook); + + // 在同一个Sheet页中按方案分组导出数据 + exportGroupedData(workbook, page, headerStyle, dataStyle, titleStyle); + + // 写入响应流 + workbook.write(response.getOutputStream()); + workbook.close(); + } catch (Exception e) { + log.error("导出Excel失败", e); + throw new RuntimeException("导出失败"); + } + } + + /** + * 按方案分组导出数据 + */ + private void exportGroupedData(Workbook workbook, List dataList, CellStyle headerStyle, CellStyle dataStyle, CellStyle titleStyle) { + Sheet sheet = workbook.createSheet("调度方案数据"); + + int currentRow = 0; + + for (ForecastDispatchPlan plan : dataList) { + // 1. 导出调度方案基本信息 + currentRow = exportPlanBasicInfo(sheet, currentRow, plan, titleStyle, dataStyle); + + // 2. 导出调度结果 + currentRow = exportPlanResult(sheet, currentRow, plan, headerStyle, dataStyle); + + // 3. 导出调度指令 + currentRow = exportPlanCommands(sheet, currentRow, plan, headerStyle, dataStyle); + + // 添加空行分隔不同方案 + currentRow += 2; + } + } + + /** + * 导出调度方案基本信息 + */ + private int exportPlanBasicInfo(Sheet sheet, int startRow, ForecastDispatchPlan plan, CellStyle titleStyle, CellStyle dataStyle) { + // 方案标题 + Row titleRow = sheet.createRow(startRow++); + Cell titleCell = titleRow.createCell(0); + titleCell.setCellValue("调度方案:" + getStringValue(plan.getPlanName())); + titleCell.setCellStyle(titleStyle); + + // 基本信息表头 + Row headerRow = sheet.createRow(startRow++); + String[] headers = {"开始时间", "结束时间", "制定时间", "制定人", "水库控制水位(m)"}; + for (int i = 0; i < headers.length; i++) { + Cell cell = headerRow.createCell(i); + cell.setCellValue(headers[i]); + cell.setCellStyle(dataStyle); + sheet.setColumnWidth(i, 5000); + } + + // 基本信息数据 + Row dataRow = sheet.createRow(startRow++); + int colNum = 0; + dataRow.createCell(colNum++).setCellValue(formatDateTime(plan.getStartTime())); + dataRow.createCell(colNum++).setCellValue(formatDateTime(plan.getEndTime())); + dataRow.createCell(colNum++).setCellValue(formatDateTime(plan.getCreateTime())); + dataRow.createCell(colNum++).setCellValue(getStringValue(plan.getCreator())); + dataRow.createCell(colNum).setCellValue(plan.getReservoirControlLevel() != null ? + plan.getReservoirControlLevel().doubleValue() : 0); + + // 设置数据行样式 + for (int i = 0; i < headers.length; i++) { + dataRow.getCell(i).setCellStyle(dataStyle); + } + + return startRow; + } + + /** + * 导出调度结果 + */ + private int exportPlanResult(Sheet sheet, int startRow, ForecastDispatchPlan plan, CellStyle headerStyle, CellStyle dataStyle) { + ForecastDispatchResult result = plan.getForecastDispatchResult(); + if (result == null) { + return startRow; + } + + // 结果标题 + Row resultTitleRow = sheet.createRow(startRow++); + Cell resultTitleCell = resultTitleRow.createCell(0); + resultTitleCell.setCellValue("调度结果"); + resultTitleCell.setCellStyle(headerStyle); + + // 结果表头 + Row resultHeaderRow = sheet.createRow(startRow++); + String[] resultHeaders = { + "最大入库流量(m³/s)", "总入库水量(万m³)", "总出库水量(万m³)", + "最高库水位(m)", "超汛限水位值(m)", "超汛限开始时间", "超汛限结束时间" + }; + for (int i = 0; i < resultHeaders.length; i++) { + Cell cell = resultHeaderRow.createCell(i); + cell.setCellValue(resultHeaders[i]); + cell.setCellStyle(headerStyle); + sheet.setColumnWidth(i, 5000); + } + + // 结果数据 + Row resultDataRow = sheet.createRow(startRow++); + int colNum = 0; + resultDataRow.createCell(colNum++).setCellValue(result.getMaxInflow() != null ? + result.getMaxInflow().doubleValue() : 0); + resultDataRow.createCell(colNum++).setCellValue(result.getTotalInflowVolume() != null ? + result.getTotalInflowVolume().doubleValue() : 0); + resultDataRow.createCell(colNum++).setCellValue(result.getTotalOutflowVolume() != null ? + result.getTotalOutflowVolume().doubleValue() : 0); + resultDataRow.createCell(colNum++).setCellValue(result.getMaxReservoirLevel() != null ? + result.getMaxReservoirLevel().doubleValue() : 0); + resultDataRow.createCell(colNum++).setCellValue(result.getExceedLimitValue() != null ? + result.getExceedLimitValue().doubleValue() : 0); + resultDataRow.createCell(colNum++).setCellValue(formatDateTime(result.getExceedLimitStart())); + resultDataRow.createCell(colNum).setCellValue(formatDateTime(result.getExceedLimitEnd())); + + // 设置数据行样式 + for (int i = 0; i < resultHeaders.length; i++) { + resultDataRow.getCell(i).setCellStyle(dataStyle); + } + + return startRow; + } + + /** + * 导出调度指令 + */ + private int exportPlanCommands(Sheet sheet, int startRow, ForecastDispatchPlan plan, CellStyle headerStyle, CellStyle dataStyle) { + List commands = plan.getForecastDispatchCommands(); + if (commands == null || commands.isEmpty()) { + return startRow; + } + + // 指令标题 + Row commandTitleRow = sheet.createRow(startRow++); + Cell commandTitleCell = commandTitleRow.createCell(0); + commandTitleCell.setCellValue("调度指令"); + commandTitleCell.setCellStyle(headerStyle); + + // 指令表头 + Row commandHeaderRow = sheet.createRow(startRow++); + String[] commandHeaders = { + "指令时间", "泄洪闸", "节制闸", "分水闸", "输水灌溉闸" + }; + for (int i = 0; i < commandHeaders.length; i++) { + Cell cell = commandHeaderRow.createCell(i); + cell.setCellValue(commandHeaders[i]); + cell.setCellStyle(headerStyle); + sheet.setColumnWidth(i, 5000); + } + + // 指令数据 + for (ForecastDispatchCommand command : commands) { + Row commandDataRow = sheet.createRow(startRow++); + int colNum = 0; + commandDataRow.createCell(colNum++).setCellValue(formatDateTime(command.getCommandTime())); + commandDataRow.createCell(colNum++).setCellValue(getGateStatus(command.getFloodGate())); + commandDataRow.createCell(colNum++).setCellValue(getGateStatus(command.getControlGate())); + commandDataRow.createCell(colNum++).setCellValue(getGateStatus(command.getDiversionGate())); + commandDataRow.createCell(colNum).setCellValue(getGateStatus(command.getIrrigationGate())); + + // 设置数据行样式 + for (int i = 0; i < commandHeaders.length; i++) { + commandDataRow.getCell(i).setCellStyle(dataStyle); + } + } + + return startRow; + } + + /** + * 创建标题样式 + */ + private CellStyle createTitleStyle(Workbook workbook) { + CellStyle style = workbook.createCellStyle(); + Font font = workbook.createFont(); + font.setBold(true); + font.setFontHeightInPoints((short) 14); + style.setFont(font); + return style; + } + + /** + * 创建表头样式 + */ + private CellStyle createHeaderStyle(Workbook workbook) { + CellStyle style = workbook.createCellStyle(); + Font font = workbook.createFont(); + font.setBold(true); + font.setFontHeightInPoints((short) 12); + style.setFont(font); + style.setAlignment(HorizontalAlignment.CENTER); + style.setVerticalAlignment(VerticalAlignment.CENTER); + style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); + style.setFillPattern(FillPatternType.SOLID_FOREGROUND); + style.setBorderTop(BorderStyle.THIN); + style.setBorderBottom(BorderStyle.THIN); + style.setBorderLeft(BorderStyle.THIN); + style.setBorderRight(BorderStyle.THIN); + return style; + } + + /** + * 创建数据样式 + */ + private CellStyle createDataStyle(Workbook workbook) { + CellStyle style = workbook.createCellStyle(); + style.setAlignment(HorizontalAlignment.LEFT); + style.setVerticalAlignment(VerticalAlignment.CENTER); + style.setBorderTop(BorderStyle.THIN); + style.setBorderBottom(BorderStyle.THIN); + style.setBorderLeft(BorderStyle.THIN); + style.setBorderRight(BorderStyle.THIN); + return style; + } + + /** + * 格式化时间 + */ + private String formatDateTime(LocalDateTime dateTime) { + if (dateTime == null) { + return ""; + } + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + return dateTime.format(formatter); + } + + /** + * 获取字符串值 + */ + private String getStringValue(String value) { + return value == null ? "" : value; + } + + /** + * 获取闸门状态文字 + */ + private String getGateStatus(Integer status) { + if (status == null) { + return "关"; + } + return status == 1 ? "开" : "关"; + } +} \ No newline at end of file diff --git a/src/main/java/com/gunshi/project/hsz/service/ForecastDispatchResultService.java b/src/main/java/com/gunshi/project/hsz/service/ForecastDispatchResultService.java new file mode 100644 index 0000000..251a8ab --- /dev/null +++ b/src/main/java/com/gunshi/project/hsz/service/ForecastDispatchResultService.java @@ -0,0 +1,20 @@ +package com.gunshi.project.hsz.service; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.gunshi.project.hsz.mapper.ForecastDispatchResultMapper; +import com.gunshi.project.hsz.model.ForecastDispatchResult; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * 描述: 调度结果表 + * author: xusan + * date: 2024-12-19 + */ +@Service +@Slf4j +@Transactional(rollbackFor = Exception.class) +public class ForecastDispatchResultService extends ServiceImpl { + +} \ No newline at end of file