diff --git a/pom.xml b/pom.xml index 07fa62b..226a4e7 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ - 1.8 + 11 5.8.36 5.17.0 3.0.2 @@ -159,6 +159,27 @@ jakarta.xml.bind jakarta.xml.bind-api + + + + com.itextpdf + itextpdf + 5.5.13.3 + + + + + com.itextpdf.tool + xmlworker + 5.5.13.3 + + + + + com.itextpdf + itext-asian + 5.2.0 + diff --git a/src/main/java/com/dpkj/modules/print/controller/MS439Controller.java b/src/main/java/com/dpkj/modules/print/controller/MS439Controller.java index e0c633b..a22252b 100644 --- a/src/main/java/com/dpkj/modules/print/controller/MS439Controller.java +++ b/src/main/java/com/dpkj/modules/print/controller/MS439Controller.java @@ -4,10 +4,13 @@ import com.dpkj.common.dto.LexMarkResultDTO; import com.dpkj.common.vo.Result; import com.dpkj.modules.print.request.MS439Request; import com.dpkj.modules.print.service.MS439PrintService; -import com.dpkj.modules.print.vo.PrinterStatus; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; /** * MS439控制层,利盟打印机 @@ -24,12 +27,28 @@ public class MS439Controller { private MS439PrintService ms439PrintService; @PostMapping("/print") - public Result> print(@Validated @RequestBody MS439Request request){ + public Result> print(@Validated @RequestBody MS439Request request) { return Result.ok(ms439PrintService.printImage(request)); } + /** + * 检验报告打印 + * + * @return + */ + @PostMapping("/printJY") + public Result> printJY() { + MS439Request ms439Request = new MS439Request(); + // 获取检验报告PDF + String path = ms439PrintService.getJYPDFPath(); + ms439Request.setPagesource("A5"); + ms439Request.setFileDir(path); + LexMarkResultDTO result = ms439PrintService.printImage(ms439Request); + return Result.ok(result); + } + @PostMapping("/getStatus") - public Result print(@RequestParam(defaultValue = "A4") String papersource){ + public Result print(@RequestParam(defaultValue = "A4") String papersource) { this.ms439PrintService.getStatus(papersource); return Result.ok(); } diff --git a/src/main/java/com/dpkj/modules/print/service/MS439PrintService.java b/src/main/java/com/dpkj/modules/print/service/MS439PrintService.java index 47af1af..df8d5d3 100644 --- a/src/main/java/com/dpkj/modules/print/service/MS439PrintService.java +++ b/src/main/java/com/dpkj/modules/print/service/MS439PrintService.java @@ -3,11 +3,12 @@ package com.dpkj.modules.print.service; import com.dpkj.common.dto.LexMarkResultDTO; import com.dpkj.modules.print.request.MS439Request; import com.dpkj.modules.print.vo.PrinterStatus; -import javassist.compiler.Lex; public interface MS439PrintService { LexMarkResultDTO printImage(MS439Request request); LexMarkResultDTO getStatus(String papersource); + + String getJYPDFPath(); } diff --git a/src/main/java/com/dpkj/modules/print/service/impl/MS439PrintServiceImpl.java b/src/main/java/com/dpkj/modules/print/service/impl/MS439PrintServiceImpl.java index f8c68ed..61fbc21 100644 --- a/src/main/java/com/dpkj/modules/print/service/impl/MS439PrintServiceImpl.java +++ b/src/main/java/com/dpkj/modules/print/service/impl/MS439PrintServiceImpl.java @@ -6,17 +6,48 @@ import com.dpkj.common.dto.LexMarkDTO; import com.dpkj.common.dto.LexMarkResultDTO; import com.dpkj.common.exception.RRException; import com.dpkj.common.utils.ThirdService; -import com.dpkj.modules.print.enums.*; +import com.dpkj.modules.print.enums.MS439DeviceStatusEnum; +import com.dpkj.modules.print.enums.MS439InkStatusEnum; +import com.dpkj.modules.print.enums.MS439MediaStatusEnum; +import com.dpkj.modules.print.enums.MS439PaperStatusEnum; +import com.dpkj.modules.print.enums.MS439StampStatusEnum; +import com.dpkj.modules.print.enums.MS439TonerStatusEnum; import com.dpkj.modules.print.request.MS439Request; import com.dpkj.modules.print.service.MS439PrintService; import com.dpkj.modules.print.utils.FolderUtils; +import com.dpkj.modules.print.utils.FontLoader; import com.dpkj.modules.print.utils.PDFUtils; import com.dpkj.modules.print.vo.PrinterStatus; +import com.itextpdf.text.BaseColor; +import com.itextpdf.text.Document; +import com.itextpdf.text.DocumentException; +import com.itextpdf.text.Font; +import com.itextpdf.text.PageSize; +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 lombok.extern.slf4j.Slf4j; +import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebApplicationContext; import org.springframework.stereotype.Service; +import org.thymeleaf.TemplateEngine; +import org.thymeleaf.context.Context; +import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver; +import org.thymeleaf.templatemode.TemplateMode; import javax.annotation.Resource; +import java.io.ByteArrayInputStream; import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * 利盟MS439打印机服务 @@ -49,7 +80,7 @@ public class MS439PrintServiceImpl implements MS439PrintService { PrinterStatus ms439 = status.getData(); // 如果是要盖章,校验盖章机器是否正常 - if ( request.getStamp() == 1) { + if (request.getStamp() == 1) { String deviceExStatus = ms439.getStDeviceExStatus(); if (deviceExStatus == null || deviceExStatus.equals("")) { throw new RRException("获取打印机设备状态出问题"); @@ -60,7 +91,7 @@ public class MS439PrintServiceImpl implements MS439PrintService { } String device = devices[1]; // 校验盖章机是否正常,除了HEALTHY都抛异常 - if (!device.equals(MS439StampStatusEnum.HEALTHY.getPrintCode()) ) { + if (!device.equals(MS439StampStatusEnum.HEALTHY.getPrintCode())) { throw new RRException(MS439StampStatusEnum.getPCode(device), MS439StampStatusEnum.getMessage(device)); } @@ -72,7 +103,7 @@ public class MS439PrintServiceImpl implements MS439PrintService { lexMarkDTO.setDevName("HtmPrinter"); lexMarkDTO.setPluginMethod("exec"); - JSONObject param = new JSONObject(); + JSONObject param = new JSONObject(); // printType 选择箱子 // param.put("prtData", String.format("PrintType=%d;pagesource=%s;copies=%d;file[0]=%s;stamp=%d;duplex=%d;color=%d;direction=%d", @@ -104,7 +135,7 @@ public class MS439PrintServiceImpl implements MS439PrintService { lexMarkDTO.setParam(param.toString()); LexMarkResultDTO paramLexMarkResultDTO = thirdService.callDevice(lexMarkDTO, LexMarkResultDTO.Param.class); - if ( paramLexMarkResultDTO.getData().getResult() != 0){ + if (paramLexMarkResultDTO.getData().getResult() != 0) { throw new RRException(500, paramLexMarkResultDTO.getData().getResult() + ""); } @@ -132,7 +163,7 @@ public class MS439PrintServiceImpl implements MS439PrintService { lexMarkDTO.setPluginMethod("exec"); LexMarkResultDTO status = thirdService.callDevice(lexMarkDTO, PrinterStatus.class); - if ( status.getResult() != 0){ + if (status.getResult() != 0) { thirdService.open("HtmPrinter", 0); status = thirdService.callDevice(lexMarkDTO, PrinterStatus.class); } @@ -142,7 +173,7 @@ public class MS439PrintServiceImpl implements MS439PrintService { throw new RRException("获取打印机纸张状态出问题"); } String[] papers = stPaperEx.split("\\|"); - if ( papers.length < 2) { + if (papers.length < 2) { throw new RRException("打印机纸盒数量不对"); } String paperStatus = ""; @@ -154,13 +185,13 @@ public class MS439PrintServiceImpl implements MS439PrintService { if (papersource.equals("A5")) { paperStatus = printerConfig.getLevelOne().equals("A5") ? papers[0] : papers[1]; } - if ( !(paperStatus.equals(MS439PaperStatusEnum.PAPERFULL.getPrintCode()) || paperStatus.equals(MS439PaperStatusEnum.PAPERLOW.getPrintCode()))){ + if (!(paperStatus.equals(MS439PaperStatusEnum.PAPERFULL.getPrintCode()) || paperStatus.equals(MS439PaperStatusEnum.PAPERLOW.getPrintCode()))) { throw new RRException(500, paperStatus); } PrinterStatus ms439 = status.getData(); // 校验打印机是否正常,除了HEALTHY都抛异常 - if (!ms439.getStDeviceStatus().equals(MS439DeviceStatusEnum.HEALTHY.getPrintCode()) ) { + if (!ms439.getStDeviceStatus().equals(MS439DeviceStatusEnum.HEALTHY.getPrintCode())) { throw new RRException(500, ms439.getStDeviceStatus()); } @@ -170,19 +201,131 @@ public class MS439PrintServiceImpl implements MS439PrintService { } // 校验磁带 满或者少才放行 - if ( !(ms439.getStToner().equals(MS439TonerStatusEnum.TONERFULL.getPrintCode()) || ms439.getStToner().equals(MS439TonerStatusEnum.TONERLOW.getPrintCode()))){ + if (!(ms439.getStToner().equals(MS439TonerStatusEnum.TONERFULL.getPrintCode()) || ms439.getStToner().equals(MS439TonerStatusEnum.TONERLOW.getPrintCode()))) { throw new RRException(500, ms439.getStToner()); } // 校验墨盒 满或者少才放行,当前获取为未知 - if ( false && !(ms439.getStInk().equals(MS439InkStatusEnum.INKFULL.getPrintCode()) || ms439.getStInk().equals(MS439InkStatusEnum.INKLOW.getPrintCode()) - || ms439.getStInk().equals(MS439InkStatusEnum.INKUNKNOWN.getPrintCode()))){ + if (false && !(ms439.getStInk().equals(MS439InkStatusEnum.INKFULL.getPrintCode()) || ms439.getStInk().equals(MS439InkStatusEnum.INKLOW.getPrintCode()) + || ms439.getStInk().equals(MS439InkStatusEnum.INKUNKNOWN.getPrintCode()))) { throw new RRException(500, ms439.getStInk()); } return status; } + @Override + public String getJYPDFPath() { + // 1. 准备输出路径 + String dirPath = "D:/TempJYPDF/"; + File dir = new File(dirPath);// 确保目录存在 + if (!dir.exists()) { + dir.mkdirs(); + } + String fileName = "report_jy_" + System.currentTimeMillis() + ".pdf"; + String pdfPath = dirPath + fileName; + try { + // 2. 准备模板数据 + Map data = prepareReportData(); + // 3. 渲染Thymeleaf模板 + String htmlContent = renderThymeleafTemplate(data); + // 4. 生成PDF文件 + createPdfFromHtml(htmlContent, pdfPath); + + return pdfPath; + } catch (Exception e) { + e.printStackTrace(); // 打印完整异常堆栈 + throw new RuntimeException("PDF生成失败: " + e.getMessage()); + } + } + + private void createPdfFromHtml(String html, String outputPath) + throws IOException, DocumentException { + + // 大小为A5纸 + Document document = new Document(PageSize.A5); + try (OutputStream os = Files.newOutputStream(Paths.get(outputPath))) { + PdfWriter writer = PdfWriter.getInstance(document, os); + document.open(); + + // 加载自定义字体 + BaseFont simfangFont = FontLoader.loadFont("/font/simfang.ttf"); + + // 创建自定义字体提供器 + XMLWorkerFontProvider fontProvider = new XMLWorkerFontProvider() { + @Override + public Font getFont(String fontname, String encoding, boolean embedded, float size, int style, BaseColor color) { + return new Font(simfangFont, size, style, color); + } + }; + + // 解析 HTML 并生成 PDF + XMLWorkerHelper.getInstance().parseXHtml( + writer, document, + new ByteArrayInputStream(html.getBytes(StandardCharsets.UTF_8)), + null, StandardCharsets.UTF_8, + fontProvider // 注入字体提供器 + ); + document.close(); // 这里关闭,确保 OutputStream 还没被关闭 + } + } + + // 模板渲染方法(保持不变) + private String renderThymeleafTemplate(Map data) { + // 设置模板数据 + Context context = new Context(); + context.setVariables(data); + + // 填充数据到html + TemplateEngine templateEngine = new TemplateEngine(); + SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver(); + resolver.setPrefix("classpath:/templates/"); + resolver.setSuffix(".html"); + resolver.setTemplateMode(TemplateMode.HTML); + resolver.setCacheable(true); + resolver.setApplicationContext(new AnnotationConfigReactiveWebApplicationContext()); + templateEngine.setTemplateResolver(resolver); + return templateEngine.process("reportJY", context); + } + + // 报告数据准备(根据实际业务实现) + private Map prepareReportData() { + Map data = new HashMap<>(); + // 患者信息 + Map patient = new HashMap<>(); + patient.put("name", "余文财"); + patient.put("gender", "男"); + patient.put("age", "25岁"); + patient.put("medicalRecord", "20240624001"); + patient.put("department", "内科"); + patient.put("bedNumber", "A301"); + data.put("patient", patient); + + // 检验项目数据 + List> items = new ArrayList<>(); + addItem(items, "白细胞计数", "7.26", "3.5-9.5", "10^9/L", false); + addItem(items, "血红蛋白", "165", "115-150", "g/L", true); + // ...其他检验项 + data.put("items", items); + + // 系统信息 + data.put("reportTime", new Date()); + data.put("doctor", "李医师"); + data.put("reviewer", "王主任"); + + return data; + } + + private void addItem(List> items, String name, + String value, String range, String unit, boolean abnormal) { + Map item = new HashMap<>(); + item.put("name", name); + item.put("result", value); + item.put("referenceRange", range); + item.put("unit", unit); + item.put("isAbnormal", abnormal); + items.add(item); + } } diff --git a/src/main/java/com/dpkj/modules/print/utils/FontLoader.java b/src/main/java/com/dpkj/modules/print/utils/FontLoader.java new file mode 100644 index 0000000..cd04578 --- /dev/null +++ b/src/main/java/com/dpkj/modules/print/utils/FontLoader.java @@ -0,0 +1,31 @@ +package com.dpkj.modules.print.utils; + +import com.itextpdf.text.pdf.BaseFont; + +import java.io.InputStream; + +/** + * @author 余文财 + * @description 字体加载 + * @date 2025.6.24 + */ +public class FontLoader { + public static BaseFont loadFont(String resourcePath) { + try (InputStream fontStream = FontLoader.class.getResourceAsStream(resourcePath)) { + if (fontStream == null) { + throw new IllegalArgumentException("字体文件未找到: " + resourcePath); + } + // 创建支持中文的 BaseFont + return BaseFont.createFont( + resourcePath, + BaseFont.IDENTITY_H, + BaseFont.EMBEDDED, + false, + fontStream.readAllBytes(), + null + ); + } catch (Exception e) { + throw new RuntimeException("字体加载失败: " + resourcePath, e); + } + } +} diff --git a/src/main/resources/font/simfang.ttf b/src/main/resources/font/simfang.ttf new file mode 100644 index 0000000..5e5930e Binary files /dev/null and b/src/main/resources/font/simfang.ttf differ diff --git a/src/main/resources/templates/reportJY.html b/src/main/resources/templates/reportJY.html new file mode 100644 index 0000000..44b8c8c --- /dev/null +++ b/src/main/resources/templates/reportJY.html @@ -0,0 +1,69 @@ + + + + + 检验报告单 + + +
+ +
+

澜沧拉祜族自治县中医医院血常规检验报告单

+

报告时间:

+
+ + +
+ + + + + + + + + + + + + + + + + + + +
姓名性别
年龄病历号
科室床号
+
+ + + + + + + + + + + + + + + + + + + + +
检测项目结果参考范围单位
+ + +
+
检验医生:
+
审核医生:
+
声明: 本报告仅对此标本负责,如有疑问请3日内联系检验科
+
+
+ +