diff --git a/fs-framework/fs-common-core/src/main/java/com/xddcodec/fs/framework/common/constant/CommonConstant.java b/fs-framework/fs-common-core/src/main/java/com/xddcodec/fs/framework/common/constant/CommonConstant.java index 4e26bc6d80794467c09cf542d751fe15b3f5ffc3..f94c7909d5866bce2aba71d548d5110044fc04ac 100644 --- a/fs-framework/fs-common-core/src/main/java/com/xddcodec/fs/framework/common/constant/CommonConstant.java +++ b/fs-framework/fs-common-core/src/main/java/com/xddcodec/fs/framework/common/constant/CommonConstant.java @@ -42,5 +42,5 @@ public interface CommonConstant { /** * 验证码长度 */ - Integer VERIFY_CODE_LENGTH = 4; + Integer VERIFY_CODE_LENGTH = 6; } diff --git a/fs-framework/fs-notify/src/main/java/com/xddcodec/fs/framework/notify/mail/service/NoOpJavaMailSender.java b/fs-framework/fs-notify/src/main/java/com/xddcodec/fs/framework/notify/mail/service/NoOpJavaMailSender.java index 2461ac56f6ea4e29c6e29ea2023f1a49dd43e460..35ffdccdd05b9a216d0c96da7d250dcb75e5fe79 100644 --- a/fs-framework/fs-notify/src/main/java/com/xddcodec/fs/framework/notify/mail/service/NoOpJavaMailSender.java +++ b/fs-framework/fs-notify/src/main/java/com/xddcodec/fs/framework/notify/mail/service/NoOpJavaMailSender.java @@ -1,37 +1,85 @@ package com.xddcodec.fs.framework.notify.mail.service; - +import jakarta.mail.Session; import jakarta.mail.internet.MimeMessage; +import lombok.extern.slf4j.Slf4j; import org.springframework.mail.MailException; import org.springframework.mail.SimpleMailMessage; import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.MimeMessagePreparator; import java.io.InputStream; +import java.util.Properties; /** - * - * @author Yann - * @date 2025/11/20 11:31 + * 空邮件发送器 - 用于禁用邮件功能时拦截邮件发送 */ +@Slf4j public class NoOpJavaMailSender implements JavaMailSender { + private static final Session DUMMY_SESSION = Session.getInstance(new Properties()); + @Override public MimeMessage createMimeMessage() { - return null; + return new MimeMessage(DUMMY_SESSION); } @Override public MimeMessage createMimeMessage(InputStream contentStream) throws MailException { - return null; + try { + return new MimeMessage(DUMMY_SESSION, contentStream); + } catch (Exception e) { + log.warn("创建 MimeMessage 失败(空邮件发送器)", e); + return new MimeMessage(DUMMY_SESSION); + } + } + + @Override + public void send(MimeMessage mimeMessage) throws MailException { + log.info("[空邮件发送器] 拦截邮件发送(MimeMessage)"); + logMailInfo(mimeMessage); } @Override public void send(MimeMessage... mimeMessages) throws MailException { + log.info("[空邮件发送器] 拦截批量邮件发送,数量: {}", mimeMessages.length); + for (MimeMessage msg : mimeMessages) { + logMailInfo(msg); + } + } + + @Override + public void send(MimeMessagePreparator mimeMessagePreparator) throws MailException { + log.info("[空邮件发送器] 拦截邮件发送(MimeMessagePreparator)"); + } + @Override + public void send(MimeMessagePreparator... mimeMessagePreparators) throws MailException { + log.info("[空邮件发送器] 拦截批量邮件发送,数量: {}", mimeMessagePreparators.length); + } + + @Override + public void send(SimpleMailMessage simpleMessage) throws MailException { + log.info("[空邮件发送器] 拦截简单邮件发送: 收件人={}, 主题={}", + simpleMessage.getTo(), simpleMessage.getSubject()); } @Override public void send(SimpleMailMessage... simpleMessages) throws MailException { + log.info("[空邮件发送器] 拦截批量简单邮件发送,数量: {}", simpleMessages.length); + } + /** + * 记录邮件信息(方便调试) + */ + private void logMailInfo(MimeMessage message) { + try { + log.info(" → 收件人: {}", message.getAllRecipients() != null ? + String.join(", ", java.util.Arrays.stream(message.getAllRecipients()) + .map(Object::toString).toArray(String[]::new)) : "无"); + log.info(" → 主题: {}", message.getSubject()); + } catch (Exception e) { + log.debug("解析邮件信息失败", e); + } } } diff --git a/fs-framework/fs-preview/src/main/java/com/xddcodec/fs/framework/preview/converter/impl/OfficeToPdfConverter.java b/fs-framework/fs-preview/src/main/java/com/xddcodec/fs/framework/preview/converter/impl/OfficeToPdfConverter.java index 330dc63b4123288e3cdf3c0fd89f78cc370602fb..32b3d5f676c7c419092ae900f1c892f651bb8679 100644 --- a/fs-framework/fs-preview/src/main/java/com/xddcodec/fs/framework/preview/converter/impl/OfficeToPdfConverter.java +++ b/fs-framework/fs-preview/src/main/java/com/xddcodec/fs/framework/preview/converter/impl/OfficeToPdfConverter.java @@ -8,7 +8,6 @@ import org.jodconverter.core.DocumentConverter; import org.jodconverter.core.office.OfficeException; import org.jodconverter.core.office.OfficeManager; import org.jodconverter.local.LocalConverter; -import org.springframework.stereotype.Component; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -19,7 +18,6 @@ import java.nio.file.Path; import java.util.UUID; @Slf4j -@Component @RequiredArgsConstructor public class OfficeToPdfConverter implements IConverter { diff --git a/fs-framework/fs-preview/src/main/java/com/xddcodec/fs/framework/preview/office/JodConverterConfiguration.java b/fs-framework/fs-preview/src/main/java/com/xddcodec/fs/framework/preview/office/JodConverterConfiguration.java index 9b1155bc1699d6fa6e8201a5c7a641786d0e9a25..7ffbe548ddd119ed0de25ab93464139101727716 100644 --- a/fs-framework/fs-preview/src/main/java/com/xddcodec/fs/framework/preview/office/JodConverterConfiguration.java +++ b/fs-framework/fs-preview/src/main/java/com/xddcodec/fs/framework/preview/office/JodConverterConfiguration.java @@ -1,5 +1,7 @@ package com.xddcodec.fs.framework.preview.office; +import com.xddcodec.fs.framework.preview.converter.impl.OfficeToPdfConverter; +import com.xddcodec.fs.framework.preview.strategy.impl.OfficePreviewStrategy; import jakarta.annotation.PreDestroy; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -14,7 +16,7 @@ import java.io.File; @Slf4j @Configuration @RequiredArgsConstructor -@ConditionalOnProperty(prefix = "file.preview.office", name = "enabled", havingValue = "true", matchIfMissing = true) +@ConditionalOnProperty(prefix = "fs.preview.office", name = "enabled", havingValue = "true", matchIfMissing = true) public class JodConverterConfiguration { private final OfficeToPdfConfig config; @@ -51,6 +53,16 @@ public class JodConverterConfiguration { return officeManager; } + @Bean + public OfficeToPdfConverter officeToPdfConverter(OfficeManager officeManager, OfficeToPdfConfig config) { + return new OfficeToPdfConverter(officeManager, config); + } + + @Bean + public OfficePreviewStrategy officePreviewStrategy(OfficeToPdfConverter officeToPdfConverter) { + return new OfficePreviewStrategy(officeToPdfConverter); + } + /** * 确保项目关闭时,LibreOffice 也能关闭 */ diff --git a/fs-framework/fs-preview/src/main/java/com/xddcodec/fs/framework/preview/strategy/impl/OfficePreviewStrategy.java b/fs-framework/fs-preview/src/main/java/com/xddcodec/fs/framework/preview/strategy/impl/OfficePreviewStrategy.java index c4b942406c311a889d0782915d63af64d292a77d..61a190594de499fbc5ed18e972389a0f94e89f46 100644 --- a/fs-framework/fs-preview/src/main/java/com/xddcodec/fs/framework/preview/strategy/impl/OfficePreviewStrategy.java +++ b/fs-framework/fs-preview/src/main/java/com/xddcodec/fs/framework/preview/strategy/impl/OfficePreviewStrategy.java @@ -8,11 +8,9 @@ import com.xddcodec.fs.framework.preview.core.PreviewContext; import com.xddcodec.fs.framework.preview.strategy.AbstractPreviewStrategy; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; import org.springframework.ui.Model; @Slf4j -@Component @RequiredArgsConstructor public class OfficePreviewStrategy extends AbstractPreviewStrategy { diff --git a/fs-framework/fs-preview/src/main/resources/templates/preview/unsupported.html b/fs-framework/fs-preview/src/main/resources/templates/preview/unsupported.html index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..cb3724dd7218e8df667654d1ce3b4fff555d4165 100644 --- a/fs-framework/fs-preview/src/main/resources/templates/preview/unsupported.html +++ b/fs-framework/fs-preview/src/main/resources/templates/preview/unsupported.html @@ -0,0 +1,161 @@ + + + + + + 文件无法预览 + + + +
+
+ + + +
+ +

+ +

+ 文件 无法在线打开。
+ 您可以下载文件到本地进行查看。 +

+ +
+ +
+
+ + + + \ No newline at end of file diff --git a/fs-modules/fs-file/src/main/java/com/xddcodec/fs/file/domain/vo/FileTransferTaskVO.java b/fs-modules/fs-file/src/main/java/com/xddcodec/fs/file/domain/vo/FileTransferTaskVO.java index 69af7efa067a1c489e2ea38292301b77c5675747..7ff69dec87014cadb30aedffc29d5d663d5347fd 100644 --- a/fs-modules/fs-file/src/main/java/com/xddcodec/fs/file/domain/vo/FileTransferTaskVO.java +++ b/fs-modules/fs-file/src/main/java/com/xddcodec/fs/file/domain/vo/FileTransferTaskVO.java @@ -3,6 +3,7 @@ package com.xddcodec.fs.file.domain.vo; import com.fasterxml.jackson.annotation.JsonFormat; import com.xddcodec.fs.file.domain.FileTransferTask; import com.xddcodec.fs.file.enums.TransferTaskStatus; +import com.xddcodec.fs.file.enums.TransferTaskType; import com.xddcodec.fs.framework.common.utils.DateUtils; import io.github.linpeilie.annotations.AutoMapper; import lombok.Data; @@ -22,6 +23,10 @@ public class FileTransferTaskVO implements Serializable { * 任务ID */ private String taskId; + /** + * 任务类型 + */ + private TransferTaskType taskType; /** * 用户ID */ diff --git a/fs-modules/fs-file/src/main/java/com/xddcodec/fs/file/service/impl/FileInfoServiceImpl.java b/fs-modules/fs-file/src/main/java/com/xddcodec/fs/file/service/impl/FileInfoServiceImpl.java index 1994daec61f179803bc132c93eb10b48ee29ee5d..3d642498327a4ff8ae74e9306fa929fba19ce80c 100644 --- a/fs-modules/fs-file/src/main/java/com/xddcodec/fs/file/service/impl/FileInfoServiceImpl.java +++ b/fs-modules/fs-file/src/main/java/com/xddcodec/fs/file/service/impl/FileInfoServiceImpl.java @@ -30,6 +30,8 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.support.TransactionSynchronization; +import org.springframework.transaction.support.TransactionSynchronizationManager; import java.io.InputStream; import java.time.LocalDateTime; @@ -443,31 +445,43 @@ public class FileInfoServiceImpl extends ServiceImpl i if (CollUtil.isEmpty(fileIds)) { return; } - String userId = StpUtil.getLoginIdAsString(); - Set allFileIds = collectFileIdsRecursively( fileIds, userId, wrapper -> wrapper.and(FILE_INFO.IS_DELETED.eq(true)) // 只能删除回收站中的 ); - if (CollUtil.isEmpty(allFileIds)) { throw new BusinessException("未找到要删除的文件或文件夹"); } + List physicalFilesToDelete = new ArrayList<>(); + for (String allFileId : allFileIds) { + FileInfo fileInfo = getById(allFileId); + String objectKey = fileInfo.getObjectKey(); - // 查询所有文件信息(用于删除物理文件) - List allFiles = listByIds(allFileIds); + long count = this.count(new QueryWrapper() + .where(FILE_INFO.OBJECT_KEY.eq(objectKey) + .and(FILE_INFO.ID.ne(allFileId)))); // 排除当前要删除的 - // 批量删除物理文件 - allFiles.stream() - .filter(file -> !file.getIsDir()) - .forEach(this::deletePhysicalFile); - - // 批量删除数据库记录 + if (count == 0) { + physicalFilesToDelete.add(fileInfo); + } + } removeByIds(allFileIds); - - log.info("用户 {} 永久删除文件/文件夹,共 {} 项", userId, allFileIds.size()); + TransactionSynchronizationManager.registerSynchronization( + new TransactionSynchronization() { + @Override + public void afterCommit() { + for (FileInfo file : physicalFilesToDelete) { + try { + deletePhysicalFile(file); + } catch (Exception e) { + log.error("删除物理文件失败: {}", file.getObjectKey(), e); + } + } + } + } + ); } @Transactional(rollbackFor = Exception.class)