This commit is contained in:
杨海航
2025-03-27 17:23:37 +08:00
parent 279b9a92bd
commit 21f359cb4f
4 changed files with 174 additions and 20 deletions

View File

@@ -93,4 +93,7 @@ public class TestRecord extends BaseEntity {
@ApiModelProperty("实验结束时间")
@JsonFormat(pattern = "yyyy/MM/dd", timezone = "GMT+8")
private LocalDate testEndDate;
@ApiModelProperty("业务Id特指委托ID")
private String businessId;
}

View File

@@ -3,6 +3,8 @@ package digital.laboratory.platform.inspection.dto;
import digital.laboratory.platform.inspection.entity.TestRecordSampleData;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class TestRecordSampleDataDocDTO extends TestRecordSampleData {
@@ -53,4 +55,12 @@ public class TestRecordSampleDataDocDTO extends TestRecordSampleData {
* 样本索引编号
*/
private String indexNum;
/**
* 质荷比(m/z) nps案件
* p 表示打印 (Print)
*/
private String pMassToChargeRatio;
}

View File

@@ -1,4 +1,5 @@
package digital.laboratory.platform.inspection.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
@@ -37,6 +38,7 @@ import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -80,7 +82,7 @@ public class InspectRecordServiceImpl implements InspectRecordService {
/**
* 生成检验记录-贵阳禁毒
*
* @param businessId 委托id
* @param businessId 委托id
* @param materialType 标注当前委托的检材是尿液还是毛发
* @return
* @throws Exception
@@ -141,19 +143,6 @@ public class InspectRecordServiceImpl implements InspectRecordService {
// 生成基础数据
HashMap<String, Object> data = buildCommonInspectRecordDocMap(entrustInfo, testRecord, materialType);
// 获取仪器设备数据(批量查询,减少数据库压力)
List<String> deviceIdList = testRecord.getDeviceIdList();
List<TestRecordInstrument> instruments = CollectionUtils.isEmpty(deviceIdList)
? Collections.emptyList()
: testRecordInstrumentService.list(Wrappers.<TestRecordInstrument>lambdaQuery()
.in(TestRecordInstrument::getId, deviceIdList));
data.put("instrumentName", CollectionUtils.isEmpty(instruments)
? "未找到仪器设备数据!"
: instruments.stream()
.map(i -> "\u3000\u3000" + i.getInstrumentName()) // 使用 Unicode 全角空格
.collect(Collectors.joining("\n")));
// 获取样品数据
List<TestRecordSampleData> dataList = testRecordSampleDataService.list(
@@ -275,11 +264,138 @@ public class InspectRecordServiceImpl implements InspectRecordService {
.collect(Collectors.toList()));
// 返回处理后的数据
data.put("dataDtos", dataDtos);
data.put("sampleSize", dataDtos.size());
data.put("sampleSize", dataDtos.size() / 2);
data.put("inspectOpinion", this.buildInspectOpinion(dataList));
return data;
}
public Map<String, Object> buildInVitroRecordData(EntrustInfo entrustInfo, TestRecord testRecord) {
Map<String, Object> data = new HashMap<>();
// 1⃣ 按化合物名称分组 TestRecordSampleData
Map<String, List<TestRecordSampleData>> compoundSampleDataMap = testRecordSampleDataService
.lambdaQuery()
.eq(TestRecordSampleData::getTestId, testRecord.getId())
.list()
.stream()
.collect(Collectors.groupingBy(TestRecordSampleData::getCompoundName));
// 2⃣ 过滤出 "标准物质" 类别的试剂,并转换为 Map (key=药品名称, value=试剂VO)
List<String> reagentConsumablesList = testRecord.getReagentConsumablesList();
Map<String, TestRecordReagentVO> reagentMap = reagentConsumablesList.stream()
.map(testRecordReagentService::getVOById)
.filter(vo -> "标准物质".equals(vo.getCategory())) // 仅保留 "标准物质"
.collect(Collectors.toMap(vo -> vo.getDrug().getName(), vo -> vo));
List<TestRecordSampleDataDocDTO> dataDtos = new ArrayList<>();
// 3⃣ 遍历每种化合物,处理实验数据
for (Map.Entry<String, List<TestRecordSampleData>> entry : compoundSampleDataMap.entrySet()) {
String compoundName = entry.getKey();
List<TestRecordSampleData> sampleDataList = entry.getValue();
// 按 sampleType 分组(如 STD, Analyte
Map<String, List<TestRecordSampleData>> sampleTypeMap = sampleDataList.stream()
.collect(Collectors.groupingBy(TestRecordSampleData::getSampleType));
// 获取标准样本STD
List<TestRecordSampleData> stdList = sampleTypeMap.get("STD");
if (stdList == null || stdList.isEmpty()) {
continue; // 没有 STD 样本,跳过该化合物
}
TestRecordSampleData stdSample = stdList.get(0);
// 4⃣ 获取 STD 样本的扩展数据 (以 MassToChargeRatio 为 key)
Map<BigDecimal, TestRecordSampleDataExpand> expandMap = testRecordSampledataExpandService.lambdaQuery()
.eq(TestRecordSampleDataExpand::getTestDataId, stdSample.getId())
.list()
.stream()
.collect(Collectors.toMap(TestRecordSampleDataExpand::getMassToChargeRatio, Function.identity()));
// 5⃣ 获取当前化合物对应的试剂,提取特征离子
TestRecordReagentVO reagentVO = reagentMap.get(compoundName);
if (reagentVO == null || reagentVO.getDrug().getCharacteristicIons() == null) {
continue; // 没有对应试剂或特征离子数据,跳过
}
String[] peaks = reagentVO.getDrug().getCharacteristicIons().split("");
// 6⃣ 处理 "标样" 数据 (STD)
for (int i = 0; i < peaks.length; i++) {
String peak = (i == 0) ? peaks[i].substring(0, peaks[i].length() - 1) : peaks[i];
TestRecordSampleDataExpand expand = expandMap.get(new BigDecimal(peak));
if (expand != null) {
TestRecordSampleDataDocDTO dto = new TestRecordSampleDataDocDTO();
BeanUtils.copyProperties(stdSample, dto);
dto.setName("标样");
dto.setPTargetRtTime(dto.getTargetRtTime().toString());
dto.setPRtTimeError("±1");
dto.setPRtTimeWithinError("/");
dto.setPMassToChargeRatio(i == 0 ? peak + "(基峰)" : peak);
dto.setPIonAbundanceRatio(expand.getIonAbundanceRatio().toString());
dto.setPIonAbundanceRatioError(expand.getIonAbundanceRatioError().toString());
dto.setPIonAbundanceRatioWithinError(expand.getIonAbundanceRatioWithinError());
dto.setPIsDetected("/");
dataDtos.add(dto);
}
}
// 7⃣ 处理 "标样空白" 数据
for (String peak : peaks) {
TestRecordSampleDataDocDTO dto = new TestRecordSampleDataDocDTO();
dto.setName("标样空白");
dto.setCompoundName(compoundName);
dto.setPTargetRtTime("/");
dto.setPRtTimeError("/");
dto.setPRtTimeWithinError("/");
dto.setPMassToChargeRatio(peak.equals(peaks[0]) ? peak + "(基峰)" : peak);
dto.setPIonAbundanceRatio("/");
dto.setPIonAbundanceRatioError("/");
dto.setPIonAbundanceRatioWithinError(peak.equals(peaks[0]) ? "/" : "");
dto.setPIsDetected("/");
dataDtos.add(dto);
}
// 8⃣ 处理 "Analyte" 样本
List<TestRecordSampleData> analyteList = sampleTypeMap.get("Analyte");
if (analyteList != null) {
analyteList.sort(testRecordSampleDataService.getSortBySampleNo()); // 按样本编号排序
for (TestRecordSampleData analyte : analyteList) {
Map<BigDecimal, TestRecordSampleDataExpand> analyteExpandMap = testRecordSampledataExpandService.lambdaQuery()
.eq(TestRecordSampleDataExpand::getTestDataId, analyte.getId())
.list()
.stream()
.collect(Collectors.toMap(TestRecordSampleDataExpand::getMassToChargeRatio, Function.identity()));
for (int i = 0; i < peaks.length; i++) {
String peak = (i == 0) ? peaks[i].substring(0, peaks[i].length() - 1) : peaks[i];
TestRecordSampleDataExpand expand = analyteExpandMap.get(new BigDecimal(peak));
if (expand != null) {
TestRecordSampleDataDocDTO dto = new TestRecordSampleDataDocDTO();
BeanUtils.copyProperties(analyte, dto);
dto.setPTargetRtTime(dto.getTargetRtTime().toString());
dto.setPRtTimeError(dto.getRtTimeWithinError());
dto.setPRtTimeWithinError(dto.getRtTimeWithinError());
dto.setPMassToChargeRatio(i == 0 ? peak + "(基峰)" : peak);
dto.setPIonAbundanceRatio(expand.getIonAbundanceRatio().toString());
dto.setPIonAbundanceRatioError(expand.getIonAbundanceRatioError().toString());
dto.setPIonAbundanceRatioWithinError(expand.getIonAbundanceRatioWithinError());
dto.setPIsDetected(dto.getIsDetected() == 1 ? "" : "");
dataDtos.add(dto);
}
}
}
}
}
// 9⃣ 返回处理后的数据
data.put("dataDtos", dataDtos);
return data;
}
public void buildIonPairAndCE(Map<String, Object> data, List<String> reagentIdList) {
List<IonPairAndCEVO> ionPairAndCEVOS = new ArrayList<>();
@@ -387,14 +503,20 @@ public class InspectRecordServiceImpl implements InspectRecordService {
/**
* 生成常规毒品的检验记录(贵阳禁毒)
*/
public String generateCommonDrugInpectRecord(String entrustId) throws Exception {
Map<String, Object> docMap = buildCommonDrugDocMap(entrustId);
public String generateCommonDrugInpectRecord(String businessId) throws Exception {
Map<String, Object> docMap = buildCommonDrugDocMap(businessId);
EntrustInfo entrustInfo = entrustInfoService.getById(businessId);
TestRecord testRecord = testRecordService.lambdaQuery()
.eq(TestRecord::getBusinessId, businessId)
.one();
Map<String, Object> data = this.buildInVitroRecordData(entrustInfo, testRecord);
docMap.putAll(data);
String templatePath = "/template" + "/贵阳禁毒常规毒品检验记录模板.docx";
LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
Configure config = Configure.builder().
bind("dataDtos", policy)
.build();
return buildDocFileAndUploadToOss(entrustId, templatePath, config, docMap);
return buildDocFileAndUploadToOss(businessId, templatePath, config, docMap);
}
/**
@@ -402,8 +524,8 @@ public class InspectRecordServiceImpl implements InspectRecordService {
*
* @return
*/
private Map<String, Object> buildCommonDrugDocMap(String entrustId) {
EntrustInfo entrustInfo = entrustInfoService.getById(entrustId);
private Map<String, Object> buildCommonDrugDocMap(String businessId) {
EntrustInfo entrustInfo = entrustInfoService.getById(businessId);
// 这里因为检验记录实体并未关联业务id, 只能先查询实验数据,在通过实验数据获取到检验记录信息
TestRecord testRecord = testRecordService.getTestRecordByBusinessId(entrustInfo.getId());
@@ -411,6 +533,7 @@ public class InspectRecordServiceImpl implements InspectRecordService {
// 封装数据到map中
Map<String, Object> docMap = buildCommonInspectRecordDocMap(entrustInfo, testRecord, "");
return docMap;
}
@@ -461,6 +584,20 @@ public class InspectRecordServiceImpl implements InspectRecordService {
data.put("materialCharacterDesc", materialCharacterDesc);
data.put("materialIngredient", targetObjectStr);
// 获取仪器设备数据(批量查询,减少数据库压力)
List<String> deviceIdList = testRecord.getDeviceIdList();
List<TestRecordInstrument> instruments = CollectionUtils.isEmpty(deviceIdList)
? Collections.emptyList()
: testRecordInstrumentService.list(Wrappers.<TestRecordInstrument>lambdaQuery()
.in(TestRecordInstrument::getId, deviceIdList));
data.put("instrumentName", CollectionUtils.isEmpty(instruments)
? "未找到仪器设备数据!"
: instruments.stream()
.map(i -> "\u3000\u3000" + i.getInstrumentName()) // 使用 Unicode 全角空格
.collect(Collectors.joining("\n")));
// 设置使用的标准物质和试剂
List<TestRecordReagent> references = testRecordReagentService.list(Wrappers.<TestRecordReagent>lambdaQuery()
.in(TestRecordReagent::getId, testRecord.getReagentConsumablesList())

View File

@@ -161,6 +161,9 @@ public class TestRecordServiceImpl extends ServiceImpl<TestRecordMapper, TestRec
//通过业务ID创建实验
} else if (testRecord.getBusinessDtoList() != null && testRecord.getBusinessDtoList().size() > 0) {
if (testRecord.getBusinessDtoList().size()>1){
throw new RuntimeException("一次只能选择一个业务!");
}
List<BusinessDto> businessDtoList = testRecord.getBusinessDtoList();
this.judgmentBusinessType(businessDtoList);//判断是否有不同类型的业务
businessDtoList.forEach(item -> {
@@ -183,6 +186,7 @@ public class TestRecordServiceImpl extends ServiceImpl<TestRecordMapper, TestRec
}
sampleInfoService.updateBatchById(sampleInfos);
}
testRecord.setBusinessId(testRecord.getBusinessDtoList().get(0).getBusinessId());
testRecord.setTestUserId(dlpUser.getId());
testRecord.setTestSerialNumber(this.createTestNumber());
testRecord.setSampleTestList(sampleIdList);