From 9064866a2c0c2988cba1d321d7af088d2647a4bc Mon Sep 17 00:00:00 2001
From: yangys <y_ys79@sina.com>
Date: 星期日, 06 七月 2025 23:59:50 +0800
Subject: [PATCH] 增加固化流程

---
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/vo/DncSendBackData.java                      |    3 
 blade-service/blade-mdm/src/main/resources/processesbpmn/program-cure.bpmn20.xml                               |    8 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcProgramExportDNCService.java       |  215 +++++++++++++++
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/CureFlowService.java                    |  111 ++++++-
 doc/sql/mdm/mdm.mysql.all.create.sql                                                                           |    1 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/DncSendBackService.java              |   27 -
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/controller/DncSendBackController.java        |   17 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/controller/NcProgramExportDNCController.java |    4 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/entity/ProcessProgRef.java                   |    7 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/controller/DispatchController.java              |    7 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcProgramApprovedService.java        |  183 -------------
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/task/cure/CureFinishOperateTask.java            |   19 +
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/ProcessProgRefService.java           |   15 +
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcProgramExchangeService.java        |  162 ++++++-----
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/entity/NcProgramExchange.java                |   10 
 15 files changed, 461 insertions(+), 328 deletions(-)

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 f464779..911f2cc 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
@@ -55,7 +55,7 @@
 
 	@Operation(summary = "瀹屾垚浠诲姟", description = "娴佸悜涓嬩竴涓妭鐐�")
 	@PostMapping("completeTask")
-	public R<Void> completeTask(String taskId, String processInstanceId, String comment,@Parameter(description = "瀵瑰簲鐨勭▼搴廼d,閫楀彿鍒嗛殧") String programIds, @Parameter(name = "variables", description = "浠诲姟鍙橀噺") @RequestBody Map<String, Object> variables) {
+	public R<Void> completeTask(String taskId, String processInstanceId, String comment,@Parameter(name = "variables", description = "浠诲姟鍙橀噺") @RequestBody Map<String, Object> variables) {
 		// 澧炲姞璇勮
 		if (StringUtil.isNoneBlank(processInstanceId, comment)) {
 			taskService.addComment(taskId, processInstanceId, comment);
@@ -63,6 +63,10 @@
 		// 闈炵┖鍒ゆ柇
 		if (Func.isEmpty(variables)) {
 			variables = Kv.create();
+		}
+		String programIds = null;
+		if(variables.containsKey("programIds")){
+			programIds = variables.get("programIds").toString();
 		}
 		if(StringUtils.isNotEmpty(programIds)) {
 			processProgRefService.addRelations(processInstanceId,Func.toLongList(programIds));
@@ -72,6 +76,7 @@
 		variables.put("approveUserNickName",AuthUtil.getNickName());
 
 		if(variables.containsKey("assignee")){
+
 			addApproveRecord(taskId,processInstanceId,comment,programIds,variables);
 			//鎸囧畾浜嗕笅涓�姝ユ墽琛屼汉
 			taskService.complete(taskId, variables);
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/CureFlowService.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/CureFlowService.java
index 15b4550..0b4c7d0 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/CureFlowService.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/CureFlowService.java
@@ -1,8 +1,11 @@
 package org.springblade.mdm.flow.service;
 
+import lombok.AllArgsConstructor;
+import org.flowable.engine.HistoryService;
 import org.flowable.engine.IdentityService;
 import org.flowable.engine.RuntimeService;
 import org.flowable.engine.runtime.ProcessInstance;
+import org.flowable.task.api.history.HistoricTaskInstance;
 import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.mdm.basesetting.machine.MachineService;
 import org.springblade.mdm.basesetting.machine.entity.Machine;
@@ -10,33 +13,38 @@
 import org.springblade.mdm.flow.vo.TaskAssignVO;
 import org.springblade.mdm.program.entity.NcNode;
 import org.springblade.mdm.program.entity.NcProgram;
+import org.springblade.mdm.program.entity.ProcessProgRef;
 import org.springblade.mdm.program.service.NcNodeService;
 import org.springblade.mdm.program.service.NcProgramService;
+import org.springblade.mdm.program.service.ProcessProgRefService;
+import org.springblade.mdm.program.vo.DncSendBackData;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * 鍥哄寲娴佺▼鏈嶅姟
  */
 @Service
+@AllArgsConstructor
 public class CureFlowService {
 
-	@Autowired
-	private RuntimeService runtimeService;
-	@Autowired
-	private AutoAssignUsersService autoAssignUsersService;
-	@Autowired
-	private IdentityService identityService;
+	private final RuntimeService runtimeService;
 
-	@Autowired
-	private NcProgramService ncProgramService;
-	@Autowired
-	private NcNodeService ncNodeService;
-	@Autowired
-	private MachineService machineService;
+	private final HistoryService historyService;
+
+	private final IdentityService identityService;
+
+	private final NcProgramService ncProgramService;
+
+	private final MachineService machineService;
+
+	private final ProcessProgRefService processProgRefService;
 	/**
 	 * 鍥哄寲娴佺▼鐨刱ey
 	 */
@@ -47,24 +55,87 @@
 	 * @param programId 绋嬪簭id
 	 */
 	public void start(long programId){
+
+
+		//pinst.getProcessInstanceId();
+		int a=1;
+		//log.info()
+	}
+
+	@Transactional
+	public void startCure(List<NcProgram> programs) {
+		//DncSendBackData sendBackData;
+		//List<Long> ncProgramIdList = dataList.stream().map(DncSendBackData::getId).toList();
+		//Map<String,List<NcProgram>> groupedProgram = groupProgramsByMachineCode(ncProgramIdList);
+		//List<NcProgram> programs = ncProgramService.listByIds(ncProgramIdList);
+		//鏍规嵁鍒嗙粍鍚姩娴佺▼锛屽苟鎻掑叆鍏宠仈琛�
+		programs.forEach(this::startOne);
+	}
+
+	/**
+	 * 鍚姩涓�涓暟鎺х▼搴忕殑鍥哄寲娴佺▼
+	 * @param prog 鏁版帶绋嬪簭瀹炰綋
+	 */
+	void startOne(NcProgram prog){
 		Map<String, Object> vars = new HashMap<>();
-		NcProgram prog = ncProgramService.getById(programId);
-		NcNode progNode = ncNodeService.getById(programId);
-		Machine machine = machineService.getByCode(progNode.getMachineCode());
-		vars.put("machineCode",machine.getCode());
+
+		//NcProgram prog = programs.get(0);
+		Machine machine = machineService.getByCode(prog.getMachineCode());
+		vars.put("machineCode",prog.getMachineCode());
 		vars.put("machineMode",machine.getName());
 		vars.put("processEdition",prog.getProcessEdition());
-		vars.put("programId",programId);
-		vars.put("program",progNode);
 
+		//璇ョ▼搴忓湪璁″垝浠诲姟鏃� 鑾峰彇缂栧埗锛屾牎瀵癸紝瀹℃壒鐨勪汉鍛橈紝浣滀负榛樿鐢ㄦ埛锛屽叾涓紪鍒舵椂绗竴涓浐瀹氱殑鐢ㄦ埛
+		ProcessProgRef preRef = processProgRefService.lastDispatchDataByNcProgramId(prog.getId());
+		//鑾峰彇瀹℃壒鐢ㄦ埛
+		List<HistoricTaskInstance> historicTasks = historyService.createHistoricTaskInstanceQuery()
+			.processInstanceId(preRef.getProcessInstanceId())
+			.orderByHistoricTaskInstanceEndTime().desc()
+			.list();
+
+		String programmer = null;
+		String checker = null;
+		String senior = null;
+
+		for (HistoricTaskInstance task : historicTasks) {
+			// 鑾峰彇浠诲姟鐨勫姙鐞嗕汉
+			if(task.getTaskDefinitionKey().equals("programmingTask")){
+				//缂栧埗
+				programmer = task.getAssignee();
+			}else if(task.getTaskDefinitionKey().equals("check")){
+				//鏍″
+				checker = task.getAssignee();
+			}else if(task.getTaskDefinitionKey().equals("senior")){
+				//瀹℃牳
+				senior = task.getAssignee();
+			}
+
+		}
+		vars.put("programmer",programmer);
+		vars.put("checker",checker);
+		vars.put("senior",senior);
 
 		String businessKey = "0";//涓氬姟琛╧ey
 
 		identityService.setAuthenticatedUserId(String.valueOf(AuthUtil.getUserId()));//璁剧疆娴佺▼鍙戣捣浜�
 		ProcessInstance pinst = runtimeService.startProcessInstanceByKey(PROCESS_KEY,businessKey,vars);
 
-		int a=1;
-		//log.info()
+		ProcessProgRef ref = new ProcessProgRef();
+		ref.setProcessInstanceId(pinst.getId());
+		ref.setNcProgramId(prog.getId());
+
+		processProgRefService.save(ref);
+
 	}
 
+	/**
+	 * 灏嗙▼搴忔寜鐓ф満鍣ㄤ唬鐮佸垎缁�
+	 * @param ncProgramIdList
+	 * @return
+	 */
+	/*
+	Map<String,List<NcProgram>> groupProgramsByMachineCode(List<Long> ncProgramIdList){
+		List<NcProgram> programs = ncProgramService.listByIds(ncProgramIdList);
+		return programs.stream().collect(Collectors.groupingBy(NcProgram::getMachineCode));
+	}*/
 }
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/task/cure/CureFinishOperateTask.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/task/cure/CureFinishOperateTask.java
new file mode 100644
index 0000000..78864a6
--- /dev/null
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/task/cure/CureFinishOperateTask.java
@@ -0,0 +1,19 @@
+package org.springblade.mdm.flow.task.cure;
+
+import lombok.extern.slf4j.Slf4j;
+import org.flowable.engine.delegate.DelegateExecution;
+import org.springblade.mdm.program.entity.NcProgram;
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@Component("cureFinishOperateTask")
+public class CureFinishOperateTask {
+
+	public void execute(DelegateExecution execution) {
+		//鍥哄寲绋嬪簭妫�鏌ユ湁鏁堟湡锛�
+		String hasCuredProgram =  (String)execution.getVariable("hasCuredProgram");
+		NcProgram ncProgram =  (NcProgram)execution.getVariable("curedNcProgram");
+
+		System.out.println("鎵ц鍥哄寲绋嬪簭浠诲姟鏈嶅姟");
+	}
+}
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/controller/DncSendBackController.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/controller/DncSendBackController.java
index a5bb5b7..8a48d27 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/controller/DncSendBackController.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/controller/DncSendBackController.java
@@ -33,7 +33,7 @@
 @Slf4j
 public class DncSendBackController {
 
-	private final DncSendBackService dncSendBackService;
+	//private final DncSendBackService dncSendBackService;
 	private final NcProgramExchangeService ncProgramExchangeService;
 	/**
 	 * 涓婁紶DNC鍥炰紶鏂囦欢
@@ -42,30 +42,29 @@
 	 */
 	@PostMapping("upload")
 	@ApiOperationSupport(order = 1)
-	@Operation(summary = "DNC鍥炰紶鏂囦欢瀵煎叆锛屼笂浼犳枃浠�", description = "涓婁紶DNC鍥炰紶鏂囦欢")
-	public R<Void> dncSendBackUpload(@RequestParam MultipartFile file) {
+	@Operation(summary = "DNC鍥炰紶鏂囦欢瀵煎叆锛屼笂浼犳枃浠�", description = "涓婁紶DNC鍥炰紶鏂囦欢,骞惰繑鍥炶В鏋愮粨鏋�")
+	public R<List<DncSendBackData>> dncSendBackUpload(@RequestParam MultipartFile file) {
 		try {
-			ncProgramExchangeService.dncSendBackUpload(file);
+			return R.data(ncProgramExchangeService.dncSendBackUpload(file));
 		}catch (Exception e){
 			log.error("瀵煎叆閿欒",e);
 			return R.fail(e.getMessage());
 		}
-		return R.success();
 	}
-
+	/*
 	@Operation(summary = "dnc鍥炰紶鏁版嵁鍒嗛〉", description = "dnc鍥炰紶鏁版嵁鍒嗛〉")
 	@GetMapping("/page")
 	public R<IPage<DncSendBackData>> page(Query query) {
 		IPage<DncSendBackData> pages = ncProgramExchangeService.dncSendBackPageQuery(query);
 		return R.data(pages);
 	}
-
+	*/
 	@PostMapping("accept")
 	@ApiOperationSupport(order = 2)
-	@Operation(summary = "DNC鍥炰紶鏁版嵁鍏ュ簱", description = "鍏ュ簱锛屽悓鏃跺惎鍔ㄥ浐鍖栨祦绋�")
+	@Operation(summary = "DNC鍥炰紶鏁版嵁鍏ュ簱", description = "鍏ュ簱锛屽悓鏃跺惎鍔ㄥ浐鍖栨祦绋�,鍏ュ弬涓轰笂浼犳槸瑙f瀽鐨勬暟鎹垪琛�")
 	public R<Void> dncSendBackAccept(@RequestParam String ids) {
 		try {
-			dncSendBackService.dncFileAccept(ids);
+			ncProgramExchangeService.dncFileAccept(ids);
 		}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/NcProgramExportDNCController.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/controller/NcProgramExportDNCController.java
index 90f6c17..5321f90 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/controller/NcProgramExportDNCController.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/controller/NcProgramExportDNCController.java
@@ -13,6 +13,7 @@
 import org.springblade.core.tool.api.R;
 import org.springblade.mdm.commons.vo.IdsVO;
 import org.springblade.mdm.program.service.NcProgramApprovedService;
+import org.springblade.mdm.program.service.NcProgramExportDNCService;
 import org.springblade.mdm.program.service.NcProgramService;
 import org.springblade.mdm.program.vo.NcNodeProgramQueryVO;
 import org.springblade.mdm.program.vo.NcProgramExportDncPageVO;
@@ -37,6 +38,7 @@
 
 	private final NcProgramService ncProgramService;
 	private final NcProgramApprovedService ncProgramApprovedService;
+	private final NcProgramExportDNCService ncProgramExportDNCService;
 	@Operation(summary = "绋嬪簭瀵煎嚭DNC鍒嗛〉鏌ヨ", description = "鍒嗛〉鏌ヨ锛屼緵鐢ㄦ埛閫夋嫨鏁版嵁")
 	@GetMapping("/export-dnc-page")
 	public R<IPage<NcProgramExportDncPageVO>> page(NcProgramExportDncQueryVO query) {
@@ -51,7 +53,7 @@
 			throw new ServiceException("鏈�夋嫨鏂囦欢瀵煎嚭");
 		}
 		try {
-			ncProgramApprovedService.exportDnc(vo.getIds(),response.getOutputStream());
+			ncProgramExportDNCService.exportDnc(vo.getIds(),response.getOutputStream());
 		} catch (IOException e) {
 			log.error("瀵煎嚭DNC寮傚父", e);
 			throw new RuntimeException(e);
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/entity/NcProgramExchange.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/entity/NcProgramExchange.java
index 5e8d91e..484ed0f 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/entity/NcProgramExchange.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/entity/NcProgramExchange.java
@@ -12,7 +12,17 @@
 @Getter
 @TableName("mdm_nc_program_exchange")
 public class NcProgramExchange extends BizEntity {
+	/**
+	 * 绋嬪簭鍚嶇О
+	 */
 	private String name;
+	/**
+	 * 浜ゆ崲绫诲瀷,1:涓嬪彂;2:鍥哄寲(dnc鍥炰紶)
+	 */
 	private int exchangeType;
+	/**
+	 * 鏁版帶绋嬪簭id
+	 */
+	private Long ncProgramId;
 
 }
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
index db55b9c..2a93aba 100644
--- 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
@@ -7,16 +7,19 @@
 
 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;
 
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/DncSendBackService.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/DncSendBackService.java
index 8e4d686..8a9381d 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/DncSendBackService.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/DncSendBackService.java
@@ -13,9 +13,9 @@
 import java.util.List;
 
 /**
- * 宸ヤ綔娴佹湇鍔″疄鐜扮被
+ * DNC鍥炰紶
  *
- * @author Chill
+ * @author yangys
  */
 @Slf4j
 @Service
@@ -28,30 +28,7 @@
 
 
 
-	/**
-	 * 鍏ュ簱鍥炰紶鏂囦欢,骞跺惎鍔ㄥ浐鍖栨祦绋�
-	 * @param ids
-	 * @return
-	 */
-	public void dncFileAccept(String ids) {
-		List<Long> idList = Func.toLongList(ids);
-		NcProgramExchange exchange;
-		//NcProgram program;
-		NcNode programNode;
 
-		for (Long id : idList) {
-			exchange = ncProgramExchangeMapper.selectById(id);
-			exchange.setStatus(2);//宸插叆搴撶姸鎬�
-			programNode = ncNodeService.getLastProgramNode(exchange.getName());
-
-			//濡傛灉鏄凡缁忓浐鍖栫殑鍒欎笉闇�瑕佸惎鍔ㄦ祦绋�
-			//鍚姩鍥哄寲娴佺▼
-			if(programNode.getIsCured() !=1) {//鏈浐鍖栫殑绋嬪簭锛屽惎鍔ㄥ浐鍖栨祦绋�
-				cureFlowService.start(programNode.getId());
-			}
-		}
-
-	}
 
 
 }
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcProgramApprovedService.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcProgramApprovedService.java
index 3b5791f..4fa1d83 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcProgramApprovedService.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcProgramApprovedService.java
@@ -63,190 +63,7 @@
 
 	}
 
-	/**
-	 * 瀵煎嚭dnc
-	 * @param approvedIdArr 寰呭鍑哄鎵硅〃id鏁扮粍
-	 */
-	public void exportDnc(Long[] approvedIdArr, OutputStream os) throws IOException {
-		ZipOutputStream zipOut = new ZipOutputStream(os);
 
-		ArrayList<Long> programIdList = new ArrayList<Long>();
 
-		for (Long approvedId : approvedIdArr) {
-			NcProgramApproved approved = this.getById(approvedId);
-			programIdList.add(approved.getNcProgramId());
-
-			NcProgram prog = progService.getById(approved.getNcProgramId());
-
-			String filename = prog.getOssName();
-			InputStream inputStream = ossTemplate.statFileStream(filename);
-
-			addInputStreamToZip(zipOut, inputStream, prog.getName());
-
-		}
-		addDataJson(zipOut, programIdList);
-
-	}
-
-	/**
-	 * 瀵煎叆鏁版嵁鏂囦欢
-	 * @param zipOut
-	 */
-	void addDataJson(ZipOutputStream zipOut, List<Long> programIdList) throws IOException {
-		addProgramDataJson(zipOut, programIdList);
-		addApproveRecordDataJson(zipOut, programIdList);
-
-		addNcNodeDataJson(zipOut, programIdList);
-	}
-
-	/**
-	 * 瀵煎叆绋嬪簭璁板綍
-	 * @param zipOut
-	 * @param programIdList
-	 */
-	void addProgramDataJson(ZipOutputStream zipOut, List<Long> programIdList) throws IOException {
-		LambdaQueryWrapper<NcProgram> queryWrapper = new LambdaQueryWrapper<>();
-		queryWrapper.in(NcProgram::getId, programIdList);
-		List<NcProgram> programList = progService.list(queryWrapper);
-		JSONArray jsonArray = new JSONArray();
-		for(NcProgram program : programList){
-			JSONObject recObj = new JSONObject();
-			recObj.put("id", program.getId());
-			recObj.put("code", program.getCode());
-			recObj.put("ossName",program.getOssName());
-			recObj.put("isTextFile",program.getIsTextFile());
-			recObj.put("category",program.getCategory());
-			recObj.put("description",program.getDescription());
-			recObj.put("name",program.getName());
-			recObj.put("partNo",program.getPartNo());
-			recObj.put("ncNodeId",program.getNcNodeId());
-			recObj.put("url",program.getUrl());
-			recObj.put("isCured",program.getIsCured());
-			recObj.put("isLocked",program.getIsLocked());
-			recObj.put("isTest",program.getIsTest());
-			recObj.put("machineCode",program.getMachineCode());
-			recObj.put("processEdition",program.getProcessEdition());
-			recObj.put("taskAssignTime",program.getTaskAssignTime());
-
-			addSuperProperties(recObj,program);
-
-			jsonArray.add(recObj);
-		}
-		addInputStreamToZip(zipOut,new ByteArrayInputStream(jsonArray.toJSONString().getBytes(StandardCharsets.UTF_8)),"exp_mdm_nc_program.json");
-
-	}
-
-	/**
-	 * 瀵煎叆瀹℃壒璁板綍
-	 * @param zipOut
-	 * @param programIdList
-	 */
-	void addApproveRecordDataJson(ZipOutputStream zipOut, List<Long> programIdList) throws IOException {
-		LambdaQueryWrapper<ApproveRecord> queryWrapper = new LambdaQueryWrapper<>();
-		queryWrapper.in(ApproveRecord::getNcProgramId, programIdList);
-		List<ApproveRecord> records = approvedService.list(queryWrapper);
-		JSONArray jsonArray = new JSONArray();
-		for(ApproveRecord record : records){
-			JSONObject recObj = new JSONObject();
-			recObj.put("id", record.getId());
-			recObj.put("comment", record.getComment());
-			recObj.put("userId",record.getUserId());
-			recObj.put("userNickname",record.getUserNickname());
-			recObj.put("operateTime",record.getOperateTime());
-			recObj.put("operateResult",record.getOperateResult());
-			recObj.put("taskName",record.getTaskName());
-			recObj.put("ncProgramId",record.getNcProgramId());
-			recObj.put("processInstanceId",record.getProcessInstanceId());
-
-			addSuperProperties(recObj,record);
-
-			jsonArray.add(recObj);
-		}
-		addInputStreamToZip(zipOut,new ByteArrayInputStream(jsonArray.toJSONString().getBytes(StandardCharsets.UTF_8)),"exp_mdm_approve_record.json");
-
-	}
-
-	/**
-	 * 瀵煎叆鑺傜偣
-	 * @param zipOut
-	 * @param programIdList
-	 */
-	void addNcNodeDataJson(ZipOutputStream zipOut, List<Long> programIdList) throws IOException {
-		LambdaQueryWrapper<NcProgram> queryWrapper = new LambdaQueryWrapper<>();
-		queryWrapper.in(NcProgram::getId, programIdList);
-
-		List<NcProgram> programs = progService.list(queryWrapper);
-		JSONArray jsonArray = new JSONArray();
-
-		ArrayList<Long> exportNodeIdList 	= new ArrayList<>();
-		for(NcProgram program : programs){
-			JSONObject recObj = new JSONObject();
-			if(!exportNodeIdList.contains(program.getNcNodeId())){
-				exportNodeIdList.add(program.getNcNodeId());
-			}
-			NcNode ncNode = ncNodeService.getById(program.getNcNodeId());
-
-			if(StringUtils.isNotEmpty(ncNode.getParentIds())){
-				List<Long> pids = Func.toLongList(ncNode.getParentIds());
-				for(Long nodeId : pids){
-					if(!exportNodeIdList.contains(nodeId)){
-						exportNodeIdList.add(nodeId);
-					}
-				}
-
-			}
-
-		}
-
-		LambdaQueryWrapper<NcNode> nodeQueryWrapper = new LambdaQueryWrapper<>();
-		nodeQueryWrapper.in(NcNode::getId, exportNodeIdList);
-		List<NcNode> nodeList =ncNodeService.list(nodeQueryWrapper);
-		for(NcNode node : nodeList){
-			JSONObject recObj = new JSONObject();
-
-			recObj.put("id", node.getId());
-			recObj.put("nodeType", node.getNodeType());
-			recObj.put("machineCode",node.getMachineCode());
-			recObj.put("parentId",node.getParentId());
-			recObj.put("description",node.getDescription());
-			recObj.put("name",node.getName());
-			recObj.put("remark",node.getRemark());
-			recObj.put("partNo",node.getPartNo());
-			recObj.put("parentIds",node.getParentIds());
-			recObj.put("processName",node.getProcessName());
-
-			addSuperProperties(recObj,node);
-
-			jsonArray.add(recObj);
-		}
-		addInputStreamToZip(zipOut,new ByteArrayInputStream(jsonArray.toJSONString().getBytes(StandardCharsets.UTF_8)),"exp_mdm_nc_node.json");
-	}
-
-	void addSuperProperties(JSONObject recObj, BizEntity entity){
-		recObj.put("tenantId",entity.getTenantId());
-		recObj.put("createTime",entity.getCreateTime());
-		recObj.put("updateTime",entity.getUpdateTime());
-		recObj.put("createUser",entity.getCreateUser());
-		recObj.put("updateUser",entity.getUpdateUser());
-		recObj.put("status",entity.getStatus());
-		recObj.put("createDept",entity.getCreateDept());
-	}
-
-	public void addInputStreamToZip(ZipOutputStream zipOut, InputStream inputStream, String entryName)
-		throws IOException {
-		// 鍒涘缓鏂扮殑 ZIP 鏉$洰
-		ZipEntry zipEntry = new ZipEntry(entryName);
-		zipOut.putNextEntry(zipEntry);
-
-		// 灏嗚緭鍏ユ祦鍐欏叆 ZIP 杈撳嚭娴�
-		byte[] buffer = new byte[1024];
-		int length;
-		while ((length = inputStream.read(buffer)) >= 0) {
-			zipOut.write(buffer, 0, length);
-		}
-
-		// 鍏抽棴褰撳墠鏉$洰
-		zipOut.closeEntry();
-	}
 }
 
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcProgramExchangeService.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcProgramExchangeService.java
index d4c2b6a..7ead897 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcProgramExchangeService.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcProgramExchangeService.java
@@ -1,16 +1,25 @@
 
 package org.springblade.mdm.program.service;
 
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.digest.DigestUtils;
 import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
+import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
 import org.apache.commons.compress.archivers.zip.ZipFile;
 import org.apache.commons.compress.utils.SeekableInMemoryByteChannel;
+import org.apache.commons.io.IOUtils;
 import org.springblade.core.mp.base.BizServiceImpl;
 import org.springblade.core.mp.support.Condition;
 import org.springblade.core.mp.support.Query;
 import org.springblade.core.tool.utils.FileUtil;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.core.tool.utils.IoUtil;
+import org.springblade.mdm.flow.service.CureFlowService;
+import org.springblade.mdm.program.entity.NcProgram;
 import org.springblade.mdm.program.entity.NcProgramExchange;
 import org.springblade.mdm.program.mapper.NcProgramExchangeMapper;
 import org.springblade.mdm.program.vo.DncSendBackData;
@@ -23,10 +32,8 @@
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.List;
+import java.time.LocalDateTime;
+import java.util.*;
 
 /**
  * 绋嬪簭浜ゆ崲锛坉nc瀵煎叆/瀵煎嚭锛�
@@ -37,30 +44,26 @@
 @Service
 @AllArgsConstructor
 public class NcProgramExchangeService extends BizServiceImpl<NcProgramExchangeMapper, NcProgramExchange> {
-
+	private final CureFlowService cureFlowService;
+	private final NcProgramService ncProgramService;
 	/**
-	 * dnc鍥炰紶鏂囦欢涓婁紶
-	 * @param file 鏂囦欢
+	 * dnc鍥炰紶鏂囦欢涓婁紶锛堣В鏋愬悗淇濆瓨鍏pload琛級
+	 * @param file DNC鍥炰紶鏂囦欢
 	 * @return
 	 */
 	public List<DncSendBackData> dncSendBackUpload(MultipartFile file) {
-		List<DncSendBackData> list ;
+		List<DncSendBackData> list;
 		try {
-			String fileName = file.getOriginalFilename();
-			//InputStream fileInputStream = file.getInputStream();
-			InputStream zipFileInputStream = FileExchangeUtil.convertFileToZip(file.getInputStream());
+			//String fileName = file.getOriginalFilename();
+			//InputStream zipFileInputStream = FileExchangeUtil.convertFileToZip(file.getInputStream());
+			InputStream zipFileInputStream = file.getInputStream();//test
+
 			byte[] bytes = FileUtil.copyToByteArray(zipFileInputStream);
 			list = parseDncZipFromByteArray(bytes);
-			for(DncSendBackData dncSendBackData:list){
-				NcProgramExchange exchange=new NcProgramExchange();
-				exchange.setName(dncSendBackData.getProgramName());
-				exchange.setStatus(1);//宸插鍏�
-				this.save(exchange);
 
-			}
 
 		} catch (IOException e) {
-			log.error("涓婁紶dnc鏂囦欢澶辫触",e);
+			log.error("涓婁紶dnc鍥炰紶鏂囦欢澶辫触",e);
 			list = Collections.emptyList();
 		}
 		return list;
@@ -92,90 +95,93 @@
 		return tempFile.toFile();
 	}
 	public static List<DncSendBackData> parseDncZipFromByteArray(byte[] zipData) throws IOException {
-		//List<DncSendBackData> datas = new ArrayList<>();
-		List<DncSendBackData> datas  = ZipFileDirectoryScanner.getFilesInDirectoryRecursive(zipData, "");
+		List<DncSendBackData> list = new ArrayList<>();
+		//List<DncSendBackData> datas  = ZipFileDirectoryScanner.getFilesInDirectoryRecursive(zipData, "");
 
-
-
-		/*
-		try (ByteArrayInputStream bis = new ByteArrayInputStream(zipData);
-			 ZipArchiveInputStream zis = new ZipArchiveInputStream(bis)) {
-
+		Map<String,String> fileMd5Map = new HashMap<>();
+		Map<String,DncSendBackData> fileDataMap = new HashMap<>();
+		try (SeekableInMemoryByteChannel channel = new SeekableInMemoryByteChannel(zipData);
+			 ZipFile zipFile = new ZipFile(channel)) {
 
 			ZipArchiveEntry entry;
-			while ((entry = zis.getNextZipEntry()) != null) {
+			Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();
+			while (entries.hasMoreElements()) {
+			//while ((entry = zis.getNextZipEntry()) != null) {
+				entry = entries.nextElement();
 				DncSendBackData prog = new DncSendBackData();
-				prog.setProgramName(entry.getName());
+				String entryName = entry.getName();
+
 				if (!entry.isDirectory()) {
+					//鐩存帴瑙f瀽绋嬪簭鐨刯son鏂囦欢
+					if(entryName.equals(NcProgramExportDNCService.PROGRAM_JSON_FILE)){
+
+						try (InputStream inputStream = zipFile.getInputStream(entry)) {
+							String jsonStr = IoUtil.readToString(inputStream);
+
+							JSONArray jsonArray = JSONArray.parseArray(jsonStr);
+							for(int i=0;i<jsonArray.size();i++){
+								JSONObject jsonObject = jsonArray.getJSONObject(i);
+								DncSendBackData d = new DncSendBackData();
+								d.setProgramName(jsonObject.getString("name"));
+								d.setId(jsonObject.getLong("id"));
+								d.setProgramNo(jsonObject.getString("code"));
+								d.setFileBackTime(LocalDateTime.now());//鍒拌揪鏃堕棿
+
+								fileDataMap.put(d.getProgramName(),d);
+								list.add(d);
+							}
+
+						}
+					}else{
+						try (InputStream inputStream = zipFile.getInputStream(entry)) {
+							fileMd5Map.put(entryName,DigestUtils.md5Hex(inputStream));//鑾峰彇鏂囦欢MD5
+						}
+
+					}
 					System.out.println("鏂囦欢鍚�: " + entry.getName());
 					System.out.println("澶у皬: " + entry.getSize());
 
 					// 璇诲彇鏂囦欢鍐呭鍒板瓧鑺傛暟缁�
 					ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
-					IOUtils.copy(zis, outputStream);
-					byte[] fileContent = outputStream.toByteArray();
 
-					// 澶勭悊鏂囦欢鍐呭...
-					System.out.println("鍐呭闀垮害: " + fileContent.length);
-				}else{
-					//鏂囦欢澶癸紝璇诲唴閮ㄦ枃浠讹紝鑾峰彇鏂囦欢鍒楄〃
-
-					System.out.println("鏂囦欢澶圭▼搴忥細"+entry.getName());
-					List<String> children = new ArrayList<>();
-					prog.setChildren(children);
 				}
 
-				datas.add(prog);
 			}
 
-
-		}*/
-		return datas;
+		}
+		//璁剧疆md5鍊�
+		fileDataMap.forEach((k,v)->{
+			if(fileMd5Map.containsKey(k)){
+				v.setMd5(fileMd5Map.get(k));
+			}
+		});
+		return list;
 	}
+
+
 	/**
-	 * 绋嬪簭涓嬪彂缁熻鍒嗛〉鏌ヨ
-	 * @param query 鏌ヨ鍙傛暟
+	 * 鍏ュ簱鍥炰紶鏂囦欢,骞跺惎鍔ㄥ浐鍖栨祦绋�
+	 * @param ids id鍒楄〃閫楀彿鍒嗛殧
 	 * @return
 	 */
+	public void dncFileAccept(String ids) {
+		List<Long> idList = Func.toLongList(ids);
+		List<NcProgram> progList = ncProgramService.listByIds(idList);
+		NcProgramExchange exchange;
+		//NcProgram program;
+		//NcNode programNode;
 
-	public IPage<DncSendBackData> dncSendBackPageQuery(Query query) {
+		for(NcProgram prog:progList){
+			exchange = new NcProgramExchange();
+			exchange.setName(prog.getName());
+			exchange.setExchangeType(2);//鍥炰紶
+			exchange.setNcProgramId(prog.getId());
 
-		IPage<DncSendBackData> page = this.getBaseMapper().dncSendBackpageQuery(Condition.getPage(query),query);
+			this.save(exchange);
 
-		return page;
-
-	}
-}
-
-
-class ZipFileDirectoryScanner {
-
-	public static List<DncSendBackData> getFilesInDirectoryRecursive(byte[] zipData, String dirPath) throws IOException {
-		List<DncSendBackData> list = new ArrayList<>();
-
-		if (!dirPath.endsWith("/")) {
-			dirPath += "/";
 		}
 
-		try (SeekableInMemoryByteChannel channel = new SeekableInMemoryByteChannel(zipData);
-			 ZipFile zipFile = new ZipFile(channel)) {
+		cureFlowService.startCure(progList);
 
-			Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();
-			while (entries.hasMoreElements()) {
-				ZipArchiveEntry entry = entries.nextElement();
-				String entryName = entry.getName();
-				DncSendBackData d = new DncSendBackData();
-				d.setProgramName(entryName);
-				if(entry.isDirectory()){
-					d.setHasChildren(true);
-				}
-				list.add(d);
-
-				//if (entryName.startsWith(dirPath) && !entry.isDirectory()) {
-				//	fileList.add(entryName);
-				//}
-			}
-		}
-		return list;
 	}
 }
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 88f5aa2..69849a5 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
@@ -1,27 +1,41 @@
 
 package org.springblade.mdm.program.service;
 
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
 import org.apache.commons.compress.archivers.zip.ZipFile;
 import org.apache.commons.compress.utils.SeekableInMemoryByteChannel;
+import org.apache.commons.lang3.StringUtils;
+import org.springblade.core.mp.base.BizEntity;
 import org.springblade.core.mp.base.BizServiceImpl;
 import org.springblade.core.mp.support.Condition;
 import org.springblade.core.mp.support.Query;
+import org.springblade.core.oss.OssTemplate;
 import org.springblade.core.tool.utils.FileUtil;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.mdm.flow.entity.ApproveRecord;
+import org.springblade.mdm.flow.service.ApproveRecordService;
+import org.springblade.mdm.program.entity.NcNode;
+import org.springblade.mdm.program.entity.NcProgram;
+import org.springblade.mdm.program.entity.NcProgramApproved;
 import org.springblade.mdm.program.entity.NcProgramExchange;
 import org.springblade.mdm.program.mapper.NcProgramExchangeMapper;
 import org.springblade.mdm.program.vo.DncSendBackData;
 import org.springframework.stereotype.Service;
 import org.springframework.web.multipart.MultipartFile;
 
-import java.io.IOException;
-import java.io.InputStream;
+import java.io.*;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
 
 /**
  * 涓嬪彂/鍥炰紶绋嬪簭缁熻
@@ -32,8 +46,13 @@
 @Service
 @AllArgsConstructor
 public class NcProgramExportDNCService extends BizServiceImpl<NcProgramExchangeMapper, NcProgramExchange> {
+	private final NcProgramService progService;
+	private final NcProgramApprovedService approvedService;
+	private final ApproveRecordService approveRecordService;
+	private final NcNodeService ncNodeService;
+	private final OssTemplate ossTemplate;
 
-
+	public static final String PROGRAM_JSON_FILE = "exp_mdm_nc_program.json";
 	/**
 	 * 鍒嗛〉鏌ヨ
 	 * @param query 鏌ヨ鍙傛暟
@@ -46,5 +65,195 @@
 		return page;
 
 	}
+
+
+	/**
+	 * 瀵煎嚭dnc鍘嬬缉鍖�
+	 * @param approvedIdArr 寰呭鍑哄鎵硅〃id鏁扮粍
+	 */
+	public void exportDnc(Long[] approvedIdArr, OutputStream os) throws IOException {
+		//FileOutputStream fos = new FileOutputStream("d:/exportDnc.zip");
+		try (ZipOutputStream zipOut = new ZipOutputStream(os);) {//os
+
+			ArrayList<Long> programIdList = new ArrayList<Long>();
+
+			for (Long approvedId : approvedIdArr) {
+				NcProgramApproved approved = approvedService.getById(approvedId);
+				programIdList.add(approved.getNcProgramId());
+
+				NcProgram prog = progService.getById(approved.getNcProgramId());
+
+				String filename = prog.getOssName();
+				InputStream inputStream = ossTemplate.statFileStream(filename);
+
+				addInputStreamToZip(zipOut, inputStream, prog.getName());
+
+			}
+			addDataJson(zipOut, programIdList);
+		}
+
+	}
+
+
+	/**
+	 * 瀵煎叆鏁版嵁鏂囦欢
+	 * @param zipOut
+	 */
+	void addDataJson(ZipOutputStream zipOut, List<Long> programIdList) throws IOException {
+		addProgramDataJson(zipOut, programIdList);
+		addApproveRecordDataJson(zipOut, programIdList);
+
+		addNcNodeDataJson(zipOut, programIdList);
+	}
+
+	/**
+	 * 瀵煎叆绋嬪簭璁板綍
+	 * @param zipOut
+	 * @param programIdList
+	 */
+	void addProgramDataJson(ZipOutputStream zipOut, List<Long> programIdList) throws IOException {
+		LambdaQueryWrapper<NcProgram> queryWrapper = new LambdaQueryWrapper<>();
+		queryWrapper.in(NcProgram::getId, programIdList);
+		List<NcProgram> programList = progService.list(queryWrapper);
+		JSONArray jsonArray = new JSONArray();
+		for(NcProgram program : programList){
+			JSONObject recObj = new JSONObject();
+			recObj.put("id", program.getId());
+			recObj.put("code", program.getCode());
+			recObj.put("ossName",program.getOssName());
+			recObj.put("isTextFile",program.getIsTextFile());
+			recObj.put("category",program.getCategory());
+			recObj.put("description",program.getDescription());
+			recObj.put("name",program.getName());
+			recObj.put("partNo",program.getPartNo());
+			recObj.put("ncNodeId",program.getNcNodeId());
+			recObj.put("url",program.getUrl());
+			recObj.put("isCured",program.getIsCured());
+			recObj.put("isLocked",program.getIsLocked());
+			recObj.put("isTest",program.getIsTest());
+			recObj.put("machineCode",program.getMachineCode());
+			recObj.put("processEdition",program.getProcessEdition());
+			recObj.put("taskAssignTime",program.getTaskAssignTime());
+
+			addSuperProperties(recObj,program);
+
+			jsonArray.add(recObj);
+		}
+		addInputStreamToZip(zipOut,new ByteArrayInputStream(jsonArray.toJSONString().getBytes(StandardCharsets.UTF_8)),PROGRAM_JSON_FILE);
+
+	}
+
+	/**
+	 * 瀵煎叆瀹℃壒璁板綍
+	 * @param zipOut
+	 * @param programIdList
+	 */
+	void addApproveRecordDataJson(ZipOutputStream zipOut, List<Long> programIdList) throws IOException {
+		LambdaQueryWrapper<ApproveRecord> queryWrapper = new LambdaQueryWrapper<>();
+		queryWrapper.in(ApproveRecord::getNcProgramId, programIdList);
+		List<ApproveRecord> records = approveRecordService.list(queryWrapper);
+		JSONArray jsonArray = new JSONArray();
+		for(ApproveRecord record : records){
+			JSONObject recObj = new JSONObject();
+			recObj.put("id", record.getId());
+			recObj.put("comment", record.getComment());
+			recObj.put("userId",record.getUserId());
+			recObj.put("userNickname",record.getUserNickname());
+			recObj.put("operateTime",record.getOperateTime());
+			recObj.put("operateResult",record.getOperateResult());
+			recObj.put("taskName",record.getTaskName());
+			recObj.put("ncProgramId",record.getNcProgramId());
+			recObj.put("processInstanceId",record.getProcessInstanceId());
+
+			addSuperProperties(recObj,record);
+
+			jsonArray.add(recObj);
+		}
+		addInputStreamToZip(zipOut,new ByteArrayInputStream(jsonArray.toJSONString().getBytes(StandardCharsets.UTF_8)),"exp_mdm_approve_record.json");
+
+	}
+
+	/**
+	 * 瀵煎叆鑺傜偣
+	 * @param zipOut
+	 * @param programIdList
+	 */
+	void addNcNodeDataJson(ZipOutputStream zipOut, List<Long> programIdList) throws IOException {
+		LambdaQueryWrapper<NcProgram> queryWrapper = new LambdaQueryWrapper<>();
+		queryWrapper.in(NcProgram::getId, programIdList);
+
+		List<NcProgram> programs = progService.list(queryWrapper);
+		JSONArray jsonArray = new JSONArray();
+
+		ArrayList<Long> exportNodeIdList 	= new ArrayList<>();
+		for(NcProgram program : programs){
+			JSONObject recObj = new JSONObject();
+			if(!exportNodeIdList.contains(program.getNcNodeId())){
+				exportNodeIdList.add(program.getNcNodeId());
+			}
+			NcNode ncNode = ncNodeService.getById(program.getNcNodeId());
+
+			if(StringUtils.isNotEmpty(ncNode.getParentIds())){
+				List<Long> pids = Func.toLongList(ncNode.getParentIds());
+				for(Long nodeId : pids){
+					if(!exportNodeIdList.contains(nodeId)){
+						exportNodeIdList.add(nodeId);
+					}
+				}
+
+			}
+
+		}
+
+		LambdaQueryWrapper<NcNode> nodeQueryWrapper = new LambdaQueryWrapper<>();
+		nodeQueryWrapper.in(NcNode::getId, exportNodeIdList);
+		List<NcNode> nodeList =ncNodeService.list(nodeQueryWrapper);
+		for(NcNode node : nodeList){
+			JSONObject recObj = new JSONObject();
+
+			recObj.put("id", node.getId());
+			recObj.put("nodeType", node.getNodeType());
+			recObj.put("machineCode",node.getMachineCode());
+			recObj.put("parentId",node.getParentId());
+			recObj.put("description",node.getDescription());
+			recObj.put("name",node.getName());
+			recObj.put("remark",node.getRemark());
+			recObj.put("partNo",node.getPartNo());
+			recObj.put("parentIds",node.getParentIds());
+			recObj.put("processName",node.getProcessName());
+
+			addSuperProperties(recObj,node);
+
+			jsonArray.add(recObj);
+		}
+		addInputStreamToZip(zipOut,new ByteArrayInputStream(jsonArray.toJSONString().getBytes(StandardCharsets.UTF_8)),"exp_mdm_nc_node.json");
+	}
+
+	void addSuperProperties(JSONObject recObj, BizEntity entity){
+		recObj.put("tenantId",entity.getTenantId());
+		recObj.put("createTime",entity.getCreateTime());
+		recObj.put("updateTime",entity.getUpdateTime());
+		recObj.put("createUser",entity.getCreateUser());
+		recObj.put("updateUser",entity.getUpdateUser());
+		recObj.put("status",entity.getStatus());
+		recObj.put("createDept",entity.getCreateDept());
+	}
+
+	public void addInputStreamToZip(ZipOutputStream zipOut, InputStream inputStream, String entryName)
+		throws IOException {
+		// 鍒涘缓鏂扮殑 ZIP 鏉$洰
+		ZipEntry zipEntry = new ZipEntry(entryName);
+		zipOut.putNextEntry(zipEntry);
+
+		// 灏嗚緭鍏ユ祦鍐欏叆 ZIP 杈撳嚭娴�
+		byte[] buffer = new byte[1024];
+		int length;
+		while ((length = inputStream.read(buffer)) >= 0) {
+			zipOut.write(buffer, 0, length);
+		}
+
+		// 鍏抽棴褰撳墠鏉$洰
+		zipOut.closeEntry();
+	}
 }
 
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/ProcessProgRefService.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/ProcessProgRefService.java
index 69cf391..55ce39d 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/ProcessProgRefService.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/ProcessProgRefService.java
@@ -25,6 +25,7 @@
  */
 package org.springblade.mdm.program.service;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.AllArgsConstructor;
@@ -94,11 +95,23 @@
 	}
 
 	/**
-	 * 鏌ヨ娴佺▼鍏宠仈鐨勭▼搴廼浜屾爣
+	 * 鏌ヨ娴佺▼鍏宠仈鐨勭▼搴�
 	 * @param processInstanceId
 	 * @return
 	 */
 	public List<NcProgramVO> listByProcess(String processInstanceId) {
 		return this.getBaseMapper().listByProcess(processInstanceId);
 	}
+
+	/**
+	 *鑾峰彇鏈�鍚庝竴璋冧换鍔″垎娲剧殑鏁版嵁锛屾牴鎹▼搴廼d
+	 * @param ncProgramId 鏁版帶绋嬪簭id
+	 */
+	public ProcessProgRef lastDispatchDataByNcProgramId(Long ncProgramId) {
+		LambdaQueryWrapper<ProcessProgRef> query = Wrappers.lambdaQuery();
+		query.eq(ProcessProgRef::getNcProgramId, ncProgramId).orderByDesc(ProcessProgRef::getCreateTime).last("LIMIT 10");;
+
+		List<ProcessProgRef> list = this.list(query);
+		return list.isEmpty() ? null : list.get(0);
+	}
 }
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/vo/DncSendBackData.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/vo/DncSendBackData.java
index 473f2cf..d9654ff 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/vo/DncSendBackData.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/vo/DncSendBackData.java
@@ -11,8 +11,9 @@
 @Getter
 @Schema(description = "DNC鍥炰紶鏁版嵁")
 public class DncSendBackData {
-	@Schema(description = "鏂囦欢鏁版嵁搴撶紪鍙�")
+	@Schema(description = "鏂囦欢鏁版嵁搴撶紪鍙�(鏁版帶绋嬪簭鐨刬d)")
 	private Long id;
+
 	@Schema(description = "绋嬪簭缂栧彿")
 	private String programNo;
 	@Schema(description = "绋嬪簭鍚嶇О")
diff --git a/blade-service/blade-mdm/src/main/resources/processesbpmn/program-cure.bpmn20.xml b/blade-service/blade-mdm/src/main/resources/processesbpmn/program-cure.bpmn20.xml
index f253164..50220a9 100644
--- a/blade-service/blade-mdm/src/main/resources/processesbpmn/program-cure.bpmn20.xml
+++ b/blade-service/blade-mdm/src/main/resources/processesbpmn/program-cure.bpmn20.xml
@@ -2,18 +2,18 @@
 <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:flowable="http://flowable.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.flowable.org/processdef">
   <process id="program-cure" name="鍥哄寲娴佺▼" isExecutable="true">
     <startEvent id="sid-abe970b9-1bee-49a1-91b4-1184c47c10b7"/>
-    <userTask id="cureProgramTask" name="鍥哄寲缂栧埗"/>
+    <userTask id="cureProgramTask" name="鍥哄寲缂栧埗" flowable:assignee="${programmer}"/>
     <sequenceFlow id="sid-910649a5-8dac-48a2-b42d-9f1132d61b26" sourceRef="cureProgramTask" targetRef="cureProgramTask"/>
     <sequenceFlow id="sid-09c7cf44-bb1a-40f4-b231-919afae5c02f" sourceRef="sid-abe970b9-1bee-49a1-91b4-1184c47c10b7" targetRef="cureProgramTask"/>
     <endEvent id="end" name="鍥哄寲缁撴潫"/>
-    <userTask id="seniorApproveTask" name="楂樺笀瀹℃牳"/>
+    <userTask id="seniorApproveTask" name="楂樺笀瀹℃牳" flowable:assignee="${assignee}"/>
     <sequenceFlow id="sid-8dd21f02-ac10-4318-b897-19b4cdc558c7" sourceRef="cureProgramTask" targetRef="cureCheckTask">
       <conditionExpression>${approve=='Y'}</conditionExpression>
     </sequenceFlow>
     <sequenceFlow id="sid-504610fe-2b87-4df4-8f42-f10c8bf3ce01" sourceRef="seniorApproveTask" targetRef="cureOKOperateTask">
       <conditionExpression>${approve=='Y'</conditionExpression>
     </sequenceFlow>
-    <userTask id="cureCheckTask" name="鍥哄寲鏍″"/>
+    <userTask id="cureCheckTask" name="鍥哄寲鏍″" flowable:assignee="${assignee}"/>
     <sequenceFlow id="sid-b4ad2b36-5fcc-4449-924b-55b0425b1278" sourceRef="cureCheckTask" targetRef="cureProgramTask">
       <conditionExpression>${approve=='N'</conditionExpression>
     </sequenceFlow>
@@ -27,7 +27,7 @@
     <sequenceFlow id="sid-c04cc547-0baf-4514-8056-54b1612cdefd" sourceRef="seniorApproveTask" targetRef="cureCheckTask">
       <conditionExpression>${approve=='N'}</conditionExpression>
     </sequenceFlow>
-    <serviceTask id="cureOKOperateTask" flowable:exclusive="true" name="鍥哄寲澶勭悊浠诲姟">
+    <serviceTask id="cureOKOperateTask" flowable:exclusive="true" name="鍥哄寲澶勭悊浠诲姟" flowable:expression="cureFinishOperateTask.execute(execution)">
       <documentation>璁剧疆鏁版嵁鐨勫浐鍖栨爣蹇楋紝鐢熸垚鍥哄寲绋嬪簭鍒楄〃</documentation>
     </serviceTask>
     <sequenceFlow id="sid-253f5be1-3275-47d6-a3a1-5d1eaf01ec79" sourceRef="cureOKOperateTask" targetRef="end"/>
diff --git a/doc/sql/mdm/mdm.mysql.all.create.sql b/doc/sql/mdm/mdm.mysql.all.create.sql
index eada037..1218e1d 100644
--- a/doc/sql/mdm/mdm.mysql.all.create.sql
+++ b/doc/sql/mdm/mdm.mysql.all.create.sql
@@ -186,6 +186,7 @@
   `id` bigint NOT NULL,
   `tenant_id` varchar(6) DEFAULT NULL COMMENT '鎵�灞炵鎴�',
   `name` varchar(100) NOT NULL COMMENT '绋嬪簭鍚嶇О',
+  `nc_program_id` bigint DEFAULT NULL COMMENT '绋嬪簭鏂囦欢id',
   `status` int DEFAULT NULL COMMENT '涓氬姟鐘舵��',
   `exchange_type` int DEFAULT NULL COMMENT '浜ゆ崲绫诲瀷,1:涓嬪彂;2:鍥哄寲(dnc鍥炰紶)',
   `create_dept` bigint DEFAULT NULL COMMENT '鍒涘缓鍗曚綅',

--
Gitblit v1.9.3