打印报告功能

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;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.Arrays;
import java.util.Objects;
import java.util.UUID;
import org.apache.poi.util.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.czlis.common.config.RuoYiConfig;
import com.czlis.common.constant.Constants;
import com.czlis.common.utils.StringUtils;
import org.springframework.util.ResourceUtils;
/**
* 图片处理工具类
@ -95,4 +97,227 @@ public class ImageUtils
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 ybh;
private String hospitalName;
private String pic1;
private String pic2;
private String pic3;
private String pic4;
private String pic5;
private String pic6;
private String pic7;
private String pic8;
private String pic9;
private String pic10;
private String pic11;
private String pic12;
/**
* 图片数组
*/
private String[] pic;
}

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

File diff suppressed because one or more lines are too long

View File

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

View File

@ -110,8 +110,8 @@ public class SecurityConfig {
// 对于登录login 注册register 验证码captchaImage 允许匿名访问
requests.antMatchers("/login", "/register", "/captchaImage","/loginAnonymous").permitAll()
// 静态资源,可匿名访问
.antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/**/*.pdf","/profile/**").permitAll()
.antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()
.antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
.antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**","/printPDF/**","/graphs/**").permitAll()
.antMatchers("/doc.html").permitAll() //Knife4j 过滤
// 除上面外的所有请求全部需要鉴权认证
.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>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>