yangys
2025-09-13 3ffe33aaa24386337e3638558eca731c62f25521
blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/ProgramConfirmTableService.java
@@ -2,32 +2,26 @@
package org.springblade.mdm.flow.service;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.flowable.engine.HistoryService;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.springblade.core.oss.OssTemplate;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.mdm.basesetting.machine.MachineService;
import org.springblade.mdm.basesetting.machine.service.MachineService;
import org.springblade.mdm.basesetting.machine.entity.Machine;
import org.springblade.mdm.flow.constants.FlowContants;
import org.springblade.mdm.basesetting.producedivision.entity.QinzheFgb;
import org.springblade.mdm.basesetting.producedivision.service.QinzheFgbService;
import org.springblade.mdm.commons.contants.DictBizConstants;
import org.springblade.mdm.commons.service.ParamService;
import org.springblade.mdm.commons.support.TemplatedPdfWriter;
import org.springblade.mdm.flow.vo.ApproveTableInfo;
import org.springblade.mdm.program.entity.NcNode;
import org.springblade.mdm.program.entity.NcProgramApproved;
import org.springblade.mdm.program.service.NcNodeService;
import org.springblade.mdm.program.service.NcProgramApprovedService;
import org.springblade.system.feign.IDictBizClient;
import org.springblade.system.feign.IUserClient;
import org.springblade.system.pojo.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.*;
import java.util.*;
import java.util.List;
/**
 * 数控程序确认表输出服务
@@ -38,317 +32,154 @@
@Service
public class ProgramConfirmTableService {
   @Autowired
   private FlowCommonService flowCommonService;
   private QinzheFgbService qinzheFgbService;
   @Autowired
   private IDictBizClient dictBizClient;
   @Autowired
   private NcNodeService ncNodeService;
   @Autowired
   private MachineService machineService;
   @Autowired
   private HistoryService historyService;
   private OssTemplate ossTemplate;
   @Autowired
   private IUserClient useClient;
   private IUserClient userClient;
   @Autowired
   private NcProgramApprovedService programApprovedService;
   private static final String UNCHECK_BOX = "☐";
   private static final String CHECKED_BOX = "☑";
   static Chunk square = new Chunk("o", new Font(Font.FontFamily.ZAPFDINGBATS, 12)); // 空方框
   static Chunk check = new Chunk("4", new Font(Font.FontFamily.ZAPFDINGBATS, 12)); // 带勾方框
   private ParamService paramService;
   @Autowired
   private ApproveInfoQueryService approveInfoQueryService;
   public void exportConfirmTable(FlowProgramProperties props, OutputStream os) throws IOException, DocumentException {
   BaseFont getBaseFont() throws DocumentException, IOException {
      return BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
      //byte[] tplBytes = getTemplateBytes();
      TemplatedPdfWriter pdfWriter = new TemplatedPdfWriter(getTemplateBytes());
      //generateTempPDF(tplBytes,props,os);
      pdfWriter.write(getPdfData(props),os);
   }
   Font getChineseFont() throws DocumentException, IOException {
      BaseFont bfChinese = getBaseFont();
      return new Font(bfChinese, 12, Font.NORMAL);
   }
   public void generateTempPDF()throws Exception {
   /*
   void generateTempPDF(byte[] bytes,FlowProgramProperties props,OutputStream outputStream) throws DocumentException, IOException {
      PdfReader reader = null;
      PdfStamper ps = null;
      OutputStream fos = null;
      ByteArrayOutputStream bos = null;
      try {
         String fileName = "d:/qrb.pdf";//模板绝对路径
         reader = new PdfReader(fileName);
         bos = new ByteArrayOutputStream();
         ps = new PdfStamper(reader, bos);
         // 使用中文字体
         //BaseFont bf = BaseFont.createFont("sTsong-Light", "uniGB-Ucs2-H", BaseFont.NOT_EMBEDDED);
         BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
         ArrayList<BaseFont> fontList = new ArrayList<BaseFont>();
         fontList.add(bf);
         AcroFields fields = ps.getAcroFields();
         fields.setSubstitutionFonts(fontList);
         fillData(fields, data());//染
         //必须要调用这个,否则文档不会生成的
         ps.setFormFlattening(true);
         if (ps != null) {
            ps.close();
         }
      PdfStamper pdfStamper = null;
         //生成pdf路径存放的路径
         fos = new FileOutputStream("d:/bb2.pdf");
         fos.write(bos.toByteArray());
      } catch (Exception e) {
         e.printStackTrace();
      } finally {
         if (fos != null) {
            fos.flush();
            fos.close();
            if (bos != null) {
               bos.close();
            }
            if (reader != null) {
               reader.close();
            }
         }
      reader = new PdfReader(bytes);
      pdfStamper =  new PdfStamper(reader, outputStream);
      // 使用中文字体
      BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
      ArrayList<BaseFont> fontList = new ArrayList<>();
      fontList.add(bf);
      AcroFields fields = pdfStamper.getAcroFields();
      fields.setSubstitutionFonts(fontList);
      fillData(fields, getData(props));//染
      //必须要调用这个,否则文档不会生成的
      pdfStamper.setFormFlattening(true);
      pdfStamper.close();
   }
   void fillData(AcroFields fields, Map<String, String> data) throws DocumentException, IOException {
      for (String key : data.keySet()) {
         String value = data.get(key);
         // 为字段赋值,注意字段名称是区分大小写的fields.setField(key,value);
         fields.setField(key,value,true);
         //form.setFieldProperty("fieldName", "clrflags", PdfAnnotation.FLAGS_HIDDEN, null);
         //fields.setFieldRichValue()
      }
   }*/
   /**
    * 获取模板字节数组
    * @return
    */
   private byte[] getTemplateBytes() throws IOException {
      String tplOssName = paramService.confirmTableTemplateOssFileName();
      try (InputStream inputStream = this.ossTemplate.statFileStream(tplOssName)) {
         return inputStream.readAllBytes();
      }
   }
   public void fillData(AcroFields fields, Map<String, String> data) {
      try {
         for (String key : data.keySet()) {
            String value = data.get(key);
            // 为字段赋值,注意字段名称是区分大小写的fields.setField(key,value);
            fields.setField(key,value);
         }
      }catch(Exception e){
         e.printStackTrace();
   /**
    * 获取打印表格的数据
    * @param props 流程属性
    * @return 数据map
    */
   Map<String,String> getPdfData(FlowProgramProperties props){
      Map<String,String> data = new HashMap<>();
      data.put("pageTotal","1");
      data.put("pageNo","1");
      data.put("processNo",props.getProcessNo());
      data.put("drawingNo",props.getDrawingNo());
      data.put("drawingNoEdition",props.getDrawingNoEdition());
      data.put("processName",props.getProcessName());
      data.put("processEdition",props.getProcessEdition());
      data.put("machineCode",props.getMachineCode());
      data.put("productModel",props.getProductModel());
      data.put("craftEdition",props.getCraftEdition());
      //零组件名称
      data.put("drawingName",getDrawingName(props.getDrawingNo()));
      data.put("deviation",props.getDeviation()!=null?props.getDeviation():StringUtils.EMPTY);
      Machine machine = this.machineService.getByCode(props.getMachineCode());
      data.put("machineMode",machine.getName());
      R<String> dictSystemResult = dictBizClient.getValue(DictBizConstants.CONTROL_SYSTEM,machine.getControlSystem());
      if(dictSystemResult.isSuccess()){
         data.put("controlSystem",dictSystemResult.getData());
      }
   }
   Map<String,String> data(){
      Map<String,String> ret = new HashMap<>();
      ret.put("drawingName","中文图名");
      ret.put("craftEdition","TH0001");
      return ret;
   }
   public void exportConfirmTable(String processInstanceId, OutputStream os) throws DocumentException, IOException {
      data.put("operator","来源MES/2025-1-1");
      data.put("jjy","来源MES/2025-1-1");
      data.put("fuheY","Y");//TODO 有 检验员 则符合
      data.put("keyongY","Y");//TODO 有 检验员 则符合
      BaseFont bfChinese = getBaseFont();
      data.put("jly","来源MES/2025-1-1");
      data.put("jln","来源MES/2025-1-1");
      ApproveTableInfo approveInfo = approveInfoQueryService.getApproveInfo(props);
      data.put("programmerName",approveInfo.getProgrammerName());
      data.put("checkerName",approveInfo.getCheckerName());
      data.put("seniorName",approveInfo.getSeniorName());
      Document document = new Document(PageSize.B5.rotate());
      PdfWriter.getInstance(document, os);
      data.put("programNo",approveInfo.getProgramNo());
      document.open();
      FlowProgramProperties props = flowCommonService.getProgramPropertiesFromHis(processInstanceId);
      ApproveTableInfo appInfo = getApproveInfo(props);
      Machine machine;
      String machineCode = props.getMachineCode();
      machine = machineService.getByCode(machineCode);
      int flag = props.getProcessDefinitionKey().equals(FlowContants.TRY_PROCESS_KEY)?1:2;
      printPage(document, bfChinese, props, machine);
      //document.newPage();
      //printPage(document, bfChinese, props, machine, 2, appInfo);
      document.close();
      return data;
   }
   void printPage(Document document, BaseFont bfChinese, FlowProgramProperties props, Machine machine) throws DocumentException, IOException {
      Font tableFont = new Font(bfChinese, 12, Font.NORMAL);
      PdfPTable titleTable = new PdfPTable(2);
      titleTable.setWidthPercentage(100);
      titleTable.setSpacingBefore(10f);
      titleTable.setSpacingAfter(10f);
      PdfPCell celBh = this.getCell("编号:",tableFont);
      titleTable.addCell(celBh);
      PdfPCell celYb = this.getCell("艺表8",tableFont);
      titleTable.addCell(celYb);
      document.add(titleTable);
      //document.add(title);
      // 创建表格(4列)
      PdfPTable table = new PdfPTable(6);
      table.setWidths(new float[]{1, 1.3f, 1f, 1.3f,1, 1.5f});
      Font ft = this.getChineseFont();
      // 添加表头
      PdfPCell tempCell = getCell("一一四厂",tableFont);
      //
      table.addCell(tempCell);
      tempCell = getCell("数控程序确认表",tableFont);
      table.addCell(tempCell);
      table.addCell(getCell("工序号", ft));
      table.addCell(getCell("工艺版次", ft));
      table.addCell(getCell("机床型号", ft));
      table.addCell(getCell("工段负责人/单元负\n责人派出时间", ft));
      table.addCell(getCell(props.getDrawingNo(), ft));//零组件号
      table.addCell(getCell(props.getProcessNo(), ft));//工序号
      table.addCell(getCell(props.getCraftEdition(), ft));//工艺版次
      table.addCell(getCell(machine.getName(), ft));//机床型号
      table.addCell(getCell("", ft));//负责人,工段负责人派出时间
      //中间大格
      PdfPCell cell = new PdfPCell();
      cell.setColspan(5);
      cell.setCalculatedHeight(400);
      Paragraph mainPara1 = new Paragraph();
      mainPara1.setLeading(30f, 0f);
      mainPara1.setFont(ft);
      mainPara1.setAlignment(Element.ALIGN_LEFT); // 对齐方式
      mainPara1.setIndentationLeft(20); // 左缩进(像素)
      mainPara1.setIndentationRight(20); // 右缩进
      mainPara1.setSpacingBefore(10); // 段前间距
      mainPara1.setSpacingAfter(10); // 段后间距
      mainPara1.add("数控程序编制任务安排:\n");
      cell.addElement(mainPara1);
      Paragraph line2Para = new Paragraph();
      line2Para.setLeading(30f, 0f);
      line2Para.setFont(ft);
      line2Para.setAlignment(Element.ALIGN_LEFT); // 对齐方式
      line2Para.setIndentationLeft(40); // 左缩进(像素)
      line2Para.add("请");
      Font underLineFt = new Font(bfChinese, 12, Font.UNDERLINE);
      //String personName = record.getUserNickname();
      Chunk block1 = square;
      Chunk block2 = check;
      cell.addElement(line2Para);
      Paragraph fangzhen = new Paragraph();
      fangzhen.setAlignment(Element.ALIGN_LEFT); // 对齐方式
      fangzhen.setIndentationLeft(20); // 左缩进(像素)
      fangzhen.setIndentationRight(20); // 右缩进
      fangzhen.setSpacingBefore(10); // 段前间距
      fangzhen.setSpacingAfter(10); // 段后间距
      fangzhen.setFont(ft);
      fangzhen.setLeading(30f, 0f);
      fangzhen.add("是否需要仿真(是");
      fangzhen.add(check);//固定是仿真
      fangzhen.add(" 否");
      fangzhen.add(square);
      fangzhen.add(")\n\n");
      cell.addElement(fangzhen);
      table.addCell(cell);
      //下一行
      PdfPCell cell21 = getCell("数控程序编号", ft);// PdfPCell();
      cell21.setColspan(2);
      //cell21.setPhrase(new Phrase("数控程序编号",ft));
      table.addCell(cell21);
      table.addCell(getCell("编制/日期", ft));
      table.addCell(getCell("校对/日期", ft));
      table.addCell(getCell("批准/日期", ft));
      PdfPCell cell2 = getCell("00001", ft);
      cell2.setColspan(2);
      //cell2.addElement(new Phrase(programPackageNode.getProgramNo(),ft));//数控程序编号
      //cell2.addElement(new Phrase("00001",ft));
      table.addCell(cell2);
      // 设置表格宽度占页面宽度的100%
      table.setWidthPercentage(100);
      // 添加表格到文档
      document.add(table);
      Phrase lastPhrase = new Phrase("注:工段派工应预先计划、合理安排数控程序编制。立加、数铣、数车等单道工序程序(两轴程序)需提前1个工作日,卧式加工中心单道工序(含多轴程序)需提前3个工作日。 ", ft);
      document.add(lastPhrase);
   }
   PdfPCell getCell(String text, Font font) throws DocumentException, IOException {
      PdfPCell cell = new PdfPCell();
      cell.setPadding(10);
      cell.setHorizontalAlignment(Element.ALIGN_CENTER);
      cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
      if (StringUtils.isNotBlank(text)) {
         Phrase p = new Phrase(text, font);
         p.setLeading(25);
         cell.setPhrase(p);
   /**
    * 查询程序编号
    * @param nodeId
    * @return
    */
   /*
   private String queryProgramNo(Long nodeId) {
      if(nodeId ==null) {
         return StringUtils.EMPTY;
      }
      return cell;
   }
   ApproveTableInfo getApproveInfo(FlowProgramProperties props){
      //编制
      R<User> leaderR = useClient.userInfoById(props.getTeamLeaderId());
      String leaderName = "";
      if (leaderR.isSuccess()) {
         leaderName = leaderR.getData().getName();
      }
      //编制
      R<User> programmerR = useClient.userInfoById(props.getProgrammerId());
      String programmerName = "";
      if (programmerR.isSuccess()) {
         programmerName = programmerR.getData().getName();
      }
      Machine machine;
      String machineCode = props.getMachineCode();
      machine = machineService.getByCode(machineCode);
      //校对
      R<User> checkerR = useClient.userInfoById(props.getCheckerId());
      String checkerName = "";
      if (checkerR.isSuccess()) {
         checkerName = checkerR.getData().getName();
      }
      //审核
      R<User> seniorR = useClient.userInfoById(props.getCheckerId());
      String senioirName = "";
      if (seniorR.isSuccess()) {
         senioirName = seniorR.getData().getName();
      }
      ApproveTableInfo appInfo = new ApproveTableInfo();
      appInfo.setTeamLeaderName(leaderName);
      appInfo.setProgrammerName(programmerName);
      appInfo.setCheckerName(checkerName);
      appInfo.setSeniorName(senioirName);
      //获取时间信息
      List<HistoricTaskInstance> hisTasks = historyService.createHistoricTaskInstanceQuery()
         .processInstanceId(props.getProcessInstanceId()).orderByTaskCreateTime().desc().list();
      for(HistoricTaskInstance task : hisTasks){
         if(appInfo.getProgrammingDate()== null && task.getTaskDefinitionKey().contains("program")){
            appInfo.setProgrammingDate(task.getEndTime());
         }
         if(appInfo.getCheckDate()== null && task.getTaskDefinitionKey().contains("check")){
            appInfo.setCheckDate(task.getEndTime());
         }
         if(appInfo.getApproveDate()== null && task.getTaskDefinitionKey().contains("approve")){
            appInfo.setApproveDate(task.getEndTime());
         }
      }
      //查询数控程序编号
      Optional<NcProgramApproved> appOpt = programApprovedService.lambdaQuery().eq(NcProgramApproved::getProcessInstanceId, props.getProcessInstanceId()).oneOpt();
      if(appOpt.isEmpty()){
         appInfo.setProgramNo("(未生成)");
      NcNode programPkdNode = this.ncNodeService.getById(nodeId);
      if (programPkdNode != null) {
         return programPkdNode.getProgramNo();
      }else{
         NcNode programPkgNameNode = this.ncNodeService.getById(appOpt.get().getNcNodeId());
         appInfo.setProgramNo(programPkgNameNode.getProgramNo());
         return StringUtils.EMPTY;
      }
      return appInfo;
   }
   */
   /**
    * 获取零组件名称
    * @param drawingNo 零件编号
    * @return 零组件名称
    */
   String getDrawingName(String drawingNo){
      QinzheFgb fgb = qinzheFgbService.getByLjh(drawingNo);
      if(fgb!= null){
         return fgb.getLjmc();
      }else{
         return StringUtils.EMPTY;
      }
   }
}