主程序

This commit is contained in:
tangw 2025-09-29 17:16:07 +08:00
parent 3530fb58a9
commit 61f7e145b0
7 changed files with 381 additions and 6 deletions

View File

@ -16,7 +16,7 @@ public class LabGraph {
private String ybh; private String ybh;
private String txmc; private String txmc;
private String txlb; private String txlb;
private Blob txnr; private byte[] txnr;
private String bz1; private String bz1;
private String bz2; private String bz2;
} }

View File

@ -0,0 +1,20 @@
package com.czlis.interfaceCommon.mapper;
import com.czlis.common.core.domain.entity.lis.LabGraph;
import org.apache.ibatis.annotations.Param;
import java.util.Date;
import java.util.List;
public interface LabGraphMapper {
int getLabGraphCount(@Param("jyrq") Date jyrq, @Param("yq") String yq, @Param("ybh") String ybh);
LabGraph getLabGraph(@Param("jyrq") Date jyrq, @Param("yq") String yq, @Param("ybh") String ybh, @Param("txmc") String txmc);
List<LabGraph> getLabGraphAll(@Param("jyrq") Date jyrq, @Param("yq") String yq, @Param("ybh") String ybh);
int updateLabGraph(LabGraph labGraph);
int updateLabGraphBlob(LabGraph labGraph);
int deleteLabGraphAll(@Param("jyrq") Date jyrq, @Param("yq") String yq, @Param("ybh") String ybh);
int deleteLabGraph(@Param("jyrq") Date jyrq, @Param("yq") String yq, @Param("ybh") String ybh,@Param("txmc") String txmc);
int insertLabGraph(LabGraph labGraph);
}

View File

@ -22,7 +22,16 @@ 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 pic5;
private String pic6;
private String pic7;
private String pic8;
private String pic9;
private String pic10;
private String pic11;
private String pic12;
} }

View File

@ -77,6 +77,8 @@ public class CommonUtil {
ComLocalconfigMapper comLocalconfigMapper; ComLocalconfigMapper comLocalconfigMapper;
@Autowired @Autowired
LabPatfeeMapper labPatfeeMapper; LabPatfeeMapper labPatfeeMapper;
@Autowired
LabGraphMapper labGraphMapper;
//====检验主表操作方法集合=== //====检验主表操作方法集合===
public LabPat getLabPatOne(Date jyrq, String yq, String ybh) { public LabPat getLabPatOne(Date jyrq, String yq, String ybh) {
return labPatMapper.getLabPatOne(jyrq, yq, ybh); return labPatMapper.getLabPatOne(jyrq, yq, ybh);
@ -113,6 +115,39 @@ public class CommonUtil {
public int updateLabPatfee(LabPatfee labPatfee) { public int updateLabPatfee(LabPatfee labPatfee) {
return labPatfeeMapper.updateLabPatfee(labPatfee); return labPatfeeMapper.updateLabPatfee(labPatfee);
} }
public int getLabGraphCount(Date jyrq,String yq,String ybh) {
return labGraphMapper.getLabGraphCount(jyrq,yq,ybh);
}
public LabGraph getLabGraph(Date jyrq,String yq,String ybh,String txmc) {
return labGraphMapper.getLabGraph(jyrq,yq,ybh,txmc);
}
public List<LabGraph> getLabGraphAll(Date jyrq,String yq,String ybh) {
return labGraphMapper.getLabGraphAll(jyrq,yq,ybh);
}
@Transactional(rollbackFor = Exception.class)
public int updateLabGraph(LabGraph labGraph) {
return labGraphMapper.updateLabGraph(labGraph);
}
@Transactional(rollbackFor = Exception.class)
public int updateLabGraphBlob(LabGraph labGraph) {
return labGraphMapper.updateLabGraphBlob(labGraph);
}
@Transactional(rollbackFor = Exception.class)
public int deleteLabGraphAll(Date jyrq,String yq,String ybh) {
return labGraphMapper.deleteLabGraphAll(jyrq,yq,ybh);
}
@Transactional(rollbackFor = Exception.class)
public int deleteLabGraph(Date jyrq,String yq,String ybh,String txmc) {
return labGraphMapper.deleteLabGraph(jyrq,yq,ybh,txmc);
}
@Transactional(rollbackFor = Exception.class)
public int insertLabGraph(LabGraph labGraph) {
return labGraphMapper.insertLabGraph(labGraph);
}
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public int insertLabPat(LabPat labPat) { public int insertLabPat(LabPat labPat) {
return labPatMapper.updateLabPat(labPat); return labPatMapper.updateLabPat(labPat);

View File

@ -0,0 +1,234 @@
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

@ -5,6 +5,7 @@ import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.codec.Base64; import cn.hutool.core.codec.Base64;
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.utils.file.FileUtils; import com.czlis.common.utils.file.FileUtils;
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;
@ -318,9 +319,33 @@ public class ReportUtil {
barCodeParam.setYbh(ybh); barCodeParam.setYbh(ybh);
barCodeParam.setSqh(sqh); barCodeParam.setSqh(sqh);
barCodeParam.setHospitalName(hospitalName); barCodeParam.setHospitalName(hospitalName);
String templatePath = RuoYiConfig.getProfile()+"/templates/report_ST.jrxml"; // 报告模板文件路径 String filename[]=getReportpic(jyrq,yq,ybh);
//return printToPdf(templatePath,barCodeParam,UUID.randomUUID().toString(),true); String httpPath = getPrintURL("graphs");
for(int i=0;i<filename.length;i++){
EntityUtils.setItem(barCodeParam,"pic"+(i+1),httpPath+"/"+filename[i]);
}
return printToPdf("report_ST",barCodeParam,UUID.randomUUID().toString(),true); return printToPdf("report_ST",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;
}
} }

View File

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.czlis.interfaceCommon.mapper.LabGraphMapper">
<select id="getLabGraph" resultType="com.czlis.common.core.domain.entity.lis.LabGraph">
SELECT * FROM lab_graph where yq = #{yq} and jyrq = #{jyrq} and ybh = #{ybh} and txmc = #{txmc}
</select>
<select id="getLabGraphAll" resultType="com.czlis.common.core.domain.entity.lis.LabGraph">
SELECT * FROM lab_graph where yq = #{yq} and jyrq = #{jyrq} and ybh = #{ybh} order by bz1 ASC
</select>
<select id="getLabGraphCount" resultType="int">
SELECT count(1) FROM lab_graph where yq = #{yq} and jyrq = #{jyrq} and ybh = #{ybh}
</select>
<update id="updateLabGraph" parameterType="com.czlis.common.core.domain.entity.lis.LabGraph">
update lab_graph
<set>
<if test="txlb != null">
txlb = #{txlb},
</if>
<if test="bz1 != null">
bz1 = #{bz1},
</if>
<if test="bz2 != null">
bz2 = #{bz2},
</if>
<if test="txnr != null">
txnr = #{txnr},
</if>
</set>
where yq = #{yq} and jyrq = #{jyrq} and ybh = #{ybh} and txmc = #{txmc}
</update>
<update id="updateLabGraphBlob" parameterType="com.czlis.common.core.domain.entity.lis.LabGraph">
update lab_graph set txnr = #{txnr}
where yq = #{yq} and jyrq = #{jyrq} and ybh = #{ybh} and txmc = #{txmc}
</update>
<delete id="deleteLabGraphAll">
delete from lab_graph where yq = #{yq} and jyrq = #{jyrq} and ybh = #{ybh}
</delete>
<delete id="deleteLabGraph">
delete from lab_graph where yq = #{yq} and jyrq = #{jyrq} and ybh = #{ybh} and txmc = #{txmc}
</delete>
<insert id="insertLabGraph" parameterType="com.czlis.common.core.domain.entity.lis.LabGraph">
insert into lab_graph (yq, jyrq, ybh,
txmc, txlb, bz1, bz2,
txnr)
values (#{yq,jdbcType=CHAR}, #{jyrq,jdbcType=TIMESTAMP}, #{ybh,jdbcType=VARCHAR},
#{txmc,jdbcType=CHAR}, #{txlb,jdbcType=VARCHAR}, #{bz1,jdbcType=VARCHAR}, #{bz2,jdbcType=VARCHAR},
#{txnr,jdbcType=LONGVARBINARY})
</insert>
</mapper>