打印报告功能

This commit is contained in:
jiangs 2025-09-30 10:14:47 +08:00
parent 61f7e145b0
commit b23efa4fad
10 changed files with 634 additions and 334 deletions

View File

@ -1,17 +1,19 @@
package com.czlis.common.utils.file; package com.czlis.common.utils.file;
import java.io.ByteArrayInputStream; import java.io.*;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URL; import java.net.URL;
import java.net.URLConnection; import java.net.URLConnection;
import java.util.Arrays; import java.util.Arrays;
import java.util.Objects;
import java.util.UUID;
import org.apache.poi.util.IOUtils; import org.apache.poi.util.IOUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.czlis.common.config.RuoYiConfig; import com.czlis.common.config.RuoYiConfig;
import com.czlis.common.constant.Constants; import com.czlis.common.constant.Constants;
import com.czlis.common.utils.StringUtils; import com.czlis.common.utils.StringUtils;
import org.springframework.util.ResourceUtils;
/** /**
* 图片处理工具类 * 图片处理工具类
@ -95,4 +97,227 @@ public class ImageUtils
IOUtils.closeQuietly(in); IOUtils.closeQuietly(in);
} }
} }
/**
* 生成图片到服务的static目录(Spring Boot场景)
* @param imageBytes 图片二进制数据
* @param staticSubDir static下的子目录(如"report_imgs/",避免文件混乱)
* @param fileName 自定义文件名(如"lab_report_20240520.jpg",建议加唯一标识)
* @return 生成的文件对象(包含static目录下的路径)
* @throws IOException 路径获取/文件写入失败
*/
public static File generateToStaticDir(byte[] imageBytes, String staticSubDir, String fileName) throws IOException {
// 1. 校验入参
Objects.requireNonNull(imageBytes, "图片二进制数据不能为null");
Objects.requireNonNull(staticSubDir, "static子目录不能为null");
Objects.requireNonNull(fileName, "文件名不能为null");
if (!fileName.contains(".")) {
throw new IllegalArgumentException("文件名必须包含后缀(如.jpg/.bmp)");
}
// 2. 获取服务的static目录绝对路径(Spring Boot核心:通过ResourceUtils获取)
File staticDir = null;
try {
// 本地开发环境:target/classes/static(Maven/Gradle构建后路径)
// 生产环境(Jar包部署):Jar包内的static目录(需注意只读问题,下文会说明)
staticDir = new File(ResourceUtils.getURL("classpath:static").getPath());
} catch (FileNotFoundException e) {
// 若Jar包部署时获取不到classpath:static(因Jar包内资源无法直接以File形式访问)
// 改用服务运行目录下的static(需手动创建)
staticDir = new File(System.getProperty("user.dir") + File.separator + "static");
}
// 3. 创建static下的子目录(如static/report_imgs/,避免所有文件堆在static根目录)
File targetDir = new File(staticDir, staticSubDir);
if (!targetDir.exists()) {
boolean mkdirsSuccess = targetDir.mkdirs(); // 递归创建多级目录
if (!mkdirsSuccess) {
throw new IOException("创建static子目录失败:" + targetDir.getAbsolutePath());
}
}
// 4. 检查static目录写入权限
if (!targetDir.canWrite()) {
throw new IOException("static目录无写入权限:" + targetDir.getAbsolutePath());
}
// 5. 创建目标文件(加唯一标识避免同名覆盖,如在文件名前加UUID)
//String uniqueFileName = UUID.randomUUID().toString().replace("-", "") + "_" + fileName;
File targetFile = new File(targetDir, fileName);
// 6. 写入图片数据
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(targetFile))) {
bos.write(imageBytes);
bos.flush();
}
System.out.println("图片已生成到static目录:" + targetFile.getAbsolutePath());
return targetFile;
}
// 支持的图片格式(文件头标识 + 后缀名映射)
private enum ImageFormat {
JPG(new byte[]{(byte) 0xFF, (byte) 0xD8, (byte) 0xFF}, ".jpg"),
PNG(new byte[]{(byte) 0x89, (byte) 0x50, (byte) 0x4E, (byte) 0x47}, ".png"),
GIF(new byte[]{(byte) 0x47, (byte) 0x49, (byte) 0x46, (byte) 0x38}, ".gif"),
BMP(new byte[]{(byte) 0x42, (byte) 0x4D}, ".bmp"); // BMP格式文件头标识
private final byte[] fileHeader; // 图片文件头(用于格式校验)
private final String suffix; // 对应的文件后缀
ImageFormat(byte[] fileHeader, String suffix) {
this.fileHeader = fileHeader;
this.suffix = suffix;
}
// 根据文件头匹配图片格式
public static ImageFormat matchFormat(byte[] data) {
if (data == null || data.length < 2) { // 至少需要2字节判断BMP格式
return null;
}
for (ImageFormat format : values()) {
// 检查数据长度是否足够
if (data.length < format.fileHeader.length) {
continue;
}
boolean match = true;
for (int i = 0; i < format.fileHeader.length; i++) {
if (data[i] != format.fileHeader[i]) {
match = false;
break;
}
}
if (match) {
return format;
}
}
return null;
}
}
/**
* 核心方法:将byte[]二进制数据生成图片临时文件
* @param imageBytes 图片二进制数据(必须是JPG/PNG/GIF/BMP格式)
* @param tempPrefix 临时文件前缀(如"report_img_",用于区分不同业务的临时文件)
* @return 生成的临时图片文件(包含绝对路径,可直接给报告模板引用)
* @throws IllegalArgumentException 入参非法(空数据、非图片格式)
* @throws IOException 临时文件创建/写入失败
*/
public static File generateTempImage(byte[] imageBytes, String tempPrefix) throws IllegalArgumentException, IOException {
// 1. 入参校验:避免空数据
Objects.requireNonNull(imageBytes, "图片二进制数据[imageBytes]不能为null");
if (imageBytes.length == 0) {
throw new IllegalArgumentException("图片二进制数据[imageBytes]长度不能为0");
}
Objects.requireNonNull(tempPrefix, "临时文件前缀[tempPrefix]不能为null");
if (tempPrefix.trim().isEmpty()) {
throw new IllegalArgumentException("临时文件前缀[tempPrefix]不能为空字符串");
}
// 2. 图片格式校验:确保是支持的图片类型(避免生成无效文件)
ImageFormat imageFormat = ImageFormat.matchFormat(imageBytes);
if (imageFormat == null) {
throw new IllegalArgumentException("不支持的图片格式!仅支持JPG/PNG/GIF/BMP");
}
// 3. 创建临时文件
File tempImageFile = File.createTempFile(tempPrefix, imageFormat.suffix);
// 4. 临时文件安全配置
tempImageFile.deleteOnExit();
setFileSafePermission(tempImageFile);
// 5. 写入二进制数据到临时文件
try (BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(tempImageFile, false)
)) {
bos.write(imageBytes);
bos.flush();
}
// 6. 二次校验
if (!tempImageFile.exists() || tempImageFile.length() != imageBytes.length) {
throw new IOException("临时图片文件生成失败!文件大小不匹配或文件未创建");
}
return tempImageFile;
}
/**
* 重载方法:指定图片格式(跳过自动校验,适用于已知格式的场景)
* @param imageBytes 图片二进制数据
* @param tempPrefix 临时文件前缀
* @param targetSuffix 目标格式后缀(如".jpg", ".png",必须带".")
* @return 临时图片文件
* @throws IOException 临时文件操作异常
*/
public static File generateTempImage(byte[] imageBytes, String tempPrefix, String targetSuffix) throws IOException {
// 入参校验
Objects.requireNonNull(imageBytes, "图片二进制数据[imageBytes]不能为null");
Objects.requireNonNull(tempPrefix, "临时文件前缀[tempPrefix]不能为null");
Objects.requireNonNull(targetSuffix, "目标格式后缀[targetSuffix]不能为null");
if (!targetSuffix.startsWith(".")) {
throw new IllegalArgumentException("目标格式后缀必须以'.'开头(如\".jpg\")");
}
// 创建临时文件
File tempImageFile = File.createTempFile(tempPrefix, targetSuffix);
tempImageFile.deleteOnExit();
setFileSafePermission(tempImageFile);
// 写入数据
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(tempImageFile))) {
bos.write(imageBytes);
bos.flush();
}
// 校验文件
if (!tempImageFile.exists()) {
throw new IOException("指定格式的临时图片文件生成失败");
}
return tempImageFile;
}
/**
* 辅助方法:设置临时文件安全权限(跨平台兼容)
*/
private static void setFileSafePermission(File file) {
if (file == null || !file.exists()) {
return;
}
// Windows系统:通过设置文件属性隐藏
if (System.getProperty("os.name").toLowerCase().contains("windows")) {
try {
Process process = Runtime.getRuntime().exec("attrib +h " + file.getAbsolutePath());
process.waitFor();
} catch (Exception e) {
System.err.println("临时文件隐藏失败:" + e.getMessage());
}
} else {
// Linux/Mac系统:设置权限为"仅当前用户读写"(600权限)
file.setReadable(true, true);
file.setWritable(true, true);
file.setExecutable(false);
}
}
/**
* 辅助方法:手动删除临时文件
* @param tempFile 临时文件对象
* @return 删除成功返回true,失败返回false
*/
public static boolean deleteTempImage(File tempFile) {
if (tempFile == null || !tempFile.exists()) {
System.out.println("临时文件不存在,无需删除");
return true;
}
boolean deleted = tempFile.delete();
if (deleted) {
System.out.println("临时文件删除成功:" + tempFile.getAbsolutePath());
} else {
System.err.println("临时文件删除失败:" + tempFile.getAbsolutePath());
}
return deleted;
}
} }

View File

@ -22,16 +22,8 @@ public class BarCodeParam {
private String yq; private String yq;
private String ybh; private String ybh;
private String hospitalName; private String hospitalName;
private String pic1; /**
private String pic2; * 图片数组
private String pic3; */
private String pic4; private String[] pic;
private String pic5;
private String pic6;
private String pic7;
private String pic8;
private String pic9;
private String pic10;
private String pic11;
private String pic12;
} }

View File

@ -1,234 +0,0 @@
package com.czlis.interfaceCommon.utils;
import org.springframework.util.ResourceUtils;
import java.io.*;
import java.util.Objects;
import java.util.UUID;
public class ImageUtils {
/**
* 生成图片到服务的static目录(Spring Boot场景)
* @param imageBytes 图片二进制数据
* @param staticSubDir static下的子目录(如"report_imgs/",避免文件混乱)
* @param fileName 自定义文件名(如"lab_report_20240520.jpg",建议加唯一标识)
* @return 生成的文件对象(包含static目录下的路径)
* @throws IOException 路径获取/文件写入失败
*/
public static File generateToStaticDir(byte[] imageBytes, String staticSubDir, String fileName) throws IOException {
// 1. 校验入参
Objects.requireNonNull(imageBytes, "图片二进制数据不能为null");
Objects.requireNonNull(staticSubDir, "static子目录不能为null");
Objects.requireNonNull(fileName, "文件名不能为null");
if (!fileName.contains(".")) {
throw new IllegalArgumentException("文件名必须包含后缀(如.jpg/.bmp)");
}
// 2. 获取服务的static目录绝对路径(Spring Boot核心:通过ResourceUtils获取)
File staticDir = null;
try {
// 本地开发环境:target/classes/static(Maven/Gradle构建后路径)
// 生产环境(Jar包部署):Jar包内的static目录(需注意只读问题,下文会说明)
staticDir = new File(ResourceUtils.getURL("classpath:static").getPath());
} catch (FileNotFoundException e) {
// 若Jar包部署时获取不到classpath:static(因Jar包内资源无法直接以File形式访问)
// 改用服务运行目录下的static(需手动创建)
staticDir = new File(System.getProperty("user.dir") + File.separator + "static");
}
// 3. 创建static下的子目录(如static/report_imgs/,避免所有文件堆在static根目录)
File targetDir = new File(staticDir, staticSubDir);
if (!targetDir.exists()) {
boolean mkdirsSuccess = targetDir.mkdirs(); // 递归创建多级目录
if (!mkdirsSuccess) {
throw new IOException("创建static子目录失败:" + targetDir.getAbsolutePath());
}
}
// 4. 检查static目录写入权限
if (!targetDir.canWrite()) {
throw new IOException("static目录无写入权限:" + targetDir.getAbsolutePath());
}
// 5. 创建目标文件(加唯一标识避免同名覆盖,如在文件名前加UUID)
String uniqueFileName = UUID.randomUUID().toString().replace("-", "") + "_" + fileName;
File targetFile = new File(targetDir, uniqueFileName);
// 6. 写入图片数据
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(targetFile))) {
bos.write(imageBytes);
bos.flush();
}
System.out.println("图片已生成到static目录:" + targetFile.getAbsolutePath());
return targetFile;
}
// 支持的图片格式(文件头标识 + 后缀名映射)
private enum ImageFormat {
JPG(new byte[]{(byte) 0xFF, (byte) 0xD8, (byte) 0xFF}, ".jpg"),
PNG(new byte[]{(byte) 0x89, (byte) 0x50, (byte) 0x4E, (byte) 0x47}, ".png"),
GIF(new byte[]{(byte) 0x47, (byte) 0x49, (byte) 0x46, (byte) 0x38}, ".gif"),
BMP(new byte[]{(byte) 0x42, (byte) 0x4D}, ".bmp"); // BMP格式文件头标识
private final byte[] fileHeader; // 图片文件头(用于格式校验)
private final String suffix; // 对应的文件后缀
ImageFormat(byte[] fileHeader, String suffix) {
this.fileHeader = fileHeader;
this.suffix = suffix;
}
// 根据文件头匹配图片格式
public static ImageFormat matchFormat(byte[] data) {
if (data == null || data.length < 2) { // 至少需要2字节判断BMP格式
return null;
}
for (ImageFormat format : values()) {
// 检查数据长度是否足够
if (data.length < format.fileHeader.length) {
continue;
}
boolean match = true;
for (int i = 0; i < format.fileHeader.length; i++) {
if (data[i] != format.fileHeader[i]) {
match = false;
break;
}
}
if (match) {
return format;
}
}
return null;
}
}
/**
* 核心方法:将byte[]二进制数据生成图片临时文件
* @param imageBytes 图片二进制数据(必须是JPG/PNG/GIF/BMP格式)
* @param tempPrefix 临时文件前缀(如"report_img_",用于区分不同业务的临时文件)
* @return 生成的临时图片文件(包含绝对路径,可直接给报告模板引用)
* @throws IllegalArgumentException 入参非法(空数据、非图片格式)
* @throws IOException 临时文件创建/写入失败
*/
public static File generateTempImage(byte[] imageBytes, String tempPrefix) throws IllegalArgumentException, IOException {
// 1. 入参校验:避免空数据
Objects.requireNonNull(imageBytes, "图片二进制数据[imageBytes]不能为null");
if (imageBytes.length == 0) {
throw new IllegalArgumentException("图片二进制数据[imageBytes]长度不能为0");
}
Objects.requireNonNull(tempPrefix, "临时文件前缀[tempPrefix]不能为null");
if (tempPrefix.trim().isEmpty()) {
throw new IllegalArgumentException("临时文件前缀[tempPrefix]不能为空字符串");
}
// 2. 图片格式校验:确保是支持的图片类型(避免生成无效文件)
ImageFormat imageFormat = ImageFormat.matchFormat(imageBytes);
if (imageFormat == null) {
throw new IllegalArgumentException("不支持的图片格式!仅支持JPG/PNG/GIF/BMP");
}
// 3. 创建临时文件
File tempImageFile = File.createTempFile(tempPrefix, imageFormat.suffix);
// 4. 临时文件安全配置
tempImageFile.deleteOnExit();
setFileSafePermission(tempImageFile);
// 5. 写入二进制数据到临时文件
try (BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(tempImageFile, false)
)) {
bos.write(imageBytes);
bos.flush();
}
// 6. 二次校验
if (!tempImageFile.exists() || tempImageFile.length() != imageBytes.length) {
throw new IOException("临时图片文件生成失败!文件大小不匹配或文件未创建");
}
return tempImageFile;
}
/**
* 重载方法:指定图片格式(跳过自动校验,适用于已知格式的场景)
* @param imageBytes 图片二进制数据
* @param tempPrefix 临时文件前缀
* @param targetSuffix 目标格式后缀(如".jpg", ".png",必须带".")
* @return 临时图片文件
* @throws IOException 临时文件操作异常
*/
public static File generateTempImage(byte[] imageBytes, String tempPrefix, String targetSuffix) throws IOException {
// 入参校验
Objects.requireNonNull(imageBytes, "图片二进制数据[imageBytes]不能为null");
Objects.requireNonNull(tempPrefix, "临时文件前缀[tempPrefix]不能为null");
Objects.requireNonNull(targetSuffix, "目标格式后缀[targetSuffix]不能为null");
if (!targetSuffix.startsWith(".")) {
throw new IllegalArgumentException("目标格式后缀必须以'.'开头(如\".jpg\")");
}
// 创建临时文件
File tempImageFile = File.createTempFile(tempPrefix, targetSuffix);
tempImageFile.deleteOnExit();
setFileSafePermission(tempImageFile);
// 写入数据
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(tempImageFile))) {
bos.write(imageBytes);
bos.flush();
}
// 校验文件
if (!tempImageFile.exists()) {
throw new IOException("指定格式的临时图片文件生成失败");
}
return tempImageFile;
}
/**
* 辅助方法:设置临时文件安全权限(跨平台兼容)
*/
private static void setFileSafePermission(File file) {
if (file == null || !file.exists()) {
return;
}
// Windows系统:通过设置文件属性隐藏
if (System.getProperty("os.name").toLowerCase().contains("windows")) {
try {
Process process = Runtime.getRuntime().exec("attrib +h " + file.getAbsolutePath());
process.waitFor();
} catch (Exception e) {
System.err.println("临时文件隐藏失败:" + e.getMessage());
}
} else {
// Linux/Mac系统:设置权限为"仅当前用户读写"(600权限)
file.setReadable(true, true);
file.setWritable(true, true);
file.setExecutable(false);
}
}
/**
* 辅助方法:手动删除临时文件
* @param tempFile 临时文件对象
* @return 删除成功返回true,失败返回false
*/
public static boolean deleteTempImage(File tempFile) {
if (tempFile == null || !tempFile.exists()) {
System.out.println("临时文件不存在,无需删除");
return true;
}
boolean deleted = tempFile.delete();
if (deleted) {
System.out.println("临时文件删除成功:" + tempFile.getAbsolutePath());
} else {
System.err.println("临时文件删除失败:" + tempFile.getAbsolutePath());
}
return deleted;
}
}

View File

@ -3,10 +3,12 @@ package com.czlis.interfaceCommon.utils;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.codec.Base64; import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.StrUtil;
import com.czlis.common.config.RuoYiConfig; import com.czlis.common.config.RuoYiConfig;
import com.czlis.common.core.domain.Result; import com.czlis.common.core.domain.Result;
import com.czlis.common.core.domain.entity.lis.LabGraph; import com.czlis.common.core.domain.entity.lis.LabGraph;
import com.czlis.common.utils.file.FileUtils; import com.czlis.common.utils.file.FileUtils;
import com.czlis.common.utils.file.ImageUtils;
import com.czlis.common.utils.ip.IpUtils; import com.czlis.common.utils.ip.IpUtils;
import com.czlis.common.utils.uuid.UUID; import com.czlis.common.utils.uuid.UUID;
import com.czlis.interfaceCommon.mapper.BackPaperMapper; import com.czlis.interfaceCommon.mapper.BackPaperMapper;
@ -26,6 +28,7 @@ import net.sf.jasperreports.engine.JREmptyDataSource;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import javax.sql.DataSource; import javax.sql.DataSource;
import java.io.File; import java.io.File;
@ -34,8 +37,6 @@ import java.sql.Connection;
import java.util.*; import java.util.*;
@Component @Component
@Slf4j @Slf4j
public class ReportUtil { public class ReportUtil {
@ -100,7 +101,7 @@ public class ReportUtil {
try { try {
//构造数据 //构造数据
System.out.println("入参参数:"+parameters.toString()); System.out.println("入参参数:" + parameters.toString());
JasperReportUtil.print(RuoYiConfig.getMzPrintName(), "backpaper", parameters, detailList); JasperReportUtil.print(RuoYiConfig.getMzPrintName(), "backpaper", parameters, detailList);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@ -108,42 +109,62 @@ public class ReportUtil {
} }
} }
public Result printToPdf(BarCodeParam barCodeParam, String pdfName){ public Result printToPdf(BarCodeParam barCodeParam, String pdfName) {
String templatePath = RuoYiConfig.getProfile()+"/templates/barcode_zy.jrxml"; // 模板文件路径 String templatePath = RuoYiConfig.getProfile() + "/templates/barcode_zy.jrxml"; // 模板文件路径
return printToPdf("barcode_zy",barCodeParam,pdfName,false); return printToPdf("barcode_zy", barCodeParam, pdfName, false);
} }
public Result printToPdf(String templatename,BarCodeParam barCodeParam, String pdfName,boolean base64){ public Result printToPdf(String templatename, BarCodeParam barCodeParam, String pdfName, boolean base64) {
String outputPath = RuoYiConfig.getProfile()+"/config/static/printPDF/"+UUID.randomUUID().toString()+".pdf"; // PDF输出路径(多级目录会自动创建) String outputPath = RuoYiConfig.getProfile() + "/config/static/printPDF/" + UUID.randomUUID().toString() + ".pdf"; // PDF输出路径(多级目录会自动创建)
// log.info("打印输入输出地址:{},{}",path,outputPath); // log.info("打印输入输出地址:{},{}",path,outputPath);
Map<String, Object> stringObjectMap = BeanUtil.beanToMap(barCodeParam); Map<String, Object> stringObjectMap = BeanUtil.beanToMap(barCodeParam);
try { try {
Connection connection = dataSource.getConnection(); Connection connection = dataSource.getConnection();
//JasperReportUtil.generatePdf(templatename,outputPath,stringObjectMap,connection); //JasperReportUtil.generatePdf(templatename,outputPath,stringObjectMap,connection);
JasperReportUtil.exportToPdf(templatename,stringObjectMap,connection,outputPath); JasperReportUtil.exportToPdf(templatename, stringObjectMap, connection, outputPath);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
log.error("打印条码失败,参数{}",barCodeParam,e); log.error("打印条码失败,参数{}", barCodeParam, e);
} }
String httpPath = getPrintURL(pdfName); String httpPath = getPrintURL(pdfName);
log.info("传给前端的pdf地址:{}",httpPath); log.info("传给前端的pdf地址:{}", httpPath);
if(base64){ if (base64) {
//删除图片文件
String[] pic = barCodeParam.getPic();
if(pic.length > 0){
for (int i = 0; i < pic.length; i++) {
String picFilePath = RuoYiConfig.getProfile() + "/config/static/graphs/"+ StrUtil.splitToArray(pic[i], "graphs/")[1];
FileUtils.deleteFile(picFilePath);
}
}
//删除最后给前端的pdf文件
File file = new File(outputPath); File file = new File(outputPath);
String data=Base64.encode(file); String data = Base64.encode(file);
FileUtils.deleteFile(outputPath); FileUtils.deleteFile(outputPath);
return new Result("0","打印成功!",data); return new Result("0", "打印成功!", data);
}else{ } else {
return new Result("0","打印成功!",httpPath); return new Result("0", "打印成功!", httpPath);
} }
} }
public String getPrintURL(String pdfName){ public String getPrintURL(String pdfName) {
String httpPath = ""; String httpPath = "";
if(printURL == null || printURL.equals("")){ if (printURL == null || printURL.equals("")) {
httpPath = "http://"+ IpUtils.getHostIp() +":" + port + "/printPDF/"+pdfName+".pdf"; httpPath = "http://" + IpUtils.getHostIp() + ":" + port + "/printPDF/" + pdfName + ".pdf";
}else{ } else {
httpPath = "http://"+ printURL +":" + port + "/printPDF/"+pdfName+".pdf"; httpPath = "http://" + printURL + ":" + port + "/printPDF/" + pdfName + ".pdf";
}
return httpPath;
}
public String getHttpURL(String pathChild) {
String httpPath = "";
if (printURL == null || printURL.equals("")) {
httpPath = "http://" + IpUtils.getHostIp() + ":" + port + "/" + pathChild;
} else {
httpPath = "http://" + printURL + ":" + port + "/" + pathChild;
} }
return httpPath; return httpPath;
@ -151,63 +172,64 @@ public class ReportUtil {
/** /**
* 判断当前报告单是否使用A4报告单 * 判断当前报告单是否使用A4报告单
*
* @param jyrq * @param jyrq
* @param yq * @param yq
* @param ybh * @param ybh
* @return * @return
*/ */
public String getReportPaperSize(Date jyrq,String yq,String ybh){ public String getReportPaperSize(Date jyrq, String yq, String ybh) {
//是否分A4,A5报告单 //是否分A4,A5报告单
String NOBOTH =commonUtil.getComOptValue(yq,"NOBOTH"); String NOBOTH = commonUtil.getComOptValue(yq, "NOBOTH");
//NOBOTH=0全部A5 //NOBOTH=0全部A5
if("".equals(NOBOTH)||NOBOTH==null||"0".equals(NOBOTH)){ if ("".equals(NOBOTH) || NOBOTH == null || "0".equals(NOBOTH)) {
return "A5"; return "A5";
} }
//NOBOTH=1全部A4 //NOBOTH=1全部A4
if("1".equals(NOBOTH)){ if ("1".equals(NOBOTH)) {
return "A4"; return "A4";
} }
//NOBOTH=2报告一A4,=3报告二A4 //NOBOTH=2报告一A4,=3报告二A4
//当前仪器是否开启双报告单模式,未开启则直接判断纸张 //当前仪器是否开启双报告单模式,未开启则直接判断纸张
String DOUBLEREPORT=commonUtil.getComOptValue(yq,"DOUBLEREPORT"); String DOUBLEREPORT = commonUtil.getComOptValue(yq, "DOUBLEREPORT");
if("".equals(DOUBLEREPORT)||DOUBLEREPORT==null||"0".equals(DOUBLEREPORT)){ if ("".equals(DOUBLEREPORT) || DOUBLEREPORT == null || "0".equals(DOUBLEREPORT)) {
if("2".equals(NOBOTH)){ if ("2".equals(NOBOTH)) {
return "A4"; return "A4";
}else { } else {
return "A5"; return "A5";
} }
} }
//判断细菌仪使用的报告单模板 //判断细菌仪使用的报告单模板
String yqdl = commonUtil.getYqdl(yq); String yqdl = commonUtil.getYqdl(yq);
if("细菌仪".equals(yqdl)){ if ("细菌仪".equals(yqdl)) {
int ym=commonUtil.getLabResultMedCount(jyrq,yq,ybh); int ym = commonUtil.getLabResultMedCount(jyrq, yq, ybh);
if(ym>1){ if (ym > 1) {
if("2".equals(NOBOTH)){ if ("2".equals(NOBOTH)) {
return "A4"; return "A4";
}else { } else {
return "A5"; return "A5";
} }
}else{ } else {
if("3".equals(NOBOTH)){ if ("3".equals(NOBOTH)) {
return "A4"; return "A4";
}else { } else {
return "A5"; return "A5";
} }
} }
} }
//常规报告如果报告使用报告二模板,判断报告二是否A4 //常规报告如果报告使用报告二模板,判断报告二是否A4
int bg2=commonUtil.getLabReport2(jyrq,yq,ybh); int bg2 = commonUtil.getLabReport2(jyrq, yq, ybh);
if(bg2>0){ if (bg2 > 0) {
if("3".equals(NOBOTH)){ if ("3".equals(NOBOTH)) {
return "A4"; return "A4";
}else { } else {
return "A5"; return "A5";
} }
} }
//无任何设定则使用报告单一 //无任何设定则使用报告单一
if("2".equals(NOBOTH)){ if ("2".equals(NOBOTH)) {
return "A4"; return "A4";
}else { } else {
return "A5"; return "A5";
} }
} }
@ -215,15 +237,16 @@ public class ReportUtil {
/** /**
* 将两个PDF文件的第一页横向(左右)合并到一个页面 * 将两个PDF文件的第一页横向(左右)合并到一个页面
*
* @param Base64input1 左侧PDF BASE64 * @param Base64input1 左侧PDF BASE64
* @param Base64input2 右侧PDF BASE64 * @param Base64input2 右侧PDF BASE64
* @param output 合并后的PDF文件路径 * @param output 合并后的PDF文件路径
*/ */
public void mergePdfsHorizontally(String Base64input1, String Base64input2, String output) throws IOException { public void mergePdfsHorizontally(String Base64input1, String Base64input2, String output) throws IOException {
//把base64数据生成pdf文件 //把base64数据生成pdf文件
String path1 = RuoYiConfig.getProfile() +"/config/static/printPDF/"+UUID.randomUUID().toString()+".pdf"; String path1 = RuoYiConfig.getProfile() + "/config/static/printPDF/" + UUID.randomUUID().toString() + ".pdf";
Base64.decodeToFile(Base64input1, new File(path1)); Base64.decodeToFile(Base64input1, new File(path1));
String path2 = RuoYiConfig.getProfile() +"/config/static/printPDF/"+UUID.randomUUID().toString()+".pdf"; String path2 = RuoYiConfig.getProfile() + "/config/static/printPDF/" + UUID.randomUUID().toString() + ".pdf";
Base64.decodeToFile(Base64input2, new File(path2)); Base64.decodeToFile(Base64input2, new File(path2));
try (PdfWriter writer = new PdfWriter(output); try (PdfWriter writer = new PdfWriter(output);
PdfDocument pdfDoc = new PdfDocument(writer); PdfDocument pdfDoc = new PdfDocument(writer);
@ -247,7 +270,7 @@ public class ReportUtil {
mergedPage.setCropBox(mergedPageSize); mergedPage.setCropBox(mergedPageSize);
// 4. 创建画布 // 4. 创建画布
try (Canvas canvas = new Canvas(mergedPage,pdfDoc.getDefaultPageSize())) { try (Canvas canvas = new Canvas(mergedPage, pdfDoc.getDefaultPageSize())) {
// 5. 左侧页面定位:左下角对齐合并页左下角(x=0, y=0) // 5. 左侧页面定位:左下角对齐合并页左下角(x=0, y=0)
Image image1 = new Image(pdf1.getFirstPage().copyAsFormXObject(pdfDoc)); Image image1 = new Image(pdf1.getFirstPage().copyAsFormXObject(pdfDoc));
@ -271,6 +294,7 @@ public class ReportUtil {
/** /**
* 将PDF文件的指定页面旋转90度(顺时针) * 将PDF文件的指定页面旋转90度(顺时针)
*
* @param input 输入PDF路径 * @param input 输入PDF路径
* @param output 输出PDF路径 * @param output 输出PDF路径
* @param pageNumber 要旋转的页码(从1开始) * @param pageNumber 要旋转的页码(从1开始)
@ -311,41 +335,48 @@ public class ReportUtil {
} }
} }
public Result printReport(Date jyrq,String yq,String ybh,String sqh){ public Result printReport(Date jyrq, String yq, String ybh, String sqh) {
String hospitalName = commonUtil.getCompany(commonUtil.getLabInstr(yq).getYljg());//commonUtil.getComDictNameById("HOS", "1"); String hospitalName = commonUtil.getCompany(commonUtil.getLabInstr(yq).getYljg());
BarCodeParam barCodeParam = new BarCodeParam(); BarCodeParam barCodeParam = new BarCodeParam();
barCodeParam.setJyrq(jyrq); barCodeParam.setJyrq(jyrq);
barCodeParam.setYq(yq); barCodeParam.setYq(yq);
barCodeParam.setYbh(ybh); barCodeParam.setYbh(ybh);
barCodeParam.setSqh(sqh); barCodeParam.setSqh(sqh);
barCodeParam.setHospitalName(hospitalName); barCodeParam.setHospitalName(hospitalName);
String filename[]=getReportpic(jyrq,yq,ybh); String[] filename = getReportpic(jyrq, yq, ybh);
String httpPath = getPrintURL("graphs"); String httpPath = getHttpURL("graphs");
for(int i=0;i<filename.length;i++){ String[] picPath = new String[filename.length];
EntityUtils.setItem(barCodeParam,"pic"+(i+1),httpPath+"/"+filename[i]); for (int i = 0; i < filename.length; i++) {
//EntityUtils.setItem(barCodeParam, "pic" + (i + 1), httpPath + "/" + filename[i]);
picPath[i] = httpPath + "/" + filename[i];
log.info("传给模板的地址:{}", httpPath + "/" + filename[i]);
} }
return printToPdf("report_ST",barCodeParam,UUID.randomUUID().toString(),true); barCodeParam.setPic(picPath);
return printToPdf("report_image2", barCodeParam, UUID.randomUUID().toString(), true);
} }
public String[] getReportpic(Date jyrq,String yq,String ybh) {
List<LabGraph> labGraphList= commonUtil.getLabGraphAll(jyrq,yq,ybh); public String[] getReportpic(Date jyrq, String yq, String ybh) {
String filepath="graphs"; List<LabGraph> labGraphList = commonUtil.getLabGraphAll(jyrq, yq, ybh);
String filename[]=null; String filepath = "graphs";
int filecount=0; log.info("labGraphList.size():{}", labGraphList.size());
if(labGraphList.size()>0){ if (labGraphList.size() <= 0) return null;
for(LabGraph labGraph:labGraphList){ String[] filename = new String[labGraphList.size()];
String txlb =labGraph.getTxlb(); int filecount = 0;
String txlbmc=UUID.randomUUID().toString()+"."+txlb.toLowerCase(); if (labGraphList.size() > 0) {
byte[] txnr=labGraph.getTxnr(); for (LabGraph labGraph : labGraphList) {
String txlb = labGraph.getTxlb();
String txlbmc = UUID.randomUUID().toString() + "." + txlb.toLowerCase();
byte[] txnr = labGraph.getTxnr();
try { try {
ImageUtils.generateToStaticDir(txnr,filepath,txlbmc); ImageUtils.generateToStaticDir(txnr, filepath, txlbmc);
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
filename[filecount]=txlbmc; filename[filecount] = txlbmc;
filecount++; filecount++;
} }
} }
return null; return filename;
} }
} }

File diff suppressed because one or more lines are too long

View File

@ -112,6 +112,12 @@
<artifactId>mssql-jdbc</artifactId> <artifactId>mssql-jdbc</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>

View File

@ -110,8 +110,8 @@ public class SecurityConfig {
// 对于登录login 注册register 验证码captchaImage 允许匿名访问 // 对于登录login 注册register 验证码captchaImage 允许匿名访问
requests.antMatchers("/login", "/register", "/captchaImage","/loginAnonymous").permitAll() requests.antMatchers("/login", "/register", "/captchaImage","/loginAnonymous").permitAll()
// 静态资源,可匿名访问 // 静态资源,可匿名访问
.antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/**/*.pdf","/profile/**").permitAll() .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
.antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll() .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**","/printPDF/**","/graphs/**").permitAll()
.antMatchers("/doc.html").permitAll() //Knife4j 过滤 .antMatchers("/doc.html").permitAll() //Knife4j 过滤
// 除上面外的所有请求全部需要鉴权认证 // 除上面外的所有请求全部需要鉴权认证
.anyRequest().authenticated(); .anyRequest().authenticated();

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,83 @@
package com.czlis.system;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.XmlUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class javaSE {
//日期计算
@Test
public void test1(){
DateTime dateTime = DateUtil.offsetDay(DateUtil.date(), 10);
System.out.println(dateTime);
}
//json转xml
@Test
public void test2(){
String jsonStr = "{\"yljg\":\"\",\"brdh\":\"\",\"brly\":\"\",\"dept\":\"\",\"sqh\":\"\",\"userid\":\"\",\"stime\":\"\",\"etime\":\"\",\"bz1\":\"\"}";
JSONObject jsonObj = JSONUtil.parseObj(jsonStr);
Map<String,Object> map = jsonObj.toBean(Map.class);
String xmlStr = XmlUtil.mapToXmlStr(map, "Request");
System.out.println(xmlStr);
// int i = DateUtil.ageOfNow("2025-06-01");
// System.out.println(i);
}
//json序列化测试
@Test
public void test3(){
List<String> dddwList = new ArrayList<>();
dddwList.add("代号");
dddwList.add("名称");
dddwList.add("代号+名称");
List<String> inputList = new ArrayList<>();
inputList.add("1");
inputList.add("2");
inputList.add("3");
Map<String,Object> map = new HashMap<>();
map.put("dddw",dddwList);
map.put("input",inputList);
map.put("radio","");
String jsonStr = JSONUtil.toJsonStr(map);
System.out.println(jsonStr);
}
@Test
public void test4(){
String now = DateUtil.today();
System.out.println("now:"+now); //1757902710365
long time = DateUtil.parse(now, "yyyy-MM-dd").getTime();
System.out.println("time:"+time);
File file = new File("D:\\DumpStack.log");
long modified = file.lastModified();
//DateTime date = DateUtil.date(modified);
System.out.println(modified);
if(time > modified){
System.out.println("当前时间大于文件修改时间");
}else{
System.out.println("当前时间小于文件修改时间");
}
}
@Test
public void test5(){
String temp = "http://47.97.125.165:8904/graphs/8c50363e-e589-4ef9-8401-c968810e9601.gif";
String string = StrUtil.splitToArray(temp, "graphs/")[1];
System.out.println(string);
}
}

View File

@ -22,11 +22,7 @@
<artifactId>lis-interfaceCommon</artifactId> <artifactId>lis-interfaceCommon</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>