package com.ruoyi.process.service.impl; import cn.hutool.core.util.NumberUtil; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.util.FileUtils; import com.alibaba.excel.util.ListUtils; import com.alibaba.excel.write.metadata.WriteSheet; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.common.utils.QueryWrappers; import com.ruoyi.process.dto.ProcessMethodSearchNewDto; import com.ruoyi.process.dto.ProcessMethodSearchNewExcel; import com.ruoyi.process.dto.ProcessMethodSearchNewImport; import com.ruoyi.process.mapper.ProcessMethodSearchNewMapper; import com.ruoyi.process.pojo.ProcessMethodSearchNew; import com.ruoyi.process.service.ProcessMethodSearchNewService; import com.ruoyi.process.utils.UserUtils; import org.apache.poi.hslf.util.LocaleDateFormat; import org.springframework.beans.BeanUtils; import org.springframework.core.io.ClassPathResource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URLEncoder; import java.security.MessageDigest; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; /** * 标准查新 * * @author zhuo * @since 2024-11-04 */ @Service public class ProcessMethodSearchNewServiceImpl extends ServiceImpl implements ProcessMethodSearchNewService { private final Set importedFileHashes = ConcurrentHashMap.newKeySet(); /** * 新增标准查新 * * @param processMethodSearchNewList * @return */ @Override @Transactional(rollbackFor = Exception.class) public boolean addMethodSearchNew(List processMethodSearchNewList) { for (ProcessMethodSearchNew processMethodSearchNew : processMethodSearchNewList) { processMethodSearchNew.setIsNewStandard(1); } // 修改之前所有没有变新的 List processMethodSearchNews = baseMapper.selectList(Wrappers.lambdaQuery() .eq(ProcessMethodSearchNew::getIsNewStandard, 1)); for (ProcessMethodSearchNew processMethodSearchNew : processMethodSearchNews) { baseMapper.update(null, Wrappers.lambdaUpdate() .set(ProcessMethodSearchNew::getMethodName, processMethodSearchNew.getNewMethodName()) .set(ProcessMethodSearchNew::getStandardNo, processMethodSearchNew.getNewStandardNo()) .set(ProcessMethodSearchNew::getFileNo, processMethodSearchNew.getNewStandardNo()) .set(ProcessMethodSearchNew::getIsNewStandard, 0) .set(ProcessMethodSearchNew::getNewMethodName, null) .set(ProcessMethodSearchNew::getNewStandardNo, null) .eq(ProcessMethodSearchNew::getMethodSearchNewId, processMethodSearchNew.getMethodSearchNewId())); } // 新增 this.saveBatch(processMethodSearchNewList); return true; } /** * 标准查新列表 * * @param processMethodSearchNew * @return */ @Override public IPage pageMethodSearchNew(Page page, ProcessMethodSearchNewDto processMethodSearchNew) { String beginDate = processMethodSearchNew.getBeginDate(); String endDate = processMethodSearchNew.getEndDate(); processMethodSearchNew.setBeginDate(null); processMethodSearchNew.setEndDate(null); // 历史记录的话 就要加时间 if(!processMethodSearchNew.getIsThisYear()) { LocalDateTime localDateTime = LocalDateTime.of(LocalDate.now().getYear(), 1, 1, 0, 0, 0); endDate = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(localDateTime); } ProcessMethodSearchNew processMethodSearchNew1 = new ProcessMethodSearchNew(); BeanUtils.copyProperties(processMethodSearchNew, processMethodSearchNew1); return baseMapper.pageMethodSearchNew(page, QueryWrappers.queryWrappers(processMethodSearchNew1), beginDate, endDate); } /** * 标准查新导出 * * @param processMethodSearchNew * @param response */ @Override public void exportMethodSearchNew(ProcessMethodSearchNewDto processMethodSearchNew, HttpServletResponse response) { // 查询标准查新 String beginDate = processMethodSearchNew.getBeginDate(); String endDate = processMethodSearchNew.getEndDate(); String writeUserId = processMethodSearchNew.getWriteUserId().toString(); String ratifyUserId = processMethodSearchNew.getRatifyUserId().toString(); String writeDate = processMethodSearchNew.getWriteDate(); String ratifyDate = processMethodSearchNew.getRatifyDate(); processMethodSearchNew.setBeginDate(null); processMethodSearchNew.setEndDate(null); processMethodSearchNew.setWriteUserId(null); processMethodSearchNew.setRatifyUserId(null); processMethodSearchNew.setWriteDate(null); processMethodSearchNew.setRatifyDate(null); List methodSearchNews = baseMapper.selectMethodSearchNew(QueryWrappers.queryWrappers(processMethodSearchNew), beginDate, endDate); int index = 1; // 格式化参数 for (ProcessMethodSearchNewDto methodSearchNew : methodSearchNews) { // 是否是跟新标准 if (methodSearchNew.getIsNewStandard().equals(1)) { methodSearchNew.setIsNewStandardString("是"); } else { methodSearchNew.setIsNewStandardString("否"); } // 备注 if (methodSearchNew.getRemark() != null) { if (methodSearchNew.getRemark().equals(1)) { methodSearchNew.setRemarkString("替换"); } else { methodSearchNew.setRemarkString("作废"); } } if (methodSearchNew.getRemark() != null) { if (methodSearchNew.getRemark().equals(1)) { methodSearchNew.setRemarkString("替换"); } else { methodSearchNew.setRemarkString("作废"); } } if(Objects.nonNull(methodSearchNew.getSearchNewSource())) { switch (methodSearchNew.getSearchNewSource()) { case 0: methodSearchNew.setStandardNet("√"); break; case 1: methodSearchNew.setInformationOffices("√"); break; case 2: methodSearchNew.setStandardBookstore("√"); break; case 3: methodSearchNew.setOther("√"); break; default: break; } } methodSearchNew.setIndex(index); index++; } // 查询签名地址 String writeUserUrl = UserUtils.getUserSignatureUrl(Integer.valueOf(writeUserId)); String ratifyUserUrl = UserUtils.getUserSignatureUrl(Integer.valueOf(ratifyUserId)); //创建ExcelWriter 可以自动关流但还是手动关一次 ExcelWriter excelWriter = null; try { // outputStream:要导出的文件的输出流 OutputStream outputStream = response.getOutputStream(); // 获取模版文件 ClassPathResource classPathResource = new ClassPathResource("/static/excel/check-records.xlsx"); // 使用模版文件的两种方式: // 1、文件路径:.withTemplate(templateFileName) // 2、输入流:.withTemplate(inputStream) // String templateFileName = classPathResource.getFile().getPath(); InputStream inputStream = classPathResource.getInputStream(); // 创建ExcelWriter excelWriter = EasyExcel.write(outputStream).withTemplate(inputStream).build(); // 获取第一个sheet页 WriteSheet writeSheet = EasyExcel.writerSheet(0, "标准查新导出").build(); //excelWriter.fill() 这地方就是填充属性。 // excelWriter.fill(methodSearchNews, fillConfig, writeSheet); // 这里fillConfig是配置文件 excelWriter.fill(methodSearchNews, writeSheet); // 这里easy excel模板导出问题 会删除后面内容再进行进行填充 // 所以list 后面还有数据 想办法手动写入 // 手动创建一个list 存放数据 然后再进行填充 // 这里List可以用对象代替 偷懒用list List> totalListList = ListUtils.newArrayList(); List totalList = ListUtils.newArrayList(); totalListList.add(totalList); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); // 第一列 totalList.add("编制人:"); // 第二列 设置签名 totalList.add(FileUtils.readFileToByteArray(new File(writeUserUrl))); // 第三列 totalList.add("日期:"); // 第五列 totalList.add(writeDate); // 第六列 totalList.add("审核:"); // 第七列 totalList.add(FileUtils.readFileToByteArray(new File(ratifyUserUrl))); // 第八列 totalList.add("日期:"); // 第九列 totalList.add(ratifyDate); // 这里追加是write 别和fill 搞错了 excelWriter.write(totalListList, writeSheet); // 设置输出流格式以及文件名: response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setCharacterEncoding("utf-8"); String fileName = URLEncoder.encode( "原材料检测信息导出", "UTF-8"); response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx"); } catch (Exception e) { throw new RuntimeException(e); } finally { // 千万别忘记close关闭流 if (excelWriter != null) { excelWriter.close(); } } } /** * 导入标准查新 * * @param file * @return */ @Override public void importMethodSearchNew(MultipartFile file) { try { // 1. 计算文件的 MD5 哈希值 String fileHash = calculateFileHash(file); // 2. 检查是否已存在相同文件 if (!importedFileHashes.add(fileHash)) { return; // 已存在,直接跳过 } // 3. 读取并处理文件 try (InputStream inputStream = file.getInputStream()) { EasyExcel.read(inputStream, ProcessMethodSearchNewExcel.class, new ProcessMethodSearchNewImport(this)) .sheet() .doRead(); } // 4. 记录文件哈希值(标记为已导入) importedFileHashes.add(fileHash); } catch (Exception e) { throw new RuntimeException(e); } } public void save (List list) { if(CollectionUtils.isNotEmpty(list)) { for (ProcessMethodSearchNewExcel a : list) { if(NumberUtil.isNumber(a.getIndex())) { ProcessMethodSearchNew processMethodSearchNew = new ProcessMethodSearchNew(); BeanUtils.copyProperties(a, processMethodSearchNew); processMethodSearchNew.setIsNewStandard(a.getIsNewStandardString() == "是" ? 1 : 0); // 是否是新标准 // 查新记录 0 标准网 1 委托情报 2 标准数 3 其他 if(StringUtils.isNotEmpty(a.getStandardNet())) { processMethodSearchNew.setSearchNewSource(0); } else if(StringUtils.isNotEmpty(a.getInformationOffices())) { processMethodSearchNew.setSearchNewSource(1); } else if(StringUtils.isNotEmpty(a.getStandardBookstore())) { processMethodSearchNew.setSearchNewSource(2); } else if(StringUtils.isNotEmpty(a.getOther())) { processMethodSearchNew.setSearchNewSource(3); } // 编制人 baseMapper.insert(processMethodSearchNew); } } } } // 计算文件的 MD5 哈希值 private String calculateFileHash(MultipartFile file) throws Exception { try (InputStream is = file.getInputStream()) { MessageDigest md = MessageDigest.getInstance("MD5"); byte[] buffer = new byte[8192]; int bytesRead; while ((bytesRead = is.read(buffer)) != -1) { md.update(buffer, 0, bytesRead); } byte[] hashBytes = md.digest(); // 将字节数组转换为十六进制字符串 return bytesToHex(hashBytes); } } private static String bytesToHex(byte[] bytes) { StringBuilder hexString = new StringBuilder(); for (byte b : bytes) { String hex = Integer.toHexString(0xff & b); if (hex.length() == 1) { hexString.append('0'); } hexString.append(hex); } return hexString.toString(); } }