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));
}
}