diff --git a/backend/src/main/java/com/yfd/platform/data/controller/FishDraftDataController.java b/backend/src/main/java/com/yfd/platform/data/controller/FishDraftDataController.java index 4f35d52..2b19f33 100644 --- a/backend/src/main/java/com/yfd/platform/data/controller/FishDraftDataController.java +++ b/backend/src/main/java/com/yfd/platform/data/controller/FishDraftDataController.java @@ -14,18 +14,13 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.fasterxml.jackson.databind.ObjectMapper; import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.config.ResponseResult; -import com.yfd.platform.data.domain.FishDraftData; -import com.yfd.platform.data.domain.FishImportRequest; -import com.yfd.platform.data.domain.FishImportResult; -import com.yfd.platform.data.domain.FishImportRowRequest; -import com.yfd.platform.data.domain.ImportTask; -import com.yfd.platform.data.domain.BatchApproveRequest; -import com.yfd.platform.data.domain.BatchRejectRequest; +import com.yfd.platform.data.domain.*; import com.yfd.platform.data.domain.vo.FishDraftDataVO; import com.yfd.platform.data.service.AttachmentUploadService; import com.yfd.platform.data.service.IFishDraftDataService; import com.yfd.platform.data.service.IFishImportService; import com.yfd.platform.data.service.IImportTaskService; +import com.yfd.platform.data.utils.ZipFileUtil; import com.yfd.platform.utils.KendoUtil; import com.yfd.platform.utils.SecurityUtils; import io.swagger.v3.oas.annotations.Operation; @@ -128,6 +123,45 @@ public class FishDraftDataController { return result ? ResponseResult.success("保存成功") : ResponseResult.error("保存失败"); } + @PostMapping("/importBatchSaveDraft") + @Operation(summary = "批量保存草稿(导入)") + public ResponseResult importBatchSaveDraft(@RequestBody BatchSaveDraftRequest batchSaveDraftRequest) { + String taskId = batchSaveDraftRequest.getTaskId(); + ImportTask importTask = importTaskService.getById(taskId); + if (importTask == null) { + return ResponseResult.error("导入任务不存在"); + } + String resultJson = importTask.getResultJson(); + List fishDraftDataList = batchSaveDraftRequest.getFishDraftDataList(); + if (resultJson != null && !resultJson.isEmpty()) { + try { + FishImportResult importResult = objectMapper.readValue(resultJson, FishImportResult.class); + ZipFileUtil.ZipContent content = new ZipFileUtil.ZipContent(); + content.images = importResult.getImageFiles(); + content.videos = importResult.getVideoFiles(); + fishImportService.processAttachments(importResult, content); + fishDraftDataList.forEach(fishDraftData -> { + for (FishImportResult.FishImportRow row : importResult.getRows()) { + if (fishDraftData.getId().equals(row.getData().getId())) { + fishDraftData.setPicpth(row.getData().getPicpth()); + fishDraftData.setVdpth(row.getData().getVdpth()); + break; + } + } + fishDraftData.setStatus("DRAFT"); + fishDraftData.setDeletedFlag(0); + fishDraftData.setLockFlag(0); + }); + } catch (Exception e) { + e.printStackTrace(); + // ignore parse error + } + } + + boolean result = fishDraftDataService.saveBatch(fishDraftDataList); + return result ? ResponseResult.success("保存成功") : ResponseResult.error("保存失败"); + } + @PostMapping("/updateDraft") @Operation(summary = "更新草稿") public ResponseResult updateDraft(@RequestBody FishDraftData fishDraftData) { @@ -400,6 +434,101 @@ public class FishDraftDataController { writeErrorResponse(response, "预览失败: " + e.getMessage()); } } + @GetMapping("/deleteFile") + @Operation(summary = "删除导入文件") + public ResponseResult deleteFile(@RequestParam String taskId, + @RequestParam String id, + @RequestParam String type, + @RequestParam String filename) { + if (taskId == null || taskId.isEmpty()) { + return ResponseResult.error("任务ID不能为空"); + } + if (id == null || id.isEmpty()) { + return ResponseResult.error("数据ID不能为空"); + } + if (filename == null || filename.isEmpty()) { + return ResponseResult.error("文件名不能为空"); + } + + ImportTask importTask = importTaskService.getById(taskId); + if (importTask == null) { + return ResponseResult.error("任务不存在"); + } + + String resultJson = importTask.getResultJson(); + if (resultJson == null || resultJson.isEmpty()) { + return ResponseResult.error("任务结果为空"); + } + + try { + FishImportResult importResult = objectMapper.readValue(resultJson, FishImportResult.class); + boolean found = false; + + for (FishImportResult.FishImportRow row : importResult.getRows()) { + FishDraftData data = row.getData(); + if (data == null || !id.equals(data.getId())) { + continue; + } + found = true; + + if ("1".equals(type)) { + String picpthName = data.getPicpthName(); + if (picpthName != null && !picpthName.isEmpty()) { + String[] names = picpthName.split(";"); + StringBuilder newNames = new StringBuilder(); + for (String name : names) { + if (!filename.equals(name.trim())) { + if (newNames.length() > 0) { + newNames.append(";"); + } + newNames.append(name.trim()); + } + } + data.setPicpthName(newNames.toString()); + } + + List> picpthList = row.getPicpthList(); + if (picpthList != null) { + picpthList.removeIf(map -> filename.equals(map.get("name"))); + } + + } else if ("2".equals(type)) { + String vdpthName = data.getVdpthName(); + if (vdpthName != null && !vdpthName.isEmpty()) { + String[] names = vdpthName.split(";"); + StringBuilder newNames = new StringBuilder(); + for (String name : names) { + if (!filename.equals(name.trim())) { + if (newNames.length() > 0) { + newNames.append(";"); + } + newNames.append(name.trim()); + } + } + data.setVdpthName(newNames.toString()); + } + + List> vdpthList = row.getVdpthList(); + if (vdpthList != null) { + vdpthList.removeIf(map -> filename.equals(map.get("name"))); + } + } + } + + if (!found) { + return ResponseResult.error("未找到对应的数据行"); + } + + String updatedJson = objectMapper.writeValueAsString(importResult); + importTaskService.saveResultJson(taskId, updatedJson); + + return ResponseResult.success("删除成功"); + + } catch (Exception e) { + log.error("删除文件失败: " + e.getMessage(), e); + return ResponseResult.error("删除失败: " + e.getMessage()); + } + } @GetMapping("/previewFileBase64") @Operation(summary = "预览临时文件内容(Base64方式)") diff --git a/backend/src/main/java/com/yfd/platform/data/domain/BatchSaveDraftRequest.java b/backend/src/main/java/com/yfd/platform/data/domain/BatchSaveDraftRequest.java new file mode 100644 index 0000000..93bb8b6 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/data/domain/BatchSaveDraftRequest.java @@ -0,0 +1,23 @@ +package com.yfd.platform.data.domain; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class BatchSaveDraftRequest { + + /** + * 任务id + */ + String taskId; + + /** + * 批量保存数据 + */ + List fishDraftDataList; +} diff --git a/backend/src/main/java/com/yfd/platform/data/domain/FishImportResult.java b/backend/src/main/java/com/yfd/platform/data/domain/FishImportResult.java index 19ef2c7..84e3a94 100644 --- a/backend/src/main/java/com/yfd/platform/data/domain/FishImportResult.java +++ b/backend/src/main/java/com/yfd/platform/data/domain/FishImportResult.java @@ -19,6 +19,8 @@ public class FishImportResult { private List unrecognizedFields; private Map imageFiles; private Map videoFiles; +// public Map images; +// public Map videos; private String tempDir; private String excelFileName; private String excelFilePath; @@ -35,6 +37,8 @@ public class FishImportResult { this.unrecognizedFields = new ArrayList<>(); this.imageFiles = new LinkedHashMap<>(); this.videoFiles = new LinkedHashMap<>(); +// this.images = new LinkedHashMap<>(); +// this.videos = new LinkedHashMap<>(); } public void addSuccessRow(FishImportRow row) { diff --git a/backend/src/main/java/com/yfd/platform/data/service/IFishImportService.java b/backend/src/main/java/com/yfd/platform/data/service/IFishImportService.java index cff4b05..b4505f1 100644 --- a/backend/src/main/java/com/yfd/platform/data/service/IFishImportService.java +++ b/backend/src/main/java/com/yfd/platform/data/service/IFishImportService.java @@ -2,6 +2,7 @@ package com.yfd.platform.data.service; import com.yfd.platform.data.domain.FishImportRequest; import com.yfd.platform.data.domain.FishImportResult; +import com.yfd.platform.data.utils.ZipFileUtil; import org.springframework.web.multipart.MultipartFile; import java.io.InputStream; @@ -41,4 +42,6 @@ public interface IFishImportService { String resolveIsfs(String value, FishImportResult.FishImportRow importRow); String parseSourceType(String value); + + void processAttachments(FishImportResult result, ZipFileUtil.ZipContent zipContent); } \ No newline at end of file diff --git a/backend/src/main/java/com/yfd/platform/data/service/impl/FishImportServiceImpl.java b/backend/src/main/java/com/yfd/platform/data/service/impl/FishImportServiceImpl.java index 44d58e0..d63a1e2 100644 --- a/backend/src/main/java/com/yfd/platform/data/service/impl/FishImportServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/data/service/impl/FishImportServiceImpl.java @@ -1,5 +1,6 @@ package com.yfd.platform.data.service.impl; +import cn.hutool.core.util.StrUtil; import com.yfd.platform.data.domain.FishDraftData; import com.yfd.platform.data.domain.FishImportRequest; import com.yfd.platform.data.domain.FishImportResult; @@ -8,8 +9,6 @@ import com.yfd.platform.data.service.IFishImportService; import com.yfd.platform.data.utils.ZipFileUtil; import com.yfd.platform.env.domain.*; import com.yfd.platform.env.mapper.*; -import com.yfd.platform.system.domain.SysDictionary; -import com.yfd.platform.system.domain.SysDictionaryItems; import com.yfd.platform.system.service.ISysDictionaryItemsService; import com.yfd.platform.system.service.ISysDictionaryService; import jakarta.annotation.Resource; @@ -27,7 +26,6 @@ import java.math.BigDecimal; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; -import java.util.stream.Collectors; @Service @Slf4j @@ -163,7 +161,7 @@ public class FishImportServiceImpl implements IFishImportService { continue; } - FishImportResult.FishImportRow importRow = parseRow(row, columnIndexMap, i); + FishImportResult.FishImportRow importRow = parseRow(result, row, columnIndexMap, i); result.setTotalCount(result.getTotalCount() + 1); if (importRow.getData() != null && importRow.getWarnings().isEmpty()) { result.addSuccessRow(importRow); @@ -174,18 +172,16 @@ public class FishImportServiceImpl implements IFishImportService { } } result.setSummary(String.format("共解析%d条数据,失败%d条,未识别字段:%s", - result.getSuccessCount(), result.getFailedCount(), + result.getSuccessCount(), result.getFailedCount(), unrecognizedHeaders.isEmpty() ? "无" : String.join(", ", unrecognizedHeaders))); return result; } - private FishImportResult.FishImportRow parseRow(Row row, Map columnIndexMap, int rowIndex) { + private FishImportResult.FishImportRow parseRow(FishImportResult result, Row row, Map columnIndexMap, int rowIndex) { FishImportResult.FishImportRow importRow = new FishImportResult.FishImportRow(rowIndex); FishDraftData data = new FishDraftData(); data.setId(UUID.randomUUID().toString()); - List missingRequiredFields = new ArrayList<>(); - for (Map.Entry entry : columnIndexMap.entrySet()) { Integer columnIndex = entry.getKey(); String fieldName = entry.getValue(); @@ -327,18 +323,53 @@ public class FishImportServiceImpl implements IFishImportService { data.setMouth(parseInteger(cellValue)); break; case "vdpth": - data.setVdpth(cellValue.trim()); - data.setVdpthName(cellValue.trim()); + String vdpth = cellValue.trim(); + List vdpthList = new ArrayList<>(); + Map videoFiles = result.getVideoFiles(); + + for (String fileName : vdpth.split(";")) { + for (String entryName : videoFiles.keySet()) { + if (entryName.equals(fileName) || entryName.endsWith("/" + fileName) || entryName.endsWith("\\" + fileName)) { + Map objectObjectHashMap = new HashMap<>(); + objectObjectHashMap.put("name", fileName); + objectObjectHashMap.put("value", fileName); + importRow.getVdpthList().add(objectObjectHashMap); + vdpthList.add(fileName); + } + } + + } + String vdpthJoin = StrUtil.join(";", vdpthList); + data.setVdpth(vdpthJoin); + data.setVdpthName(vdpthJoin); + break; case "picpth": - data.setPicpth(cellValue.trim()); - data.setPicpthName(cellValue.trim()); + String picpth = cellValue.trim(); + List picpthList = new ArrayList<>(); + Map imageFiles = result.getImageFiles(); + + for (String fileName : picpth.split(";")) { + for (String entryName : imageFiles.keySet()) { + if (entryName.equals(fileName) || entryName.endsWith("/" + fileName) || entryName.endsWith("\\" + fileName)) { + Map objectObjectHashMap = new HashMap<>(); + objectObjectHashMap.put("name", fileName); + objectObjectHashMap.put("value", fileName); + importRow.getPicpthList().add(objectObjectHashMap); + picpthList.add(fileName); + } + } + + } + String picpthJoin = StrUtil.join(";", picpthList); + data.setPicpth(picpthJoin); + data.setPicpthName(picpthJoin); break; case "isfs": if (StringUtils.hasText(cellValue)) { String isfs = resolveIsfs(cellValue.trim(), importRow); data.setIsfs("1".equals(isfs) ? 1 : 0); - }else{ + } else { importRow.getWarnings().add("isfs"); } break; @@ -451,7 +482,6 @@ public class FishImportServiceImpl implements IFishImportService { } - public String resolveStationCode(String stationName) { if (stationName == null) { return null; @@ -694,7 +724,7 @@ public class FishImportServiceImpl implements IFishImportService { String lowerName = value.toLowerCase().trim(); if (lowerName.equals("是")) { return "1"; - } else if (lowerName.equals("否") ) { + } else if (lowerName.equals("否")) { return "0"; } importRow.getWarnings().add("isfs"); @@ -829,6 +859,7 @@ public class FishImportServiceImpl implements IFishImportService { /** * 解析 BigDecimal 类型数据 + * * @param value 字符串数值 * @return BigDecimal 对象,解析失败或为空时返回 null */ @@ -872,22 +903,21 @@ public class FishImportServiceImpl implements IFishImportService { ZipFileUtil.cleanupTempDir(zipContent.tempDir); return result; } - + result.setTempDir(zipContent.tempDir); + result.setImageFiles(zipContent.images); + result.setVideoFiles(zipContent.videos); try (Workbook workbook = new XSSFWorkbook(new FileInputStream(zipContent.excelFilePath))) { Sheet sheet = workbook.getSheetAt(0); result = parseSheet(sheet, result); } - - result.setImageFiles(zipContent.images); - result.setVideoFiles(zipContent.videos); - result.setTempDir(zipContent.tempDir); result.setExcelFileName(zipContent.excelFileName); result.setExcelFilePath(zipContent.excelFilePath); - +// result.setVideos(zipContent.videos); +// result.setImages(zipContent.images); log.info("ZIP文件解析完成"); - processAttachments(result, zipContent); - - log.info("ZIP文件处理完成"); +// processAttachments(result, zipContent); +// +// log.info("ZIP文件处理完成"); result.setSummary(result.getSummary() + String.format("\nZIP内容: 发现%d张图片, %d个视频", zipContent.images.size(), zipContent.videos.size())); @@ -901,7 +931,8 @@ public class FishImportServiceImpl implements IFishImportService { } } - private void processAttachments(FishImportResult result, ZipFileUtil.ZipContent zipContent) { + @Override + public void processAttachments(FishImportResult result, ZipFileUtil.ZipContent zipContent) { for (FishImportResult.FishImportRow importRow : result.getRows()) { FishDraftData data = importRow.getData(); if (data == null) { @@ -912,12 +943,12 @@ public class FishImportServiceImpl implements IFishImportService { String picpth = data.getPicpth(); if (StringUtils.hasText(vdpth)) { - String uploadedVdpth = processVideoAttachments(importRow,vdpth, zipContent.videos); + String uploadedVdpth = processVideoAttachments(importRow, vdpth, zipContent.videos); data.setVdpth(uploadedVdpth); } if (StringUtils.hasText(picpth)) { - String uploadedPicpth = processImageAttachments(importRow,picpth, zipContent.images); + String uploadedPicpth = processImageAttachments(importRow, picpth, zipContent.images); data.setPicpth(uploadedPicpth); } } @@ -964,7 +995,7 @@ public class FishImportServiceImpl implements IFishImportService { return String.join(",", attachmentIds); } - private String processImageAttachments(FishImportResult.FishImportRow importRow,String imageNames, Map imageMap) { + private String processImageAttachments(FishImportResult.FishImportRow importRow, String imageNames, Map imageMap) { if (imageNames == null || imageNames.isEmpty() || imageMap == null || imageMap.isEmpty()) { return imageNames; }