From 61763cc1a182effa7e5535ac72d54a6a56f029eb Mon Sep 17 00:00:00 2001
From: yangys <y_ys79@sina.com>
Date: 星期六, 06 九月 2025 09:52:41 +0800
Subject: [PATCH] word版审批表,确认表

---
 doc/mdm/qrb.docx                                                                                                 |    0 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/commons/service/UserCommonService.java                 |   40 ++
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/statreport/controller/ApproveTablePrintController.java |   93 +++++
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/execute/BatchDispatchService.java         |   20 +
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/statreport/service/ConfirmTablePrintService.java       |  205 +++++++++++
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/entity/TaskDispatch.java                          |    5 
 doc/mdm/spd.docx                                                                                                 |    0 
 blade-service/blade-mdm/pom.xml                                                                                  |   38 ++
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/statreport/service/ApproveTableService.java            |  168 +++++++++
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/ProgramConfirmTableService.java           |    4 
 /dev/null                                                                                                        |   74 ----
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/statreport/controller/ConfirmTablePrintController.java |   81 ++++
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/statreport/utils/WordReplaceUtil.java                  |  113 ++++++
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/FlowCommonService.java                    |    8 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/StartDispatcher.java                     |    1 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/execute/AbstractFlowCompleteService.java  |    7 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/controller/FlowMgrController.java                 |   23 -
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/statreport/utils/XmlToDocxWithPOI.java                 |   25 +
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/execute/TryFlowCompleteService.java       |   24 +
 blade-service/blade-mdm/src/test/java/org/springblade/mdm/statreport/utils/XmlToDocxWithPOITest.java             |  142 +++++++
 20 files changed, 960 insertions(+), 111 deletions(-)

diff --git a/blade-service/blade-mdm/pom.xml b/blade-service/blade-mdm/pom.xml
index ddf3ebc..43bdc93 100644
--- a/blade-service/blade-mdm/pom.xml
+++ b/blade-service/blade-mdm/pom.xml
@@ -116,6 +116,44 @@
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-freemarker</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.docx4j</groupId>
+            <artifactId>docx4j-core</artifactId>
+            <version>8.3.10</version>
+        </dependency>
+        <dependency>
+            <groupId>org.docx4j</groupId>
+            <artifactId>docx4j-JAXB-Internal</artifactId>
+            <version>8.3.10</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>javax.xml.bind</groupId>
+                    <artifactId>jaxb-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.docx4j</groupId>
+            <artifactId>docx4j-JAXB-ReferenceImpl</artifactId>
+            <version>8.3.10</version>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jaxb</groupId>
+            <artifactId>jaxb-runtime</artifactId>
+            <version>2.3.1</version>
+        </dependency>
+        <!-- Apache POI 鐢ㄤ簬澶勭悊docx鏂囦欢 -->
+        <!--<dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml</artifactId>
+        </dependency>-->
+
+        <!-- 鍖呭惈OpenXML鏍煎紡鐨勫畬鏁� schema 瀹氫箟 -->
+        <!--<dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml-full</artifactId>
+            <version>5.4.0</version>
+        </dependency>-->
     </dependencies>
     <build>
         <plugins>
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/commons/service/UserCommonService.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/commons/service/UserCommonService.java
new file mode 100644
index 0000000..47a7cc8
--- /dev/null
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/commons/service/UserCommonService.java
@@ -0,0 +1,40 @@
+
+package org.springblade.mdm.commons.service;
+
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springblade.core.tool.api.R;
+import org.springblade.mdm.flow.constants.FlowContants;
+import org.springblade.system.feign.ISysClient;
+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.util.Map;
+
+/**
+ * 绯荤粺鍙傛暟鑾峰彇鏈嶅姟
+ *
+ * @author yangys
+ */
+@Slf4j
+@Service
+public class UserCommonService {
+	@Autowired
+	private IUserClient userClient;
+	/**
+	 * 鑾峰彇鐢ㄦ埛濮撳悕
+	 * @return
+	 */
+	public String getUserNameById(Long programmerId){
+		R<User> programmerResult = userClient.userInfoById(programmerId);
+		if(programmerResult.isSuccess()) {
+			return programmerResult.getData().getName();
+		}else{
+			return null;
+		}
+	}
+
+
+}
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/controller/FlowMgrController.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/controller/FlowMgrController.java
index c729b8e..89f11f7 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/controller/FlowMgrController.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/controller/FlowMgrController.java
@@ -31,9 +31,6 @@
 import org.springframework.format.annotation.DateTimeFormat;
 import org.springframework.web.bind.annotation.*;
 
-import java.io.IOException;
-import java.net.URLEncoder;
-import java.nio.charset.StandardCharsets;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.util.ArrayList;
@@ -52,8 +49,7 @@
 	private FlowCommonService flowCommonService;
 	@Autowired
 	private HistoryService historyService;
-	@Autowired
-	private ApproveTableService approveTableService;
+
 	@Autowired
 	private ProgramConfirmTableService programConfirmTableService;
 	@Autowired
@@ -169,24 +165,7 @@
 		return R.success();
 	}
 
-	@PostMapping("/export-approve-table")
-	@Operation(summary = "瀵煎嚭瀹℃壒琛�", description = "瀵煎嚭瀹℃壒琛╬df")
-	public void exportApproveTable(String processInstanceId, HttpServletResponse response) {
 
-		try {
-			FlowProgramProperties props = flowCommonService.getProgramPropertiesFromHis(processInstanceId);
-			String progName = props.getDrawingNo()+"-"+props.getProcessNo()+"-"+props.getProcessEdition();
-			//String filename = URLEncoder.encode("鏁版帶绋嬪簭缂栧埗瀹℃壒鍗�", StandardCharsets.UTF_8)+ DateUtil.format(DateUtil.now(), "yyyyMMddHHmm")+".pdf";
-			String filename = UrlUtil.encode("鏁版帶绋嬪簭缂栧埗瀹℃壒鍗�"+progName)+".pdf";
-			response.setHeader("Content-Disposition", "attachment; filename="+filename);
-			response.setContentType("application/octet-stream");
-			approveTableService.exportApproveTable(processInstanceId,response.getOutputStream());
-		} catch (Exception e) {
-			log.error("瀵煎嚭瀹℃壒琛ㄥ紓甯�", e);
-			throw new RuntimeException(e);
-		}
-
-	}
 
 	@PostMapping("/export-confirm-table")
 	@Operation(summary = "瀵煎嚭纭琛�", description = "瀵煎嚭鏁版帶绋嬪簭纭琛╬df")
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/entity/TaskDispatch.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/entity/TaskDispatch.java
index 115429b..db9525e 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/entity/TaskDispatch.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/entity/TaskDispatch.java
@@ -83,4 +83,9 @@
 	 * 閿欒淇℃伅
 	 */
 	private String errMsg;
+
+	/**
+	 * 绋嬪簭缂栧彿
+	 */
+	private String programNo;
 }
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/StartDispatcher.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/StartDispatcher.java
index 5f7dad7..a3b8bf8 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/StartDispatcher.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/StartDispatcher.java
@@ -126,7 +126,6 @@
 			ncNodeService.updateById(curedProgramPackage);
 		}
 
-
 		return inst.getProcessInstanceId();
 	}
 
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/ApproveTableService.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/ApproveTableService.java
deleted file mode 100644
index 7336c4b..0000000
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/ApproveTableService.java
+++ /dev/null
@@ -1,178 +0,0 @@
-
-package org.springblade.mdm.flow.service;
-
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
-import org.springblade.core.oss.OssTemplate;
-import org.springblade.core.tool.utils.DateUtil;
-import org.springblade.mdm.basesetting.machine.service.MachineService;
-import org.springblade.mdm.basesetting.machine.entity.Machine;
-import org.springblade.mdm.commons.service.ParamService;
-import org.springblade.mdm.commons.support.TemplatedPdfWriter;
-import org.springblade.mdm.flow.constants.FlowContants;
-import org.springblade.mdm.flow.vo.ApproveTableInfo;
-import org.springblade.mdm.program.service.NcNodeService;
-import org.springblade.system.feign.IUserClient;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.*;
-
-import com.itextpdf.text.*;
-import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
-
-/**
- * 瀹℃壒璁板綍锛岀敤浜庢煡璇㈡墽琛岃建杩�
- *
- * @author yangys
- */
-@Slf4j
-@Service
-public class ApproveTableService {
-	@Autowired
-	private FlowCommonService flowCommonService;
-	@Autowired
-	private NcNodeService ncNodeService;
-	@Autowired
-	private MachineService machineService;
-	@Autowired
-	private IUserClient useClient;
-	@Autowired
-	private ParamService paramService;
-	@Autowired
-	private OssTemplate ossTemplate;
-
-	@Autowired
-	private ApproveInfoQueryService approveInfoQueryService;
-
-	@Autowired
-	private FreeMarkerConfigurer freeMarkerConfigurer;
-
-	//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 IOException, DocumentException {
-		FlowProgramProperties props = flowCommonService.getProgramPropertiesFromHis(processInstanceId);
-
-		TemplatedPdfWriter pdfWriter = new TemplatedPdfWriter(getTemplateBytes());
-		pdfWriter.write(getPdfData(props),os);
-	}
-
-	/**
-	 * 鑾峰彇pdf妯℃澘鐨勫瓧鑺傛暟缁�
-	 * @return 妯℃澘瀛楄妭鏁扮粍
-	 * @throws IOException
-	 */
-	private byte[] getTemplateBytes() throws IOException {
-		String tplOssName = paramService.approveTableTemplateOssFileName();
-		try (InputStream inputStream = this.ossTemplate.statFileStream(tplOssName)) {
-			return inputStream.readAllBytes();
-		}
-	}
-
-	/**
-	 * 鑾峰彇濉厖鏁版嵁
-	 */
-
-	Map<String,String> getPdfData(FlowProgramProperties props){
-		ApproveTableInfo approveInfo = approveInfoQueryService.getApproveInfo(props);
-		Machine machine;
-		String machineCode = props.getMachineCode();
-		machine = machineService.getByCode(machineCode);
-
-		Map<String,String> pdfData = new HashMap<>();
-		pdfData.put("drawingNo",props.getDrawingNo());
-		pdfData.put("processNo",props.getProcessNo());
-		pdfData.put("craftEdition",props.getCraftEdition());
-		pdfData.put("machineMode",machine.getName());
-
-		String DATE_PATTERN = "yyyy-M-d";
-
-		String dispatchDateStr = " ";
-		if (approveInfo.getDispatchDate() != null) {
-			dispatchDateStr = DateUtil.format(approveInfo.getDispatchDate(), DATE_PATTERN);
-		}
-
-		pdfData.put("teamLeader",approveInfo.getTeamLeaderName()+"/"+dispatchDateStr);
-
-		if(StringUtils.equals(props.getHasCuredProgram(),FlowContants.Y)){
-			pdfData.put("fuzeren",approveInfo.getCheckerName());
-			pdfData.put("checkY","Y");//鍥哄寲锛屽睘浜庢牎瀵逛换鍔�
-		}else{
-			pdfData.put("fuzeren",approveInfo.getProgrammerName());//璐熻矗浜�
-			pdfData.put("programY","Y");//鍏朵粬锛屽睘浜庣紪鍒朵换鍔�
-		}
-		pdfData.put("fangzhenY","Y");
-
-		pdfData.put("programNo",approveInfo.getProgramNo());
-
-		Date programDate = approveInfo.getCheckDate();
-		Date checkDate = approveInfo.getCheckDate();
-
-		String pDateStr = " ";
-		if (programDate != null) {
-			pDateStr = DateUtil.format(programDate, DATE_PATTERN);
-		}
-		String checkDateStr = " ";
-		if (checkDate != null) {
-			checkDateStr = DateUtil.format(programDate, DATE_PATTERN);
-		}
-
-		String approveDateStr = " ";
-		if (approveInfo.getApproveDate() != null) {
-			approveDateStr = DateUtil.format(approveInfo.getApproveDate(), DATE_PATTERN);
-		}
-
-		pdfData.put("programmer",approveInfo.getProgrammerName()+"/"+pDateStr);
-		pdfData.put("checker",approveInfo.getCheckerName()+"/"+checkDateStr);
-		pdfData.put("senior",approveInfo.getSeniorName()+"/"+approveDateStr);
-
-		pdfData.put("sendDir",machine.getProgSendDir()!=null?machine.getProgSendDir():"");
-
-		return pdfData;
-	}
-
-	/*
-	public void exportApproveTableOld(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();
-	}
-	*/
-
-
-}
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/FlowCommonService.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/FlowCommonService.java
index be09907..e0c2278 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/FlowCommonService.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/FlowCommonService.java
@@ -13,6 +13,7 @@
 import org.springblade.mdm.basesetting.machine.entity.Machine;
 import org.springblade.mdm.basesetting.producedivision.entity.ProduceDivision;
 import org.springblade.mdm.basesetting.producedivision.service.ProduceDivisionService;
+import org.springblade.mdm.commons.service.UserCommonService;
 import org.springblade.mdm.flow.constants.FlowContants;
 import org.springblade.mdm.flow.constants.FlowVariableContants;
 import org.springblade.mdm.program.entity.NcNode;
@@ -32,7 +33,7 @@
 	private final ProduceDivisionService produceDivisionService;
 	private final NodeDeptQueryService nodeDeptQueryService;
 	private final MachineService machineService;
-	private final IUserClient userClient;
+	private final UserCommonService userCommonService;
 	/**
 	 * 鏍规嵁娴佺▼瀹炰緥id鑾峰彇definitionKey
 	 * @param processInstanceId
@@ -178,10 +179,7 @@
 			vars.put(FlowContants.ASSIGNEE, defaultAssignee);//绗竴涓鎵圭敤鎴凤細缁勯暱
 		}
 
-		R<User> programmerResult = userClient.userInfoById(div.getProgrammerId());
-		if(programmerResult.isSuccess()) {
-			vars.put(FlowContants.PROGRAMMER_NAME, programmerResult.getData().getName());
-		}
+		vars.put(FlowContants.PROGRAMMER_NAME, userCommonService.getUserNameById(div.getProgrammerId()));
 		return div;
 	}
 
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/ProgramConfirmTableService.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/ProgramConfirmTableService.java
index 23113ee..fe8af9f 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/ProgramConfirmTableService.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/ProgramConfirmTableService.java
@@ -120,7 +120,7 @@
 
 		//闆剁粍浠跺悕绉�
 		data.put("drawingName",getDrawingName(props.getDrawingNo()));
-		data.put("deviation",props.getDeviation());
+		data.put("deviation",props.getDeviation()!=null?props.getDeviation():StringUtils.EMPTY);
 
 
 
@@ -136,6 +136,8 @@
 		data.put("fuheY","Y");//TODO 鏈� 妫�楠屽憳 鍒欑鍚�
 		data.put("keyongY","Y");//TODO 鏈� 妫�楠屽憳 鍒欑鍚�
 
+		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());
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/execute/AbstractFlowCompleteService.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/execute/AbstractFlowCompleteService.java
index ec94ba4..543c53c 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/execute/AbstractFlowCompleteService.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/execute/AbstractFlowCompleteService.java
@@ -4,7 +4,11 @@
 import org.flowable.engine.RuntimeService;
 import org.flowable.engine.TaskService;
 import org.flowable.task.api.Task;
+import org.springblade.core.tool.api.R;
+import org.springblade.mdm.flow.constants.FlowContants;
 import org.springblade.mdm.flow.service.ApproveRecordService;
+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 org.springframework.transaction.annotation.Transactional;
@@ -23,6 +27,7 @@
 	protected RuntimeService runtimeService;
 	@Autowired
 	protected ApproveRecordService approveRecordService;
+
 	@Transactional
 	public abstract void completeTask(String taskId, String processInstanceId, String comment, @Parameter(name = "variables", description = "娴佺▼鍙橀噺") @RequestBody Map<String, Object> variables);
 
@@ -48,4 +53,6 @@
 		String operateResult = variables.get("approve")+"";
 		approveRecordService.saveApproveRecords(currentTask(taskId),operateResult,comment);
 	}
+
+
 }
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/execute/BatchDispatchService.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/execute/BatchDispatchService.java
index 32c732a..74c3c7a 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/execute/BatchDispatchService.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/execute/BatchDispatchService.java
@@ -7,7 +7,9 @@
 import org.flowable.task.api.Task;
 import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.tool.support.Kv;
+import org.springblade.core.tool.utils.Func;
 import org.springblade.core.tool.utils.StringUtil;
+import org.springblade.mdm.commons.service.UserCommonService;
 import org.springblade.mdm.flow.constants.FlowContants;
 import org.springblade.mdm.flow.constants.FlowVariableContants;
 import org.springblade.mdm.flow.service.ApproveRecordService;
@@ -35,6 +37,8 @@
 	private RuntimeService runtimeService;
 	@Autowired
 	private FlowCommonService flowCommonService;
+	@Autowired
+	private UserCommonService userCommonService;
 	@Transactional
 	public void batchDispatchTask(BatchDispatchVO batchDispatchVO) {
 		//String[] taskIds, String[] processInstanceIds, String comment, String assignee
@@ -54,8 +58,13 @@
 			taskId = taskIds[i];
 			processInstanceId = batchDispatchVO.getProcessInstanceIds()[i];
 
+			runtimeService.setVariable(processInstanceId,FlowContants.PROGRAMMER_NAME,userCommonService.getUserNameById(Func.toLong(batchDispatchVO.getAssignee())));
+
 			Task task = getTask(taskId);
 
+			if(!task.getTaskDefinitionKey().equals("teamLeaderTask")){
+				throw new ServiceException("闈瀃浠诲姟鍒嗘淳]鑺傜偣鐨勪换鍔′笉鑳芥壒閲忔淳宸�");
+			}
 			if (StringUtil.isNoneBlank(processInstanceId, comment)) {
 				taskService.addComment(taskId, processInstanceId, comment);
 			}
@@ -87,9 +96,16 @@
 			taskId = taskIds[i];
 			processInstanceId = batchDispatchVO.getProcessInstanceIds()[i];
 
-			variables.put("assignee", getAutoProgrammer(processInstanceId));
-
 			Task task = getTask(taskId);
+			if(!task.getTaskDefinitionKey().equals("teamLeaderTask")){
+				throw new ServiceException("闈瀃浠诲姟鍒嗘淳]鑺傜偣鐨勪换鍔′笉鑳芥壒閲忔淳宸�");
+			}
+
+			Object programmerId = getAutoProgrammer(processInstanceId);
+			variables.put("assignee", programmerId);
+
+			runtimeService.setVariable(processInstanceId,FlowContants.PROGRAMMER_NAME,userCommonService.getUserNameById(Func.toLong(programmerId)));
+
 
 			if (StringUtil.isNoneBlank(processInstanceId, batchDispatchVO.getComment())) {
 				taskService.addComment(taskId, processInstanceId, batchDispatchVO.getComment());
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/execute/TryFlowCompleteService.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/execute/TryFlowCompleteService.java
index 0884332..7fb183e 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/execute/TryFlowCompleteService.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/execute/TryFlowCompleteService.java
@@ -4,17 +4,21 @@
 import org.flowable.task.api.Task;
 import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.secure.utils.AuthUtil;
+import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.support.Kv;
 import org.springblade.core.tool.utils.Func;
 import org.springblade.core.tool.utils.StringUtil;
 import org.springblade.mdm.basesetting.machine.entity.Machine;
 import org.springblade.mdm.basesetting.machine.service.MachineService;
 import org.springblade.mdm.commons.service.ParamService;
+import org.springblade.mdm.commons.service.UserCommonService;
 import org.springblade.mdm.flow.constants.FlowContants;
 import org.springblade.mdm.flow.constants.FlowVariableContants;
 import org.springblade.mdm.flow.service.FlowCommonService;
 import org.springblade.mdm.flow.service.FlowProgramFileService;
 import org.springblade.mdm.flow.service.FlowProgramProperties;
+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 org.springframework.transaction.annotation.Transactional;
@@ -34,6 +38,8 @@
 	@Autowired
 	private FlowCommonService flowCommonService;
 	@Autowired
+	private UserCommonService userCommonService;
+	@Autowired
 	private MachineService machineService;
 
 	@Transactional
@@ -47,6 +53,11 @@
 			throw new ServiceException("璇锋寚瀹氭祦绋嬩笅涓�姝ュ鐞嗕汉");
 		}
 
+		// 闈炵┖鍒ゆ柇
+		if (Func.isEmpty(variables)) {
+			variables = Kv.create();
+		}
+
 		if(task.getTaskDefinitionKey().equals("programmingTask") ) {//缂栧埗鑺傜偣
 			//璁板綍瀹為檯缂栫▼鍛�
 			variables.put(FlowVariableContants.ACT_PROGRAMMER,Func.toStr(AuthUtil.getUserId()));
@@ -54,14 +65,16 @@
 			if(this.needUploadProgramFile(props.getMachineCode())) {
 				flowProgramFileService.checkProgramFiles(processInstanceId, FlowContants.Y.equals(operateResult));
 			}
+		}else if(task.getTaskDefinitionKey().equals("teamLeaderTask")){
+			if(FlowContants.Y.equals(operateResult)) {
+				runtimeService.setVariable(task.getExecutionId(),FlowContants.PROGRAMMER_NAME,userCommonService.getUserNameById(Func.toLong(variables.get("assignee"))));
+			}
+
 		}
 		if (StringUtil.isNoneBlank(processInstanceId, comment)) {
 			taskService.addComment(taskId, processInstanceId, comment);
 		}
-		// 闈炵┖鍒ゆ柇
-		if (Func.isEmpty(variables)) {
-			variables = Kv.create();
-		}
+
 		variables.put(FlowContants.LAST_STEP_USER_NICKNAME, AuthUtil.getNickName());
 
 
@@ -70,13 +83,12 @@
 		variables.remove(FlowContants.PROCESS_EDITION);//涓嶈鍗囩増浜�
 
 		if("confirmIsUseableTask".equals(task.getTaskDefinitionKey())){
-
 			variables.put(FlowContants.CURE_PROGRAM_USEABLE,operateResult);
-
 		}
 		taskService.complete(taskId, variables);
 	}
 
+
 	/**
 	 * 鏄惁闇�瑕佷笂浼犳枃浠讹紙杞﹀簥涓嶉渶瑕侊級
 	 * @param machineCode 鏈哄簥缂栫爜
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/statreport/controller/ApproveTablePrintController.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/statreport/controller/ApproveTablePrintController.java
new file mode 100644
index 0000000..0212ca4
--- /dev/null
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/statreport/controller/ApproveTablePrintController.java
@@ -0,0 +1,93 @@
+package org.springblade.mdm.statreport.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.poi.ss.usermodel.DateUtil;
+import org.flowable.engine.RuntimeService;
+import org.flowable.engine.TaskService;
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.core.tool.utils.UrlUtil;
+import org.springblade.mdm.flow.entity.TaskDispatch;
+import org.springblade.mdm.flow.excution.StartDispatcher;
+import org.springblade.mdm.flow.service.FlowCommonService;
+import org.springblade.mdm.flow.service.FlowProgramFileService;
+import org.springblade.mdm.flow.service.FlowProgramProperties;
+import org.springblade.mdm.flow.service.TaskDispatchService;
+import org.springblade.mdm.flow.service.execute.DefaultFlowCompleteService;
+import org.springblade.mdm.flow.service.execute.TryFlowCompleteService;
+import org.springblade.mdm.flow.vo.DispathTaskQueryVO;
+import org.springblade.mdm.flow.vo.TaskAssignVO;
+import org.springblade.mdm.statreport.service.ApproveTableService;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.time.LocalDateTime;
+
+@Slf4j
+@RestController
+@AllArgsConstructor
+@RequestMapping("/statreport/tableprint")
+@Tag(name = "琛ㄦ牸鎵撳嵃", description = "琛ㄦ牸鎵撳嵃")
+public class ApproveTablePrintController {
+
+	@Autowired
+	private FlowCommonService flowCommonService;
+	@Autowired
+	private ApproveTableService approveTableService;
+	private final TaskDispatchService taskDispatchService;
+	@Operation(summary = "浠诲姟瀹℃壒琛�", description = "浠诲姟瀹℃壒琛�")
+	@GetMapping("/dispatch-page")
+	public R<IPage<TaskDispatch>> dispatchPatch(DispathTaskQueryVO queryVO) {
+		LocalDateTime end = null;
+		if(queryVO.getCreateTimeEnd()!=null){
+			end = DateUtil.toLocalDateTime(queryVO.getCreateTimeEnd()).plusDays(1);
+		}
+		return R.data(taskDispatchService.lambdaQuery()
+			.like(StringUtils.isNotBlank(queryVO.getDrawingNo()), TaskDispatch::getDrawingNo,queryVO.getDrawingNo())
+			.eq(TaskDispatch::getStatus,TaskDispatch.STATUS_STARTED)
+			.ge(queryVO.getCreateTimeBegin()!=null, TaskDispatch::getCreateTime,queryVO.getCreateTimeBegin())
+			.le(queryVO.getCreateTimeEnd()!=null, TaskDispatch::getCreateTime,end).orderByDesc(TaskDispatch::getCreateTime)
+			.page(Condition.getPage(queryVO)));
+	}
+
+	@PostMapping("/export-approve-table")
+	@Operation(summary = "瀵煎嚭瀹℃壒琛�", description = "瀵煎嚭瀹℃壒琛╬df")
+	public void exportApproveTable(String id,HttpServletResponse response) throws IOException {
+
+		TaskDispatch dispatch = taskDispatchService.getById(id);
+		FlowProgramProperties props = flowCommonService.getProgramPropertiesFromHis(dispatch.getProcessInstanceId());
+
+		String progName = props.getDrawingNo()+"-"+props.getProcessNo()+"-"+props.getProcessEdition();
+
+		String filename = UrlUtil.encode("鏁版帶绋嬪簭缂栧埗瀹℃壒鍗�"+progName)+".docx";
+
+
+		ByteArrayOutputStream outputStream = approveTableService.exportApproveTableDoc(dispatch,props);
+
+		byte[] fileBytes = outputStream.toByteArray();
+
+		response.setHeader("Content-Disposition", "attachment; filename="+filename);
+		response.setContentType("application/octet-stream");
+		response.getOutputStream().write(fileBytes);
+
+	}
+
+}
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/statreport/controller/ConfirmTablePrintController.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/statreport/controller/ConfirmTablePrintController.java
new file mode 100644
index 0000000..8ab66f9
--- /dev/null
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/statreport/controller/ConfirmTablePrintController.java
@@ -0,0 +1,81 @@
+package org.springblade.mdm.statreport.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.poi.ss.usermodel.DateUtil;
+import org.flowable.engine.HistoryService;
+import org.flowable.engine.RuntimeService;
+import org.flowable.engine.history.HistoricProcessInstance;
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.mp.support.Query;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.UrlUtil;
+import org.springblade.mdm.flow.entity.TaskDispatch;
+import org.springblade.mdm.flow.service.FlowCommonService;
+import org.springblade.mdm.flow.service.FlowProgramProperties;
+import org.springblade.mdm.flow.service.TaskDispatchService;
+import org.springblade.mdm.flow.vo.DispathTaskQueryVO;
+import org.springblade.mdm.flow.vo.FlowVO;
+import org.springblade.mdm.statreport.service.ApproveTableService;
+import org.springblade.mdm.statreport.service.ConfirmTablePrintService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.time.LocalDateTime;
+
+@Slf4j
+@RestController
+@AllArgsConstructor
+@RequestMapping("/statreport/tableprint")
+@Tag(name = "琛ㄦ牸鎵撳嵃", description = "琛ㄦ牸鎵撳嵃")
+public class ConfirmTablePrintController {
+
+	private FlowCommonService flowCommonService;
+	private ConfirmTablePrintService confirmTablePrintService;
+	private final TaskDispatchService taskDispatchService;
+	private final HistoryService hisService;
+
+	@GetMapping("/confirm-page")
+	@ApiOperationSupport(order = 3)
+	@Operation(summary = "纭鍗曞垪琛�", description = "纭鍗曞垪琛�")
+	public R<IPage<FlowVO>> finishedList(@Parameter(description = "娴佺▼鍚嶇О")String myProcessName, @Parameter(description = "娴佺▼鍒涘缓鏃堕棿寮�濮�") LocalDateTime createTimeBegin, @Parameter(description = "娴佺▼鍒涘缓鏃堕棿鎴") LocalDateTime createTimeEnd, @Parameter(description = "鍏抽敭瀛�") String keyword, Query query) {
+		IPage<FlowVO> pages = confirmTablePrintService.confirmTablePage(Condition.getPage(query), myProcessName,keyword,createTimeBegin,createTimeEnd);
+		return R.data(pages);
+	}
+
+
+	@PostMapping("/export-confirm-table")
+	@Operation(summary = "瀵煎嚭鏁版帶绋嬪簭纭琛�", description = "鏁版帶绋嬪簭纭琛�")
+	public void exportConfirmTable(String processInstanceId,HttpServletResponse response) throws IOException {
+
+		HistoricProcessInstance his = hisService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
+		String taskDispatchId = his.getBusinessKey();
+		TaskDispatch dispatch = taskDispatchService.getById(taskDispatchId);
+		FlowProgramProperties props = flowCommonService.getProgramPropertiesFromHis(processInstanceId);
+
+		String progName = props.getDrawingNo()+"-"+props.getProcessNo()+"-"+props.getProcessEdition();
+
+		String filename = UrlUtil.encode("鏁版帶绋嬪簭纭琛�"+progName)+".docx";
+
+		ByteArrayOutputStream outputStream = confirmTablePrintService.exportConfirmTableDoc(dispatch,props);
+
+		byte[] fileBytes = outputStream.toByteArray();
+
+		response.setHeader("Content-Disposition", "attachment; filename="+filename);
+		response.setContentType("application/octet-stream");
+		response.getOutputStream().write(fileBytes);
+
+	}
+}
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/statreport/service/ApproveTableService.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/statreport/service/ApproveTableService.java
new file mode 100644
index 0000000..7eda2b9
--- /dev/null
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/statreport/service/ApproveTableService.java
@@ -0,0 +1,168 @@
+
+package org.springblade.mdm.statreport.service;
+
+import com.itextpdf.text.DocumentException;
+import freemarker.template.Template;
+import freemarker.template.TemplateException;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springblade.core.oss.OssTemplate;
+import org.springblade.core.tool.utils.DateUtil;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.mdm.basesetting.machine.entity.Machine;
+import org.springblade.mdm.basesetting.machine.service.MachineService;
+import org.springblade.mdm.commons.service.ParamService;
+import org.springblade.mdm.commons.support.TemplatedPdfWriter;
+import org.springblade.mdm.flow.constants.FlowContants;
+import org.springblade.mdm.flow.entity.TaskDispatch;
+import org.springblade.mdm.flow.service.ApproveInfoQueryService;
+import org.springblade.mdm.flow.service.FlowCommonService;
+import org.springblade.mdm.flow.service.FlowProgramProperties;
+import org.springblade.mdm.flow.service.TaskDispatchService;
+import org.springblade.mdm.flow.vo.ApproveTableInfo;
+import org.springblade.mdm.program.service.NcNodeService;
+import org.springblade.mdm.statreport.utils.WordReplaceUtil;
+import org.springblade.system.feign.IUserClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 瀹℃壒璁板綍锛岀敤浜庢煡璇㈡墽琛岃建杩�
+ *
+ * @author yangys
+ */
+@Slf4j
+@Service
+public class ApproveTableService {
+	@Autowired
+	private NcNodeService ncNodeService;
+	@Autowired
+	private MachineService machineService;
+	@Autowired
+	private IUserClient useClient;
+	@Autowired
+	private OssTemplate ossTemplate;
+
+	@Autowired
+	private ApproveInfoQueryService approveInfoQueryService;
+
+	@Autowired
+	private ParamService paramService;
+	/**
+	 * 瀵煎嚭word宀告湰
+	 * @param dispatch 浠诲姟鍒嗘淳
+	 * @param props 娴佺▼灞炴��
+	 */
+	public ByteArrayOutputStream exportApproveTableDoc(TaskDispatch dispatch,FlowProgramProperties props) throws IOException {
+		ByteArrayOutputStream os= new ByteArrayOutputStream();
+		String tplOssName = paramService.approveTableTemplateOssFileName();
+		try(InputStream tplInputStream = ossTemplate.statFileStream(tplOssName);) {
+			WordReplaceUtil.convert(getData(dispatch, props), tplInputStream, os);
+		}
+		return os;
+	}
+
+	/**
+	 * 鑾峰彇濉厖鏁版嵁
+	 */
+
+	Map<String,String> getData(TaskDispatch dispatch,FlowProgramProperties props){
+		ApproveTableInfo approveInfo = approveInfoQueryService.getApproveInfo(props);
+		Machine machine;
+		String machineCode = props.getMachineCode();
+		machine = machineService.getByCode(machineCode);
+
+		Map<String,String> dataMap = new HashMap<>();
+		dataMap.put("drawingNo",props.getDrawingNo());
+		dataMap.put("processNo",props.getProcessNo());
+		dataMap.put("craftEdition",props.getCraftEdition());
+		dataMap.put("processEdition",props.getProcessEdition());
+		dataMap.put("machineMode",machine.getName());
+
+		String DATE_PATTERN = "yyyy-M-d";
+
+		String dispatchDateStr = " ";
+		if (approveInfo.getDispatchDate() != null) {
+			dispatchDateStr = DateUtil.format(approveInfo.getDispatchDate(), DATE_PATTERN);
+		}
+
+		dataMap.put("teamLeader",approveInfo.getTeamLeaderName()+"/"+dispatchDateStr);
+		dataMap.put("fuzeren",approveInfo.getProgrammerName());//璐熻矗浜�
+		int isProgram = 0;
+		if(StringUtils.equals(props.getHasCuredProgram(),FlowContants.Y)){
+			//鏍″浠诲姟
+			dataMap.put("jd", WordReplaceUtil.CHECKED);
+			dataMap.put("bc", WordReplaceUtil.UNCHECKED);
+
+		}else{
+			//缂栫▼浠诲姟
+			dataMap.put("jd", WordReplaceUtil.UNCHECKED);
+			dataMap.put("bc", WordReplaceUtil.CHECKED);
+		}
+
+		dataMap.put("programNo",dispatch.getProgramNo());
+		dataMap.put("fzy",WordReplaceUtil.CHECKED);
+		dataMap.put("fzn",WordReplaceUtil.UNCHECKED);
+		Date programDate = approveInfo.getCheckDate();
+		Date checkDate = approveInfo.getCheckDate();
+
+		String bianzhiDateStr = DateUtil.format(dispatch.getCreateTime(), DATE_PATTERN);
+
+		String checkDateStr = " ";
+		if (checkDate != null) {
+			checkDateStr = DateUtil.format(programDate, DATE_PATTERN);
+		}
+
+		String approveDateStr = " ";
+		if (approveInfo.getApproveDate() != null) {
+			approveDateStr = DateUtil.format(approveInfo.getApproveDate(), DATE_PATTERN);
+		}
+
+		dataMap.put("programmer",approveInfo.getProgrammerName()+"/"+bianzhiDateStr);
+		dataMap.put("jiaodui",approveInfo.getTeamLeaderName()+"/鏃堕棿涓嶇‘瀹�");
+		dataMap.put("shenpi",approveInfo.getSeniorName()+"/鏃堕棿涓嶇‘瀹�");
+
+		dataMap.put("sendPath",machine.getProgSendDir()!=null?machine.getProgSendDir():"");
+
+		return dataMap;
+	}
+
+	/*
+	public void exportApproveTableOld(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();
+	}
+	*/
+
+
+}
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/statreport/service/ConfirmTablePrintService.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/statreport/service/ConfirmTablePrintService.java
new file mode 100644
index 0000000..9560746
--- /dev/null
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/statreport/service/ConfirmTablePrintService.java
@@ -0,0 +1,205 @@
+
+package org.springblade.mdm.statreport.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import lombok.AllArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
+import org.flowable.engine.HistoryService;
+import org.flowable.engine.RuntimeService;
+import org.flowable.engine.TaskService;
+import org.flowable.engine.history.HistoricProcessInstance;
+import org.flowable.engine.history.HistoricProcessInstanceQuery;
+import org.flowable.engine.task.Comment;
+import org.flowable.task.api.Task;
+import org.flowable.task.api.TaskInfoQuery;
+import org.flowable.task.api.TaskQuery;
+import org.flowable.task.api.history.HistoricTaskInstance;
+import org.flowable.task.api.history.HistoricTaskInstanceQuery;
+import org.springblade.core.oss.OssTemplate;
+import org.springblade.core.secure.utils.AuthUtil;
+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.entity.Machine;
+import org.springblade.mdm.basesetting.machine.service.MachineService;
+import org.springblade.mdm.commons.contants.DictBizConstants;
+import org.springblade.mdm.commons.service.ParamService;
+import org.springblade.mdm.flow.constants.FlowContants;
+import org.springblade.mdm.flow.entity.FlowProgramFile;
+import org.springblade.mdm.flow.entity.MdmFlowProcess;
+import org.springblade.mdm.flow.entity.TaskDispatch;
+import org.springblade.mdm.flow.service.FlowProgramFileService;
+import org.springblade.mdm.flow.service.FlowProgramProperties;
+import org.springblade.mdm.flow.util.MdmFlowCache;
+import org.springblade.mdm.flow.vo.ApproveTableInfo;
+import org.springblade.mdm.flow.vo.FlowVO;
+import org.springblade.mdm.statreport.utils.WordReplaceUtil;
+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.IOException;
+import java.io.InputStream;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.*;
+
+/**
+ * 娴佺▼涓氬姟瀹炵幇绫�
+ *
+ * @author Chill
+ */
+@Service
+@AllArgsConstructor
+public class ConfirmTablePrintService {
+	private final RuntimeService runtimeService;
+	private final IDictBizClient dictBizClient;
+	private final HistoryService historyService;
+	private final IUserClient userClient;
+	private final FlowProgramFileService flowProgramFileService;
+	@Autowired
+	private MachineService machineService;
+	@Autowired
+	private ParamService paramService;
+	@Autowired
+	private OssTemplate ossTemplate;
+	/**
+	 * 瀵煎嚭word宀告湰
+	 * @param dispatch 浠诲姟鍒嗘淳
+	 * @param props 娴佺▼灞炴��
+	 */
+	public ByteArrayOutputStream exportConfirmTableDoc(TaskDispatch dispatch, FlowProgramProperties props) throws IOException {
+		ByteArrayOutputStream os= new ByteArrayOutputStream();
+		String tplOssName = paramService.confirmTableTemplateOssFileName();
+		try(InputStream tplInputStream = ossTemplate.statFileStream(tplOssName);) {
+			WordReplaceUtil.convert(getData(dispatch, props), tplInputStream, os);
+		}
+		return os;
+	}
+
+	/**
+	 * 鑾峰彇濉厖鏁版嵁
+	 */
+
+	Map<String,String> getData(TaskDispatch dispatch,FlowProgramProperties props){
+		//ApproveTableInfo approveInfo = approveInfoQueryService.getApproveInfo(props);
+		Machine machine;
+		String machineCode = props.getMachineCode();
+		machine = machineService.getByCode(machineCode);
+
+		if(dispatch == null){
+			dispatch = new TaskDispatch();//TODO 鍚庨潰鍘绘帀
+		}
+
+		Map<String,String> dataMap = new HashMap<>();
+
+		dataMap.put("bh","涓嶆槑纭�");
+
+		dataMap.put("drawingNo",props.getDrawingNo());
+		dataMap.put("processNo",props.getProcessNo());
+		dataMap.put("craftEdition",props.getCraftEdition());
+		dataMap.put("processEdition",props.getProcessEdition());
+		dataMap.put("machineMode",machine.getName());
+
+		String DATE_PATTERN = "yyyy-M-d";
+
+		String dispatchDateStr = " ";
+
+		String ctlSystem = "";
+		R<String> ctmR = dictBizClient.getValue(DictBizConstants.CONTROL_SYSTEM,machine.getControlSystem());
+		if(ctmR.isSuccess()){
+			ctlSystem = ctmR.getData();
+		}
+		dataMap.put("deviation",dispatch.getDeviation()==null?"":dispatch.getDeviation());
+		dataMap.put("controlSystem",ctlSystem);
+		dataMap.put("czz","鎿嶄綔鑰�");
+		dataMap.put("jyy","妫�楠屽憳");
+
+
+		dataMap.put("programNo",dispatch.getProgramNo());
+		dataMap.put("fuhey",WordReplaceUtil.CHECKED);
+		dataMap.put("fuhen",WordReplaceUtil.UNCHECKED);
+		dataMap.put("jly",WordReplaceUtil.CHECKED);
+		dataMap.put("jln",WordReplaceUtil.UNCHECKED);
+
+		String bianzhiDateStr = "";//DateUtil.format(dispatch.getCreateTime(), DATE_PATTERN);
+
+
+		dataMap.put("bianzhi","缂栫▼鍛橈紵/"+bianzhiDateStr);
+		dataMap.put("jiaodui","宸ヨ壓鏍″锛�/鏃堕棿涓嶇‘瀹�");
+		dataMap.put("shenhe","楂樺笀锛�/鏃堕棿涓嶇‘瀹�");
+
+		dataMap.put("sendPath",machine.getProgSendDir()!=null?machine.getProgSendDir():"");
+
+		return dataMap;
+	}
+
+	/**
+	 * 宸插畬缁撶殑娴佺▼鍒嗛〉鍒楄〃
+	 * @param page 鍒嗛〉淇℃伅
+	 * @param createTimeBegin
+	 * @param createTimeEnd
+	 * @param keyword 鍏抽敭瀛�
+	 * @return
+	 */
+	public IPage<FlowVO> confirmTablePage(IPage<FlowVO> page, String drawingNo, String keyword,LocalDateTime createTimeBegin, LocalDateTime createTimeEnd) {
+		//鍥哄寲閲岃矾鏉戝畼
+		HistoricProcessInstanceQuery query = this.historyService.createHistoricProcessInstanceQuery().finished().processDefinitionKey(FlowContants.CURE_PROCESS_KEY).includeProcessVariables();
+			//.finished() // 鍙煡璇㈠凡瀹屾垚鐨勬祦绋�.unfinished() // 鏌ヨ鏈畬鎴愮殑娴佺▼
+		query.variableNotExists(FlowContants.EXCEPTION);//闈炲紓甯告祦绋�
+		if(createTimeBegin!=null) {
+			query.startedAfter(DateUtil.toDate(createTimeBegin));
+		}
+		if(createTimeEnd!=null) {
+			query.startedBefore(DateUtil.toDate(createTimeEnd));
+		}
+		if(Func.isNotEmpty(drawingNo)) {
+			String likeVal = "%" + drawingNo + "%";
+			query.variableValueLike(FlowContants.DRAWING_NO,likeVal);
+		}
+
+
+		query.orderByProcessInstanceEndTime().desc(); // 鎸夌粨鏉熸椂闂撮檷搴忔帓鍒�
+		page.setTotal(query.count());
+
+		long firstResult = (page.getCurrent()-1) * page.getSize();
+		List<HistoricProcessInstance> processes = query
+			.listPage((int)firstResult, (int)page.getSize());
+
+		List<FlowVO> records = new LinkedList<>();
+
+		for(HistoricProcessInstance processInstance : processes) {
+			FlowVO vo = new FlowVO();
+			vo.setProcessDefinitionKey(processInstance.getProcessDefinitionKey());
+			vo.setProcessInstanceId(processInstance.getId());
+			vo.setProcessDefinitionName(processInstance.getProcessDefinitionName());
+			vo.setVariables(processInstance.getProcessVariables());
+
+			vo.setProcessCreateTime(processInstance.getStartTime());
+			vo.setHistoryTaskEndTime(processInstance.getEndTime());
+
+
+			vo.setFile(getFileString(processInstance.getId()));
+			records.add(vo);
+		}
+
+		page.setRecords(records);
+
+		return page;
+	}
+	/**
+	鑾峰彇鍒楄〃涓殑鏂囦欢鍚�
+	 */
+	String getFileString(String processInstanceId){
+		String result = "";
+		List<FlowProgramFile> fileList = flowProgramFileService.lambdaQuery().eq(FlowProgramFile::getProcessInstanceId, processInstanceId).list();
+
+		result = String.join(",",fileList.stream().map(FlowProgramFile::getName).toList());
+
+		return result;
+	}
+
+}
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/statreport/utils/WordReplaceUtil.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/statreport/utils/WordReplaceUtil.java
new file mode 100644
index 0000000..3711446
--- /dev/null
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/statreport/utils/WordReplaceUtil.java
@@ -0,0 +1,113 @@
+package org.springblade.mdm.statreport.utils;
+
+import org.apache.poi.xwpf.usermodel.*;
+import java.io.*;
+import java.util.List;
+import java.util.Map;
+
+public class WordReplaceUtil {
+	public static final String CHECKED = "鈽�";
+	public static final String UNCHECKED = "鈻�";
+
+
+	public static void convert(Map<String, String> data,InputStream inputStream,OutputStream outputSteam ) {
+		try {
+			// 璇诲彇 Word 妯℃澘鏂囦欢
+			//FileInputStream fis = new FileInputStream("d:/spd.docx");
+			XWPFDocument document = new XWPFDocument(inputStream);
+
+			// 鏇挎崲鏂囨。涓殑鍗犱綅绗�
+			replacePlaceholders(document, data);
+
+			// 淇濆瓨涓烘柊鐨� Word 鏂囨。
+			//FileOutputStream fos = new FileOutputStream("d:/poioutput.docx");
+			document.write(outputSteam);
+
+			//System.out.println("鏂扮殑 Word 鏂囨。鐢熸垚鎴愬姛锛�");
+		} catch (IOException e) {
+			e.printStackTrace();
+			//System.out.println("鐢熸垚鏂扮殑 Word 鏂囨。澶辫触锛�" + e.getMessage());
+		}
+	}
+
+	private static void replacePlaceholders(XWPFDocument document, Map<String, String> data) {
+		// 閬嶅巻鏂囨。涓殑姣忎釜娈佃惤
+		document.getTables().forEach(table -> {
+			List<XWPFTableRow> rows = table.getRows();
+			//閬嶅巻琛ㄦ牸,骞舵浛鎹㈡ā鏉�
+			replaceTableRow(rows, data);
+
+			table.getBody().getParagraphs().forEach(paragraph -> {
+				replaceTextInPhoto(paragraph,data);
+			});
+		});
+		for (XWPFParagraph paragraph : document.getParagraphs()) {
+			// 閬嶅巻娈佃惤涓殑姣忎釜鏂囨湰杩愯瀵硅薄
+			for (XWPFRun run : paragraph.getRuns()) {
+				String text = run.getText(0);
+				if (text != null) {
+					// 閬嶅巻鏁版嵁鏄犲皠锛屾浛鎹㈠崰浣嶇
+					for (Map.Entry<String, String> entry : data.entrySet()) {
+						String placeholder = entry.getKey();
+						String replacement = entry.getValue();
+						if (text.contains(placeholder)) {
+							text = text.replace(placeholder, replacement);
+							run.setText(text, 0);
+						}
+					}
+				}
+			}
+		}
+	}
+
+	static void replaceTextInPhoto(XWPFParagraph paragraph,Map<String,String> data) {
+		for (XWPFRun run : paragraph.getRuns()) {
+			String text = run.getText(0);
+			if (text != null) {
+				// 閬嶅巻鏁版嵁鏄犲皠锛屾浛鎹㈠崰浣嶇
+				for (Map.Entry<String, String> entry : data.entrySet()) {
+					String placeholder = entry.getKey();
+					String replacement = entry.getValue();
+					if(replacement!=null) {
+						if (text.contains(placeholder)) {
+							text = text.replace(placeholder, replacement);
+							run.setText(text, 0);
+						}
+					}
+				}
+			}
+		}
+	}
+
+	public static void replaceTableRow(List<XWPFTableRow> rows , Map<String, String> data){
+		for (XWPFTableRow row : rows) {
+			//寰楀埌琛ㄦ牸姣忎竴琛岀殑鎵�鏈夎〃鏍�
+			List<XWPFTableCell> cells = row.getTableCells();
+			for (XWPFTableCell cell : cells) {
+				//鍒ゆ柇鍗曞厓鏍兼槸鍚﹂渶瑕佹浛鎹�
+
+					List<XWPFParagraph> paragraphs = cell.getParagraphs();
+					for (XWPFParagraph paragraph : paragraphs) {
+						List<XWPFRun> runs = paragraph.getRuns();
+						for (XWPFRun run : runs) {
+							String text = run.getText(0);
+							if (text != null) {
+								// 閬嶅巻鏁版嵁鏄犲皠锛屾浛鎹㈠崰浣嶇
+								for (Map.Entry<String, String> entry : data.entrySet()) {
+									String placeholder = entry.getKey();
+									String replacement = entry.getValue();
+									if(replacement!=null) {
+										if (text.contains(placeholder)) {
+											text = text.replace(placeholder, replacement);
+											run.setText(text, 0);
+										}
+									}
+								}
+							}
+						}
+					}
+
+			}
+		}
+	}
+}
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/statreport/utils/XmlToDocxWithPOI.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/statreport/utils/XmlToDocxWithPOI.java
new file mode 100644
index 0000000..bb76dee
--- /dev/null
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/statreport/utils/XmlToDocxWithPOI.java
@@ -0,0 +1,25 @@
+package org.springblade.mdm.statreport.utils;
+import org.apache.commons.io.FileUtils;
+import org.docx4j.openpackaging.contenttype.ContentType;
+import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
+import org.docx4j.openpackaging.parts.WordprocessingML.AltChunkType;
+import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
+import org.docx4j.openpackaging.parts.WordprocessingML.AlternativeFormatInputPart;
+import org.docx4j.openpackaging.parts.PartName;
+import org.docx4j.wml.ObjectFactory;
+
+import java.io.File;
+import java.io.FileInputStream;
+
+public class XmlToDocxWithPOI {
+	public static void convertXmlToDocx(String xmlFilePath, String outputFilePath) throws Exception {
+
+// 鍒涘缓 Word 鏂囨。瀵硅薄
+		WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage();
+		MainDocumentPart mainDocumentPart = wordMLPackage.getMainDocumentPart();
+
+		mainDocumentPart.addAltChunk(AltChunkType.Xml,new FileInputStream(xmlFilePath));
+
+		wordMLPackage.save(new File(outputFilePath));
+	}
+}
diff --git a/blade-service/blade-mdm/src/test/java/org/springblade/mdm/flow/service/ApproveTableServiceTest.java b/blade-service/blade-mdm/src/test/java/org/springblade/mdm/flow/service/ApproveTableServiceTest.java
deleted file mode 100644
index 8c1a423..0000000
--- a/blade-service/blade-mdm/src/test/java/org/springblade/mdm/flow/service/ApproveTableServiceTest.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package org.springblade.mdm.flow.service;
-
-import com.itextpdf.text.Document;
-import com.itextpdf.text.DocumentException;
-import com.itextpdf.text.PageSize;
-import com.itextpdf.text.pdf.BaseFont;
-import com.itextpdf.text.pdf.PdfWriter;
-import org.junit.jupiter.api.Test;
-import org.springblade.mdm.basesetting.machine.entity.Machine;
-import org.springblade.mdm.flow.vo.ApproveTableInfo;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.Calendar;
-import java.util.Date;
-
-public class ApproveTableServiceTest {
-	@Test
-	public void test(){
-		ApproveTableService s = new ApproveTableService();
-		/*
-		try {
-
-
-			Document document = new Document(PageSize.B5.rotate());
-
-			String filename = "t"+System.currentTimeMillis()+".pdf";
-			File pdf = new File(filename);
-			if(pdf.exists()){
-				pdf.delete();
-			}
-			PdfWriter.getInstance(document,new FileOutputStream(pdf));
-
-			document.open();
-
-			FlowProgramProperties props = new FlowProgramProperties();
-			props.setDrawingNo("CP3-1");
-			props.setProcessNo("A");
-			props.setProcessEdition("93");
-			props.setCraftEdition("宸ヨ壓鐗堟");
-			props.setProductModel("CP3");
-			//缂栧埗
-
-			Machine machine = new Machine();
-			machine.setName("1075");
-			machine.setProgSendDir("d:\\mdm\\send");
-
-			ApproveTableInfo appInfo = new ApproveTableInfo();
-			appInfo.setTeamLeaderName("缁勯暱1");
-			appInfo.setProgrammerName("缂栧埗1");
-			appInfo.setCheckerName("鏍″1");
-			appInfo.setSeniorName("瀹℃牳1");
-
-
-			Calendar startCal = Calendar.getInstance();
-			startCal.add(Calendar.DAY_OF_MONTH, -5);
-			appInfo.setProgrammingDate(startCal.getTime());
-
-			startCal.add(Calendar.DAY_OF_MONTH, 2);
-			appInfo.setCheckDate(startCal.getTime());
-
-
-			startCal.add(Calendar.DAY_OF_MONTH, 2);
-			appInfo.setApproveDate(startCal.getTime());
-
-
-			document.close();
-		} catch (Exception e) {
-		}
-
-		 */
-	}
-}
diff --git a/blade-service/blade-mdm/src/test/java/org/springblade/mdm/statreport/utils/XmlToDocxWithPOITest.java b/blade-service/blade-mdm/src/test/java/org/springblade/mdm/statreport/utils/XmlToDocxWithPOITest.java
new file mode 100644
index 0000000..2893b81
--- /dev/null
+++ b/blade-service/blade-mdm/src/test/java/org/springblade/mdm/statreport/utils/XmlToDocxWithPOITest.java
@@ -0,0 +1,142 @@
+package org.springblade.mdm.statreport.utils;
+
+import org.apache.poi.xwpf.usermodel.*;
+import org.apache.xmlbeans.XmlException;
+import org.docx4j.Docx4J;
+import org.docx4j.TraversalUtil;
+import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
+import org.docx4j.openpackaging.exceptions.Docx4JException;
+import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
+import org.docx4j.wml.ContentAccessor;
+import org.docx4j.wml.P;
+import org.docx4j.wml.R;
+import org.docx4j.wml.Text;
+import org.junit.jupiter.api.Test;
+import javax.xml.bind.JAXBElement;
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.docx4j.XmlUtils;
+import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody;
+import org.openxmlformats.schemas.wordprocessingml.x2006.main.DocumentDocument;
+
+public class XmlToDocxWithPOITest {
+	private String checked = "鈽�";
+	private String unchecked = "鈻�";
+	//@Test
+	public void test() throws Exception {
+
+		convert();
+	}
+
+	public void convert() {
+		try {
+			// 璇诲彇 Word 妯℃澘鏂囦欢
+			FileInputStream fis = new FileInputStream("d:/spd.docx");
+			XWPFDocument document = new XWPFDocument(fis);
+
+			// 鍑嗗瑕佹浛鎹㈢殑鏁版嵁
+			Map<String, String> data = new HashMap<>();
+			data.put("processNo","bh01");
+			data.put("bz",checked);
+			data.put("jd",unchecked);
+			data.put("fzy",checked);
+			data.put("fzn",unchecked);
+
+			// 鏇挎崲鏂囨。涓殑鍗犱綅绗�
+			replacePlaceholders(document, data);
+
+			// 淇濆瓨涓烘柊鐨� Word 鏂囨。
+			FileOutputStream fos = new FileOutputStream("d:/poioutput.docx");
+			document.write(fos);
+			fos.close();
+			fis.close();
+
+			System.out.println("鏂扮殑 Word 鏂囨。鐢熸垚鎴愬姛锛�");
+		} catch (IOException e) {
+			e.printStackTrace();
+			System.out.println("鐢熸垚鏂扮殑 Word 鏂囨。澶辫触锛�" + e.getMessage());
+		}
+	}
+
+	private void replacePlaceholders(XWPFDocument document, Map<String, String> data) {
+		// 閬嶅巻鏂囨。涓殑姣忎釜娈佃惤
+		document.getTables().forEach(table -> {
+			List<XWPFTableRow> rows = table.getRows();
+			//閬嶅巻琛ㄦ牸,骞舵浛鎹㈡ā鏉�
+			eachTable(rows, data);
+
+			table.getBody().getParagraphs().forEach(paragraph -> {
+				replaceTextInPhoto(paragraph,data);
+			});
+		});
+		for (XWPFParagraph paragraph : document.getParagraphs()) {
+			// 閬嶅巻娈佃惤涓殑姣忎釜鏂囨湰杩愯瀵硅薄
+			for (XWPFRun run : paragraph.getRuns()) {
+				String text = run.getText(0);
+				if (text != null) {
+					// 閬嶅巻鏁版嵁鏄犲皠锛屾浛鎹㈠崰浣嶇
+					for (Map.Entry<String, String> entry : data.entrySet()) {
+						String placeholder = entry.getKey();
+						String replacement = entry.getValue();
+						if (text.contains(placeholder)) {
+							text = text.replace(placeholder, replacement);
+							run.setText(text, 0);
+						}
+					}
+				}
+			}
+		}
+	}
+
+	void replaceTextInPhoto(XWPFParagraph paragraph,Map<String,String> data) {
+		for (XWPFRun run : paragraph.getRuns()) {
+			String text = run.getText(0);
+			if (text != null) {
+				// 閬嶅巻鏁版嵁鏄犲皠锛屾浛鎹㈠崰浣嶇
+				for (Map.Entry<String, String> entry : data.entrySet()) {
+					String placeholder = entry.getKey();
+					String replacement = entry.getValue();
+					if (text.contains(placeholder)) {
+						text = text.replace(placeholder, replacement);
+						run.setText(text, 0);
+					}
+				}
+			}
+		}
+	}
+
+	public static void eachTable(List<XWPFTableRow> rows , Map<String, String> data){
+		for (XWPFTableRow row : rows) {
+			//寰楀埌琛ㄦ牸姣忎竴琛岀殑鎵�鏈夎〃鏍�
+			List<XWPFTableCell> cells = row.getTableCells();
+			for (XWPFTableCell cell : cells) {
+				//鍒ゆ柇鍗曞厓鏍兼槸鍚﹂渶瑕佹浛鎹�
+
+					List<XWPFParagraph> paragraphs = cell.getParagraphs();
+					for (XWPFParagraph paragraph : paragraphs) {
+						List<XWPFRun> runs = paragraph.getRuns();
+						for (XWPFRun run : runs) {
+							String text = run.getText(0);
+							if (text != null) {
+								// 閬嶅巻鏁版嵁鏄犲皠锛屾浛鎹㈠崰浣嶇
+								for (Map.Entry<String, String> entry : data.entrySet()) {
+									String placeholder = entry.getKey();
+									String replacement = entry.getValue();
+									if (text.contains(placeholder)) {
+										text = text.replace(placeholder, replacement);
+										run.setText(text, 0);
+									}
+								}
+							}
+						}
+					}
+
+			}
+		}
+	}
+}
diff --git a/doc/mdm/qrb.docx b/doc/mdm/qrb.docx
index 8470040..aa5f7ba 100644
--- a/doc/mdm/qrb.docx
+++ b/doc/mdm/qrb.docx
Binary files differ
diff --git a/doc/mdm/spd.docx b/doc/mdm/spd.docx
new file mode 100644
index 0000000..506e62c
--- /dev/null
+++ b/doc/mdm/spd.docx
Binary files differ

--
Gitblit v1.9.3