添加政策导出
This commit is contained in:
@@ -116,6 +116,12 @@
|
|||||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||||
<artifactId>jackson-datatype-jsr310</artifactId>
|
<artifactId>jackson-datatype-jsr310</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- openpdf -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.librepdf</groupId>
|
||||||
|
<artifactId>openpdf</artifactId>
|
||||||
|
<version>1.3.30</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
@@ -3,6 +3,7 @@ package com.ruoyi.cms.controller.cms;
|
|||||||
import com.ruoyi.cms.domain.policy.PolicyInfo;
|
import com.ruoyi.cms.domain.policy.PolicyInfo;
|
||||||
import com.ruoyi.cms.domain.policy.PolicyInfoQuery;
|
import com.ruoyi.cms.domain.policy.PolicyInfoQuery;
|
||||||
import com.ruoyi.cms.service.policy.IPolicyInfoService;
|
import com.ruoyi.cms.service.policy.IPolicyInfoService;
|
||||||
|
import com.ruoyi.cms.util.pdf.OpenPdfPolicyUtil;
|
||||||
import com.ruoyi.common.annotation.Log;
|
import com.ruoyi.common.annotation.Log;
|
||||||
import com.ruoyi.common.core.controller.BaseController;
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
@@ -17,6 +18,7 @@ import org.springframework.security.access.prepost.PreAuthorize;
|
|||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
@@ -168,4 +170,13 @@ public class CmsPolicyInfoController extends BaseController {
|
|||||||
return error("文件上传失败:" + e.getMessage());
|
return error("文件上传失败:" + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/exportUtil")
|
||||||
|
public void pdfByUtil(@RequestParam Long id, HttpServletResponse response) throws Exception {
|
||||||
|
PolicyInfo policyInfo=policyInfoService.selectById(id);
|
||||||
|
if (policyInfo == null) {
|
||||||
|
throw new RuntimeException("未查询到对应政策信息");
|
||||||
|
}
|
||||||
|
OpenPdfPolicyUtil.exportPolicyPdf(policyInfo, response);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,154 @@
|
|||||||
|
package com.ruoyi.cms.util.pdf;
|
||||||
|
|
||||||
|
import com.lowagie.text.*;
|
||||||
|
import com.lowagie.text.pdf.BaseFont;
|
||||||
|
import com.lowagie.text.pdf.PdfWriter;
|
||||||
|
import com.ruoyi.cms.domain.policy.PolicyInfo;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OpenPDF 政策PDF导出工具
|
||||||
|
* 优化:表格列宽、文本清洗、自动换行、去除多余空行、增加边框区分
|
||||||
|
*/
|
||||||
|
public class OpenPdfPolicyUtil {
|
||||||
|
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
|
private static BaseFont baseFont;
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
// OpenPDF内置中文字体,无需外部ttf,Linux/Windows通用
|
||||||
|
baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("初始化PDF宋体字体失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void exportPolicyPdf(PolicyInfo policy, HttpServletResponse response) throws Exception {
|
||||||
|
String rawName = getCleanText(policy.getZcmc());
|
||||||
|
String fileName = URLEncoder.encode(rawName + ".pdf", "UTF-8");
|
||||||
|
response.setContentType("application/pdf");
|
||||||
|
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
|
||||||
|
response.setHeader("Cache-Control", "no-cache");
|
||||||
|
|
||||||
|
try (OutputStream out = response.getOutputStream();
|
||||||
|
Document document = new Document(PageSize.A4, 40, 40, 60, 60)) {
|
||||||
|
|
||||||
|
PdfWriter writer = PdfWriter.getInstance(document, out);
|
||||||
|
document.open();
|
||||||
|
|
||||||
|
// ========== 1、文档主标题 ==========
|
||||||
|
Font titleFont = new Font(baseFont, 20, Font.BOLD);
|
||||||
|
Paragraph titlePara = new Paragraph(getCleanText(policy.getZcmc()), titleFont);
|
||||||
|
titlePara.setAlignment(Element.ALIGN_CENTER);
|
||||||
|
titlePara.setSpacingAfter(25);
|
||||||
|
document.add(titlePara);
|
||||||
|
|
||||||
|
// ========== 2、基础信息表格(调整列宽20/30/20/30,加宽标题列) ==========
|
||||||
|
Font tableHeadFont = new Font(baseFont, 12, Font.BOLD);
|
||||||
|
Font tableValFont = new Font(baseFont, 12);
|
||||||
|
Table infoTable = new Table(4);
|
||||||
|
float[] colWidth = new float[]{20, 30, 20, 30};
|
||||||
|
infoTable.setWidths(colWidth);
|
||||||
|
infoTable.setWidth(100);
|
||||||
|
infoTable.setBorderWidth(0.6f); // 增加边框,区分单元格
|
||||||
|
|
||||||
|
// 第一行
|
||||||
|
infoTable.addCell(buildCell(getCleanText("政策类型"), tableHeadFont));
|
||||||
|
infoTable.addCell(buildCell(getCleanText(policy.getZclx()), tableValFont));
|
||||||
|
infoTable.addCell(buildCell(getCleanText("政策级别"), tableHeadFont));
|
||||||
|
infoTable.addCell(buildCell(getCleanText(policy.getZcLevel()), tableValFont));
|
||||||
|
|
||||||
|
// 第二行
|
||||||
|
infoTable.addCell(buildCell(getCleanText("发文单位"), tableHeadFont));
|
||||||
|
infoTable.addCell(buildCell(getCleanText(policy.getSourceUnit()), tableValFont));
|
||||||
|
infoTable.addCell(buildCell(getCleanText("受理单位"), tableHeadFont));
|
||||||
|
infoTable.addCell(buildCell(getCleanText(policy.getAcceptUnit()), tableValFont));
|
||||||
|
|
||||||
|
// 第三行
|
||||||
|
String publishDate = policy.getPublishTime() == null ? "无" : DATE_FORMAT.format(policy.getPublishTime());
|
||||||
|
infoTable.addCell(buildCell(getCleanText("发文时间"), tableHeadFont));
|
||||||
|
infoTable.addCell(buildCell(publishDate, tableValFont));
|
||||||
|
infoTable.addCell(buildCell(getCleanText("浏览数量"), tableHeadFont));
|
||||||
|
infoTable.addCell(buildCell(String.valueOf(policy.getViewNum()), tableValFont));
|
||||||
|
|
||||||
|
document.add(infoTable);
|
||||||
|
document.add(new Paragraph(" "));
|
||||||
|
|
||||||
|
// ========== 3、政策四大章节 ==========
|
||||||
|
Font sectionTitleFont = new Font(baseFont, 14, Font.BOLD);
|
||||||
|
Font contentFont = new Font(baseFont, 11);
|
||||||
|
float lineMulti = 1.45f;
|
||||||
|
|
||||||
|
addSection(document, "一、政策内容", policy.getZcContent(), sectionTitleFont, contentFont, lineMulti);
|
||||||
|
addSection(document, "二、补贴标准", policy.getSubsidyStandard(), sectionTitleFont, contentFont, lineMulti);
|
||||||
|
addSection(document, "三、申报条件", policy.getApplyCondition(), sectionTitleFont, contentFont, lineMulti);
|
||||||
|
addSection(document, "四、经办渠道", policy.getHandleChannel(), sectionTitleFont, contentFont, lineMulti);
|
||||||
|
|
||||||
|
/*// ========== 4、附件信息 ==========
|
||||||
|
Paragraph fileTitlePara = new Paragraph("五、附件文件信息", sectionTitleFont);
|
||||||
|
fileTitlePara.setSpacingBefore(18);
|
||||||
|
fileTitlePara.setSpacingAfter(8);
|
||||||
|
document.add(fileTitlePara);
|
||||||
|
|
||||||
|
String fileInfo = "文件名称:" + getCleanText(policy.getFileName()) + "\n文件地址:" + getCleanText(policy.getFileUrl());
|
||||||
|
Paragraph filePara = new Paragraph(fileInfo, contentFont);
|
||||||
|
filePara.setMultipliedLeading(lineMulti);
|
||||||
|
filePara.setIndentationLeft(5);
|
||||||
|
document.add(filePara);*/
|
||||||
|
|
||||||
|
document.close();
|
||||||
|
writer.flush();
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建单元格:移除多余\n换行,仅靠段落间距,消除大量空白行
|
||||||
|
*/
|
||||||
|
private static Cell buildCell(String text, Font font) {
|
||||||
|
Cell cell = new Cell();
|
||||||
|
Paragraph cellPara = new Paragraph(text, font);
|
||||||
|
cellPara.setSpacingBefore(4);
|
||||||
|
cellPara.setSpacingAfter(4);
|
||||||
|
cell.add(cellPara);
|
||||||
|
return cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增:统一处理章节标题+正文,自动清洗文本、缩进、行间距
|
||||||
|
*/
|
||||||
|
private static void addSection(Document doc, String title, String rawContent, Font titleFont, Font contentFont, float lineHeight) throws DocumentException {
|
||||||
|
Paragraph titlePara = new Paragraph(title, titleFont);
|
||||||
|
titlePara.setSpacingBefore(14);
|
||||||
|
titlePara.setSpacingAfter(7);
|
||||||
|
doc.add(titlePara);
|
||||||
|
|
||||||
|
String cleanContent = getCleanText(rawContent);
|
||||||
|
Paragraph contentPara = new Paragraph(cleanContent, contentFont);
|
||||||
|
contentPara.setMultipliedLeading(lineHeight);
|
||||||
|
contentPara.setIndentationLeft(5);
|
||||||
|
doc.add(contentPara);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 核心文本清洗:清除多余换行、空格、统一全角符号,解决公文排版错乱
|
||||||
|
*/
|
||||||
|
private static String getCleanText(String str) {
|
||||||
|
if (str == null || str.trim().isEmpty()) {
|
||||||
|
return "无";
|
||||||
|
}
|
||||||
|
// 去除首尾空白
|
||||||
|
String temp = str.trim();
|
||||||
|
// 多个换行替换为单个换行
|
||||||
|
temp = temp.replaceAll("\\s*\n\\s*", "\n");
|
||||||
|
// 多个空格压缩为单个
|
||||||
|
temp = temp.replaceAll(" +", " ");
|
||||||
|
// 全角顿号统一(可选,按需开启)
|
||||||
|
temp = temp.replace("、", "、");
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user