From d0bbd4b023cc24ff38fc017dc348a1dfc549fe6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=B5=B7=E8=88=AA?= <11918452+yang-haihang@user.noreply.gitee.com> Date: Thu, 12 Mar 2026 14:13:44 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=80=81=E6=A3=80=E5=AF=BC?= =?UTF-8?q?=E5=85=A5=E6=A8=A1=E6=9D=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/ExcelOperationServiceImpl.java | 120 +++++++++++++----- src/main/resources/bootstrap.yml | 1 + 2 files changed, 90 insertions(+), 31 deletions(-) diff --git a/src/main/java/digital/laboratory/platform/entrustment/service/impl/ExcelOperationServiceImpl.java b/src/main/java/digital/laboratory/platform/entrustment/service/impl/ExcelOperationServiceImpl.java index 133db3f..4531b5e 100644 --- a/src/main/java/digital/laboratory/platform/entrustment/service/impl/ExcelOperationServiceImpl.java +++ b/src/main/java/digital/laboratory/platform/entrustment/service/impl/ExcelOperationServiceImpl.java @@ -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 getDrugLiteMap() { @@ -423,34 +426,92 @@ public class ExcelOperationServiceImpl implements ExcelOperationService { CaseEvent cj) { List entrustmentIdentificationMaterialList = new ArrayList<>(); - List errorMessages = new ArrayList<>(); // 用于收集错误信息 + List errorMessages = new ArrayList<>(); + + // 预定义合法的单位集合 + Set validUnits = Stream.of("g", "mg", "l", "ml").collect(Collectors.toSet()); + // 预定义需要校验身份证的鉴定类别 + Set idCardRequiredResults = Stream.of("首次鉴定", "补充鉴定", "重新鉴定").collect(Collectors.toSet()); + ArrayList suspects = new ArrayList<>(); for (int i = 0; i < data.size(); i++) { Map 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("单位")); - - // 3. 增强日期解析 (支持 yyyy-MM-dd 和 EEE MMM dd ... 格式) - String drawTimeStr = datum.get("提取时间"); - material.setDrawTime(flexibleDateParse(drawTimeStr, rowNum)); + material.setUnit(unit); + + // 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,24 +616,30 @@ 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 + "数值格式错误"); + } } /** * 构建匹配筛查目标物毒品列表 * - * @param drugLiteMap 毒品信息缓存Map - * @param material 委托鉴定检材对象 - * @param drugs 待匹配毒品名称数组 + * @param drugLiteMap 毒品信息缓存Map + * @param material 委托鉴定检材对象 + * @param drugs 待匹配毒品名称数组 * @throws CheckedException 抛出检查异常 */ - private void buildMatchedDrugs(Map drugLiteMap, EntrustmentIdentificationMaterial material,String[] drugs) { + private void buildMatchedDrugs(Map drugLiteMap, EntrustmentIdentificationMaterial material, String[] drugs) { ArrayList matchedDrugs = new ArrayList<>(); if (drugs.length == 0 || (drugs.length == 1 && drugs[0].trim().isEmpty())) { matchedDrugs.add(drugLiteMap.get("海洛因")); diff --git a/src/main/resources/bootstrap.yml b/src/main/resources/bootstrap.yml index 4e4eff4..dcc7e0b 100644 --- a/src/main/resources/bootstrap.yml +++ b/src/main/resources/bootstrap.yml @@ -47,6 +47,7 @@ spring: max-file-size: 20MB # 默认最大请求大小为10M, 总上传的数据大小 max-request-size: 55MB + location: D:/temp # 文件上传相关 支持阿里云、华为云、腾讯、minio