feat(test-report): 支持xls和doc格式文件上传。优化台账管理功能,即监测点的word附件可以为空。

This commit is contained in:
dk
2026-07-21 10:19:29 +08:00
parent dbd288faec
commit 598ff9ea81
7 changed files with 124 additions and 48 deletions

View File

@@ -13,11 +13,11 @@ public final class AiReportFileExtensionConst {
private AiReportFileExtensionConst() { private AiReportFileExtensionConst() {
} }
public static final Set<String> ALLOWED_EXTENSIONS = unmodifiable("docx", "xlsx", "pdf"); public static final Set<String> ALLOWED_EXTENSIONS = unmodifiable("docx", "xls", "xlsx", "pdf");
public static final Set<String> WORD_EXTENSIONS = unmodifiable("docx"); public static final Set<String> WORD_EXTENSIONS = unmodifiable("docx");
public static final Set<String> EXCEL_EXTENSIONS = unmodifiable("xlsx"); public static final Set<String> EXCEL_EXTENSIONS = unmodifiable("xls", "xlsx");
public static final Set<String> PDF_EXTENSIONS = unmodifiable("pdf"); public static final Set<String> PDF_EXTENSIONS = unmodifiable("pdf");

View File

@@ -65,12 +65,12 @@ public class TestReportLedgerExcelParser {
public ParsedLedger parseForValidate(String fileName, InputStream inputStream) { public ParsedLedger parseForValidate(String fileName, InputStream inputStream) {
String normalizedFileName = StrUtil.trimToNull(fileName); String normalizedFileName = StrUtil.trimToNull(fileName);
if (!TestReportConst.LEDGER_SUMMARY_FILE_NAME.equals(normalizedFileName)) { if (!TestReportConst.isLedgerSummaryFileName(normalizedFileName)) {
throw new BusinessException(CommonResponseEnum.FAIL, "校验文件阶段:台账汇总文件名必须为台账信息汇总.xlsx"); throw new BusinessException(CommonResponseEnum.FAIL, "校验文件阶段:台账汇总文件名必须为台账信息汇总.xls或台账信息汇总.xlsx");
} }
try (Workbook workbook = WorkbookFactory.create(inputStream)) { try (Workbook workbook = WorkbookFactory.create(inputStream)) {
ParsedLedger ledger = new ParsedLedger(); ParsedLedger ledger = new ParsedLedger();
ledger.setSummaryFileName(TestReportConst.LEDGER_SUMMARY_FILE_NAME); ledger.setSummaryFileName(normalizedFileName);
ledger.getRequiredSheets().addAll(REQUIRED_SHEETS); ledger.getRequiredSheets().addAll(REQUIRED_SHEETS);
collectSheets(ledger, workbook); collectSheets(ledger, workbook);
@@ -139,11 +139,13 @@ public class TestReportLedgerExcelParser {
point.setTestDeviceNo(optionalCell(row, 3)); point.setTestDeviceNo(optionalCell(row, 3));
point.setClientUnitName(optionalCell(row, 4)); point.setClientUnitName(optionalCell(row, 4));
point.setExcelAttachmentName(requireCell(row, 5, rowIndex, "Excel附件名称")); point.setExcelAttachmentName(requireCell(row, 5, rowIndex, "Excel附件名称"));
point.setWordAttachmentName(requireCell(row, 6, rowIndex, "Word附件名称")); point.setWordAttachmentName(optionalCell(row, 6));
validateExtension(point.getExcelAttachmentName(), Arrays.asList(".xls", ".xlsx"), validateExtension(point.getExcelAttachmentName(), Arrays.asList(".xls", ".xlsx"),
"" + (rowIndex + 1) + "行Excel附件扩展名仅允许xls/xlsx"); "" + (rowIndex + 1) + "行Excel附件扩展名仅允许xls/xlsx");
validateExtension(point.getWordAttachmentName(), Arrays.asList(".doc", ".docx"), if (StrUtil.isNotBlank(point.getWordAttachmentName())) {
"" + (rowIndex + 1) + "行Word附件扩展名仅允许doc/docx"); validateExtension(point.getWordAttachmentName(), Arrays.asList(".doc", ".docx"),
"" + (rowIndex + 1) + "行Word附件扩展名仅允许doc/docx");
}
String pointKey = point.getSubstationName() + "|" + point.getPointName(); String pointKey = point.getSubstationName() + "|" + point.getPointName();
if (!pointKeys.add(pointKey)) { if (!pointKeys.add(pointKey)) {
throw new BusinessException(CommonResponseEnum.FAIL, "校验文件阶段:监测点信息中存在重复点位"); throw new BusinessException(CommonResponseEnum.FAIL, "校验文件阶段:监测点信息中存在重复点位");
@@ -151,7 +153,7 @@ public class TestReportLedgerExcelParser {
if (!excelNames.add(point.getExcelAttachmentName())) { if (!excelNames.add(point.getExcelAttachmentName())) {
throw new BusinessException(CommonResponseEnum.FAIL, "校验文件阶段监测点信息中存在重复Excel附件名称"); throw new BusinessException(CommonResponseEnum.FAIL, "校验文件阶段监测点信息中存在重复Excel附件名称");
} }
if (!wordNames.add(point.getWordAttachmentName())) { if (StrUtil.isNotBlank(point.getWordAttachmentName()) && !wordNames.add(point.getWordAttachmentName())) {
throw new BusinessException(CommonResponseEnum.FAIL, "校验文件阶段监测点信息中存在重复Word附件名称"); throw new BusinessException(CommonResponseEnum.FAIL, "校验文件阶段监测点信息中存在重复Word附件名称");
} }
points.add(point); points.add(point);
@@ -229,7 +231,7 @@ public class TestReportLedgerExcelParser {
if (!attachmentNames.contains(point.getExcelAttachmentName())) { if (!attachmentNames.contains(point.getExcelAttachmentName())) {
throw new BusinessException(CommonResponseEnum.FAIL, "校验文件阶段:第" + point.getRowNo() + "行缺少Excel附件"); throw new BusinessException(CommonResponseEnum.FAIL, "校验文件阶段:第" + point.getRowNo() + "行缺少Excel附件");
} }
if (!attachmentNames.contains(point.getWordAttachmentName())) { if (StrUtil.isNotBlank(point.getWordAttachmentName()) && !attachmentNames.contains(point.getWordAttachmentName())) {
throw new BusinessException(CommonResponseEnum.FAIL, "校验文件阶段:第" + point.getRowNo() + "行缺少Word附件"); throw new BusinessException(CommonResponseEnum.FAIL, "校验文件阶段:第" + point.getRowNo() + "行缺少Word附件");
} }
} }

View File

@@ -78,24 +78,25 @@ public class TestReportLedgerImportService {
TestReportStorageService.UploadedBatch uploadedBatch = testReportStorageService.saveValidateSessionFiles(sessionId, fileMap); TestReportStorageService.UploadedBatch uploadedBatch = testReportStorageService.saveValidateSessionFiles(sessionId, fileMap);
List<String> sessionFileNames = testReportStorageService.listValidateSessionFileNames(sessionId); List<String> sessionFileNames = testReportStorageService.listValidateSessionFileNames(sessionId);
Set<String> sessionFileNameSet = new HashSet<String>(sessionFileNames); Set<String> sessionFileNameSet = new HashSet<String>(sessionFileNames);
String summaryFileName = resolveSummaryFileName(sessionFileNameSet);
TestReportLedgerValidateResultVO result = new TestReportLedgerValidateResultVO(); TestReportLedgerValidateResultVO result = new TestReportLedgerValidateResultVO();
result.setSessionId(sessionId); result.setSessionId(sessionId);
result.setTempStoragePath(uploadedBatch.getTempStoragePath()); result.setTempStoragePath(uploadedBatch.getTempStoragePath());
result.setUploadedFileCount(sessionFileNames.size()); result.setUploadedFileCount(sessionFileNames.size());
result.setCanContinueUpload(Boolean.TRUE); result.setCanContinueUpload(Boolean.TRUE);
result.setSummaryFileName(TestReportConst.LEDGER_SUMMARY_FILE_NAME); result.setSummaryFileName(summaryFileName);
result.setSummaryFilePresent(sessionFileNameSet.contains(TestReportConst.LEDGER_SUMMARY_FILE_NAME)); result.setSummaryFilePresent(summaryFileName != null);
if (!Boolean.TRUE.equals(result.getSummaryFilePresent())) { if (!Boolean.TRUE.equals(result.getSummaryFilePresent())) {
result.setSuccess(Boolean.FALSE); result.setSuccess(Boolean.FALSE);
result.getFailReasons().add("鏍¢獙鏂囦欢闃舵锛氱己灏戝彴璐︿俊鎭眹鎬?xlsx"); result.getFailReasons().add("校验文件阶段:缺少台账信息汇总.xls或台账信息汇总.xlsx");
persistValidateSessionResult(sessionId, result); persistValidateSessionResult(sessionId, result);
return result; return result;
} }
try (AiReportMinioStorageService.StoredObject storedObject = try (AiReportMinioStorageService.StoredObject storedObject =
testReportStorageService.getValidateSessionObject(sessionId, TestReportConst.LEDGER_SUMMARY_FILE_NAME); testReportStorageService.getValidateSessionObject(sessionId, summaryFileName);
InputStream inputStream = storedObject.getInputStream()) { InputStream inputStream = storedObject.getInputStream()) {
TestReportLedgerExcelParser.ParsedLedger ledger = testReportLedgerExcelParser.parseForValidate( TestReportLedgerExcelParser.ParsedLedger ledger = testReportLedgerExcelParser.parseForValidate(
TestReportConst.LEDGER_SUMMARY_FILE_NAME, inputStream); summaryFileName, inputStream);
Map<String, TestDevicePO> dbDeviceMap = loadExistingDevices(collectDeviceNos(ledger)); Map<String, TestDevicePO> dbDeviceMap = loadExistingDevices(collectDeviceNos(ledger));
Map<String, ClientUnitPO> dbClientMap = loadExistingClients(collectClientNames(ledger)); Map<String, ClientUnitPO> dbClientMap = loadExistingClients(collectClientNames(ledger));
result.getRequiredSheets().addAll(ledger.getRequiredSheets()); result.getRequiredSheets().addAll(ledger.getRequiredSheets());
@@ -106,10 +107,10 @@ public class TestReportLedgerImportService {
result.setSuccess(result.getMissingSheets().isEmpty() && result.getMissingAttachmentCount() != null result.setSuccess(result.getMissingSheets().isEmpty() && result.getMissingAttachmentCount() != null
&& result.getMissingAttachmentCount() == 0 && !hasReferenceErrors(result.getPoints())); && result.getMissingAttachmentCount() == 0 && !hasReferenceErrors(result.getPoints()));
if (!result.getMissingSheets().isEmpty()) { if (!result.getMissingSheets().isEmpty()) {
result.getFailReasons().add("鏍¢獙鏂囦欢闃舵锛歋heet涓嶄笉榻? " + String.join("銆?", result.getMissingSheets())); result.getFailReasons().add("校验文件阶段缺少必需Sheet" + String.join("", result.getMissingSheets()));
} }
if (result.getMissingAttachmentCount() != null && result.getMissingAttachmentCount() > 0) { if (result.getMissingAttachmentCount() != null && result.getMissingAttachmentCount() > 0) {
result.getFailReasons().add("鏍¢獙鏂囦欢闃舵锛氬瓨鍦ㄧ己澶遍檮浠讹紝鍙户缁笂浼犲悗鍐嶆鏍¢獙"); result.getFailReasons().add("校验文件阶段:存在缺失附件,可继续上传后再次校验");
} }
appendReferenceFailReasons(result); appendReferenceFailReasons(result);
persistValidateSessionResult(sessionId, result); persistValidateSessionResult(sessionId, result);
@@ -117,7 +118,7 @@ public class TestReportLedgerImportService {
} catch (BusinessException exception) { } catch (BusinessException exception) {
throw exception; throw exception;
} catch (Exception exception) { } catch (Exception exception) {
throw new BusinessException(CommonResponseEnum.FAIL, "鏍¢獙鏂囦欢闃舵锛氳鍙栧彴璐︽眹鎬籩xcel澶辫触"); throw new BusinessException(CommonResponseEnum.FAIL, "校验文件阶段读取台账汇总excel失败");
} }
} }
@@ -126,9 +127,9 @@ public class TestReportLedgerImportService {
String batchId = UUID.randomUUID().toString(); String batchId = UUID.randomUUID().toString();
TestReportStorageService.UploadedBatch uploadedBatch = testReportStorageService.saveTempBatchFiles(report.getId(), batchId, fileMap); TestReportStorageService.UploadedBatch uploadedBatch = testReportStorageService.saveTempBatchFiles(report.getId(), batchId, fileMap);
try { try {
MultipartFile summaryFile = fileMap.get(TestReportConst.LEDGER_SUMMARY_FILE_NAME); String summaryFileName = resolveSummaryFileName(fileMap.keySet());
if (summaryFile == null) { if (summaryFileName == null) {
throw new BusinessException(CommonResponseEnum.FAIL, "校验文件阶段:缺少台账信息汇总.xlsx"); throw new BusinessException(CommonResponseEnum.FAIL, "校验文件阶段:缺少台账信息汇总.xls或台账信息汇总.xlsx");
} }
TestReportLedgerExcelParser.ParsedLedger ledger = parseLedgerFromBatch(report.getId(), batchId, fileMap.keySet()); TestReportLedgerExcelParser.ParsedLedger ledger = parseLedgerFromBatch(report.getId(), batchId, fileMap.keySet());
Map<String, TestDevicePO> dbDeviceMap = loadExistingDevices(collectDeviceNos(ledger)); Map<String, TestDevicePO> dbDeviceMap = loadExistingDevices(collectDeviceNos(ledger));
@@ -170,10 +171,14 @@ public class TestReportLedgerImportService {
} }
private TestReportLedgerExcelParser.ParsedLedger parseLedgerFromBatch(String reportId, String batchId, Collection<String> fileNames) { private TestReportLedgerExcelParser.ParsedLedger parseLedgerFromBatch(String reportId, String batchId, Collection<String> fileNames) {
String summaryFileName = resolveSummaryFileName(fileNames);
if (StrUtil.isBlank(summaryFileName)) {
throw new BusinessException(CommonResponseEnum.FAIL, "校验文件阶段:缺少台账信息汇总.xls或台账信息汇总.xlsx");
}
try (AiReportMinioStorageService.StoredObject storedObject = try (AiReportMinioStorageService.StoredObject storedObject =
testReportStorageService.getTempBatchObject(reportId, batchId, TestReportConst.LEDGER_SUMMARY_FILE_NAME); testReportStorageService.getTempBatchObject(reportId, batchId, summaryFileName);
InputStream inputStream = storedObject.getInputStream()) { InputStream inputStream = storedObject.getInputStream()) {
return testReportLedgerExcelParser.parse(TestReportConst.LEDGER_SUMMARY_FILE_NAME, inputStream, return testReportLedgerExcelParser.parse(summaryFileName, inputStream,
buildAttachmentNameSet(fileNames)); buildAttachmentNameSet(fileNames));
} catch (Exception exception) { } catch (Exception exception) {
throw new BusinessException(CommonResponseEnum.FAIL, "校验文件阶段读取台账汇总excel失败"); throw new BusinessException(CommonResponseEnum.FAIL, "校验文件阶段读取台账汇总excel失败");
@@ -186,7 +191,7 @@ public class TestReportLedgerImportService {
return attachmentNames; return attachmentNames;
} }
for (String fileName : fileNames) { for (String fileName : fileNames) {
if (StrUtil.isBlank(fileName) || TestReportConst.LEDGER_SUMMARY_FILE_NAME.equals(fileName)) { if (StrUtil.isBlank(fileName) || TestReportConst.isLedgerSummaryFileName(fileName)) {
continue; continue;
} }
attachmentNames.add(fileName); attachmentNames.add(fileName);
@@ -194,6 +199,24 @@ public class TestReportLedgerImportService {
return attachmentNames; return attachmentNames;
} }
private String resolveSummaryFileName(Collection<String> fileNames) {
if (fileNames == null || fileNames.isEmpty()) {
return null;
}
String matchedFileName = null;
for (String fileName : fileNames) {
if (!TestReportConst.isLedgerSummaryFileName(fileName)) {
continue;
}
if (matchedFileName != null && !matchedFileName.equals(fileName)) {
throw new BusinessException(CommonResponseEnum.FAIL,
"校验文件阶段:台账汇总文件仅允许上传一个,文件名必须为台账信息汇总.xls或台账信息汇总.xlsx");
}
matchedFileName = fileName;
}
return matchedFileName;
}
private void fillPointValidationResult(TestReportLedgerValidateResultVO result, private void fillPointValidationResult(TestReportLedgerValidateResultVO result,
TestReportLedgerExcelParser.ParsedLedger ledger, TestReportLedgerExcelParser.ParsedLedger ledger,
Set<String> sessionFileNameSet, Set<String> sessionFileNameSet,
@@ -211,18 +234,20 @@ public class TestReportLedgerImportService {
TestReportLedgerValidateAttachmentVO excelAttachment = buildAttachmentRow( TestReportLedgerValidateAttachmentVO excelAttachment = buildAttachmentRow(
pointRow.getExcelAttachmentName(), "excel", sessionFileNameSet.contains(pointRow.getExcelAttachmentName())); pointRow.getExcelAttachmentName(), "excel", sessionFileNameSet.contains(pointRow.getExcelAttachmentName()));
TestReportLedgerValidateAttachmentVO wordAttachment = buildAttachmentRow(
pointRow.getWordAttachmentName(), "word", sessionFileNameSet.contains(pointRow.getWordAttachmentName()));
pointVO.getAttachments().add(excelAttachment); pointVO.getAttachments().add(excelAttachment);
pointVO.getAttachments().add(wordAttachment);
int pointMissingCount = 0; int pointMissingCount = 0;
if (Boolean.TRUE.equals(excelAttachment.getMissing())) { if (Boolean.TRUE.equals(excelAttachment.getMissing())) {
pointMissingCount++; pointMissingCount++;
} }
if (Boolean.TRUE.equals(wordAttachment.getMissing())) { if (StrUtil.isNotBlank(pointRow.getWordAttachmentName())) {
pointMissingCount++; TestReportLedgerValidateAttachmentVO wordAttachment = buildAttachmentRow(
pointRow.getWordAttachmentName(), "word", sessionFileNameSet.contains(pointRow.getWordAttachmentName()));
pointVO.getAttachments().add(wordAttachment);
if (Boolean.TRUE.equals(wordAttachment.getMissing())) {
pointMissingCount++;
}
} }
pointVO.setMissingAttachmentCount(pointMissingCount); pointVO.setMissingAttachmentCount(pointMissingCount);
fillReferenceValidationResult(pointVO, pointRow, dbDeviceMap, dbClientMap, sheetDeviceMap, sheetClientMap); fillReferenceValidationResult(pointVO, pointRow, dbDeviceMap, dbClientMap, sheetDeviceMap, sheetClientMap);
@@ -273,10 +298,23 @@ public class TestReportLedgerImportService {
attachmentVO.setUploaded(uploaded); attachmentVO.setUploaded(uploaded);
attachmentVO.setMissing(!uploaded); attachmentVO.setMissing(!uploaded);
attachmentVO.setReuploadAllowed(Boolean.TRUE); attachmentVO.setReuploadAllowed(Boolean.TRUE);
attachmentVO.setMessage(uploaded ? "宸蹭笂浼?" : "缂哄皯闄勪欢锛屽彲缁х画涓婁紶"); attachmentVO.setMessage(uploaded ? "已上传" : "缺少附件,可继续上传");
return attachmentVO; return attachmentVO;
} }
private int countWordAttachments(TestReportLedgerExcelParser.ParsedLedger ledger) {
if (ledger == null || ledger.getPoints() == null || ledger.getPoints().isEmpty()) {
return 0;
}
int count = 0;
for (TestReportLedgerExcelParser.ParsedPointRow point : ledger.getPoints()) {
if (StrUtil.isNotBlank(point.getWordAttachmentName())) {
count++;
}
}
return count;
}
private List<String> resolveOrphanAttachmentNames(TestReportLedgerExcelParser.ParsedLedger ledger, Set<String> sessionFileNameSet) { private List<String> resolveOrphanAttachmentNames(TestReportLedgerExcelParser.ParsedLedger ledger, Set<String> sessionFileNameSet) {
Set<String> referencedNames = new HashSet<String>(); Set<String> referencedNames = new HashSet<String>();
for (TestReportLedgerExcelParser.ParsedPointRow pointRow : ledger.getPoints()) { for (TestReportLedgerExcelParser.ParsedPointRow pointRow : ledger.getPoints()) {
@@ -289,7 +327,7 @@ public class TestReportLedgerImportService {
} }
List<String> orphanAttachmentNames = new java.util.ArrayList<String>(); List<String> orphanAttachmentNames = new java.util.ArrayList<String>();
for (String fileName : sessionFileNameSet) { for (String fileName : sessionFileNameSet) {
if (TestReportConst.LEDGER_SUMMARY_FILE_NAME.equals(fileName)) { if (TestReportConst.isLedgerSummaryFileName(fileName)) {
continue; continue;
} }
if (!referencedNames.contains(fileName)) { if (!referencedNames.contains(fileName)) {
@@ -303,7 +341,7 @@ public class TestReportLedgerImportService {
try { try {
testReportStorageService.writeValidateSessionResult(sessionId, OBJECT_MAPPER.writeValueAsString(result)); testReportStorageService.writeValidateSessionResult(sessionId, OBJECT_MAPPER.writeValueAsString(result));
} catch (Exception exception) { } catch (Exception exception) {
throw new BusinessException(CommonResponseEnum.FAIL, "鏍¢獙鏂囦欢闃舵锛氫繚瀛樻牎楠岀粨鏋滃け璐?"); throw new BusinessException(CommonResponseEnum.FAIL, "校验文件阶段:保存校验结果失败");
} }
} }
@@ -593,7 +631,7 @@ public class TestReportLedgerImportService {
result.setTotalFileCount(uploadedFileCount); result.setTotalFileCount(uploadedFileCount);
result.setPointCount(ledger.getPoints().size()); result.setPointCount(ledger.getPoints().size());
result.setExcelAttachmentCount(ledger.getPoints().size()); result.setExcelAttachmentCount(ledger.getPoints().size());
result.setWordAttachmentCount(ledger.getPoints().size()); result.setWordAttachmentCount(countWordAttachments(ledger));
result.getStages().add(buildStage("文件选择", "文件选择完成")); result.getStages().add(buildStage("文件选择", "文件选择完成"));
result.getStages().add(buildStage("文件校验", "文件校验通过")); result.getStages().add(buildStage("文件校验", "文件校验通过"));
return result; return result;
@@ -613,7 +651,7 @@ public class TestReportLedgerImportService {
result.setTotalFileCount(uploadedFileCount); result.setTotalFileCount(uploadedFileCount);
result.setPointCount(ledger.getPoints().size()); result.setPointCount(ledger.getPoints().size());
result.setExcelAttachmentCount(ledger.getPoints().size()); result.setExcelAttachmentCount(ledger.getPoints().size());
result.setWordAttachmentCount(ledger.getPoints().size()); result.setWordAttachmentCount(countWordAttachments(ledger));
result.setDeviceAddedCount(summary.getDeviceAddedCount()); result.setDeviceAddedCount(summary.getDeviceAddedCount());
result.setDeviceReuseCount(summary.getDeviceReuseCount()); result.setDeviceReuseCount(summary.getDeviceReuseCount());
result.setClientAddedCount(summary.getClientAddedCount()); result.setClientAddedCount(summary.getClientAddedCount());

View File

@@ -38,11 +38,11 @@ public class TestReportLedgerTemplateService {
private void writeGuideSheet(XSSFSheet sheet) { private void writeGuideSheet(XSSFSheet sheet) {
Row row0 = sheet.createRow(0); Row row0 = sheet.createRow(0);
row0.createCell(0).setCellValue("1. 汇总文件名固定为台账信息汇总.xlsx"); row0.createCell(0).setCellValue("1. 汇总文件名固定为台账信息汇总,扩展名支持 .xls、.xlsx");
Row row1 = sheet.createRow(1); Row row1 = sheet.createRow(1);
row1.createCell(0).setCellValue("2. 监测点信息sheet必填检测设备/委托单位sheet按需填写"); row1.createCell(0).setCellValue("2. 监测点信息sheet必填检测设备/委托单位sheet按需填写");
Row row2 = sheet.createRow(2); Row row2 = sheet.createRow(2);
row2.createCell(0).setCellValue("3. 每个监测点必须同时填写Excel附件名称Word附件名称"); row2.createCell(0).setCellValue("3. 每个监测点必须填写Excel附件名称Word附件名称可按需填写");
Row row3 = sheet.createRow(3); Row row3 = sheet.createRow(3);
row3.createCell(0).setCellValue("4. 检测设备编号、委托单位名称优先匹配数据库未命中时再匹配本次sheet"); row3.createCell(0).setCellValue("4. 检测设备编号、委托单位名称优先匹配数据库未命中时再匹配本次sheet");
sheet.setColumnWidth(0, 120 * 256); sheet.setColumnWidth(0, 120 * 256);

View File

@@ -14,6 +14,9 @@ import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream; import java.io.InputStream;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
@@ -24,28 +27,34 @@ import java.util.Set;
@RequiredArgsConstructor @RequiredArgsConstructor
public class TestReportStorageService { public class TestReportStorageService {
private static final Set<String> POINT_WORD_ATTACHMENT_EXTENSIONS = Collections.unmodifiableSet(
new LinkedHashSet<String>(Arrays.asList("doc", "docx")));
private static final Set<String> IMPORT_ALLOWED_EXTENSIONS = Collections.unmodifiableSet(
new LinkedHashSet<String>(Arrays.asList("doc", "docx", "xls", "xlsx", "pdf")));
private final AiReportMinioStorageService minioStorageService; private final AiReportMinioStorageService minioStorageService;
public String saveSourceExcel(String reportId, MultipartFile file) { public String saveSourceExcel(String reportId, MultipartFile file) {
validateMultipartFile(file, AiReportFileExtensionConst.EXCEL_EXTENSIONS, "原始Excel文件不能为空", "原始Excel仅允许xlsx格式"); validateMultipartFile(file, AiReportFileExtensionConst.EXCEL_EXTENSIONS, "原始Excel文件不能为空", "原始Excel仅允许xls/xlsx格式");
return minioStorageService.saveMultipartFile(buildBusinessDir(reportId, TestReportConst.STORAGE_SOURCE_EXCEL_DIR), return minioStorageService.saveMultipartFile(buildBusinessDir(reportId, TestReportConst.STORAGE_SOURCE_EXCEL_DIR),
null, file, false).getObjectName(); null, file, false).getObjectName();
} }
public String saveLedgerSummaryExcel(String reportId, MultipartFile file) { public String saveLedgerSummaryExcel(String reportId, MultipartFile file) {
validateMultipartFile(file, AiReportFileExtensionConst.EXCEL_EXTENSIONS, "台账汇总文件不能为空", "台账汇总仅允许xlsx格式"); validateMultipartFile(file, AiReportFileExtensionConst.EXCEL_EXTENSIONS, "台账汇总文件不能为空", "台账汇总仅允许xls/xlsx格式");
return minioStorageService.saveMultipartFile(buildBusinessDir(reportId, TestReportConst.STORAGE_LEDGER_SUMMARY_DIR), return minioStorageService.saveMultipartFile(buildBusinessDir(reportId, TestReportConst.STORAGE_LEDGER_SUMMARY_DIR),
null, file, false).getObjectName(); null, file, false).getObjectName();
} }
public String savePointExcelAttachment(String reportId, MultipartFile file) { public String savePointExcelAttachment(String reportId, MultipartFile file) {
validateMultipartFile(file, AiReportFileExtensionConst.EXCEL_EXTENSIONS, "监测点Excel附件不能为空", "监测点Excel附件仅允许xlsx格式"); validateMultipartFile(file, AiReportFileExtensionConst.EXCEL_EXTENSIONS, "监测点Excel附件不能为空", "监测点Excel附件仅允许xls/xlsx格式");
return minioStorageService.saveMultipartFile(buildBusinessDir(reportId, TestReportConst.STORAGE_POINT_EXCEL_DIR), return minioStorageService.saveMultipartFile(buildBusinessDir(reportId, TestReportConst.STORAGE_POINT_EXCEL_DIR),
null, file, false).getObjectName(); null, file, false).getObjectName();
} }
public String savePointWordAttachment(String reportId, MultipartFile file) { public String savePointWordAttachment(String reportId, MultipartFile file) {
validateMultipartFile(file, AiReportFileExtensionConst.WORD_EXTENSIONS, "监测点Word附件不能为空", "监测点Word附件仅允许docx格式"); validateMultipartFile(file, POINT_WORD_ATTACHMENT_EXTENSIONS, "监测点Word附件不能为空", "监测点Word附件仅允许doc/docx格式");
return minioStorageService.saveMultipartFile(buildBusinessDir(reportId, TestReportConst.STORAGE_POINT_WORD_DIR), return minioStorageService.saveMultipartFile(buildBusinessDir(reportId, TestReportConst.STORAGE_POINT_WORD_DIR),
null, file, false).getObjectName(); null, file, false).getObjectName();
} }
@@ -91,19 +100,19 @@ public class TestReportStorageService {
public String saveLedgerSummaryFromTemp(String reportId, String batchId, String fileName) { public String saveLedgerSummaryFromTemp(String reportId, String batchId, String fileName) {
return copyTempBatchFile(reportId, batchId, fileName, return copyTempBatchFile(reportId, batchId, fileName,
buildBusinessDir(reportId, TestReportConst.STORAGE_LEDGER_SUMMARY_DIR), buildBusinessDir(reportId, TestReportConst.STORAGE_LEDGER_SUMMARY_DIR),
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "保存台账汇总excel失败"); resolveExcelContentType(fileName), "保存台账汇总excel失败");
} }
public String savePointExcelFromTemp(String reportId, String batchId, String fileName) { public String savePointExcelFromTemp(String reportId, String batchId, String fileName) {
return copyTempBatchFile(reportId, batchId, fileName, return copyTempBatchFile(reportId, batchId, fileName,
buildBusinessDir(reportId, TestReportConst.STORAGE_POINT_EXCEL_DIR), buildBusinessDir(reportId, TestReportConst.STORAGE_POINT_EXCEL_DIR),
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "保存监测点excel附件失败"); resolveExcelContentType(fileName), "保存监测点excel附件失败");
} }
public String savePointWordFromTemp(String reportId, String batchId, String fileName) { public String savePointWordFromTemp(String reportId, String batchId, String fileName) {
return copyTempBatchFile(reportId, batchId, fileName, return copyTempBatchFile(reportId, batchId, fileName,
buildBusinessDir(reportId, TestReportConst.STORAGE_POINT_WORD_DIR), buildBusinessDir(reportId, TestReportConst.STORAGE_POINT_WORD_DIR),
"application/vnd.openxmlformats-officedocument.wordprocessingml.document", "保存监测点word附件失败"); resolveWordContentType(fileName), "保存监测点Word附件失败");
} }
public String saveGeneratedPlaceholder(String reportId, String fileName, byte[] content) { public String saveGeneratedPlaceholder(String reportId, String fileName, byte[] content) {
@@ -212,8 +221,24 @@ public class TestReportStorageService {
} }
private void validateAllowedUploadFile(String fileName) { private void validateAllowedUploadFile(String fileName) {
validateFileName(fileName, AiReportFileExtensionConst.ALLOWED_EXTENSIONS, "文件不能为空", validateFileName(fileName, IMPORT_ALLOWED_EXTENSIONS, "文件不能为空",
"仅允许上传docx、xlsx、pdf文件"); "仅允许上传doc、docx、xls、xlsx、pdf文件");
}
private String resolveExcelContentType(String fileName) {
String extension = resolveExtension(fileName);
if ("xls".equals(extension)) {
return "application/vnd.ms-excel";
}
return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
}
private String resolveWordContentType(String fileName) {
String extension = resolveExtension(fileName);
if ("doc".equals(extension)) {
return "application/msword";
}
return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
} }
private void validateFileName(String fileName, Set<String> allowedExtensions, private void validateFileName(String fileName, Set<String> allowedExtensions,

View File

@@ -35,7 +35,9 @@ public final class TestReportConst {
public static final String STORAGE_VALIDATE_SESSION_DIR = "validate-session"; public static final String STORAGE_VALIDATE_SESSION_DIR = "validate-session";
public static final String STORAGE_VALIDATE_RESULT_FILE_NAME = "validate-result.json"; public static final String STORAGE_VALIDATE_RESULT_FILE_NAME = "validate-result.json";
public static final String LEDGER_SUMMARY_FILE_NAME = "台账信息汇总.xlsx"; public static final String LEDGER_SUMMARY_FILE_BASE_NAME = "台账信息汇总";
public static final String LEDGER_SUMMARY_FILE_NAME = LEDGER_SUMMARY_FILE_BASE_NAME + ".xlsx";
public static final String LEDGER_SUMMARY_FILE_NAME_XLS = LEDGER_SUMMARY_FILE_BASE_NAME + ".xls";
public static final String LEDGER_GUIDE_SHEET_NAME = "填写说明"; public static final String LEDGER_GUIDE_SHEET_NAME = "填写说明";
public static final String LEDGER_POINT_SHEET_NAME = "监测点信息"; public static final String LEDGER_POINT_SHEET_NAME = "监测点信息";
public static final String LEDGER_DEVICE_SHEET_NAME = "检测设备"; public static final String LEDGER_DEVICE_SHEET_NAME = "检测设备";
@@ -43,4 +45,13 @@ public final class TestReportConst {
private TestReportConst() { private TestReportConst() {
} }
public static boolean isLedgerSummaryFileName(String fileName) {
if (fileName == null) {
return false;
}
String normalizedFileName = fileName.trim();
return LEDGER_SUMMARY_FILE_NAME.equalsIgnoreCase(normalizedFileName)
|| LEDGER_SUMMARY_FILE_NAME_XLS.equalsIgnoreCase(normalizedFileName);
}
} }

View File

@@ -525,8 +525,8 @@ public class TestReportServiceImpl extends ServiceImpl<TestReportMapper, TestRep
throw new BusinessException(CommonResponseEnum.FAIL, MSG_IMPORT_FILES_REQUIRED); throw new BusinessException(CommonResponseEnum.FAIL, MSG_IMPORT_FILES_REQUIRED);
} }
String normalizedFileName = originalFileName.toLowerCase(); String normalizedFileName = originalFileName.toLowerCase();
if (!normalizedFileName.endsWith(".xlsx")) { if (!normalizedFileName.endsWith(".xls") && !normalizedFileName.endsWith(".xlsx")) {
throw new BusinessException(CommonResponseEnum.FAIL, "原始Excel仅允许xlsx格式"); throw new BusinessException(CommonResponseEnum.FAIL, "原始Excel仅允许xls/xlsx格式");
} }
if (!fileNames.add(originalFileName)) { if (!fileNames.add(originalFileName)) {
throw new BusinessException(CommonResponseEnum.FAIL, MSG_IMPORT_FILE_NAME_DUPLICATE); throw new BusinessException(CommonResponseEnum.FAIL, MSG_IMPORT_FILE_NAME_DUPLICATE);