yangys
2025-09-20 fcee672452c02cc29e0e17ebc27a8c51698c6d0d
blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/DncBackFileService.java
@@ -5,15 +5,39 @@
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.flowable.engine.HistoryService;
import org.flowable.engine.ProcessEngine;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.base.BizServiceImpl;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.oss.OssTemplate;
import org.springblade.core.oss.model.BladeFile;
import org.springblade.core.tool.utils.FileUtil;
import org.springblade.mdm.flow.entity.FlowProgramFile;
import org.springblade.mdm.flow.service.FlowBusinessService;
import org.springblade.mdm.program.entity.DncBackFile;
import org.springblade.mdm.program.entity.NcNode;
import org.springblade.mdm.program.mapper.DncBackFileMapper;
import org.springblade.mdm.program.vo.DncBackFileQueryVO;
import org.springblade.mdm.program.vo.DncBackFileVO;
import org.springblade.mdm.program.vo.DncSendBackFile;
import org.springblade.mdm.utils.FileContentUtil;
import org.springblade.mdm.utils.ZipTextFileContentUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Optional;
import java.util.zip.ZipEntry;
/**
 * DNC回传文件处理服务
@@ -26,9 +50,124 @@
public class DncBackFileService extends BizServiceImpl<DncBackFileMapper, DncBackFile> {
   private final NcNodeService ncNodeService;
   private final OssTemplate ossTemplate;
   private final HistoryService historyService;
   private final FlowBusinessService businessService;
   public IPage<DncBackFileVO> pageQuery(DncBackFileQueryVO query) {
      return this.baseMapper.pageQuery(Condition.getPage(query),query);
      IPage<DncBackFileVO> page=  this.baseMapper.pageQuery(Condition.getPage(query),query);
      page.getRecords().forEach(item->{
         item.setProcessExecuted(isProcessExecuted(item.getProcessInstanceId()));
      });
      return page;
   }
   /**
    * 检查流程实例是否被执行过(通过历史记录)
    */
   public boolean isProcessExecuted(String processInstanceId) {
      // 检查是否有历史活动记录
      /*
      long activityCount = historyService.createHistoricActivityInstanceQuery()
         .processInstanceId(processInstanceId)
         .count();
   */
      // 检查是否有历史任务记录
      long taskCount = historyService.createHistoricTaskInstanceQuery()
         .processInstanceId(processInstanceId)
         .count();
      //多于一个任务被处理,说明至少流转到第二个节点了
      return taskCount > 1;
   }
   /**
    * 取消流程
    * @param id 回传记录id
    */
   @Transactional
   public void cancelProcess(long id) {
      DncBackFile backFIle = this.getById(id);
      NcNode packageNode = ncNodeService.getById(backFIle.getNcNodeId());
      //多于一个任务被处理,说明至少流转到第二个节点了
      if(isProcessExecuted(packageNode.getProcessInstanceId())){
         throw new ServiceException("流程已经开始处理,不可取消");
      }
      businessService.deleteProcessInstance(packageNode.getProcessInstanceId());
      this.baseMapper.deleteById(id);
   }
   /**
    * 获取回传记录的文件列表
    * @param id 回传记录id
    * @return
    */
   public List<DncSendBackFile> filesById(long id) throws IOException {
      List<DncSendBackFile> fileList = new ArrayList<>();
      DncBackFile backFIle = this.getById(id);
      InputStream inputStream = this.ossTemplate.statFileStream(backFIle.getOssName());
      Path tempZipFile = createTempFile(inputStream);
      List<String> entryNameList = new ArrayList<>();
      NcNode packageNode =  this.ncNodeService.getById(backFIle.getNcNodeId());
      String targetFolder = packageNode.getName()+"-"+packageNode.getProcessEdition()+"/";
      ZipEntry entry;
      try (java.util.zip.ZipFile zipFile = new java.util.zip.ZipFile(tempZipFile.toFile())) {
         Enumeration<? extends ZipEntry> entries = zipFile.entries();
         while(entries.hasMoreElements()) {
            entry = entries.nextElement();
            if(!entry.isDirectory() && entry.getName().startsWith(targetFolder)){
               //这里面之前时入库的文件
               DncSendBackFile file = new DncSendBackFile();
               file.setName(entry.getName().substring(targetFolder.length()));
               file.setEntryName(entry.getName());
               fileList.add(file);
            }
         }
      }
      return fileList;
   }
   Path createTempFile(InputStream inputStream) throws IOException {
      byte[] zipData = FileUtil.copyToByteArray(inputStream);
      Path tempFile = Files.createTempFile("tempzip"+System.currentTimeMillis(), ".zip");
      // 写入字节数据到临时文件
      Files.write(tempFile, zipData, StandardOpenOption.WRITE);
      return tempFile;
   }
   /**
    * 从文件夹名解析出程序包名和和工序版次
    * @param folderName 文件夹名
    * @return 结构数据
    */
   PackageAndProcessEdition parseProgramPackageFromFolderName(String folderName){
      int index = StringUtils.lastIndexOf(folderName,'-');
      String processEditon = "";
      String temp;
      String packageName = "";
      if(index != -1){
         processEditon = folderName.substring(index+1);
         packageName = folderName.substring(0,index);
      }
      PackageAndProcessEdition result = new PackageAndProcessEdition();;
      result.setProgramPackageName(packageName);
      result.setProcessEdition(processEditon);
      return result;
   }
   /**
    * 获取历史记录中的文件内容
    * @param id 回传历史记录id
    * @param entryName 压缩包文件路径
    * @return
    */
   public String getEntryFileContent(long id, String entryName) throws IOException {
      DncBackFile backFIle = this.getById(id);
      return ZipTextFileContentUtil.getTextContent(this.ossTemplate.statFileStream(backFIle.getOssName()),entryName);
   }
}