Browse Source

[feat]增加导出功能,整合world、pdf

pull/7/head
杨威 4 weeks ago
parent
commit
18f0af1e1b
  1. 17
      dk-modules/business/pom.xml
  2. 5
      dk-modules/business/src/main/java/org/dromara/business/domain/bo/BusinessAlertBo.java
  3. 49
      dk-modules/business/src/main/java/org/dromara/business/service/impl/BusinessAlertServiceImpl.java
  4. 101
      dk-modules/business/src/main/java/org/dromara/business/utils/HtmlConvertPdfHelper.java
  5. 4
      dk-modules/business/src/main/resources/templates/alert.ftl
  6. 124
      dk-modules/business/src/main/resources/templates/pdfAlert.ftl

17
dk-modules/business/pom.xml

@ -132,6 +132,23 @@
<artifactId>spring-boot-starter-freemarker</artifactId> <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency> </dependency>
<!-- html转pdf -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.11</version>
</dependency>
<dependency>
<groupId>com.itextpdf.tool</groupId>
<artifactId>xmlworker</artifactId>
<version>5.5.11</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
</dependencies> </dependencies>
<build> <build>
<finalName>${project.artifactId}</finalName> <finalName>${project.artifactId}</finalName>

5
dk-modules/business/src/main/java/org/dromara/business/domain/bo/BusinessAlertBo.java

@ -247,4 +247,9 @@ public class BusinessAlertBo {
*/ */
private String caseNumber; private String caseNumber;
/**
* 不传的话默认world
*/
private String exportType = "world";
} }

49
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.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itextpdf.text.DocumentException;
import freemarker.template.TemplateException;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; 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")?"已忽略":"待验证"); businessAlert.setHandleType(businessAlert.getHandleType().equalsIgnoreCase("waiting")?"未处理":businessAlert.getHandleType().equalsIgnoreCase("finish")?"已完结":businessAlert.getHandleType().equalsIgnoreCase("cancel")?"已忽略":"待验证");
if (businessAlert.getBusinessType() == 1){ if (businessAlert.getBusinessType() == 1){
businessAlert.setImages(imageToBase64(MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_ALERT, businessAlert.getImages(), 3600).toString())); businessAlert.setImages(MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_ALERT, businessAlert.getImages(), 3600).toString());
businessAlert.setMaxImages(imageToBase64(MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_ALERT, businessAlert.getMaxImages(), 3600).toString())); businessAlert.setMaxImages(MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_ALERT, businessAlert.getMaxImages(), 3600).toString());
businessAlert.setMaxMateSourceImgUrl(imageToBase64(MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_ALERT, businessAlert.getMaxMateSourceImgUrl(), 3600).toString())); businessAlert.setMaxMateSourceImgUrl(MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_ALERT, businessAlert.getMaxMateSourceImgUrl(), 3600).toString());
businessAlert.setMateSourceImgUrl(imageToBase64(MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_ALERT, businessAlert.getMateSourceImgUrl(), 3600).toString())); businessAlert.setMateSourceImgUrl(MinioUntil.getObjectUrlOne(MinIOConstants.BUCKET_ALERT, businessAlert.getMateSourceImgUrl(), 3600).toString());
}else { }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()); // Double gimbalYawDegree = feignDeviceGroup.getGimbalYawDegree(businessAlert.getTaskImageId());
if (ObjectUtil.isNotEmpty(gimbalYawDegree) && gimbalYawDegree != -1.0){ // if (ObjectUtil.isNotEmpty(gimbalYawDegree) && gimbalYawDegree != -1.0){
if (gimbalYawDegree < 0){ // if (gimbalYawDegree < 0){
gimbalYawDegree = gimbalYawDegree - 180; // gimbalYawDegree = gimbalYawDegree - 180;
}else { // }else {
gimbalYawDegree = 180 - gimbalYawDegree; // gimbalYawDegree = 180 - gimbalYawDegree;
} // }
//
log.info("旋转角度${}",gimbalYawDegree); // log.info("旋转角度${}",gimbalYawDegree);
//
String rotatedAndOverlayImage = ImageRotator.rotateAndOverlayImage(null, null, gimbalYawDegree); // String rotatedAndOverlayImage = ImageRotator.rotateAndOverlayImage(null, null, gimbalYawDegree);
businessAlert.setIcon(rotatedAndOverlayImage); // businessAlert.setIcon(rotatedAndOverlayImage);
} // }
} catch (Exception e) { } catch (Exception e) {
log.error(e.getMessage(),e); log.error(e.getMessage(),e);
@ -894,10 +896,17 @@ public class BusinessAlertServiceImpl implements IBusinessAlertService {
System.out.println("消耗时长:" + (endMillis-startMillis)); System.out.println("消耗时长:" + (endMillis-startMillis));
resultMap.put("alertList",alertList); resultMap.put("alertList",alertList);
if (bo.getExportType().equalsIgnoreCase("world")){
//生成word //生成word
FreemarkerUtil.renderTplFileToWord("预警导出.docx","alert.ftl",resultMap,response); FreemarkerUtil.renderTplFileToWord("预警导出.docx","alert.ftl",resultMap,response);
// FreemarkerUtil.renderTplFileToPDF("预警导出.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);
}
}
} }

101
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<String, Object> 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);
}
}

4
dk-modules/business/src/main/resources/templates/alert.ftl

@ -578,7 +578,7 @@
<w:rFonts w:hint="fareast"/> <w:rFonts w:hint="fareast"/>
<w:lang w:val="EN-US" w:fareast="ZH-CN"/> <w:lang w:val="EN-US" w:fareast="ZH-CN"/>
</w:rPr> </w:rPr>
<w:t>${startTime?if_exists}-${endTime?if_exists}</w:t> <w:t>${startTime?if_exists}~${endTime?if_exists}</w:t>
</w:r> </w:r>
</w:p> </w:p>
<w:p> <w:p>
@ -1766,7 +1766,7 @@
<w:sz-cs w:val="30"/> <w:sz-cs w:val="30"/>
<w:lang w:val="EN-US" w:fareast="ZH-CN"/> <w:lang w:val="EN-US" w:fareast="ZH-CN"/>
</w:rPr> </w:rPr>
<w:t>现场情况</w:t> <#-- <w:t>现场情况</w:t>-->
</w:r> </w:r>
</w:p> </w:p>

124
dk-modules/business/src/main/resources/templates/pdfAlert.ftl

@ -0,0 +1,124 @@
<!DOCTYPE html>
<html>
<head>
<title>Early Warning Record</title>
<style>
table, th, td {
border: 1px solid black;
border-collapse: collapse;
text-align: center;
}
h2, p {
text-align: left;
margin-top: 40px;
margin-left: 60px;
}
table {
margin: 40px auto;
width: 100%;
}
h2 {
color: #1b5aa1;
}
td {
word-wrap: break-word;
word-break: break-all;
}
</style>
</head>
<body>
<h2>一、报表日期</h2>
<p>${startTime?if_exists}~${endTime?if_exists}</p>
<h2>二、数据情况</h2>
<p>预警信息总计:${total?if_exists}条;未处理:${todo?if_exists}条; 已完结:${finish?if_exists}条; 已忽略:${cancel?if_exists}条。</p>
<p>详情如下</p>
<table>
<!-- 使用 colgroup 和 col 标签为每一列设置不同宽度 -->
<colgroup>
<col style="width: 5%;"/>
<col style="width: 10%;"/>
<col style="width: 10%;"/>
<col style="width: 10%;"/>
<col style="width: 10%;"/>
<col style="width: 10%;"/>
</colgroup>
<tbody>
<tr>
<td>序号</td>
<td>预警名称</td>
<td>所属部门</td>
<td>预警状态</td>
<td>经纬度</td>
<td>预警时间</td>
</tr>
<#if (alertList?size gt 0) && alertList??>
<#list alertList as item>
<tr>
<td>${item_index + 1}</td>
<td>${item.jobName?if_exists}</td>
<td>${item.deptName?if_exists}</td>
<td>${item.handleType?if_exists}</td>
<td>${item.lng?if_exists} ${item.lat?if_exists}</td>
<td>${item.createTime?datetime?string('yyyy-MM-dd HH:mm:ss')}</td>
</tr>
</#list>
</#if>
</tbody>
</table>
<script>
</script>
<#if (alertList?size gt 0) && alertList??>
<#list alertList as item>
<h2>(${item_index + 1})预警信息:${item.jobName?if_exists}</h2>
<table>
<colgroup>
<col style="width: 50%;"/>
<col style="width: 50%;"/>
</colgroup>
<tbody>
<tr>
<td style="height: 50px;">前期影像</td>
<td style="height: 50px;">后期影像</td>
</tr>
<tr>
<td><img src="${item.maxImages}" alt="前期影像1" style="width: 330px; height: 290px;"/></td>
<td><img src="${item.images}" alt="前期影像2" style="width: 330px; height: 290px;"/></td>
</tr>
<tr>
<td><img src="${item.maxMateSourceImgUrl}" alt="后期影像1" style="width: 330px; height: 290px;"/></td>
<td><img src="${item.mateSourceImgUrl}" alt="后期影像2" style="width: 330px; height: 290px;"/></td>
</tr>
</tbody>
</table>
<#if item.assignUserId??>
<h2>处置内容</h2>
<table style="border-collapse: collapse; border: none; margin-top: 50px;width: 50%;height: 50%;">
<tbody>
<tr>
<td style="border: none; text-align: left; height: 30px; vertical-align: top;">识别类型:${item.labelCn?if_exists}</td>
<td style="border: none; text-align: left; height: 30px; vertical-align: top;">指派人员: ${item.assignUserName?if_exists}</td>
</tr>
<tr>
<td style="border: none; text-align: left; height: 30px; vertical-align: top;">预警时间: ${item.createTime?datetime?string('yyyy-MM-dd HH:mm:ss')}</td>
<td style="border: none; text-align: left; height: 30px; vertical-align: top;">指派时间:
<#if item.assignDate??>
${item.assignDate?datetime?string('yyyy-MM-dd HH:mm:ss')}
</#if>
</td>
</tr>
<tr>
<td colspan="2" style="border: none; text-align: left; height: 40px;width: 50%; vertical-align: top;" >任务内容: ${item.reason?if_exists}</td>
</tr>
</tbody>
</table>
</#if>
</#list>
</#if>
</body>
</html>
Loading…
Cancel
Save