package org.springblade.mdm.flow.service; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.HistoryService; import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.runtime.ProcessInstance; import org.flowable.task.api.history.HistoricTaskInstance; import org.springblade.core.tool.api.R; import org.springblade.core.tool.utils.DateUtil; import org.springblade.core.tool.utils.Func; import org.springblade.mdm.basesetting.machine.MachineService; import org.springblade.mdm.basesetting.machine.entity.Machine; import org.springblade.mdm.flow.constants.FlowContants; 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.IUserClient; import org.springblade.system.pojo.entity.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.io.IOException; import java.io.OutputStream; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Optional; import com.itextpdf.text.*; import com.itextpdf.text.pdf.*; /** * 审批记录,用于查询执行轨迹 * * @author yangys */ @Slf4j @Service public class ApproveTableService { @Autowired private FlowCommonService flowCommonService; @Autowired private NcNodeService ncNodeService; @Autowired private MachineService machineService; @Autowired private HistoryService historyService; @Autowired private IUserClient useClient; @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)); // 带勾方框 BaseFont getBaseFont() throws DocumentException, IOException { return BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); } Font getChineseFont() throws DocumentException, IOException { BaseFont bfChinese = getBaseFont(); return new Font(bfChinese, 12, Font.NORMAL); } public void exportApproveTable(String processInstanceId, OutputStream os) throws DocumentException, IOException { BaseFont bfChinese = getBaseFont(); Document document = new Document(PageSize.B5.rotate()); PdfWriter.getInstance(document, os); 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, flag, appInfo); //document.newPage(); //printPage(document, bfChinese, props, machine, 2, appInfo); document.close(); } /** * 打印一个步骤(编制/校对) * @param document * @param bfChinese * @param props * @param machine * @param flag * @param approveInfo * @throws DocumentException * @throws IOException */ void printPage(Document document, BaseFont bfChinese, FlowProgramProperties props, Machine machine, int flag, ApproveTableInfo approveInfo) throws DocumentException, IOException { Font tipFont = new Font(bfChinese, 10, Font.NORMAL); Paragraph tip = new Paragraph("艺表6", tipFont); tip.setAlignment(Element.ALIGN_RIGHT); tip.setSpacingAfter(-5); // 段后间距 tip.setIndentationRight(220f); // 设置行距(行间距) //mixedParagraph.setLeading(24f); // 绝对行距 //mixedParagraph.setLeading(1.5f, 2f); // 也可以使用相对行距:mixedParagraph.setLeading(1.5f, 24f); // 第一个参数是文本高度的倍数,第二个参数是额外的固定行距 Font titleFont = new Font(bfChinese, 14, Font.NORMAL); Paragraph title = new Paragraph("数控程序审批单", titleFont); //title.setLeading(40f, 0f); tip.setSpacingBefore(-0.5f); title.setSpacingAfter(10); // 段后间距 title.setAlignment(Element.ALIGN_CENTER); title.setPaddingTop(-0.6f); Paragraph mixedParagraph = new Paragraph(); mixedParagraph.add(tip); mixedParagraph.add(title); mixedParagraph.setSpacingAfter(10); document.add(mixedParagraph); //document.add(title); // 创建表格(4列) PdfPTable table = new PdfPTable(5); table.setWidths(new float[]{1.5f, 1.4f, 1.4f, 1.4f, 1.5f}); Font ft = this.getChineseFont(); // 添加表头 PdfPCell tempCell = new PdfPCell();//getCell("零组件号"); tempCell.setHorizontalAlignment(Element.ALIGN_CENTER); tempCell.setVerticalAlignment(Element.ALIGN_MIDDLE); Phrase pt1 = new Phrase("零组件号", ft); tempCell.setPhrase(pt1); //tempCell.addElement(pt1); // 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(approveInfo.getTeamLeaderName(), 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; Date programDate = approveInfo.getProgrammingDate(); //TODO 查询时间 Date checkDate = approveInfo.getCheckDate(); Phrase p; if (1 == flag) { p = new Phrase(" " + approveInfo.getProgrammerName() + " ", underLineFt); } else { p = new Phrase(" " + approveInfo.getCheckerName() + " ", underLineFt); } line2Para.add(p); Phrase p2 = new Phrase("负责数控程序(编制"); if (flag == 1) { p2.add(block2); p2.add(new Chunk(" 校对", ft)); p2.add(block1); } else { p2.add(block1); p2.add(new Chunk(" 校对", ft)); p2.add(block2); } p2.add(new Chunk(")", ft)); line2Para.add(p2); 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); String pDateStr = " "; if (programDate != null) { pDateStr = DateUtil.format(programDate, "yyyy-MM-dd"); } String checkDateStr = " "; if (checkDate != null) { checkDateStr = DateUtil.format(programDate, "yyyy-MM-dd"); } String approveDateStr = " "; if (approveInfo.getApproveDate() != null) { approveDateStr = DateUtil.format(approveInfo.getApproveDate(), "yyyy-MM-dd"); } table.addCell(getCell(approveInfo.getProgrammerName()+" " +pDateStr, ft));//编制/日期 table.addCell(getCell(approveInfo.getCheckerName()+" " +checkDateStr, ft)); table.addCell(getCell(approveInfo.getSeniorName()+" " +approveDateStr, ft)); PdfPCell sendPathCell = getCell("数控程序传输路径:" + (machine.getProgSendDir() == null ? "" : machine.getProgSendDir()), ft);// PdfPCell(); sendPathCell.setHorizontalAlignment(Element.ALIGN_LEFT); sendPathCell.setColspan(5); table.addCell(sendPathCell); // 设置表格宽度占页面宽度的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); } return cell; } ApproveTableInfo getApproveInfo(FlowProgramProperties props){ //编制 R leaderR = useClient.userInfoById(props.getTeamLeaderId()); String leaderName = ""; if (leaderR.isSuccess()) { leaderName = leaderR.getData().getName(); } //编制 R 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 checkerR = useClient.userInfoById(props.getCheckerId()); String checkerName = ""; if (checkerR.isSuccess()) { checkerName = checkerR.getData().getName(); } //审核 R 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 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 appOpt = programApprovedService.lambdaQuery().eq(NcProgramApproved::getProcessInstanceId, props.getProcessInstanceId()).oneOpt(); if(appOpt.isEmpty()){ appInfo.setProgramNo("(未生成)"); }else{ NcNode programPkgNameNode = this.ncNodeService.getById(appOpt.get().getNcNodeId()); appInfo.setProgramNo(programPkgNameNode.getProgramNo()); } return appInfo; } }