11 小时以前 55d694aaae4e421b5e55cd941500e08f85cb5d4d
src/main/java/com/ruoyi/measuringinstrumentledger/service/impl/MeasuringInstrumentLedgerServiceImpl.java
@@ -2,20 +2,20 @@
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.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.enums.FileNameType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.measuringinstrumentledger.dto.MeasuringInstrumentLedgerImportDto;
import com.ruoyi.measuringinstrumentledger.dto.MeasuringInstrumentLedgerDto;
import com.ruoyi.measuringinstrumentledger.mapper.MeasuringInstrumentLedgerMapper;
import com.ruoyi.measuringinstrumentledger.mapper.MeasuringInstrumentLedgerRecordMapper;
import com.ruoyi.measuringinstrumentledger.pojo.MeasuringInstrumentLedger;
import com.ruoyi.measuringinstrumentledger.pojo.MeasuringInstrumentLedgerRecord;
import com.ruoyi.measuringinstrumentledger.service.MeasuringInstrumentLedgerService;
import com.ruoyi.other.mapper.TempFileMapper;
import com.ruoyi.other.pojo.TempFile;
import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.project.system.mapper.SysUserMapper;
import com.ruoyi.sales.mapper.CommonFileMapper;
@@ -23,22 +23,19 @@
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
import java.util.UUID;
import java.util.Set;
import java.util.stream.Collectors;
/**
@@ -52,12 +49,7 @@
    private final MeasuringInstrumentLedgerMapper measuringInstrumentLedgerMapper;
    private final MeasuringInstrumentLedgerRecordMapper measuringInstrumentLedgerRecordMapper;
    private final TempFileMapper tempFileMapper;
    private final CommonFileMapper commonFileMapper;
    private final SysUserMapper sysUserMapper;
    @Value("${file.upload-dir}")
    private String uploadDir;
    @Override
    public IPage<MeasuringInstrumentLedger> listPage(Page page, MeasuringInstrumentLedger measuringInstrumentLedger) {
@@ -74,12 +66,6 @@
                collect = measuringInstrumentLedgerRecords.stream().map(MeasuringInstrumentLedgerRecord::getId).collect(Collectors.toList());
            }
            collect.add(item.getId());
            LambdaQueryWrapper<CommonFile> salesLedgerFileWrapper = new LambdaQueryWrapper<>();
            salesLedgerFileWrapper.in(CommonFile::getCommonId, collect)
                    .in(CommonFile::getType,types);
            List<CommonFile> commonFiles = commonFileMapper.selectList(salesLedgerFileWrapper);
            item.setCommonFiles(commonFiles);
        });
        return measuringInstrumentLedgerIPage;
    }
@@ -107,13 +93,93 @@
//            if(!CollectionUtils.isEmpty(req.getTempFileIds())){
//                migrateTempFilesToFormal(measuringInstrumentLedger.getId(), req.getTempFileIds(), FileNameType.MEASURING.getValue());
//            }
            // 台账记录绑定一次
            if(!CollectionUtils.isEmpty(req.getTempFileIds())){
                migrateTempFilesToFormal(measuringInstrumentLedgerRecord.getId(), req.getTempFileIds(), FileNameType.MEASURINGRecord.getValue());
            }
            return true;
        }
        return false;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult importData(MultipartFile file) {
        if (file == null || file.isEmpty()) {
            return AjaxResult.error("请上传 Excel 文件");
        }
        String filename = file.getOriginalFilename();
        if (filename == null || !(filename.endsWith(".xls") || filename.endsWith(".xlsx"))) {
            return AjaxResult.error("只支持导入 xls 或 xlsx 文件");
        }
        try {
            ExcelUtil<MeasuringInstrumentLedgerImportDto> util = new ExcelUtil<>(MeasuringInstrumentLedgerImportDto.class);
            List<MeasuringInstrumentLedgerImportDto> rows = util.importExcel(file.getInputStream());
            if (CollectionUtils.isEmpty(rows)) {
                return AjaxResult.error("Excel 中没有可导入的数据");
            }
            Set<String> codes = new HashSet<>();
            Map<Integer, String> errors = new LinkedHashMap<>();
            List<MeasuringInstrumentLedger> ledgers = new ArrayList<>();
            Long tenantId = SecurityUtils.getLoginUser().getTenantId();
            Long userId = SecurityUtils.getUserId();
            String userName = SecurityUtils.getLoginUser().getNickName();
            for (int i = 0; i < rows.size(); i++) {
                MeasuringInstrumentLedgerImportDto row = rows.get(i);
                int excelRow = i + 2;
                String code = StringUtils.trim(row.getCode());
                String name = StringUtils.trim(row.getName());
                if (!StringUtils.hasText(code)) {
                    errors.put(excelRow, "计量器具编号不能为空");
                    continue;
                }
                if (!StringUtils.hasText(name)) {
                    errors.put(excelRow, "计量器具名称不能为空");
                    continue;
                }
                if (!codes.add(code)) {
                    errors.put(excelRow, "计量器具编号在 Excel 中重复");
                    continue;
                }
                if (row.getValid() != null && row.getValid() <= 0) {
                    errors.put(excelRow, "检定有效期必须大于 0");
                    continue;
                }
                MeasuringInstrumentLedger ledger = new MeasuringInstrumentLedger();
                ledger.setCode(code);
                ledger.setName(name);
                ledger.setModel(StringUtils.trim(row.getModel()));
                ledger.setMostDate(row.getMostDate());
                ledger.setValid(row.getValid());
                ledger.setRecordDate(row.getRecordDate() == null ? new Date() : row.getRecordDate());
                ledger.setUnit(StringUtils.trim(row.getUnit()));
                ledger.setDeptId(row.getDeptId());
                ledger.setInstationLocation(StringUtils.trim(row.getInstationLocation()));
                ledger.setCycle(StringUtils.trim(row.getCycle()));
                ledger.setUserId(userId);
                ledger.setUserName(userName);
                ledger.setTenantId(tenantId);
                if (row.getMostDate() != null && row.getValid() != null) {
                    ledger.setNextDate(new Date(row.getMostDate().getTime() + 86400000L * row.getValid()));
                }
                ledgers.add(ledger);
            }
            if (!codes.isEmpty()) {
                for (String code : measuringInstrumentLedgerMapper.selectExistingCodes(tenantId, codes)) {
                    errors.put(-1, "计量器具编号已存在:" + code);
                }
            }
            if (!errors.isEmpty()) {
                return AjaxResult.error("导入校验失败:" + errors.values().stream().limit(100).collect(Collectors.joining(";")));
            }
            saveBatch(ledgers);
            return AjaxResult.success("成功导入 " + ledgers.size() + " 条数据");
        } catch (Exception e) {
            log.error("计量器具台账导入失败", e);
            return AjaxResult.error("导入失败,请检查 Excel 内容");
        }
    }
    @Override
    public void downloadTemplate(HttpServletResponse response) {
        ExcelUtil<MeasuringInstrumentLedgerImportDto> util = new ExcelUtil<>(MeasuringInstrumentLedgerImportDto.class);
        util.importTemplateExcel(response, "计量器具台账导入模板");
    }
    @Override
@@ -131,84 +197,7 @@
        }
        measuringInstrumentLedger.setUserName(sysUser.getUserName());
        measuringInstrumentLedgerMapper.insert(measuringInstrumentLedger);
        if(!CollectionUtils.isEmpty(measuringInstrumentLedger.getTempFileIds())){
            migrateTempFilesToFormal(measuringInstrumentLedger.getId(), measuringInstrumentLedger.getTempFileIds(), FileNameType.MEASURING.getValue());
        }
        return true;
    }
    /**
     * 将临时文件迁移到正式目录
     *
     * @param businessId  业务ID(销售台账ID)
     * @param tempFileIds 临时文件ID列表
     * @throws IOException 文件操作异常
     */
    private void migrateTempFilesToFormal(Long businessId, List<String> tempFileIds,Integer fileType) throws IOException {
        if (CollectionUtils.isEmpty(tempFileIds)) {
            return;
        }
        // 构建正式目录路径(按业务类型和日期分组)
        String formalDir = uploadDir + LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE);
        Path formalDirPath = Paths.get(formalDir);
        // 确保正式目录存在(递归创建)
        if (!Files.exists(formalDirPath)) {
            Files.createDirectories(formalDirPath);
        }
        for (String tempFileId : tempFileIds) {
            // 查询临时文件记录
            TempFile tempFile = tempFileMapper.selectById(tempFileId);
            if (tempFile == null) {
                log.warn("临时文件不存在,跳过处理: {}", tempFileId);
                continue;
            }
            // 构建正式文件名(包含业务ID和时间戳,避免冲突)
            String originalFilename = tempFile.getOriginalName();
            String fileExtension = FilenameUtils.getExtension(originalFilename);
            String formalFilename = businessId + "_" +
                    System.currentTimeMillis() + "_" +
                    UUID.randomUUID().toString().substring(0, 8) +
                    (StringUtils.hasText(fileExtension) ? "." + fileExtension : "");
            Path formalFilePath = formalDirPath.resolve(formalFilename);
            try {
                // 执行文件迁移(使用原子操作确保安全性)
//                Files.move(
//                        Paths.get(tempFile.getTempPath()),
//                        formalFilePath,
//                        StandardCopyOption.REPLACE_EXISTING,
//                        StandardCopyOption.ATOMIC_MOVE
//                );
                // 原子移动失败,使用复制+删除
                Files.copy(Paths.get(tempFile.getTempPath()), formalFilePath, StandardCopyOption.REPLACE_EXISTING);
                Files.deleteIfExists(Paths.get(tempFile.getTempPath()));
                log.info("文件迁移成功: {} -> {}", tempFile.getTempPath(), formalFilePath);
                // 更新文件记录(关联到业务ID)
                CommonFile fileRecord = new CommonFile();
                fileRecord.setCommonId(businessId);
                fileRecord.setName(originalFilename);
                fileRecord.setUrl(formalFilePath.toString());
                fileRecord.setCreateTime(LocalDateTime.now());
                fileRecord.setType(fileType);
                commonFileMapper.insert(fileRecord);
                // 删除临时文件记录
                tempFileMapper.deleteById(tempFile);
                log.info("文件迁移成功: {} -> {}", tempFile.getTempPath(), formalFilePath);
            } catch (IOException e) {
                log.error("文件迁移失败: {}", tempFile.getTempPath(), e);
                // 可选择回滚事务或记录失败文件
                throw new IOException("文件迁移异常", e);
            }
        }
    }
}