|
|
|
|
@ -1,6 +1,7 @@ |
|
|
|
|
package digital.laboratory.platform.entrustment.service.impl; |
|
|
|
|
|
|
|
|
|
import cn.hutool.core.collection.CollUtil; |
|
|
|
|
import cn.hutool.core.util.IdcardUtil; |
|
|
|
|
import cn.hutool.core.util.StrUtil; |
|
|
|
|
import com.baomidou.mybatisplus.core.toolkit.IdWorker; |
|
|
|
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
|
|
|
|
@ -43,6 +44,7 @@ import java.time.temporal.ChronoUnit; |
|
|
|
|
import java.util.*; |
|
|
|
|
import java.util.function.Function; |
|
|
|
|
import java.util.stream.Collectors; |
|
|
|
|
import java.util.stream.Stream; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @author ChenJiangBao |
|
|
|
|
@ -333,6 +335,7 @@ public class ExcelOperationServiceImpl implements ExcelOperationService { |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* 获取毒品清单信息,并转成map |
|
|
|
|
* |
|
|
|
|
* @return |
|
|
|
|
*/ |
|
|
|
|
private Map<String, DrugLite> getDrugLiteMap() { |
|
|
|
|
@ -423,34 +426,92 @@ public class ExcelOperationServiceImpl implements ExcelOperationService { |
|
|
|
|
CaseEvent cj) { |
|
|
|
|
|
|
|
|
|
List<EntrustmentIdentificationMaterial> entrustmentIdentificationMaterialList = new ArrayList<>(); |
|
|
|
|
List<String> errorMessages = new ArrayList<>(); // 用于收集错误信息
|
|
|
|
|
List<String> errorMessages = new ArrayList<>(); |
|
|
|
|
|
|
|
|
|
// 预定义合法的单位集合
|
|
|
|
|
Set<String> validUnits = Stream.of("g", "mg", "l", "ml").collect(Collectors.toSet()); |
|
|
|
|
// 预定义需要校验身份证的鉴定类别
|
|
|
|
|
Set<String> idCardRequiredResults = Stream.of("首次鉴定", "补充鉴定", "重新鉴定").collect(Collectors.toSet()); |
|
|
|
|
|
|
|
|
|
ArrayList<Suspect> suspects = new ArrayList<>(); |
|
|
|
|
for (int i = 0; i < data.size(); i++) { |
|
|
|
|
Map<String, String> datum = data.get(i); |
|
|
|
|
int rowNum = i + 1; // 实际行号用于报错提示
|
|
|
|
|
int rowNum = i + 2; |
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
// 1. 基础数据校验
|
|
|
|
|
// 1. 基础必填校验
|
|
|
|
|
validateField(datum, "疑似物种类", rowNum); |
|
|
|
|
validateField(datum, "提取时间", rowNum); |
|
|
|
|
|
|
|
|
|
// 2. 单位合法性校验
|
|
|
|
|
String unit = datum.get("单位"); |
|
|
|
|
if (StrUtil.isBlank(unit) || !validUnits.contains(unit.toLowerCase())) { |
|
|
|
|
throw new IllegalArgumentException("单位[" + unit + "]不合法,只能是 g, mg, l, ml 中的一种"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 3. 身份证号业务校验
|
|
|
|
|
// 条件:生物样本(Type=1) 且 属于指定的鉴定结果类别
|
|
|
|
|
// 3. 身份证号业务校验及一致性比对
|
|
|
|
|
if (entrustment.getEntrustmentType() == 1 && idCardRequiredResults.contains(entrustment.getOldIdentificationResult())) { |
|
|
|
|
String idCard = datum.get("身份证号"); |
|
|
|
|
if (StrUtil.isBlank(idCard)) { |
|
|
|
|
throw new IllegalArgumentException("当前鉴定类别下,身份证号不能为空"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 使用 Hutool 的工具类校验身份证合法性(比正则更严谨,会校验最后一位校验码)
|
|
|
|
|
if (!IdcardUtil.isValidCard(idCard)) { |
|
|
|
|
throw new IllegalArgumentException("身份证号[" + idCard + "]格式非法"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// --- 性别一致性校验 ---
|
|
|
|
|
String genderInExcel = datum.get("性别"); |
|
|
|
|
if (StrUtil.isNotBlank(genderInExcel)) { |
|
|
|
|
int genderCode = IdcardUtil.getGenderByIdCard(idCard); // 1为男,0为女
|
|
|
|
|
String genderFromIdCard = (genderCode == 1) ? "男" : "女"; |
|
|
|
|
if (!genderInExcel.equals(genderFromIdCard)) { |
|
|
|
|
throw new IllegalArgumentException("性别[" + genderInExcel + "]与身份证信息(" + genderFromIdCard + ")不一致"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// --- 年龄一致性校验 ---
|
|
|
|
|
String ageStr = datum.get("年龄"); |
|
|
|
|
if (StrUtil.isNotBlank(ageStr)) { |
|
|
|
|
int ageInExcel = Integer.parseInt(ageStr); |
|
|
|
|
// 获取身份证对应的年龄(基于当前系统时间计算)
|
|
|
|
|
int ageFromIdCard = IdcardUtil.getAgeByIdCard(idCard); |
|
|
|
|
|
|
|
|
|
// 考虑到 Excel 录入时可能存在周岁/虚岁或计算日期差异,通常允许 ±1 岁的误差
|
|
|
|
|
if (Math.abs(ageInExcel - ageFromIdCard) > 1) { |
|
|
|
|
throw new IllegalArgumentException("年龄[" + ageInExcel + "]与身份证计算结果(" + ageFromIdCard + ")偏差过大"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
EntrustmentIdentificationMaterial material = new EntrustmentIdentificationMaterial(); |
|
|
|
|
// ... (ID, CaseId 等设置保持不变)
|
|
|
|
|
material.setId(IdWorker.get32UUID().toUpperCase()); |
|
|
|
|
material.setEntrustmentId(entrustment.getId()); |
|
|
|
|
material.setCaseId(entrustment.getCaseId()); |
|
|
|
|
|
|
|
|
|
material.setName(datum.get("疑似物种类")); |
|
|
|
|
|
|
|
|
|
// 2. 数值转换校验 (防止 Integer.valueOf 报错)
|
|
|
|
|
// 4. 增强日期解析 (支持 yyyy-MM-dd, yyyy/MM/dd, UTC格式)
|
|
|
|
|
material.setDrawTime(flexibleDateParse(datum.get("提取时间"), rowNum)); |
|
|
|
|
|
|
|
|
|
// 5. 数值转换
|
|
|
|
|
material.setRtSampleQuantity(convertToInt(datum.get("留存样个数"), "留存样个数", rowNum)); |
|
|
|
|
material.setQuantity(convertToBigDecimal(datum.get("重量/体积"), "重量/体积", rowNum)); |
|
|
|
|
material.setUnit(datum.get("单位")); |
|
|
|
|
material.setUnit(unit); |
|
|
|
|
|
|
|
|
|
// 3. 增强日期解析 (支持 yyyy-MM-dd 和 EEE MMM dd ... 格式)
|
|
|
|
|
String drawTimeStr = datum.get("提取时间"); |
|
|
|
|
material.setDrawTime(flexibleDateParse(drawTimeStr, rowNum)); |
|
|
|
|
// 6. 身份证号赋值 (如果 datum 中存在则记录)
|
|
|
|
|
if (datum.containsKey("身份证号")) { |
|
|
|
|
Suspect suspect = new Suspect(); |
|
|
|
|
suspect.setIdNumber(datum.get("身份证号")); |
|
|
|
|
suspect.setName(datum.get("姓名")); |
|
|
|
|
suspects.add(suspect); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 4. 原有业务逻辑
|
|
|
|
|
// ... (后续原有业务逻辑:性状、目标物、年龄、性别等保持不变)
|
|
|
|
|
// -------------------------------------------------------
|
|
|
|
|
String formDesc = datum.getOrDefault("性状描述", ""); |
|
|
|
|
material.setForm(formDesc); |
|
|
|
|
material.setFormName(formDesc); |
|
|
|
|
@ -458,11 +519,8 @@ public class ExcelOperationServiceImpl implements ExcelOperationService { |
|
|
|
|
material.setColor(formDesc.substring(0, formDesc.indexOf("色") + 1)); |
|
|
|
|
} |
|
|
|
|
material.setDrawPlace(datum.get("提取地点")); |
|
|
|
|
|
|
|
|
|
String screeningObj = datum.getOrDefault("筛查目标物", ""); |
|
|
|
|
String[] drugs = screeningObj.split("、"); |
|
|
|
|
String[] drugs = datum.getOrDefault("筛查目标物", "").split("、"); |
|
|
|
|
buildMatchedDrugs(drugLiteMap, material, drugs); |
|
|
|
|
|
|
|
|
|
material.setType(String.valueOf(entrustment.getEntrustmentType())); |
|
|
|
|
if (entrustment.getEntrustmentType() == 0) { |
|
|
|
|
material.setTypeName("常规毒品"); |
|
|
|
|
@ -470,35 +528,29 @@ public class ExcelOperationServiceImpl implements ExcelOperationService { |
|
|
|
|
material.setTypeName("生物样本"); |
|
|
|
|
material.setBiologyType(EntrustBiologyType.isExist(formDesc).getDesc()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
material.setOrderNo(orderNo); |
|
|
|
|
material.setImEntrustNumber(String.valueOf(orderNo)); |
|
|
|
|
orderNo++; |
|
|
|
|
|
|
|
|
|
material.setPackComplete("完整".equals(datum.get("包装信息"))); |
|
|
|
|
|
|
|
|
|
if (StrUtil.isNotBlank(datum.get("年龄"))) { |
|
|
|
|
material.setMaterialAge(convertToInt(datum.get("年龄"), "年龄", rowNum)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
material.setBiologyGender(datum.get("性别")); |
|
|
|
|
material.setAnalysisOption(AnalysisOptionEnums.fromDesc(datum.get("检验项目")).getCode()); |
|
|
|
|
|
|
|
|
|
entrustmentIdentificationMaterialService.setMaterialIdentificationNo(material, cj); |
|
|
|
|
material.setSample1No(sampleService.getNewSampleNo(material.getImNo(), 1)); |
|
|
|
|
|
|
|
|
|
entrustmentIdentificationMaterialList.add(material); |
|
|
|
|
|
|
|
|
|
} catch (Exception e) { |
|
|
|
|
errorMessages.add("第" + rowNum + "行处理失败: " + e.getMessage()); |
|
|
|
|
errorMessages.add("第" + rowNum + "行: " + e.getMessage()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 5. 如果有错误,抛出异常或返回给前端
|
|
|
|
|
if (!errorMessages.isEmpty()) { |
|
|
|
|
throw new RuntimeException("Excel导入校验失败:\n" + String.join("\n", errorMessages)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
suspectService.addSuspectList(suspects, entrustment.getId()); |
|
|
|
|
return entrustmentIdentificationMaterialList; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -564,13 +616,19 @@ public class ExcelOperationServiceImpl implements ExcelOperationService { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private Integer convertToInt(String val, String fieldName, int row) { |
|
|
|
|
try { return StrUtil.isBlank(val) ? 0 : Integer.valueOf(val); } |
|
|
|
|
catch (Exception e) { throw new IllegalArgumentException(fieldName + "数字格式错误"); } |
|
|
|
|
try { |
|
|
|
|
return StrUtil.isBlank(val) ? 0 : Integer.valueOf(val); |
|
|
|
|
} catch (Exception e) { |
|
|
|
|
throw new IllegalArgumentException(fieldName + "数字格式错误"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private BigDecimal convertToBigDecimal(String val, String fieldName, int row) { |
|
|
|
|
try { return StrUtil.isBlank(val) ? BigDecimal.ZERO : new BigDecimal(val); } |
|
|
|
|
catch (Exception e) { throw new IllegalArgumentException(fieldName + "数值格式错误"); } |
|
|
|
|
try { |
|
|
|
|
return StrUtil.isBlank(val) ? BigDecimal.ZERO : new BigDecimal(val); |
|
|
|
|
} catch (Exception e) { |
|
|
|
|
throw new IllegalArgumentException(fieldName + "数值格式错误"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
@ -581,7 +639,7 @@ public class ExcelOperationServiceImpl implements ExcelOperationService { |
|
|
|
|
* @param drugs 待匹配毒品名称数组 |
|
|
|
|
* @throws CheckedException 抛出检查异常 |
|
|
|
|
*/ |
|
|
|
|
private void buildMatchedDrugs(Map<String, DrugLite> drugLiteMap, EntrustmentIdentificationMaterial material,String[] drugs) { |
|
|
|
|
private void buildMatchedDrugs(Map<String, DrugLite> drugLiteMap, EntrustmentIdentificationMaterial material, String[] drugs) { |
|
|
|
|
ArrayList<DrugLite> matchedDrugs = new ArrayList<>(); |
|
|
|
|
if (drugs.length == 0 || (drugs.length == 1 && drugs[0].trim().isEmpty())) { |
|
|
|
|
matchedDrugs.add(drugLiteMap.get("海洛因")); |
|
|
|
|
|