package com.ruoyi.business.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.basic.entity.StorageAttachment; import com.ruoyi.basic.entity.StorageBlob; import com.ruoyi.basic.entity.dto.StorageBlobDTO; import com.ruoyi.basic.mapper.StorageAttachmentMapper; import com.ruoyi.basic.mapper.StorageBlobMapper; import com.ruoyi.basic.service.StorageAttachmentService; import com.ruoyi.business.dto.ArchiveDto; import com.ruoyi.business.entity.Archive; import com.ruoyi.business.mapper.ArchiveMapper; import com.ruoyi.business.service.ArchiveService; import com.ruoyi.common.utils.bean.BeanUtils; import com.ruoyi.common.utils.file.MinioUtils; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; import static com.ruoyi.common.constant.StorageAttachmentConstants.StorageAttachmentFile; import static com.ruoyi.common.enums.StorageAttachmentRecordType.Archives; /** *

* 档案信息表,记录系统中各类档案的基本信息 服务实现类 *

* * @author ruoyi * @since 2025-06-10 */ @Service @RequiredArgsConstructor public class ArchiveServiceImpl extends ServiceImpl implements ArchiveService { private final ArchiveMapper archiveMapper; private final StorageAttachmentService storageAttachmentService; private final StorageBlobMapper storageBlobMapper; private final StorageAttachmentMapper storageAttachmentMapper; private final MinioUtils minioUtils; @Override public IPage selectArchiveList(Page page, ArchiveDto archiveDto) { // 1. 分页查询主数据 LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.orderByDesc(Archive::getCreateTime); IPage archivePage = archiveMapper.selectPage(page, queryWrapper); // 2. 无数据提前返回 if (CollectionUtils.isEmpty(archivePage.getRecords())) { return new Page<>(archivePage.getCurrent(), archivePage.getSize(), archivePage.getTotal()); } // 3. 批量获取所有档案ID List archiveIds = archivePage.getRecords() .stream() .map(Archive::getId) .collect(Collectors.toList()); // 4. 批量查询附件映射关系(避免N+1) List storageAttachments = storageAttachmentMapper .selectList(new LambdaQueryWrapper() .in(StorageAttachment::getRecordId, archiveIds) .eq(StorageAttachment::getRecordType, Archives.ordinal()) ); Map> attachmentsMap = storageAttachmentMapper .selectList(new LambdaQueryWrapper() .in(StorageAttachment::getRecordId, archiveIds) .eq(StorageAttachment::getRecordType, Archives.ordinal()) ).stream() .collect(Collectors.groupingBy(StorageAttachment::getRecordId)); // 5. 批量查询所有需要的文件数据 Set blobIds = attachmentsMap.values() .stream() .flatMap(List::stream) .map(StorageAttachment::getStorageBlobId) .collect(Collectors.toSet()); Map blobMap = blobIds.isEmpty() ? Collections.emptyMap() : storageBlobMapper.selectList(new LambdaQueryWrapper().in(StorageBlob::getId, blobIds)) .stream() .collect(Collectors.toMap(StorageBlob::getId, Function.identity())); // 6. 组装DTO(单次循环完成数据装配) List dtoList = archivePage.getRecords().stream().map(archive -> { ArchiveDto dto = new ArchiveDto(); BeanUtils.copyProperties(archive, dto); // 复制主对象属性 // 按需添加附件信息 List blobDTOs = Optional.ofNullable(attachmentsMap.get(archive.getId())) .orElse(Collections.emptyList()) .stream() .map(att -> blobMap.get(att.getStorageBlobId())) .filter(Objects::nonNull) .map(blob -> { StorageBlobDTO blobDTO = new StorageBlobDTO(); BeanUtils.copyProperties(blob, blobDTO); // 动态生成预览地址和下载地址 // 设置预览URL blobDTO.setUrl(minioUtils.getPreviewUrls( blob.getBucketFilename(), blob.getBucketName(), true )); // 设置下载URL blobDTO.setDownloadUrl(minioUtils.getDownloadUrls( blob.getBucketFilename(), blob.getBucketName(), blob.getOriginalFilename(), // 原始文件名 true )); return blobDTO; }) .collect(Collectors.toList()); dto.setStorageBlobDTO(blobDTOs); return dto; }).collect(Collectors.toList()); // 7. 构建返回分页对象 IPage resultPage = new Page<>(); resultPage.setRecords(dtoList); return resultPage; } @Override public int addOrEditArchive(ArchiveDto archiveDto) { Archive archive = new Archive(); BeanUtils.copyProperties(archiveDto, archive); int i; if (Objects.isNull(archiveDto.getId())) { i = archiveMapper.insert(archive); } else { i = archiveMapper.updateById(archive); } if (archiveDto.getStorageBlobDTO() != null && !archiveDto.getStorageBlobDTO().isEmpty()) { List attachments = new ArrayList<>(); for (StorageBlobDTO storageBlobDTO : archiveDto.getStorageBlobDTO()) { StorageAttachment storageAttachment = new StorageAttachment( StorageAttachmentFile, (long) Archives.ordinal(), archive.getId() ); storageAttachment.setStorageBlobDTO(storageBlobDTO); attachments.add(storageAttachment); } storageAttachmentService.saveStorageAttachment(attachments, archive.getId(), Archives, StorageAttachmentFile); } return i; } @Override public int delByIds(Long[] ids) { // 检查参数 if (ids == null || ids.length == 0) { return 0; } // 构造更新条件 UpdateWrapper updateWrapper = new UpdateWrapper<>(); updateWrapper.in("id", ids) .set("deleted", 1); // 设置 deleted 为 1 表示已删除 // 执行批量逻辑删除 return archiveMapper.update(null, updateWrapper); } @Override public List fileList(ArchiveDto archiveDto) { List storageAttachments = storageAttachmentService.selectStorageAttachments(archiveDto.getId(), Archives, StorageAttachmentFile); return storageAttachments; } }