|
|
|
@ -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()) |
|
|
|
|