userNameMap = users.stream()
+ .collect(Collectors.toMap(SysUser::getId, SysUser::getNickname, (a, b) -> a));
+
+ for (T item : list) {
+ try {
+ Object idValue = idField.get(item);
+ if (idValue != null && StrUtil.isNotBlank(idValue.toString())) {
+ String userName = userNameMap.get(idValue.toString());
+ nameField.set(item, StrUtil.blankToDefault(userName, "未知"));
+ }
+ } catch (IllegalAccessException e) {
+ continue;
+ }
+ }
+ }
+
+ /**
+ * 批量填充用户名称(支持多个用户ID字段)
+ *
+ * 使用方式:在实体类中定义多个 @UserIdField 和 @UserNameField 配对字段
+ *
+ * @param list 需要填充的实体列表
+ * @param idFields 用户ID字段名数组
+ * @param nameFields 用户名字段名数组
+ */
+ public void fillUserNames(List list, String[] idFields, String[] nameFields) {
+ if (CollUtil.isEmpty(list) || idFields == null || nameFields == null || idFields.length != nameFields.length) {
+ return;
+ }
+
+ Class> clazz = list.get(0).getClass();
+ Field[] allFields = clazz.getDeclaredFields();
+ Map fieldMap = new HashMap<>();
+ for (Field field : allFields) {
+ fieldMap.put(field.getName(), field);
+ }
+
+ List idFieldList = new ArrayList<>();
+ List nameFieldList = new ArrayList<>();
+ for (String idFieldName : idFields) {
+ Field f = fieldMap.get(idFieldName);
+ if (f != null) {
+ f.setAccessible(true);
+ idFieldList.add(f);
+ }
+ }
+ for (String nameFieldName : nameFields) {
+ Field f = fieldMap.get(nameFieldName);
+ if (f != null) {
+ f.setAccessible(true);
+ nameFieldList.add(f);
+ }
+ }
+
+ if (idFieldList.isEmpty() || nameFieldList.isEmpty()) {
+ return;
+ }
+
+ Set userIds = new HashSet<>();
+ for (T item : list) {
+ for (Field idField : idFieldList) {
+ try {
+ Object idValue = idField.get(item);
+ if (idValue != null && StrUtil.isNotBlank(idValue.toString())) {
+ userIds.add(idValue.toString());
+ }
+ } catch (IllegalAccessException e) {
+ continue;
+ }
+ }
+ }
+
+ if (userIds.isEmpty()) {
+ return;
+ }
+
+ List users = sysUserMapper.selectBatchIds(userIds);
+ Map userNameMap = users.stream()
+ .collect(Collectors.toMap(SysUser::getId, SysUser::getNickname, (a, b) -> a));
+
+ for (T item : list) {
+ for (int i = 0; i < idFieldList.size() && i < nameFieldList.size(); i++) {
+ try {
+ Object idValue = idFieldList.get(i).get(item);
+ if (idValue != null && StrUtil.isNotBlank(idValue.toString())) {
+ String userName = userNameMap.get(idValue.toString());
+ nameFieldList.get(i).set(item, StrUtil.blankToDefault(userName, "未知"));
+ }
+ } catch (IllegalAccessException e) {
+ continue;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
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 3e8a46e..5510e43 100644
--- a/backend/src/main/java/com/yfd/platform/config/MyMetaObjectHandler.java
+++ b/backend/src/main/java/com/yfd/platform/config/MyMetaObjectHandler.java
@@ -27,11 +27,17 @@ public class MyMetaObjectHandler implements MetaObjectHandler {
// 自动填充更新时间
this.strictInsertFill(metaObject, "updatedAt", Date.class, now);
- // 自动填充更新时间
- this.strictInsertFill(metaObject, "createdBy", String.class, SecurityUtils.getUserId());
+ try {
+ String userId = SecurityUtils.getUserId();
+ // 自动填充更新时间
+ this.strictInsertFill(metaObject, "createdBy", String.class, userId );
+
+ // 自动填充更新时间
+ this.strictInsertFill(metaObject, "updatedBy", String.class, userId);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
- // 自动填充更新时间
- this.strictInsertFill(metaObject, "updatedBy", String.class, SecurityUtils.getUserId());
}
/**
@@ -41,7 +47,13 @@ public class MyMetaObjectHandler implements MetaObjectHandler {
public void updateFill(MetaObject metaObject) {
// 自动填充更新时间
this.strictUpdateFill(metaObject, "updatedAt", Date.class, new Date());
- // 自动填充更新人
- this.strictInsertFill(metaObject, "updatedBy", String.class, SecurityUtils.getUserId());
+ try {
+ String userId = SecurityUtils.getUserId();
+ // 自动填充更新人
+ this.strictInsertFill(metaObject, "updatedBy", String.class, userId);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
}
}
diff --git a/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java b/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java
index 2bcef19..ac00ba5 100644
--- a/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java
+++ b/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java
@@ -53,6 +53,10 @@ public class SecurityConfig {
.authorizeHttpRequests(auth -> auth
.requestMatchers("/user/login").anonymous()
.requestMatchers("/user/code").permitAll()
+ .requestMatchers("/sms/resetPassword").permitAll()
+ .requestMatchers("/data/fishDraft/previewFile").permitAll()
+ .requestMatchers("/tempFile/**").permitAll()
+ .requestMatchers("/system/user/auditUser").permitAll()
.requestMatchers("/eng/**").permitAll()
.requestMatchers("/env/**").permitAll()
.requestMatchers("/sw/**").permitAll()
diff --git a/backend/src/main/java/com/yfd/platform/config/WebConfig.java b/backend/src/main/java/com/yfd/platform/config/WebConfig.java
index 45b051a..8356277 100644
--- a/backend/src/main/java/com/yfd/platform/config/WebConfig.java
+++ b/backend/src/main/java/com/yfd/platform/config/WebConfig.java
@@ -4,6 +4,7 @@ import cn.hutool.cache.Cache;
import cn.hutool.cache.CacheUtil;
import lombok.SneakyThrows;
import jakarta.annotation.Resource;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
@@ -17,6 +18,9 @@ public class WebConfig implements WebMvcConfigurer {
@Resource
private FileSpaceProperties fileSpaceProperties;
+ @Value("${app.zip-import.temp-dir}")
+ private String platformPath;
+
@Bean
@@ -54,7 +58,8 @@ public class WebConfig implements WebMvcConfigurer {
String systemUrl = "file:" + fileSpaceProperties.getSystem().replace("\\", "/")+"user\\";
registry.addResourceHandler("/avatar/**").addResourceLocations(systemUrl).setCachePeriod(0);
-
+ String platformUrl = "file:" + platformPath.replace("\\", "/");
+ registry.addResourceHandler("/tempFile/**").addResourceLocations(platformUrl).setCachePeriod(0);
}
diff --git a/backend/src/main/java/com/yfd/platform/data/controller/ApprovalChangeLogController.java b/backend/src/main/java/com/yfd/platform/data/controller/ApprovalChangeLogController.java
index 26e019f..49a2d2f 100644
--- a/backend/src/main/java/com/yfd/platform/data/controller/ApprovalChangeLogController.java
+++ b/backend/src/main/java/com/yfd/platform/data/controller/ApprovalChangeLogController.java
@@ -2,6 +2,7 @@ package com.yfd.platform.data.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yfd.platform.common.DataSourceRequest;
+import com.yfd.platform.common.utils.UserNameFillHelper;
import com.yfd.platform.config.ResponseResult;
import com.yfd.platform.data.domain.ApprovalChangeLog;
import com.yfd.platform.data.domain.ApprovalLog;
@@ -28,6 +29,9 @@ public class ApprovalChangeLogController {
@Resource
private IApprovalChangeLogService approvalChangeLogService;
+ @Resource
+ private UserNameFillHelper userNameFillHelper;
+
@GetMapping("/list")
@Operation(summary = "查询变更记录列表")
public ResponseResult list() {
@@ -39,7 +43,8 @@ public class ApprovalChangeLogController {
@Operation(summary = "分页查询变更记录列表(通用)")
public ResponseResult queryPageList(@RequestBody DataSourceRequest request) {
Page approvalChangeLogPage = DataSourceRequestUtil.executeQuery(request, ApprovalChangeLog.class, approvalChangeLogService);
- approvalChangeLogService.fillUserNames(approvalChangeLogPage.getRecords());
+ userNameFillHelper.fillUserNames(approvalChangeLogPage.getRecords());
+ // approvalChangeLogService.fillUserNames(approvalChangeLogPage.getRecords());
return ResponseResult.successData(approvalChangeLogPage);
}
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 85a449d..fd0b529 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
@@ -1,24 +1,35 @@
package com.yfd.platform.data.controller;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.OutputStream;
+import java.net.URLEncoder;
+import java.nio.file.Files;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.Map;
+
+import cn.hutool.core.io.FileUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yfd.platform.common.DataSourceRequest;
import com.yfd.platform.config.ResponseResult;
-import com.yfd.platform.data.domain.FishDraftData;
-import com.yfd.platform.data.domain.FishImportRequest;
-import com.yfd.platform.data.domain.FishImportResult;
-import com.yfd.platform.data.domain.ImportTask;
-import com.yfd.platform.data.domain.BatchApproveRequest;
-import com.yfd.platform.data.domain.BatchRejectRequest;
+import com.yfd.platform.data.domain.*;
import com.yfd.platform.data.domain.vo.FishDraftDataVO;
+import com.yfd.platform.data.service.AttachmentUploadService;
import com.yfd.platform.data.service.IFishDraftDataService;
import com.yfd.platform.data.service.IFishImportService;
import com.yfd.platform.data.service.IImportTaskService;
+import com.yfd.platform.data.utils.ZipFileUtil;
import com.yfd.platform.utils.KendoUtil;
import com.yfd.platform.utils.SecurityUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
@@ -33,6 +44,7 @@ import java.util.*;
@RestController
@RequestMapping("/data/fishDraft")
@Tag(name = "过鱼数据")
+@Slf4j
public class FishDraftDataController {
@Resource
@@ -47,10 +59,13 @@ public class FishDraftDataController {
@Resource
private ObjectMapper objectMapper;
+ @Resource
+ private AttachmentUploadService attachmentUploadService;
+
@PostMapping("/page")
@Operation(summary = "分页查询过鱼数据(关联电站和设施)")
public ResponseResult queryPageList(@RequestBody DataSourceRequest dataSourceRequest) {
- Page result = fishDraftDataService.queryPageList( dataSourceRequest);
+ Page result = fishDraftDataService.queryPageList(dataSourceRequest);
return ResponseResult.successData(result);
}
@@ -109,6 +124,45 @@ public class FishDraftDataController {
return result ? ResponseResult.success("保存成功") : ResponseResult.error("保存失败");
}
+ @PostMapping("/importBatchSaveDraft")
+ @Operation(summary = "批量保存草稿(导入)")
+ public ResponseResult importBatchSaveDraft(@RequestBody BatchSaveDraftRequest batchSaveDraftRequest) {
+ String taskId = batchSaveDraftRequest.getTaskId();
+ ImportTask importTask = importTaskService.getById(taskId);
+ if (importTask == null) {
+ return ResponseResult.error("导入任务不存在");
+ }
+ String resultJson = importTask.getResultJson();
+ List fishDraftDataList = batchSaveDraftRequest.getFishDraftDataList();
+ if (resultJson != null && !resultJson.isEmpty()) {
+ try {
+ FishImportResult importResult = objectMapper.readValue(resultJson, FishImportResult.class);
+ ZipFileUtil.ZipContent content = new ZipFileUtil.ZipContent();
+ content.images = importResult.getImageFiles();
+ content.videos = importResult.getVideoFiles();
+ fishImportService.processAttachments(importResult, content);
+ fishDraftDataList.forEach(fishDraftData -> {
+ for (FishImportResult.FishImportRow row : importResult.getRows()) {
+ if (fishDraftData.getId().equals(row.getData().getId())) {
+ fishDraftData.setPicpth(row.getData().getPicpth());
+ fishDraftData.setVdpth(row.getData().getVdpth());
+ break;
+ }
+ }
+ fishDraftData.setStatus("DRAFT");
+ fishDraftData.setDeletedFlag(0);
+ fishDraftData.setLockFlag(0);
+ });
+ } catch (Exception e) {
+ e.printStackTrace();
+ // ignore parse error
+ }
+ }
+
+ boolean result = fishDraftDataService.saveBatch(fishDraftDataList);
+ return result ? ResponseResult.success("保存成功") : ResponseResult.error("保存失败");
+ }
+
@PostMapping("/updateDraft")
@Operation(summary = "更新草稿")
public ResponseResult updateDraft(@RequestBody FishDraftData fishDraftData) {
@@ -134,7 +188,7 @@ public class FishDraftDataController {
@PostMapping("/submitDraft")
@Operation(summary = "提交草稿")
public ResponseResult submitDraft(@RequestParam String id,
- @RequestParam String operatorId) {
+ @RequestParam String operatorId) {
boolean result = fishDraftDataService.submitDraft(id, operatorId);
return result ? ResponseResult.success("提交成功") : ResponseResult.error("提交失败");
}
@@ -161,7 +215,6 @@ public class FishDraftDataController {
}
-
@PostMapping("/lockDraft")
@Operation(summary = "锁定草稿")
public ResponseResult lockDraft(@RequestParam String id) {
@@ -207,18 +260,22 @@ public class FishDraftDataController {
@PostMapping("/importZip")
@Operation(summary = "导入ZIP过鱼数据(每个用户同时只能进行一次导入)")
public ResponseResult importZip(@RequestParam("file") MultipartFile file) {
+ log.info("开始导入ZIP文件");
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();
@@ -232,8 +289,10 @@ public class FishDraftDataController {
task.setStatus("UPLOADED");
task.setUploadUserId(uploadUserId);
task.setUploadTime(new Date());
+ log.info("保存导入任务成功");
importTaskService.save(task);
+ log.info("开始保存文件");
FishImportRequest request = new FishImportRequest();
request.setImportNo(importNo);
request.setUploadUserId(uploadUserId);
@@ -243,7 +302,7 @@ public class FishDraftDataController {
result.setTaskId(taskId);
String status = "VALIDATED";
if ("1".equals(result.getCode())) {
- status="FAILED";
+ status = "FAILED";
}
importTaskService.updateStatus(taskId, status, null);
importTaskService.updateProgress(taskId, result.getTotalCount(), result.getSuccessCount(), result.getFailedCount());
@@ -262,10 +321,281 @@ public class FishDraftDataController {
}
}
+ @GetMapping("/previewTempFiles")
+ @Operation(summary = "预览临时文件列表")
+ public ResponseResult previewTempFiles(@RequestParam String taskId) {
+ if (taskId == null || taskId.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);
+
+ Map previewData = new HashMap<>();
+ previewData.put("tempDir", importResult.getTempDir());
+ previewData.put("excelFileName", importResult.getExcelFileName());
+ previewData.put("excelFilePath", importResult.getExcelFilePath());
+
+ List