diff --git a/backend/src/main/java/com/yfd/platform/config/MyMetaObjectHandler.java b/backend/src/main/java/com/yfd/platform/config/MyMetaObjectHandler.java index 5510e43..2459da8 100644 --- a/backend/src/main/java/com/yfd/platform/config/MyMetaObjectHandler.java +++ b/backend/src/main/java/com/yfd/platform/config/MyMetaObjectHandler.java @@ -2,6 +2,7 @@ package com.yfd.platform.config; import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import com.yfd.platform.utils.SecurityUtils; +import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.reflection.MetaObject; import org.springframework.stereotype.Component; @@ -12,6 +13,7 @@ import java.util.Date; * 用于处理 @TableField(fill = FieldFill.INSERT/UPDATE) 注解 */ @Component +@Slf4j public class MyMetaObjectHandler implements MetaObjectHandler { @@ -35,7 +37,7 @@ public class MyMetaObjectHandler implements MetaObjectHandler { // 自动填充更新时间 this.strictInsertFill(metaObject, "updatedBy", String.class, userId); } catch (Exception e) { - e.printStackTrace(); + log.info("message{}",e.getMessage()); } } @@ -52,7 +54,7 @@ public class MyMetaObjectHandler implements MetaObjectHandler { // 自动填充更新人 this.strictInsertFill(metaObject, "updatedBy", String.class, userId); } catch (Exception e) { - e.printStackTrace(); + log.info("message{}",e.getMessage()); } } 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 d145d90..53d927d 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 @@ -5,6 +5,7 @@ import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.config.ResponseResult; import com.yfd.platform.data.domain.ApprovalMain; import com.yfd.platform.data.service.IApprovalMainService; +import com.yfd.platform.data.service.IFishDraftDataService; import com.yfd.platform.utils.DataSourceRequestUtil; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -26,15 +27,20 @@ public class ApprovalMainController { @Resource private IApprovalMainService approvalMainService; + @Resource + private IFishDraftDataService fishDraftDataService; + @GetMapping("/page") @Operation(summary = "分页查询审批列表") public ResponseResult queryPageList( @RequestParam(defaultValue = "1") Integer current, @RequestParam(defaultValue = "10") Integer size, @RequestParam(required = false) String bizType, - @RequestParam(required = false) String status) { + @RequestParam(required = false) String status, + @RequestParam(required = false) String ennm, + @RequestParam(required = false) String hbrvnm) { Page page = new Page<>(current, size); - Page result = approvalMainService.queryPageList(page, bizType, status); + Page result = approvalMainService.queryPageList(page, bizType, status,ennm,hbrvnm); return ResponseResult.successData(result); } 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 cc48f44..1e1a0d5 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 @@ -5,11 +5,15 @@ import java.io.FileInputStream; import java.io.OutputStream; import java.net.URLEncoder; import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Base64; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.CompletableFuture; import cn.hutool.core.io.FileUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.fasterxml.jackson.databind.ObjectMapper; import com.yfd.platform.common.DataSourceRequest; @@ -29,6 +33,9 @@ import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; +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; @@ -111,16 +118,57 @@ public class FishDraftDataController { return result ? ResponseResult.success("保存成功") : ResponseResult.error("保存失败"); } +// @PostMapping("/batchSaveDraft") +// @Operation(summary = "批量保存草稿") +// public ResponseResult saveDraft(@RequestBody List fishDraftDataList) { +// +// fishDraftDataList.forEach(fishDraftData -> { +// fishDraftData.setStatus("DRAFT"); +// fishDraftData.setDeletedFlag(0); +// fishDraftData.setLockFlag(0); +// }); +// boolean result = fishDraftDataService.saveBatch(fishDraftDataList); +// return result ? ResponseResult.success("保存成功") : ResponseResult.error("保存失败"); +// } + @PostMapping("/batchSaveDraft") @Operation(summary = "批量保存草稿") - public ResponseResult saveDraft(@RequestBody List fishDraftDataList) { + @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(); + } + } - fishDraftDataList.forEach(fishDraftData -> { - fishDraftData.setStatus("DRAFT"); - fishDraftData.setDeletedFlag(0); - fishDraftData.setLockFlag(0); - }); + if (importResult == null || importResult.getRows() == null) { + return ResponseResult.error("导入数据不存在"); + } + Date date = new Date(); + List fishDraftDataList = new ArrayList<>(); + for (FishImportResult.FishImportRow row : importResult.getRows()) { + FishDraftData data = row.getData(); + data.setRowIndex(row.getRowIndex()); + data.setStatus("DRAFT"); + data.setEnddt(data.getStrdt()); + data.setDeletedFlag(0); + data.setLockFlag(0); + data.setTm(date); + fishDraftDataList.add(data); + } boolean result = fishDraftDataService.saveBatch(fishDraftDataList); + fishImportService.processAttachmentsAsync(fishDraftDataList, imageFiles, videoFiles,importTask.getTempDir()); + importTaskService.markSuccess(taskId); return result ? ResponseResult.success("保存成功") : ResponseResult.error("保存失败"); } @@ -200,6 +248,15 @@ public class FishDraftDataController { return result ? ResponseResult.success("提交成功") : ResponseResult.error("提交失败"); } + @PostMapping("/submitDraftsAll") + @Operation(summary = "批量提交当前用户全部草稿") + public ResponseResult submitDraftsAll() { + List draft = fishDraftDataService.list(new LambdaQueryWrapper().eq(FishDraftData::getDeletedFlag, 0).eq(FishDraftData::getCreatedBy, SecurityUtils.getUserId()).in(FishDraftData::getStatus, "REJECTED", "DRAFT").select(FishDraftData::getId)); + List ids = draft.stream().map(FishDraftData::getId).toList(); + boolean result = fishDraftDataService.submitDrafts(ids); + return result ? ResponseResult.success("提交成功") : ResponseResult.error("提交失败"); + } + @PostMapping("/batchApprove") @Operation(summary = "批量审批通过") public ResponseResult batchApprove(@RequestBody BatchApproveRequest request) { @@ -207,6 +264,27 @@ public class FishDraftDataController { return result ? ResponseResult.success("审批通过") : ResponseResult.error("审批失败"); } +// @PostMapping("/batchApproveAll") +// @Operation(summary = "批量全部审批通过") +// public ResponseResult batchApproveAll(@RequestBody BatchApproveRequest request) { +// List draft = fishDraftDataService.list(new LambdaQueryWrapper().eq(FishDraftData::getCreatedBy, SecurityUtils.getUserId()).eq(FishDraftData::getStatus, "PENDING").select(FishDraftData::getId)); +// List ids = draft.stream().map(FishDraftData::getId).toList(); +// boolean result = fishDraftDataService.batchApprove(ids, request.getApproveComment()); +// return result ? ResponseResult.success("审批通过") : ResponseResult.error("审批失败"); +// } + + @PostMapping("/batchApproveByApprovalId") + @Operation(summary = "根据审批批次全部审批通过") + public ResponseResult batchApproveByApprovalId(@RequestBody BatchApproveRequest request) { + if (request.getApprovalIds().isEmpty()) { + return ResponseResult.error("请选择审批批次"); + } + List draft = fishDraftDataService.list(new LambdaQueryWrapper().eq(FishDraftData::getDeletedFlag, 0).in(FishDraftData::getApprovalId, request.getApprovalIds()).eq(FishDraftData::getStatus, "PENDING").select(FishDraftData::getId)); + List ids = draft.stream().map(FishDraftData::getId).toList(); + boolean result = fishDraftDataService.batchApprove(ids, request.getApproveComment()); + return result ? ResponseResult.success("审批通过") : ResponseResult.error("审批失败"); + } + @PostMapping("/reject") @Operation(summary = "审批驳回") public ResponseResult batchReject(@RequestBody BatchRejectRequest request) { @@ -214,6 +292,22 @@ public class FishDraftDataController { return result ? ResponseResult.success("驳回成功") : ResponseResult.error("驳回失败"); } + @PostMapping("/batchReject") + @Operation(summary = "批量驳回") + public ResponseResult batchRejectFull(@RequestBody BatchRejectRequest request) { + if (request.getApprovalIds() != null && !request.getApprovalIds().isEmpty()) { + List draft = fishDraftDataService.list(new LambdaQueryWrapper().eq(FishDraftData::getDeletedFlag, 0).in(FishDraftData::getApprovalId, request.getApprovalIds()).eq(FishDraftData::getStatus, "PENDING").select(FishDraftData::getId)); + List ids = draft.stream().map(FishDraftData::getId).toList(); + boolean result = fishDraftDataService.rejectBatch(ids, request.getRejectReason()); + return result ? ResponseResult.success("驳回成功") : ResponseResult.error("驳回失败"); + } + if (request.getIds() != null && !request.getIds().isEmpty()) { + boolean result = fishDraftDataService.rejectBatch(request.getIds(), request.getRejectReason()); + return result ? ResponseResult.success("驳回成功") : ResponseResult.error("驳回失败"); + } + return ResponseResult.error("请选择要驳回的数据"); + } + @PostMapping("/lockDraft") @Operation(summary = "锁定草稿") @@ -264,22 +358,27 @@ public class FishDraftDataController { if (file == null || file.isEmpty()) { return ResponseResult.error("请上传文件"); } - log.info("开始上传文件"); String fileName = file.getOriginalFilename(); if (fileName == null || (!fileName.endsWith(".zip"))) { return ResponseResult.error("请上传ZIP文件(.zip)"); } - log.info("开始处理文件"); String uploadUserId = SecurityUtils.getUserId(); if (importTaskService.hasImportingTask(uploadUserId)) { return ResponseResult.error("您有正在进行的导入任务,请等待完成后重试"); } - log.info("开始保存导入任务"); String importNo = "IMP" + System.currentTimeMillis(); String taskId = UUID.randomUUID().toString(); 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()); + ImportTask task = new ImportTask(); task.setId(taskId); task.setImportNo(importNo); @@ -289,33 +388,45 @@ public class FishDraftDataController { task.setStatus("UPLOADED"); task.setUploadUserId(uploadUserId); task.setUploadTime(new Date()); - log.info("保存导入任务成功"); + task.setTempDir(tempDirPath.toString()); importTaskService.save(task); + log.info("导入任务已创建: {}", taskId); + SecurityContext securityContext = SecurityContextHolder.getContext(); + CompletableFuture.runAsync(() -> { + try { + SecurityContextHolder.setContext(securityContext); + log.info("异步开始解析ZIP文件, taskId: {}", taskId); + FishImportResult result = fishImportService.parseAndMapZipFromFile( + savedZipFile, tempDirPath.toString(), uploadUserId); + result.setTaskId(taskId); + String status = "VALIDATED"; + if ("1".equals(result.getCode())) { + status = "FAILED"; + } + 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); + } catch (Exception e) { + log.error("异步解析ZIP失败, taskId: {}", taskId, e); + importTaskService.markFailed(taskId, "导入失败: " + e.getMessage()); + } finally { + SecurityContextHolder.clearContext(); + if (savedZipFile.exists()) { + savedZipFile.delete(); + } + } + }); - log.info("开始保存文件"); - FishImportRequest request = new FishImportRequest(); - request.setImportNo(importNo); - request.setUploadUserId(uploadUserId); - request.setBizType("FISH"); - - FishImportResult result = fishImportService.parseAndMapZip(file, uploadUserId); - result.setTaskId(taskId); - String status = "VALIDATED"; - if ("1".equals(result.getCode())) { - status = "FAILED"; - } - importTaskService.updateStatus(taskId, status, null); - importTaskService.updateProgress(taskId, result.getTotalCount(), result.getSuccessCount(), result.getFailedCount()); - - try { - String resultJson = objectMapper.writeValueAsString(result); - importTaskService.saveResultJson(taskId, resultJson); - } catch (Exception e) { - // 忽略JSON序列化错误,不影响主流程 - e.printStackTrace(); - } - return ResponseResult.successData(result); + Map response = new HashMap<>(); + response.put("taskId", taskId); + response.put("importNo", importNo); + response.put("status", "UPLOADED"); + return ResponseResult.successData(response); } catch (Exception e) { + log.error("创建导入任务失败", e); importTaskService.markFailed(taskId, "导入失败: " + e.getMessage()); return ResponseResult.error("导入失败: " + e.getMessage()); } @@ -435,12 +546,13 @@ 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) { + @RequestParam String id, + @RequestParam String type, + @RequestParam String filename) { if (taskId == null || taskId.isEmpty()) { return ResponseResult.error("任务ID不能为空"); } @@ -612,28 +724,13 @@ public class FishDraftDataController { return ResponseResult.successData(result); } - int totalCount = currentTask.getTotalCount() != null ? currentTask.getTotalCount() : 0; - int successCount = currentTask.getSuccessCount() != null ? currentTask.getSuccessCount() : 0; - int failCount = currentTask.getFailCount() != null ? currentTask.getFailCount() : 0; - int progressPercent = totalCount > 0 ? (int) ((successCount + failCount) * 100.0 / totalCount) : 0; - String statusText = getStatusText(currentTask.getStatus()); boolean canImport = isTaskComplete(currentTask.getStatus()); Map taskInfo = new HashMap<>(); taskInfo.put("id", currentTask.getId()); - taskInfo.put("importNo", currentTask.getImportNo()); - taskInfo.put("fileName", currentTask.getFileName()); - taskInfo.put("fileSize", currentTask.getFileSize()); taskInfo.put("status", currentTask.getStatus()); taskInfo.put("statusText", statusText); - taskInfo.put("totalCount", totalCount); - taskInfo.put("successCount", successCount); - taskInfo.put("failCount", failCount); - taskInfo.put("progressPercent", progressPercent); - taskInfo.put("errorMsg", currentTask.getErrorMsg() != null ? currentTask.getErrorMsg() : ""); - taskInfo.put("uploadTime", currentTask.getUploadTime()); - result.put("hasImportingTask", true); result.put("canImport", canImport); result.put("currentTask", taskInfo); @@ -845,6 +942,57 @@ public class FishDraftDataController { } } + @PostMapping("/deleteRowById") + @Operation(summary = "删除数据") + public ResponseResult deleteRowById(@RequestBody FishImportRowRequest request) { + String taskId = request.getTaskId(); + FishDraftData data = request.getData(); + + if (taskId == null || taskId.isEmpty()) { + return ResponseResult.error("任务ID不能为空"); + } + if (data == null || data.getId() == null || data.getId().isEmpty()) { + return ResponseResult.error("数据对象或其ID不能为空"); + } + + try { + ImportTask task = importTaskService.getById(taskId); + if (task == null) { + return ResponseResult.error("任务不存在"); + } + + String resultJson = task.getResultJson(); + if (resultJson == null || resultJson.isEmpty()) { + 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++) { + FishImportResult.FishImportRow row = importResult.getRows().get(i); + if (row.getData() != null && data.getId().equals(row.getData().getId())) { + targetRow = row; + targetIndex = i; + break; + } + } + + if (targetIndex == -1) { + return ResponseResult.error("未找到对应的数据行"); + } + importResult.getRows().remove(targetIndex); + 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()); + } + } + private void validateAndNormalizeData(FishDraftData data, FishImportResult.FishImportRow importRow, List warnings) { if (data.getStcd() == null || data.getStcd().isEmpty()) { diff --git a/backend/src/main/java/com/yfd/platform/data/controller/ImportTaskController.java b/backend/src/main/java/com/yfd/platform/data/controller/ImportTaskController.java index 176f640..3682d35 100644 --- a/backend/src/main/java/com/yfd/platform/data/controller/ImportTaskController.java +++ b/backend/src/main/java/com/yfd/platform/data/controller/ImportTaskController.java @@ -101,7 +101,7 @@ public class ImportTaskController { public ResponseResult updateStatus(@RequestParam String id, @RequestParam String status, @RequestParam(required = false) String errorMsg) { - boolean result = importTaskService.updateStatus(id, status, errorMsg); + boolean result = importTaskService.updateStatus(id, status,null, errorMsg); return result ? ResponseResult.success("更新成功") : ResponseResult.error("更新失败"); } diff --git a/backend/src/main/java/com/yfd/platform/data/domain/ApprovalMain.java b/backend/src/main/java/com/yfd/platform/data/domain/ApprovalMain.java index c45084c..1e0a3c1 100644 --- a/backend/src/main/java/com/yfd/platform/data/domain/ApprovalMain.java +++ b/backend/src/main/java/com/yfd/platform/data/domain/ApprovalMain.java @@ -82,6 +82,30 @@ public class ApprovalMain implements Serializable { */ private String remark; + + /** + * 电站 + */ + private String ennm; + + + /** + * 流域 + */ + private String hbrvnm; + + /** + * 电站 + */ + private String stcd; + + + /** + * 流域 + */ + private String hbrvcd; + + /** * 创建时间 */ diff --git a/backend/src/main/java/com/yfd/platform/data/domain/BatchApproveRequest.java b/backend/src/main/java/com/yfd/platform/data/domain/BatchApproveRequest.java index 08c3ac3..66226b5 100644 --- a/backend/src/main/java/com/yfd/platform/data/domain/BatchApproveRequest.java +++ b/backend/src/main/java/com/yfd/platform/data/domain/BatchApproveRequest.java @@ -15,6 +15,9 @@ public class BatchApproveRequest { @Schema(description = "草稿数据ID列表") private List ids; + @Schema(description = "批次ID列表") + List approvalIds; + @Schema(description = "审批意见") private String approveComment; } \ No newline at end of file diff --git a/backend/src/main/java/com/yfd/platform/data/domain/BatchRejectRequest.java b/backend/src/main/java/com/yfd/platform/data/domain/BatchRejectRequest.java index 2b97b19..fd1deb9 100644 --- a/backend/src/main/java/com/yfd/platform/data/domain/BatchRejectRequest.java +++ b/backend/src/main/java/com/yfd/platform/data/domain/BatchRejectRequest.java @@ -3,6 +3,8 @@ package com.yfd.platform.data.domain; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import java.util.List; + /** * 审批驳回请求参数 */ @@ -13,6 +15,12 @@ public class BatchRejectRequest { @Schema(description = "草稿数据ID") private String id; + @Schema(description = "草稿数据ID列表") + private List ids; + + @Schema(description = "批次ID列表") + private List approvalIds; + @Schema(description = "驳回原因") private String rejectReason; } \ 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 fe8ac15..4273248 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 @@ -156,6 +156,14 @@ public class FishDraftData implements Serializable { */ private Integer deletedFlag; + + /** + * 行号 + */ + private Integer rowIndex; + + + /** * 删除人 */ diff --git a/backend/src/main/java/com/yfd/platform/data/domain/vo/FishDraftDataVO.java b/backend/src/main/java/com/yfd/platform/data/domain/vo/FishDraftDataVO.java index 2037ca7..35fa621 100644 --- a/backend/src/main/java/com/yfd/platform/data/domain/vo/FishDraftDataVO.java +++ b/backend/src/main/java/com/yfd/platform/data/domain/vo/FishDraftDataVO.java @@ -216,7 +216,7 @@ public class FishDraftDataVO implements Serializable { /** * 排序字段 */ - private Integer orderIndex; + private Integer rowIndex; /** * 创建人名称 diff --git a/backend/src/main/java/com/yfd/platform/data/mapper/FishDraftDataMapper.java b/backend/src/main/java/com/yfd/platform/data/mapper/FishDraftDataMapper.java index 3ad254f..6ebcbec 100644 --- a/backend/src/main/java/com/yfd/platform/data/mapper/FishDraftDataMapper.java +++ b/backend/src/main/java/com/yfd/platform/data/mapper/FishDraftDataMapper.java @@ -27,7 +27,10 @@ public interface FishDraftDataMapper extends BaseMapper { @Param("status") String status, @Param("ftp") String ftp, @Param("startTime") String startTime, - @Param("endTime") String endTime,@Param("userId") String userId,@Param("hbrvcd") String hbrvcd); + @Param("endTime") String endTime, + @Param("userId") String userId, + @Param("hbrvcd") String hbrvcd, + @Param("approvalId") String approvalId); /** * 关联查询过鱼数据(不分页) diff --git a/backend/src/main/java/com/yfd/platform/data/mapper/ImportTaskMapper.java b/backend/src/main/java/com/yfd/platform/data/mapper/ImportTaskMapper.java index 8325796..0937aab 100644 --- a/backend/src/main/java/com/yfd/platform/data/mapper/ImportTaskMapper.java +++ b/backend/src/main/java/com/yfd/platform/data/mapper/ImportTaskMapper.java @@ -38,15 +38,16 @@ public interface ImportTaskMapper extends BaseMapper { @Select("SELECT * FROM IMPORT_TASK WHERE UPLOAD_USER_ID = #{uploadUserId} ORDER BY CREATED_AT DESC") List selectByUploadUserId(@Param("uploadUserId") String uploadUserId); - @Select("") - List selectByUserIdAndStatuses(@Param("uploadUserId") String uploadUserId, - @Param("statuses") List statuses); + @Select("SELECT * FROM (" + + "SELECT ID, IMPORT_NO, BIZ_TYPE, FILE_NAME, FILE_SIZE, FILE_PATH, TEMP_DIR, " + + "TOTAL_COUNT, SUCCESS_COUNT, FAIL_COUNT, STATUS, ERROR_MSG, " + + "UPLOAD_USER_ID, UPLOAD_TIME, EXPIRE_TIME, CREATED_AT, UPDATED_AT " + + "FROM IMPORT_TASK " + + "WHERE UPLOAD_USER_ID = #{uploadUserId} " + + "AND STATUS IN ('UPLOADED', 'PARSING', 'VALIDATED') " + + "ORDER BY CREATED_AT DESC" + + ") WHERE ROWNUM = 1") + List selectByUserIdAndStatuses(@Param("uploadUserId") String uploadUserId); /** * 查询过期的任务 diff --git a/backend/src/main/java/com/yfd/platform/data/mapper/SysUserDataScopeMapper.java b/backend/src/main/java/com/yfd/platform/data/mapper/SysUserDataScopeMapper.java index 525fba4..8a592c2 100644 --- a/backend/src/main/java/com/yfd/platform/data/mapper/SysUserDataScopeMapper.java +++ b/backend/src/main/java/com/yfd/platform/data/mapper/SysUserDataScopeMapper.java @@ -42,5 +42,5 @@ public interface SysUserDataScopeMapper extends BaseMapper { /** * 查询有效权限(状态=1且在有效期内的) */ - List selectValidPermissions(@Param("userId") Long userId); + List selectValidPermissions(@Param("userId") String userId); } diff --git a/backend/src/main/java/com/yfd/platform/data/service/AttachmentUploadService.java b/backend/src/main/java/com/yfd/platform/data/service/AttachmentUploadService.java index 1cd11a4..2531588 100644 --- a/backend/src/main/java/com/yfd/platform/data/service/AttachmentUploadService.java +++ b/backend/src/main/java/com/yfd/platform/data/service/AttachmentUploadService.java @@ -32,13 +32,20 @@ public class AttachmentUploadService { @Value("${attachment.token}") private String token; - // 定义一个固定的线程池用于文件上传(建议根据服务器性能调整核心线程数) + @Value("${attachment.upload-url}") + private String uploadUrl; + + @Value("${attachment.video-url}") + private String videoUrl; + + @Value("${attachment.delete-url}") + private String deleteUrl; +// private static final String DELETE_URL = "https://211.99.26.225:12125/FileDelete"; + private static final ExecutorService UPLOAD_EXECUTOR = new ThreadPoolExecutor( 5, 10, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(100), new ThreadPoolExecutor.CallerRunsPolicy() ); - private static final String UPLOAD_URL = "https://211.99.26.225:12125/upload"; - private static final String VIDEO_URL = "https://211.99.26.225:12125/upload"; private final HttpClient httpClient; @@ -68,32 +75,14 @@ public class AttachmentUploadService { System.arraycopy(footer.getBytes(), 0, body, header.getBytes().length + fileContent.length, footer.getBytes().length); try { - // 1. 创建信任所有证书的 TrustManager - TrustManager[] trustAllCerts = new TrustManager[]{ - new X509TrustManager() { - public void checkClientTrusted(X509Certificate[] chain, String authType) {} - public void checkServerTrusted(X509Certificate[] chain, String authType) {} - public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } - } - }; - - // 2. 初始化 SSLContext - SSLContext sc = SSLContext.getInstance("TLS"); - sc.init(null, trustAllCerts, new SecureRandom()); - - // 3. 构建支持 HTTPS 且忽略证书验证的 HttpClient - HttpClient secureClient = HttpClient.newBuilder() - .sslContext(sc) - .build(); - + log.info("开始上传文件:uploadUrl {}", uploadUrl); HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create(UPLOAD_URL)) + .uri(URI.create(uploadUrl)) .header("Content-Type", "multipart/form-data; boundary=" + boundary) .POST(HttpRequest.BodyPublishers.ofByteArray(body)) .build(); - // 4. 使用新的 secureClient 发送请求 - HttpResponse response = secureClient.send(request, HttpResponse.BodyHandlers.ofString()); + HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); if (response.statusCode() == 200) { String responseBody = response.body(); @@ -109,6 +98,68 @@ public class AttachmentUploadService { } +// public String uploadFile(File file) throws IOException, InterruptedException { +// if (file == null || !file.exists()) { +// log.warn("文件不存在或为空: {}", file); +// return null; +// } +// +// String boundary = "----FormBoundary" + System.currentTimeMillis(); +// byte[] fileContent = Files.readAllBytes(file.toPath()); +// String fileName = file.getName(); +// +// String header = "--" + boundary + "\r\n" + +// "Content-Disposition: form-data; name=\"file\"; filename=\"" + fileName + "\"\r\n" + +// "Content-Type: application/octet-stream\r\n\r\n"; +// String footer = "\r\n--" + boundary + "--\r\n"; +// +// byte[] body = new byte[header.getBytes().length + fileContent.length + footer.getBytes().length]; +// System.arraycopy(header.getBytes(), 0, body, 0, header.getBytes().length); +// System.arraycopy(fileContent, 0, body, header.getBytes().length, fileContent.length); +// System.arraycopy(footer.getBytes(), 0, body, header.getBytes().length + fileContent.length, footer.getBytes().length); +// +// try { +// // 1. 创建信任所有证书的 TrustManager +// TrustManager[] trustAllCerts = new TrustManager[]{ +// new X509TrustManager() { +// public void checkClientTrusted(X509Certificate[] chain, String authType) {} +// public void checkServerTrusted(X509Certificate[] chain, String authType) {} +// public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } +// } +// }; +// +// // 2. 初始化 SSLContext +// SSLContext sc = SSLContext.getInstance("TLS"); +// sc.init(null, trustAllCerts, new SecureRandom()); +// +// // 3. 构建支持 HTTPS 且忽略证书验证的 HttpClient +// HttpClient secureClient = HttpClient.newBuilder() +// .sslContext(sc) +// .build(); +// +// HttpRequest request = HttpRequest.newBuilder() +// .uri(URI.create(uploadUrl)) +// .header("Content-Type", "multipart/form-data; boundary=" + boundary) +// .POST(HttpRequest.BodyPublishers.ofByteArray(body)) +// .build(); +// +// // 4. 使用新的 secureClient 发送请求 +// HttpResponse response = secureClient.send(request, HttpResponse.BodyHandlers.ofString()); +// +// if (response.statusCode() == 200) { +// String responseBody = response.body(); +// return parseAttachmentId(responseBody); +// } else { +// log.error("上传文件失败: {}, 状态码: {}", fileName, response.statusCode()); +// return null; +// } +// } catch (Exception e) { +// log.error("文件上传过程中发生异常: {}", e.getMessage(), e); +// return null; +// } +// } + + /** * 多线程批量上传文件 * @param files 文件列表 @@ -266,7 +317,55 @@ public class AttachmentUploadService { } } - private static final String DELETE_URL = "https://211.99.26.225:12125/FileDelete"; + + +// public boolean deleteFile(String attachmentId) { +// if (attachmentId == null || attachmentId.isEmpty()) { +// log.warn("附件ID为空"); +// return false; +// } +// +// try { +// TrustManager[] trustAllCerts = new TrustManager[]{ +// new X509TrustManager() { +// public void checkClientTrusted(X509Certificate[] chain, String authType) {} +// public void checkServerTrusted(X509Certificate[] chain, String authType) {} +// public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } +// } +// }; +// +// SSLContext sc = SSLContext.getInstance("TLS"); +// sc.init(null, trustAllCerts, new SecureRandom()); +// +// HttpClient secureClient = HttpClient.newBuilder() +// .sslContext(sc) +// .build(); +// +// String formData = "fileId=" + attachmentId; +// +// HttpRequest request = HttpRequest.newBuilder() +// .uri(URI.create(deleteUrl)) +// .header("Content-Type", "application/x-www-form-urlencoded") +// .header("token", token) +// .POST(HttpRequest.BodyPublishers.ofString(formData)) +// .build(); +// +// HttpResponse response = secureClient.send(request, HttpResponse.BodyHandlers.ofString()); +// +// if (response.statusCode() == 200) { +// String responseBody = response.body(); +// return parseDeleteResult(responseBody); +// } else { +// log.error("删除附件失败: {}, 状态码: {}", attachmentId, response.statusCode()); +// return false; +// } +// } catch (Exception e) { +// log.error("删除附件过程中发生异常: {}", attachmentId, e); +// return false; +// } +// } + + public boolean deleteFile(String attachmentId) { if (attachmentId == null || attachmentId.isEmpty()) { @@ -275,31 +374,16 @@ public class AttachmentUploadService { } try { - TrustManager[] trustAllCerts = new TrustManager[]{ - new X509TrustManager() { - public void checkClientTrusted(X509Certificate[] chain, String authType) {} - public void checkServerTrusted(X509Certificate[] chain, String authType) {} - public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } - } - }; - - SSLContext sc = SSLContext.getInstance("TLS"); - sc.init(null, trustAllCerts, new SecureRandom()); - - HttpClient secureClient = HttpClient.newBuilder() - .sslContext(sc) - .build(); - String formData = "fileId=" + attachmentId; HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create(DELETE_URL)) + .uri(URI.create(deleteUrl)) .header("Content-Type", "application/x-www-form-urlencoded") .header("token", token) .POST(HttpRequest.BodyPublishers.ofString(formData)) .build(); - HttpResponse response = secureClient.send(request, HttpResponse.BodyHandlers.ofString()); + HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); if (response.statusCode() == 200) { String responseBody = response.body(); @@ -314,6 +398,7 @@ public class AttachmentUploadService { } } + private boolean parseDeleteResult(String jsonResponse) { if (jsonResponse == null || jsonResponse.isEmpty()) { return false; diff --git a/backend/src/main/java/com/yfd/platform/data/service/IApprovalMainService.java b/backend/src/main/java/com/yfd/platform/data/service/IApprovalMainService.java index b2ee766..2c18651 100644 --- a/backend/src/main/java/com/yfd/platform/data/service/IApprovalMainService.java +++ b/backend/src/main/java/com/yfd/platform/data/service/IApprovalMainService.java @@ -3,6 +3,7 @@ package com.yfd.platform.data.service; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; import com.yfd.platform.data.domain.ApprovalMain; +import org.springframework.web.bind.annotation.RequestParam; import java.util.List; @@ -16,7 +17,7 @@ public interface IApprovalMainService extends IService { /** * 分页查询审批列表 */ - Page queryPageList(Page page, String bizType, String status); + Page queryPageList(Page page, String bizType, String status,String ennm, String hbrvnm); void fillUserNames(List list); diff --git a/backend/src/main/java/com/yfd/platform/data/service/IFishDraftDataService.java b/backend/src/main/java/com/yfd/platform/data/service/IFishDraftDataService.java index 2be6536..d3b2486 100644 --- a/backend/src/main/java/com/yfd/platform/data/service/IFishDraftDataService.java +++ b/backend/src/main/java/com/yfd/platform/data/service/IFishDraftDataService.java @@ -75,6 +75,11 @@ public interface IFishDraftDataService extends IService { */ boolean batchReject(String id, String rejectReason); + /** + * 批量驳回 + */ + boolean rejectBatch(List ids, String rejectReason); + /** * 锁定草稿 */ 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 38e416e..c78bdc5 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 @@ -5,6 +5,7 @@ import com.yfd.platform.data.domain.FishImportResult; import com.yfd.platform.data.utils.ZipFileUtil; import org.springframework.web.multipart.MultipartFile; +import java.io.File; import java.io.InputStream; /** @@ -14,12 +15,14 @@ import java.io.InputStream; */ public interface IFishImportService { - FishImportResult parseAndMapExcel(FishImportRequest request, InputStream inputStream); + FishImportResult parseAndMapExcel(FishImportRequest request, InputStream inputStream,String userId); - FishImportResult parseAndMapExcelFromPath(FishImportRequest request); + FishImportResult parseAndMapExcelFromPath(FishImportRequest request,String userId); FishImportResult parseAndMapZip(MultipartFile file, String uploadUserId); + FishImportResult parseAndMapZipFromFile(File zipFile, String tempDir, String uploadUserId); + String resolveStationCode(String stationName); String resolveFpssCode(String name); @@ -48,4 +51,9 @@ public interface IFishImportService { boolean validateFpssBelongsToStation(String fpssCode, String stationCode); void processAttachments(FishImportResult result, ZipFileUtil.ZipContent zipContent); + + void processAttachmentsAsync(java.util.List dataList, + java.util.Map imageFiles, + java.util.Map videoFiles, + String tempDir); } \ No newline at end of file diff --git a/backend/src/main/java/com/yfd/platform/data/service/IImportTaskService.java b/backend/src/main/java/com/yfd/platform/data/service/IImportTaskService.java index 901bf65..9726983 100644 --- a/backend/src/main/java/com/yfd/platform/data/service/IImportTaskService.java +++ b/backend/src/main/java/com/yfd/platform/data/service/IImportTaskService.java @@ -41,7 +41,7 @@ public interface IImportTaskService extends IService { /** * 更新任务状态 */ - boolean updateStatus(String id, String status, String errorMsg); + boolean updateStatus(String id, String status,String tempDir, String errorMsg); /** * 更新解析进度 diff --git a/backend/src/main/java/com/yfd/platform/data/service/impl/ApprovalMainServiceImpl.java b/backend/src/main/java/com/yfd/platform/data/service/impl/ApprovalMainServiceImpl.java index cab10cd..27923ee 100644 --- a/backend/src/main/java/com/yfd/platform/data/service/impl/ApprovalMainServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/data/service/impl/ApprovalMainServiceImpl.java @@ -1,10 +1,13 @@ package com.yfd.platform.data.service.impl; import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.yfd.platform.data.domain.ApprovalMain; +import com.yfd.platform.data.domain.SysUserDataScope; import com.yfd.platform.data.mapper.ApprovalMainMapper; +import com.yfd.platform.data.mapper.SysUserDataScopeMapper; import com.yfd.platform.data.service.IApprovalLogService; import com.yfd.platform.data.service.IApprovalMainService; import com.yfd.platform.system.domain.SysUser; @@ -15,6 +18,7 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; import java.util.*; +import java.util.stream.Collectors; /** *

@@ -33,11 +37,16 @@ public class ApprovalMainServiceImpl extends ServiceImpl queryPageList(Page page, String bizType, String status) { + public Page queryPageList(Page page, String bizType, String status,String ennm, String hbrvnm) { Page approvalMainPage = this.page(page, this.lambdaQuery() .eq(StringUtils.hasText(bizType), ApprovalMain::getBizType, bizType) .eq(StringUtils.hasText(status), ApprovalMain::getStatus, status) + .like(StringUtils.hasText(ennm), ApprovalMain::getEnnm, ennm) + .like(StringUtils.hasText(hbrvnm), ApprovalMain::getHbrvnm, hbrvnm) .orderByDesc(ApprovalMain::getCreatedAt) .getWrapper()); fillUserNames(approvalMainPage.getRecords()); @@ -52,6 +61,7 @@ public class ApprovalMainServiceImpl extends ServiceImpl userIds = new HashSet<>(); for (ApprovalMain vo : list) { + if (StrUtil.isNotBlank(vo.getApproverId())) { userIds.add(vo.getApproverId()); } @@ -63,7 +73,6 @@ public class ApprovalMainServiceImpl extends ServiceImpl userNameMap = new HashMap<>(); List users = sysUserMapper.selectBatchIds(userIds); for (SysUser user : users) { diff --git a/backend/src/main/java/com/yfd/platform/data/service/impl/FishDraftDataServiceImpl.java b/backend/src/main/java/com/yfd/platform/data/service/impl/FishDraftDataServiceImpl.java index 8e47134..c1d83a4 100644 --- a/backend/src/main/java/com/yfd/platform/data/service/impl/FishDraftDataServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/data/service/impl/FishDraftDataServiceImpl.java @@ -9,12 +9,21 @@ import com.yfd.platform.common.DataSourceLoadOptionsBase; import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.data.domain.ApprovalMain; import com.yfd.platform.data.domain.FishDraftData; +import com.yfd.platform.data.domain.SysUserDataScope; import com.yfd.platform.data.domain.vo.FishDraftDataVO; import com.yfd.platform.data.mapper.FishDraftDataMapper; +import com.yfd.platform.data.mapper.SysUserDataScopeMapper; import com.yfd.platform.data.service.IApprovalChangeLogService; import com.yfd.platform.data.service.IApprovalLogService; import com.yfd.platform.data.service.IApprovalMainService; import com.yfd.platform.data.service.IFishDraftDataService; +import com.yfd.platform.env.domain.SdEngInfoBH; +import com.yfd.platform.env.domain.SdFpssR; +import com.yfd.platform.env.domain.SdHbrvDic; +import com.yfd.platform.env.mapper.SdEngInfoBHMapper; +import com.yfd.platform.env.mapper.SdFpssRMapper; +import com.yfd.platform.env.mapper.SdHbrvDicMapper; +import com.yfd.platform.env.service.ISdFpssRService; import com.yfd.platform.system.domain.SysUser; import com.yfd.platform.system.mapper.SysUserMapper; import com.yfd.platform.utils.KendoUtil; @@ -22,6 +31,8 @@ import com.yfd.platform.utils.QgcQueryWrapperUtil; import com.yfd.platform.utils.SecurityUtils; import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.apache.ibatis.executor.BatchResult; import org.springframework.security.core.GrantedAuthority; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -35,6 +46,7 @@ import java.util.*; *

*/ @Service +@Slf4j public class FishDraftDataServiceImpl extends ServiceImpl implements IFishDraftDataService { @Resource @@ -55,27 +67,49 @@ public class FishDraftDataServiceImpl extends ServiceImpl queryPageList(DataSourceRequest dataSourceRequest) { Page page = KendoUtil.getPage(dataSourceRequest); + page.setSize(dataSourceRequest.getTake()); + page.setCurrent(dataSourceRequest.getSkip()); DataSourceLoadOptionsBase loadOptions = dataSourceRequest.toDevRequest(); String stcd = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "stcd"); + String approvalId = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "approvalId"); String rstcd = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "rstcd"); String hbrvcd = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "hbrvcd"); String baseId = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "baseId"); String ftp = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "ftp"); String direction = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "direction"); String status = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "status"); - String TM = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "TM"); + String STRDT = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "strdt"); String startTime=null; String endTime=null; - String userId = (SecurityUtils.hasPermission("sjtb:edit-review") || "admin".equals(SecurityUtils.getCurrentUsername())) ?null:SecurityUtils.getUserId(); - // 如果 startTime 和 endTime 为空,尝试从 TM 字段解析 - if (StrUtil.isNotBlank(TM)&& TM.split( ",").length==2) { - startTime=TM.split(",")[0]; - endTime=TM.split(",")[1]; +// String userId = (SecurityUtils.hasPermission("sjtb:edit-review") || "admin".equals(SecurityUtils.getCurrentUsername())) ?null:SecurityUtils.getUserId(); + String userId = SecurityUtils.getUserId(); + if(StrUtil.isNotBlank(approvalId)){ + userId=null; } - Page resultPage = fishDraftDataMapper.selectJoinPage(page, stcd, rstcd, baseId, direction, status, ftp, startTime, endTime,userId,hbrvcd); + // 如果 startTime 和 endTime 为空,尝试从 TM 字段解析 + if (StrUtil.isNotBlank(STRDT)&& STRDT.split( ",").length==2) { + startTime=STRDT.split(",")[0]; + endTime=STRDT.split(",")[1]; + } + Page resultPage = fishDraftDataMapper.selectJoinPage(page, stcd, rstcd, baseId, direction, status, ftp, startTime, endTime,userId,hbrvcd,approvalId); fillUserNames(resultPage.getRecords()); return resultPage; } @@ -240,6 +274,7 @@ public class FishDraftDataServiceImpl extends ServiceImpl updateWrapper = new LambdaUpdateWrapper<>(); @@ -282,6 +319,85 @@ public class FishDraftDataServiceImpl extends ServiceImpl permissions = userDataScopeMapper.selectValidPermissions(userId); + if (permissions == null || permissions.isEmpty()) { + return; + } + + Set hbrvcdSet = new HashSet<>(); + Set hbrvnmSet = new HashSet<>(); + Set stcdSet = new HashSet<>(); + Set ennmSet = new HashSet<>(); + + for (SysUserDataScope permission : permissions) { + String orgType = permission.getOrgType(); + String orgId = permission.getOrgId(); + + if (orgId == null || orgId.isEmpty()) { + continue; + } + + if ("HBRVCD".equals(orgType)) { + hbrvcdSet.add(orgId); + + SdHbrvDic hbrv = hbrvDicMapper.selectById(orgId); + if (hbrv != null && hbrv.getHbrvnm() != null) { + hbrvnmSet.add(hbrv.getHbrvnm()); + } + + List stationList = engInfoBHMapper.selectByHbrvcd(orgId); + if (stationList != null) { + for (SdEngInfoBH station : stationList) { + if (station.getStcd() != null) { + stcdSet.add(station.getStcd()); + } + if (station.getEnnm() != null) { + ennmSet.add(station.getEnnm()); + } + } + } + + } else if ("STATION".equals(orgType)) { + SdEngInfoBH station = engInfoBHMapper.selectById(orgId); + if (station != null) { + if (station.getHbrvcd() != null) { + hbrvcdSet.add(station.getHbrvcd()); + } + if (station.getStcd() != null) { + stcdSet.add(station.getStcd()); + } + if (station.getEnnm() != null) { + ennmSet.add(station.getEnnm()); + } + + SdHbrvDic hbrv = hbrvDicMapper.selectById(station.getHbrvcd()); + if (hbrv != null && hbrv.getHbrvnm() != null) { + hbrvnmSet.add(hbrv.getHbrvnm()); + } + } + } + } + + if (!hbrvcdSet.isEmpty()) { + approvalMain.setHbrvcd(String.join(",", hbrvcdSet)); + } + if (!hbrvnmSet.isEmpty()) { + approvalMain.setHbrvnm(String.join(",", hbrvnmSet)); + } + if (!stcdSet.isEmpty()) { + approvalMain.setStcd(String.join(",", stcdSet)); + } + if (!ennmSet.isEmpty()) { + approvalMain.setEnnm(String.join(",", ennmSet)); + } + } + @Override @Transactional(rollbackFor = Exception.class) @@ -295,6 +411,7 @@ public class FishDraftDataServiceImpl extends ServiceImpl dataList = this.listByIds(ids); Set processedApprovalIds = new HashSet<>(); List validIds = new ArrayList<>(); + List fpssRList = new ArrayList<>(); for (FishDraftData fishDraftData : dataList) { if ("PENDING".equals(fishDraftData.getStatus())) { @@ -302,6 +419,8 @@ public class FishDraftDataServiceImpl extends ServiceImpl ids, String rejectReason) { + if (ids == null || ids.isEmpty()) { + return false; + } + if (StrUtil.isBlank(rejectReason)) { + throw new IllegalArgumentException("驳回原因不能为空"); + } + Date now = new Date(); + String operatorId = SecurityUtils.getUserId(); + + List dataList = this.listByIds(ids); + Set processedApprovalIds = new HashSet<>(); + List validIds = new ArrayList<>(); + + for (FishDraftData fishDraftData : dataList) { + if ("PENDING".equals(fishDraftData.getStatus())) { + validIds.add(fishDraftData.getId()); + if (fishDraftData.getApprovalId() != null) { + processedApprovalIds.add(fishDraftData.getApprovalId()); + } + } + } + + if (!validIds.isEmpty()) { + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.in(FishDraftData::getId, validIds); + updateWrapper.set(FishDraftData::getStatus, "REJECTED"); + updateWrapper.set(FishDraftData::getApproveTime, now); + updateWrapper.set(FishDraftData::getUpdatedBy, operatorId); + this.update(updateWrapper); + + for (String approvalId : processedApprovalIds) { + approvalLogService.logReject(approvalId, operatorId, rejectReason); + ApprovalMain approvalMain = approvalMainService.getById(approvalId); + if (approvalMain != null) { + approvalMain.setStatus("REJECTED"); + approvalMain.setApproverId(operatorId); + approvalMain.setApproveTime(now); + approvalMain.setRemark(rejectReason); + approvalMainService.updateById(approvalMain); + } + } + } + + return true; + } + @Override @Transactional(rollbackFor = Exception.class) public boolean lockDraft(String id) { 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 32c0d3d..0228d07 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,24 +1,33 @@ package com.yfd.platform.data.service.impl; +import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 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.SysUserDataScope; +import com.yfd.platform.data.mapper.SysUserDataScopeMapper; 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.utils.ZipFileUtil; import com.yfd.platform.env.domain.*; import com.yfd.platform.env.mapper.*; import com.yfd.platform.system.service.ISysDictionaryItemsService; import com.yfd.platform.system.service.ISysDictionaryService; +import com.yfd.platform.utils.SecurityUtils; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import org.springframework.web.multipart.MultipartFile; +import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; @@ -26,6 +35,7 @@ import java.math.BigDecimal; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; +import java.util.concurrent.CompletableFuture; @Service @Slf4j @@ -58,6 +68,12 @@ public class FishImportServiceImpl implements IFishImportService { @Resource private AttachmentUploadService attachmentUploadService; + @Resource + private IFishDraftDataService fishDraftDataService; + + @Resource + private SysUserDataScopeMapper userDataScopeMapper; + private static final Map EXCEL_COLUMN_MAPPING = new LinkedHashMap<>(); private static final Map EXCEL_COLUMN_INDEX_MAPPING = new LinkedHashMap<>(); @@ -123,12 +139,12 @@ public class FishImportServiceImpl implements IFishImportService { } @Override - public FishImportResult parseAndMapExcel(FishImportRequest request, InputStream inputStream) { + public FishImportResult parseAndMapExcel(FishImportRequest request, InputStream inputStream, String userId) { FishImportResult result = new FishImportResult(); try (Workbook workbook = new XSSFWorkbook(inputStream)) { Sheet sheet = workbook.getSheetAt(0); - return parseSheet(sheet, result); + return parseSheet(sheet, result, userId); } catch (IOException e) { result.setSummary("Excel文件解析失败: " + e.getMessage()); return result; @@ -136,20 +152,20 @@ public class FishImportServiceImpl implements IFishImportService { } @Override - public FishImportResult parseAndMapExcelFromPath(FishImportRequest request) { + public FishImportResult parseAndMapExcelFromPath(FishImportRequest request, String userId) { FishImportResult result = new FishImportResult(); try (InputStream inputStream = request.getFilePath().startsWith("http") ? new java.net.URL(request.getFilePath()).openStream() : new java.io.FileInputStream(request.getFilePath())) { - return parseAndMapExcel(request, inputStream); + return parseAndMapExcel(request, inputStream, userId); } catch (IOException e) { result.setSummary("读取文件失败: " + e.getMessage()); return result; } } - private FishImportResult parseSheet(Sheet sheet, FishImportResult result) { + private FishImportResult parseSheet(Sheet sheet, FishImportResult result, String uploadUserId) { loadStationAndBaseCache(); Row headerRow = sheet.getRow(0); @@ -167,7 +183,7 @@ public class FishImportServiceImpl implements IFishImportService { continue; } - FishImportResult.FishImportRow importRow = parseRow(result, row, columnIndexMap, i); + FishImportResult.FishImportRow importRow = parseRow(result, row, columnIndexMap, i, uploadUserId); result.setTotalCount(result.getTotalCount() + 1); if (importRow.getData() != null && importRow.getWarnings().isEmpty()) { result.addSuccessRow(importRow); @@ -183,10 +199,65 @@ public class FishImportServiceImpl implements IFishImportService { return result; } - private FishImportResult.FishImportRow parseRow(FishImportResult result, Row row, Map columnIndexMap, int rowIndex) { + private FishImportResult.FishImportRow parseRow(FishImportResult result, Row row, Map columnIndexMap, int rowIndex, String userId) { FishImportResult.FishImportRow importRow = new FishImportResult.FishImportRow(rowIndex); FishDraftData data = new FishDraftData(); data.setId(UUID.randomUUID().toString()); + Set allowedHbrvcdSet = new HashSet<>(); + Set directStcdSet = new HashSet<>(); + Set directBHSet = new HashSet<>(); + if (userId != null) { + List permissions = userDataScopeMapper.selectValidPermissions(userId); + if (permissions != null && !permissions.isEmpty()) { + for (SysUserDataScope permission : permissions) { + String orgType = permission.getOrgType(); + String orgId = permission.getOrgId(); + + if (orgId == null || orgId.isEmpty()) { + continue; + } + + if ("HBRVCD".equals(orgType)) { + allowedHbrvcdSet.add(orgId); + } else if ("STATION".equals(orgType)) { + directStcdSet.add(orgId); + } + } + } + } + +// Set allStcdSet = new HashSet<>(); + + if (!allowedHbrvcdSet.isEmpty() || !directStcdSet.isEmpty()) { + if (!allowedHbrvcdSet.isEmpty()) { + List stationsFromHbrv = engInfoBHMapper.selectByHbrvcdList(new ArrayList<>(allowedHbrvcdSet)); + for (SdEngInfoBH station : stationsFromHbrv) { + if (station.getStcd() != null) { + directStcdSet.add(station.getStcd()); + } + } + } + + if (!directStcdSet.isEmpty()) { + List stationsFromStcd = engInfoBHMapper.selectBatchIds(new ArrayList<>(directStcdSet)); + for (SdEngInfoBH station : stationsFromStcd) { + if (station.getStcd() != null) { + directStcdSet.add(station.getStcd()); + } + if (station.getHbrvcd() != null) { + allowedHbrvcdSet.add(station.getHbrvcd()); + } + } + } + } + if (!directStcdSet.isEmpty()) { + List sdFpssBHS = fpssBHMapper.selectList(new LambdaQueryWrapper().in(SdFpssBH::getRstcd, directStcdSet).select(SdFpssBH::getStcd)); + for (SdFpssBH sdFpssBH : sdFpssBHS) { + if (sdFpssBH.getStcd() != null) { + directBHSet.add(sdFpssBH.getStcd()); + } + } + } for (Map.Entry entry : columnIndexMap.entrySet()) { Integer columnIndex = entry.getKey(); String fieldName = entry.getValue(); @@ -205,8 +276,15 @@ public class FishImportServiceImpl implements IFishImportService { importRow.getWarnings().add("rstcd"); data.setEnnm(cellValue.trim()); } else { - data.setEnnm(cellValue.trim()); - data.setRstcd(stcd); + if (directStcdSet.contains(stcd)) { + data.setEnnm(cellValue.trim()); + data.setRstcd(stcd); + } else { + importRow.getWarnings().add("rstcd"); + data.setEnnm(cellValue.trim()); + data.setRstcd(cellValue); + } + } } break; @@ -239,19 +317,26 @@ public class FishImportServiceImpl implements IFishImportService { } break; case "hbrvcd": - if(!StringUtils.hasText(cellValue)){ + if (!StringUtils.hasText(cellValue)) { importRow.getWarnings().add("hbrvcd"); data.setHbrvcd(cellValue); data.setHbrvnm(cellValue); - }else{ + } else { String hbrvcdCode = resolveHbrvcdCode(cellValue.trim()); if (hbrvcdCode == null) { importRow.getWarnings().add("hbrvcd"); data.setHbrvcd(cellValue.trim()); data.setHbrvnm(cellValue.trim()); - }else{ - data.setHbrvcd(hbrvcdCode); - data.setHbrvnm(cellValue.trim()); + } else { + if (allowedHbrvcdSet.contains(hbrvcdCode)) { + data.setHbrvcd(hbrvcdCode); + data.setHbrvnm(cellValue.trim()); + } else { + importRow.getWarnings().add("hbrvcd"); + data.setHbrvcd(cellValue.trim()); + data.setHbrvnm(cellValue.trim()); + } + } } // if (StringUtils.hasText(cellValue)) { @@ -419,8 +504,15 @@ public class FishImportServiceImpl implements IFishImportService { data.setStcd(cellValue.trim()); data.setStnm(cellValue.trim()); } else { - data.setStnm(cellValue.trim()); - data.setStcd(stcd); + if (directBHSet.contains(stcd)) { + data.setStnm(cellValue.trim()); + data.setStcd(stcd); + } else { + importRow.getWarnings().add("stcd"); + data.setStcd(cellValue.trim()); + data.setStnm(cellValue.trim()); + } + } } break; @@ -468,8 +560,65 @@ public class FishImportServiceImpl implements IFishImportService { } private void loadStationAndBaseCache() { +// String userId = SecurityUtils.getUserId(); +// Set allowedHbrvcdSet = new HashSet<>(); +// Set directStcdSet = new HashSet<>(); +// +// if (userId != null) { +// List permissions = userDataScopeMapper.selectValidPermissions(userId); +// if (permissions != null && !permissions.isEmpty()) { +// for (SysUserDataScope permission : permissions) { +// String orgType = permission.getOrgType(); +// String orgId = permission.getOrgId(); +// +// if (orgId == null || orgId.isEmpty()) { +// continue; +// } +// +// if ("HBRVCD".equals(orgType)) { +// allowedHbrvcdSet.add(orgId); +// } else if ("STATION".equals(orgType)) { +// directStcdSet.add(orgId); +// } +// } +// } +// } +// +// Set allStcdSet = new HashSet<>(); +// +// if (!allowedHbrvcdSet.isEmpty() || !directStcdSet.isEmpty()) { +// if (!allowedHbrvcdSet.isEmpty()) { +// List stationsFromHbrv = engInfoBHMapper.selectByHbrvcdList(new ArrayList<>(allowedHbrvcdSet)); +// for (SdEngInfoBH station : stationsFromHbrv) { +// if (station.getStcd() != null) { +// allStcdSet.add(station.getStcd()); +// } +// } +// } +// +// if (!directStcdSet.isEmpty()) { +// List stationsFromStcd = engInfoBHMapper.selectBatchIds(new ArrayList<>(directStcdSet)); +// for (SdEngInfoBH station : stationsFromStcd) { +// if (station.getStcd() != null) { +// allStcdSet.add(station.getStcd()); +// } +// if (station.getHbrvcd() != null) { +// allowedHbrvcdSet.add(station.getHbrvcd()); +// } +// } +// } +// } + if (STATION_NAME_CACHE.isEmpty()) { List stationList = engInfoBHMapper.selectList(null); +// if (!allStcdSet.isEmpty()) { +// stationList = engInfoBHMapper.selectBatchIds(new ArrayList<>(allStcdSet)); +// } else if("admin".equals(SecurityUtils.getCurrentUsername())){ +// +// }else { +// stationList = new ArrayList<>(); +// } + for (SdEngInfoBH station : stationList) { if (StringUtils.hasText(station.getEnnm())) { STATION_NAME_CACHE.put(station.getEnnm().trim().toLowerCase(), station.getStcd()); @@ -478,7 +627,7 @@ public class FishImportServiceImpl implements IFishImportService { if (StringUtils.hasText(station.getEnnm())) { STATION_CODE_TO_NAME_CACHE.put(station.getStcd().trim().toLowerCase(), station.getEnnm().trim().toLowerCase()); } - if (StringUtils.hasText(station.getBaseId())) { + if (StringUtils.hasText(station.getHbrvcd())) { STATION_TO_BASE_CACHE.put(station.getStcd().trim().toLowerCase(), station.getHbrvcd()); } } @@ -515,6 +664,13 @@ public class FishImportServiceImpl implements IFishImportService { if (HBRVCD_NAME_CACHE.isEmpty()) { List riverList = sdHbrvDicMapper.selectList(null); +// if (!allowedHbrvcdSet.isEmpty()) { +// LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); +// wrapper.in(SdHbrvDic::getHbrvcd, allowedHbrvcdSet); +// riverList = sdHbrvDicMapper.selectList(wrapper); +// } else { +// riverList = sdHbrvDicMapper.selectList(null); +// } for (SdHbrvDic river : riverList) { if (StringUtils.hasText(river.getHbrvnm())) { HBRVCD_NAME_CACHE.put(river.getHbrvnm().trim().toLowerCase(), river.getHbrvcd()); @@ -543,6 +699,11 @@ public class FishImportServiceImpl implements IFishImportService { if (FPSS_BH_CACHE.isEmpty()) { List sdFpssBHS = fpssBHMapper.selectList(null); +// if (!allStcdSet.isEmpty()) { +// sdFpssBHS = fpssBHMapper.selectList(new LambdaQueryWrapper().in(SdFpssBH::getStcd, allStcdSet)); +// } else { +// sdFpssBHS = fpssBHMapper.selectList(null); +// } for (SdFpssBH sdFpssBH : sdFpssBHS) { if (StringUtils.hasText(sdFpssBH.getStnm())) { FPSS_BH_CACHE.put(sdFpssBH.getStnm().trim().toLowerCase(), sdFpssBH.getStcd()); @@ -1046,7 +1207,7 @@ public class FishImportServiceImpl implements IFishImportService { result.setVideoFiles(zipContent.videos); try (Workbook workbook = new XSSFWorkbook(new FileInputStream(zipContent.excelFilePath))) { Sheet sheet = workbook.getSheetAt(0); - result = parseSheet(sheet, result); + result = parseSheet(sheet, result, uploadUserId); } result.setExcelFileName(zipContent.excelFileName); result.setExcelFilePath(zipContent.excelFilePath); @@ -1069,6 +1230,44 @@ public class FishImportServiceImpl implements IFishImportService { } } + @Override + public FishImportResult parseAndMapZipFromFile(File zipFile, String tempDir, String uploadUserId) { + FishImportResult result = new FishImportResult(); + + try { + log.info("开始异步解析ZIP文件..."); + ZipFileUtil.ZipContent zipContent = ZipFileUtil.extractFromSavedZipFile(zipFile, tempDir); + + if (zipContent.excelFilePath == null) { + result.setSummary("ZIP文件中未找到Excel文件"); + result.setCode("1"); + result.setMessage("ZIP文件中未找到Excel文件"); + 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, uploadUserId); + } + result.setExcelFileName(zipContent.excelFileName); + result.setExcelFilePath(zipContent.excelFilePath); + log.info("ZIP文件异步解析完成"); + result.setSummary(result.getSummary() + String.format("\nZIP内容: 发现%d张图片, %d个视频", + zipContent.images.size(), zipContent.videos.size())); + + return result; + + } catch (Exception e) { + log.error("ZIP文件异步解析失败", e); + result.setSummary("ZIP文件解析失败: " + e.getMessage()); + result.setCode("1"); + result.setMessage("ZIP文件解析失败"); + return result; + } + } + @Override public void processAttachments(FishImportResult result, ZipFileUtil.ZipContent zipContent) { for (FishImportResult.FishImportRow importRow : result.getRows()) { @@ -1092,6 +1291,118 @@ public class FishImportServiceImpl implements IFishImportService { } } + @Override + public void processAttachmentsAsync(List dataList, + Map imageFiles, + Map videoFiles, + String tempDir) { + if (dataList == null || dataList.isEmpty()) { + return; + } + List> futures = new ArrayList<>(); + SecurityContext securityContext = SecurityContextHolder.getContext(); + for (FishDraftData data : dataList) { + CompletableFuture future = CompletableFuture.runAsync(() -> { + try { + SecurityContextHolder.setContext(securityContext); + String vdpth = data.getVdpth(); + String picpth = data.getPicpth(); + + if(StrUtil.isBlank(vdpth)||StrUtil.isBlank(picpth)){ + log.error("数据不完整, 忽略处理"); + return; + } + if (StringUtils.hasText(vdpth) && videoFiles != null && !videoFiles.isEmpty()) { + String uploadedVdpth = uploadVideoFilesAsync(vdpth, videoFiles); + if (uploadedVdpth != null) { + data.setVdpth(uploadedVdpth); + } + } + + if (StringUtils.hasText(picpth) && imageFiles != null && !imageFiles.isEmpty()) { + String uploadedPicpth = uploadImageFilesAsync(picpth, imageFiles); + if (uploadedPicpth != null) { + data.setPicpth(uploadedPicpth); + } + } + + fishDraftDataService.updateById(data); + log.info("异步上传附件完成, dataId: {},{},{}", data.getId(), data.getPicpth(), data.getVdpth()); + } catch (Exception e) { + log.error("异步上传附件失败, dataId: {}", data.getId(), e); + } finally { + SecurityContextHolder.clearContext(); + } + }); + futures.add(future); + } + CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])) + .thenRun(() -> { + + try { + // del 方法会递归删除目录及其所有内容 + FileUtil.del(tempDir); + } catch (Exception e) { + log.error("删除临时目录失败{}", e.getMessage()); + } + + }) + .exceptionally(ex -> { + log.error("等待异步任务完成时发生异常", ex); + return null; + }); + } + + private String uploadVideoFilesAsync(String videoNames, Map videoMap) { + String[] fileNames = videoNames.split(";"); + List attachmentIds = new ArrayList<>(); + + for (String fileName : fileNames) { + fileName = fileName.trim(); + if (fileName.isEmpty()) { + continue; + } + String actualPath = findFilePath(fileName, videoMap); + if (actualPath != null) { + try { + String attachmentId = attachmentUploadService.uploadFileAndGetId(actualPath); + if (attachmentId != null) { + attachmentIds.add(attachmentId); + } + } catch (Exception e) { + log.error("上传视频失败: {}", fileName, e); + } + } + } + + return attachmentIds.isEmpty() ? videoNames : String.join(",", attachmentIds); + } + + private String uploadImageFilesAsync(String imageNames, Map imageMap) { + String[] fileNames = imageNames.split(";"); + List attachmentIds = new ArrayList<>(); + + for (String fileName : fileNames) { + fileName = fileName.trim(); + if (fileName.isEmpty()) { + continue; + } + String actualPath = findFilePath(fileName, imageMap); + if (actualPath != null) { + try { + String attachmentId = attachmentUploadService.uploadFileAndGetId(actualPath); + if (attachmentId != null) { + attachmentIds.add(attachmentId); + } + } catch (Exception e) { + log.error("上传图片失败: {}", fileName, e); + } + } + } + + return attachmentIds.isEmpty() ? imageNames : String.join(",", attachmentIds); + } + private String processVideoAttachments(FishImportResult.FishImportRow importRow, String videoNames, Map videoMap) { if (videoNames == null || videoNames.isEmpty() || videoMap == null || videoMap.isEmpty()) { return videoNames; @@ -1110,7 +1421,9 @@ public class FishImportServiceImpl implements IFishImportService { fileMap.put("name", fileName); if (actualPath != null) { try { + log.info("开始上传视频文件: {}", actualPath); String attachmentId = attachmentUploadService.uploadFileAndGetId(actualPath); + log.info("开始上传视频文件后:{}attachmentId{} ", actualPath, attachmentId); if (attachmentId != null) { attachmentIds.add(attachmentId); fileMap.put("value", attachmentId); @@ -1150,7 +1463,9 @@ public class FishImportServiceImpl implements IFishImportService { String actualPath = findFilePath(fileName, imageMap); if (actualPath != null) { try { + log.info("开始上传图片文件: {}", actualPath); String attachmentId = attachmentUploadService.uploadFileAndGetId(actualPath); + log.info("开始上传图片文件后:{}attachmentId{} ", actualPath, attachmentId); if (attachmentId != null) { attachmentIds.add(attachmentId); fileMap.put("value", attachmentId); diff --git a/backend/src/main/java/com/yfd/platform/data/service/impl/ImportTaskServiceImpl.java b/backend/src/main/java/com/yfd/platform/data/service/impl/ImportTaskServiceImpl.java index 396b213..c8cb5f6 100644 --- a/backend/src/main/java/com/yfd/platform/data/service/impl/ImportTaskServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/data/service/impl/ImportTaskServiceImpl.java @@ -12,12 +12,14 @@ import com.yfd.platform.data.mapper.ImportTaskMapper; import com.yfd.platform.data.service.AttachmentUploadService; import com.yfd.platform.data.service.IImportTaskService; import jakarta.annotation.Resource; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; import java.util.Date; import java.util.List; +import java.util.concurrent.CompletableFuture; /** *

@@ -81,12 +83,13 @@ public class ImportTaskServiceImpl extends ServiceImpl activeStatuses = List.of("UPLOADED", "PARSING", "VALIDATING"); - List tasks = importTaskMapper.selectByUserIdAndStatuses(uploadUserId, activeStatuses); +// List activeStatuses = List.of("UPLOADED", "PARSING", "VALIDATING"); + List tasks = importTaskMapper.selectByUserIdAndStatuses(uploadUserId); return tasks != null && !tasks.isEmpty(); } @@ -182,30 +172,20 @@ public class ImportTaskServiceImpl extends ServiceImpl fileIds = StrUtil.split(vdpth, ","); - fileIds.forEach(fileId -> attachmentUploadService.deleteFile(fileId)); - } - String picpth = successRow.getData().getPicpth(); - if (StringUtils.hasText(picpth)) { - List fileIds = StrUtil.split(vdpth, ","); - fileIds.forEach(fileId -> attachmentUploadService.deleteFile(fileId)); - } + String temp = importTask.getTempDir(); + if (StrUtil.isNotBlank( temp)) { + FileUtil.del(temp); + }else{ + if (importTask.getResultJson() != null && !importTask.getResultJson().isEmpty()) { + try { + FishImportResult importResult = objectMapper.readValue(importTask.getResultJson(), FishImportResult.class); + String tempDir = importResult.getTempDir(); + // del 方法会递归删除目录及其所有内容 + FileUtil.del(tempDir); + } catch (Exception e) { + e.printStackTrace(); + // ignore parse error } - String tempDir = importResult.getTempDir(); - // del 方法会递归删除目录及其所有内容 - FileUtil.del(tempDir); - } catch (Exception e) { - e.printStackTrace(); - // ignore parse error } } importTask.setStatus("CANCELLED"); @@ -216,8 +196,8 @@ public class ImportTaskServiceImpl extends ServiceImpl activeStatuses = List.of("UPLOADED", "PARSING", "VALIDATED"); - List tasks = importTaskMapper.selectByUserIdAndStatuses(uploadUserId, activeStatuses); +// List activeStatuses = List.of("UPLOADED", "PARSING", "VALIDATED"); + List tasks = importTaskMapper.selectByUserIdAndStatuses(uploadUserId); if (tasks == null || tasks.isEmpty()) { return null; } diff --git a/backend/src/main/java/com/yfd/platform/data/utils/ZipFileUtil.java b/backend/src/main/java/com/yfd/platform/data/utils/ZipFileUtil.java index 30fedc3..662fb4b 100644 --- a/backend/src/main/java/com/yfd/platform/data/utils/ZipFileUtil.java +++ b/backend/src/main/java/com/yfd/platform/data/utils/ZipFileUtil.java @@ -73,6 +73,55 @@ public class ZipFileUtil { return extractZipToTemp(file, getDefaultTempDir()); } +// public static ZipContent extractZipToTemp(MultipartFile file, String baseTempDir) throws IOException { +// ZipContent content = new ZipContent(); +// +// String taskId = UUID.randomUUID().toString().substring(0, 8); +// Path tempDirPath = Paths.get(baseTempDir, "zip_" + taskId); +// +// log.info("extractZipToTemp: {}", tempDirPath); +// Files.createDirectories(tempDirPath); +// content.tempDir = tempDirPath.toString(); +// File zipFile = new File(tempDirPath.toFile(), "upload.zip"); +// file.transferTo(zipFile); +// +// try { +// log.info("--------------isValidZipFile------------"); +// if (!isValidZipFile(zipFile)) { +// log.info("--------------文件不是有效的ZIP格式或已损坏------------"); +// throw new IOException("文件不是有效的ZIP格式或已损坏"); +// } +// +// IOException lastException = null; +// Charset[] charsets = new Charset[]{ +// StandardCharsets.UTF_8, +// Charset.forName("GBK"), +// StandardCharsets.ISO_8859_1, +// Charset.forName("GB18030") +// }; +// +// for (Charset charset : charsets) { +// try { +// content = extractFromZipFile(zipFile, tempDirPath.toFile(), charset); +// content.tempDir = tempDirPath.toString(); +// return content; +// } catch (IOException e) { +// lastException = e; +// content = new ZipContent(); +// content.tempDir = tempDirPath.toString(); +// } +// } +// +// log.error("extractZipToTemp: {}", lastException.getMessage()); +// throw lastException != null ? lastException : new IOException("无法解析ZIP文件"); +// +// } finally { +// if (zipFile.exists()) { +// zipFile.delete(); +// } +// } +// } + public static ZipContent extractZipToTemp(MultipartFile file, String baseTempDir) throws IOException { ZipContent content = new ZipContent(); @@ -86,35 +135,7 @@ public class ZipFileUtil { file.transferTo(zipFile); try { - log.info("--------------isValidZipFile------------"); - if (!isValidZipFile(zipFile)) { - log.info("--------------文件不是有效的ZIP格式或已损坏------------"); - throw new IOException("文件不是有效的ZIP格式或已损坏"); - } - - IOException lastException = null; - Charset[] charsets = new Charset[]{ - StandardCharsets.UTF_8, - Charset.forName("GBK"), - StandardCharsets.ISO_8859_1, - Charset.forName("GB18030") - }; - - for (Charset charset : charsets) { - try { - content = extractFromZipFile(zipFile, tempDirPath.toFile(), charset); - content.tempDir = tempDirPath.toString(); - return content; - } catch (IOException e) { - lastException = e; - content = new ZipContent(); - content.tempDir = tempDirPath.toString(); - } - } - - log.error("extractZipToTemp: {}", lastException.getMessage()); - throw lastException != null ? lastException : new IOException("无法解析ZIP文件"); - + return extractFromSavedZipFile(zipFile, tempDirPath.toString()); } finally { if (zipFile.exists()) { zipFile.delete(); @@ -122,6 +143,35 @@ public class ZipFileUtil { } } + public static ZipContent extractFromSavedZipFile(File zipFile, String tempDir) throws IOException { + if (!isValidZipFile(zipFile)) { + log.info("--------------文件不是有效的ZIP格式或已损坏------------"); + throw new IOException("文件不是有效的ZIP格式或已损坏"); + } + + IOException lastException = null; + Charset[] charsets = new Charset[]{ + StandardCharsets.UTF_8, + Charset.forName("GBK"), + StandardCharsets.ISO_8859_1, + Charset.forName("GB18030") + }; + + for (Charset charset : charsets) { + try { + ZipContent content = extractExcelWithRelatedFiles(zipFile, new File(tempDir), charset); + content.tempDir = tempDir; + return content; + } catch (IOException e) { + lastException = e; + log.warn("使用编码 {} 解析失败: {}", charset, e.getMessage()); + } + } + + log.error("extractFromSavedZipFile: {}", lastException != null ? lastException.getMessage() : "未知错误"); + throw lastException != null ? lastException : new IOException("无法解析ZIP文件"); + } + private static boolean isValidZipFile(File file) { if (file == null || file.length() < 4) { return false; @@ -179,6 +229,134 @@ public class ZipFileUtil { return content; } + + private static ZipContent extractExcelWithRelatedFiles(File zipFile, File tempDir, Charset charset) throws IOException { + ZipContent content = new ZipContent(); + + try (ZipFile zip = new ZipFile(zipFile, charset)) { + Enumeration entries = zip.entries(); + + String excelEntryName = null; + String excelParentPath = null; + + while (entries.hasMoreElements()) { + ZipEntry entry = entries.nextElement(); + String entryName = entry.getName(); + + if (entry.isDirectory()) { + continue; + } + + String lowerName = entryName.toLowerCase(); + if ((lowerName.endsWith(".xlsx") || lowerName.endsWith(".xls")) && excelEntryName == null) { + excelEntryName = entryName; + excelParentPath = getParentDirectory(entryName); + log.info("找到Excel文件: {}, 所在目录: {}", excelEntryName, excelParentPath); + break; + } + } + + if (excelEntryName == null) { + throw new IOException("ZIP文件中未找到Excel文件(.xlsx或.xls)"); + } + + entries = zip.entries(); + int excelCount = 0; + int imageCount = 0; + int videoCount = 0; + + while (entries.hasMoreElements()) { + ZipEntry entry = entries.nextElement(); + String entryName = entry.getName(); + + if (entry.isDirectory()) { + continue; + } + + String entryParentPath = getParentDirectory(entryName); + String fileName = getFileName(entryName); + String lowerName = entryName.toLowerCase(); + + boolean shouldExtract = false; + String targetSubFolder = ""; + + if (lowerName.endsWith(".xlsx") || lowerName.endsWith(".xls")) { + if (excelParentPath.equals(entryParentPath)) { + shouldExtract = true; + targetSubFolder = ""; + } + } else if (isInSubDirectory(entryParentPath, excelParentPath, "images")) { + if (isImageFile(lowerName)) { + shouldExtract = true; + targetSubFolder = "images"; + } + } else if (isInSubDirectory(entryParentPath, excelParentPath, "videos")) { + if (isVideoFile(lowerName)) { + shouldExtract = true; + targetSubFolder = "videos"; + } + } + + if (shouldExtract) { + try (InputStream is = zip.getInputStream(entry)) { + String filePath = saveFileToDir(is, tempDir, targetSubFolder, fileName); + + if (targetSubFolder.isEmpty()) { + if (content.excelFilePath == null) { + content.excelFileName = fileName; + content.excelFilePath = filePath; + excelCount++; + log.info("提取Excel文件: {}", fileName); + } + } else if ("images".equals(targetSubFolder)) { + content.images.put(fileName, filePath); + imageCount++; + log.debug("提取图片文件: {}", fileName); + } else if ("videos".equals(targetSubFolder)) { + content.videos.put(fileName, filePath); + videoCount++; + log.debug("提取视频文件: {}", fileName); + } + } + } + } + + if (content.excelFilePath == null) { + throw new IOException("未能提取到Excel文件"); + } + + log.info("提取完成 - Excel: {}个, 图片: {}个, 视频: {}个", + excelCount, imageCount, videoCount); + } + + return content; + } + + private static String getParentDirectory(String entryName) { + if (entryName == null || entryName.isEmpty()) { + return ""; + } + int lastSep = Math.max(entryName.lastIndexOf('/'), entryName.lastIndexOf('\\')); + if (lastSep >= 0) { + return entryName.substring(0, lastSep); + } + return ""; + } + + private static boolean isInSubDirectory(String entryParentPath, String excelParentPath, String subFolder) { + String expectedPath; + if (excelParentPath.isEmpty()) { + expectedPath = subFolder; + } else { + expectedPath = excelParentPath + "/" + subFolder; + } + + String normalizedEntryPath = entryParentPath.replace("\\", "/"); + String normalizedExpectedPath = expectedPath.replace("\\", "/"); + + return normalizedEntryPath.equalsIgnoreCase(normalizedExpectedPath); + } + private static String getFileName(String entryName) { if (entryName == null) return ""; int lastSep = Math.max(entryName.lastIndexOf('/'), entryName.lastIndexOf('\\')); diff --git a/backend/src/main/java/com/yfd/platform/env/controller/FpssRController.java b/backend/src/main/java/com/yfd/platform/env/controller/FpssRController.java new file mode 100644 index 0000000..a631024 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/controller/FpssRController.java @@ -0,0 +1,80 @@ +package com.yfd.platform.env.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.env.domain.SdFpssR; +import com.yfd.platform.env.service.ISdFpssRService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.*; + +/** + *

+ * 过鱼设施人工数据表 前端控制器 + *

+ */ +@RestController +@RequestMapping("/data/fpssR") +@Tag(name = "过鱼数据管理") +public class FpssRController { + + @Resource + private ISdFpssRService fpssRService; + + @GetMapping("/page") + @Operation(summary = "分页查询过鱼数据列表") + public ResponseResult queryPageList( + @RequestParam(defaultValue = "1") Integer current, + @RequestParam(defaultValue = "10") Integer size, + @RequestParam(required = false) String stcd, + @RequestParam(required = false) Integer yr, + @RequestParam(required = false) String ftp) { + Page page = new Page<>(current, size); + Page result = fpssRService.queryPageList(page, stcd, yr, ftp); + return ResponseResult.successData(result); + } + + @GetMapping("/getById") + @Operation(summary = "根据ID查询过鱼数据") + public ResponseResult getById(@RequestParam String id) { + SdFpssR fpssR = fpssRService.getById(id); + return ResponseResult.successData(fpssR); + } + + @PostMapping("/add") + @Operation(summary = "新增过鱼数据") + public ResponseResult add(@RequestBody SdFpssR fpssR) { + boolean result = fpssRService.save(fpssR); + return result ? ResponseResult.success("新增成功") : ResponseResult.error("新增失败"); + } + + @PostMapping("/update") + @Operation(summary = "修改过鱼数据") + public ResponseResult update(@RequestBody SdFpssR fpssR) { + boolean result = fpssRService.updateById(fpssR); + return result ? ResponseResult.success("修改成功") : ResponseResult.error("修改失败"); + } + + @PostMapping("/delete") + @Operation(summary = "删除过鱼数据") + public ResponseResult delete(@RequestParam String id) { + boolean result = fpssRService.removeById(id); + return result ? ResponseResult.success("删除成功") : ResponseResult.error("删除失败"); + } + + @PostMapping("/batchDelete") + @Operation(summary = "批量删除过鱼数据") + public ResponseResult batchDelete(@RequestBody java.util.List ids) { + if (ids == null || ids.isEmpty()) { + return ResponseResult.error("请选择要删除的数据"); + } + boolean result = true; + for (String id : ids) { + if (!fpssRService.removeById(id)) { + result = false; + } + } + return result ? ResponseResult.success("删除成功") : ResponseResult.error("部分删除失败"); + } +} \ No newline at end of file diff --git a/backend/src/main/java/com/yfd/platform/env/controller/SdFpssBHController.java b/backend/src/main/java/com/yfd/platform/env/controller/SdFpssBHController.java index ef18bfe..f56fb92 100644 --- a/backend/src/main/java/com/yfd/platform/env/controller/SdFpssBHController.java +++ b/backend/src/main/java/com/yfd/platform/env/controller/SdFpssBHController.java @@ -61,9 +61,8 @@ public class SdFpssBHController { @Operation(summary = "设施下拉列表(根据电站编码筛选 + 支持名称模糊搜索 + 支持基地编码筛选)") public ResponseResult dropdown(@RequestParam(required = false) String rstcd, @RequestParam(required = false) String stnm, - @RequestParam(required = false) String baseId, - @RequestParam(required = false) String hbrvcd) { - return ResponseResult.successData(sdFpssBHService.selectForDropdown(rstcd, stnm, baseId,hbrvcd)); + @RequestParam(required = false) String baseId) { + return ResponseResult.successData(sdFpssBHService.selectForDropdown(rstcd, stnm, baseId)); } @Log(module = "过鱼设施管理", value = "新增过鱼设施") diff --git a/backend/src/main/java/com/yfd/platform/env/domain/SdFpssR.java b/backend/src/main/java/com/yfd/platform/env/domain/SdFpssR.java new file mode 100644 index 0000000..a6baecd --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/domain/SdFpssR.java @@ -0,0 +1,144 @@ +package com.yfd.platform.env.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + *

+ * 过鱼设施人工数据表 + *

+ */ +@Data +@TableName("SD_FPSS_R") +public class SdFpssR implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键ID + */ + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + /** + * 过鱼设施编码 + */ + private String stcd; + + /** + * 填报时间 + */ + private Date tm; + + /** + * 鱼种类 + */ + private String ftp; + + /** + * 鱼类规格,单位:cm + */ + private String fsz; + + /** + * 过鱼数量,单位:尾 + */ + private Integer fcnt; + + /** + * 平均体重,单位:g + */ + private String fwet; + + /** + * 开始日期 + */ + private Date strdt; + + /** + * 结束日期 + */ + private Date enddt; + + /** + * 游向:0=上行,1=下行,2=上行折返,3=下行折返 + */ + private Integer direction; + + /** + * 当日运行次数 + */ + private Integer rcnt; + + /** + * 过鱼设施引用流量 + */ + private BigDecimal fq; + + /** + * 过鱼图片文件路径 + */ + private String picpth; + + /** + * 过鱼视频文件路径 + */ + private String vdpth; + + /** + * 年份:数据时间,精确到年 + */ + private Integer yr; + + /** + * 主要月份 + */ + private String mouth; + + /** + * 创建人 + */ + private String recordUser; + + /** + * 创建时间 + */ + private Date recordTime; + + /** + * 更新人 + */ + private String modifyUser; + + /** + * 更新时间 + */ + private Date modifyTime; + + /** + * 是否已删除:0=未删除 1=已删除 + */ + private Integer isDeleted; + + /** + * 删除人 + */ + private String deleteUser; + + /** + * 删除时间 + */ + private Date deleteTime; + + /** + * 是否鱼苗(0否 1是) + */ + private Integer isfs; + +} \ No newline at end of file diff --git a/backend/src/main/java/com/yfd/platform/env/mapper/SdFpssBHMapper.java b/backend/src/main/java/com/yfd/platform/env/mapper/SdFpssBHMapper.java index 9e13625..08c53fa 100644 --- a/backend/src/main/java/com/yfd/platform/env/mapper/SdFpssBHMapper.java +++ b/backend/src/main/java/com/yfd/platform/env/mapper/SdFpssBHMapper.java @@ -16,13 +16,11 @@ public interface SdFpssBHMapper extends BaseMapper { "LEFT JOIN SD_ENGINFO_B_H E ON F.RSTCD = E.STCD " + "WHERE 1=1 " + " AND E.BASE_ID = #{baseId} " + - " AND E.HBRVCD = #{hbrvcd} " + " AND F.RSTCD = #{rstcd} " + " AND F.STNM LIKE '%' || #{stnm} || '%' " + "ORDER BY F.ORDER_INDEX DESC" + "") List selectForDropdownWithBaseId(@Param("rstcd") String rstcd, @Param("stnm") String stnm, - @Param("baseId") String baseId, - @Param("hbrvcd") String hbrvcd); + @Param("baseId") String baseId); } \ No newline at end of file diff --git a/backend/src/main/java/com/yfd/platform/env/mapper/SdFpssRMapper.java b/backend/src/main/java/com/yfd/platform/env/mapper/SdFpssRMapper.java new file mode 100644 index 0000000..9a32050 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/mapper/SdFpssRMapper.java @@ -0,0 +1,14 @@ +package com.yfd.platform.env.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.yfd.platform.env.domain.SdFpssR; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 过鱼设施人工数据表 Mapper 接口 + *

+ */ +@Mapper +public interface SdFpssRMapper extends BaseMapper { +} \ No newline at end of file diff --git a/backend/src/main/java/com/yfd/platform/env/service/ISdFpssBHService.java b/backend/src/main/java/com/yfd/platform/env/service/ISdFpssBHService.java index df2d231..7b37c27 100644 --- a/backend/src/main/java/com/yfd/platform/env/service/ISdFpssBHService.java +++ b/backend/src/main/java/com/yfd/platform/env/service/ISdFpssBHService.java @@ -16,7 +16,7 @@ public interface ISdFpssBHService extends IService { /** * 设施下拉列表(根据电站编码筛选 + 支持名称模糊搜索 + 支持基地编码筛选) */ - List selectForDropdown(String rstcd, String stnm, String baseId,String hbrvcd); + List selectForDropdown(String rstcd, String stnm, String baseId); Set getUserAuthorizedStationCodes(); diff --git a/backend/src/main/java/com/yfd/platform/env/service/ISdFpssRService.java b/backend/src/main/java/com/yfd/platform/env/service/ISdFpssRService.java new file mode 100644 index 0000000..eed22d3 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/service/ISdFpssRService.java @@ -0,0 +1,18 @@ +package com.yfd.platform.env.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.yfd.platform.env.domain.SdFpssR; + +/** + *

+ * 过鱼设施人工数据表 服务类 + *

+ */ +public interface ISdFpssRService extends IService { + + /** + * 分页查询过鱼数据 + */ + Page queryPageList(Page page, String stcd, Integer yr, String ftp); +} \ No newline at end of file diff --git a/backend/src/main/java/com/yfd/platform/env/service/impl/SdEngInfoBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/env/service/impl/SdEngInfoBHServiceImpl.java index 55f361a..9d68ba5 100644 --- a/backend/src/main/java/com/yfd/platform/env/service/impl/SdEngInfoBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/env/service/impl/SdEngInfoBHServiceImpl.java @@ -46,6 +46,8 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl authorizedStations = getUserAuthorizedStationCodes(); if (authorizedStations != null && !authorizedStations.isEmpty()) { wrapper.in(SdEngInfoBH::getStcd, authorizedStations); + }else if (!"admin".equals(SecurityUtils.getCurrentUsername())){ + return page; } return this.page(page, wrapper); } @@ -68,10 +70,10 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl selectForDropdown(SdEngInfoBHRequest sdEngInfoBHRequest) { String baseId = sdEngInfoBHRequest.getBaseId(); + String hbrvcd = sdEngInfoBHRequest.getHbrvcd(); String ennm = sdEngInfoBHRequest.getEnnm(); List rvcds = sdEngInfoBHRequest.getRvcds(); List hbrvcds = sdEngInfoBHRequest.getHbrvcds(); - String hbrvcd = sdEngInfoBHRequest.getHbrvcd(); LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(StringUtils.hasText(baseId), SdEngInfoBH::getBaseId, baseId) .eq(StringUtils.hasText(hbrvcd), SdEngInfoBH::getHbrvcd, hbrvcd) @@ -84,10 +86,9 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl authorizedStations = getUserAuthorizedStationCodes(); if (authorizedStations != null && !authorizedStations.isEmpty()) { wrapper.in(SdEngInfoBH::getStcd, authorizedStations); + } else if (!"admin".equals(SecurityUtils.getCurrentUsername())){ + return new ArrayList<>(); } -// else { -// return new ArrayList<>(); -// } return this.list(wrapper); } @@ -105,17 +106,38 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl(); } + Set stationCodes = new HashSet<>(); - List basinCodes = new ArrayList<>(); + Set basinCodes = new HashSet<>(); for (SysUserDataScope scope : sysUserDataScopes) { String orgType = scope.getOrgType(); String orgId = scope.getOrgId(); if ("STATION".equals(orgType)) { - stationCodes.add(orgId); + SdEngInfoBH station = engInfoBHMapper.selectById(orgId); + if (station != null) { + if (station.getHbrvcd() != null) { + basinCodes.add(station.getHbrvcd()); + } + if (station.getStcd() != null) { + stationCodes.add(station.getStcd()); + } + + } } else if ("HBRVCD".equals(orgType)) { - basinCodes.add(orgId); + List stationList = engInfoBHMapper.selectByHbrvcd(orgId); + if (stationList != null) { + for (SdEngInfoBH station : stationList) { + if (station.getStcd() != null) { + stationCodes.add(station.getStcd()); + } + if (station.getEnnm() != null) { + basinCodes.add(station.getHbrvcd()); + } + } + } + } } @@ -155,10 +177,12 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl selectRegDropdown(SdEngInfoBHRequest sdEngInfoBHRequest) { String baseId = sdEngInfoBHRequest.getBaseId(); String ennm = sdEngInfoBHRequest.getEnnm(); + String hbrvcd = sdEngInfoBHRequest.getHbrvcd(); List rvcds = sdEngInfoBHRequest.getRvcds(); List hbrvcds = sdEngInfoBHRequest.getHbrvcds(); LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(StringUtils.hasText(baseId), SdEngInfoBH::getBaseId, baseId) + .eq(StringUtils.hasText(hbrvcd), SdEngInfoBH::getHbrvcd, hbrvcd) .in(rvcds != null && !rvcds.isEmpty(), SdEngInfoBH::getRvcd, rvcds) .in(hbrvcds != null && !hbrvcds.isEmpty(), SdEngInfoBH::getHbrvcd, hbrvcds) .like(StringUtils.hasText(ennm), SdEngInfoBH::getEnnm, ennm) diff --git a/backend/src/main/java/com/yfd/platform/env/service/impl/SdFpssBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/env/service/impl/SdFpssBHServiceImpl.java index d08ffcd..036578e 100644 --- a/backend/src/main/java/com/yfd/platform/env/service/impl/SdFpssBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/env/service/impl/SdFpssBHServiceImpl.java @@ -50,6 +50,8 @@ public class SdFpssBHServiceImpl extends ServiceImpl i Set authorizedStations = getUserAuthorizedStationCodes(); if (authorizedStations != null && !authorizedStations.isEmpty()) { wrapper.in(SdFpssBH::getRstcd, authorizedStations); + }else if (!"admin".equals(SecurityUtils.getCurrentUsername())){ + return page; } wrapper.orderByDesc(SdFpssBH::getOrderIndex); @@ -64,13 +66,13 @@ public class SdFpssBHServiceImpl extends ServiceImpl i } @Override - public List selectForDropdown(String rstcd, String stnm,String baseId, String hbrvcd) { + public List selectForDropdown(String rstcd, String stnm, String baseId) { Set authorizedStations = getUserAuthorizedStationCodes(); List result; - if (StringUtils.hasText(hbrvcd)|| StringUtils.hasText(baseId)) { - result = baseMapper.selectForDropdownWithBaseId(rstcd, stnm, baseId,hbrvcd); + if (StringUtils.hasText(baseId)) { + result = baseMapper.selectForDropdownWithBaseId(rstcd, stnm, baseId); } else { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(StringUtils.hasText(rstcd), SdFpssBH::getRstcd, rstcd) @@ -78,7 +80,7 @@ public class SdFpssBHServiceImpl extends ServiceImpl i .orderByDesc(SdFpssBH::getOrderIndex); result = list(wrapper); } - if (authorizedStations.isEmpty()) { + if (authorizedStations.isEmpty()&&"admin".equals(SecurityUtils.getCurrentUsername())) { return result; } @@ -100,20 +102,40 @@ public class SdFpssBHServiceImpl extends ServiceImpl i return new HashSet<>(); } + Set stationCodes = new HashSet<>(); - List basinCodes = new ArrayList<>(); + Set basinCodes = new HashSet<>(); for (SysUserDataScope scope : sysUserDataScopes) { String orgType = scope.getOrgType(); String orgId = scope.getOrgId(); if ("STATION".equals(orgType)) { - stationCodes.add(orgId); + SdEngInfoBH station = sdEngInfoBHMapper.selectById(orgId); + if (station != null) { + if (station.getHbrvcd() != null) { + basinCodes.add(station.getHbrvcd()); + } + if (station.getStcd() != null) { + stationCodes.add(station.getStcd()); + } + + } } else if ("HBRVCD".equals(orgType)) { - basinCodes.add(orgId); + List stationList = sdEngInfoBHMapper.selectByHbrvcd(orgId); + if (stationList != null) { + for (SdEngInfoBH station : stationList) { + if (station.getStcd() != null) { + stationCodes.add(station.getStcd()); + } + if (station.getEnnm() != null) { + basinCodes.add(station.getHbrvcd()); + } + } + } + } } - if (!stationCodes.isEmpty()) { return stationCodes; } diff --git a/backend/src/main/java/com/yfd/platform/env/service/impl/SdFpssRServiceImpl.java b/backend/src/main/java/com/yfd/platform/env/service/impl/SdFpssRServiceImpl.java new file mode 100644 index 0000000..5483b26 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/service/impl/SdFpssRServiceImpl.java @@ -0,0 +1,64 @@ +package com.yfd.platform.env.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.yfd.platform.env.domain.SdFpssR; +import com.yfd.platform.env.mapper.SdFpssRMapper; +import com.yfd.platform.env.service.ISdFpssRService; +import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; + +import java.util.Date; + +/** + *

+ * 过鱼设施人工数据表 服务实现类 + *

+ */ +@Service +public class SdFpssRServiceImpl extends ServiceImpl implements ISdFpssRService { + + @Override + public Page queryPageList(Page page, String stcd, Integer yr, String ftp) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + + if (StringUtils.hasText(stcd)) { + wrapper.eq(SdFpssR::getStcd, stcd); + } + if (yr != null) { + wrapper.eq(SdFpssR::getYr, yr); + } + if (StringUtils.hasText(ftp)) { + wrapper.like(SdFpssR::getFtp, ftp); + } + + wrapper.eq(SdFpssR::getIsDeleted, 0); + wrapper.orderByDesc(SdFpssR::getRecordTime); + return page(page, wrapper); + } + + @Override + public boolean save(SdFpssR entity) { + entity.setRecordTime(new Date()); + entity.setIsDeleted(0); + return super.save(entity); + } + + @Override + public boolean updateById(SdFpssR entity) { + entity.setModifyTime(new Date()); + return super.updateById(entity); + } + +// @Override +// public boolean removeById(Object id) { +// SdFpssR entity = getById(id); +// if (entity != null) { +// entity.setIsDeleted(1); +// entity.setDeleteTime(new Date()); +// return updateById(entity); +// } +// return false; +// } +} \ No newline at end of file diff --git a/backend/src/main/java/com/yfd/platform/env/service/impl/SdHbrvDicServiceImpl.java b/backend/src/main/java/com/yfd/platform/env/service/impl/SdHbrvDicServiceImpl.java index dac49a8..da19175 100644 --- a/backend/src/main/java/com/yfd/platform/env/service/impl/SdHbrvDicServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/env/service/impl/SdHbrvDicServiceImpl.java @@ -33,6 +33,8 @@ public class SdHbrvDicServiceImpl extends ServiceImpl queryPageList(Page page, String hbrvnm, String baseid) { return this.page(page, this.lambdaQuery() @@ -109,6 +111,8 @@ public class SdHbrvDicServiceImpl extends ServiceImpl(); } + }else if (!"admin".equals(SecurityUtils.getCurrentUsername())){ + return new ArrayList<>(); } wrapper.like(hbrvnm != null && !hbrvnm.isEmpty(), SdHbrvDic::getHbrvnm, hbrvnm) .eq(baseid != null && !baseid.isEmpty(), SdHbrvDic::getBaseid, baseid) @@ -131,16 +135,36 @@ public class SdHbrvDicServiceImpl extends ServiceImpl stationCodes = new HashSet<>(); - List basinCodes = new ArrayList<>(); + Set basinCodes = new HashSet<>(); for (SysUserDataScope scope : sysUserDataScopes) { String orgType = scope.getOrgType(); String orgId = scope.getOrgId(); if ("STATION".equals(orgType)) { - stationCodes.add(orgId); + SdEngInfoBH station = engInfoBHMapper.selectById(orgId); + if (station != null) { + if (station.getHbrvcd() != null) { + basinCodes.add(station.getHbrvcd()); + } + if (station.getStcd() != null) { + stationCodes.add(station.getStcd()); + } + + } } else if ("HBRVCD".equals(orgType)) { - basinCodes.add(orgId); + List stationList = engInfoBHMapper.selectByHbrvcd(orgId); + if (stationList != null) { + for (SdEngInfoBH station : stationList) { + if (station.getStcd() != null) { + stationCodes.add(station.getStcd()); + } + if (station.getEnnm() != null) { + basinCodes.add(station.getHbrvcd()); + } + } + } + } } diff --git a/backend/src/main/java/com/yfd/platform/env/service/impl/SdHydrobaseServiceImpl.java b/backend/src/main/java/com/yfd/platform/env/service/impl/SdHydrobaseServiceImpl.java index 3523a05..1a0b460 100644 --- a/backend/src/main/java/com/yfd/platform/env/service/impl/SdHydrobaseServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/env/service/impl/SdHydrobaseServiceImpl.java @@ -87,6 +87,8 @@ public class SdHydrobaseServiceImpl extends ServiceImpl(); } + }else if (!"admin".equals(SecurityUtils.getCurrentUsername())){ + return new ArrayList<>(); } // else { // return new ArrayList<>(); @@ -109,16 +111,36 @@ public class SdHydrobaseServiceImpl extends ServiceImpl stationCodes = new HashSet<>(); - List basinCodes = new ArrayList<>(); + Set basinCodes = new HashSet<>(); for (SysUserDataScope scope : sysUserDataScopes) { String orgType = scope.getOrgType(); String orgId = scope.getOrgId(); if ("STATION".equals(orgType)) { - stationCodes.add(orgId); + SdEngInfoBH station = sdEngInfoBHMapper.selectById(orgId); + if (station != null) { + if (station.getHbrvcd() != null) { + basinCodes.add(station.getHbrvcd()); + } + if (station.getStcd() != null) { + stationCodes.add(station.getStcd()); + } + + } } else if ("HBRVCD".equals(orgType)) { - basinCodes.add(orgId); + List stationList = sdEngInfoBHMapper.selectByHbrvcd(orgId); + if (stationList != null) { + for (SdEngInfoBH station : stationList) { + if (station.getStcd() != null) { + stationCodes.add(station.getStcd()); + } + if (station.getEnnm() != null) { + basinCodes.add(station.getHbrvcd()); + } + } + } + } } diff --git a/backend/src/main/java/com/yfd/platform/system/controller/LoginController.java b/backend/src/main/java/com/yfd/platform/system/controller/LoginController.java index ac08378..0ad501f 100644 --- a/backend/src/main/java/com/yfd/platform/system/controller/LoginController.java +++ b/backend/src/main/java/com/yfd/platform/system/controller/LoginController.java @@ -5,6 +5,7 @@ import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; import cn.hutool.jwt.JWTUtil; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.wf.captcha.base.Captcha; import com.yfd.platform.annotation.Log; @@ -97,9 +98,18 @@ public class LoginController { } LoginUser loginUser = (LoginUser) authenticate.getPrincipal(); Integer status = loginUser.getUser().getStatus(); + String regStatus = loginUser.getUser().getRegStatus(); if ("0".equals(status.toString())) { return ResponseResult.error("账号已停用"); } + + if ("PENDING".equals(regStatus)) { + return ResponseResult.error("账号待审核,请联系管理员"); + } + + if ("REJECTED".equals(regStatus)) { + return ResponseResult.error("账号审核未通过"); + } HttpServletRequest request = RequestHolder.getHttpServletRequest(); SysLog sysLog = new SysLog(); sysLog.setUsercode(user.getUsername()); @@ -190,7 +200,7 @@ public class LoginController { } @Log(module = "用户登录", value = "更改用户密码") - @GetMapping("/updatePassword") + @PostMapping("/updatePassword") @Operation(summary = "更改用户密码") @ResponseBody public ResponseResult updatePassword(@RequestBody SysUser user) throws Exception { @@ -199,9 +209,13 @@ public class LoginController { user.getPassword()); BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); String cryptPassword = passwordEncoder.encode(password); - UpdateWrapper updateWrapper = new UpdateWrapper<>(); - updateWrapper.set("password", cryptPassword); - updateWrapper.eq("id", user.getId()); + // 验证新密码和旧密码是否一致 + if (passwordEncoder.matches(password, user.getOldPassword())) { + return ResponseResult.error("新密码不能与旧密码相同"); + } + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.set(SysUser::getPassword, cryptPassword); + updateWrapper.eq(SysUser::getId, user.getId()); userService.update(updateWrapper); return ResponseResult.success(); } diff --git a/backend/src/main/java/com/yfd/platform/system/controller/SmsVerifyCodeController.java b/backend/src/main/java/com/yfd/platform/system/controller/SmsVerifyCodeController.java index 3dd784a..279f5d6 100644 --- a/backend/src/main/java/com/yfd/platform/system/controller/SmsVerifyCodeController.java +++ b/backend/src/main/java/com/yfd/platform/system/controller/SmsVerifyCodeController.java @@ -167,7 +167,7 @@ public class SmsVerifyCodeController { user.setBelongingUnit(smsVerifyCodeRequest.getBelongingUnit()); user.setRegTime(new Date()); user.setNickname(smsVerifyCodeRequest.getRealName()); - user.setStatus(1); + user.setStatus(0); user.setOrgid("e90063ced25e3d469860e88d920c082f"); user.setUsertype(1); user.setUsername(smsVerifyCodeRequest.getUsername()); @@ -204,7 +204,7 @@ public class SmsVerifyCodeController { selectedBasinCodes.addAll(Arrays.asList(hbrvcdCode.split(","))); } -// Set addedStationCodes = new HashSet<>(); + Set addedStationCodes = new HashSet<>(); for (String basinCode : selectedBasinCodes) { if (StringUtils.isEmpty(basinCode)) { @@ -241,7 +241,7 @@ public class SmsVerifyCodeController { scope.setStatus(1); scope.setPermissionType("READ"); sysUserDataScopeService.addDataScope(scope); -// addedStationCodes.add(basinCode); + addedStationCodes.add(basinCode); } else { Set stationsInBasinAndSelected = allStationCodesInBasin.stream() .filter(selectedStationCodes::contains) @@ -255,27 +255,27 @@ public class SmsVerifyCodeController { scope.setStatus(1); scope.setPermissionType("READ"); sysUserDataScopeService.addDataScope(scope); -// addedStationCodes.add(stationCd); + addedStationCodes.add(stationCd); } } } -// Set standaloneStations = selectedStationCodes.stream() -// .filter(code -> !addedStationCodes.contains(code)) -// .collect(Collectors.toSet()); -// -// for (String stationCd : standaloneStations) { -// if (StringUtils.isEmpty(stationCd)) { -// continue; -// } -// SysUserDataScope scope = new SysUserDataScope(); -// scope.setUserId(userId); -// scope.setOrgType("STATION"); -// scope.setOrgId(stationCd); -// scope.setStatus(1); -// scope.setPermissionType("READ"); -// sysUserDataScopeService.addDataScope(scope); -// } + Set standaloneStations = selectedStationCodes.stream() + .filter(code -> !addedStationCodes.contains(code)) + .collect(Collectors.toSet()); + + for (String stationCd : standaloneStations) { + if (StringUtils.isEmpty(stationCd)) { + continue; + } + SysUserDataScope scope = new SysUserDataScope(); + scope.setUserId(userId); + scope.setOrgType("STATION"); + scope.setOrgId(stationCd); + scope.setStatus(1); + scope.setPermissionType("READ"); + sysUserDataScopeService.addDataScope(scope); + } SysUser user = new SysUser(); user.setId(userId); userService.updateUserRoles( user,"c13481a486c9ee559cf305284df4d207"); @@ -316,12 +316,9 @@ public class SmsVerifyCodeController { } catch (Exception e) { return ResponseResult.error("密码解密失败"); } - String encodePassword = existUser.getPassword(); BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); String encryptedPassword = passwordEncoder.encode(password); - if (passwordEncoder.matches(password, encodePassword)) { - return ResponseResult.error("新密码不能与旧密码相同"); - } + boolean success = userService.updatePasswordByPhone(phone, encryptedPassword); if (success) { return ResponseResult.success(); diff --git a/backend/src/main/java/com/yfd/platform/system/controller/UserController.java b/backend/src/main/java/com/yfd/platform/system/controller/UserController.java index cda7434..01217a4 100644 --- a/backend/src/main/java/com/yfd/platform/system/controller/UserController.java +++ b/backend/src/main/java/com/yfd/platform/system/controller/UserController.java @@ -214,7 +214,7 @@ public class UserController { } if (StrUtil.isBlank(auditStatus) || ( !"APPROVED".equals(auditStatus)&&!"REJECTED".equals(auditStatus))) { - return ResponseResult.error("审核状态错误:1-通过 2-驳回"); + return ResponseResult.error("审核状态错误"); } SysUser user = userService.getById(userId); if (user == null) { diff --git a/backend/src/main/java/com/yfd/platform/system/domain/SysUser.java b/backend/src/main/java/com/yfd/platform/system/domain/SysUser.java index 1fae968..e37f595 100644 --- a/backend/src/main/java/com/yfd/platform/system/domain/SysUser.java +++ b/backend/src/main/java/com/yfd/platform/system/domain/SysUser.java @@ -155,6 +155,12 @@ public class SysUser implements Serializable { */ private String companyCode; + @TableField(exist = false) + /** + * 登录密码(加密存储) + */ + private String oldPassword; + @TableField(exist = false) List roles; } diff --git a/backend/src/main/java/com/yfd/platform/system/service/impl/UserDetailsServiceImpl.java b/backend/src/main/java/com/yfd/platform/system/service/impl/UserDetailsServiceImpl.java index dc28501..6042bee 100644 --- a/backend/src/main/java/com/yfd/platform/system/service/impl/UserDetailsServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/system/service/impl/UserDetailsServiceImpl.java @@ -35,9 +35,9 @@ public class UserDetailsServiceImpl implements UserDetailsService { @Override @DataSource(name = "master") public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { - //根据用户名称查询用户信息 + //根据用户名称或手机号查询用户信息 QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.eq("username", username); + queryWrapper.and(wrapper -> wrapper.eq("username", username).or().eq("phone", username)); SysUser user = userService.getOne(queryWrapper); if (ObjectUtil.isEmpty(user)) { throw new RuntimeException("用户账号不存在!"); diff --git a/backend/src/main/resources/application-devtw.yml b/backend/src/main/resources/application-devtw.yml index 33320bc..64b040c 100644 --- a/backend/src/main/resources/application-devtw.yml +++ b/backend/src/main/resources/application-devtw.yml @@ -10,12 +10,12 @@ spring: druid: master: driverClassName: oracle.jdbc.OracleDriver - url: "${DB_MASTER_URL:jdbc:oracle:thin:@172.16.31.190:1521/SDLYZ}" + url: "${DB_MASTER_URL:jdbc:oracle:thin:@172.16.21.134:1521/SDLYZ}" username: "${DB_MASTER_USERNAME:QGC_REFA}" password: "${DB_MASTER_PASSWORD:Y4M4K1oCkL8U}" slave: driverClassName: oracle.jdbc.OracleDriver - url: "${DB_SLAVE_URL:jdbc:oracle:thin:@172.16.31.190:1521/SDLYZ}" + url: "${DB_SLAVE_URL:jdbc:oracle:thin:@172.16.21.134:1521/SDLYZ}" username: "${DB_SLAVE_USERNAME:QGC_REFA}" password: "${DB_SLAVE_PASSWORD:Y4M4K1oCkL8U}" @@ -27,8 +27,8 @@ spring: matching-strategy: ant_path_matcher servlet: multipart: - max-file-size: 30MB - max-request-size: 100MB + max-file-size: 300MB + max-request-size: 500MB logging: file: @@ -117,3 +117,11 @@ task: keep-alive-seconds: 60 # 队列容量 queue-capacity: 50 + +attachment: + token: ${ATTACHMENT_TOKEN:qgcBkod25ngBa4wu8BtfCPYsJ7lQGVDoexH} + upload-url: ${ATTACHMENT_UPLOAD_URL:http://172.16.31.185:18200/upload} + video-url: ${ATTACHMENT_VIDEO_URL:http://172.16.31.185:18200/upload} + delete-url: ${ATTACHMENT_DELETE_URL:http://172.16.31.185:18200/delete} +# upload-url: ${ATTACHMENT_UPLOAD_URL:https://211.99.26.225:12125/upload} +# video-url: ${ATTACHMENT_VIDEO_URL:https://211.99.26.225:12125/upload} \ No newline at end of file diff --git a/backend/src/main/resources/application-prod.yml b/backend/src/main/resources/application-prod.yml index 27be67d..392b634 100644 --- a/backend/src/main/resources/application-prod.yml +++ b/backend/src/main/resources/application-prod.yml @@ -27,8 +27,8 @@ spring: matching-strategy: ant_path_matcher servlet: multipart: - max-file-size: 30MB - max-request-size: 100MB + max-file-size: 300MB + max-request-size: 500MB logging: file: @@ -36,7 +36,7 @@ logging: level: root: info com.yfd.platform: info - com.yfd.platform.*.mapper: trace +# com.yfd.platform.*.mapper: trace # 在线文档: swagger-ui(生产环境建议关闭) swagger-ui: @@ -117,3 +117,9 @@ task: keep-alive-seconds: 60 # 队列容量 queue-capacity: 50 + +attachment: + token: ${ATTACHMENT_TOKEN:qgcBkod25ngBa4wu8BtfCPYsJ7lQGVDoexH} + upload-url: ${ATTACHMENT_UPLOAD_URL:http://172.16.31.185:18200/upload} + video-url: ${ATTACHMENT_VIDEO_URL:http://172.16.31.185:18200/upload} + delete-url: ${ATTACHMENT_DELETE_URL:http://172.16.31.185:18200/delete} \ No newline at end of file diff --git a/backend/src/main/resources/application.yml b/backend/src/main/resources/application.yml index b11a8a0..d8e6c7e 100644 --- a/backend/src/main/resources/application.yml +++ b/backend/src/main/resources/application.yml @@ -40,5 +40,3 @@ springdoc: path: /swagger-ui.html packages-to-scan: com.yfd.platform -attachment: - token: ${ATTACHMENT_TOKEN:qgcBkod25ngBa4wu8BtfCPYsJ7lQGVDoexH} \ No newline at end of file diff --git a/backend/src/main/resources/mapper/data/FishDraftDataMapper.xml b/backend/src/main/resources/mapper/data/FishDraftDataMapper.xml index acb5626..ec55559 100644 --- a/backend/src/main/resources/mapper/data/FishDraftDataMapper.xml +++ b/backend/src/main/resources/mapper/data/FishDraftDataMapper.xml @@ -78,7 +78,7 @@ - + @@ -123,7 +123,8 @@ E.RVCD, E.LGTD, E.LTTD, - E.ORDER_INDEX + E.ORDER_INDEX, + D.ROW_INDEX