From 18f0af1e1b98b44b6052066c47dcd2fcda80b6cc Mon Sep 17 00:00:00 2001 From: yangwei <867012372@qq.com> Date: Wed, 28 May 2025 14:08:12 +0800 Subject: [PATCH] =?UTF-8?q?[feat]=E5=A2=9E=E5=8A=A0=E5=AF=BC=E5=87=BA?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=EF=BC=8C=E6=95=B4=E5=90=88world=E3=80=81pdf?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dk-modules/business/pom.xml | 17 +++ .../business/domain/bo/BusinessAlertBo.java | 5 + .../impl/BusinessAlertServiceImpl.java | 51 ++++--- .../business/utils/HtmlConvertPdfHelper.java | 101 ++++++++++++++ .../src/main/resources/templates/alert.ftl | 4 +- .../src/main/resources/templates/pdfAlert.ftl | 124 ++++++++++++++++++ 6 files changed, 279 insertions(+), 23 deletions(-) create mode 100644 dk-modules/business/src/main/java/org/dromara/business/utils/HtmlConvertPdfHelper.java create mode 100644 dk-modules/business/src/main/resources/templates/pdfAlert.ftl diff --git a/dk-modules/business/pom.xml b/dk-modules/business/pom.xml index 94dd52d..f917221 100644 --- a/dk-modules/business/pom.xml +++ b/dk-modules/business/pom.xml @@ -132,6 +132,23 @@ spring-boot-starter-freemarker + + + com.itextpdf + itextpdf + 5.5.11 + + + com.itextpdf.tool + xmlworker + 5.5.11 + + + com.itextpdf + itext-asian + 5.2.0 + + ${project.artifactId} diff --git a/dk-modules/business/src/main/java/org/dromara/business/domain/bo/BusinessAlertBo.java b/dk-modules/business/src/main/java/org/dromara/business/domain/bo/BusinessAlertBo.java index 5db6e46..23f549f 100644 --- a/dk-modules/business/src/main/java/org/dromara/business/domain/bo/BusinessAlertBo.java +++ b/dk-modules/business/src/main/java/org/dromara/business/domain/bo/BusinessAlertBo.java @@ -247,4 +247,9 @@ public class BusinessAlertBo { */ private String caseNumber; + /** + * 不传的话默认world + */ + private String exportType = "world"; + } diff --git a/dk-modules/business/src/main/java/org/dromara/business/service/impl/BusinessAlertServiceImpl.java b/dk-modules/business/src/main/java/org/dromara/business/service/impl/BusinessAlertServiceImpl.java index 3f05263..10a5cd1 100644 --- a/dk-modules/business/src/main/java/org/dromara/business/service/impl/BusinessAlertServiceImpl.java +++ b/dk-modules/business/src/main/java/org/dromara/business/service/impl/BusinessAlertServiceImpl.java @@ -11,6 +11,8 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.itextpdf.text.DocumentException; +import freemarker.template.TemplateException; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -860,28 +862,28 @@ public class BusinessAlertServiceImpl implements IBusinessAlertService { businessAlert.setHandleType(businessAlert.getHandleType().equalsIgnoreCase("waiting")?"未处理":businessAlert.getHandleType().equalsIgnoreCase("finish")?"已完结":businessAlert.getHandleType().equalsIgnoreCase("cancel")?"已忽略":"待验证"); if (businessAlert.getBusinessType() == 1){ - businessAlert.setImages(imageToBase64(MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_ALERT, businessAlert.getImages(), 3600).toString())); - businessAlert.setMaxImages(imageToBase64(MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_ALERT, businessAlert.getMaxImages(), 3600).toString())); - businessAlert.setMaxMateSourceImgUrl(imageToBase64(MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_ALERT, businessAlert.getMaxMateSourceImgUrl(), 3600).toString())); - businessAlert.setMateSourceImgUrl(imageToBase64(MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_ALERT, businessAlert.getMateSourceImgUrl(), 3600).toString())); + businessAlert.setImages(MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_ALERT, businessAlert.getImages(), 3600).toString()); + businessAlert.setMaxImages(MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_ALERT, businessAlert.getMaxImages(), 3600).toString()); + businessAlert.setMaxMateSourceImgUrl(MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_ALERT, businessAlert.getMaxMateSourceImgUrl(), 3600).toString()); + businessAlert.setMateSourceImgUrl(MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_ALERT, businessAlert.getMateSourceImgUrl(), 3600).toString()); }else { - businessAlert.setImages(imageToBase64(MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_ALERT, businessAlert.getImages(), 3600).toString())); + businessAlert.setImages(MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_ALERT, businessAlert.getImages(), 3600).toString()); } //获取指南针 - Double gimbalYawDegree = feignDeviceGroup.getGimbalYawDegree(businessAlert.getTaskImageId()); - if (ObjectUtil.isNotEmpty(gimbalYawDegree) && gimbalYawDegree != -1.0){ - if (gimbalYawDegree < 0){ - gimbalYawDegree = gimbalYawDegree - 180; - }else { - gimbalYawDegree = 180 - gimbalYawDegree; - } - - log.info("旋转角度${}",gimbalYawDegree); - - String rotatedAndOverlayImage = ImageRotator.rotateAndOverlayImage(null, null, gimbalYawDegree); - businessAlert.setIcon(rotatedAndOverlayImage); - } +// Double gimbalYawDegree = feignDeviceGroup.getGimbalYawDegree(businessAlert.getTaskImageId()); +// if (ObjectUtil.isNotEmpty(gimbalYawDegree) && gimbalYawDegree != -1.0){ +// if (gimbalYawDegree < 0){ +// gimbalYawDegree = gimbalYawDegree - 180; +// }else { +// gimbalYawDegree = 180 - gimbalYawDegree; +// } +// +// log.info("旋转角度${}",gimbalYawDegree); +// +// String rotatedAndOverlayImage = ImageRotator.rotateAndOverlayImage(null, null, gimbalYawDegree); +// businessAlert.setIcon(rotatedAndOverlayImage); +// } } catch (Exception e) { log.error(e.getMessage(),e); @@ -894,10 +896,17 @@ public class BusinessAlertServiceImpl implements IBusinessAlertService { System.out.println("消耗时长:" + (endMillis-startMillis)); resultMap.put("alertList",alertList); - //生成word - FreemarkerUtil.renderTplFileToWord("预警导出.docx","alert.ftl",resultMap,response); -// FreemarkerUtil.renderTplFileToPDF("预警导出.docx","alert.ftl",resultMap,response); + if (bo.getExportType().equalsIgnoreCase("world")){ + //生成word + FreemarkerUtil.renderTplFileToWord("预警导出.docx","alert.ftl",resultMap,response); + } else if (bo.getExportType().equalsIgnoreCase("pdf")) { + try { + HtmlConvertPdfHelper.htmlConvertPDF(resultMap,"pdfAlert.ftl"); + } catch (Exception e) { + log.error(e.getMessage(),e); + } + } } diff --git a/dk-modules/business/src/main/java/org/dromara/business/utils/HtmlConvertPdfHelper.java b/dk-modules/business/src/main/java/org/dromara/business/utils/HtmlConvertPdfHelper.java new file mode 100644 index 0000000..9f45e05 --- /dev/null +++ b/dk-modules/business/src/main/java/org/dromara/business/utils/HtmlConvertPdfHelper.java @@ -0,0 +1,101 @@ +package org.dromara.business.utils; + +import cn.hutool.extra.spring.SpringUtil; +import com.itextpdf.text.Document; +import com.itextpdf.text.DocumentException; +import com.itextpdf.text.Font; +import com.itextpdf.text.pdf.BaseFont; +import com.itextpdf.text.pdf.PdfWriter; +import com.itextpdf.tool.xml.XMLWorkerFontProvider; +import com.itextpdf.tool.xml.XMLWorkerHelper; +import freemarker.template.TemplateException; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.ui.freemarker.FreeMarkerTemplateUtils; +import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.net.URLEncoder; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.Map; + +/** + * Html转换Pdf + * + * @author :Mall + * @date :Created in 2022-04-25 + */ +public class HtmlConvertPdfHelper { + + /** + * Freemarker的配置类,模板目录默认 在 resources下的 templates + */ + private static FreeMarkerConfigurer freeMarkerConfigurer = SpringUtil.getBean(FreeMarkerConfigurer.class); + + public static void renderTplFileToPDF(String fileName , String templateName, Map datas, HttpServletResponse response) { + try { + response.setCharacterEncoding(StandardCharsets.UTF_8.name()); // 字符集编码 + response.setContentType("application/pdf;"); + response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8")); + response.addHeader("Access-Control-Allow-Origin", "*"); // 实现跨域 + byte[] bytes = htmlConvertPDF(datas, templateName); + // 将生成的文档写入到响应的输出流中 + response.reset(); // 重置响应 + response.getOutputStream().write(bytes); + response.getOutputStream().flush(); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * freemarker转PDF + * + * @param templateName ftl文件名称,需要在resources/templates目录下 + * @return + * @throws IOException + */ + public static byte[] htmlConvertPDF(Object map,String templateName) throws IOException, TemplateException, DocumentException { + String htmlText = FreeMarkerTemplateUtils.processTemplateIntoString(freeMarkerConfigurer.getConfiguration().getTemplate(templateName), map); + return htmlConvertPDF(htmlText); + } + + /** + * 根据HTML内容转Image + * + * @param htmText HTML文本字符串 + */ + public static byte[] htmlConvertPDF(String htmText) throws DocumentException, IOException { + //最终返回的byte流 + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + //第一步,创建一个 iTextSharp.text.Document对象的实例: + Document document = new Document(); + //第二步,为该Document创建一个Writer实例: + PdfWriter writer = PdfWriter.getInstance(document, byteArrayOutputStream); + //第三步,打开当前Document + document.open(); + XMLWorkerHelper.getInstance().parseXHtml(writer, document, new ByteArrayInputStream(htmText.getBytes()), null, Charset.defaultCharset(), new AsianFontProvider()); + document.close(); + return byteArrayOutputStream.toByteArray(); + } +} + + +/** + * 用于中文显示的Provider + */ +class AsianFontProvider extends XMLWorkerFontProvider { + @Override + public Font getFont(final String fontname, String encoding, float size, int style) { + try { + BaseFont bfChinese = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); + return new Font(bfChinese, size, style); + } catch (Exception e) { + } + return super.getFont(fontname, encoding, size, style); + } +} + diff --git a/dk-modules/business/src/main/resources/templates/alert.ftl b/dk-modules/business/src/main/resources/templates/alert.ftl index 9697092..7937b57 100644 --- a/dk-modules/business/src/main/resources/templates/alert.ftl +++ b/dk-modules/business/src/main/resources/templates/alert.ftl @@ -578,7 +578,7 @@ - ${startTime?if_exists}-${endTime?if_exists} + ${startTime?if_exists}~${endTime?if_exists} @@ -1766,7 +1766,7 @@ - 现场情况 +<#-- 现场情况--> diff --git a/dk-modules/business/src/main/resources/templates/pdfAlert.ftl b/dk-modules/business/src/main/resources/templates/pdfAlert.ftl new file mode 100644 index 0000000..7cc75f2 --- /dev/null +++ b/dk-modules/business/src/main/resources/templates/pdfAlert.ftl @@ -0,0 +1,124 @@ + + + + Early Warning Record + + + + +

一、报表日期

+

${startTime?if_exists}~${endTime?if_exists}

+

二、数据情况

+

预警信息总计:${total?if_exists}条;未处理:${todo?if_exists}条; 已完结:${finish?if_exists}条; 已忽略:${cancel?if_exists}条。

+

详情如下

+ + + + + + + + + + + + + + + + + + + + + <#if (alertList?size gt 0) && alertList??> + <#list alertList as item> + + + + + + + + + + + +
序号预警名称所属部门预警状态经纬度预警时间
${item_index + 1}${item.jobName?if_exists}${item.deptName?if_exists}${item.handleType?if_exists}${item.lng?if_exists} ${item.lat?if_exists}${item.createTime?datetime?string('yyyy-MM-dd HH:mm:ss')}
+ + +<#if (alertList?size gt 0) && alertList??> + <#list alertList as item> +

(${item_index + 1})预警信息:${item.jobName?if_exists}

+ + + + + + + + + + + + + + + + + + + +
前期影像后期影像
前期影像1前期影像2
后期影像1后期影像2
+ + <#if item.assignUserId??> +

处置内容

+ + + + + + + + + + + + + + + +
识别类型:${item.labelCn?if_exists}指派人员: ${item.assignUserName?if_exists}
预警时间: ${item.createTime?datetime?string('yyyy-MM-dd HH:mm:ss')}指派时间: + <#if item.assignDate??> + ${item.assignDate?datetime?string('yyyy-MM-dd HH:mm:ss')} + +
任务内容: ${item.reason?if_exists}
+ + + + +