洪水预报-预报方案管理-PDF导出
parent
154a9e51d1
commit
a9466ce01b
13
pom.xml
13
pom.xml
|
|
@ -54,6 +54,19 @@
|
||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.itextpdf</groupId>
|
||||||
|
<artifactId>itext7-core</artifactId>
|
||||||
|
<version>7.2.5</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.itextpdf</groupId>
|
||||||
|
<artifactId>font-asian</artifactId>
|
||||||
|
<version>7.2.5</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.baomidou</groupId>
|
<groupId>com.baomidou</groupId>
|
||||||
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
|
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@ import com.gunshi.project.hsz.validate.markers.Update;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
|
@ -27,13 +29,17 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 描述: 预报_预测方案管理表
|
* 描述: 预报_预测方案管理表
|
||||||
|
|
@ -43,6 +49,7 @@ import java.util.stream.Collectors;
|
||||||
@Tag(name = "预报_预测方案管理表")
|
@Tag(name = "预报_预测方案管理表")
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping(value="/forecastProject")
|
@RequestMapping(value="/forecastProject")
|
||||||
|
@Slf4j
|
||||||
public class ForecastProjectController {
|
public class ForecastProjectController {
|
||||||
|
|
||||||
private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
|
|
@ -175,4 +182,66 @@ public class ForecastProjectController {
|
||||||
}
|
}
|
||||||
return R.ok(forecastProject);
|
return R.ok(forecastProject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Operation(summary = "pdf导出")
|
||||||
|
@GetMapping("export")
|
||||||
|
public void export(@RequestParam("ids") List<String> ids, HttpServletResponse response) {
|
||||||
|
try {
|
||||||
|
// 设置响应头
|
||||||
|
response.setContentType("application/zip");
|
||||||
|
response.setHeader("Content-Disposition", "attachment; filename=\"forecast_reports.zip\"");
|
||||||
|
|
||||||
|
// 创建ZIP输出流
|
||||||
|
ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream());
|
||||||
|
|
||||||
|
|
||||||
|
for (String projectId : ids) {
|
||||||
|
ForecastProject forecastProject = service.getById(projectId);
|
||||||
|
if (Objects.isNull(forecastProject)) {
|
||||||
|
throw new IllegalArgumentException("当前数据不存在");
|
||||||
|
}
|
||||||
|
List<ForecastResults> resultList = forecastResultsService.list(new QueryWrapper<ForecastResults>().eq("project_id", projectId).orderBy(true, true, "tm"));
|
||||||
|
if (CollectionUtils.isNotEmpty(resultList)) {
|
||||||
|
List<ForecastResultVo> vos = resultList.stream()
|
||||||
|
.map(result -> {
|
||||||
|
ForecastResultVo vo = new ForecastResultVo();
|
||||||
|
vo.setTm(sdf.format(result.getTm()));
|
||||||
|
vo.setYcRkQValue(result.getYcRkQValue());
|
||||||
|
vo.setRealRkQValue(result.getRealRkQValue());
|
||||||
|
vo.setYcCkQValue(result.getYcCkQValue());
|
||||||
|
vo.setRealCkQValue(result.getRealCkQValue());
|
||||||
|
vo.setYcSwHValue(result.getYcSwHValue());
|
||||||
|
vo.setRealSwHValue(result.getRealSwHValue());
|
||||||
|
BigDecimal ycSwHValue = result.getYcSwHValue() == null ? BigDecimal.ZERO : result.getYcSwHValue();
|
||||||
|
BigDecimal realSwHValue = result.getRealSwHValue() == null ? BigDecimal.ZERO : result.getRealSwHValue();
|
||||||
|
vo.setSwHDValue(ycSwHValue.subtract(realSwHValue));// 处理预测与实测水位差
|
||||||
|
vo.setDrp(result.getDrp());
|
||||||
|
vo.setIspreDrp(result.getIspreDrp());
|
||||||
|
vo.setR(result.getR());
|
||||||
|
vo.setFlLowLimLev(result.getFlLowLimLev());
|
||||||
|
vo.setCurrentYdgdyjz(result.getCurrentYdgdyjz());
|
||||||
|
vo.setPa(result.getPa());
|
||||||
|
return vo;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
forecastProject.setVoList(vos);
|
||||||
|
forecastResultsService.handleVoList(forecastProject);
|
||||||
|
}
|
||||||
|
//进行pdf导出
|
||||||
|
// 为每个项目生成PDF
|
||||||
|
String fileName = "预报报告_" + forecastProject.getName() + "_" +
|
||||||
|
new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + ".pdf";
|
||||||
|
// 添加到ZIP
|
||||||
|
zipOut.putNextEntry(new ZipEntry(fileName));
|
||||||
|
service.generatePdf(forecastProject, zipOut);
|
||||||
|
zipOut.closeEntry();
|
||||||
|
}
|
||||||
|
zipOut.finish();
|
||||||
|
zipOut.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("PDF导出失败", e);
|
||||||
|
throw new RuntimeException("导出失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,15 +6,42 @@ import com.gunshi.project.hsz.entity.vo.ForecastResultVo;
|
||||||
import com.gunshi.project.hsz.mapper.ForecastProjectMapper;
|
import com.gunshi.project.hsz.mapper.ForecastProjectMapper;
|
||||||
import com.gunshi.project.hsz.model.ForecastProject;
|
import com.gunshi.project.hsz.model.ForecastProject;
|
||||||
import com.gunshi.project.hsz.model.ForecastResults;
|
import com.gunshi.project.hsz.model.ForecastResults;
|
||||||
|
import com.itextpdf.io.font.PdfEncodings;
|
||||||
|
import com.itextpdf.kernel.colors.DeviceRgb;
|
||||||
|
import com.itextpdf.kernel.events.Event;
|
||||||
|
import com.itextpdf.kernel.events.IEventHandler;
|
||||||
|
import com.itextpdf.kernel.events.PdfDocumentEvent;
|
||||||
|
import com.itextpdf.kernel.font.PdfFont;
|
||||||
|
import com.itextpdf.kernel.font.PdfFontFactory;
|
||||||
|
import com.itextpdf.kernel.geom.PageSize;
|
||||||
|
import com.itextpdf.kernel.geom.Rectangle;
|
||||||
|
import com.itextpdf.kernel.pdf.PdfDocument;
|
||||||
|
import com.itextpdf.kernel.pdf.PdfPage;
|
||||||
|
import com.itextpdf.kernel.pdf.PdfWriter;
|
||||||
|
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
|
||||||
|
import com.itextpdf.layout.Canvas;
|
||||||
|
import com.itextpdf.layout.Document;
|
||||||
|
import com.itextpdf.layout.element.Cell;
|
||||||
|
import com.itextpdf.layout.element.Paragraph;
|
||||||
|
import com.itextpdf.layout.element.Table;
|
||||||
|
import com.itextpdf.layout.properties.TextAlignment;
|
||||||
|
import com.itextpdf.layout.properties.UnitValue;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 描述: 预报_预测方案管理表
|
* 描述: 预报_预测方案管理表
|
||||||
|
|
@ -63,6 +90,118 @@ public class ForecastProjectService extends ServiceImpl<ForecastProjectMapper, F
|
||||||
}
|
}
|
||||||
return forecastResultsService.saveBatch(retList);
|
return forecastResultsService.saveBatch(retList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void generatePdf(ForecastProject project, ZipOutputStream outputStream) {
|
||||||
|
|
||||||
|
// 使用ByteArrayOutputStream作为缓冲
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
PdfDocument pdfDoc = null;
|
||||||
|
Document document = null;
|
||||||
|
try{
|
||||||
|
PdfWriter writer = new PdfWriter(baos);
|
||||||
|
pdfDoc = new PdfDocument(writer);
|
||||||
|
document = new Document(pdfDoc,PageSize.A4.rotate());
|
||||||
|
// 设置字体
|
||||||
|
String fontPath = "/fonts/ChineseFonts.ttf";
|
||||||
|
PdfFont font = PdfFontFactory.createFont(fontPath, PdfEncodings.IDENTITY_H);
|
||||||
|
// 第一行:基本信息
|
||||||
|
Paragraph header1 = new Paragraph()
|
||||||
|
.add("预见期(小时): " + (project.getForecastPeriod() != null ? project.getForecastPeriod() : "无") + " ")
|
||||||
|
.add("预热期(天): " + (project.getForecastWarm() != null ? project.getForecastWarm() : "无") + " ")
|
||||||
|
.add("预报时间: " + formatDate(project.getForecastTm()) + " ")
|
||||||
|
.add("开始时间: " + formatDate(project.getStartTm()) + " ")
|
||||||
|
.add("结束时间: " + formatDate(project.getEndTm()))
|
||||||
|
.setFont(font)
|
||||||
|
.setFontSize(10);
|
||||||
|
|
||||||
|
document.add(header1);
|
||||||
|
document.add(new Paragraph("\n"));
|
||||||
|
|
||||||
|
// 第二行:统计信息
|
||||||
|
Paragraph header2 = new Paragraph()
|
||||||
|
.add("预报最高调洪水位(m): " + (project.getYcMaxSwH() != null ? project.getYcMaxSwH().setScale(2, RoundingMode.HALF_UP) : "无") + " ")
|
||||||
|
.add("预报最大入库流量(m³/s): " + (project.getYcMaxRkQ() != null ? project.getYcMaxRkQ().setScale(2, RoundingMode.HALF_UP) : "无") + " ")
|
||||||
|
.add("预报最大下泄流量(m³/s): " + (project.getYcMaxCkQ() != null ? project.getYcMaxCkQ().setScale(2, RoundingMode.HALF_UP) : "无") + " ")
|
||||||
|
.add("预报洪水总量(万m³): " + (project.getYcSumFlood() != null ? project.getYcSumFlood().setScale(2, RoundingMode.HALF_UP) : "无"))
|
||||||
|
.setFont(font)
|
||||||
|
.setFontSize(10);
|
||||||
|
|
||||||
|
document.add(header2);
|
||||||
|
document.add(new Paragraph("\n"));
|
||||||
|
|
||||||
|
// 第三行:数据表格
|
||||||
|
if (CollectionUtils.isNotEmpty(project.getVoList())) {
|
||||||
|
Table table = new Table(9); // 10列
|
||||||
|
table.setWidth(UnitValue.createPercentValue(100));
|
||||||
|
|
||||||
|
// 表头
|
||||||
|
table.addHeaderCell(createCell("序号", font, true));
|
||||||
|
table.addHeaderCell(createCell("时间", font, true));
|
||||||
|
table.addHeaderCell(createCell("降雨量(mm)", font, true));
|
||||||
|
table.addHeaderCell(createCell("实测水位(m)", font, true));
|
||||||
|
table.addHeaderCell(createCell("预报水位(m)", font, true));
|
||||||
|
table.addHeaderCell(createCell("入库流量(m³/s)", font, true));
|
||||||
|
table.addHeaderCell(createCell("预报入库流量(m³/s)", font, true));
|
||||||
|
table.addHeaderCell(createCell("实际出库流量(m³/s)", font, true));
|
||||||
|
table.addHeaderCell(createCell("预报出库流量(m³/s)", font, true));
|
||||||
|
|
||||||
|
// 表格数据
|
||||||
|
int index = 1;
|
||||||
|
for (ForecastResultVo vo : project.getVoList()) {
|
||||||
|
table.addCell(createCell(String.valueOf(index++), font, false));
|
||||||
|
table.addCell(createCell(vo.getTm(), font, false));
|
||||||
|
table.addCell(createCell(formatBigDecimal(vo.getDrp()), font, false));
|
||||||
|
table.addCell(createCell(formatBigDecimal(vo.getRealSwHValue()), font, false));
|
||||||
|
table.addCell(createCell(formatBigDecimal(vo.getYcSwHValue()), font, false));
|
||||||
|
table.addCell(createCell(formatBigDecimal(vo.getRealRkQValue()), font, false));
|
||||||
|
table.addCell(createCell(formatBigDecimal(vo.getYcRkQValue()), font, false));
|
||||||
|
table.addCell(createCell(formatBigDecimal(vo.getRealCkQValue()), font, false));
|
||||||
|
table.addCell(createCell(formatBigDecimal(vo.getYcCkQValue()), font, false));
|
||||||
|
}
|
||||||
|
document.add(table);
|
||||||
|
} else {
|
||||||
|
document.add(new Paragraph("无预报结果数据").setFont(font));
|
||||||
|
}
|
||||||
|
// 5. 关闭文档(关键:先关闭Document,再关闭PdfDocument)
|
||||||
|
document.close();
|
||||||
|
pdfDoc.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("生成PDF失败", e);
|
||||||
|
throw new RuntimeException("PDF生成失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
byte[] pdfBytes = baos.toByteArray();
|
||||||
|
outputStream.write(pdfBytes);
|
||||||
|
}catch (IOException e){
|
||||||
|
log.error("写入ZIP失败", e);
|
||||||
|
throw new RuntimeException("写入ZIP失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 辅助方法:创建表格单元格
|
||||||
|
private Cell createCell(String text, PdfFont font, boolean isHeader) {
|
||||||
|
Cell cell = new Cell().add(new Paragraph(text).setFont(font).setFontSize(8));
|
||||||
|
if (isHeader) {
|
||||||
|
cell.setBackgroundColor(new DeviceRgb(220, 220, 220));
|
||||||
|
cell.setBold();
|
||||||
|
}
|
||||||
|
cell.setPadding(3);
|
||||||
|
return cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 辅助方法:格式化日期
|
||||||
|
private String formatDate(Date date) {
|
||||||
|
if (date == null) return "无";
|
||||||
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
|
return sdf.format(date);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 辅助方法:格式化BigDecimal
|
||||||
|
private String formatBigDecimal(BigDecimal value) {
|
||||||
|
if (value == null) return "-";
|
||||||
|
return value.setScale(2, RoundingMode.HALF_UP).toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Binary file not shown.
Loading…
Reference in New Issue