package com.ltkj.hosp.service.impl; import java.io.*; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.*; import java.util.List; import java.util.stream.Collectors; import cn.hutool.core.date.DateUtil; import cn.hutool.core.io.FileUtil; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.itextpdf.text.*; import com.itextpdf.text.pdf.*; import com.itextpdf.text.pdf.draw.LineSeparator; import com.ltkj.common.core.domain.AjaxResult; import com.ltkj.common.core.domain.entity.SysDictData; import com.ltkj.common.utils.DateUtils; import com.ltkj.common.utils.PDFDocumentUtil; import com.ltkj.common.utils.SecurityUtils; import com.ltkj.common.utils.pdfutils.MergePdf; import com.ltkj.common.utils.pdfutils.MyHeaderFooter; import com.ltkj.common.utils.pdfutils.PDFBinaryUtil; import com.ltkj.common.utils.pdfutils.PdfUtils; import com.ltkj.db.DataSourceContextHolder; import com.ltkj.hosp.domain.*; import com.ltkj.hosp.service.*; import com.ltkj.mall.mallOrderUtils.TjConstants; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import com.ltkj.hosp.mapper.TjReportMapper; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.interceptor.TransactionAspectSupport; import javax.annotation.Resource; import static com.ltkj.common.utils.pdfutils.PDFBinaryUtil.getPDFBinary; /** * 体检报告存储Service业务层处理 * * @author ltkj * @date 2022-12-06 */ @Service public class TjReportServiceImpl extends ServiceImpl implements ITjReportService { @Resource private TjReportMapper tjReportMapper; @Autowired private ITjReportService tjReportService; @Resource private ITjCustomerService tjCustomerService; @Autowired private ITjOrderService tjOrderService; @Autowired private ITjOrderDetailService tjOrderDetailService; @Resource private ITjProjectService projectService; @Resource private IDictCompService dictCompService; @Resource private ITjReportTemplateService reportTemplateService; @Resource private ITjOrderRemarkService tjOrderRemarkService; @Resource private ITjStandardService tjStandardService; @Autowired private ITjReportPrintService printService; /** * 查询体检报告存储 * * @param reId 体检报告存储主键 * @return 体检报告存储 */ @Override public TjReport selectTjReportByReId(Long reId) { return tjReportMapper.selectTjReportByReId(reId); } /** * 查询体检报告存储列表 * * @param tjReport 体检报告存储 * @return 体检报告存储 */ @Override public List selectTjReportList(TjReport tjReport) { return tjReportMapper.selectTjReportList(tjReport); } /** * 新增体检报告存储 * * @param tjReport 体检报告存储 * @return 结果 */ @Override public int insertTjReport(TjReport tjReport) { return tjReportMapper.insertTjReport(tjReport); } /** * 修改体检报告存储 * * @param tjReport 体检报告存储 * @return 结果 */ @Override public int updateTjReport(TjReport tjReport) { return tjReportMapper.updateTjReport(tjReport); } /** * 批量删除体检报告存储 * * @param reIds 需要删除的体检报告存储主键 * @return 结果 */ @Override public int deleteTjReportByReIds(Long[] reIds) { return tjReportMapper.deleteTjReportByReIds(reIds); } /** * 删除体检报告存储信息 * * @param reId 体检报告存储主键 * @return 结果 */ @Override public int deleteTjReportByReId(Long reId) { return tjReportMapper.deleteTjReportByReId(reId); } // @Value("${path.filePath}") // private String value; // @Override // public AjaxResult getTjReport(String tjNumber) { // //根据体检号 // //在order里查询体检状态 判断体检是否完成 // LambdaQueryWrapper wq = new LambdaQueryWrapper<>(); // wq.eq(TjOrder::getTjNumber, tjNumber); // TjOrder tjOrder = tjOrderService.getOne(wq); // if (null != tjOrder) { // Integer checkStatus = tjOrder.getCheckStatus(); // if (checkStatus == 1) { // //查出客户个人信息 通过user_id // LambdaQueryWrapper wq1 = new LambdaQueryWrapper<>(); // wq1.eq(TjCustomer::getCusId, tjOrder.getUserId()); // TjCustomer tjCustomer = tjCustomerService.getOne(wq1); // // //根据order表的单位id查出单位名称 // LambdaQueryWrapper wq111 = new LambdaQueryWrapper<>(); // wq111.eq(DictComp::getDrugManufacturerId, tjOrder.getFirmId()); // DictComp dictComp = dictCompService.getOne(wq111); // // //查出记录详情 通过order_id // LambdaQueryWrapper wq2 = new LambdaQueryWrapper<>(); // wq2.eq(TjOrderDetail::getOrderId, tjOrder.getOrderId()); // List list = tjOrderDetailService.list(wq2); // // //遍历客户所选的项目(包含子项父项) // for (TjOrderDetail tjOrderDetail : list) { // //查出单个项目对象 赋值给对象属性 // TjProject tjProject = projectService.selectTjProjectByProId(tjOrderDetail.getProId()); // tjOrderDetail.setProject(tjProject); // } // /* // * ====================第一部分 填充体检报告封面模板 // * */ // //根据数据库中的模板二进制文件 转pdf 创建文件夹 将pdf放进文件夹 // LambdaQueryWrapper tjReportTemplateLambdaQueryWrapper = new LambdaQueryWrapper<>(); // tjReportTemplateLambdaQueryWrapper.eq(TjReportTemplate::getFlag, 1); // TjReportTemplate one1 = reportTemplateService.getOne(tjReportTemplateLambdaQueryWrapper); // String template = one1.getTemplate(); //拿到二进制 // // //本地创建临时文件夹 // //String userId ="10000"; // //当前登录的人工号 // String userId = SecurityUtils.getLoginUser().getUsername(); // //二进制转pdf 存储在临时文件夹中 // PDFBinaryUtil.base64StringToPDF(template, FileUtil.mkdir(value).getPath() + File.separator + userId + "体检报告封面模板.pdf"); // // // 模板文件路径 // String inputFileName = value + File.separator + userId + "体检报告封面模板.pdf"; // // 生成的文件路径 // String outputFileName = value + File.separator + userId + "体检报告封面页.pdf"; // OutputStream os = null; // PdfStamper ps = null; // PdfReader reader = null; // File file = new File(outputFileName); // try { // os = Files.newOutputStream(file.toPath()); // // 读入pdf表单 // reader = new PdfReader(inputFileName); // // 根据表单生成一个新的pdf // ps = new PdfStamper(reader, os); // // 获取pdf表单 // AcroFields form = ps.getAcroFields(); // // 给表单添加中文字体 // //String prefixFont = "C:Windows\\Fonts" + File.separator + "STFANGSO.TTF"; // //该字体造成类型不均匀,但是pdf转图片不乱码 // //BaseFont bf = BaseFont.createFont("C:Windows\\Fonts\\simfang.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED); // BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); // form.addSubstitutionFont(bf); // // // 填充数据给表格 // Map data = new HashMap<>(); // data.put("name", tjCustomer.getCusName()); // //填充性别:判断男女 // Long cusSex = tjCustomer.getCusSex(); // String sex; // if (cusSex == 0) { // sex = "男"; // } else { // sex = "女"; // } // data.put("sex", sex); // data.put("age", DateUtil.ageOfNow(tjCustomer.getCusBrithday())); // data.put("tjnumber", tjNumber); // data.put("tjdate", DateUtils.parseDateToStr("yyyy/MM/dd", tjOrder.getCreateTime())); // data.put("phone", tjCustomer.getCusPhone()); // if (dictComp == null) { // data.put("work", "无"); // } else { // data.put("work", dictComp.getCnName()); // } // // data.put("remark", "示例:身高体重" + // "\n1、合理控制饮食,少吃点" + // "\n心电图" + // "\n请注意保持!!!这里放建议/异常啥的。。。。或总检建议" + tjOrder.getCheckAdvice()); // // 遍历data 给pdf表单表格赋值 // for (String key : data.keySet()) { // form.setField(key, data.get(key).toString()); // } // //设置为无法编辑 // ps.setFormFlattening(true); // // ps.close(); // os.close(); // reader.close(); // /* // * ==========================第二部分 生成项目详情 // */ // //文档对象 实现A4纸页面 // Document document = new Document(PageSize.A4); // //document.setMarginMirroring(true); // //设置文档的页边距就是距离页面边上的距离,分别为:左边距,右边距,上边距,下边距 // document.setMargins(70, 70, 40, 40); // //这个是生成pdf的位置以及名称 // String fileName = value + File.separator + userId + "体检报告项目详情页.pdf"; // OutputStream outputStream = Files.newOutputStream(Paths.get(fileName)); // PdfWriter pdfWriter = PdfWriter.getInstance(document, outputStream); // // // 添加页眉/页脚/水印 // pdfWriter.setPageEvent((PdfPageEvent) new MyHeaderFooter());// 页眉页脚(需要时设置) // // //打开文档 // document.open(); // // // 获取数据 // Map> tjOrderRemarkObjectMap = addTable(tjNumber); // for (Map.Entry> entry : tjOrderRemarkObjectMap.entrySet()) { // List value = entry.getValue(); // LambdaQueryWrapper wqqq = new LambdaQueryWrapper<>(); // wqqq.eq(TjProject::getProId, entry.getKey().getProId()); // TjProject one11 = projectService.getOne(wqqq); // // String titleName = one11.getProName(); // // 设置标题字体样式 // Font titleFonts = PdfUtils.setFont(9); // Paragraph paragraph = PdfUtils.setParagraph(titleFonts, titleName); // // // 设置表格 // // 定义列名 // String[] titles = {"体检项目", "体检结果", "单位", "参考范围"}; // // 获取列表数据 // //设置表头字体样式 // Font headFont = PdfUtils.setFont(9); // // 设置正文字体样式:12号 // Font textFont = PdfUtils.setFont(9); // //创建表格 将表头字体和正文字体放进去 // PdfPTable table = setTable(headFont, textFont, titles, value); // // // 填充表格内容 // document.add(paragraph); // document.add(table); // // //判断备注是否为空 空不能显示null // if (entry.getKey().getRemark() == null) { // entry.getKey().setRemark(""); // } // // //备注 // String remark = "备注:" + entry.getKey().getRemark(); // Font remarkFonts = PdfUtils.setFont(9); // Paragraph pp = PdfUtils.setParagraph(remarkFonts, remark); // document.add(pp); // // //主检医师 // String doctorName = "主检医师:" + entry.getKey().getDoctorName(); // Font doctorFonts = PdfUtils.setFont(9); // Paragraph df = PdfUtils.setParagraph(doctorFonts, doctorName); // df.setAlignment(Element.ALIGN_RIGHT); // document.add(df); // // //分割线 // LineSeparator objectName = new LineSeparator(); // document.add(objectName); // } // /* // * document关闭的其实是文件的监听状态,writer关闭的是io流,writer创建在document之后 // * */ // document.close(); // pdfWriter.close(); // outputStream.close(); // // //=============================== 第三部分 合并体检报告封面页和体检报告项目详情页 // String[] files1 = {value + File.separator + userId + "体检报告封面页.pdf", value + File.separator + userId + "体检报告项目详情页.pdf"}; // String outputPath1 = value + File.separator; // String outputFileName1 = tjNumber + "体检报告.pdf"; // // File file1 = new File(outputPath1 + outputFileName1); // List f = new ArrayList<>(); // for (String s : files1) { // f.add(new File(s)); // } // MergePdf.mergeFileToPDF(f, file1); // // //============================= 第四部分 将pdf路径存储数据库 文件转二进制存储和和路径存储 // TjReport tjReport = new TjReport(); // tjReport.setTjNumber(String.valueOf(tjNumber)); // tjReport.setPath(outputPath1 + outputFileName1); // String pdfBinary = getPDFBinary(outputPath1 + outputFileName1); // tjReport.setReport(pdfBinary); // tjReportService.save(tjReport); // // //将临时文件夹中的四个文件删除 // //FileUtil.del(value+"\\"+tjNumber + "体检报告.pdf"); // FileUtil.del(value + File.separator + userId + "体检报告封面模板.pdf"); // FileUtil.del(value + File.separator + userId + "体检报告项目详情页.pdf"); // FileUtil.del(value + File.separator + userId + "体检报告封面页.pdf"); // // //修改order表中的打印报告时间为当前时间 // LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); // updateWrapper.eq(TjOrder::getTjNumber, tjNumber); // updateWrapper.set(TjOrder::getReportTime, new Date()); // tjOrderService.update(updateWrapper); // // // return AjaxResult.success("已生成报告!可直接点击预览!"); // // } catch (Exception e) { // e.printStackTrace(); // return AjaxResult.error("PDF导出失败"); // } // } // } // return null; // } @Override public Integer getSelectCount(Wrapper queryWrapper) { return tjReportMapper.selectCount(queryWrapper); } public Map> addTable(String tjNumber) { //创建map 键为父项目 值为子项目集合 Map> printReport = new HashMap<>(); //通过传入的体检号查到该客户的体检记录 LambdaQueryWrapper wq1 = new LambdaQueryWrapper<>(); wq1.eq(TjOrder::getTjNumber, tjNumber); TjOrder one = tjOrderService.getOne(wq1); //拿到体检记录的orderid,查出项目详细信息 LambdaQueryWrapper wq = new LambdaQueryWrapper<>(); wq.eq(TjOrderDetail::getOrderId, one.getOrderId()); List tjOrderDetails = tjOrderDetailService.list(wq); //遍历体检记录 将项目的具体信息 //遍历客户所选的项目(包含子项父项) for (TjOrderDetail tjOrderDetail : tjOrderDetails) { //查出单个项目对象 赋值给对象属性 TjProject tjProject = projectService.selectTjProjectByProId(tjOrderDetail.getProId()); tjOrderDetail.setProject(tjProject); } //查出客户个人信息 LambdaQueryWrapper wq22 = new LambdaQueryWrapper<>(); wq22.eq(TjCustomer::getCusId, one.getUserId()); TjCustomer customer = tjCustomerService.getOne(wq22); //查询夫项目备注表 LambdaQueryWrapper wqq = new LambdaQueryWrapper<>(); wqq.eq(TjOrderRemark::getTjNumber, tjNumber); List tjOrderRemarks = tjOrderRemarkService.list(wqq); for (TjOrderRemark tjOrderRemark : tjOrderRemarks) { printReport.put(tjOrderRemark, null); } for (Map.Entry> entry : printReport.entrySet()) { List tjPdfVOS = new ArrayList<>(); for (TjOrderDetail tjOrderDetail : tjOrderDetails) { if (tjOrderDetail.getProject().getProParentId().equals(entry.getKey().getProId())) { //查标准 LambdaQueryWrapper wq6 = new LambdaQueryWrapper<>(); wq6.eq(TjStandard::getProId, tjOrderDetail.getProId()); List list2 = tjStandardService.list(wq6); //判断标准个数,根据年龄性别 推断出一个标准 if (list2.size() == 0) { tjOrderDetail.setStandard(null); } else if (list2.size() == 1) { //查出一条标准 不区分年龄性别 tjOrderDetail.setStandard(list2.get(0)); } else { //多条标准 根据客户年龄性别判断 //性别 Long cusSex = customer.getCusSex(); Date cusBrithday = customer.getCusBrithday(); //年龄 int age = DateUtil.ageOfNow(cusBrithday); //遍历判断标准 for (TjStandard tjStandard : list2) { LambdaQueryWrapper wq8 = new LambdaQueryWrapper<>(); //判断性别 if (tjStandard.getTjSex() != null) { wq8.eq(TjStandard::getTjSex, cusSex); } //判断年龄段 if (tjStandard.getTjType() != null) { wq8.eq(TjStandard::getTjType, getAgeType(age)); } TjStandard standard = tjStandardService.getOne(wq8); tjOrderDetail.setStandard(standard); } } TjPdfVO tjPdfVO = new TjPdfVO(); tjPdfVO.setProName(tjOrderDetail.getProject().getProName()); //体检项目名 tjPdfVO.setProResult(tjOrderDetail.getProResult()); //体检结果 tjPdfVO.setCompany(tjOrderDetail.getStandard().getCompany()); //单位 String tjStandardGtValue = tjOrderDetail.getStandard().getTjStandardGtValue(); String tjStandardLtValue = tjOrderDetail.getStandard().getTjStandardLtValue(); tjPdfVO.setStandardValue(tjStandardLtValue + "-" + tjStandardGtValue); //参考值范围 //满足条件的子项目加入集合 tjPdfVOS.add(tjPdfVO); } } printReport.put(entry.getKey(), tjPdfVOS); } return printReport; } public int getAgeType(Integer age) { int type = 0; if (1 < age && age < 4) { type = 1; } else if (5 < age && age < 11) { type = 2; } else if (12 < age && age < 18) { type = 3; } else if (19 < age && age < 35) { type = 4; } else if (36 < age && age < 59) { type = 5; } else if (60 < age && age < 150) { type = 6; } return type; } /** * 设置 * 表格内容 * * @param headFont * @param textFont * @param title * @param list * @return */ public static PdfPTable setTable(Font headFont, Font textFont, String[] title, List list) { //四列 PdfPTable table = PdfUtils.createTable(new float[]{120, 120, 120, 120}); //画标题 for (String head : title) { table.addCell(PdfUtils.createCell(head, headFont)); } //画内容 for (TjPdfVO tjPdfVO : list) { table.addCell(PdfUtils.createCell(tjPdfVO.getProName(), textFont)); table.addCell(PdfUtils.createCell(tjPdfVO.getProResult(), textFont)); table.addCell(PdfUtils.createCell(tjPdfVO.getCompany(), textFont)); table.addCell(PdfUtils.createCell(tjPdfVO.getStandardValue(), textFont)); } return table; } @Override public AjaxResult makeBatchReport(List tjNumbers,String value) { return sqlGetReportToMake(tjNumbers,value); } /** * 通过sql 直接查报告base64进行整合返回 * 如果sql数据量巨大 查询缓慢 可以试试 makeReport(List tjNumbers)已注释 * @param tjNumbers * @return */ private AjaxResult sqlGetReportToMake(List tjNumbers,String value) { // LambdaQueryWrapper tjReportLambdaQueryWrapper = new LambdaQueryWrapper<>(); // tjReportLambdaQueryWrapper.in(TjReport::getTjNumber, tjNumbers); // List list = tjReportService.list(tjReportLambdaQueryWrapper); ArrayList base64Pdfs = new ArrayList<>(); // for (TjReport report : list) { // if (report == null || report.getReport() == null) { // // 没有该报告 直接跳过 // continue; // } // base64Pdfs.add(report.getReport()); // } String key = DataSourceContextHolder.getDataSourceKey(); key = key.replace("ltkjpeis10_",""); if(null !=tjNumbers && !tjNumbers.isEmpty()){ for (String number : tjNumbers) { TjOrder order = tjOrderService.getOrderByTjNum(number); TjCustomer tjCustomer = tjCustomerService.getById( order.getUserId()); String filePath = value + File.separator + key + File.separator + tjCustomer.getCusId() + order.getTjNumber() + tjCustomer.getCusName() + "_报告.pdf"; try { // 读取文件为字节数组 Path path = Paths.get(filePath); byte[] fileBytes = Files.readAllBytes(path); // 将字节数组转换为 Base64 字符串 String base64String = Base64.getEncoder().encodeToString(fileBytes); base64Pdfs.add(base64String); // 输出 Base64 编码的字符串 // System.out.println(base64String); TjReportPrint print=new TjReportPrint(); print.setTjNumber(order.getTjNumber()); print.setPrintBy(SecurityUtils.getLoginUser().getUser().getNickName()); print.setPrintTime(new Date()); print.setPrintStatus("已打印"); if (printService.save(print)) { order.setPrintLastTime(new Date()); order.setStatus(TjConstants.TJ_END); tjOrderService.updateById(order); } } catch (IOException e) { e.printStackTrace(); log.error(String.valueOf(e)); } } try { byte[] mergePDF = PDFDocumentUtil.mergePDFs(base64Pdfs); String s = Base64.getEncoder().encodeToString(mergePDF); return AjaxResult.success().put("file",s); } catch (DocumentException | IOException e) { e.printStackTrace(); TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); return AjaxResult.error("批量生成失败"); } } return AjaxResult.error("批量生成失败"); } }