diff --git a/backend/src/main/java/com/yfd/platform/config/JwtAuthenticationTokenFilter.java b/backend/src/main/java/com/yfd/platform/config/JwtAuthenticationTokenFilter.java
index bcb79c0..2f3c035 100644
--- a/backend/src/main/java/com/yfd/platform/config/JwtAuthenticationTokenFilter.java
+++ b/backend/src/main/java/com/yfd/platform/config/JwtAuthenticationTokenFilter.java
@@ -11,6 +11,7 @@ import com.yfd.platform.constant.Constant;
import com.yfd.platform.system.domain.LoginUser;
import com.yfd.platform.system.domain.Message;
import com.yfd.platform.system.service.IMessageService;
+import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
@@ -25,6 +26,7 @@ import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
+@Slf4j
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
@Autowired
@@ -36,6 +38,9 @@ public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
FilterChain filterChain) throws ServletException, IOException {
//获取token
String uri = httpServletRequest.getRequestURI();
+ if(uri.contains("/data/fishDraft/importZip")){
+ log.info("请求地址:{}", uri);
+ }
String token = httpServletRequest.getHeader("token");
if (StrUtil.isEmpty(token) || "/user/login".equals(uri)) {
filterChain.doFilter(httpServletRequest, httpServletResponse);
diff --git a/backend/src/main/java/com/yfd/platform/config/ProdApiPrefixFilter.java b/backend/src/main/java/com/yfd/platform/config/ProdApiPrefixFilter.java
deleted file mode 100644
index 4c1680a..0000000
--- a/backend/src/main/java/com/yfd/platform/config/ProdApiPrefixFilter.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.yfd.platform.config;
-
-import jakarta.servlet.Filter;
-import jakarta.servlet.FilterChain;
-import jakarta.servlet.RequestDispatcher;
-import jakarta.servlet.ServletException;
-import jakarta.servlet.ServletRequest;
-import jakarta.servlet.ServletResponse;
-import jakarta.servlet.annotation.WebFilter;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import java.io.IOException;
-
-/**
- * 将以 /prod-api/ 开头的请求转发到去掉前缀的真实后端接口路径。
- * 例如:/prod-api/user/code -> /user/code
- * 这样可以兼容前端生产环境仍使用 /prod-api 作为网关前缀的情况。
- */
-@WebFilter(urlPatterns = "/prod-api/*", filterName = "prodApiPrefixFilter")
-public class ProdApiPrefixFilter implements Filter {
-
- private static final String PREFIX = "/prod-api";
-
- @Override
- public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
- if (!(req instanceof HttpServletRequest) || !(res instanceof HttpServletResponse)) {
- chain.doFilter(req, res);
- return;
- }
-
- HttpServletRequest request = (HttpServletRequest) req;
- String uri = request.getRequestURI();
-
- // 仅拦截 /prod-api/* 的接口请求并进行内部 forward
- if (uri.startsWith(PREFIX + "/")) {
- String forwardUri = uri.substring(PREFIX.length());
- RequestDispatcher dispatcher = request.getRequestDispatcher(forwardUri);
- dispatcher.forward(req, res);
- return;
- }
-
- chain.doFilter(req, res);
- }
-}
\ No newline at end of file
diff --git a/backend/src/main/java/com/yfd/platform/config/SwaggerConfig.java b/backend/src/main/java/com/yfd/platform/config/SwaggerConfig.java
index 212db9b..42bd358 100644
--- a/backend/src/main/java/com/yfd/platform/config/SwaggerConfig.java
+++ b/backend/src/main/java/com/yfd/platform/config/SwaggerConfig.java
@@ -1,4 +1,5 @@
package com.yfd.platform.config;
+
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springdoc.core.models.GroupedOpenApi;
@@ -6,9 +7,6 @@ import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.Contact;
-/**
- * Springdoc OpenAPI 配置
- */
@Configuration
public class SwaggerConfig {
@@ -23,37 +21,51 @@ public class SwaggerConfig {
);
}
- @Bean
- public GroupedOpenApi groupWebsiteApi() {
- return GroupedOpenApi.builder()
- .group("1. 平台模块")
- .packagesToScan("com.yfd.platform.modules.platformdb.controller")
- .build();
- }
+// @Bean
+// public GroupedOpenApi groupPlatformApi() {
+// return GroupedOpenApi.builder()
+// .group("1. 平台模块")
+// .packagesToScan("com.yfd.platform.modules.platformdb.controller")
+// .build();
+// }
- @Bean
- public GroupedOpenApi groupQuartzApi() {
- return GroupedOpenApi.builder()
- .group("2. 定时任务")
- .packagesToScan("com.yfd.platform.modules.quartz.controller")
- .build();
- }
+// @Bean
+// public GroupedOpenApi groupQuartzApi() {
+// return GroupedOpenApi.builder()
+// .group("2. 定时任务")
+// .packagesToScan("com.yfd.platform.modules.quartz.controller")
+// .build();
+// }
@Bean
public GroupedOpenApi groupSystemApi() {
return GroupedOpenApi.builder()
- .group("3. 系统管理")
+ .group("1. 系统管理")
.packagesToScan("com.yfd.platform.system.controller")
.build();
}
+ @Bean
+ public GroupedOpenApi groupDataEnvApi() {
+ return GroupedOpenApi.builder()
+ .group("2. 过鱼数据模块")
+ .packagesToScan("com.yfd.platform.data.controller")
+ .build();
+ }
+
@Bean
public GroupedOpenApi groupEnvApi() {
return GroupedOpenApi.builder()
- .group("4. 环境/基地/流域管理")
+ .group("3. 全过程-生态环保数据服务")
.packagesToScan("com.yfd.platform.env.controller")
.build();
}
-
-}
+ @Bean
+ public GroupedOpenApi groupEngApi() {
+ return GroupedOpenApi.builder()
+ .group("4. 全过程-常规水电数据服务")
+ .packagesToScan("com.yfd.platform.eng.controller")
+ .build();
+ }
+}
\ No newline at end of file
diff --git a/backend/src/main/java/com/yfd/platform/data/controller/ApprovalMainController.java b/backend/src/main/java/com/yfd/platform/data/controller/ApprovalMainController.java
index 53d927d..c0db986 100644
--- a/backend/src/main/java/com/yfd/platform/data/controller/ApprovalMainController.java
+++ b/backend/src/main/java/com/yfd/platform/data/controller/ApprovalMainController.java
@@ -13,6 +13,7 @@ import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
+import java.util.List;
/**
*
@@ -116,4 +117,11 @@ public class ApprovalMainController {
boolean result = approvalMainService.removeById(id);
return result ? ResponseResult.success("删除成功") : ResponseResult.error("删除失败");
}
+
+ @PostMapping("/batchDelete")
+ @Operation(summary = "删除审批")
+ public ResponseResult delete(@RequestBody List ids) {
+ boolean result = approvalMainService.removeBatchByIds(ids);
+ return result ? ResponseResult.success("删除成功") : ResponseResult.error("删除失败");
+ }
}
\ No newline at end of file
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 1e1a0d5..5a84a7c 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
@@ -3,7 +3,9 @@ package com.yfd.platform.data.controller;
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
+import java.net.URLDecoder;
import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -11,8 +13,12 @@ import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -20,12 +26,15 @@ import com.yfd.platform.common.DataSourceRequest;
import com.yfd.platform.config.ResponseResult;
import com.yfd.platform.data.domain.*;
import com.yfd.platform.data.domain.vo.FishDraftDataVO;
+import com.yfd.platform.data.domain.vo.FishStatisticsVO;
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.IFishStatisticsService;
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.MultipartStreamParser;
import com.yfd.platform.utils.SecurityUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -33,12 +42,12 @@ import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
-import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.*;
@@ -69,6 +78,18 @@ public class FishDraftDataController {
@Resource
private AttachmentUploadService attachmentUploadService;
+ @Resource
+ private IFishStatisticsService fishStatisticsService;
+
+ @Autowired
+ private ThreadPoolTaskExecutor taskExecutor;
+
+ private final ExecutorService attachmentDeleteExecutor = Executors.newFixedThreadPool(4, r -> {
+ Thread t = new Thread(r, "attachment-delete");
+ t.setDaemon(true);
+ return t;
+ });
+
@PostMapping("/page")
@Operation(summary = "分页查询过鱼数据(关联电站和设施)")
public ResponseResult queryPageList(@RequestBody DataSourceRequest dataSourceRequest) {
@@ -83,6 +104,13 @@ public class FishDraftDataController {
return ResponseResult.successData(list);
}
+ @PostMapping("/statistics")
+ @Operation(summary = "过鱼到数统计(按用户月度汇总,支持流域/电站多选过滤)")
+ public ResponseResult statistics(@RequestBody DataSourceRequest dataSourceRequest) {
+ Page result = fishStatisticsService.queryPage(dataSourceRequest);
+ return ResponseResult.successData(result);
+ }
+
@GetMapping("/getById")
@Operation(summary = "根据ID查询")
public ResponseResult getById(@RequestParam String id) {
@@ -133,23 +161,10 @@ public class FishDraftDataController {
@PostMapping("/batchSaveDraft")
@Operation(summary = "批量保存草稿")
- @Transactional(rollbackFor = Exception.class)
public ResponseResult saveDraft(@RequestBody FishImportRowRequest request) {
String taskId = request.getTaskId();
ImportTask importTask = importTaskService.getById(taskId);
- String resultJson = importTask.getResultJson();
- FishImportResult importResult = null;
- Map imageFiles = null;
- Map videoFiles = null;
- if (resultJson != null && !resultJson.isEmpty()) {
- try {
- importResult = objectMapper.readValue(resultJson, FishImportResult.class);
- imageFiles = importResult.getImageFiles();
- videoFiles = importResult.getVideoFiles();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
+ FishImportResult importResult = importTaskService.buildImportResult(taskId);
if (importResult == null || importResult.getRows() == null) {
return ResponseResult.error("导入数据不存在");
@@ -164,10 +179,12 @@ public class FishDraftDataController {
data.setDeletedFlag(0);
data.setLockFlag(0);
data.setTm(date);
+ data.setVdpthList(row.getVdpthList());
+ data.setPicpthList(row.getPicpthList());
fishDraftDataList.add(data);
}
- boolean result = fishDraftDataService.saveBatch(fishDraftDataList);
- fishImportService.processAttachmentsAsync(fishDraftDataList, imageFiles, videoFiles,importTask.getTempDir());
+ boolean result = fishDraftDataService.batchSaveDraft(fishDraftDataList);
+ fishImportService.processAttachmentsAsync(fishDraftDataList, importTask.getTempDir());
importTaskService.markSuccess(taskId);
return result ? ResponseResult.success("保存成功") : ResponseResult.error("保存失败");
}
@@ -180,11 +197,10 @@ public class FishDraftDataController {
if (importTask == null) {
return ResponseResult.error("导入任务不存在");
}
- String resultJson = importTask.getResultJson();
+ FishImportResult importResult = importTaskService.buildImportResult(taskId);
List fishDraftDataList = batchSaveDraftRequest.getFishDraftDataList();
- if (resultJson != null && !resultJson.isEmpty()) {
+ if (importResult != null) {
try {
- FishImportResult importResult = objectMapper.readValue(resultJson, FishImportResult.class);
ZipFileUtil.ZipContent content = new ZipFileUtil.ZipContent();
content.images = importResult.getImageFiles();
content.videos = importResult.getVideoFiles();
@@ -203,7 +219,6 @@ public class FishDraftDataController {
});
} catch (Exception e) {
e.printStackTrace();
- // ignore parse error
}
}
@@ -226,10 +241,90 @@ public class FishDraftDataController {
return result ? ResponseResult.success("删除成功") : ResponseResult.error("删除失败");
}
+
+
+// @PostMapping("/approvalIdRemoveDraft")
+// @Operation(summary = "根据批次号批量删除草稿(软删除)")
+// public ResponseResult approvalIdRemoveDraft(@RequestBody BatchApproveRequest request) {
+// List draft = fishDraftDataService.list(new LambdaQueryWrapper().eq(FishDraftData::getDeletedFlag, 0).in(FishDraftData::getApprovalId, request.getApprovalIds()).eq(FishDraftData::getStatus, "REJECTED").select(FishDraftData::getId));
+// List ids = draft.stream().map(FishDraftData::getId).toList();
+// boolean result = fishDraftDataService.batchRemoveDraft(ids);
+// if(result){
+// List list = fishDraftDataService.list(new LambdaQueryWrapper().in(FishDraftData::getId, ids).select(FishDraftData::getPicpth, FishDraftData::getVdpth, FishDraftData::getId));
+// // 异步删除附件
+// CompletableFuture.runAsync(() -> {
+// for (FishDraftData fishDraftData : list) {
+// String picpth = fishDraftData.getPicpth();
+// String vdpth = fishDraftData.getVdpth();
+//
+// try {
+// if (StrUtil.isNotBlank(picpth)) {
+// // 假设 picpth 是分号或逗号分隔的文件ID/路径
+// List split = StrUtil.split(picpth, StrUtil.C_COMMA);
+// for (String fileId : split) {
+// if (StrUtil.isNotBlank(fileId)) {
+// attachmentUploadService.deleteFile(fileId.trim());
+// }
+// }
+// }
+// if (StrUtil.isNotBlank(vdpth)) {
+// List split = StrUtil.split(vdpth, StrUtil.C_COMMA);
+// for (String fileId : split) {
+// if (StrUtil.isNotBlank(fileId)) {
+// attachmentUploadService.deleteFile(fileId.trim());
+// }
+// }
+// }
+// } catch (Exception e) {
+// log.error("异步删除附件失败, dataId: {}", fishDraftData.getId(), e);
+// }
+// }
+// }, attachmentDeleteExecutor).exceptionally(ex -> {
+// log.error("异步删除任务执行异常", ex);
+// return null;
+// });
+// }
+// return result ? ResponseResult.success("删除成功") : ResponseResult.error("删除失败");
+// }
@PostMapping("/batchRemoveDraft")
@Operation(summary = "批量删除草稿(软删除)")
public ResponseResult batchRemoveDraft(@RequestBody List ids) {
boolean result = fishDraftDataService.batchRemoveDraft(ids);
+ if(result){
+ List list = fishDraftDataService.list(new LambdaQueryWrapper().in(FishDraftData::getId, ids).select(FishDraftData::getPicpth, FishDraftData::getVdpth, FishDraftData::getId));
+ // 异步删除附件
+ CompletableFuture.runAsync(() -> {
+ for (FishDraftData fishDraftData : list) {
+ String picpth = fishDraftData.getPicpth();
+ String vdpth = fishDraftData.getVdpth();
+
+ try {
+ if (StrUtil.isNotBlank(picpth)) {
+ // 假设 picpth 是分号或逗号分隔的文件ID/路径
+ List split = StrUtil.split(picpth, StrUtil.C_COMMA);
+ for (String fileId : split) {
+ if (StrUtil.isNotBlank(fileId)) {
+ attachmentUploadService.deleteFile(fileId.trim());
+ }
+ }
+ }
+ if (StrUtil.isNotBlank(vdpth)) {
+ List split = StrUtil.split(vdpth, StrUtil.C_COMMA);
+ for (String fileId : split) {
+ if (StrUtil.isNotBlank(fileId)) {
+ attachmentUploadService.deleteFile(fileId.trim());
+ }
+ }
+ }
+ } catch (Exception e) {
+ log.error("异步删除附件失败, dataId: {}", fishDraftData.getId(), e);
+ }
+ }
+ }, attachmentDeleteExecutor).exceptionally(ex -> {
+ log.error("异步删除任务执行异常", ex);
+ return null;
+ });
+ }
return result ? ResponseResult.success("删除成功") : ResponseResult.error("删除失败");
}
@@ -353,16 +448,11 @@ public class FishDraftDataController {
@PostMapping("/importZip")
@Operation(summary = "导入ZIP过鱼数据(每个用户同时只能进行一次导入)")
- public ResponseResult importZip(@RequestParam("file") MultipartFile file) {
+ public ResponseResult importZip(HttpServletRequest request) {
log.info("开始导入ZIP文件");
- if (file == null || file.isEmpty()) {
- return ResponseResult.error("请上传文件");
- }
- String fileName = file.getOriginalFilename();
- if (fileName == null || (!fileName.endsWith(".zip"))) {
- return ResponseResult.error("请上传ZIP文件(.zip)");
- }
+
String uploadUserId = SecurityUtils.getUserId();
+
if (importTaskService.hasImportingTask(uploadUserId)) {
return ResponseResult.error("您有正在进行的导入任务,请等待完成后重试");
}
@@ -370,52 +460,72 @@ public class FishDraftDataController {
String importNo = "IMP" + System.currentTimeMillis();
String taskId = UUID.randomUUID().toString();
+ ImportTask task = null;
+ Path tempDirPath = null;
+
try {
String baseTempDir = ZipFileUtil.getDefaultTempDir();
String taskDirName = "zip_" + UUID.randomUUID().toString().substring(0, 8);
- Path tempDirPath = Paths.get(baseTempDir, taskDirName);
- Files.createDirectories(tempDirPath);
- File savedZipFile = new File(tempDirPath.toFile(), "upload.zip");
- file.transferTo(savedZipFile);
- log.info("ZIP文件已保存到: {}", savedZipFile.getAbsolutePath());
+ tempDirPath = Paths.get(baseTempDir, taskDirName);
- ImportTask task = new ImportTask();
+ task = new ImportTask();
task.setId(taskId);
task.setImportNo(importNo);
task.setBizType("FISH");
- task.setFileName(fileName);
- task.setFileSize(file.getSize());
- task.setStatus("UPLOADED");
+ task.setStatus("UPLOADING");
task.setUploadUserId(uploadUserId);
task.setUploadTime(new Date());
task.setTempDir(tempDirPath.toString());
importTaskService.save(task);
- log.info("导入任务已创建: {}", taskId);
+ log.info("导入任务已预创建: {}, 状态: UPLOADING", taskId);
+
+ MultipartStreamParser.StreamedFile streamedFile =
+ MultipartStreamParser.streamToFile(request, tempDirPath);
+
+ String fileName = streamedFile.getOriginalFileName();
+ if (fileName == null || !fileName.toLowerCase().endsWith(".zip")) {
+ importTaskService.markFailed(taskId, "文件格式错误: 请上传ZIP文件");
+ return ResponseResult.error("请上传ZIP文件(.zip)");
+ }
+
+ File savedZipFile = streamedFile.getTargetFile();
+ long fileSize = streamedFile.getFileSize();
+ log.info("ZIP文件已保存到: {} ({} bytes)", savedZipFile.getAbsolutePath(), fileSize);
+
+ task.setFileName(fileName);
+ task.setFileSize(fileSize);
+ task.setStatus("UPLOADED");
+ importTaskService.updateById(task);
+ log.info("导入任务已更新: {}, 状态: UPLOADED, 文件名: {}", taskId, fileName);
+
SecurityContext securityContext = SecurityContextHolder.getContext();
+ Path finalTempDirPath = tempDirPath;
CompletableFuture.runAsync(() -> {
try {
SecurityContextHolder.setContext(securityContext);
log.info("异步开始解析ZIP文件, taskId: {}", taskId);
+
FishImportResult result = fishImportService.parseAndMapZipFromFile(
- savedZipFile, tempDirPath.toString(), uploadUserId);
+ savedZipFile, finalTempDirPath.toString(), uploadUserId);
result.setTaskId(taskId);
- String status = "VALIDATED";
- if ("1".equals(result.getCode())) {
- status = "FAILED";
- }
+
+ String status = "1".equals(result.getCode()) ? "FAILED" : "VALIDATED";
+
importTaskService.updateStatus(taskId, status, result.getTempDir(), null);
importTaskService.updateProgress(taskId, result.getTotalCount(),
result.getSuccessCount(), result.getFailedCount());
- String resultJson = objectMapper.writeValueAsString(result);
- importTaskService.saveResultJson(taskId, resultJson);
- log.info("异步解析完成, taskId: {}, 状态: {}", taskId, status);
+ importTaskService.saveResultJson(taskId, result);
+
+ log.info("异步解析完成, taskId: {}, 状态: {}, 成功: {}, 失败: {}",
+ taskId, status, result.getSuccessCount(), result.getFailedCount());
} catch (Exception e) {
log.error("异步解析ZIP失败, taskId: {}", taskId, e);
importTaskService.markFailed(taskId, "导入失败: " + e.getMessage());
} finally {
SecurityContextHolder.clearContext();
if (savedZipFile.exists()) {
- savedZipFile.delete();
+ boolean deleted = savedZipFile.delete();
+ log.debug("临时ZIP文件删除: {}, 结果: {}", savedZipFile.getAbsolutePath(), deleted);
}
}
});
@@ -425,9 +535,23 @@ public class FishDraftDataController {
response.put("importNo", importNo);
response.put("status", "UPLOADED");
return ResponseResult.successData(response);
+
} catch (Exception e) {
- log.error("创建导入任务失败", e);
- importTaskService.markFailed(taskId, "导入失败: " + e.getMessage());
+ log.error("导入ZIP文件失败, taskId: {}", taskId, e);
+
+ if (task != null) {
+ importTaskService.markFailed(taskId, "导入失败: " + e.getMessage());
+ }
+
+ if (tempDirPath != null) {
+ try {
+ cn.hutool.core.io.FileUtil.del(tempDirPath.toFile());
+ log.debug("清理临时目录: {}", tempDirPath);
+ } catch (Exception cleanupEx) {
+ log.warn("清理临时目录失败: {}", tempDirPath, cleanupEx);
+ }
+ }
+
return ResponseResult.error("导入失败: " + e.getMessage());
}
}
@@ -445,13 +569,11 @@ public class FishDraftDataController {
return ResponseResult.error("任务不存在");
}
- String resultJson = task.getResultJson();
- if (resultJson == null || resultJson.isEmpty()) {
+ FishImportResult importResult = importTaskService.buildImportResult(taskId);
+ if (importResult == null) {
return ResponseResult.error("任务结果为空");
}
- FishImportResult importResult = objectMapper.readValue(resultJson, FishImportResult.class);
-
Map previewData = new HashMap<>();
previewData.put("tempDir", importResult.getTempDir());
previewData.put("excelFileName", importResult.getExcelFileName());
@@ -495,20 +617,14 @@ public class FishDraftDataController {
@GetMapping("/previewFile")
@Operation(summary = "预览临时文件内容")
public void previewFile(@RequestParam String taskId, @RequestParam String filename, @RequestParam String type, HttpServletRequest request, HttpServletResponse response) {
+ String decodedFilename = URLDecoder.decode(filename, StandardCharsets.UTF_8);
+ log.debug("原始文件名: {}, 解码后: {}", filename, decodedFilename);
ImportTask importTask = importTaskService.getById(taskId);
- String resultJson = importTask.getResultJson();
String filePath = null;
String dir = "1".equals(type) ? "images" : "videos";
- if (resultJson != null && !resultJson.isEmpty()) {
- try {
- FishImportResult importResult = objectMapper.readValue(resultJson, FishImportResult.class);
- String tempDir = importResult.getTempDir();
- filePath = tempDir + File.separator + dir + File.separator + filename;
- } catch (Exception e) {
- e.printStackTrace();
- // ignore parse error
- }
+ if (importTask != null && importTask.getTempDir() != null) {
+ filePath = importTask.getTempDir() + File.separator + dir + File.separator + decodedFilename;
}
if (filePath == null) {
writeErrorResponse(response, "文件路径不能为空");
@@ -568,13 +684,12 @@ public class FishDraftDataController {
return ResponseResult.error("任务不存在");
}
- String resultJson = importTask.getResultJson();
- if (resultJson == null || resultJson.isEmpty()) {
+ FishImportResult importResult = importTaskService.buildImportResult(taskId);
+ if (importResult == null) {
return ResponseResult.error("任务结果为空");
}
try {
- FishImportResult importResult = objectMapper.readValue(resultJson, FishImportResult.class);
boolean found = false;
for (FishImportResult.FishImportRow row : importResult.getRows()) {
@@ -632,8 +747,7 @@ public class FishDraftDataController {
return ResponseResult.error("未找到对应的数据行");
}
- String updatedJson = objectMapper.writeValueAsString(importResult);
- importTaskService.saveResultJson(taskId, updatedJson);
+ importTaskService.saveResultJson(taskId, importResult);
return ResponseResult.success("删除成功");
@@ -723,7 +837,6 @@ public class FishDraftDataController {
result.put("currentTask", null);
return ResponseResult.successData(result);
}
-
String statusText = getStatusText(currentTask.getStatus());
boolean canImport = isTaskComplete(currentTask.getStatus());
@@ -752,7 +865,8 @@ public class FishDraftDataController {
}
private boolean isTaskComplete(String status) {
- return "CONFIRMED".equals(status) || "FAILED".equals(status) || "CANCELLED".equals(status);
+ return "CONFIRMED".equals(status) || "CANCELLED".equals(status);
+// return "CONFIRMED".equals(status) || "FAILED".equals(status) || "CANCELLED".equals(status);
}
@GetMapping("/getLastImportResult")
@@ -768,15 +882,7 @@ public class FishDraftDataController {
));
}
- FishImportResult importResult = null;
- if (lastTask.getResultJson() != null && !lastTask.getResultJson().isEmpty()) {
- try {
- importResult = objectMapper.readValue(lastTask.getResultJson(), FishImportResult.class);
- } catch (Exception e) {
- e.printStackTrace();
- // ignore parse error
- }
- }
+ FishImportResult importResult = importTaskService.buildImportResult(lastTask.getId());
int totalCount = lastTask.getTotalCount() != null ? lastTask.getTotalCount() : 0;
int successCount = lastTask.getSuccessCount() != null ? lastTask.getSuccessCount() : 0;
@@ -871,13 +977,11 @@ public class FishDraftDataController {
return ResponseResult.error("任务不存在");
}
- String resultJson = task.getResultJson();
- if (resultJson == null || resultJson.isEmpty()) {
+ FishImportResult importResult = importTaskService.buildImportResult(taskId);
+ if (importResult == null) {
return ResponseResult.error("任务结果为空");
}
- FishImportResult importResult = objectMapper.readValue(resultJson, FishImportResult.class);
-
FishImportResult.FishImportRow targetRow = null;
int targetIndex = -1;
for (int i = 0; i < importResult.getRows().size(); i++) {
@@ -925,8 +1029,8 @@ public class FishDraftDataController {
importResult.setSuccessCount(successCount);
importResult.setFailedCount(failedCount);
- String updatedJson = objectMapper.writeValueAsString(importResult);
- importTaskService.saveResultJson(taskId, updatedJson);
+// String updatedJson = objectMapper.writeValueAsString(importResult);
+ importTaskService.saveResultJson(taskId, importResult);
Map map = new HashMap<>();
map.put("success", true);
@@ -961,13 +1065,11 @@ public class FishDraftDataController {
return ResponseResult.error("任务不存在");
}
- String resultJson = task.getResultJson();
- if (resultJson == null || resultJson.isEmpty()) {
+ FishImportResult importResult = importTaskService.buildImportResult(taskId);
+ if (importResult == null) {
return ResponseResult.error("任务结果为空");
}
- FishImportResult importResult = objectMapper.readValue(resultJson, FishImportResult.class);
-
FishImportResult.FishImportRow targetRow = null;
int targetIndex = -1;
for (int i = 0; i < importResult.getRows().size(); i++) {
@@ -983,8 +1085,8 @@ public class FishDraftDataController {
return ResponseResult.error("未找到对应的数据行");
}
importResult.getRows().remove(targetIndex);
- String updatedJson = objectMapper.writeValueAsString(importResult);
- importTaskService.saveResultJson(taskId, updatedJson);
+// String updatedJson = objectMapper.writeValueAsString(importResult);
+ importTaskService.saveResultJson(taskId, importResult);
return ResponseResult.success();
} catch (Exception e) {
@@ -1122,13 +1224,11 @@ public class FishDraftDataController {
return ResponseResult.error("任务不存在");
}
- String resultJson = task.getResultJson();
- if (resultJson == null || resultJson.isEmpty()) {
+ FishImportResult importResult = importTaskService.buildImportResult(taskId);
+ if (importResult == null) {
return ResponseResult.error("任务结果为空");
}
- FishImportResult importResult = objectMapper.readValue(resultJson, FishImportResult.class);
-
FishImportResult.FishImportRow matchedRow = findMatchingRow(importResult, data.getId());
FishImportResult.FishImportRow resultRow = new FishImportResult.FishImportRow();
@@ -1214,4 +1314,17 @@ public class FishDraftDataController {
return errors;
}
+
+ @jakarta.annotation.PreDestroy
+ public void shutdown() {
+ attachmentDeleteExecutor.shutdown();
+ try {
+ if (!attachmentDeleteExecutor.awaitTermination(30, TimeUnit.SECONDS)) {
+ attachmentDeleteExecutor.shutdownNow();
+ }
+ } catch (InterruptedException e) {
+ attachmentDeleteExecutor.shutdownNow();
+ Thread.currentThread().interrupt();
+ }
+ }
}
\ No newline at end of file
diff --git a/backend/src/main/java/com/yfd/platform/data/domain/FishDraftData.java b/backend/src/main/java/com/yfd/platform/data/domain/FishDraftData.java
index 4273248..da33082 100644
--- a/backend/src/main/java/com/yfd/platform/data/domain/FishDraftData.java
+++ b/backend/src/main/java/com/yfd/platform/data/domain/FishDraftData.java
@@ -8,6 +8,8 @@ import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
+import java.util.List;
+import java.util.Map;
/**
*
@@ -65,11 +67,23 @@ public class FishDraftData implements Serializable {
*/
private Date strdt;
+ /**
+ * 开始日期
+ */
+ @TableField(exist = false)
+ private String strdtStr;
+
/**
* 结束日期
*/
private Date enddt;
+ /**
+ * 结束日期
+ */
+ @TableField(exist = false)
+ private String enddtStr;
+
/**
* 游向(上行/下行/上行折返/下行折返)
*/
@@ -254,4 +268,10 @@ public class FishDraftData implements Serializable {
@TableField(exist = false)
private String ftpName;
+ @TableField(exist = false)
+ private List