package com.ruoyi.business.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 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.QrCodeDto; import com.ruoyi.business.dto.QrCodeScanRecordDto; import com.ruoyi.business.entity.Archive; import com.ruoyi.business.entity.QrCode; import com.ruoyi.business.entity.QrCodeScanRecord; import com.ruoyi.business.mapper.QrCodeMapper; import com.ruoyi.business.mapper.QrCodeScanRecordMapper; import com.ruoyi.business.service.QrCodeScanRecordService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.utils.bean.BeanUtils; import com.ruoyi.common.utils.file.MinioUtils; import com.ruoyi.system.mapper.SysUserMapper; import org.springframework.stereotype.Service; import lombok.RequiredArgsConstructor; 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; import static com.ruoyi.common.enums.StorageAttachmentRecordType.QrCodeScanRecords; /** *

* 二维码扫码记录表 服务实现类 *

* * @author ld * @since 2025-06-24 */ @Service @RequiredArgsConstructor public class QrCodeScanRecordServiceImpl extends ServiceImpl implements QrCodeScanRecordService { private final QrCodeScanRecordMapper qrCodeScanRecordMapper; private final QrCodeMapper qrCodeMapper; private final StorageAttachmentService storageAttachmentService; private final StorageBlobMapper storageBlobMapper; private final StorageAttachmentMapper storageAttachmentMapper; private final MinioUtils minioUtils; private final SysUserMapper sysUserMapper; @Override public IPage selectQrCodeScanRecordList(Page page, QrCodeScanRecordDto qrCodeScanRecordDto) { // 1. 构建基础查询条件 LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.orderByDesc(QrCodeScanRecord::getCreateTime); // 2. 执行分页查询 IPage scanRecordIPage = qrCodeScanRecordMapper.selectPage(page, queryWrapper); // 3. 无数据提前返回 if (CollectionUtils.isEmpty(scanRecordIPage.getRecords())) { return new Page<>(scanRecordIPage.getCurrent(), scanRecordIPage.getSize(), scanRecordIPage.getTotal()); } // 4. 批量获取所有记录ID和二维码ID List recordIds = scanRecordIPage.getRecords().stream() .map(QrCodeScanRecord::getId) .collect(Collectors.toList()); Set qrCodeIds = scanRecordIPage.getRecords().stream() .map(QrCodeScanRecord::getQrCodeId) .filter(Objects::nonNull) .collect(Collectors.toSet()); // 5. 批量查询关联数据(使用最新API) // 5.1 查询二维码信息(替换selectBatchIds为selectByIds) Map qrCodeMap = qrCodeIds.isEmpty() ? Collections.emptyMap() : qrCodeMapper.selectByIds(qrCodeIds).stream() .collect(Collectors.toMap(QrCode::getId, Function.identity())); // 5.2 查询附件关联关系 Map> attachmentsMap = storageAttachmentMapper .selectList(new LambdaQueryWrapper() .in(StorageAttachment::getRecordId, recordIds) .eq(StorageAttachment::getRecordType, QrCodeScanRecords.ordinal())) .stream() .collect(Collectors.groupingBy(StorageAttachment::getRecordId)); // 5.3 查询文件数据(使用selectByIds) Set blobIds = attachmentsMap.values().stream() .flatMap(List::stream) .map(StorageAttachment::getStorageBlobId) .collect(Collectors.toSet()); Map blobMap = blobIds.isEmpty() ? Collections.emptyMap() : storageBlobMapper.selectByIds(blobIds).stream() .collect(Collectors.toMap(StorageBlob::getId, Function.identity())); // 6. 组装DTO数据 List dtoList = scanRecordIPage.getRecords().stream().map(record -> { QrCodeScanRecordDto dto = new QrCodeScanRecordDto(); BeanUtils.copyProperties(record, dto); SysUser sysUser = sysUserMapper.selectUserById(record.getScannerId()); dto.setScanner(sysUser.getNickName()); // 6.1 设置二维码信息 Optional.ofNullable(qrCodeMap.get(record.getQrCodeId())) .ifPresent(qrCode -> { BeanUtils.copyProperties(qrCode, dto); // 复制到父类 dto.setQrCode(qrCode); // 设置完整对象 }); // 6.2 设置附件信息 dto.setStorageBlobDTO( Optional.ofNullable(attachmentsMap.get(record.getId())) .orElse(Collections.emptyList()) .stream() .map(att -> { StorageBlobDTO blobDTO = new StorageBlobDTO(); Optional.ofNullable(blobMap.get(att.getStorageBlobId())) .ifPresent(blob -> { BeanUtils.copyProperties(blob, blobDTO); blobDTO.setUrl(minioUtils.getPreviewUrls(blob.getBucketFilename(), blob.getBucketName(), true)); blobDTO.setDownloadUrl(minioUtils.getDownloadUrls(blob.getBucketFilename(),blob.getBucketName(),blob.getOriginalFilename(),true)); }); return blobDTO; }) .filter(blobDTO -> blobDTO.getId() != null) // 过滤无效附件 .collect(Collectors.toList()) ); return dto; }).collect(Collectors.toList()); // 7. 构建返回分页对象 IPage resultPage = new Page<>(); BeanUtils.copyProperties(scanRecordIPage, resultPage); resultPage.setRecords(dtoList); return resultPage; } @Override public int addOrEditQrCodeRecord(QrCodeScanRecordDto qrCodeScanRecordDto) { QrCodeScanRecord qrCodeScanRecord = new QrCodeScanRecord(); BeanUtils.copyProperties(qrCodeScanRecordDto, qrCodeScanRecord); int i; if (Objects.isNull(qrCodeScanRecordDto.getId())) { i = qrCodeScanRecordMapper.insert(qrCodeScanRecord); } else { i = qrCodeScanRecordMapper.updateById(qrCodeScanRecord); } if (qrCodeScanRecordDto.getStorageBlobDTO() != null && !qrCodeScanRecordDto.getStorageBlobDTO().isEmpty()) { List attachments = new ArrayList<>(); for (StorageBlobDTO storageBlobDTO : qrCodeScanRecordDto.getStorageBlobDTO()) { StorageAttachment storageAttachment = new StorageAttachment( StorageAttachmentFile, (long) QrCodeScanRecords.ordinal(), qrCodeScanRecord.getId() ); storageAttachment.setStorageBlobDTO(storageBlobDTO); attachments.add(storageAttachment); } storageAttachmentService.saveStorageAttachment(attachments, qrCodeScanRecord.getId(), QrCodeScanRecords, StorageAttachmentFile); } return i; } @Override public int delByIds(Long[] ids) { return qrCodeScanRecordMapper.deleteByIds(Arrays.asList(ids)); } }