diff --git a/dlp-drugtesting-biz/src/main/java/digital/laboratory/platform/inspection/service/impl/InspectRecordServiceImpl.java b/dlp-drugtesting-biz/src/main/java/digital/laboratory/platform/inspection/service/impl/InspectRecordServiceImpl.java index 506cf17..2e6b85c 100644 --- a/dlp-drugtesting-biz/src/main/java/digital/laboratory/platform/inspection/service/impl/InspectRecordServiceImpl.java +++ b/dlp-drugtesting-biz/src/main/java/digital/laboratory/platform/inspection/service/impl/InspectRecordServiceImpl.java @@ -33,6 +33,8 @@ import digital.laboratory.platform.sys.enums.entrust.EntrustBiologyType; import feign.Response; import org.apache.commons.io.output.ByteArrayOutputStream; import org.apache.poi.xwpf.usermodel.XWPFTable; +import org.apache.poi.xwpf.usermodel.XWPFTableCell; +import org.apache.poi.xwpf.usermodel.XWPFTableRow; import org.springframework.beans.BeanUtils; import org.springframework.mock.web.MockMultipartFile; import org.springframework.stereotype.Service; @@ -125,17 +127,8 @@ public class InspectRecordServiceImpl implements InspectRecordService { System.out.println(String.format("转换为 PDF 结束")); } - /** - * 生成生物样本检验记录数据map - * - * @param entrustInfo 委托实体信息 - * @param materialType 检材类型 - * @return - * @throws Exception - */ public Map buildInVivoRecordData(EntrustInfo entrustInfo, String materialType) throws Exception { - // 获取检验记录信息 TestRecord testRecord = testRecordService.getTestRecordByBusinessId(entrustInfo.getId()); @@ -146,7 +139,6 @@ public class InspectRecordServiceImpl implements InspectRecordService { // 生成基础数据 HashMap data = buildCommonInspectRecordDocMap(entrustInfo, testRecord, materialType); - // 获取样品数据 List dataList = testRecordSampleDataService.list( Wrappers.lambdaQuery().eq(TestRecordSampleData::getTestId, testRecord.getId())); @@ -179,13 +171,13 @@ public class InspectRecordServiceImpl implements InspectRecordService { TestRecordSampleDataDocDTO blankVo = new TestRecordSampleDataDocDTO(); blankVo.setName("空白" + materialType); blankVo.setCompoundName(compoundName); - blankVo.setPTargetRtTime("/"); - blankVo.setPRtTimeError("/"); - blankVo.setPRtTimeWithinError("否"); - blankVo.setPIonAbundanceRatio("/"); - blankVo.setPIonAbundanceRatioError("/"); - blankVo.setPIonAbundanceRatioWithinError("否"); - blankVo.setPIsDetected("否"); + blankVo.setPTargetRtTime("/"); // 设置空值为"/" + blankVo.setPRtTimeError("/"); // 设置空值为"/" + blankVo.setPRtTimeWithinError("否"); // 默认"否" + blankVo.setPIonAbundanceRatio("/"); // 设置空值为"/" + blankVo.setPIonAbundanceRatioError("/"); // 设置空值为"/" + blankVo.setPIonAbundanceRatioWithinError("否"); // 默认"否" + blankVo.setPIsDetected("否"); // 默认"否" dataDtos.add(blankVo); // 根据样品类型分组 @@ -197,22 +189,24 @@ public class InspectRecordServiceImpl implements InspectRecordService { TestRecordSampleData std = map.get("STD").get(0); TestRecordSampleDataDocDTO stdVo = new TestRecordSampleDataDocDTO(); BeanUtils.copyProperties(std, stdVo); + List expandList = dataExpandMap.get(std.getId()); if (expandList != null) { for (TestRecordSampleDataExpand expand : expandList) { if (!expand.getBasePeak()) { - stdVo.setPIonAbundanceRatio(expand.getIonAbundanceRatio().toString()); - stdVo.setPIonAbundanceRatioError("/"); - stdVo.setPIonAbundanceRatioWithinError("/"); + stdVo.setPIonAbundanceRatio(expand.getIonAbundanceRatio() != null ? expand.getIonAbundanceRatio().toString() : "/"); + stdVo.setPIonAbundanceRatioError("/"); // 设置空值为"/" + stdVo.setPIonAbundanceRatioWithinError("/"); // 设置空值为"/" break; // 只取第一个符合条件的扩展数据 } } } stdVo.setName("空白" + materialType + "加标"); - stdVo.setPTargetRtTime(std.getTargetRtTime().toString()); - stdVo.setPRtTimeError("/"); - stdVo.setPRtTimeWithinError("/"); - stdVo.setPIsDetected("是"); + stdVo.setPTargetRtTime(std.getTargetRtTime() != null ? std.getTargetRtTime().toString() : "/"); + stdVo.setPRtTimeError("/"); // 设置空值为"/" + stdVo.setPRtTimeWithinError("/"); // 设置空值为"/" + stdVo.setPIsDetected("是"); // 默认"是" + stdVo.setCompoundName(compoundName); dataDtos.add(stdVo); } @@ -226,38 +220,43 @@ public class InspectRecordServiceImpl implements InspectRecordService { TestRecordSampleData item = analyte.get(i); TestRecordSampleDataDocDTO vo = new TestRecordSampleDataDocDTO(); BeanUtils.copyProperties(item, vo); - vo.setPTargetRtTime(vo.getTargetRtTime().toString()); - vo.setPRtTimeError(vo.getRtTimeError().toString()); - vo.setPRtTimeWithinError(vo.getRtTimeWithinError().toString()); - vo.setPIsDetected(item.getIsDetected() == 1 ? "是" : "否"); + + vo.setPTargetRtTime(item.getTargetRtTime() != null ? item.getTargetRtTime().toString() : "/"); + vo.setPRtTimeError(item.getRtTimeError() != null ? item.getRtTimeError().toString() : "/"); + vo.setPRtTimeWithinError(item.getRtTimeWithinError() != null ? item.getRtTimeWithinError().toString() : "/"); + vo.setPIsDetected(item.getIsDetected() != null && item.getIsDetected() == 1 ? "是" : "否"); List expandList = dataExpandMap.get(item.getId()); if (expandList != null) { for (TestRecordSampleDataExpand expand : expandList) { if (!expand.getBasePeak()) { - vo.setPIonAbundanceRatio(expand.getIonAbundanceRatio().toString()); - vo.setPIonAbundanceRatioError(expand.getIonAbundanceRatioError().toString()); - vo.setPIonAbundanceRatioWithinError(expand.getIonAbundanceRatioWithinError()); + vo.setPIonAbundanceRatio(expand.getIonAbundanceRatio() != null ? expand.getIonAbundanceRatio().toString() : "/"); + vo.setPIonAbundanceRatioError(expand.getIonAbundanceRatioError() != null ? expand.getIonAbundanceRatioError().toString() : "/"); + vo.setPIonAbundanceRatioWithinError(expand.getIonAbundanceRatioWithinError() != null ? expand.getIonAbundanceRatioWithinError() : "/"); break; // 只取第一个符合条件的扩展数据 } } } + // 重新命名样品 vo.setName((dataList .stream() .collect(Collectors.groupingBy(TestRecordSampleData::getSampleNo)) .keySet() .size() == 1) ? "检材样品" : (i + 1) + "号检材样品"); + vo.setCompoundName(compoundName); dataVOS.add(vo); } dataDtos.addAll(dataVOS); } } + // 加入图谱序号值 int indexNum = 1; for (int i = 0; i < dataDtos.size(); i++) { dataDtos.get(i).setIndexNum(String.valueOf(indexNum++)); } + this.buildIonPairAndCE(data, testRecordReagentService .list(Wrappers.lambdaQuery() .in(TestRecordReagent::getId, testRecord.getReagentConsumablesList()) @@ -265,9 +264,11 @@ public class InspectRecordServiceImpl implements InspectRecordService { .stream() .map(item -> item.getId()) .collect(Collectors.toList())); + // 返回处理后的数据 data.put("dataDtos", dataDtos); - data.put("sampleSize", dataDtos.size() / 2); + data.put("compoundSize", dataDtos.stream().collect(Collectors.groupingBy(TestRecordSampleData::getCompoundName)).size()); + data.put("type", "inVivo"); data.put("inspectOpinion", this.buildInspectOpinion(testRecordSampleDataService .lambdaQuery() .eq(TestRecordSampleData::getTestId, testRecord.getId()) @@ -276,6 +277,7 @@ public class InspectRecordServiceImpl implements InspectRecordService { return data; } + public Map buildInVitroRecordData(EntrustInfo entrustInfo, TestRecord testRecord, Map data) { @@ -423,6 +425,7 @@ public class InspectRecordServiceImpl implements InspectRecordService { // 9️⃣ 返回处理后的数据 data.put("dataDtos", dataDtos); data.put("sampleSize", dataDtos.size()); + data.put("type", "inVitro"); try { Map> isDetectedMap = testRecordSampleDataService @@ -473,12 +476,12 @@ public class InspectRecordServiceImpl implements InspectRecordService { if (!isDetectedStrs.isEmpty()) { data.put("isDetectedStrs", "阳性结果:" + "\n" + isDetectedStrs.stream() .map(item -> "\u3000\u3000" + item) - .collect(Collectors.joining("\u2611"))); + .collect(Collectors.joining("\n"))); } if (!notDetectedStrs.isEmpty()) { data.put("notDetectedStrs", "阴性结果:" + "\n" + notDetectedStrs.stream() .map(item -> "\u3000\u3000" + item) - .collect(Collectors.joining("\u2611"))); + .collect(Collectors.joining("\n"))); } } catch (Exception e) { } @@ -556,7 +559,8 @@ public class InspectRecordServiceImpl implements InspectRecordService { System.out.println(data); LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy(); Configure config = Configure.builder(). - bind("dataDtos", policy).build(); + bind("dataDtos", policy) + .bind("ionPairAndCEVOS", policy).build(); return buildDocFileAndUploadToOss(entrustInfo.getId(), templatePath, config, data); } @@ -579,25 +583,51 @@ public class InspectRecordServiceImpl implements InspectRecordService { XWPFTemplate template = XWPFTemplate.compile(bis, config).render(data); NiceXWPFDocument document = template.getXWPFDocument(); - List tables = document.getTables(); XWPFTable table = tables.get(tables.size() - 1); // 获取最后一个表格 - int sampleSize = (int) data.get("sampleSize"); - // **处理合并单元格** - int startRow = 1; // 从第二行开始(索引从0开始,所以第二行是索引1) - int mergeStep = 4; // 每4行合并一次 + String type = (String) data.get("type"); - // 指定需要合并的列(注意索引从0开始) - int[] mergeColumns = {0, 1, 2, 3, 4, 9}; // 1、2、3、4、5、10列的索引分别是 0, 1, 2, 3, 4, 9 + if (type.equals("inVitro")) { + int startRow = 1; // 从第二行开始(表头是第一行,索引从0开始) + // **处理合并单元格** + int mergeStep = 4; // 每4行合并一次 + int[] mergeColumns = {0, 1, 2, 3, 4, 9}; // 合并的列:第1、2、3、4、5、10列,索引分别是 0, 1, 2, 3, 4, 9 - // 遍历表格数据行 - for (int rowIndex = startRow; rowIndex < table.getNumberOfRows(); rowIndex += mergeStep) { - int endRow = Math.min(rowIndex + mergeStep - 1, table.getNumberOfRows() - 1); // 计算合并的终止行,防止越界 + // 遍历表格数据行 + for (int rowIndex = startRow; rowIndex < table.getNumberOfRows(); rowIndex += mergeStep) { + int endRow = Math.min(rowIndex + mergeStep - 1, table.getNumberOfRows() - 1); // 计算合并的终止行,防止越界 + for (int col : mergeColumns) { + TableTools.mergeCellsVertically(table, col, rowIndex, endRow); + } + } + } else { + int compoundSize = (int) data.get("compoundSize"); // 获取compoundSize值 + + // **处理合并单元格** + int startRow = 1; // 从第二行开始(表头是第一行,索引从0开始) + String currentCompoundName = null; + int mergeStartRow = -1; + + for (int rowIndex = startRow; rowIndex < table.getNumberOfRows(); rowIndex++) { + XWPFTableRow row = table.getRow(rowIndex); + XWPFTableCell cell = row.getCell(1); // 获取第二列的单元格(索引1) + String compoundName = cell.getText().trim(); + + if (currentCompoundName == null || !currentCompoundName.equals(compoundName)) { + // 如果当前化合物名称与上一行不同,则结束之前的合并 + if (mergeStartRow >= 0 && rowIndex > mergeStartRow + 1) { + TableTools.mergeCellsVertically(table, 1, mergeStartRow, rowIndex - 1); // 合并第二列(列索引1) + } + currentCompoundName = compoundName; + mergeStartRow = rowIndex; + } + } - for (int col : mergeColumns) { - TableTools.mergeCellsVertically(table, col, rowIndex, endRow); + // 处理最后一组合并(循环结束后可能残留未合并的区域) + if (mergeStartRow >= 0 && mergeStartRow < table.getNumberOfRows() - 1) { + TableTools.mergeCellsVertically(table, 1, mergeStartRow, table.getNumberOfRows() - 1); } } @@ -615,7 +645,6 @@ public class InspectRecordServiceImpl implements InspectRecordService { } - /** * 生成常规毒品的检验记录(贵阳禁毒) */ @@ -720,13 +749,18 @@ public class InspectRecordServiceImpl implements InspectRecordService { if (references == null || references.isEmpty()) { data.put("referenceMaterialName", "未找到试剂耗材数据!"); } else { - String firstStr = "\u2611" + " " + references.get(0).getReagentConsumableName() + "\n"; - references.remove(references.get(0)); - String referenceMaterialName = references.stream() - .map(reagent -> "\u3000\u3000\u2611" + " " + reagent.getReagentConsumableName()) - .collect(Collectors.joining("\n")); - data.put("referenceMaterialName", firstStr + referenceMaterialName); + String referenceMaterialName = ""; + if (references.size() == 1) { + referenceMaterialName = "\u2611" + " " + references.get(0).getReagentConsumableName(); + } else { + String firstStr = "\u2611" + " " + references.get(0).getReagentConsumableName() + "\n"; + references.remove(references.get(0)); + referenceMaterialName = firstStr + references.stream() + .map(reagent -> "\u3000\u3000\u2611" + " " + reagent.getReagentConsumableName()) + .collect(Collectors.joining("\n")); + } + data.put("referenceMaterialName", referenceMaterialName); data.put("materialIngredient", references.stream() .map(reagent -> reagent.getReagentConsumableName())