From f68757a9b30d5a5d854684053b1fb5a518bf8cc5 Mon Sep 17 00:00:00 2001 From: gulongcheng <474084054@qq.com> Date: Fri, 13 Feb 2026 13:52:42 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E4=BC=98=E5=8C=96=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/MinioFileIDataFileServiceImpl.java | 233 +++++------------- .../FileModifyApproveHelper.java | 200 +++++++++++++++ .../ModifyFileApproveStrategy.java | 233 ++++++------------ .../ModifyMetadataApproveStrategy.java | 144 +---------- 4 files changed, 355 insertions(+), 455 deletions(-) create mode 100644 data/src/main/java/com/sdm/data/service/impl/dataFileHandle/FileModifyApproveHelper.java diff --git a/data/src/main/java/com/sdm/data/service/impl/MinioFileIDataFileServiceImpl.java b/data/src/main/java/com/sdm/data/service/impl/MinioFileIDataFileServiceImpl.java index 863fdd0e..485f2455 100644 --- a/data/src/main/java/com/sdm/data/service/impl/MinioFileIDataFileServiceImpl.java +++ b/data/src/main/java/com/sdm/data/service/impl/MinioFileIDataFileServiceImpl.java @@ -49,6 +49,7 @@ import com.sdm.data.service.approve.FileApproveRequestBuilder; import com.sdm.data.service.impl.dataFileHandle.ApproveContext; import com.sdm.data.service.impl.dataFileHandle.ApproveStrategy; import com.sdm.data.service.impl.dataFileHandle.ApproveStrategyFactory; +import com.sdm.data.service.impl.dataFileHandle.FileModifyApproveHelper; import io.minio.Result; import io.minio.messages.Item; import jakarta.servlet.http.HttpServletResponse; @@ -182,6 +183,9 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService { @Autowired private DictTagHelper dictTagHelper; + @Autowired + private FileModifyApproveHelper fileModifyApproveHelper; + private static final String TEMP_FILE_PATH = "/usr/local/nginx/html/storage/"; @@ -2495,11 +2499,7 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService { } // 不需要审批:直接更新或上传 - if (ObjectUtils.isEmpty(req.getFile())) { - updateMetadataDirectly(req, fileMetadataInfo, dirMetadataInfo); - } else { - uploadAndUpdateFile(req, fileMetadataInfo, fileMetadataInfo.getVersionNo(), fileMetadataInfo.getFileGroupId(), dirMetadataInfo); - } + updateFileDirectly(req, fileMetadataInfo, dirMetadataInfo); return SdmResponse.success("更新成功"); } @@ -2656,184 +2656,83 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService { } /** - * 直接更新元数据(无需审批、无需上传新文件)。 + * 直接更新文件(无需审批)。 *

- * 包含:基础字段更新、工况库绑定关系同步、标签关系更新。 + * 统一处理“仅元数据更新”和“含文件上传更新”的逻辑。 + * 含文件上传时:保留历史版本,主记录指向新文件(鸠占鹊巢)。 *

- * - * @param req 更新请求 - * @param fileMetadataInfo 当前文件元数据 - * @param dirMetadataInfo 父目录元数据(用于标签更新时的目录上下文) */ - private void updateMetadataDirectly(UpdateFileReq req, FileMetadataInfo fileMetadataInfo, FileMetadataInfo dirMetadataInfo) { + private void updateFileDirectly(UpdateFileReq req, FileMetadataInfo fileMetadataInfo, FileMetadataInfo dirMetadataInfo) { + boolean hasFileUpload = !ObjectUtils.isEmpty(req.getFile()); + + // 1. 如果有文件上传,先处理文件上传和版本备份 + if (hasFileUpload) { + // 1.1 备份当前主记录为历史版本 + FileMetadataInfo historyFileInfo = new FileMetadataInfo(); + BeanUtils.copyProperties(fileMetadataInfo, historyFileInfo); + historyFileInfo.setId(null); // 清空ID,插入新记录 + historyFileInfo.setTempMetadata(null); + historyFileInfo.setIsLatest(false); + fileMetadataInfoService.save(historyFileInfo); + + // 1.1.1 复制原文件的权限到历史版本 + fileModifyApproveHelper.copyFilePermissions(fileMetadataInfo.getId(), historyFileInfo.getId(), fileUserPermissionService); + + // 1.2 上传新文件并获取新 ObjectKey + String originalName = req.getFileName(); + Long newVersionNo = fileMetadataInfo.getVersionNo() + 1; + String versionSuffix = "_V" + newVersionNo; + int dotIndex = originalName.lastIndexOf('.'); + if (dotIndex == -1) { + throw new RuntimeException("文件没有后缀"); + } + String modifiedFileName = originalName.substring(0, dotIndex) + versionSuffix + originalName.substring(dotIndex); + String newFileMinioObjectKey = getFileMinioObjectKey(dirMetadataInfo.getObjectKey() + modifiedFileName); + + try { + minioService.uploadFile(req.getFile(), newFileMinioObjectKey, null, fileMetadataInfo.getBucketName()); + } catch (Exception e) { + log.error("上传文件失败", e); + throw new RuntimeException("上传文件失败: " + e.getMessage()); + } + + // 1.3 更新主记录的文件相关属性 + fileMetadataInfo.setObjectKey(newFileMinioObjectKey); + fileMetadataInfo.setOriginalName(originalName); + fileMetadataInfo.setFileSize(req.getFile().getSize()); + fileMetadataInfo.setVersionNo(newVersionNo); + + // 更新文件存储统计信息 + fileStorageService.lambdaUpdate() + .eq(FileStorage::getFileId, fileMetadataInfo.getId()) + .set(FileStorage::getFileName, originalName) + .set(FileStorage::getFileSize, req.getFile().getSize()) + .update(); + } + + // 2. 更新通用元数据字段 fileMetadataInfo.setProjectId(req.getProjectId()); fileMetadataInfo.setAnalysisDirectionId(req.getAnalysisDirectionId()); fileMetadataInfo.setRemarks(req.getRemarks()); fileMetadataInfo.setUpdateTime(LocalDateTime.now()); fileMetadataInfo.setUpdaterId(ThreadLocalContext.getUserId()); - fileMetadataInfo.setFileType(req.getFileType()); + fileMetadataInfo.setIsLatest(true); // 确保为主版本 - if (CollectionUtils.isNotEmpty(req.getSimulationPoolInfoList())) { - fileSimulationMappingService.lambdaUpdate().eq(FileSimulationMapping::getFileId, fileMetadataInfo.getId()).remove(); - for (SimulationPoolInfo poolInfo : req.getSimulationPoolInfoList()) { - fileSimulationMappingService.lambdaUpdate() - .eq (FileSimulationMapping::getSimulationPoolId, poolInfo.getSimulationPoolId()) - .eq (FileSimulationMapping::getSimulationPoolVersion, poolInfo.getSimulationPoolVersion()) - .eq(FileSimulationMapping::getFileId, fileMetadataInfo.getId()).remove(); - for (String taskId : poolInfo.getSimulationPoolTaskIds()) { - FileSimulationMapping mapping = new FileSimulationMapping(); - mapping.setFileId(fileMetadataInfo.getId()); - mapping.setSimulationPoolId(poolInfo.getSimulationPoolId()); - mapping.setSimulationPoolVersion(poolInfo.getSimulationPoolVersion()); - mapping.setSimulationPoolTaskId(taskId); - fileSimulationMappingService.save(mapping); - } - } - } + // 3. 更新工况库绑定(按工况库版本更新:先删指定版本下的绑定,再插入) + fileModifyApproveHelper.updateSimulationMappings(fileMetadataInfo.getId(), req.getSimulationPoolInfoList(), fileSimulationMappingService); + // 4. 更新扩展字段 + fileModifyApproveHelper.updateExtensions(fileMetadataInfo.getId(), req.getFileMetadataExtensionRequest(), fileMetadataExtensionService); + + // 5. 更新标签 if (CollectionUtils.isNotEmpty(req.getDictTags())) { updateFileTags(req, fileMetadataInfo, dirMetadataInfo); } + + // 6. 保存主记录更新 fileMetadataInfoService.updateById(fileMetadataInfo); } - - /** - * 覆盖上传新文件(鸠占鹊巢):保持主记录 ID 不变,同时保留历史版本。 - *

- * 最小方案约束: - * 1) 仅保留“文件内容 + 主元数据”的历史版本;标签/工况/扩展信息始终以最新为准,不做历史克隆; - * 2) 上传的新文件使用新的 objectKey(带版本号后缀),避免覆盖 MinIO 旧对象。 - *

- */ - public void uploadAndUpdateFile(UpdateFileReq req, FileMetadataInfo oldFileMetadataInfo, Long versionNo, Long fileGroupId, FileMetadataInfo dirMetadataInfo) { - String newFileMinioObjectKey = ""; - try { - // 1) 备份:克隆当前主记录为历史行(新 ID),用于版本回溯 - FileMetadataInfo historyFileInfo = new FileMetadataInfo(); - BeanUtils.copyProperties(oldFileMetadataInfo, historyFileInfo); - historyFileInfo.setId(null); - historyFileInfo.setTempMetadata(null); - historyFileInfo.setIsLatest(false); - fileMetadataInfoService.save(historyFileInfo); - - // 2) 生成新版本文件名与 objectKey - String originalName = req.getFileName(); - String versionSuffix = "_V" + (versionNo + 1); - int dotIndex = originalName.lastIndexOf('.'); - if (dotIndex == -1) { - log.error("文件没有后缀"); - throw new RuntimeException("文件没有后缀"); - } - String modifiedFileName = originalName.substring(0, dotIndex) + versionSuffix + originalName.substring(dotIndex); - - String parDirObjectKey = dirMetadataInfo.getObjectKey(); - newFileMinioObjectKey = getFileMinioObjectKey(parDirObjectKey + modifiedFileName); - - // 3) 上传新文件 - minioService.uploadFile(req.getFile(), newFileMinioObjectKey, null, oldFileMetadataInfo.getBucketName()); - - // 4) 原地更新:主记录 ID 不变,指向最新版本 - oldFileMetadataInfo.setObjectKey(newFileMinioObjectKey); - oldFileMetadataInfo.setOriginalName(req.getFileName()); - oldFileMetadataInfo.setFileSize(req.getFile().getSize()); - oldFileMetadataInfo.setVersionNo(versionNo + 1); - oldFileMetadataInfo.setFileGroupId(fileGroupId); - oldFileMetadataInfo.setIsLatest(true); - oldFileMetadataInfo.setUpdateTime(LocalDateTime.now()); - oldFileMetadataInfo.setUpdaterId(ThreadLocalContext.getUserId()); - - // 同步本次更新的元数据字段 - oldFileMetadataInfo.setRemarks(req.getRemarks()); - oldFileMetadataInfo.setProjectId(req.getProjectId()); - oldFileMetadataInfo.setAnalysisDirectionId(req.getAnalysisDirectionId()); - oldFileMetadataInfo.setFileType(req.getFileType()); - - fileMetadataInfoService.updateById(oldFileMetadataInfo); - - // 5) 更新关联(仅更新主记录关联,不做历史克隆) - if (CollectionUtils.isNotEmpty(req.getDictTags())) { - updateFileTags(req, oldFileMetadataInfo, dirMetadataInfo); - } - - if (CollectionUtils.isNotEmpty(req.getSimulationPoolInfoList())) { - for (SimulationPoolInfo simulationPoolInfo : req.getSimulationPoolInfoList()) { - fileSimulationMappingService.lambdaUpdate() - .eq (FileSimulationMapping::getSimulationPoolId, simulationPoolInfo.getSimulationPoolId()) - .eq (FileSimulationMapping::getSimulationPoolVersion, simulationPoolInfo.getSimulationPoolVersion()) - .eq(FileSimulationMapping::getFileId, oldFileMetadataInfo.getId()).remove(); - for (String simulationPoolTaskId : simulationPoolInfo.getSimulationPoolTaskIds()) { - FileSimulationMapping fileSimulationMapping = new FileSimulationMapping(); - fileSimulationMapping.setFileId(oldFileMetadataInfo.getId()); - fileSimulationMapping.setSimulationPoolId(simulationPoolInfo.getSimulationPoolId()); - fileSimulationMapping.setSimulationPoolVersion(simulationPoolInfo.getSimulationPoolVersion()); - fileSimulationMapping.setSimulationPoolTaskId(simulationPoolTaskId); - fileSimulationMappingService.save(fileSimulationMapping); - } - } - } - - // 扩展字段:作为“最新态”数据,覆盖更新主记录对应的扩展信息 - List fileMetadataExtensionRequestList = req.getFileMetadataExtensionRequest(); - if (fileMetadataExtensionRequestList != null && !fileMetadataExtensionRequestList.isEmpty()) { - fileMetadataExtensionService.lambdaUpdate().eq(FileMetadataExtension::getTFilemetaId, oldFileMetadataInfo.getId()).remove(); - List fileMetadataExtensionList = new ArrayList<>(); - fileMetadataExtensionRequestList.forEach(extensionRequest -> { - FileMetadataExtension fileMetadataExtension = new FileMetadataExtension(); - fileMetadataExtension.setTFilemetaId(oldFileMetadataInfo.getId()); - fileMetadataExtension.setExtensionKey(extensionRequest.getExtensionKey()); - fileMetadataExtension.setExtensionValue(extensionRequest.getExtensionValue()); - fileMetadataExtension.setDataType(Objects.toString(extensionRequest.getDataType(), "string")); - fileMetadataExtensionList.add(fileMetadataExtension); - }); - fileMetadataExtensionService.saveBatch(fileMetadataExtensionList); - } - - // FileStorage:只更新主记录 fileId 对应的统计信息,避免新增一堆重复统计 - fileStorageService.lambdaUpdate() - .eq(FileStorage::getFileId, oldFileMetadataInfo.getId()) - .set(FileStorage::getFileName, oldFileMetadataInfo.getOriginalName()) - .set(FileStorage::getFileSize, oldFileMetadataInfo.getFileSize()) - .set(FileStorage::getFileBizType, oldFileMetadataInfo.getFileType()) - .update(); - - // 6) 审批:beforeData 使用备份历史行,afterData 使用更新后的主行 - boolean isKnowledge = dirMetadataInfo != null && DirTypeEnum.isApprovalRequired(dirMetadataInfo.getDirType()); - if (isKnowledge) { - FileApproveRequestBuilder builder = FileApproveRequestBuilder.builder() - .toUpdateFileIds(List.of(oldFileMetadataInfo.getId())) - .contents(DirTypeEnum.buildApprovalTitle(dirMetadataInfo.getDirType(), "文件修改")) - .approveType(ApproveTypeEnum.KNOWLEDGE_APPROVE) - .approveFileActionENUM(ApproveFileActionENUM.MODIFY) - .beforeData(List.of(historyFileInfo)) - .afterData(List.of(oldFileMetadataInfo)) - .templateId(req.getTemplateId()) - .templateName(req.getTemplateName()) - .knowledgeBaseName(extractRelativePath(dirMetadataInfo)) - .build(); - - if (CollectionUtils.isNotEmpty(builder.getBeforeData())) { - setCreatorNames(builder.getBeforeData()); - setProjectName(builder.getBeforeData()); - setAnalysisDirectionName(builder.getBeforeData()); - setSimulationPoolAndTaskInfo(builder.getBeforeData()); - } - - if (CollectionUtils.isNotEmpty(builder.getAfterData())) { - setCreatorNames(builder.getAfterData()); - setProjectName(builder.getAfterData()); - setAnalysisDirectionName(builder.getAfterData()); - setSimulationPoolAndTaskInfo(builder.getAfterData()); - } - - fileApproveExecutor.launchApproveAndUpdateStatus(builder, ApproveFileDataTypeEnum.MODIFY_REVIEWING); - } - } catch (Exception e) { - minioService.deleteFile(newFileMinioObjectKey, oldFileMetadataInfo.getBucketName()); - log.error("更新文件失败", e); - throw new RuntimeException("更新文件失败: " + e.getMessage(), e); - } - } private List buildDictTagsFromEnum(UpdateFileReq req) { List dictTags = new ArrayList<>(); diff --git a/data/src/main/java/com/sdm/data/service/impl/dataFileHandle/FileModifyApproveHelper.java b/data/src/main/java/com/sdm/data/service/impl/dataFileHandle/FileModifyApproveHelper.java new file mode 100644 index 00000000..063706ee --- /dev/null +++ b/data/src/main/java/com/sdm/data/service/impl/dataFileHandle/FileModifyApproveHelper.java @@ -0,0 +1,200 @@ +package com.sdm.data.service.impl.dataFileHandle; + +import com.sdm.common.entity.req.data.FileMetadataExtensionRequest; +import com.sdm.common.entity.req.data.SimulationPoolInfo; +import com.sdm.data.model.entity.*; +import com.sdm.data.service.*; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * 文件修改审批辅助类 + *

+ * 提取 ModifyFileApproveStrategy 和 ModifyMetadataApproveStrategy 的公共逻辑 + *

+ */ +@Component +@Slf4j +public class FileModifyApproveHelper { + + /** + * 更新扩展参数 + */ + public void updateExtensions(Long fileId, List requests, + IFileMetadataExtensionService extensionService) { + if (ObjectUtils.isNotEmpty(requests)) { + // 先删除旧的 + extensionService.lambdaUpdate().eq(FileMetadataExtension::getTFilemetaId, fileId).remove(); + + // 插入新的 + List list = new ArrayList<>(); + requests.forEach(req -> { + FileMetadataExtension ext = new FileMetadataExtension(); + ext.setTFilemetaId(fileId); + ext.setExtensionKey(req.getExtensionKey()); + ext.setExtensionValue(req.getExtensionValue()); + ext.setDataType(Objects.toString(req.getDataType(), "string")); + list.add(ext); + }); + extensionService.saveBatch(list); + } + } + + /** + * 更新工况库绑定关系 + * 按工况库维度更新:先删除指定工况库版本下的绑定,再插入新绑定 + */ + public void updateSimulationMappings(Long fileId, List poolInfos, + IFileSimulationMappingService mappingService) { + if (CollectionUtils.isNotEmpty(poolInfos)) { + for (SimulationPoolInfo poolInfo : poolInfos) { + // 1. 删除当前文件在指定工况库版本下的旧绑定 + mappingService.lambdaUpdate() + .eq(FileSimulationMapping::getFileId, fileId) + .eq(FileSimulationMapping::getSimulationPoolId, poolInfo.getSimulationPoolId()) + .eq(FileSimulationMapping::getSimulationPoolVersion, poolInfo.getSimulationPoolVersion()) + .remove(); + + // 2. 插入新绑定 + List mappings = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(poolInfo.getSimulationPoolTaskIds())) { + for (String taskId : poolInfo.getSimulationPoolTaskIds()) { + FileSimulationMapping mapping = new FileSimulationMapping(); + mapping.setFileId(fileId); + mapping.setSimulationPoolId(poolInfo.getSimulationPoolId()); + mapping.setSimulationPoolVersion(poolInfo.getSimulationPoolVersion()); + mapping.setSimulationPoolTaskId(taskId); + mappings.add(mapping); + } + mappingService.saveBatch(mappings); + } + } + } + } + + /** + * 复制文件权限 + * + * @param sourceFileId 源文件ID + * @param targetFileId 目标文件ID + * @param permissionService 权限服务 + */ + public void copyFilePermissions(Long sourceFileId, Long targetFileId, IFileUserPermissionService permissionService) { + if (sourceFileId == null || targetFileId == null) { + return; + } + + // 1. 查询源文件的所有权限记录 + List sourcePermissions = permissionService.lambdaQuery() + .eq(FileUserPermission::getTFilemetaId, sourceFileId) + .list(); + + if (CollectionUtils.isEmpty(sourcePermissions)) { + return; + } + + // 2. 构建目标文件的权限记录 + List targetPermissions = new ArrayList<>(); + for (FileUserPermission sourcePerm : sourcePermissions) { + FileUserPermission targetPerm = new FileUserPermission(); + targetPerm.setTFilemetaId(targetFileId); + targetPerm.setUserId(sourcePerm.getUserId()); + targetPerm.setPermission(sourcePerm.getPermission()); + targetPerm.setTenantId(sourcePerm.getTenantId()); + targetPermissions.add(targetPerm); + } + + // 3. 批量保存 + if (CollectionUtils.isNotEmpty(targetPermissions)) { + permissionService.saveBatch(targetPermissions); + } + } + + /** + * 审批通过后更新文件标签 + */ + public void updateFileTagsAfterApproval(FileMetadataInfo metadata, FileMetadataInfo updateInfo, + IFileMetadataInfoService fileMetadataInfoService, + IFileTagRelService fileTagRelService) { + try { + Long tenantId = metadata.getTenantId(); + Long creatorId = metadata.getCreatorId(); + Long fileId = metadata.getId(); + + // 从 updateInfo 中获取标签缓存 + Map> dictTagIdsCache = updateInfo.getDictTagIdsCache(); + if (dictTagIdsCache == null || dictTagIdsCache.isEmpty()) { + return; + } + + // 删除旧标签关系(只删除当前租户的) + fileTagRelService.lambdaUpdate() + .eq(FileTagRel::getTenantId, tenantId) + .eq(FileTagRel::getFileId, fileId) + .remove(); + + // 查询当前目录及所有祖先目录 ID + Long dirId = updateInfo.getParentId(); + List dirIdAndAncestors = dirId != null ? collectDirIdAndAncestorIds(dirId, fileMetadataInfoService) : new ArrayList<>(); + + // 构建新标签关系(为当前目录及每个祖先目录各创建一条) + List newTagRelList = new ArrayList<>(); + Long fileSize = updateInfo.getFileSize() != null ? updateInfo.getFileSize() : 0L; + + for (Map.Entry> classEntry : dictTagIdsCache.entrySet()) { + Map valueMap = classEntry.getValue(); + + for (Integer dictId : valueMap.values()) { + if (dictId == null) { + continue; + } + + for (Long ancestorDirId : dirIdAndAncestors) { + FileTagRel tagRel = new FileTagRel(); + tagRel.setFileId(fileId); + tagRel.setTagId(dictId); + tagRel.setDirId(ancestorDirId); + tagRel.setTenantId(tenantId); + tagRel.setCreatorId(creatorId); + tagRel.setFileSize(fileSize); + newTagRelList.add(tagRel); + } + } + } + + // 批量插入新标签关系 + if (CollectionUtils.isNotEmpty(newTagRelList)) { + fileTagRelService.saveBatch(newTagRelList); + log.info("Approved and updated file tags for fileId: {}, total: {} tags", fileId, newTagRelList.size()); + } + } catch (Exception e) { + log.error("Failed to update file tags after approval for fileId: {}", metadata.getId(), e); + // 不抛出异常,避免影响审批流程 + } + } + + /** + * 收集当前目录及其所有祖先目录的 ID(从当前目录到根路径) + */ + private List collectDirIdAndAncestorIds(Long dirId, IFileMetadataInfoService fileMetadataInfoService) { + List dirIds = new ArrayList<>(); + Long currentId = dirId; + int maxDepth = 100; // 防止循环引用导致死循环 + while (currentId != null && currentId > 0 && dirIds.size() < maxDepth) { + dirIds.add(currentId); + FileMetadataInfo dirMeta = fileMetadataInfoService.getById(currentId); + if (dirMeta == null || dirMeta.getParentId() == null || dirMeta.getParentId() <= 0) { + break; + } + currentId = dirMeta.getParentId(); + } + return dirIds; + } +} diff --git a/data/src/main/java/com/sdm/data/service/impl/dataFileHandle/ModifyFileApproveStrategy.java b/data/src/main/java/com/sdm/data/service/impl/dataFileHandle/ModifyFileApproveStrategy.java index d1e0e04e..e76ecf96 100644 --- a/data/src/main/java/com/sdm/data/service/impl/dataFileHandle/ModifyFileApproveStrategy.java +++ b/data/src/main/java/com/sdm/data/service/impl/dataFileHandle/ModifyFileApproveStrategy.java @@ -4,204 +4,125 @@ import com.alibaba.fastjson2.JSONObject; import com.sdm.common.entity.constants.NumberConstants; import com.sdm.common.entity.enums.ApprovalFileDataStatusEnum; import com.sdm.common.entity.enums.ApproveFileDataTypeEnum; -import com.sdm.common.entity.req.data.FileMetadataExtensionRequest; -import com.sdm.common.entity.req.data.SimulationPoolInfo; -import com.sdm.data.model.entity.*; +import com.sdm.data.model.entity.FileMetadataInfo; +import com.sdm.data.model.entity.FileStorage; import com.sdm.data.service.*; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.ObjectUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Objects; @Service @Slf4j public class ModifyFileApproveStrategy implements ApproveStrategy { + + @Autowired + private FileModifyApproveHelper fileModifyApproveHelper; + + @Autowired + private IFileUserPermissionService fileUserPermissionService; + @Override + @Transactional(rollbackFor = Exception.class) public boolean handle(ApproveContext context) { int status = context.getApproveStatus(); - FileMetadataInfo backupHistory = context.getApproveMetadataInfos().get(0); + FileMetadataInfo currentFileMetadata = context.getApproveMetadataInfos().get(0); IMinioService minioService = context.getMinioService(); IFileMetadataInfoService fileMetadataInfoService = context.getFileMetadataInfoService(); IFileMetadataExtensionService fileMetadataExtensionService = context.getFileMetadataExtensionService(); - IFileUserPermissionService fileUserPermissionService = context.getFileUserPermissionService(); IFileStorageService fileStorageService = context.getFileStorageService(); IFileSimulationMappingService fileSimulationMappingService = context.getFileSimulationMappingService(); IFileTagRelService fileTagRelService = context.getFileTagRelService(); // 解析 tempMetadata 获取审批相关信息 - String tempMetadata = backupHistory.getTempMetadata(); - FileMetadataInfo updateInfo = JSONObject.parseObject(tempMetadata, FileMetadataInfo.class); + String tempMetadata = currentFileMetadata.getTempMetadata(); + FileMetadataInfo newVersionInfo = JSONObject.parseObject(tempMetadata, FileMetadataInfo.class); // 审批通过:主记录正式生效,备份行保留为历史版本(isLatest=false) if (NumberConstants.TWO == status) { - // updateInfo作为新记录顶替原来的老文件,复用老文件的id,需要更新扩展参数、标签、工况库映射、文件存储表的文件名等信息 + // 1. 备份:克隆当前主记录为历史行(新 ID),用于版本回溯 + // 必须新建一个对象进行复制,避免直接修改 currentFileMetadata 导致后续更新主表时 ID 丢失 + FileMetadataInfo historyFileInfo = new FileMetadataInfo(); + BeanUtils.copyProperties(currentFileMetadata, historyFileInfo); + historyFileInfo.setId(null); // ID 置空,插入新记录 + historyFileInfo.setIsLatest(false); + historyFileInfo.setApprovalStatus(null); + historyFileInfo.setApproveType(null); + historyFileInfo.setTempMetadata(null); + historyFileInfo.setUpdateTime(LocalDateTime.now()); + fileMetadataInfoService.save(historyFileInfo); + + // 1.1 复制原文件的权限到历史版本 + fileModifyApproveHelper.copyFilePermissions(currentFileMetadata.getId(), historyFileInfo.getId(), fileUserPermissionService); + + // 2. 更新附属信息 (扩展参数、标签、工况) // 处理扩展参数 - if(ObjectUtils.isNotEmpty(updateInfo.getFileMetadataExtensionRequest())){ - fileMetadataExtensionService.lambdaUpdate().eq(FileMetadataExtension::getTFilemetaId, updateInfo.getId()).remove(); + fileModifyApproveHelper.updateExtensions(currentFileMetadata.getId(), newVersionInfo.getFileMetadataExtensionRequest(), fileMetadataExtensionService); - List fileMetadataExtensionRequestList = updateInfo.getFileMetadataExtensionRequest(); - List fileMetadataExtensionList = new ArrayList<>(); - fileMetadataExtensionRequestList.forEach(extensionRequest -> { - FileMetadataExtension fileMetadataExtension = new FileMetadataExtension(); - fileMetadataExtension.setTFilemetaId(updateInfo.getId()); - fileMetadataExtension.setExtensionKey(extensionRequest.getExtensionKey()); - fileMetadataExtension.setExtensionValue(extensionRequest.getExtensionValue()); - fileMetadataExtension.setDataType(Objects.toString(extensionRequest.getDataType(), "string")); - fileMetadataExtensionList.add(fileMetadataExtension); - }); - fileMetadataExtensionService.saveBatch(fileMetadataExtensionList); + // 处理标签更新 + if (newVersionInfo.getDictTagIdsCache() != null && !newVersionInfo.getDictTagIdsCache().isEmpty()) { + fileModifyApproveHelper.updateFileTagsAfterApproval(currentFileMetadata, newVersionInfo, fileMetadataInfoService, fileTagRelService); } - // 处理标签更新(如果 tempMetadata 中包含标签信息) - if (updateInfo.getDictTagIdsCache() != null && !updateInfo.getDictTagIdsCache().isEmpty()) { - updateFileTagsAfterApproval(backupHistory, updateInfo, fileMetadataInfoService, fileTagRelService); - } - - //绑定文件和工况库的关系 - List simulationPoolInfoList = updateInfo.getSimulationPoolInfoList(); - if (CollectionUtils.isNotEmpty(simulationPoolInfoList)) { - for (SimulationPoolInfo simulationPoolInfo : simulationPoolInfoList) { - // 先删除原先所有的文件绑定关系 - fileSimulationMappingService.lambdaUpdate() - .eq (FileSimulationMapping::getSimulationPoolId, simulationPoolInfo.getSimulationPoolId()) - .eq (FileSimulationMapping::getSimulationPoolVersion, simulationPoolInfo.getSimulationPoolVersion()) - .eq(FileSimulationMapping::getFileId, updateInfo.getId()).remove(); - for (String simulationPoolTaskId : simulationPoolInfo.getSimulationPoolTaskIds()) { - FileSimulationMapping fileSimulationMapping = new FileSimulationMapping(); - fileSimulationMapping.setFileId(updateInfo.getId()); - fileSimulationMapping.setSimulationPoolId(simulationPoolInfo.getSimulationPoolId()); - fileSimulationMapping.setSimulationPoolVersion(simulationPoolInfo.getSimulationPoolVersion()); - fileSimulationMapping.setSimulationPoolTaskId(simulationPoolTaskId); - fileSimulationMappingService.save(fileSimulationMapping); - } - } - } + // 绑定文件和工况库的关系 + fileModifyApproveHelper.updateSimulationMappings(currentFileMetadata.getId(), newVersionInfo.getSimulationPoolInfoList(), fileSimulationMappingService); // 更新文件存储信息 fileStorageService.lambdaUpdate() - .eq(FileStorage::getFileId, updateInfo.getId()) - .set(FileStorage::getFileName, updateInfo.getOriginalName()) + .eq(FileStorage::getFileId, currentFileMetadata.getId()) + .set(FileStorage::getFileName, newVersionInfo.getOriginalName()) .update(); - updateInfo.setIsLatest(true); - updateInfo.setTempMetadata( null); - updateInfo.setApproveType(ApproveFileDataTypeEnum.COMPLETED.getCode()); - updateInfo.setApprovalStatus(ApprovalFileDataStatusEnum.APPROVED.getKey()); + // 3. 更新主记录为新版本数据 + // 锁定主记录 ID,更新核心字段 + FileMetadataInfo updateEntity = new FileMetadataInfo(); + updateEntity.setId(currentFileMetadata.getId()); + + // 复制关键元数据(新文件路径、版本号、大小、名称等) + updateEntity.setObjectKey(newVersionInfo.getObjectKey()); + updateEntity.setOriginalName(newVersionInfo.getOriginalName()); + updateEntity.setFileSize(newVersionInfo.getFileSize()); + updateEntity.setVersionNo(newVersionInfo.getVersionNo()); + + // 复制业务属性 + updateEntity.setProjectId(newVersionInfo.getProjectId()); + updateEntity.setAnalysisDirectionId(newVersionInfo.getAnalysisDirectionId()); + updateEntity.setRemarks(newVersionInfo.getRemarks()); + + // 更新状态 + updateEntity.setIsLatest(true); + updateEntity.setTempMetadata(null); + updateEntity.setApproveType(ApproveFileDataTypeEnum.COMPLETED.getCode()); + updateEntity.setApprovalStatus(ApprovalFileDataStatusEnum.APPROVED.getKey()); + updateEntity.setUpdateTime(LocalDateTime.now()); + + fileMetadataInfoService.updateById(updateEntity); - // backupHistory作为历史备份, 更新为历史版本,设置新id, - backupHistory.setId(null); - backupHistory.setIsLatest(false); - backupHistory.setApprovalStatus(null); - backupHistory.setApproveType(null); - backupHistory.setUpdateTime(LocalDateTime.now()); - backupHistory.setTempMetadata(null); - fileMetadataInfoService.save(backupHistory); return true; } // 审批不通过,删除新 MinIO 临时文件对象 if (NumberConstants.THREE == status) { // 1. 删除临时文件 - minioService.deleteFile(updateInfo.getObjectKey(), updateInfo.getBucketName()); - backupHistory.setTempMetadata(null); - backupHistory.setApprovalStatus(ApprovalFileDataStatusEnum.REJECTED.getKey()); - backupHistory.setApproveType(ApproveFileDataTypeEnum.COMPLETED.getCode()); - backupHistory.setIsLatest(true); - backupHistory.setUpdateTime(LocalDateTime.now()); - fileMetadataInfoService.updateById(backupHistory); + if (newVersionInfo != null && newVersionInfo.getObjectKey() != null) { + minioService.deleteFile(newVersionInfo.getObjectKey(), newVersionInfo.getBucketName()); + } + + // 2. 更新主记录状态 + fileMetadataInfoService.lambdaUpdate() + .eq(FileMetadataInfo::getId, currentFileMetadata.getId()) + .set(FileMetadataInfo::getTempMetadata, null) + .set(FileMetadataInfo::getApprovalStatus, ApprovalFileDataStatusEnum.REJECTED.getKey()) + .set(FileMetadataInfo::getApproveType, ApproveFileDataTypeEnum.COMPLETED.getCode()) + .set(FileMetadataInfo::getUpdateTime, LocalDateTime.now()) + .update(); return true; } return false; } - - /** - * 审批通过后更新文件标签 - * 从 updateInfo 中获取标签信息并更新到 file_tag_rel 表 - * 为当前文件所在目录及其所有祖先目录创建标签关系 - */ - private void updateFileTagsAfterApproval(FileMetadataInfo metadata, FileMetadataInfo updateInfo, - IFileMetadataInfoService fileMetadataInfoService, - IFileTagRelService fileTagRelService) { - try { - Long tenantId = metadata.getTenantId(); - Long creatorId = metadata.getCreatorId(); - Long fileId = metadata.getId(); - - // 从 updateInfo 中获取标签缓存 - Map> dictTagIdsCache = updateInfo.getDictTagIdsCache(); - if (dictTagIdsCache == null || dictTagIdsCache.isEmpty()) { - return; - } - - // 删除旧标签关系(只删除当前租户的) - fileTagRelService.lambdaUpdate() - .eq(FileTagRel::getTenantId, tenantId) - .eq(FileTagRel::getFileId, fileId) - .remove(); - - // 查询当前目录及所有祖先目录 ID - Long dirId = updateInfo.getParentId(); - List dirIdAndAncestors = dirId != null ? collectDirIdAndAncestorIds(dirId, fileMetadataInfoService) : new ArrayList<>(); - - // 构建新标签关系(为当前目录及每个祖先目录各创建一条) - List newTagRelList = new ArrayList<>(); - Long fileSize = updateInfo.getFileSize() != null ? updateInfo.getFileSize() : 0L; - - for (Map.Entry> classEntry : dictTagIdsCache.entrySet()) { - Map valueMap = classEntry.getValue(); - - for (Integer dictId : valueMap.values()) { - if (dictId == null) { - continue; - } - - for (Long ancestorDirId : dirIdAndAncestors) { - FileTagRel tagRel = new FileTagRel(); - tagRel.setFileId(fileId); - tagRel.setTagId(dictId); - tagRel.setDirId(ancestorDirId); - tagRel.setTenantId(tenantId); - tagRel.setCreatorId(creatorId); - tagRel.setFileSize(fileSize); - newTagRelList.add(tagRel); - } - } - } - - // 批量插入新标签关系 - if (CollectionUtils.isNotEmpty(newTagRelList)) { - fileTagRelService.saveBatch(newTagRelList); - log.info("Approved and updated file tags for fileId: {}, total: {} tags", fileId, newTagRelList.size()); - } - } catch (Exception e) { - log.error("Failed to update file tags after approval for fileId: {}", metadata.getId(), e); - // 不抛出异常,避免影响审批流程 - } - } - - /** - * 收集当前目录及其所有祖先目录的 ID(从当前目录到根路径) - */ - private List collectDirIdAndAncestorIds(Long dirId, IFileMetadataInfoService fileMetadataInfoService) { - List dirIds = new ArrayList<>(); - Long currentId = dirId; - int maxDepth = 100; // 防止循环引用导致死循环 - while (currentId != null && currentId > 0 && dirIds.size() < maxDepth) { - dirIds.add(currentId); - FileMetadataInfo dirMeta = fileMetadataInfoService.getById(currentId); - if (dirMeta == null || dirMeta.getParentId() == null || dirMeta.getParentId() <= 0) { - break; - } - currentId = dirMeta.getParentId(); - } - return dirIds; - } -} \ No newline at end of file +} diff --git a/data/src/main/java/com/sdm/data/service/impl/dataFileHandle/ModifyMetadataApproveStrategy.java b/data/src/main/java/com/sdm/data/service/impl/dataFileHandle/ModifyMetadataApproveStrategy.java index 85c6aa17..54140861 100644 --- a/data/src/main/java/com/sdm/data/service/impl/dataFileHandle/ModifyMetadataApproveStrategy.java +++ b/data/src/main/java/com/sdm/data/service/impl/dataFileHandle/ModifyMetadataApproveStrategy.java @@ -4,32 +4,26 @@ import com.alibaba.fastjson2.JSONObject; import com.sdm.common.entity.constants.NumberConstants; import com.sdm.common.entity.enums.ApprovalFileDataStatusEnum; import com.sdm.common.entity.enums.ApproveFileDataTypeEnum; -import com.sdm.common.entity.req.data.FileMetadataExtensionRequest; -import com.sdm.common.entity.req.data.SimulationPoolInfo; -import com.sdm.data.model.entity.FileMetadataExtension; import com.sdm.data.model.entity.FileMetadataInfo; -import com.sdm.data.model.entity.FileSimulationMapping; -import com.sdm.data.model.entity.FileTagRel; import com.sdm.data.service.IFileMetadataExtensionService; import com.sdm.data.service.IFileMetadataInfoService; import com.sdm.data.service.IFileSimulationMappingService; import com.sdm.data.service.IFileTagRelService; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.ObjectUtils; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Objects; +import org.springframework.transaction.annotation.Transactional; @Service @Slf4j public class ModifyMetadataApproveStrategy implements ApproveStrategy { + + @Autowired + private FileModifyApproveHelper fileModifyApproveHelper; + @Override + @Transactional(rollbackFor = Exception.class) public boolean handle(ApproveContext context) { -// FileMetadataInfo metadata = context.getApproveMetadataInfo(); FileMetadataInfo metadata = context.getApproveMetadataInfos().get(0); int status = context.getApproveStatus(); IFileMetadataInfoService service = context.getFileMetadataInfoService(); @@ -52,47 +46,16 @@ public class ModifyMetadataApproveStrategy implements ApproveStrategy { .set(FileMetadataInfo::getApproveType, ApproveFileDataTypeEnum.COMPLETED.getCode()) .update(); - //绑定文件和工况库的关系 - List simulationPoolInfoList = updateInfo.getSimulationPoolInfoList(); - if (CollectionUtils.isNotEmpty(simulationPoolInfoList)) { - for (SimulationPoolInfo simulationPoolInfo : simulationPoolInfoList) { - // 先删除原先所有的文件绑定关系 - fileSimulationMappingService.lambdaUpdate() - .eq (FileSimulationMapping::getSimulationPoolId, simulationPoolInfo.getSimulationPoolId()) - .eq (FileSimulationMapping::getSimulationPoolVersion, simulationPoolInfo.getSimulationPoolVersion()) - .eq(FileSimulationMapping::getFileId, metadata.getId()).remove(); - for (String simulationPoolTaskId : simulationPoolInfo.getSimulationPoolTaskIds()) { - FileSimulationMapping fileSimulationMapping = new FileSimulationMapping(); - fileSimulationMapping.setFileId(metadata.getId()); - fileSimulationMapping.setSimulationPoolId(simulationPoolInfo.getSimulationPoolId()); - fileSimulationMapping.setSimulationPoolVersion(simulationPoolInfo.getSimulationPoolVersion()); - fileSimulationMapping.setSimulationPoolTaskId(simulationPoolTaskId); - fileSimulationMappingService.save(fileSimulationMapping); - } - } - } + // 绑定文件和工况库的关系 + fileModifyApproveHelper.updateSimulationMappings(metadata.getId(), updateInfo.getSimulationPoolInfoList(), fileSimulationMappingService); // 处理标签更新(如果 tempMetadata 中包含标签信息) if (updateInfo.getDictTagIdsCache() != null && !updateInfo.getDictTagIdsCache().isEmpty()) { - updateFileTagsAfterApproval(metadata, updateInfo, service, fileTagRelService); + fileModifyApproveHelper.updateFileTagsAfterApproval(metadata, updateInfo, service, fileTagRelService); } // 处理扩展参数 - if(ObjectUtils.isNotEmpty(updateInfo.getFileMetadataExtensionRequest())){ - fileMetadataExtensionService.lambdaUpdate().eq(FileMetadataExtension::getTFilemetaId, metadata.getId()).remove(); - - List fileMetadataExtensionRequestList = updateInfo.getFileMetadataExtensionRequest(); - List fileMetadataExtensionList = new ArrayList<>(); - fileMetadataExtensionRequestList.forEach(extensionRequest -> { - FileMetadataExtension fileMetadataExtension = new FileMetadataExtension(); - fileMetadataExtension.setTFilemetaId(metadata.getId()); - fileMetadataExtension.setExtensionKey(extensionRequest.getExtensionKey()); - fileMetadataExtension.setExtensionValue(extensionRequest.getExtensionValue()); - fileMetadataExtension.setDataType(Objects.toString(extensionRequest.getDataType(), "string")); - fileMetadataExtensionList.add(fileMetadataExtension); - }); - fileMetadataExtensionService.saveBatch(fileMetadataExtensionList); - } + fileModifyApproveHelper.updateExtensions(metadata.getId(), updateInfo.getFileMetadataExtensionRequest(), fileMetadataExtensionService); return true; } @@ -108,87 +71,4 @@ public class ModifyMetadataApproveStrategy implements ApproveStrategy { } return false; } - - /** - * 审批通过后更新文件标签 - * 从 updateInfo 中获取标签信息并更新到 file_tag_rel 表 - * 为当前文件所在目录及其所有祖先目录创建标签关系 - */ - private void updateFileTagsAfterApproval(FileMetadataInfo metadata, FileMetadataInfo updateInfo, - IFileMetadataInfoService fileMetadataInfoService, - IFileTagRelService fileTagRelService) { - try { - Long tenantId = metadata.getTenantId(); - Long creatorId = metadata.getCreatorId(); - Long fileId = metadata.getId(); - - // 从 updateInfo 中获取标签缓存 - Map> dictTagIdsCache = updateInfo.getDictTagIdsCache(); - if (dictTagIdsCache == null || dictTagIdsCache.isEmpty()) { - return; - } - - // 删除旧标签关系(只删除当前租户的) - fileTagRelService.lambdaUpdate() - .eq(FileTagRel::getTenantId, tenantId) - .eq(FileTagRel::getFileId, fileId) - .remove(); - - // 查询当前目录及所有祖先目录 ID - Long dirId = updateInfo.getParentId(); - List dirIdAndAncestors = dirId != null ? collectDirIdAndAncestorIds(dirId, fileMetadataInfoService) : new ArrayList<>(); - - // 构建新标签关系(为当前目录及每个祖先目录各创建一条) - List newTagRelList = new ArrayList<>(); - Long fileSize = updateInfo.getFileSize() != null ? updateInfo.getFileSize() : 0L; - - for (Map.Entry> classEntry : dictTagIdsCache.entrySet()) { - Map valueMap = classEntry.getValue(); - - for (Integer dictId : valueMap.values()) { - if (dictId == null) { - continue; - } - - for (Long ancestorDirId : dirIdAndAncestors) { - FileTagRel tagRel = new FileTagRel(); - tagRel.setFileId(fileId); - tagRel.setTagId(dictId); - tagRel.setDirId(ancestorDirId); - tagRel.setTenantId(tenantId); - tagRel.setCreatorId(creatorId); - tagRel.setFileSize(fileSize); - newTagRelList.add(tagRel); - } - } - } - - // 批量插入新标签关系 - if (CollectionUtils.isNotEmpty(newTagRelList)) { - fileTagRelService.saveBatch(newTagRelList); - log.info("Approved and updated file tags for fileId: {}, total: {} tags", fileId, newTagRelList.size()); - } - } catch (Exception e) { - log.error("Failed to update file tags after approval for fileId: {}", metadata.getId(), e); - // 不抛出异常,避免影响审批流程 - } - } - - /** - * 收集当前目录及其所有祖先目录的 ID(从当前目录到根路径) - */ - private List collectDirIdAndAncestorIds(Long dirId, IFileMetadataInfoService fileMetadataInfoService) { - List dirIds = new ArrayList<>(); - Long currentId = dirId; - int maxDepth = 100; // 防止循环引用导致死循环 - while (currentId != null && currentId > 0 && dirIds.size() < maxDepth) { - dirIds.add(currentId); - FileMetadataInfo dirMeta = fileMetadataInfoService.getById(currentId); - if (dirMeta == null || dirMeta.getParentId() == null || dirMeta.getParentId() <= 0) { - break; - } - currentId = dirMeta.getParentId(); - } - return dirIds; - } -} \ No newline at end of file +}