From 8a735e48d2fa0b24b791adbfbbbb907319e7f789 Mon Sep 17 00:00:00 2001 From: HanLong <404402223@qq.com> Date: Thu, 8 Jan 2026 22:57:31 +0800 Subject: [PATCH] =?UTF-8?q?feat:[=E8=AF=95=E9=AA=8C=E7=AE=A1=E7=90=86][?= =?UTF-8?q?=E8=AF=95=E9=AA=8C=E6=96=B9=E6=B3=95]=E5=AF=BC=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../business/controller/StudyMethodController.java | 35 ++- .../business/service/IStudyMethodReadService.java | 1 + .../service/impl/StudyMethodReadServiceImpl.java | 9 + .../service/impl/StudyMethodServiceImpl.java | 1 + .../main/java/com/hxhq/business/utils/PdfUtil.java | 77 +++++- .../hxhq/business/utils/StudyMethodFileUtil.java | 266 +++++++++++++++++++++ 6 files changed, 382 insertions(+), 7 deletions(-) create mode 100644 hxhq-modules/hxhq-system/src/main/java/com/hxhq/business/utils/StudyMethodFileUtil.java diff --git a/hxhq-modules/hxhq-system/src/main/java/com/hxhq/business/controller/StudyMethodController.java b/hxhq-modules/hxhq-system/src/main/java/com/hxhq/business/controller/StudyMethodController.java index 1599c7e..2261e3d 100644 --- a/hxhq-modules/hxhq-system/src/main/java/com/hxhq/business/controller/StudyMethodController.java +++ b/hxhq-modules/hxhq-system/src/main/java/com/hxhq/business/controller/StudyMethodController.java @@ -1,14 +1,19 @@ package com.hxhq.business.controller; -import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.hxhq.business.domain.StudyMethodRead; import com.hxhq.business.form.study.StudyMethodForm; import com.hxhq.business.form.study.StudyMethodReadForm; import com.hxhq.business.form.study.StudyMethodSearchForm; +import com.hxhq.business.service.IStudyMethodReadService; +import com.hxhq.business.utils.StudyMethodFileUtil; +import com.hxhq.common.core.domain.MpBaseEntity; import com.hxhq.common.security.utils.SecurityUtils; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import com.hxhq.business.domain.StudyMethod; @@ -30,6 +35,12 @@ public class StudyMethodController extends BaseController { @Autowired private IStudyMethodService studyMethodService; + @Autowired + private IStudyMethodReadService studyMethodReadService; + + @Autowired + private StudyMethodFileUtil studyMethodFileUtil; + /** * 查询试验-试验方法列表 */ @@ -64,4 +75,24 @@ public class StudyMethodController extends BaseController { studyMethodService.read(form); return AjaxResult.success(); } + + @GetMapping(value = "/read/list") + public AjaxResult getReadList(Long studyMethodId) { + List list = studyMethodReadService.queryList(studyMethodId); + return AjaxResult.success(list); + } + + @GetMapping(value = "/test") + public AjaxResult test(Long studyMethodId) { + StudyMethod studyMethod = studyMethodService.getById(studyMethodId); + if(studyMethod == null) { + return error("试验方法不存在或已删除"); + } + List list = studyMethodReadService.queryList(studyMethodId); + + String exportStudyMethodFilePath = studyMethodFileUtil.exportStudyMethodFile(studyMethod, list); + Map result = new HashMap<>(); + result.put("fileUrl", exportStudyMethodFilePath); + return AjaxResult.success(result); + } } diff --git a/hxhq-modules/hxhq-system/src/main/java/com/hxhq/business/service/IStudyMethodReadService.java b/hxhq-modules/hxhq-system/src/main/java/com/hxhq/business/service/IStudyMethodReadService.java index 1207e02..a209b46 100644 --- a/hxhq-modules/hxhq-system/src/main/java/com/hxhq/business/service/IStudyMethodReadService.java +++ b/hxhq-modules/hxhq-system/src/main/java/com/hxhq/business/service/IStudyMethodReadService.java @@ -15,4 +15,5 @@ import java.util.List; */ public interface IStudyMethodReadService extends IService { + List queryList(Long studyMethodId); } diff --git a/hxhq-modules/hxhq-system/src/main/java/com/hxhq/business/service/impl/StudyMethodReadServiceImpl.java b/hxhq-modules/hxhq-system/src/main/java/com/hxhq/business/service/impl/StudyMethodReadServiceImpl.java index 2814323..41e3b0c 100644 --- a/hxhq-modules/hxhq-system/src/main/java/com/hxhq/business/service/impl/StudyMethodReadServiceImpl.java +++ b/hxhq-modules/hxhq-system/src/main/java/com/hxhq/business/service/impl/StudyMethodReadServiceImpl.java @@ -1,5 +1,6 @@ package com.hxhq.business.service.impl; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.hxhq.business.domain.StudyMethod; @@ -9,6 +10,7 @@ import com.hxhq.business.mapper.StudyMethodMapper; import com.hxhq.business.mapper.StudyMethodReadMapper; import com.hxhq.business.service.IStudyMethodReadService; import com.hxhq.business.service.IStudyMethodService; +import com.hxhq.common.core.domain.MpBaseEntity; import com.hxhq.system.api.domain.SysUser; import com.hxhq.system.service.ISysUserService; import org.springframework.beans.BeanUtils; @@ -28,4 +30,11 @@ public class StudyMethodReadServiceImpl extends ServiceImpl queryList(Long studyMethodId) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(StudyMethodRead::getStudyMethodId, studyMethodId); + queryWrapper.orderByDesc(MpBaseEntity::getId); + return this.list(queryWrapper); + } } diff --git a/hxhq-modules/hxhq-system/src/main/java/com/hxhq/business/service/impl/StudyMethodServiceImpl.java b/hxhq-modules/hxhq-system/src/main/java/com/hxhq/business/service/impl/StudyMethodServiceImpl.java index d26f526..1f65091 100644 --- a/hxhq-modules/hxhq-system/src/main/java/com/hxhq/business/service/impl/StudyMethodServiceImpl.java +++ b/hxhq-modules/hxhq-system/src/main/java/com/hxhq/business/service/impl/StudyMethodServiceImpl.java @@ -94,6 +94,7 @@ public class StudyMethodServiceImpl extends ServiceImpl list) { + String fileUrl = studyMethod.getFileUrl(); + fileUrl = fileUrl.replaceFirst(localFilePrefix, ""); + int indexOf = fileUrl.lastIndexOf("/"); + String path = fileUrl.substring(0, indexOf); + String exportFileName = exportTable(SecurityUtils.getNickName() + DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD_HH_MM_SS), list, + localFilePath + fileUrl, localFilePath + File.separator + path); + return localFilePrefix + path + File.separator + exportFileName; + } + + + /** + * 复制原有PDF的所有页面到新Document中 + */ + private static void copyOriginalPagesToDocument(Document doc, PdfWriter writer, PdfReader reader) throws DocumentException { + int pageCount = reader.getNumberOfPages(); + PdfContentByte canvas = writer.getDirectContent(); // 获取直接内容画布 + + for (int i = 1; i <= pageCount; i++) { + doc.newPage(); // 新建一页(与原PDF页面一一对应) + // 5.5.11中通过PdfImportedPage导入原有页面 + PdfImportedPage importedPage = writer.getImportedPage(reader, i); + // 将原有页面绘制到新文档的当前页 + canvas.addTemplate(importedPage, 0, 0); + } + } + + /** + * 导出table + * @param headerText + * @param fileDir + * @return + */ + public static String exportTable(String headerText, List list, String SRC_PDF, String fileDir) { + Document document = null; + FileOutputStream fos = null; + String filePath = ""; + String fileName = ""; + try { + // 1. 生成文件名 + fileName = generateFileName(); + + // 2. 确保目录存在 + File dir = new File(fileDir); + if (!dir.exists()) { + dir.mkdirs(); + } + + // 3. 完整文件路径 + filePath = Paths.get(fileDir, fileName).toString(); + + // 创建PDF文档 设置文档边距,避免内容遮挡页眉页脚 + + // 1. 读取原有PDF,获取页面尺寸(保证新文档与原文档格式一致) + PdfReader srcReader = new PdfReader(SRC_PDF); + Rectangle pageSize = srcReader.getPageSize(1); // 取第一页尺寸作为新文档尺寸 + + // 2. 初始化Document(iText 5的核心高层类) + document = new Document(pageSize); + fos = new FileOutputStream(filePath); + // 3. 关联PdfWriter,绑定Document和输出流(5.5.11必须先创建Writer再open Document) + PdfWriter writer = PdfWriter.getInstance(document, fos); + + // 设置页面事件,每页添加文字页眉 + writer.setPageEvent(new TextHeaderEvent(headerText)); + + // 4. 设置PDF属性 + document.addTitle("华西海圻"); + document.addAuthor("华西海圻"); + document.addCreator("华西海圻"); + document.addCreationDate(); + + document.open(); + + // 5. 复制原有PDF的所有页面到新Document中 + copyOriginalPagesToDocument(document, writer, srcReader); + + // 6. 设置中文字体 + BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); + Font headerFont = new Font(bfChinese, 12, Font.BOLD); + Font contentFont = new Font(bfChinese, 10, Font.NORMAL); + + // 7. 表格设置到新的一页 + document.newPage(); + + // 8. 创建表格 + PdfPTable table = new PdfPTable(4); + table.setWidthPercentage(100); + table.setSpacingBefore(10); + + // 9. 表头 + String[] headers = {"签名人", "签名意义", "签名时间", "备注"}; + for (String header : headers) { + PdfPCell cell = new PdfPCell(new Phrase(header, headerFont)); + cell.setHorizontalAlignment(Element.ALIGN_CENTER); + cell.setBackgroundColor(BaseColor.WHITE); + cell.setPadding(8); + cell.setBorderWidth(1); + table.addCell(cell); + } + + // 10. 表格数据 + int rowNum = 0; + for (StudyMethodRead studyMethodRead : list) { + // 交替行颜色 + if (rowNum % 2 == 0) { + table.getDefaultCell().setBackgroundColor(BaseColor.WHITE); + } else { + table.getDefaultCell().setBackgroundColor(BaseColor.WHITE); + } + table.addCell(createCell(studyMethodRead.getQmrMc(), contentFont)); + table.addCell(createCell(studyMethodRead.getQmyy(), contentFont)); + table.addCell(createCell(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, studyMethodRead.getCreateTime()), contentFont)); + table.addCell(createCell(studyMethodRead.getRemark(), contentFont)); + rowNum++; + } + document.add(table); + + log.info("生成成功:{}", filePath); + } catch (Exception e) { + log.error("生成失败", e); + throw new RuntimeException("生成失败: " + e.getMessage()); + } finally { + if (document != null) { + document.close(); + } + if (fos != null) { + try { + fos.close(); + } catch (IOException e) { + log.error("关闭文件流失败", e); + } + } + } + return fileName; + } + + + + /** + * 创建表格 + */ + private static PdfPCell createCell(String content, Font font) { + PdfPCell cell = new PdfPCell(new Phrase(content, font)); + cell.setHorizontalAlignment(Element.ALIGN_CENTER); + cell.setVerticalAlignment(Element.ALIGN_MIDDLE); + cell.setPadding(6); + cell.setMinimumHeight(25); + return cell; + } + + + /** + * 生成文件名 + */ + private static String generateFileName() { + Random random= new Random(); + String timestamp = DateUtils.dateTimeNow("yyyyMMddHHmmss"); + return String.format("%s_%s.pdf", timestamp,random.nextInt(1000)); + } + + + /** + * 页面事件处理类 - 每页添加文字页眉 + */ + static class TextHeaderEvent extends PdfPageEventHelper { + private String headerText; + private BaseFont baseFont; + + public TextHeaderEvent(String headerText) throws Exception { + this.headerText = headerText; + // 创建字体(支持中文) + this.baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); + } + + @Override + public void onEndPage(PdfWriter writer, Document document) { + try { + // 获取页面尺寸 + Rectangle pageSize = document.getPageSize(); + float pageWidth = pageSize.getWidth(); + float pageHeight = pageSize.getHeight(); + + // 设置页眉参数 + float topMargin = 15; // 顶部边距 + float fontSize = 10; // 字体大小 + + // 计算文字宽度(用于居中) + float textWidth = baseFont.getWidthPoint(headerText, fontSize); + + // 计算居中位置 + float textX = (pageWidth - textWidth) / 2; + float textY = pageHeight - topMargin; + + // 获取画布 + PdfContentByte canvas = writer.getDirectContent(); + + // 添加页眉文字 + canvas.beginText(); + canvas.setFontAndSize(baseFont, fontSize); + canvas.setTextMatrix(textX, textY); + canvas.showText(headerText); + canvas.endText(); + + // 添加页眉分隔线(可选) + addHeaderLine(canvas, pageWidth, textY - 10); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void addHeaderLine(PdfContentByte canvas, float pageWidth, float yPos) { + canvas.setLineWidth(0.5f); + canvas.moveTo(50, yPos); + canvas.lineTo(pageWidth - 50, yPos); + canvas.stroke(); + } + } +} \ No newline at end of file