修改送检导入模板
This commit is contained in:
@@ -4,6 +4,9 @@ import io.swagger.annotations.ApiModel;
|
|||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@ApiModel(value = "CheckoutResultExcelDTO", description = "存储要导出的检出结果excel数据DTO对象")
|
@ApiModel(value = "CheckoutResultExcelDTO", description = "存储要导出的检出结果excel数据DTO对象")
|
||||||
public class CheckoutResultExcelDTO {
|
public class CheckoutResultExcelDTO {
|
||||||
@@ -14,6 +17,9 @@ public class CheckoutResultExcelDTO {
|
|||||||
@ApiModelProperty("送检日期")
|
@ApiModelProperty("送检日期")
|
||||||
private String deliverTime;
|
private String deliverTime;
|
||||||
|
|
||||||
|
@ApiModelProperty("受理时间")
|
||||||
|
private LocalDateTime acceptTime;
|
||||||
|
|
||||||
@ApiModelProperty("送检单位")
|
@ApiModelProperty("送检单位")
|
||||||
private String clientOrgName;
|
private String clientOrgName;
|
||||||
|
|
||||||
|
|||||||
+41
-21
@@ -281,40 +281,52 @@ public class EntrustMaterialCheckoutResultServiceImpl extends ServiceImpl<Entrus
|
|||||||
private void buildExcel(HttpServletResponse response, List<CheckoutResultExcelDTO> checkoutResultExcelDTOS) throws IOException {
|
private void buildExcel(HttpServletResponse response, List<CheckoutResultExcelDTO> checkoutResultExcelDTOS) throws IOException {
|
||||||
Workbook workbook = new XSSFWorkbook();
|
Workbook workbook = new XSSFWorkbook();
|
||||||
Sheet sheet = workbook.createSheet(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
|
Sheet sheet = workbook.createSheet(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
|
||||||
// 表头导入
|
|
||||||
|
// 表头
|
||||||
List<String> head = buildExcelHead();
|
List<String> head = buildExcelHead();
|
||||||
// 算上表头的行数
|
|
||||||
int rowCount = checkoutResultExcelDTOS.size() + 1;
|
int rowCount = checkoutResultExcelDTOS.size() + 1;
|
||||||
|
|
||||||
for (int i = 0; i < rowCount; i++) {
|
for (int i = 0; i < rowCount; i++) {
|
||||||
if (i == 0) {
|
|
||||||
Row row = sheet.createRow(i);
|
Row row = sheet.createRow(i);
|
||||||
|
|
||||||
|
// 第一行:表头
|
||||||
|
if (i == 0) {
|
||||||
for (int j = 0; j < head.size(); j++) {
|
for (int j = 0; j < head.size(); j++) {
|
||||||
row.createCell(j).setCellValue(head.get(j));
|
row.createCell(j).setCellValue(head.get(j));
|
||||||
}
|
}
|
||||||
} else {
|
continue;
|
||||||
// 开始写入具体数据内容
|
}
|
||||||
Row row = sheet.createRow(i);
|
|
||||||
|
// 数据填充
|
||||||
CheckoutResultExcelDTO excelDTO = checkoutResultExcelDTOS.get(i - 1);
|
CheckoutResultExcelDTO excelDTO = checkoutResultExcelDTOS.get(i - 1);
|
||||||
row.createCell(0).setCellValue(excelDTO.getOrder());
|
|
||||||
row.createCell(1).setCellValue(excelDTO.getDeliverTime());
|
row.createCell(0).setCellValue(getValue(excelDTO.getOrder()));
|
||||||
row.createCell(2).setCellValue(excelDTO.getClientOrgName());
|
row.createCell(1).setCellValue(getValue(excelDTO.getDeliverTime())); // 已经是 String
|
||||||
row.createCell(3).setCellValue(excelDTO.getProvinceCollectPlace());
|
row.createCell(2).setCellValue(getValue(excelDTO.getClientOrgName()));
|
||||||
row.createCell(4).setCellValue(excelDTO.getCityCollectPlace());
|
row.createCell(3).setCellValue(getValue(excelDTO.getProvinceCollectPlace()));
|
||||||
row.createCell(5).setCellValue(excelDTO.getAcceptNo());
|
row.createCell(4).setCellValue(getValue(excelDTO.getCityCollectPlace()));
|
||||||
row.createCell(6).setCellValue(excelDTO.getOrderNo());
|
row.createCell(5).setCellValue(getValue(excelDTO.getAcceptNo()));
|
||||||
row.createCell(7).setCellValue(excelDTO.getTypeName());
|
row.createCell(6).setCellValue(getValue(excelDTO.getOrderNo()));
|
||||||
row.createCell(8).setCellValue(excelDTO.getColor());
|
row.createCell(7).setCellValue(getValue(excelDTO.getTypeName()));
|
||||||
row.createCell(9).setCellValue(excelDTO.getFormName());
|
row.createCell(8).setCellValue(getValue(excelDTO.getColor()));
|
||||||
row.createCell(10).setCellValue(excelDTO.getQualitativeResult());
|
row.createCell(9).setCellValue(getValue(excelDTO.getFormName()));
|
||||||
row.createCell(11).setCellValue(excelDTO.getQuantitativeResult());
|
row.createCell(10).setCellValue(getValue(excelDTO.getQualitativeResult()));
|
||||||
row.createCell(12).setCellValue(excelDTO.getOtherResult());
|
row.createCell(11).setCellValue(getValue(excelDTO.getQuantitativeResult()));
|
||||||
row.createCell(13).setCellValue(excelDTO.getRemark());
|
row.createCell(12).setCellValue(getValue(excelDTO.getOtherResult()));
|
||||||
}
|
row.createCell(13).setCellValue(getValue(excelDTO.getRemark()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 输出到流
|
// 输出到流
|
||||||
workbook.write(response.getOutputStream());
|
workbook.write(response.getOutputStream());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getValue(Object obj) {
|
||||||
|
return obj == null || obj.toString().isEmpty() ? "无" : obj.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private List<String> buildExcelHead() {
|
private List<String> buildExcelHead() {
|
||||||
List<String> headList = new ArrayList<>();
|
List<String> headList = new ArrayList<>();
|
||||||
headList.add("序号");
|
headList.add("序号");
|
||||||
@@ -366,6 +378,7 @@ public class EntrustMaterialCheckoutResultServiceImpl extends ServiceImpl<Entrus
|
|||||||
excelDTO.setAcceptNo(entrust.getAcceptNo());
|
excelDTO.setAcceptNo(entrust.getAcceptNo());
|
||||||
excelDTO.setOrderNo(material.getOrderNo());
|
excelDTO.setOrderNo(material.getOrderNo());
|
||||||
excelDTO.setTypeName(typeName);
|
excelDTO.setTypeName(typeName);
|
||||||
|
excelDTO.setAcceptTime(material.getAcceptTime());
|
||||||
String formName = material.getFormName();
|
String formName = material.getFormName();
|
||||||
// 从检材性状描述中提取,因为贵阳没有填颜色, 匹配有色字的信息,例如“白色粉末”中的“白色”,否则取检材形态描述字段的值。
|
// 从检材性状描述中提取,因为贵阳没有填颜色, 匹配有色字的信息,例如“白色粉末”中的“白色”,否则取检材形态描述字段的值。
|
||||||
excelDTO.setColor(StrUtil.isBlank(material.getColor()) ? formName.substring(0, formName.indexOf("色") + 1) : material.getColor());
|
excelDTO.setColor(StrUtil.isBlank(material.getColor()) ? formName.substring(0, formName.indexOf("色") + 1) : material.getColor());
|
||||||
@@ -384,6 +397,11 @@ public class EntrustMaterialCheckoutResultServiceImpl extends ServiceImpl<Entrus
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
checkoutResultExcelDTOList.sort(Comparator.comparing(CheckoutResultExcelDTO::getAcceptTime));
|
||||||
|
int order = 1;
|
||||||
|
for (CheckoutResultExcelDTO checkoutResultExcelDTO : checkoutResultExcelDTOList) {
|
||||||
|
checkoutResultExcelDTO.setOrder(order++);
|
||||||
|
}
|
||||||
return checkoutResultExcelDTOList;
|
return checkoutResultExcelDTOList;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -664,6 +682,7 @@ public class EntrustMaterialCheckoutResultServiceImpl extends ServiceImpl<Entrus
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据原始鉴定结果获取所有可能的鉴定结果,包括委托、首次鉴定、补充鉴定和重新鉴定的情形。
|
* 根据原始鉴定结果获取所有可能的鉴定结果,包括委托、首次鉴定、补充鉴定和重新鉴定的情形。
|
||||||
|
*
|
||||||
* @param oldResults
|
* @param oldResults
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@@ -845,6 +864,7 @@ public class EntrustMaterialCheckoutResultServiceImpl extends ServiceImpl<Entrus
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 导出Excel
|
* 导出Excel
|
||||||
|
*
|
||||||
* @param response
|
* @param response
|
||||||
* @param excelDTO
|
* @param excelDTO
|
||||||
* @return
|
* @return
|
||||||
|
|||||||
+126
-27
@@ -35,14 +35,12 @@ import java.io.IOException;
|
|||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.time.LocalDate;
|
import java.time.*;
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.time.format.DateTimeFormatterBuilder;
|
||||||
|
import java.time.temporal.ChronoField;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@@ -417,33 +415,54 @@ public class ExcelOperationServiceImpl implements ExcelOperationService {
|
|||||||
* @param cj 案件信息对象
|
* @param cj 案件信息对象
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private List<EntrustmentIdentificationMaterial> processExcelDataToMaterialEntity(List<Map<String, String>> data, Entrustment entrustment, Map<String, DrugLite> drugLiteMap, int orderNo, CaseEvent cj) {
|
private List<EntrustmentIdentificationMaterial> processExcelDataToMaterialEntity(
|
||||||
|
List<Map<String, String>> data,
|
||||||
|
Entrustment entrustment,
|
||||||
|
Map<String, DrugLite> drugLiteMap,
|
||||||
|
int orderNo,
|
||||||
|
CaseEvent cj) {
|
||||||
|
|
||||||
List<EntrustmentIdentificationMaterial> entrustmentIdentificationMaterialList = new ArrayList<>();
|
List<EntrustmentIdentificationMaterial> entrustmentIdentificationMaterialList = new ArrayList<>();
|
||||||
for (Map<String, String> datum : data) {
|
List<String> errorMessages = new ArrayList<>(); // 用于收集错误信息
|
||||||
// 构建检材对象
|
|
||||||
|
for (int i = 0; i < data.size(); i++) {
|
||||||
|
Map<String, String> datum = data.get(i);
|
||||||
|
int rowNum = i + 1; // 实际行号用于报错提示
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 1. 基础数据校验
|
||||||
|
validateField(datum, "疑似物种类", rowNum);
|
||||||
|
validateField(datum, "提取时间", rowNum);
|
||||||
|
|
||||||
EntrustmentIdentificationMaterial material = new EntrustmentIdentificationMaterial();
|
EntrustmentIdentificationMaterial material = new EntrustmentIdentificationMaterial();
|
||||||
material.setId(IdWorker.get32UUID().toUpperCase());
|
material.setId(IdWorker.get32UUID().toUpperCase());
|
||||||
material.setEntrustmentId(entrustment.getId());
|
material.setEntrustmentId(entrustment.getId());
|
||||||
material.setCaseId(entrustment.getCaseId());
|
material.setCaseId(entrustment.getCaseId());
|
||||||
|
|
||||||
material.setName(datum.get("疑似物种类"));
|
material.setName(datum.get("疑似物种类"));
|
||||||
material.setRtSampleQuantity(Integer.valueOf(datum.get("留存样个数")));
|
|
||||||
material.setQuantity(new BigDecimal(datum.get("重量/体积")));
|
// 2. 数值转换校验 (防止 Integer.valueOf 报错)
|
||||||
|
material.setRtSampleQuantity(convertToInt(datum.get("留存样个数"), "留存样个数", rowNum));
|
||||||
|
material.setQuantity(convertToBigDecimal(datum.get("重量/体积"), "重量/体积", rowNum));
|
||||||
material.setUnit(datum.get("单位"));
|
material.setUnit(datum.get("单位"));
|
||||||
String formDesc = datum.get("性状描述");
|
|
||||||
|
// 3. 增强日期解析 (支持 yyyy-MM-dd 和 EEE MMM dd ... 格式)
|
||||||
|
String drawTimeStr = datum.get("提取时间");
|
||||||
|
material.setDrawTime(flexibleDateParse(drawTimeStr, rowNum));
|
||||||
|
|
||||||
|
// 4. 原有业务逻辑
|
||||||
|
String formDesc = datum.getOrDefault("性状描述", "");
|
||||||
material.setForm(formDesc);
|
material.setForm(formDesc);
|
||||||
material.setFormName(formDesc);
|
material.setFormName(formDesc);
|
||||||
// 提取颜色
|
|
||||||
if (StrUtil.isNotBlank(formDesc) && formDesc.contains("色")) {
|
if (StrUtil.isNotBlank(formDesc) && formDesc.contains("色")) {
|
||||||
// 截取“色”之前的部分(包含“色”)
|
|
||||||
material.setColor(formDesc.substring(0, formDesc.indexOf("色") + 1));
|
material.setColor(formDesc.substring(0, formDesc.indexOf("色") + 1));
|
||||||
}
|
}
|
||||||
material.setDrawTime(LocalDate.parse(datum.get("提取时间"), DateTimeFormatter.ofPattern("yyyy-MM-dd")).atStartOfDay());
|
|
||||||
material.setDrawPlace(datum.get("提取地点"));
|
material.setDrawPlace(datum.get("提取地点"));
|
||||||
|
|
||||||
// 检测结果解析
|
String screeningObj = datum.getOrDefault("筛查目标物", "");
|
||||||
String[] drugs = datum.get("筛查目标物").split("、");
|
String[] drugs = screeningObj.split("、");
|
||||||
buildMatchedDrugs(drugLiteMap, material, drugs);
|
buildMatchedDrugs(drugLiteMap, material, drugs);
|
||||||
// 设置委托类型
|
|
||||||
material.setType(String.valueOf(entrustment.getEntrustmentType()));
|
material.setType(String.valueOf(entrustment.getEntrustmentType()));
|
||||||
if (entrustment.getEntrustmentType() == 0) {
|
if (entrustment.getEntrustmentType() == 0) {
|
||||||
material.setTypeName("常规毒品");
|
material.setTypeName("常规毒品");
|
||||||
@@ -451,29 +470,109 @@ public class ExcelOperationServiceImpl implements ExcelOperationService {
|
|||||||
material.setTypeName("生物样本");
|
material.setTypeName("生物样本");
|
||||||
material.setBiologyType(EntrustBiologyType.isExist(formDesc).getDesc());
|
material.setBiologyType(EntrustBiologyType.isExist(formDesc).getDesc());
|
||||||
}
|
}
|
||||||
|
|
||||||
material.setOrderNo(orderNo);
|
material.setOrderNo(orderNo);
|
||||||
material.setImEntrustNumber(String.valueOf(orderNo));
|
material.setImEntrustNumber(String.valueOf(orderNo));
|
||||||
orderNo++;
|
orderNo++;
|
||||||
String packageInfo = datum.get("包装信息");
|
|
||||||
if (packageInfo.equals("完整")) {
|
material.setPackComplete("完整".equals(datum.get("包装信息")));
|
||||||
material.setPackComplete(true);
|
|
||||||
} else {
|
if (StrUtil.isNotBlank(datum.get("年龄"))) {
|
||||||
material.setPackComplete(false);
|
material.setMaterialAge(convertToInt(datum.get("年龄"), "年龄", rowNum));
|
||||||
}
|
|
||||||
String age = datum.get("年龄");
|
|
||||||
if (StrUtil.isNotBlank(age)) {
|
|
||||||
material.setMaterialAge(Integer.valueOf(age));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
material.setBiologyGender(datum.get("性别"));
|
material.setBiologyGender(datum.get("性别"));
|
||||||
material.setAnalysisOption(AnalysisOptionEnums.fromDesc(datum.get("检验项目")).getCode());
|
material.setAnalysisOption(AnalysisOptionEnums.fromDesc(datum.get("检验项目")).getCode());
|
||||||
|
|
||||||
entrustmentIdentificationMaterialService.setMaterialIdentificationNo(material, cj);
|
entrustmentIdentificationMaterialService.setMaterialIdentificationNo(material, cj);
|
||||||
material.setSample1No(sampleService.getNewSampleNo(material.getImNo(), 1));
|
material.setSample1No(sampleService.getNewSampleNo(material.getImNo(), 1));
|
||||||
|
|
||||||
entrustmentIdentificationMaterialList.add(material);
|
entrustmentIdentificationMaterialList.add(material);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
errorMessages.add("第" + rowNum + "行处理失败: " + e.getMessage());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 如果有错误,抛出异常或返回给前端
|
||||||
|
if (!errorMessages.isEmpty()) {
|
||||||
|
throw new RuntimeException("Excel导入校验失败:\n" + String.join("\n", errorMessages));
|
||||||
|
}
|
||||||
|
|
||||||
return entrustmentIdentificationMaterialList;
|
return entrustmentIdentificationMaterialList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 极度灵活的日期解析器:支持 yyyy-MM-dd, yyyy/MM/dd, UTC格式, 以及时间戳
|
||||||
|
*/
|
||||||
|
private LocalDateTime flexibleDateParse(String dateStr, int rowNum) {
|
||||||
|
if (StrUtil.isBlank(dateStr)) return null;
|
||||||
|
|
||||||
|
dateStr = dateStr.trim();
|
||||||
|
|
||||||
|
// 1. 尝试解析常见的数字分割格式 (2025-10-10, 2025/10/10, 2025.10.10)
|
||||||
|
String standardizedDate = dateStr.replace("/", "-").replace(".", "-");
|
||||||
|
if (standardizedDate.matches("\\d{4}-\\d{1,2}-\\d{1,2}.*")) {
|
||||||
|
try {
|
||||||
|
// 取前10位进行日期转换
|
||||||
|
String datePart = standardizedDate.split(" ")[0];
|
||||||
|
// 考虑月日可能是一位数的情况,这里用 DateTimeFormatter 更稳妥
|
||||||
|
DateTimeFormatter df = new DateTimeFormatterBuilder()
|
||||||
|
.appendPattern("yyyy-")
|
||||||
|
.appendValue(ChronoField.MONTH_OF_YEAR)
|
||||||
|
.appendLiteral("-")
|
||||||
|
.appendValue(ChronoField.DAY_OF_MONTH)
|
||||||
|
.toFormatter();
|
||||||
|
return LocalDate.parse(datePart, df).atStartOfDay();
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 如果正则匹配但解析失败,继续往下走
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 尝试解析 UTC 格式 (Fri Oct 10 00:00:00 UTC 2025)
|
||||||
|
if (dateStr.contains("UTC") || dateStr.matches("^[a-zA-Z].*")) {
|
||||||
|
try {
|
||||||
|
DateTimeFormatter utcFormatter = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US);
|
||||||
|
return ZonedDateTime.parse(dateStr, utcFormatter).toLocalDateTime();
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 继续尝试
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 尝试解析纯数字时间戳 (部分 Excel 导入框架会把日期转为 Excel 序列天数或 Unix 时间戳)
|
||||||
|
if (dateStr.matches("^\\d+$")) {
|
||||||
|
try {
|
||||||
|
long val = Long.parseLong(dateStr);
|
||||||
|
// 如果数字很小,可能是 Excel 的天数格式 (比如 45678)
|
||||||
|
if (val < 100000) {
|
||||||
|
return LocalDateTime.of(1899, 12, 30, 0, 0).plusDays(val);
|
||||||
|
}
|
||||||
|
// 否则视为秒级或毫秒级时间戳
|
||||||
|
return LocalDateTime.ofInstant(Instant.ofEpochMilli(val > 10000000000L ? val : val * 1000), ZoneId.systemDefault());
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 继续尝试
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果所有尝试都失败了,给用户清晰的反馈
|
||||||
|
throw new IllegalArgumentException("日期格式[" + dateStr + "]无法识别。支持格式: 2025-10-10, 2025/10/10 或标准系统格式");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 辅助转换方法...
|
||||||
|
private void validateField(Map<String, String> map, String key, int row) {
|
||||||
|
if (StrUtil.isBlank(map.get(key))) throw new IllegalArgumentException(key + "不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
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 + "数字格式错误"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
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 + "数值格式错误"); }
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构建匹配筛查目标物毒品列表
|
* 构建匹配筛查目标物毒品列表
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user