From 1e2b04fabbbc4b1ae37d7951068d7ab235f5b5f9 Mon Sep 17 00:00:00 2001
From: yangys <y_ys79@sina.com>
Date: 星期三, 17 九月 2025 15:29:38 +0800
Subject: [PATCH] 现场编制功能适配

---
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/commons/controller/RemindController.java                   |    5 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/controller/NcNodeHisController.java                |  101 ++++
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/controller/ProgramOnMachineImportController.java   |   62 ++
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/programannotation/AbstractProcessor.java   |   19 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/controller/MyFlowController.java                      |    7 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/dispatch/FinishDataHandler.java              |    4 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/controller/NcNodeController.java                   |   41 +
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/dispatch/NormalFinishDataHandler.java        |  101 +++-
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/FlowBusinessService.java                      |   48 +
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/ProgramOnMachineExportService.java            |  105 +++++
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/unlock/UnlockFinishListener.java             |   24 +
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/FlowProgramProperties.java                    |    5 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/FlowCommonService.java                        |    2 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/programannotation/DefaultProcessor.java    |   16 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/vo/TodoQueryVO.java                                   |   25 +
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/machinefile/service/ReceiveFileCheckService.java           |   97 ++++
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/thirdpart/controller/MesController.java                    |    1 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/dispatch/DispatchFinishListener.java         |   10 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/ProgramOnMachineService.java               |   57 ++
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/constants/FlowVariableContants.java                   |    5 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/config/InitBean.java                                       |    9 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/execute/BatchDispatchService.java             |   35 +
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/mapper/NcNodeHisMapper.java                        |    4 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcProgramExportDNCService.java             |   15 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/task/MachineFileScanTask.java                              |    2 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/mapper/NcNodeMapper.java                           |    4 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/ListenerHelper.java                          |   39 +
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/cure/DeviationCureFinishDataHandler.java     |    3 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/entity/ProgramOnMachine.java                       |   47 ++
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/LockFlowService.java                          |    6 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/vo/ProgramOnMachineExcel.java                         |   32 +
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/controller/DispatchController.java                    |   20 
 /dev/null                                                                                                            |   30 -
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/cure/NormalCureFinishDataHandler.java        |   13 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/mapper/NcNodeMapper.xml                            |    8 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcNodeHisService.java                      |   22 +
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/vo/ProgramOnMachineQueryVO.java                       |   29 +
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcNodeService.java                         |   35 +
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/ReplaceFlowService.java                       |    1 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/task/ReceiveDirCheckTask.java                              |   57 --
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/controller/ProgramOnMachineExportController.java      |   75 +++
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/execute/TryFlowCompleteService.java           |    6 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/machinefile/service/MachineFileScanService.java            |    2 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/mapper/NcNodeHisMapper.xml                         |    6 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/mapper/ProgramOnMachineMapper.java                 |    9 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/mapper/ProgramOnMachineMapper.xml                  |    6 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/programannotation/AnnotationProcessor.java |    1 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/FlowProgramFileService.java                   |    4 
 48 files changed, 1,056 insertions(+), 199 deletions(-)

diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/commons/controller/RemindController.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/commons/controller/RemindController.java
index 7368ac1..725ca85 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/commons/controller/RemindController.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/commons/controller/RemindController.java
@@ -21,6 +21,7 @@
 import org.springblade.mdm.flow.service.FlowCommonService;
 import org.springblade.mdm.flow.service.FlowTransferService;
 import org.springblade.mdm.flow.vo.FlowVO;
+import org.springblade.mdm.flow.vo.TodoQueryVO;
 import org.springblade.mdm.gkw.programnode.vo.ProgramNodeVO;
 import org.springblade.mdm.program.service.NcProgramApprovedService;
 import org.springblade.mdm.program.vo.NcProgramExportDncPageVO;
@@ -65,10 +66,10 @@
 		return R.data(result);
 	}
 	long queryTodoCount(){
-		Query query = new Query();
+		TodoQueryVO query = new TodoQueryVO();
 		query.setCurrent(1);
 		query.setSize(1);
-		IPage<FlowVO> pages = businessService.selectTodoPage(Condition.getPage(query), null,null,null);
+		IPage<FlowVO> pages = businessService.selectTodoPage(Condition.getPage(query), query);
 		return pages.getTotal();
 	}
 	/**
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/config/InitBean.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/config/InitBean.java
index cdc92c2..da959cb 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/config/InitBean.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/config/InitBean.java
@@ -14,6 +14,8 @@
 import org.springblade.mdm.machinefile.service.MachineFileService;
 import org.springblade.mdm.program.service.ProgramAnnotationService;
 import org.springblade.system.feign.ISysClient;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.EnableAsync;
 import org.springframework.stereotype.Component;
 
 import java.nio.file.Path;
@@ -24,6 +26,7 @@
 @Slf4j
 @AllArgsConstructor
 @Component
+@EnableAsync
 public class InitBean {
 	private final DirectorLockService directorLockService;
 	private final DynamicDirectoryWatcher directoryWatcher;
@@ -32,14 +35,14 @@
 	private final ParamService paramService;
 	private final ProgramAnnotationService annotationService;
 	private final MachineFileScanService machineFileScanService;
-	private final ISysClient sysClient;
 	private final TaskDispatchService taskDispatchService;
 	@PostConstruct
 	public void init() {
 		log.info("搴旂敤鍚姩鏃舵墽琛屽垵濮嬪寲鎿嶄綔 @PostConstruct");
 		String networkType = paramService.networkType();
 		if(!ParamService.NETWORK_TYPE_SHEMI.equals(networkType)) {
-			machineFileScanService.scanMachineFile();//鍚姩鎵ц涓�娆℃壂鎻�
+			machineFileScanService.scanMachineFile();
+
 			//宸ユ帶缃戞墠鍚姩鏂囦欢鐩戞帶
 			log.info("宸ユ帶缃戝惎鍔ㄦ枃浠剁洃鎺�");
 			initMachineDirMonitor();
@@ -66,8 +69,8 @@
 			addToWatchDirList(monitorInfoList,m);
 		});
 		for (WatchInfo info : monitorInfoList) {
-			Path dirPath = Paths.get(info.getPath());
 			try {
+				Path dirPath = Paths.get(info.getPath());
 				if(!dirPath.toFile().exists()) {
 					dirPath.toFile().mkdirs();
 				}
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/constants/FlowVariableContants.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/constants/FlowVariableContants.java
index e92c059..316d06f 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/constants/FlowVariableContants.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/constants/FlowVariableContants.java
@@ -137,4 +137,9 @@
 	 * 娴佺▼鍙橀噺涓殑寮傚父鏍囧織锛�="1"涓哄紓甯告祦绋�
 	 */
 	public static final String EXCEPTION = "exception";
+
+	/**
+	 * 鐜板満缂栧埗
+	 */
+	public static final String PROGRAM_ON_MACHINE ="programOnMachine";
 }
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/controller/DispatchController.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/controller/DispatchController.java
index 1309f3f..3fe8583 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/controller/DispatchController.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/controller/DispatchController.java
@@ -172,16 +172,18 @@
 		}catch(Exception e){
 			return R.fail(e.getMessage());
 		}
+	}
+
+	@Operation(summary = "缂栫▼鍛樼幇鍦虹紪鍒舵壒閲忓鐞�", description = "缂栫▼鍛樼幇鍦虹紪鍒舵壒閲忓鐞�")
+	@PostMapping("batch-program-on-machine")
+	public R<Void> batchProgramOnMachine(@RequestBody BatchDispatchVO batchDispatchVO) {
+		try {
+			dispatchService.batchProgramOnMachine(batchDispatchVO);
+			return R.success("娴佺▼鎻愪氦鎴愬姛");
+		}catch(Exception e){
+			return R.fail(e.getMessage());
+		}
 
 	}
-	/*
-	void addApproveRecord(String taskId,String comment,Map<String, Object> variables){
-		String operateResult = variables.get("approve")+"";
 
-		Task task = taskService.createTaskQuery()
-			.taskId(taskId)
-			.singleResult();
-		approveRecordService.saveApproveRecords(task,operateResult,comment);
-
-	}*/
 }
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/controller/MyFlowController.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/controller/MyFlowController.java
index 2b18b4e..8b9b7e8 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/controller/MyFlowController.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/controller/MyFlowController.java
@@ -20,6 +20,7 @@
 import org.springblade.mdm.flow.service.FlowTransferService;
 import org.springblade.mdm.flow.vo.DoneQueryVO;
 import org.springblade.mdm.flow.vo.FlowVO;
+import org.springblade.mdm.flow.vo.TodoQueryVO;
 import org.springblade.mdm.gkw.programnode.vo.ProgramNodeVO;
 import org.springblade.system.feign.IUserSearchClient;
 import org.springblade.system.pojo.entity.User;
@@ -58,10 +59,8 @@
 	@GetMapping("todo-list")
 	@ApiOperationSupport(order = 3)
 	@Operation(summary = "寰呭姙浠诲姟", description = "浼犲叆娴佺▼淇℃伅")
-	public R<IPage<FlowVO>> todoList(@Parameter(description = "鍏抽敭瀛�") String keyword, @Parameter(description = "鍒涘缓鏃堕棿寮�濮�") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime createTimeBegin, @Parameter(description = "鍒涘缓鏃堕棿鎴")  @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime createTimeEnd, Query query) {
-		IPage<FlowVO> pages = businessService.selectTodoPage(Condition.getPage(query), createTimeBegin,createTimeEnd,keyword);
-
-			//pages = businessService.selectFinishedPage(Condition.getPage(query), "",createTimeBegin, createTimeEnd, keyword);
+	public R<IPage<FlowVO>> todoList(TodoQueryVO queryVO) {
+		IPage<FlowVO> pages = businessService.selectTodoPage(Condition.getPage(queryVO),queryVO);
 
 		return R.data(pages);
 	}
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/controller/ProgramOnMachineExportController.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/controller/ProgramOnMachineExportController.java
new file mode 100644
index 0000000..ce45ae4
--- /dev/null
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/controller/ProgramOnMachineExportController.java
@@ -0,0 +1,75 @@
+package org.springblade.mdm.flow.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.tags.Tag;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.flowable.engine.HistoryService;
+import org.springblade.core.excel.util.ExcelUtil;
+import org.springblade.core.mp.support.Condition;
+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.flow.constants.FlowVariableContants;
+import org.springblade.mdm.flow.service.FlowCommonService;
+import org.springblade.mdm.flow.service.ProgramOnMachineExportService;
+import org.springblade.mdm.flow.service.TaskDispatchService;
+import org.springblade.mdm.flow.vo.FlowVO;
+import org.springblade.mdm.flow.vo.ProgramOnMachineExcel;
+import org.springblade.mdm.flow.vo.ProgramOnMachineQueryVO;
+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.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+@Slf4j
+@RestController
+@AllArgsConstructor
+@RequestMapping("/flowmgr/programonmachine")
+@Tag(name = "鐜板満缂栧埗瀵煎嚭", description = "鐜板満缂栧埗瀵煎嚭")
+public class ProgramOnMachineExportController {
+
+	private FlowCommonService flowCommonService;
+	private ProgramOnMachineExportService programOnMachineService;
+	private final TaskDispatchService taskDispatchService;
+	private final HistoryService historyService;
+	@GetMapping("/finished-page")
+	@ApiOperationSupport(order = 3)
+	@Operation(summary = "宸插鎵瑰垪琛�", description = "宸插鎵瑰垪琛�")
+	public R<IPage<FlowVO>> finishedPage(ProgramOnMachineQueryVO queryVO) {
+		IPage<FlowVO> pages = programOnMachineService.finishedPage(Condition.getPage(queryVO), queryVO);
+		return R.data(pages);
+	}
+
+
+	@PostMapping("/export")
+	@Operation(summary = "瀵煎嚭鐜板満缂栧埗璁板綍", description = "瀵煎嚭鐜板満缂栧埗璁板綍")
+	public void export(ProgramOnMachineQueryVO queryVO,HttpServletResponse response) throws IOException {
+		queryVO.setCurrent(1);
+		queryVO.setSize(Integer.MAX_VALUE);
+		IPage<FlowVO> page = programOnMachineService.finishedPage(Condition.getPage(queryVO), queryVO);
+
+		List<ProgramOnMachineExcel> list = new ArrayList<>();
+
+		page.getRecords().forEach(record -> {
+			ProgramOnMachineExcel excel = new ProgramOnMachineExcel();
+			Map<String,Object> vars = record.getVariables();
+			excel.setDrawingNo(Func.toStr(vars.get(FlowVariableContants.DRAWING_NO)));
+			excel.setProcessNo(Func.toStr(vars.get(FlowVariableContants.PROCESS_NO)));
+			excel.setProcessEdition(Func.toStr(vars.get(FlowVariableContants.PROCESS_EDITION)));
+			excel.setMachineCode(Func.toStr(vars.get(FlowVariableContants.MACHINE_CODE)));
+			excel.setProcessInstanceId(record.getProcessInstanceId());
+			list.add(excel);
+		});
+		ExcelUtil.export(response, "鐜板満缂栧埗璁板綍" + DateUtil.time(), "鏈哄簥鏁版嵁琛�", list, ProgramOnMachineExcel.class);
+
+	}
+}
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/ListenerHelper.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/ListenerHelper.java
new file mode 100644
index 0000000..db2ea16
--- /dev/null
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/ListenerHelper.java
@@ -0,0 +1,39 @@
+package org.springblade.mdm.flow.excution;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springblade.mdm.flow.constants.FlowContants;
+import org.springblade.mdm.flow.service.FlowProgramProperties;
+import org.springblade.mdm.program.entity.NcNode;
+import org.springblade.mdm.program.entity.NcProgramApproved;
+import org.springblade.mdm.program.service.NcProgramApprovedService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@Component
+public class ListenerHelper {
+	@Autowired
+	private NcProgramApprovedService approvedService;
+
+	//澧炲姞涓�涓鍑哄伐鎺х綉鐨勮褰�
+	/**
+	 * 淇濆瓨瀹℃壒瀹屾垚鐨勮褰�
+	 * @param packageNode
+	 * @param props
+	 */
+	public void addApproveTable(NcNode packageNode, FlowProgramProperties props){
+		if(FlowContants.Y.equals(props.getProgramOnMachine())){
+			log.warn("鐜板満缂栧埗锛屼笉杩涘叆瀹℃壒璁板綍琛�");
+			return ;
+		}
+		NcProgramApproved approved = new NcProgramApproved();
+
+		approved.setProgramName(packageNode.getName());
+		approved.setNcNodeId(packageNode.getId());//绋嬪簭鍖呰妭鐐筰d
+		approved.setTitle(props.getTitle());
+		approved.setProgrammerId(props.getActProgrammerId());
+		approved.setProcessInstanceId(props.getProcessInstanceId());
+		approvedService.save(approved);
+
+	}
+}
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/cure/DeviationCureFinishDataHandler.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/cure/DeviationCureFinishDataHandler.java
index c568bef..6b5c328 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/cure/DeviationCureFinishDataHandler.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/cure/DeviationCureFinishDataHandler.java
@@ -37,8 +37,7 @@
 	public void handleData(FlowProgramProperties props) {
 		// 鎵ц涓氬姟閫昏緫
 		NcNode pkgNode = nodeService.lambdaQuery().eq(NcNode::getProcessInstanceId,  props.getProcessInstanceId()).one();
-
-		pkgNode.lock();
+		pkgNode.lock("鍋忕鍗曞洖浼犻攣瀹�");
 		pkgNode.setIsLastEdition(0);
 		nodeService.updateById(pkgNode);
 
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/cure/NormalCureFinishDataHandler.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/cure/NormalCureFinishDataHandler.java
index 295993f..f949f78 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/cure/NormalCureFinishDataHandler.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/cure/NormalCureFinishDataHandler.java
@@ -85,6 +85,19 @@
 		//List<NcNode> historyProgramPackageNodes = nodeService.getTryNodeHistory(pkgNode);
 		try {
 			moveNodeToCuredTree(pkgNode, flowProps);//, historyProgramPackageNodes
+
+			//鍥哄寲涓嶉攣瀹氾紝鍚庣画杩樺彲鑳戒娇鐢ㄨ鍥哄寲绋嬪簭
+			//nodeService.lockSameNameOtherMachineGroupProgramPackage(pkgNode);
+			/*
+			nodeService.lambdaUpdate().eq(NcNode::getDrawingNo,pkgNode.getDrawingNo())
+				.eq(NcNode::getProcessNo,pkgNode.getProcessNo())
+				.eq(NcNode::getName,pkgNode.getName())
+				.ne(NcNode::getMachineGroupCode,pkgNode.getMachineGroupCode())
+				.eq(NcNode::getIsCured,1)
+				.set(NcNode::getIsLocked,NcNode.LOCKED)
+				.set(NcNode::getRemark,"鍥炰紶鍥哄寲鍚屽悕绋嬪簭閿佸畾")
+				.update();
+			*/
 		}catch(Exception e) {
 			log.error("鍥哄寲娴佺▼瀹屾垚寮傚父",e);
 			throw new ServiceException("鏅�氬浐鍖栨墽琛屽紓甯�"+e.getMessage());
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/dispatch/DispatchFinishListener.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/dispatch/DispatchFinishListener.java
index 7754634..8a1d794 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/dispatch/DispatchFinishListener.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/dispatch/DispatchFinishListener.java
@@ -3,6 +3,7 @@
 import lombok.extern.slf4j.Slf4j;
 import org.flowable.engine.RuntimeService;
 import org.flowable.engine.delegate.DelegateExecution;
+import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.tool.utils.DateUtil;
 import org.springblade.mdm.flow.service.FlowCommonService;
 import org.springblade.mdm.flow.service.FlowProgramProperties;
@@ -40,9 +41,12 @@
 
 		FlowProgramProperties props = flowCommonService.getProgramProperties(instId);
 		FinishDataHandler dataHandler = dataHandlerHelper.getDataHandler(props);
-
-		dataHandler.handleData(props);
-
+		try {
+			dataHandler.handleData(props);
+		}catch(Exception e) {
+			log.error("澶勭悊閿欒",e);
+			throw new ServiceException("娲惧伐瀹屾垚澶勭悊寮傚父"+e.getMessage());
+		}
 		nodeHisService.mergeNodeToHisGeTime(time);
 		log.info("娴佺▼宸插畬鎴恑n DispatchFinishListener");
 	}
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/dispatch/FinishDataHandler.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/dispatch/FinishDataHandler.java
index 80b5f53..f38164b 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/dispatch/FinishDataHandler.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/dispatch/FinishDataHandler.java
@@ -3,6 +3,8 @@
 import org.flowable.engine.delegate.DelegateExecution;
 import org.springblade.mdm.flow.service.FlowProgramProperties;
 
+import java.io.IOException;
+
 /**
  * 鐣欏瓨缁欑粨鏉熷鐞嗙粨鏋�
  */
@@ -11,5 +13,5 @@
 	 * 澶勭悊浜嗘暟鎹�
 	 * @param props
 	 */
-	void handleData(FlowProgramProperties props);
+	void handleData(FlowProgramProperties props) throws IOException;
 }
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/dispatch/NormalFinishDataHandler.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/dispatch/NormalFinishDataHandler.java
index 890e623..64ac2f0 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/dispatch/NormalFinishDataHandler.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/dispatch/NormalFinishDataHandler.java
@@ -3,20 +3,32 @@
 import com.alibaba.excel.util.StringUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.io.IOUtils;
+import org.springblade.core.oss.OssTemplate;
+import org.springblade.core.oss.model.BladeFile;
+import org.springblade.mdm.basesetting.machine.entity.Machine;
+import org.springblade.mdm.basesetting.machine.service.MachineService;
 import org.springblade.mdm.flow.constants.FlowContants;
+import org.springblade.mdm.flow.entity.FlowProgramFile;
+import org.springblade.mdm.flow.excution.ListenerHelper;
 import org.springblade.mdm.flow.service.FlowProgramFileService;
 import org.springblade.mdm.flow.service.FlowProgramProperties;
 import org.springblade.mdm.gkw.programnode.vo.ProgramNameVO;
 import org.springblade.mdm.program.entity.NcNode;
-import org.springblade.mdm.program.entity.NcProgramApproved;
 import org.springblade.mdm.program.service.NcNodeAutoCreateService;
 import org.springblade.mdm.program.service.NcNodeService;
 import org.springblade.mdm.program.service.NcProgramApprovedService;
+import org.springblade.mdm.program.service.ProgramAnnotationService;
+import org.springblade.mdm.program.service.programannotation.*;
 import org.springblade.mdm.utils.ProgramFileNameParser;
+import org.springblade.system.pojo.entity.DictBiz;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
 import java.time.LocalDateTime;
 import java.util.List;
 
@@ -27,18 +39,27 @@
 @Component("normalDispatchFinishDataHandler")
 public class NormalFinishDataHandler implements FinishDataHandler{
 	@Autowired
-	private NcProgramApprovedService approvedService;
-	@Autowired
 	private FlowProgramFileService flowProgramFileService;
+	@Autowired
+	private MachineAnnotationConfig annotationConfig;
+	@Autowired
+	private MachineService machineService;
 	@Autowired
 	private NcNodeService ncNodeService;
 	@Autowired
 	private NcNodeAutoCreateService ncNodeAutoCreateService;
+	@Autowired
+	private ProgramAnnotationService programAnnotationService;
+	@Autowired
+	private ListenerHelper listenerHelper;
+	@Autowired
+	private OssTemplate ossTemplate;
+
 	/**
 	 * DispatchFinishListener涓皟鐢�
 	 * @param props 娴佺▼灞炴��
 	 */
-	public void handleData(FlowProgramProperties props) {
+	public void handleData(FlowProgramProperties props) throws IOException {
 		// 鎵ц涓氬姟閫昏緫
 		LocalDateTime now = LocalDateTime.now();
 		NcNode packageNode;
@@ -57,8 +78,12 @@
 
 				packageNode = ncNodeAutoCreateService.createNodeTreeWithProgram(props,newVersion);
 			}else{
-				//鍙敤锛屽崌鐗堬紙淇敼鍏跺伐搴忕増娆★級锛屽師鏉ョ殑鑺傜偣娓呴櫎
+				//String oriProcessEdition = packageNode.getProcessEdition();
+				//鍙敤锛岀┖鍗囩増锛堜慨鏀瑰叾宸ュ簭鐗堟锛夛紝鍘熸潵鐨勮妭鐐规竻闄�
 				moveToNewProcessEdition(packageNode,props);
+
+				//鏇存柊宸插浐鍖栫殑锛屽悓鍚嶃�佷笉鍚屾満搴婄粍鐨勭▼搴忎负閿佸畾鐘舵��
+				ncNodeService.lockSameNameOtherMachineGroupProgramPackage(packageNode);
 			}
 		}else{
 			//鏅�氳瘯鍒�
@@ -68,7 +93,7 @@
 			ncNodeService.updateById(packageNode);
 		}
 
-		addApproveTable(packageNode,props);
+		listenerHelper.addApproveTable(packageNode,props);
 
 		log.info("鏅�氭祦绋嬪凡瀹屾垚in DispatchFinishListener");
 	}
@@ -78,8 +103,9 @@
 	 * @param packageNode 绋嬪簭鍖呭悕鑺傜偣
 	 * @param props 娴佺▼灞炴��
 	 */
-	private void moveToNewProcessEdition(NcNode packageNode, FlowProgramProperties props) {
-		ncNodeService.deleteMachineNodeByParentId(packageNode.getParentId());
+	private void moveToNewProcessEdition(NcNode packageNode, FlowProgramProperties props) throws IOException {
+		//ncNodeService.deleteMachineGroupNodeByParentId();
+		ncNodeService.getBaseMapper().deleteById(packageNode.getParentId());//鍒犻櫎鏈哄簥缁勮妭鐐�
 
 		FlowProgramProperties tempProps = new FlowProgramProperties();
 		BeanUtils.copyProperties(props,tempProps);
@@ -87,6 +113,7 @@
 		NcNode machineGroupNode = ncNodeAutoCreateService.createNodeTreeToMachineGroup(tempProps);
 
 		//绉诲姩鍘嗗彶鑺傜偣鍒版柊鐨勭増娆¤妭鐐逛笅
+		/*
 		List<NcNode> packageHisNodes = ncNodeService.getTryNodeHistory(packageNode);//璇ュ寘鐨勫巻鍙茶妭鐐瑰垪琛�
 		for(NcNode hisPackageNode : packageHisNodes){
 			hisPackageNode.setParentId(machineGroupNode.getId());
@@ -100,27 +127,39 @@
 			ncNodeService.updateBatchById(oriProgramNodes);
 		}
 		ncNodeService.updateBatchById(packageHisNodes);
-
+		*/
 		//绉诲姩绋嬪簭鍖呭悕鑺傜偣
 		packageNode.setProcessEdition(tempProps.getProcessEdition());
 		packageNode.setParentId(machineGroupNode.getId());
-		packageNode.setParentIds(machineGroupNode.getParentIds()+","+machineGroupNode.getId());
+		packageNode.setParentIds(machineGroupNode.subNodeParentIds());
 		packageNode.setName(tempProps.getDrawingNo()+"-"+tempProps.getProcessNo()+"-"+tempProps.getProcessEdition());
-		this.ncNodeService.updateById(packageNode);
 
+		this.ncNodeService.updateById(packageNode);
+		Machine machine = machineService.getByCode(packageNode.getMachineCode());
 		//绉诲姩绋嬪簭鑺傜偣
+		//List<DictBiz> annoDicts = programAnnotationService.getAnnotionDictList();
 		List<NcNode> programNodes = ncNodeService.getProgramFilesByPackageId(packageNode.getId());
 		for(NcNode programNode : programNodes){
+			FlowProgramFile progFile = this.flowProgramFileService.getById(programNode.getFlowProgramFileId());
 
-			programNode.setName(buildNewFilename(programNode.getName(),tempProps.getProcessEdition()));//鍚嶇О淇敼锛屽伐搴忕増娆¢儴鍒�
-			programNode.setParentIds(packageNode.getParentIds()+","+packageNode.getId());
+			programNode.setParentIds(packageNode.subNodeParentIds());
 			programNode.setProcessEdition(tempProps.getProcessEdition());//淇敼宸ュ簭鐗堟
 			programNode.setVersionNumber(packageNode.getVersionNumber());
+			if(progFile.isProgram()) {
+				programNode.setName(buildNewFilename(programNode.getName(), tempProps.getProcessEdition()));//鍚嶇О淇敼锛屽伐搴忕増娆¢儴鍒�
+				setNewProgramNameAnnotation(programNode.getName(), progFile, machine.getControlSystem());
+			}
 		}
 		ncNodeService.updateBatchById(programNodes);
 
 	}
 
+	/**
+	 * 鏋勫缓鏂扮殑绋嬪簭甯傚悕
+	 * @param filename 绋嬪簭鍖呭悕
+	 * @param newProcessEdition 鏂扮殑宸ュ簭鐗堟
+	 * @return 鏂扮殑绋嬪簭鏂囦欢鍚�
+	 */
 	String buildNewFilename(String filename,String newProcessEdition){
 		ProgramNameVO pnameVO = ProgramFileNameParser.parseProgramName(filename);
 		String ext = FilenameUtils.getExtension(filename);
@@ -132,20 +171,34 @@
 	}
 
 	/**
-	 * 淇濆瓨瀹℃壒瀹屾垚鐨勮褰�
-	 * @param packageNode
-	 * @param props
+	 * 璁剧疆鍥哄寲娉ㄩ噴,瀹炵幇鏂瑰紡锛岃幏鍙栨枃浠跺瓧鑺備笅锛屼慨鏀瑰悗鏇挎崲鏂囦欢
+	 * @param flowProgramFile oss 鏂囦欢
+	 *
 	 */
-	void addApproveTable(NcNode packageNode,FlowProgramProperties props){
-		NcProgramApproved approved = new NcProgramApproved();
+	void setNewProgramNameAnnotation(String filename,FlowProgramFile flowProgramFile, String controlSystem) throws IOException {
 
-		approved.setProgramName(packageNode.getName());
-		approved.setNcNodeId(packageNode.getId());//绋嬪簭鍖呰妭鐐筰d
-		approved.setTitle(props.getTitle());
-		approved.setProgrammerId(props.getActProgrammerId());
-		approved.setProcessInstanceId(props.getProcessInstanceId());
-		approvedService.save(approved);
+		try(InputStream ins = ossTemplate.statFileStream(flowProgramFile.getOssName());){
+			ByteArrayInputStream byteInputStream =  new ByteArrayInputStream(IOUtils.toByteArray(ins));
 
+			//List<DictBiz> annoDictList = programAnnotationService.getAnnotionDictList();
+
+			AnnotationProcessor annoProcessor = ProcessorHelper.getProcessor(controlSystem,this.annotationConfig);
+			/*
+			AnnotationProperties annoProps = annotationConfig.getConfigMap().get(controlSystem);
+			if(annoProps == null){
+				annoProps = AnnotationProperties.getDefault();
+			}*/
+			InputStream finishedStream = annoProcessor.setFilenameAnnotation(filename,byteInputStream);
+			//InputStream finishedStream = AnnotationUtil.setAnnotationAndGetInputStream(byteInputStream, "GH", annoProps.getStatusLineIndex(), controlSystem, annoDictList);
+			try(finishedStream) {
+				finishedStream.reset();
+				BladeFile bfile = ossTemplate.putFile(flowProgramFile.getName(), finishedStream);
+				//鏇挎崲鍘熸湁鐨勬枃浠跺湴鍧�
+				flowProgramFile.setOssName(bfile.getName());
+				flowProgramFile.setName(filename);
+				flowProgramFileService.updateById(flowProgramFile);
+			}
+		}
 	}
 
 }
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/unlock/UnlockFinishListener.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/unlock/UnlockFinishListener.java
index 8752c04..a6343e6 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/unlock/UnlockFinishListener.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/unlock/UnlockFinishListener.java
@@ -5,7 +5,12 @@
 import org.flowable.engine.delegate.DelegateExecution;
 import org.springblade.core.tool.utils.DateUtil;
 import org.springblade.mdm.flow.constants.FlowContants;
+import org.springblade.mdm.flow.excution.ListenerHelper;
+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.program.entity.NcNode;
+import org.springblade.mdm.program.entity.NcProgramApproved;
 import org.springblade.mdm.program.service.NcNodeHisService;
 import org.springblade.mdm.program.service.NcNodeService;
 import org.springblade.mdm.program.service.NcProgramApprovedService;
@@ -26,6 +31,12 @@
 	private NcNodeHisService nodeHisService;
 	@Autowired
 	private NcNodeService ncNodeService;
+	@Autowired
+	private FlowCommonService flowCommonService;
+	@Autowired
+	private NcProgramApprovedService approvedService;
+	@Autowired
+	private ListenerHelper listenerHelper;
 	/**
 	 * 鍦ㄦ祦绋嬬粨鏉熸椂鑷姩璋冪敤,锛堥厤缃湪瀹℃壒缁撴潫浜嬩欢鐨別xecutelistener涓簡锛�
 	 * @param execution 鎵ц瀵硅薄
@@ -33,11 +44,20 @@
 	public void handle(DelegateExecution execution) {
 		// 鎵ц涓氬姟閫昏緫
 		Date time = DateUtil.now();
-		Long nodeId = runtimeService.getVariable(execution.getId(),FlowContants.NODE_ID,Long.class);
 
-		this.ncNodeService.unlock(nodeId);
+		FlowProgramProperties props = flowCommonService.getProgramProperties(execution.getProcessInstanceId());
+		//Long nodeId = runtimeService.getVariable(execution.getId(),FlowContants.NODE_ID,Long.class);
+
+		NcNode packageNode = this.ncNodeService.getById(props.getNodeId());
+		if(packageNode.isDeviationProgram()) {
+			listenerHelper.addApproveTable(packageNode,props);
+		}
+		this.ncNodeService.unlock(props.getNodeId());
+
 
 		nodeHisService.mergeNodeToHisGeTime(time);
 	}
 
+
+
 }
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/FlowBusinessService.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/FlowBusinessService.java
index f6e0bf3..eebb8de 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/FlowBusinessService.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/FlowBusinessService.java
@@ -18,12 +18,16 @@
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.*;
 
+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.flow.constants.FlowContants;
 import org.springblade.mdm.flow.constants.FlowVariableContants;
 import org.springblade.mdm.flow.entity.FlowProgramFile;
 import org.springblade.mdm.flow.entity.MdmFlowProcess;
 import org.springblade.mdm.flow.util.MdmFlowCache;
 import org.springblade.mdm.flow.vo.FlowVO;
+import org.springblade.mdm.flow.vo.TodoQueryVO;
 import org.springblade.system.feign.IUserClient;
 import org.springblade.system.pojo.entity.User;
 import org.springframework.stereotype.Service;
@@ -45,6 +49,8 @@
 	private final HistoryService historyService;
 	private final IUserClient userClient;
 	private final FlowProgramFileService flowProgramFileService;
+	private final ParamService paramService;
+	private final MachineService machineService;
 	/**
 	 * 鏌ヨ鎴戠殑娴佺▼(涓汉寰呭姙鍒楄〃)
 	 * @param page 鍒嗛〉淇℃伅
@@ -53,21 +59,47 @@
 	 * @param keyword 鏌ヨ鍏抽敭瀛�
 	 * @return
 	 */
-	public IPage<FlowVO> selectTodoPage(IPage<FlowVO> page, LocalDateTime createTimeBegin, LocalDateTime createTimeEnd, String keyword) {
+	public IPage<FlowVO> selectTodoPage(IPage<FlowVO> page, TodoQueryVO queryVO) {//LocalDateTime createTimeBegin, LocalDateTime createTimeEnd, String keyword
 		//String taskUser = TaskUtil.getTaskUser();
 		String userId = "" + AuthUtil.getUserId();
 		List<FlowVO> flowList = new LinkedList<>();
 
 		TaskQuery todoQuery = taskService.createTaskQuery().taskAssignee(userId).active().includeProcessVariables();
-		if (Func.isNotEmpty(createTimeBegin)) {
-			todoQuery.taskCreatedAfter(DateUtil.toDate(createTimeBegin));
+
+		if(queryVO.getMachineSpec() != null){
+			if(queryVO.getMachineSpec().length==1) {//2涓负鍏ㄩ��
+				//鏌ヨ杞﹀簥浠g爜闆嗗悎
+				String turnVal = paramService.turninngValue();
+				List<Machine> machines = machineService.lambdaQuery().eq(Machine::getMachineSpec, turnVal).eq(Machine::getStatus, Machine.STATUS_ENABLE).list();
+				List<String> turnMachineCodes = machines.stream().map(Machine::getCode).toList();
+
+				List<String> specs = Arrays.asList(queryVO.getMachineSpec());
+				if (specs.contains("1")) {
+					//杞﹀簥
+					todoQuery.or();
+					for (String mCode : turnMachineCodes) {
+						todoQuery.processVariableValueEquals(FlowVariableContants.MACHINE_CODE, mCode);
+					}
+					todoQuery.endOr();
+				} else {
+					//鍔犲伐涓績
+					todoQuery.or();
+					for (String mCode : turnMachineCodes) {
+						todoQuery.processVariableValueNotEquals(FlowVariableContants.MACHINE_CODE, mCode);
+					}
+					todoQuery.endOr();
+				}
+			}
 		}
-		if (Func.isNotEmpty(createTimeEnd)) {
-			todoQuery.taskCreatedBefore(DateUtil.toDate(createTimeEnd));
-			//todoQuery.taskInProgressStartTimeBefore(DateUtil.toDate(createTimeEnd));
+
+		if (Func.isNotEmpty(queryVO.getCreateTimeBegin())) {
+			todoQuery.taskCreatedAfter(DateUtil.toDate(queryVO.getCreateTimeBegin()));
 		}
-		if (Func.isNotEmpty(keyword)) {
-			addKeywordCondition(todoQuery, keyword);
+		if (Func.isNotEmpty(queryVO.getCreateTimeEnd())) {
+			todoQuery.taskCreatedBefore(DateUtil.toDate(queryVO.getCreateTimeEnd()));
+		}
+		if (Func.isNotEmpty(queryVO.getKeyword())) {
+			addKeywordCondition(todoQuery, queryVO.getKeyword());
 		}
 
 		todoQuery.orderByTaskCreateTime().desc();
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 038ac74..eef7d61 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
@@ -127,6 +127,8 @@
 		programProperties.setActCheckerId(Func.toLong(vars.get(FlowVariableContants.ACT_CHECKER)));
 		programProperties.setActSeniorId(Func.toLong(vars.get(FlowVariableContants.ACT_SENIOR)));
 		programProperties.setProgrammerName(Func.toStr(vars.get("programmerName")));
+
+		programProperties.setProgramOnMachine(Func.toStr(vars.get(FlowVariableContants.PROGRAM_ON_MACHINE)));
 	}
 	/**
 	 * 娴佺▼鏄惁鍦ㄨ繘琛�
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/FlowProgramFileService.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/FlowProgramFileService.java
index 018112f..e2c00c0 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/FlowProgramFileService.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/FlowProgramFileService.java
@@ -12,8 +12,10 @@
 import org.springblade.core.mp.base.BizServiceImpl;
 import org.springblade.core.oss.OssTemplate;
 import org.springblade.core.oss.model.BladeFile;
+import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.api.IResultCode;
 import org.springblade.core.tool.utils.Func;
+import org.springblade.core.tool.utils.UrlUtil;
 import org.springblade.mdm.flow.entity.FlowProgramFile;
 import org.springblade.mdm.flow.mapper.FlowProgramFileMapper;
 import org.springblade.mdm.flow.vo.ProgramUploadVO;
@@ -140,7 +142,7 @@
 
 	public void download(Long id, HttpServletResponse response) throws IOException {
 		FlowProgramFile flowFile = this.getById(id);
-		response.setHeader("Content-Disposition", "attachment; filename="+flowFile.getName());
+		response.setHeader("Content-Disposition", "attachment; filename="+ UrlUtil.encode(flowFile.getName()));
 		response.setContentType("application/octet-stream");
 		try(InputStream ins = ossTemplate.statFileStream(flowFile.getOssName());){
 			IOUtils.copy(ins,response.getOutputStream());
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/FlowProgramProperties.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/FlowProgramProperties.java
index 4b1fcf8..83d6729 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/FlowProgramProperties.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/FlowProgramProperties.java
@@ -89,4 +89,9 @@
 	private Long actCheckerId;
 	@Schema(description = "瀹為檯鏍″濮撳悕")
 	private Long actSeniorId;
+
+
+
+	@Schema(description = "鐜板満缂栧埗鏍囪")
+	private String programOnMachine;
 }
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/LockFlowService.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/LockFlowService.java
index 8c832d0..7d38e76 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/LockFlowService.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/LockFlowService.java
@@ -51,7 +51,11 @@
 		vars.put(FlowVariableContants.MY_PROCESS_NAME,"瑙i攣娴佺▼");
 		vars.put("comment", "瑙i攣绋嬪簭"+programPackage.getName());
 		vars.put("unlockReason", unlockReason);
-		identityService.setAuthenticatedUserId(String.valueOf(AuthUtil.getUserId()));//璁剧疆娴佺▼鍙戣捣浜�
+
+		String userId = String.valueOf(AuthUtil.getUserId());
+		identityService.setAuthenticatedUserId(userId);//璁剧疆娴佺▼鍙戣捣浜�
+		vars.put(FlowVariableContants.ACT_PROGRAMMER,userId);
+
 		ProcessInstance inst = runtimeService.startProcessInstanceByKey(FlowContants.UNLOCK_PROCESS_KEY,nodeId+"",vars);
 
 		programPackage.setProcessInstanceId(inst.getId());
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/ProgramOnMachineExportService.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/ProgramOnMachineExportService.java
new file mode 100644
index 0000000..50225aa
--- /dev/null
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/ProgramOnMachineExportService.java
@@ -0,0 +1,105 @@
+
+package org.springblade.mdm.flow.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import lombok.AllArgsConstructor;
+import org.flowable.engine.HistoryService;
+import org.flowable.engine.history.HistoricProcessInstance;
+import org.flowable.engine.history.HistoricProcessInstanceQuery;
+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.basesetting.producedivision.service.QinzheFgbService;
+import org.springblade.mdm.commons.service.ParamService;
+import org.springblade.mdm.flow.constants.FlowContants;
+import org.springblade.mdm.flow.constants.FlowVariableContants;
+import org.springblade.mdm.flow.vo.FlowVO;
+import org.springblade.mdm.flow.vo.ProgramOnMachineQueryVO;
+import org.springblade.mdm.program.service.NcNodeHisService;
+import org.springblade.mdm.program.service.NcNodeService;
+import org.springblade.system.feign.IDictBizClient;
+import org.springframework.stereotype.Service;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.*;
+
+/**
+ * 娴佺▼涓氬姟瀹炵幇绫�
+ *
+ * @author Chill
+ */
+@Service
+@AllArgsConstructor
+public class ProgramOnMachineExportService {
+
+	private final HistoryService historyService;
+	private final ParamService paramService;
+	private final MachineService machineService;
+	/**
+	 *
+	 * @param page 鍒嗛〉淇℃伅
+	 * @param queryVO 鏌ヨ鏁版嵁瀵硅薄
+	 * @return
+	 */
+	public IPage<FlowVO> finishedPage(IPage<FlowVO> page, ProgramOnMachineQueryVO queryVO) {
+		//鍥哄寲閲岃矾鏉戝畼
+		HistoricProcessInstanceQuery query = this.historyService.createHistoricProcessInstanceQuery().finished().processDefinitionKey(FlowContants.CURE_PROCESS_KEY).includeProcessVariables();
+			//.finished() // 鍙煡璇㈠凡瀹屾垚鐨勬祦绋�.unfinished() // 鏌ヨ鏈畬鎴愮殑娴佺▼
+		query.variableNotExists(FlowVariableContants.EXCEPTION);//闈炲紓甯告祦绋�
+		query.variableValueEquals(FlowVariableContants.PROGRAM_ON_MACHINE,FlowContants.Y);//閫夋嫨鐜板満缂栧埗鐨�
+		/*
+		//杞﹀簥鎴栬�呴�夋嫨鐜板満缂栧埗鐨勭▼搴�
+		String turnVal = paramService.turninngValue();
+		List<Machine> machines = machineService.lambdaQuery().eq(Machine::getMachineSpec,turnVal).eq(Machine::getStatus,Machine.STATUS_ENABLE).list();
+		List<String> turnMachineCodes = machines.stream().map(Machine::getCode).toList();
+		query.or();
+		for(String mCode : turnMachineCodes){
+			query.variableValueEquals(FlowVariableContants.MACHINE_CODE, mCode);
+		}
+
+		query.endOr();
+		*/
+		if(queryVO.getEndTimeBegin()!=null) {
+			query.finishedAfter(DateUtil.toDate(queryVO.getEndTimeBegin()));
+		}
+		if(queryVO.getEndTimeEnd()!=null) {
+			query.finishedBefore(DateUtil.toDate(queryVO.getEndTimeEnd()));
+		}
+		if(Func.isNotEmpty(queryVO.getDrawingNo())) {
+			String likeVal = "%" + queryVO.getDrawingNo() + "%";
+			query.variableValueLike(FlowVariableContants.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;
+	}
+
+}
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/ReplaceFlowService.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/ReplaceFlowService.java
index 1c6b17c..1477156 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/ReplaceFlowService.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/ReplaceFlowService.java
@@ -146,7 +146,6 @@
 			ProgramFileNameCheckUtil.checkFilename(file.getOriginalFilename(),progProps);
 		}
 
-
 		String programName = NcNodeService.genProgramName(progProps.getDrawingNo(),progProps.getProcessNo(),progProps.getProcessEdition());
 
 		BladeFile bfile = ossTemplate.putFile(file);
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 29385e6..85f0557 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
@@ -6,6 +6,7 @@
 import org.flowable.engine.runtime.ProcessInstance;
 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.support.Kv;
 import org.springblade.core.tool.utils.Func;
 import org.springblade.core.tool.utils.StringUtil;
@@ -160,7 +161,6 @@
 				//椹冲洖锛屾煡璇㈠疄闄呯紪绋嬩汉鍛� 椹冲洖
 				variables.put(FlowVariableContants.ASSIGNEE, getActualProgrammer(processInstanceId));
 			}
-			//approveRecordService.saveApproveRecords(task,FlowContants.Y,batchDispatchVO.getComment());
 
 			taskService.complete(taskId, variables);
 		}
@@ -198,4 +198,37 @@
 			throw new ServiceException("浠诲姟id涓庢祦绋嬪疄渚媔d鏁伴噺涓嶄竴鑷�");
 		}
 	}
+
+	/**
+	 * 鎺掔粌閫氳繃鐜板満缂栧埗
+	 * @param batchDispatchVO
+	 */
+    public void batchProgramOnMachine(BatchDispatchVO batchDispatchVO) {
+		checkBatchParameter(batchDispatchVO);
+		String[] taskIds = batchDispatchVO.getTaskIds();
+		String taskId;
+		String processInstanceId;
+
+		//瀹℃壒缁撴灉鍜屽鐞嗕汉閮戒竴鏍风殑
+		Map<String, Object> variables = Kv.create();
+		variables.put(FlowVariableContants.APPROVE, FlowContants.Y);
+		variables.put(FlowVariableContants.COMMENT, batchDispatchVO.getComment());
+		variables.put(FlowVariableContants.PROGRAM_ON_MACHINE, FlowContants.Y);//鐜板満缂栧埗:鏄�
+		variables.put(FlowVariableContants.ACT_PROGRAMMER, AuthUtil.getUserId()+"");//瀹為檯缂栧埗
+		variables.put(FlowVariableContants.ASSIGNEE,batchDispatchVO.getAssignee());
+		for(int i=0;i<taskIds.length;i++) {
+			taskId = taskIds[i];
+			processInstanceId = batchDispatchVO.getProcessInstanceIds()[i];
+
+			Task task = getTask(taskId);
+			if(!task.getTaskDefinitionKey().equals("programmingTask")){
+				throw new ServiceException("闈炵紪鍒朵换鍔★紝涓嶈兘鎸囧畾鐜板満缂栧埗");
+			}
+			if (StringUtil.isNoneBlank(processInstanceId, batchDispatchVO.getComment())) {
+				taskService.addComment(taskId, processInstanceId, batchDispatchVO.getComment());
+			}
+
+			taskService.complete(taskId, variables);
+		}
+    }
 }
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 acd1439..2315566 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,7 +4,6 @@
 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;
@@ -59,7 +58,8 @@
 		if(task.getTaskDefinitionKey().equals("programmingTask") ) {//缂栧埗鑺傜偣
 			//璁板綍瀹為檯缂栫▼鍛�
 			variables.put(FlowVariableContants.ACT_PROGRAMMER,Func.toStr(AuthUtil.getUserId()));
-			String programOnMachine = Func.toStr(variables.getOrDefault("programOnMachine",FlowContants.N));//鏄惁鐜板満缂栫▼
+
+			String programOnMachine = Func.toStr(variables.getOrDefault(FlowVariableContants.PROGRAM_ON_MACHINE,FlowContants.N));//鏄惁鐜板満缂栫▼
 			if(this.needUploadProgramFile(props.getMachineCode()) && programOnMachine.equals(FlowContants.N)) {
 				flowProgramFileService.checkProgramFiles(processInstanceId, FlowContants.Y.equals(operateResult));
 			}
@@ -72,7 +72,7 @@
 		}else if(task.getTaskDefinitionKey().equals("approveTask")){
 			variables.put(FlowVariableContants.ACT_SENIOR,Func.toStr(AuthUtil.getUserId()));
 		}
-		variables.remove("programOnMachine");//鍏朵粬鑺傜偣锛屽拷鐣ョ幇鍦虹紪绋嬫爣璁�
+		variables.remove(FlowVariableContants.PROGRAM_ON_MACHINE);//鍏朵粬鑺傜偣锛屽拷鐣ョ幇鍦虹紪绋嬫爣璁�
 		if (StringUtil.isNoneBlank(processInstanceId, comment)) {
 			taskService.addComment(taskId, processInstanceId, comment);
 		}
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/vo/ProgramOnMachineExcel.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/vo/ProgramOnMachineExcel.java
new file mode 100644
index 0000000..63a2aa6
--- /dev/null
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/vo/ProgramOnMachineExcel.java
@@ -0,0 +1,32 @@
+package org.springblade.mdm.flow.vo;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.write.style.ColumnWidth;
+import com.alibaba.excel.annotation.write.style.ContentRowHeight;
+import com.alibaba.excel.annotation.write.style.HeadRowHeight;
+
+import lombok.Data;
+
+@Data
+@ColumnWidth(25)
+@HeadRowHeight(20)
+@ContentRowHeight(18)
+public class ProgramOnMachineExcel {
+
+
+	@ExcelProperty("闆剁粍浠跺彿")
+	private String drawingNo;
+	@ExcelProperty("宸ュ簭鍙�")
+	private String processNo;
+	@ExcelProperty("宸ュ簭鐗堟")
+	private String processEdition;
+
+	@ColumnWidth(20)
+	@ExcelProperty("鏈哄簥缂栧彿")
+	private String machineCode;
+
+	@ColumnWidth(20)
+	@ExcelProperty("娴佺▼缂栧彿")
+	private String processInstanceId;
+
+}
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/vo/ProgramOnMachineQueryVO.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/vo/ProgramOnMachineQueryVO.java
new file mode 100644
index 0000000..ac81ac5
--- /dev/null
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/vo/ProgramOnMachineQueryVO.java
@@ -0,0 +1,29 @@
+package org.springblade.mdm.flow.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+import org.springblade.core.mp.support.Query;
+import org.springblade.core.tool.utils.DateUtil;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDate;
+import java.util.Date;
+
+/**
+ * 鍒嗛〉鎷嗙嚎鍛�
+ */
+
+@Schema(description = "鏈哄簥鏌ヨ瀵硅薄")
+@Setter
+@Getter
+public class ProgramOnMachineQueryVO extends Query {
+	@Schema(description = "闆剁粍浠跺彿")
+	private String drawingNo;
+	@DateTimeFormat(pattern = DateUtil.PATTERN_DATE)
+	@Schema(description = "瀹℃壒瀹屾垚鏃堕棿寮�濮�")
+	private LocalDate endTimeBegin;
+	@DateTimeFormat(pattern = DateUtil.PATTERN_DATE)
+	@Schema(description = "瀹℃壒瀹屾垚鏃堕棿鎴")
+	private LocalDate endTimeEnd;
+}
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/vo/TodoQueryVO.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/vo/TodoQueryVO.java
new file mode 100644
index 0000000..d2d32e9
--- /dev/null
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/vo/TodoQueryVO.java
@@ -0,0 +1,25 @@
+package org.springblade.mdm.flow.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springblade.core.mp.support.Query;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+@Data
+public class TodoQueryVO extends Query {
+	@Schema(description = "鍏抽敭瀛�")
+	private String keyword;
+
+	@Schema(description = "鍒涘缓鏃堕棿寮�濮�")
+	@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+	private LocalDateTime createTimeBegin;
+
+	@Schema(description = "鍒涘缓鏃堕棿鎴")
+	@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+	private LocalDateTime createTimeEnd;
+
+	@Schema(description = "鏈哄簥绫诲瀷")
+	private String[] machineSpec;
+}
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/machinefile/service/MachineFileScanService.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/machinefile/service/MachineFileScanService.java
index a3a297f..ab4e604 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/machinefile/service/MachineFileScanService.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/machinefile/service/MachineFileScanService.java
@@ -12,6 +12,7 @@
 import org.springblade.mdm.utils.FileContentUtil;
 import org.springblade.system.pojo.entity.DictBiz;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Component;
 
 import java.io.BufferedInputStream;
@@ -41,6 +42,7 @@
 	/**
 	 * 鎵弿鎵�鏈夋満搴婄殑閰嶇疆鐩綍
 	 */
+	@Async
 	public void scanMachineFile() {
 		List<Machine> machines = machineService.getEnableMachines();
 		for (Machine machine : machines) {
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/machinefile/service/ReceiveFileCheckService.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/machinefile/service/ReceiveFileCheckService.java
new file mode 100644
index 0000000..0052fa3
--- /dev/null
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/machinefile/service/ReceiveFileCheckService.java
@@ -0,0 +1,97 @@
+package org.springblade.mdm.machinefile.service;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.springblade.core.log.exception.ServiceException;
+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.gkw.programnode.vo.ProgramNameVO;
+import org.springblade.mdm.machinefile.entity.FileSendRecord;
+import org.springblade.mdm.machinefile.entity.MachineFile;
+import org.springblade.mdm.program.service.ProgramAnnotationService;
+import org.springblade.mdm.program.service.programannotation.AnnotationUtil;
+import org.springblade.mdm.utils.FileContentUtil;
+import org.springblade.mdm.utils.ProgramFileNameParser;
+import org.springblade.system.pojo.entity.DictBiz;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.FileTime;
+import java.util.Date;
+import java.util.List;
+import java.util.Optional;
+
+@Slf4j
+@Component
+public class ReceiveFileCheckService {
+	@Autowired
+	private MachineFileService machineFileService;
+	@Autowired
+	private MachineService machineService;
+	@Autowired
+	private ParamService paramService;
+	@Autowired
+	private FileSendRecordService fileSendRecordService;
+	/**
+	 * 鏂囦欢鍚堟硶鎬ф鏌�
+	 * @param machineFile
+	 */
+	@Transactional(rollbackFor = Exception.class)
+	public void check(MachineFile machineFile,List<MachineFile> allFilesInDir,Machine machine) throws IOException {
+		String srcFilepath = MachineFileService.getBasePath(machine,machineFile.getDirType())+ File.separator+machineFile.getName();
+		Path source = Paths.get(srcFilepath);
+		if(!source.toFile().exists()){
+			return;
+		}
+		try(InputStream fileIns = Files.newInputStream(Paths.get(srcFilepath));) {
+			if(!FileContentUtil.isTextFile(fileIns)){
+				//闈炴枃鏈�
+				machineFile.setExceptionType(MachineFile.EXCEPTION_NOT_TEXT);
+			}else{
+				ProgramNameVO progNameVO =  ProgramFileNameParser.parseProgramName(machineFile.getName());
+				if(!progNameVO.isValidFilename()){
+					machineFile.setExceptionType(MachineFile.EXCEPTION_BAD_FILENAME);
+				}else {
+					String prefix = progNameVO.logicProgramName()+"-";
+					long matchCount = allFilesInDir.stream().filter(file -> file.getName().startsWith(prefix)).count();
+					if(matchCount != progNameVO.getSegmentCount()){//鏂囦欢娈垫暟缂哄け
+						machineFile.setExceptionType(MachineFile.EXCEPTION_LOST_FILES);
+					}else{
+						//妫�鏌ユ槸鍚﹀尮閰嶄笅鍙戣褰曠殑娈垫暟
+						//姝h礋3绉掍綔涓烘煡璇㈡椂闂�
+						Date beginTime = new Date(machineFile.getFileCreateTime().getTime()-3000);
+						Date endTime = new Date(machineFile.getFileCreateTime().getTime()+3000);
+						Optional<FileSendRecord> optFile = fileSendRecordService.lambdaQuery()
+							.eq(FileSendRecord::getMachineCode,machineFile.getMachineCode())
+							.likeRight(FileSendRecord::getName,prefix).between(FileSendRecord::getCreateTime,beginTime,endTime).oneOpt();
+
+						if(optFile.isPresent()){
+							//纭疄涓嬪彂杩囷紝姣斿鎬绘鏁版槸鍚︾浉鍚�
+							FileSendRecord sendFile = optFile.get();
+							ProgramNameVO sendProgNameVO =  ProgramFileNameParser.parseProgramName(sendFile.getName());
+							if(progNameVO.getSegmentCount() != sendProgNameVO.getSegmentCount()){
+								//娈垫暟涓嶅尮閰�
+								machineFile.setExceptionType(MachineFile.EXCEPTION_NOT_MATCH_SEND);
+							}else{
+								machineFile.setExceptionType(MachineFile.EXCEPTION_OK);
+							}
+						}
+					}
+				}
+			}
+
+			machineFileService.updateById(machineFile);
+		}
+	}
+}
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/controller/NcNodeController.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/controller/NcNodeController.java
index 2c207eb..30494ee 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/controller/NcNodeController.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/controller/NcNodeController.java
@@ -4,20 +4,25 @@
 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.springblade.core.log.exception.ServiceException;
 import org.springblade.core.tenant.annotation.NonDS;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.Func;
 import org.springblade.mdm.flow.service.FlowProgramFileService;
 import org.springblade.mdm.flow.service.TaskDispatchService;
 import org.springblade.mdm.program.entity.NcNode;
+import org.springblade.mdm.program.service.NcNodeHisService;
 import org.springblade.mdm.program.service.NcNodeService;
 import org.springblade.mdm.program.service.ProgramFlowStatusQueryService;
 import org.springblade.mdm.program.vo.*;
 import org.springframework.web.bind.annotation.*;
 
+import java.io.IOException;
+import java.rmi.ServerError;
 import java.util.Comparator;
 import java.util.List;
 
@@ -34,6 +39,7 @@
 @Slf4j
 public class NcNodeController {
 	private final NcNodeService ncNodeService;
+	private final NcNodeHisService nodeHisService;
 	private final ProgramFlowStatusQueryService programFlowStatusQueryService;
 	private final FlowProgramFileService flowProgramFileService;
 	private final TaskDispatchService taskDispatchService;
@@ -154,13 +160,14 @@
 	public R<List<String>> drawingNoPick(String drawingNo) {
 		return R.data(taskDispatchService.drawingNoSeletDropList(drawingNo));
 	}
+/*
 
 	@GetMapping("/history-by-nodeid")
-	@Operation(summary = "鏍规嵁缁戝畾鑺傜偣id鑾峰彇鍘嗗彶鍒楄〃", description = "绋嬪簭鍘嗗彶鍒楄〃锛屼粎鈥樼▼搴忓寘鈥欏瓧鍏稿��70鐨勬暟鎹�傜敤浜庢樉绀虹▼搴忕殑鈥樺巻鍙茬増鏈��")
-	public R<List<NcNodeVO>> historyByBindNodeId(@Parameter(description="鑺傜偣ID(nodeType=70鐨勮妭鐐筰d)")@RequestParam Long id) {
-		return R.data(this.ncNodeService.historyByNodeId(id));
+	@Operation(summary = "鏍规嵁缁戝畾鑺傜偣id鑾峰彇鍘嗗彶鍒楄〃", description = "绋嬪簭鍘嗗彶鍒楄〃锛屼粎鈥樼▼搴忓寘鈥欏瓧鍏稿��60鐨勬暟鎹�傜敤浜庢樉绀虹▼搴忕殑鈥樺巻鍙茬増鏈��")
+	public R<List<NcNodeVO>> historyByBindNodeId(@Parameter(description="鑺傜偣ID(nodeType=60鐨勮妭鐐筰d)")@RequestParam Long id) {
+		return R.data(this.nodeHisService.historyByNodeId(id));
 	}
-
+*/
 
 	@GetMapping("/compare-content")
 	@Operation(summary = "瀵规瘮鍐呭鏁版嵁", description = "鏌ヨ瀵规瘮鍐呭鐨�2涓枃鏈暟鎹�")
@@ -178,19 +185,19 @@
 		return R.data(vo);
 	}
 
-	@GetMapping("/content-by-nodeid")
-	@Operation(summary = "鏍规嵁鑺傜偣鑾峰彇鏂囦欢鍐呭", description = "浠呴檺鏂囨湰鏍煎紡鐨勫唴瀹癸紝浜岃繘鍒舵枃浠跺皢杩斿洖绌轰覆")
-	public R<String> fileContentByNodeId(@Parameter(description = "鑺傜偣id") Long nodeId) {
-		try {
-			NcNode ncnode = ncNodeService.getById(nodeId);
-			if(ncnode.getFlowProgramFileId() != null) {
-				return R.data(flowProgramFileService.getFileContent(ncnode.getFlowProgramFileId()));
-			}else{
-				return R.data("鎵句笉鍒版枃浠�");
-			}
-		}catch(Exception e) {
-			log.error("鍒犻櫎鏂囦欢澶辫触",e);
-			return R.fail(e.getMessage());
+
+
+	@GetMapping("/download-by-nodeid")
+	@Operation(summary = "涓嬭浇鑺傜偣瀵瑰簲鐨勬枃浠�", description = "涓嬭浇鑺傜偣瀵瑰簲鐨勬枃浠�")
+	public void downloadByNodeId(@Parameter(description = "鑺傜偣id") Long nodeId, HttpServletResponse response) throws IOException {
+
+		NcNode ncnode = ncNodeService.getById(nodeId);
+		if(ncnode.getFlowProgramFileId() != null) {
+			flowProgramFileService.download(ncnode.getFlowProgramFileId(),response);
+		}else{
+			log.error("闈炴枃浠惰妭鐐�");
+			throw new ServiceException("鑺傜偣鏃犳枃浠秈d");
 		}
+
 	}
 }
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/controller/NcNodeHisController.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/controller/NcNodeHisController.java
new file mode 100644
index 0000000..4bcfc61
--- /dev/null
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/controller/NcNodeHisController.java
@@ -0,0 +1,101 @@
+
+package org.springblade.mdm.program.controller;
+
+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.springblade.core.log.exception.ServiceException;
+import org.springblade.core.tenant.annotation.NonDS;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.mdm.flow.service.FlowProgramFileService;
+import org.springblade.mdm.flow.service.TaskDispatchService;
+import org.springblade.mdm.program.entity.NcNode;
+import org.springblade.mdm.program.entity.NcNodeHis;
+import org.springblade.mdm.program.service.NcNodeHisService;
+import org.springblade.mdm.program.service.NcNodeService;
+import org.springblade.mdm.program.service.ProgramFlowStatusQueryService;
+import org.springblade.mdm.program.vo.CompareDataVO;
+import org.springblade.mdm.program.vo.NcNodeOldQueryVO;
+import org.springblade.mdm.program.vo.NcNodeQueryVO;
+import org.springblade.mdm.program.vo.NcNodeVO;
+import org.springframework.beans.BeanUtils;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * 绋嬪簭鑺傜偣
+ *
+ * @author yangys
+ */
+@NonDS
+@RestController
+@RequestMapping("/program/nodehis")
+@AllArgsConstructor
+@Tag(name = "绋嬪簭鑺傜偣", description = "绋嬪簭鑺傜偣")
+@Slf4j
+public class NcNodeHisController {
+	private final NcNodeService ncNodeService;
+	private final NcNodeHisService nodeHisService;
+	private final FlowProgramFileService flowProgramFileService;
+
+
+	@GetMapping("/history-by-nodeid")
+	@Operation(summary = "鏍规嵁缁戝畾鑺傜偣id鑾峰彇鍘嗗彶鍒楄〃", description = "绋嬪簭鍘嗗彶鍒楄〃锛屼粎鈥樼▼搴忓寘鈥欏瓧鍏稿��60鐨勬暟鎹�傜敤浜庢樉绀虹▼搴忕殑鈥樺巻鍙茬増鏈��")
+	public R<List<NcNodeVO>> historyByBindNodeId(@Parameter(description="鑺傜偣ID(nodeType=60鐨勮妭鐐筰d)")@RequestParam Long id) {
+		return R.data(this.nodeHisService.historyByNodeId(id));
+	}
+
+	@GetMapping("/files-by-parent-id")
+	@Operation(summary = "鑾峰彇鍘嗗彶绋嬪簭鍖呮枃浠跺垪琛�", description = "鑾峰彇鍘嗗彶绋嬪簭鍖呮枃浠跺垪琛�")
+	public R<List<NcNodeVO>> filesByParentNodeId(@Parameter(description="鑺傜偣ID(nodeType=60鐨勮妭鐐筰d)")@RequestParam Long id) {
+		List<NcNodeHis> nodes = nodeHisService.lambdaQuery().eq(NcNodeHis::getParentId,id).orderByDesc(NcNodeHis::getCreateTime).list();
+		List<NcNodeVO> voList = new ArrayList<>(nodes.stream().map(nh -> {NcNodeVO vo = new NcNodeVO();
+			BeanUtils.copyProperties(nh,vo);
+			return vo;
+		}).toList());
+		NcNodeHis pkgNode = nodeHisService.getById(id);
+		//鏂囦欢锛屾寜鐓у厛绋嬪簭锛屽悗鍏朵粬鎺掑簭
+		if(!voList.isEmpty()) {
+			if (voList.get(0).getNodeType().equals(NcNode.TYPE_PROGRAM_FILE)) {
+				Comparator<NcNodeVO> cp = new Comparator<>() {
+					@Override
+					public int compare(NcNodeVO n1, NcNodeVO n2) {
+						if (n1.getName().startsWith(pkgNode.getName()) && !n2.getName().startsWith(pkgNode.getName())) {
+							return -1;
+						} else {
+							return 1;
+						}
+					}
+				};
+				voList.sort(cp.thenComparing(NcNodeVO::getName));
+
+			}
+		}
+		return R.data(voList);
+	}
+
+	@GetMapping("/content-by-nodeid")
+	@Operation(summary = "鏍规嵁鑺傜偣鑾峰彇鏂囦欢鍐呭", description = "浠呴檺鏂囨湰鏍煎紡鐨勫唴瀹癸紝浜岃繘鍒舵枃浠跺皢杩斿洖绌轰覆")
+	public R<String> fileContentByNodeId(@Parameter(description = "鑺傜偣id") Long nodeId) {
+		try {
+			NcNodeHis node = this.nodeHisService.getById(nodeId);
+			if(node.getFlowProgramFileId() != null) {
+				return R.data(flowProgramFileService.getFileContent(node.getFlowProgramFileId()));
+			}else{
+				return R.data("鎵句笉鍒版枃浠�");
+			}
+		}catch(Exception e) {
+			log.error("鑾峰彇鏂囦欢鍐呭澶辫触",e);
+			return R.fail(e.getMessage());
+		}
+	}
+}
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/controller/ProgramOnMachineImportController.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/controller/ProgramOnMachineImportController.java
new file mode 100644
index 0000000..d6eae27
--- /dev/null
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/controller/ProgramOnMachineImportController.java
@@ -0,0 +1,62 @@
+
+package org.springblade.mdm.program.controller;
+
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springblade.core.excel.util.ExcelUtil;
+import org.springblade.core.tenant.annotation.NonDS;
+import org.springblade.core.tool.api.R;
+import org.springblade.mdm.program.service.MdmProgramImportService;
+import org.springblade.mdm.program.service.ProgramOnMachineService;
+import org.springblade.mdm.program.vo.MdmProgramImportVO;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.List;
+
+/**
+ * mdm瀵煎叆鎺ュ彛锛屽伐鎺х綉鍔熻兘
+ *
+ * @author yangys
+ */
+@NonDS
+@RestController
+@RequestMapping("/program/mdmimport/")
+@AllArgsConstructor
+@Tag(name = "MDM瀵煎叆", description = "宸ユ帶缃慚DM瀵煎叆鎺ュ彛")
+@Slf4j
+public class ProgramOnMachineImportController {
+
+	private final ProgramOnMachineService programOnMachineService;
+	/**
+	 * 涓婁紶DNC鍥炰紶鏂囦欢
+	 *
+	 * @param file    dnc绋嬪簭鎵撳寘鏂囦欢
+	 */
+	@PostMapping("import-prog-on-machine")
+	@ApiOperationSupport(order = 1)
+	@Operation(summary = "MDM绋嬪簭瀵煎叆", description = "宸ユ帶缃憁dm绋嬪簭瀵煎叆")
+	public R<Integer> upload(@RequestParam MultipartFile file) {
+		if(file == null || file.isEmpty() || file.getOriginalFilename() ==null){
+			return R.fail("鏂囦欢涓嶈兘涓虹┖");
+		}
+		String filename = file.getOriginalFilename().toLowerCase();
+		if(!StringUtils.endsWithAny(filename,".xlsx",".xls")){
+			return R.fail("鏂囦欢蹇呴』涓篍xcel鏂囦欢");
+		}
+		try {
+			return R.data(programOnMachineService.importData(file));
+		}catch (Exception e){
+			log.error("瀵煎叆閿欒",e);
+			return R.fail(e.getMessage());
+		}
+	}
+
+}
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/entity/ProcessProgRef.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/entity/ProcessProgRef.java
deleted file mode 100644
index a1d3829..0000000
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/entity/ProcessProgRef.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.springblade.mdm.program.entity;
-
-import com.baomidou.mybatisplus.annotation.TableName;
-import lombok.Getter;
-import lombok.Setter;
-import org.springblade.core.mp.base.BizEntity;
-
-import java.time.LocalDateTime;
-
-/**
- * 娴佺▼瀹炰緥涓庣▼搴廼d鐨勫叧鑱�
- */
-@Setter
-@Getter
-@TableName("mdm_process_prog_ref")
-public class ProcessProgRef extends BizEntity {
-	/**
-	 * 娴佺▼瀹炰緥id
-	 */
-	private String processInstanceId;
-	/**
-	 * 鏁版帶绋嬪簭id
-	 */
-	private Long ncProgramId;
-
-	/**
-	 * 娴佺▼瀹氫箟key
-	 */
-	private String processDefinitionKey;
-}
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/entity/ProgramOnMachine.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/entity/ProgramOnMachine.java
new file mode 100644
index 0000000..54eb036
--- /dev/null
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/entity/ProgramOnMachine.java
@@ -0,0 +1,47 @@
+package org.springblade.mdm.program.entity;
+
+import com.alibaba.excel.util.StringUtils;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Getter;
+import lombok.Setter;
+import org.springblade.core.mp.base.BizEntity;
+import org.springblade.mdm.flow.entity.FlowProgramFile;
+
+import java.util.Date;
+
+/**
+ * 鐜板満缂栫▼璁板綍
+ */
+
+@Setter
+@Getter
+@TableName("mdm_program_on_machine")
+public class ProgramOnMachine extends BizEntity {
+
+	/**
+	 * 璁惧缂栧彿
+	 */
+	private String machineCode;
+
+
+	/**
+	 * 宸ュ簭鐗堟
+	 */
+	private String processEdition;
+
+
+	/**
+	 * 闆剁粍浠跺彿/鍥惧彿
+	 */
+	private String drawingNo;
+
+	/**
+	 * 宸ュ簭鍙�
+	 */
+	private String processNo;
+
+	/**
+	 * 娴佺▼瀹炰緥id
+	 */
+	private String processInstanceId;
+}
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/mapper/NcNodeHisMapper.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/mapper/NcNodeHisMapper.java
index e678575..9441ce9 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/mapper/NcNodeHisMapper.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/mapper/NcNodeHisMapper.java
@@ -3,10 +3,14 @@
 import org.apache.ibatis.annotations.Param;
 import org.springblade.core.mp.mapper.BladeMapper;
 import org.springblade.mdm.program.entity.NcNodeHis;
+import org.springblade.mdm.program.vo.NcNodeVO;
 
 import java.util.List;
 
 public interface NcNodeHisMapper extends BladeMapper<NcNodeHis> {
 
 	long countById(Long id);
+
+
+    List<NcNodeVO> packageHistoryBySerial(@Param("hisSerial")Long hisSerial);
 }
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/mapper/NcNodeHisMapper.xml b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/mapper/NcNodeHisMapper.xml
index 912b368..f866f93 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/mapper/NcNodeHisMapper.xml
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/mapper/NcNodeHisMapper.xml
@@ -18,5 +18,11 @@
     <select id="countById" resultType="java.lang.Long">
         select count(1) from mdm_nc_node_his where id=#{id}
     </select>
+    <select id="packageHistoryBySerial" resultType="org.springblade.mdm.program.vo.NcNodeVO">
+        select n.id,n.name,n.version_number,n.create_time,n.update_time,u.name create_user_name,n.process_no
+        from mdm_nc_node_his n left join blade_user u on n.create_user=u.id and u.is_deleted=0
+        where n.is_deleted=0 and n.node_type='60' and his_serial=#{hisSerial}
+        order by create_time desc
+    </select>
 
 </mapper>
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/mapper/NcNodeMapper.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/mapper/NcNodeMapper.java
index 330ca69..dd34604 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/mapper/NcNodeMapper.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/mapper/NcNodeMapper.java
@@ -41,7 +41,7 @@
 	 * @param name 鑺傜偣鍚嶇О
 	 * @return
 	 */
-    List<NcNodeVO> historyByParentIdAndName(@Param("name") String name,@Param("parentNode")NcNode parentNode);
+    //List<NcNodeVO> historyByParentIdAndName(@Param("name") String name,@Param("parentNode")NcNode parentNode);
 
 	/**
 	 * 鍒犻櫎瀛愯妭鐐癸紝鐢ㄤ簬鍒犻櫎绋嬪簭鍖呭悕鑺傜偣鐨勫瓙鑺傜偣
@@ -53,7 +53,7 @@
 	 * 绉婚櫎鏌愯妭鐐逛笅鐨勫姞宸ユ満搴婅妭鐐�
 	 * @param parentId 绯绘浣唅d
 	 */
-    void deleteMachineNodeByParentId(Long parentId);
+   // void deleteMachineGroupNodeByParentId(Long parentId);
 
 	/**
 	 * 鍒犻櫎闈炴渶鏂扮増鏈憿鐨勬暟鎹甽ast_edition<>1
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/mapper/NcNodeMapper.xml b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/mapper/NcNodeMapper.xml
index 9e96ee9..1cf5c54 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/mapper/NcNodeMapper.xml
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/mapper/NcNodeMapper.xml
@@ -30,10 +30,11 @@
     <delete id="deleteSubNodes">
         delete from mdm_nc_node where parent_id=#{nodeId}
     </delete>
-    <delete id="deleteMachineNodeByParentId">
+    <!--
+    <delete id="deleteMachineGroupNodeByParentId">
         delete from mdm_nc_node where parent_id=#{parentId} and node_type='50'
     </delete>
-
+    -->
 
     <sql id="all_columns">id,tenant_id,name,parent_id,parent_ids,node_type,status,create_dept,is_deleted,create_time,create_user,update_time,update_user</sql>
     <sql id="all_columns_n">n.id,n.tenant_id,n.name,n.parent_id,n.parent_ids,n.node_type,n.version_number,n.description,n.remark,n.drawing_no,n.drawing_no_edition,n.craft_edition,n.is_last_edition,n.is_locked,n.process_edition,n.process_no,n.product_model,n.is_cured,n.process_instance_id,n.status,n.create_dept,n.is_deleted,n.create_time,n.create_user,n.update_time,n.update_user</sql>
@@ -94,7 +95,7 @@
                 </if>
         </where>
     </select>
-
+    <!--
     <select id="historyByParentIdAndName" resultType="org.springblade.mdm.program.vo.NcNodeVO">
         select n.id,n.name,n.version_number,n.create_time,n.update_time,u.name create_user_name,n.process_no
          from mdm_nc_node n left join blade_user u on n.create_user=u.id and u.is_deleted=0
@@ -102,6 +103,7 @@
         where n.is_deleted=0 and n.parent_id in (select id from mdm_nc_node where parent_id=#{parentNode.parentId}) and n.name=#{name}
 
     </select>
+    -->
     <select id="searchList2" resultType="org.springblade.mdm.program.vo.NcNodeVO">
         select <include refid="all_columns_n"/>,dt.dict_value as node_type_name,u.name create_user_name,(
         SELECT
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/mapper/ProgramOnMachineMapper.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/mapper/ProgramOnMachineMapper.java
new file mode 100644
index 0000000..9a4f7d3
--- /dev/null
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/mapper/ProgramOnMachineMapper.java
@@ -0,0 +1,9 @@
+package org.springblade.mdm.program.mapper;
+
+import org.springblade.core.mp.mapper.BladeMapper;
+import org.springblade.mdm.program.entity.ProgramOnMachine;
+
+public interface ProgramOnMachineMapper extends BladeMapper<ProgramOnMachine> {
+
+
+}
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/mapper/ProgramOnMachineMapper.xml b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/mapper/ProgramOnMachineMapper.xml
new file mode 100644
index 0000000..5c124e5
--- /dev/null
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/mapper/ProgramOnMachineMapper.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.springblade.mdm.program.mapper.ProgramOnMachineMapper">
+
+
+</mapper>
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcNodeHisService.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcNodeHisService.java
index 173ad44..64b382e 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcNodeHisService.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcNodeHisService.java
@@ -69,4 +69,26 @@
 			.le(NcNodeHis::getCreateTime,programPkgNode.getCreateTime())  //鏃堕棿灏忎簬绛変簬褰撳墠鑺傜偣
 			.count();
 	}
+
+	/**
+	 * 鏌ヨ鑺傜偣鐨勫巻鍙插垪琛紙鑺傜偣鐨勪笂绾ц妭鐐光�濈▼搴忓寘鍚嶁�滃洜涓哄瓨鍦ㄥ涓増鏈紝鎵�浠ュ巻鍙茶褰曚篃闇�瑕佹牴鎹笉鍚岀増鏈▼搴忓寘鍚嶈繘琛屾煡璇級
+	 * @param id
+	 * @return
+	 */
+	@Transactional(readOnly = true)
+	public List<NcNodeVO> historyByNodeId(Long id) {
+		NcNodeHis node = this.getById(id);
+		/*
+		List<NcNodeHis> nodes = lambdaQuery().eq(NcNodeHis::getNodeType,NcNode.TYPE_PROGRAM_PACKAGE)
+			.eq(NcNodeHis::getHisSerial, node.getHisSerial()).orderByDesc(NcNodeHis::getCreateTime).list();
+		List<NcNodeVO> voList = new ArrayList<>();
+		nodes.forEach(ncNode -> {
+			NcNodeVO vo = new NcNodeVO();
+			BeanUtils.copyProperties(ncNode, vo);
+			vo.setCreateUserName();
+			voList.add(vo);
+		});*/
+		return this.baseMapper.packageHistoryBySerial(node.getHisSerial());
+		//return voList;
+	}
 }
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcNodeService.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcNodeService.java
index 48d78fd..5ec9172 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcNodeService.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcNodeService.java
@@ -180,17 +180,7 @@
 		}
 	}
 
-	/**
-	 * 鏌ヨ鑺傜偣鐨勫巻鍙插垪琛紙鑺傜偣鐨勪笂绾ц妭鐐光�濈▼搴忓寘鍚嶁�滃洜涓哄瓨鍦ㄥ涓増鏈紝鎵�浠ュ巻鍙茶褰曚篃闇�瑕佹牴鎹笉鍚岀増鏈▼搴忓寘鍚嶈繘琛屾煡璇級
-	 * @param id
-	 * @return
-	 */
-	@Transactional(readOnly = true)
-    public List<NcNodeVO> historyByNodeId(Long id) {
-		NcNode node = this.getById(id);
-		NcNode parentNode = this.getById(node.getParentId());
-		return this.baseMapper.historyByParentIdAndName(node.getName(),parentNode);
-    }
+
 
 	/**
 	 * 鑾峰彇鈥滅▼搴忓寘鍚嶁�濊瘯鍒囩殑鏈�鏂扮増鏈�
@@ -456,9 +446,10 @@
 	 * 鏍规嵁涓婄骇鑺傜偣id锛岀Щ鍔ㄤ笅闈㈢殑鍔犲伐鏈哄簥鑺傜偣
 	 * @param parentId 涓婄骇鑺傜偣id
 	 */
-	public void deleteMachineNodeByParentId(Long parentId) {
-		baseMapper.deleteMachineNodeByParentId(parentId);
-	}
+	/*
+	public void deleteMachineGroupNodeByParentId(Long parentId) {
+		baseMapper.deleteMachineGroupNodeByParentId(parentId);
+	}*/
 
 	/**
 	 * 鍒犻櫎鎵�鍋堕潪鏈�鏂扮増鏈殑鏁版嵁锛坔odeHIs閲岄潰宸茬粡淇濆瓨杩囷級
@@ -466,4 +457,20 @@
 	public void deleteOldEditionNodeData() {
 		baseMapper.deleteOldEditionNodeData();
 	}
+
+	/**
+	 * //鏇存柊宸插浐鍖栫殑锛屽悓鍚嶃�佷笉鍚屾満搴婄粍鐨勭▼搴忎负閿佸畾鐘舵��
+	 * @param packageNode
+	 */
+    public void lockSameNameOtherMachineGroupProgramPackage(NcNode packageNode) {
+		lambdaUpdate().eq(NcNode::getDrawingNo,packageNode.getDrawingNo())
+			.eq(NcNode::getProcessNo,packageNode.getProcessNo())
+			.eq(NcNode::getName,packageNode.getName())
+			.ne(NcNode::getMachineGroupCode,packageNode.getMachineGroupCode())
+			.eq(NcNode::getIsCured,1)
+			.eq(NcNode::getIsLastEdition,1)
+			.set(NcNode::getIsLocked,NcNode.LOCKED)
+			.set(NcNode::getRemark,"鍥炰紶鍥哄寲鍚屽悕绋嬪簭閿佸畾")
+			.update();
+    }
 }
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcProgramExportDNCService.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcProgramExportDNCService.java
index d696db6..1248513 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcProgramExportDNCService.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcProgramExportDNCService.java
@@ -6,11 +6,14 @@
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.io.FilenameUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.flowable.engine.HistoryService;
+import org.flowable.engine.history.HistoricProcessInstance;
 import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.mp.base.BizServiceImpl;
 import org.springblade.core.oss.OssTemplate;
 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.flow.entity.FlowProgramFile;
 import org.springblade.mdm.flow.service.FlowProgramFileService;
 import org.springblade.mdm.program.entity.NcNode;
@@ -48,7 +51,7 @@
 	private final NcNodeHisService ncNodeHisService;
 	private final OssTemplate ossTemplate;
 	private final FlowProgramFileService flowProgramFileService;
-	private final ProgramAnnotationService programAnnotationService;
+	private final HistoryService historyService;
 
 	private final MachineAnnotationConfig annotationConfig;
 	/**
@@ -65,6 +68,16 @@
 
 				approved.setStatus(NcProgramApproved.STATUS_EXPORTED);
 				approvedService.updateById(approved);
+
+				NcNode pkgNode = this.ncNodeService.getById(approved.getNcNodeId());
+				if(pkgNode.isDeviationProgram()){
+					//鍋忕鍗曠殑绋嬪簭锛屽鏋滃鎵瑰鍑鸿褰曟槸瑙i攣褰㈡垚鐨勶紝杩樻槸闇�瑕侀攣瀹氾紱鏅�氳瘯鍒囪繃鐨勶紝涓嶉攣瀹�
+					HistoricProcessInstance hisInst = historyService.createHistoricProcessInstanceQuery().processInstanceId(approved.getProcessInstanceId()).singleResult();
+					if(hisInst != null && hisInst.getProcessDefinitionKey().equals(FlowContants.UNLOCK_PROCESS_KEY)){
+						pkgNode.lock("涓嬪彂瀵煎嚭閿佸畾");
+						ncNodeService.updateById(pkgNode);
+					}
+				}
 			}
 
 		}catch(Exception e){
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/ProgramOnMachineService.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/ProgramOnMachineService.java
new file mode 100644
index 0000000..ddc42ca
--- /dev/null
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/ProgramOnMachineService.java
@@ -0,0 +1,57 @@
+
+package org.springblade.mdm.program.service;
+
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springblade.core.excel.util.ExcelUtil;
+import org.springblade.core.mp.base.BizServiceImpl;
+import org.springblade.core.tool.utils.BeanUtil;
+import org.springblade.mdm.basesetting.machine.service.MachineService;
+import org.springblade.mdm.commons.service.ParamService;
+
+import org.springblade.mdm.flow.vo.ProgramOnMachineExcel;
+import org.springblade.mdm.program.entity.ProgramOnMachine;
+import org.springblade.mdm.program.mapper.ProgramOnMachineMapper;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.*;
+
+/**
+ * DNC鍥炰紶鏂囦欢澶勭悊鏈嶅姟
+ *
+ * @author yangys
+ */
+@Slf4j
+@Service
+@AllArgsConstructor
+public class ProgramOnMachineService extends BizServiceImpl<ProgramOnMachineMapper, ProgramOnMachine> {
+
+	@Transactional(rollbackFor = Exception.class)
+	public int importData(MultipartFile file) {
+		List<ProgramOnMachineExcel> excelList = ExcelUtil.read(file, ProgramOnMachineExcel.class);
+
+		List<ProgramOnMachine> list = excelList.stream().map(excel -> {
+			ProgramOnMachine progMachine = new ProgramOnMachine();
+			BeanUtil.copyProperties(excel, progMachine);
+			return progMachine;
+		}).toList();
+
+		batchSaveData(list);
+
+		return list.size();
+	}
+
+	void batchSaveData(List<ProgramOnMachine> list) {
+		for (ProgramOnMachine progOnMachine : list) {
+			if(!existsByProcessInstanceId(progOnMachine.getProcessInstanceId())){
+				save(progOnMachine);
+			}
+		}
+	}
+
+	boolean existsByProcessInstanceId(String processInstanceId){
+		return this.lambdaQuery().eq(ProgramOnMachine::getProcessInstanceId,processInstanceId).count() > 0;
+	}
+}
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/programannotation/AbstractProcessor.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/programannotation/AbstractProcessor.java
index 7e6ca99..4574869 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/programannotation/AbstractProcessor.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/programannotation/AbstractProcessor.java
@@ -1,5 +1,6 @@
 package org.springblade.mdm.program.service.programannotation;
 
+import org.apache.commons.io.FilenameUtils;
 import org.apache.commons.io.IOUtils;
 import org.springblade.mdm.program.service.ProgramAnnotationService;
 import org.springblade.mdm.utils.FileContentUtil;
@@ -18,6 +19,24 @@
 
 	protected AnnotationProperties annotationProperties;
 
+	@Override
+	public InputStream setFilenameAnnotation(String fileName, InputStream inputStream) throws IOException {
+		List<DictBiz> annoDicts = programAnnotationService.getAnnotionDictList();
+		ByteArrayInputStream bais = new ByteArrayInputStream(com.qiniu.util.IOUtils.toByteArray(inputStream));
+
+		String line = FileContentUtil.readLineAt(bais, annotationProperties.getProgramNameLineIndex());
+		bais.reset();
+		boolean isAnnotation = AnnotationUtil.isAnnotation(line,this.getControlSystem(),annoDicts);
+		InputStream insAfter;
+		//鍔犲叆绋嬪簭鍚嶆敞閲婅
+		String proNameLine =  AnnotationUtil.generateAnnotation(FilenameUtils.removeExtension(fileName),getControlSystem(),annoDicts);
+		if(isAnnotation){
+			insAfter = FileContentUtil.replaceAtLine(bais, annotationProperties.getProgramNameLineIndex(),proNameLine);
+		}else{
+			insAfter = FileContentUtil.insertLine(bais, annotationProperties.getProgramNameLineIndex(),proNameLine);
+		}
+		return insAfter;
+	}
 
 	@Override
 	public InputStream setAnnotation(AnnotationData annoData,InputStream inputStream) throws IOException {
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/programannotation/AnnotationProcessor.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/programannotation/AnnotationProcessor.java
index 2d5bf01..224f6f8 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/programannotation/AnnotationProcessor.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/programannotation/AnnotationProcessor.java
@@ -19,4 +19,5 @@
 	String getControlSystem();
 	InputStream setAnnotation(AnnotationData annoData,InputStream inputStream) throws IOException;
 
+	InputStream setFilenameAnnotation(String programName,InputStream inputStream) throws IOException;
 }
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/programannotation/DefaultProcessor.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/programannotation/DefaultProcessor.java
index eb2908a..083dd1a 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/programannotation/DefaultProcessor.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/programannotation/DefaultProcessor.java
@@ -24,25 +24,13 @@
 
 	@Override
 	public InputStream setAnnotation(AnnotationData annoData, InputStream inputStream) throws IOException {
-		List<DictBiz> annoDicts = programAnnotationService.getAnnotionDictList();
-		ByteArrayInputStream bais = new ByteArrayInputStream(IOUtils.toByteArray(inputStream));
-
-		String line = FileContentUtil.readLineAt(bais, annotationProperties.getProgramNameLineIndex());
-		bais.reset();
-		boolean isAnnotation = AnnotationUtil.isAnnotation(line,controlSystem,annoDicts);
-		InputStream insAfter;
-		//鍔犲叆绋嬪簭鍚嶆敞閲婅
-		String proNameLine =  AnnotationUtil.generateAnnotation(FilenameUtils.removeExtension(annoData.getFilename()),getControlSystem(),annoDicts);
-		if(isAnnotation){
-			insAfter = FileContentUtil.replaceAtLine(bais, annotationProperties.getProgramNameLineIndex(),proNameLine);
-		}else{
-			insAfter = FileContentUtil.insertLine(bais, annotationProperties.getProgramNameLineIndex(),proNameLine);
-		}
+		InputStream insAfter = super.setFilenameAnnotation(annoData.getFilename(),inputStream);
 
 		return super.setAnnotation(annoData, insAfter);
 
 	}
 
+
 	@Override
 	public void setControlSystem(String controlSystemDictVal) {
 		this.controlSystem = controlSystemDictVal;
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/task/MachineFileScanTask.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/task/MachineFileScanTask.java
index c49cee9..00275d3 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/task/MachineFileScanTask.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/task/MachineFileScanTask.java
@@ -31,7 +31,7 @@
 	//@Scheduled(cron = "0 1 0 * * ?") // 姣忓ぉ涓婂崍0鐐�1鍒嗘墽琛�
 	//@Scheduled(cron = "0 */5 * * * ?")
 	//@Scheduled(cron = "0 15 19 * * ?") //test
-	@Scheduled(cron = "${task.cron.machine_file_scan:0 1 * * * ?}")
+	@Scheduled(cron = "${task.cron.machine_file_scan:0 1 0 * * ?}")
 	public void execute() {
 		String networkType = paramService.getParamValue(ParamService.NETWORK_TYPE,ParamService.NETWORK_TYPE_SHEMI);
 
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/task/ReceiveDirCheckTask.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/task/ReceiveDirCheckTask.java
index 77a97e3..079a2d9 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/task/ReceiveDirCheckTask.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/task/ReceiveDirCheckTask.java
@@ -9,12 +9,14 @@
 import org.springblade.mdm.machinefile.entity.MachineFile;
 import org.springblade.mdm.machinefile.service.FileSendRecordService;
 import org.springblade.mdm.machinefile.service.MachineFileService;
+import org.springblade.mdm.machinefile.service.ReceiveFileCheckService;
 import org.springblade.mdm.utils.FileContentUtil;
 import org.springblade.mdm.utils.ProgramFileNameParser;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.EnableScheduling;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.io.File;
 import java.io.IOException;
@@ -43,7 +45,7 @@
 	@Autowired
 	private ParamService paramService;
 	@Autowired
-	private FileSendRecordService fileSendRecordService;
+	private ReceiveFileCheckService receiveFileCheckService;
 	/**
 	 * 鏂囦欢榛樿淇濆瓨灏忔椂鏁帮紝0涓嶉檺鍒�
 	 */
@@ -79,9 +81,9 @@
 
 			for(MachineFile machineFile : recFiles){
 				try {
-					checkFile(machineFile, recFiles,machine);
+					receiveFileCheckService.check(machineFile, recFiles,machine);
 				}catch(Exception e){
-					log.error("妫�鏌ec鏂囦欢澶辫触:"+machineFile.getName(),e);
+					log.error("妫�鏌ec鏂囦欢澶辫触:{}",machineFile.getName(),e);
 				}
 			}
 
@@ -89,54 +91,5 @@
 
 	}
 
-	/**
-	 * 鏂囦欢绉诲姩鍒皌emp
-	 * @param machineFile
-	 */
-	private void checkFile(MachineFile machineFile,List<MachineFile> allFilesInDir,Machine machine) throws IOException {
-		String srcFilepath = MachineFileService.getBasePath(machine,machineFile.getDirType())+ File.separator+machineFile.getName();
-		Path source = Paths.get(srcFilepath);
-		if(!source.toFile().exists()){
-			return;
-		}
-		try(InputStream fileIns = Files.newInputStream(Paths.get(srcFilepath));) {
-			if(!FileContentUtil.isTextFile(fileIns)){
-				//闈炴枃鏈�
-				machineFile.setExceptionType(MachineFile.EXCEPTION_NOT_TEXT);
-			}else{
-				ProgramNameVO progNameVO =  ProgramFileNameParser.parseProgramName(machineFile.getName());
-				if(!progNameVO.isValidFilename()){
-					machineFile.setExceptionType(MachineFile.EXCEPTION_BAD_FILENAME);
-				}else {
-					String prefix = progNameVO.logicProgramName()+"-";
-					long matchCount = allFilesInDir.stream().filter(file -> file.getName().startsWith(prefix)).count();
-					if(matchCount != progNameVO.getSegmentCount()){//鏂囦欢娈垫暟缂哄け
-						machineFile.setExceptionType(MachineFile.EXCEPTION_LOST_FILES);
-					}else{
-						//妫�鏌ユ槸鍚﹀尮閰嶄笅鍙戣褰曠殑娈垫暟
-						//姝h礋3绉掍綔涓烘煡璇㈡椂闂�
-						Date beginTime = new Date(machineFile.getFileCreateTime().getTime()-3000);
-						Date endTime = new Date(machineFile.getFileCreateTime().getTime()+3000);
-						Optional<FileSendRecord> optFile = fileSendRecordService.lambdaQuery()
-							.eq(FileSendRecord::getMachineCode,machineFile.getMachineCode())
-							.likeRight(FileSendRecord::getName,prefix).between(FileSendRecord::getCreateTime,beginTime,endTime).oneOpt();
 
-						if(optFile.isPresent()){
-							//纭疄涓嬪彂杩囷紝姣斿鎬绘鏁版槸鍚︾浉鍚�
-							FileSendRecord sendFile = optFile.get();
-							ProgramNameVO sendProgNameVO =  ProgramFileNameParser.parseProgramName(sendFile.getName());
-							if(progNameVO.getSegmentCount() != sendProgNameVO.getSegmentCount()){
-								//娈垫暟涓嶅尮閰�
-								machineFile.setExceptionType(MachineFile.EXCEPTION_NOT_MATCH_SEND);
-							}else{
-								machineFile.setExceptionType(MachineFile.EXCEPTION_OK);
-							}
-						}
-					}
-				}
-			}
-
-			machineFileService.updateById(machineFile);
-		}
-	}
 }
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/thirdpart/controller/MesController.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/thirdpart/controller/MesController.java
index af1cce3..d721785 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/thirdpart/controller/MesController.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/thirdpart/controller/MesController.java
@@ -44,6 +44,7 @@
 	@Operation(summary = "鎺ユ敹MES浠诲姟", description = "鎺ユ敹MES浠诲姟")
 	public R<Void> newTask(@RequestBody MesTaskVO mesTaskVO) {
 		try {
+			log.info("鎺ユ敹MES浠诲姟锛屽弬鏁�:{}", mesTaskVO);
 			TaskAssignVO startVO = this.toTaskAssignVO(mesTaskVO);
 
 			List<String> errors = checkTaskData(startVO);

--
Gitblit v1.9.3