From c903c1606a9c9e58d2b12adea1d7f5c775cca041 Mon Sep 17 00:00:00 2001
From: yangys <y_ys79@sina.com>
Date: 星期四, 07 八月 2025 19:25:37 +0800
Subject: [PATCH] 替换流程基本实现

---
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/constants/FlowContants.java                 |    6 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/mapper/ReplaceProgramFileMapper.java        |   10 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/mapper/ReplaceProgramMapper.xml             |   13 +
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/ReplaceProgramFileService.java      |  218 +++++++++++++++++++
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcNodeAutoCreateService.java     |    1 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/vo/ReplaceFlowStartVO.java                  |   20 +
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/entity/NcNode.java                       |    3 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/replace/ReplaceFinishListener.java |   74 ++++++
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/controller/ReplaceFlowController.java       |   78 +++++++
 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/flow/entity/ReplaceProgramFile.java              |   35 +++
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcNodeService.java               |    2 
 blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/ReplaceFlowService.java             |  106 +++++++++
 blade-service/blade-mdm/src/main/resources/processesbpmn/program-replace.bpmn20.xml                        |   89 ++++++++
 14 files changed, 654 insertions(+), 3 deletions(-)

diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/constants/FlowContants.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/constants/FlowContants.java
index b988c37..61a648f 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/constants/FlowContants.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/constants/FlowContants.java
@@ -14,6 +14,11 @@
 	 * 鍥哄寲娴佺▼KEY
 	 */
 	public static final String CURE_PROCESS_KEY = "program-cure";
+	/**
+	 * 绋嬪簭鏇挎崲娴佺▼key
+	 */
+	public static final String REPLACE_PROCESS_KEY = "program-replace";
+
 
 	public static final String TEAM_LEADER = "teamLeader";
 
@@ -83,4 +88,5 @@
 	 * 鏄惁鍦ㄦ湁鏁堟湡鍐呯殑key
 	 */
 	public static final String VALIDITY_PERIOD = "validityPeriod";
+
 }
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/controller/ReplaceFlowController.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/controller/ReplaceFlowController.java
new file mode 100644
index 0000000..3ec3c5a
--- /dev/null
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/controller/ReplaceFlowController.java
@@ -0,0 +1,78 @@
+package org.springblade.mdm.flow.controller;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.flowable.engine.RuntimeService;
+import org.flowable.engine.TaskService;
+import org.flowable.engine.runtime.ProcessInstance;
+import org.flowable.task.api.Task;
+import org.springblade.core.tool.api.R;
+import org.springblade.mdm.flow.constants.FlowContants;
+import org.springblade.mdm.flow.excution.StartDispatcher;
+import org.springblade.mdm.flow.service.ApproveRecordService;
+import org.springblade.mdm.flow.service.FlowProgramFileService;
+import org.springblade.mdm.flow.service.ReplaceFlowService;
+import org.springblade.mdm.flow.service.TaskDispatchService;
+import org.springblade.mdm.flow.service.execute.AbstractFlowCompleteService;
+import org.springblade.mdm.flow.service.execute.DefaultFlowCompleteService;
+import org.springblade.mdm.flow.service.execute.TryFlowCompleteService;
+import org.springblade.mdm.flow.vo.ReplaceFlowStartVO;
+import org.springblade.mdm.flow.vo.TaskAssignVO;
+import org.springblade.mdm.program.service.ProcessProgRefService;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Map;
+
+@Slf4j
+@RestController
+@AllArgsConstructor
+@RequestMapping("/flow/replace")
+@Tag(name = "鏇挎崲娴佺▼", description = "鏇挎崲娴佺▼")
+public class ReplaceFlowController {
+
+	private final StartDispatcher dispatcher;
+
+	private final TaskService taskService;
+	private final RuntimeService runtimeService;
+	private final ProcessProgRefService processProgRefService;
+
+	private final ApproveRecordService approveRecordService;
+	private final FlowProgramFileService flowProgramFileService;
+	private final DefaultFlowCompleteService defaultFlowCompleteService;
+	private final TaskDispatchService taskDispatchService;
+	private final ReplaceFlowService replaceFlowService;
+
+
+	@PostMapping("/prestart")
+	@Operation(summary = "鍑嗗绋嬪簭鏇挎崲娴佺▼", description = "鍑嗗绋嬪簭鏇挎崲娴佺▼锛屾墦寮�鐣岄潰涔嬪墠璋冪敤锛岃皟鐢ㄤ箣鍚庝細鍒濆鍖栨枃浠跺垪琛�")
+	public R<Long> prestart(@Parameter(description = "绋嬪簭鍖呭悕 鑺傜偣鐨刬d") Long nodeId) {
+		long tempId = System.currentTimeMillis();
+		try {
+			replaceFlowService.pre(nodeId,tempId);
+			return R.data(tempId);
+		}catch(Exception e){
+			log.error("棰勫紑濮嬮敊璇�",e);
+			return R.fail(e.getMessage());
+		}
+
+	}
+	/**
+	 * 鍙戣捣鏇挎崲娴佺▼
+	 */
+	@PostMapping("/start")
+	@Operation(summary = "鍙戣捣绋嬪簭鏇挎崲娴佺▼", description = "鍙戣捣绋嬪簭鏇挎崲娴佺▼")
+	public R<Boolean> start(@RequestBody ReplaceFlowStartVO startVO) {
+		try {
+			replaceFlowService.start(startVO);
+			return R.data(true);
+		}catch(Exception e){
+			log.error("鍙戣捣绋嬪簭鏇挎崲閿欒",e);
+			return R.fail(e.getMessage());
+		}
+
+	}
+
+}
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/entity/ReplaceProgramFile.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/entity/ReplaceProgramFile.java
new file mode 100644
index 0000000..1923517
--- /dev/null
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/entity/ReplaceProgramFile.java
@@ -0,0 +1,35 @@
+package org.springblade.mdm.flow.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Getter;
+import lombok.Setter;
+import org.springblade.core.mp.base.BizEntity;
+
+/**
+ * 鏇挎崲娴佺▼娴佺▼绋嬪簭鏂囦欢
+ */
+@Setter
+@Getter
+@TableName("mdm_replace_program_file")
+public class ReplaceProgramFile extends BizEntity {
+
+	private String processInstanceId;
+	/**
+	 * 鏂囦欢鍚� 绗﹀悎鏍煎紡鐨勬枃浠跺悕锛屾鏌ユ枃浠跺悕闇�瑕佹帓闄ゆ墿灞曞悕
+	 */
+	private String name;
+	/**
+	 * oss鏂囦欢鍚�
+	 */
+	private String ossName;
+	/**
+	 * oss鏂囦欢鍚�
+	 */
+	private String programName;
+
+	/**
+	 * 涓庣晫闈氦浜掔殑涓存椂id锛岄娆℃墦寮�鐣岄潰鏃跺彂缁欏墠绔紝鎻愪氦鏃舵彁浜ょ粰鍚庣锛屽悗闈㈠氨娌$敤浜�
+	 */
+	private Long tempId;
+
+}
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/replace/ReplaceFinishListener.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/replace/ReplaceFinishListener.java
new file mode 100644
index 0000000..79347d4
--- /dev/null
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/excution/replace/ReplaceFinishListener.java
@@ -0,0 +1,74 @@
+package org.springblade.mdm.flow.excution.replace;
+
+import lombok.extern.slf4j.Slf4j;
+import org.flowable.engine.RuntimeService;
+import org.flowable.engine.delegate.DelegateExecution;
+import org.springblade.mdm.flow.entity.ApproveRecord;
+import org.springblade.mdm.flow.entity.FlowProgramFile;
+import org.springblade.mdm.flow.service.ApproveRecordService;
+import org.springblade.mdm.flow.service.FlowProgramFileService;
+import org.springblade.mdm.program.entity.NcNode;
+import org.springblade.mdm.program.entity.NcProgramApproved;
+import org.springblade.mdm.program.service.NcNodeService;
+import org.springblade.mdm.program.service.NcProgramApprovedService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * 鏇挎崲瀹屾垚鎵ц鐨勪簨浠讹紝鍔熻兘锛氭彃鍏ュ鎵硅〃鏁版嵁
+ */
+@Slf4j
+@Component("replaceFinishListener")
+public class ReplaceFinishListener {
+	@Autowired
+	private RuntimeService runtimeService;
+	@Autowired
+	private NcProgramApprovedService approvedService;
+	@Autowired
+	private ApproveRecordService approveRecordService;
+	@Autowired
+	private FlowProgramFileService flowProgramFileService;
+
+	@Autowired
+	private NcNodeService ncNodeService;
+	/**
+	 * 鍦ㄦ祦绋嬬粨鏉熸椂鑷姩璋冪敤,锛堥厤缃湪瀹℃壒缁撴潫浜嬩欢鐨別xecutelistener涓簡锛�
+	 * @param execution 鎵ц瀵硅薄
+	 */
+	public void handle(DelegateExecution execution) {
+		// 鎵ц涓氬姟閫昏緫
+		String instId = execution.getProcessInstanceId();
+		log.info("浜嬩欢鍚嶇О{}锛宨nstid={}" , execution.getEventName(),instId);
+
+
+		log.info("娴佺▼宸插畬鎴恑n repalceFinishListener");
+	}
+
+	void updateFlowProgramFile(String instId){
+		List<FlowProgramFile> programFiles =  flowProgramFileService.lambdaQuery().eq(FlowProgramFile::getProcessInstanceId, instId).list();
+		if(!programFiles.isEmpty()) {
+			FlowProgramFile pf = programFiles.get(0);
+			NcProgramApproved approved = new NcProgramApproved();
+			approved.setProgramName(pf.getProgramName());
+
+			NcNode pkgNode = ncNodeService.getProgramPackageByName(pf.getProgramName());
+			if(pkgNode!=null) {
+				approved.setNcNodeId(pkgNode.getId());//绋嬪簭鍖呰妭鐐筰d
+				approvedService.save(approved);
+			}else{
+				log.warn("鏈壘鍒板悕涓簕}鐨勭▼搴忓寘",pf.getProgramName());
+			}
+		}else{
+			log.warn("娌℃湁绋嬪簭鏂囦欢");
+		}
+	}
+
+	void updateApproveRecordNodeId(NcNode pkgNode){
+		//鏇存柊瀹℃壒璁板綍鐨刵cNodeId
+		approveRecordService.lambdaUpdate()
+			.eq(ApproveRecord::getProcessInstanceId, pkgNode.getProcessInstanceId())
+			.set(ApproveRecord::getNcNodeId,pkgNode.getId()).update();
+	}
+}
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/mapper/ReplaceProgramFileMapper.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/mapper/ReplaceProgramFileMapper.java
new file mode 100644
index 0000000..9446499
--- /dev/null
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/mapper/ReplaceProgramFileMapper.java
@@ -0,0 +1,10 @@
+package org.springblade.mdm.flow.mapper;
+
+import org.springblade.core.mp.mapper.BladeMapper;
+import org.springblade.mdm.flow.entity.FlowProgramFile;
+import org.springblade.mdm.flow.entity.ReplaceProgramFile;
+
+public interface ReplaceProgramFileMapper extends BladeMapper<ReplaceProgramFile> {
+
+
+}
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/mapper/ReplaceProgramMapper.xml b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/mapper/ReplaceProgramMapper.xml
new file mode 100644
index 0000000..37455f5
--- /dev/null
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/mapper/ReplaceProgramMapper.xml
@@ -0,0 +1,13 @@
+<?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.flow.mapper.ReplaceProgramFileMapper">
+    <resultMap id="BaseResultMap" type="org.springblade.mdm.flow.entity.ReplaceProgramFile">
+        <id column="id" property="id"/>
+        <result column="status" property="status"/>
+        <result column="create_time" property="createTime"/>
+        <result column="update_time" property="updateTime"/>
+        <result column="is_deleted" property="isDeleted"/>
+    </resultMap>
+
+
+</mapper>
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 1ebab27..372356c 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
@@ -54,6 +54,8 @@
 		programProperties.setProcessEdition(String.valueOf(vars.get(FlowContants.PROCESS_EDITION)));//宸ュ簭鐗堟
 		programProperties.setProcessName(String.valueOf(vars.get(FlowContants.PROCESS_NAME)));
 		programProperties.setMachineCode(String.valueOf(vars.get(FlowContants.MACHINE_CODE)));
+
+		programProperties.setMachineMode(String.valueOf(vars.get(FlowContants.MACHINE_MODE)));
 		//鏁版嵁澶勭悊鍚嶇О涓虹増娆′互鍓嶏紝闆朵欢鍙峰姞宸ュ簭鍙凤細YZL4-1100-01-50 闆剁粍浠跺彿锛歒ZL4-1100-01 宸ュ簭鍙� 50
 
 		programProperties.setCraftEdition(String.valueOf(vars.get(FlowContants.CRAFT_EDITION)));
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
new file mode 100644
index 0000000..8a8c43b
--- /dev/null
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/ReplaceFlowService.java
@@ -0,0 +1,106 @@
+package org.springblade.mdm.flow.service;
+
+import lombok.AllArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
+import org.flowable.engine.IdentityService;
+import org.flowable.engine.RuntimeService;
+import org.flowable.engine.TaskService;
+import org.flowable.engine.runtime.ProcessInstance;
+import org.flowable.task.api.Task;
+import org.simpleframework.xml.core.Replace;
+import org.springblade.core.secure.utils.AuthUtil;
+import org.springblade.mdm.basesetting.machine.MachineService;
+import org.springblade.mdm.basesetting.machine.entity.Machine;
+import org.springblade.mdm.flow.constants.FlowContants;
+import org.springblade.mdm.flow.entity.FlowProgramFile;
+import org.springblade.mdm.flow.entity.ReplaceProgramFile;
+import org.springblade.mdm.flow.vo.ReplaceFlowStartVO;
+import org.springblade.mdm.flow.vo.TaskAssignVO;
+import org.springblade.mdm.program.entity.NcNode;
+import org.springblade.mdm.program.service.NcNodeService;
+import org.springblade.mdm.utils.EntityUtil;
+import org.springframework.beans.BeanUtils;
+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;
+
+@AllArgsConstructor
+@Service
+public class ReplaceFlowService {
+	private final NcNodeService nodeService;
+	private final TaskService taskService;
+	private final RuntimeService runtimeService;
+	private final IdentityService identityService;
+	private final FlowProgramFileService flowProgramFileService;
+	private final ReplaceProgramFileService replaceProgramFileService;
+	private final MachineService machineService;
+	/**
+     * 杞淳锛屽苟璁板綍鑷繁鐨勫娉ㄤ俊鎭�
+	 * @param nodeId 鏇挎崲鐨勮妭鐐筰d
+	 */
+	@Transactional
+	public void pre(long nodeId,long tempId) {
+		List<NcNode> fileNodes = nodeService.lambdaQuery()
+			.eq(NcNode::getParentId, nodeId)
+			.eq(NcNode::getIsLastEdition,1)
+			.eq(NcNode::getNodeType,NcNode.TYPE_PROGRAM_FILE).list();
+		List<Long> fileIds = fileNodes.stream().map(NcNode::getFlowProgramFileId).toList();
+
+		List<FlowProgramFile> programFiles = flowProgramFileService.lambdaQuery()
+			.in(FlowProgramFile::getId, fileIds).list();
+
+		//灏嗙幇鏈夋枃浠跺鍒跺埌鐙珛鐨勮〃涓紝鍚庣画浣滀负瀹℃壒鐨勬枃浠讹紝瀹℃壒鐣岄潰璋冪敤鐨勬帴鍙d篃涓嶅悓锛屾渶濂藉崟鐙紑鍙�
+		for(FlowProgramFile programFile : programFiles) {
+			ReplaceProgramFile replaceProgramFile = new ReplaceProgramFile();
+			BeanUtils.copyProperties(programFile, replaceProgramFile);
+			EntityUtil.clearBaseProperties(replaceProgramFile);
+			replaceProgramFile.setTempId(tempId);
+
+			replaceProgramFileService.save(replaceProgramFile);
+		}
+	}
+
+	/**
+	 * 鍚姩鏇挎崲娴佺▼
+	 */
+	@Transactional
+	public String start(ReplaceFlowStartVO startVO){
+
+		Map<String, Object> vars = new HashMap<>();
+		vars.put(FlowContants.ASSIGNEE,startVO.getAssignee());//绗竴涓鎵圭敤鎴�
+
+		vars.put(FlowContants.TITLE,startVO.getTitle());
+		NcNode programPackge = nodeService.getById(startVO.getNodeId());
+		//鏈哄簥缂栧彿
+		vars.put(FlowContants.MACHINE_CODE,programPackge.getMachineCode());
+		//Machine machine = machineService.getByCode(programPackge.getMachineCode());
+		//鏈哄簥鍨嬪彿
+		//if(machine != null) {
+			//vars.put(FlowContants.MACHINE_MODE, programPackge.getMachineMode());
+		//}
+		vars.put(FlowContants.PROCESS_NO,programPackge.getProcessNo());
+		vars.put(FlowContants.PROCESS_NAME,programPackge.getProcessName());
+		vars.put(FlowContants.PROCESS_EDITION,programPackge.getProcessEdition());
+		vars.put(FlowContants.CRAFT_EDITION,programPackge.getCraftEdition());
+
+		vars.put(FlowContants.DRAWING_NO,programPackge.getDrawingNo());
+		vars.put(FlowContants.DRAWING_NO_EDITION,programPackge.getDrawingNoEdition());
+
+		vars.put(FlowContants.PRODUCT_MODEL,programPackge.getProductModel());
+
+		identityService.setAuthenticatedUserId(String.valueOf(AuthUtil.getUserId()));//璁剧疆娴佺▼鍙戣捣浜�
+		ProcessInstance inst = runtimeService.startProcessInstanceByKey(FlowContants.REPLACE_PROCESS_KEY,"0",vars);
+
+
+		replaceProgramFileService.lambdaUpdate().eq(ReplaceProgramFile::getTempId,startVO.getTempId()).set(ReplaceProgramFile::getProcessInstanceId,inst.getProcessInstanceId());
+
+		return inst.getProcessInstanceId();
+	}
+
+}
+
+
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/ReplaceProgramFileService.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/ReplaceProgramFileService.java
new file mode 100644
index 0000000..a95fc2f
--- /dev/null
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/service/ReplaceProgramFileService.java
@@ -0,0 +1,218 @@
+
+package org.springblade.mdm.flow.service;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.flowable.engine.RuntimeService;
+import org.springblade.core.log.exception.ServiceException;
+import org.springblade.core.mp.base.BizServiceImpl;
+import org.springblade.core.oss.OssTemplate;
+import org.springblade.core.oss.model.BladeFile;
+import org.springblade.core.tool.api.IResultCode;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.mdm.flow.entity.ReplaceProgramFile;
+import org.springblade.mdm.flow.mapper.ReplaceProgramFileMapper;
+import org.springblade.mdm.flow.vo.ProgramUploadVO;
+import org.springblade.mdm.utils.FileContentUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+/**
+ * 娴佺▼绋嬪簭澶勭悊锛屽寘鎷笂浼狅紝鏌ヨ灞曠ず
+ *
+ * @author yangys
+ */
+@Slf4j
+@Service
+public class ReplaceProgramFileService extends BizServiceImpl<ReplaceProgramFileMapper, ReplaceProgramFile> {
+	@Autowired
+	private OssTemplate ossTemplate;
+	@Autowired
+	private RuntimeService runtimeService;
+	@Autowired
+	private FlowCommonService flowCommonService;
+
+	/**
+	 * 涓婁紶绋嬪簭寰愭枃浠讹紙缂栧埗鑺傜偣璋冪敤锛�
+	 * @param uploadVO 涓婁紶瀵硅薄
+	 */
+	public void uploadFlowProgramFile(ProgramUploadVO uploadVO) {
+
+		FlowProgramProperties progProps= flowCommonService.getProgramProperties(uploadVO.getProcessInstanceId());
+		MultipartFile file = uploadVO.getFile();
+		if(file.getSize() == 0){
+			throw new ServiceException("绋嬪簭鏂囦欢涓嶅彲涓虹┖鏂囦欢");
+		}
+		checkFilename(file.getOriginalFilename(),progProps);
+
+		String programName = getProgramName(progProps);
+
+		BladeFile bfile = ossTemplate.putFile(file);
+
+		ReplaceProgramFile progFile = new ReplaceProgramFile();
+		progFile.setName(file.getOriginalFilename());
+		progFile.setOssName(bfile.getName());
+		progFile.setProcessInstanceId(uploadVO.getProcessInstanceId());
+
+		progFile.setProgramName(programName);
+
+		save(progFile);
+
+	}
+
+	/**
+	 * 鑾峰彇绋嬪簭鍚嶇О
+	 * @param progProps
+	 * @return
+	 */
+	String getProgramName(FlowProgramProperties progProps){
+		return progProps.getDrawingNo()+"-"+progProps.getProcessNo();
+	}
+
+	/**
+	 * 妫�鏌ユ枃浠跺悕鍚堟硶鎬�
+	 * @param filename 鏂囦欢鍚�
+	 * @param programProperties 绋嬪簭灞炴�э紝鍙戣捣鏃跺~鍐欑殑
+	 */
+	void checkFilename(String filename,FlowProgramProperties programProperties){
+		//绋嬪簭鍚嶇О锛氶浂浠跺彿鍔犲伐搴忓彿锛屾枃浠跺悕搴旇浠ユ寮�澶�
+		String expectedProgramName = programProperties.getDrawingNo()+"-"+programProperties.getProcessNo();
+		if(!StringUtils.startsWith(filename,expectedProgramName)){
+
+			IResultCode rc = new IResultCode() {
+				@Override
+				public String getMessage() {
+					return "绋嬪簭鏂囦欢鍚嶄笉鍚堟硶锛屽簲涓猴細"+expectedProgramName+"-"+programProperties.getCraftEdition()+"-[娈垫暟]-[娈靛彿].[鏂囦欢鎵╁睍鍚峕";
+				}
+
+				@Override
+				public int getCode() {
+					return 1;
+				}
+			};
+			throw new ServiceException(rc);
+			//throw new ServiceException("绋嬪簭鏂囦欢鍚嶄笉鍚堟硶锛屽簲涓猴細"+expectedProgramName+"-"+programProperties.getCraftEdition()+"-[娈垫暟]-[娈靛彿].[鏂囦欢鎵╁睍鍚峕");
+		}
+
+		//鎴彇鍚庨潰鐨勬鏁板拰绗嚑娈�
+		String endPart = StringUtils.removeStart(filename,expectedProgramName+"-"+programProperties.getCraftEdition()+"-");
+
+		//鍘绘帀鎵╁睍鍚�
+		if(endPart.contains(".")){
+			endPart = endPart.substring(0,endPart.indexOf("."));
+		}
+
+		int sepCount = StringUtils.countMatches(endPart,"-");
+		if(sepCount != 1){//- 鍙峰簲璇ユ槸1涓�
+			IResultCode rc = new IResultCode() {
+				@Override
+				public String getMessage() {
+					return "绋嬪簭鏂囦欢鍚嶄笉鍚堟硶锛屽簲涓猴細"+expectedProgramName+"-"+programProperties.getCraftEdition()+"-[娈垫暟]-[娈靛彿].[鏂囦欢鎵╁睍鍚峕";
+				}
+
+				@Override
+				public int getCode() {
+					return 2;
+				}
+			};
+			throw new ServiceException(rc);
+			//throw new ServiceException("绋嬪簭鏂囦欢鍚嶄笉鍚堟硶锛屽簲涓猴細"+expectedProgramName+"-"+programProperties.getCraftEdition()+"-[娈垫暟]-[娈靛彿].[鏂囦欢鎵╁睍鍚峕");
+		}
+
+		String[] arr = StringUtils.split(endPart,"-");
+		if(!StringUtils.isNumeric(arr[0]) || Func.toInt(arr[0]) >99 || Func.toInt(arr[0]) < 1){
+			IResultCode rc = new IResultCode() {
+				@Override
+				public String getMessage() {
+					return "绋嬪簭娈垫暟涓嶅悎娉曪紝搴斾负涓や綅浠ュ唴鏁存暟";
+				}
+
+				@Override
+				public int getCode() {
+					return 3;
+				}
+			};
+			throw new ServiceException(rc);
+		}
+		int segCount = Func.toInt(arr[0]);
+
+		if(!StringUtils.isNumeric(arr[1]) || Func.toInt(arr[1]) < 1 || Func.toInt(arr[1]) > segCount){
+			IResultCode rc = new IResultCode() {
+				@Override
+				public String getMessage() {
+					return "绋嬪簭娈靛彿涓嶅悎娉曪紝搴斾负涓や綅浠ュ唴鏁存暟涓斿皬浜庣瓑浜庢鏁般��";
+				}
+
+				@Override
+				public int getCode() {
+					return 4;
+				}
+			};
+			throw new ServiceException(rc);
+		}
+	}
+
+	/**
+	 * 鑾峰彇鏂囦欢鍐呭
+	 * @param id 鏂囦欢id
+	 * @return 鏂囦欢鍐呭鏂囨湰
+	 */
+	public String getFileContent(Long id) {
+		String result  ="";
+
+		ReplaceProgramFile programFile = this.getById(id);
+		String fileName = programFile.getOssName();
+		try (InputStream inputStream = ossTemplate.statFileStream(fileName)) {
+			result = FileContentUtil.getContentFromStream(inputStream);
+		} catch (IOException e) {
+			throw new RuntimeException(e);
+		}
+
+		return result;
+	}
+
+	/**
+	 * 楠岃瘉绋嬪簭鏂囦欢鐨勫畬鏁存�э紝浠呭湪缂栧埗鑺傜偣浣跨敤
+	 * @param processInstanceId 娴佺▼瀹炰緥id
+	 */
+	public void checkProgramFiles(String processInstanceId,boolean isPass) {
+		List<ReplaceProgramFile> flowPrograms = this.lambdaQuery().eq(ReplaceProgramFile::getProcessInstanceId, processInstanceId).orderByAsc(ReplaceProgramFile::getCreateTime).list();
+		if(isPass && flowPrograms.isEmpty()){
+			throw new ServiceException("璇蜂笂浼犵▼搴忔枃浠�");
+		}
+		int totalSeg = 0;
+		if(!flowPrograms.isEmpty()){
+			ReplaceProgramFile progFile = flowPrograms.get(0);
+			totalSeg = getProgramSegCount(progFile.getName());
+		}
+
+		if(totalSeg != flowPrograms.size()){
+			throw new ServiceException("搴斾笂浼�"+totalSeg+"娈电▼搴忥紝瀹為檯涓婁紶"+flowPrograms.size()+"娈�");
+		}
+
+
+	}
+
+	/**
+	 * 鏍规嵁鏂囦欢鍚嶈幏鍙栫▼搴忔�绘鏍�
+	 * @param filename 鏂囦欢鍚�
+	 * @return
+	 */
+	int getProgramSegCount(String filename){
+		int idx = filename.lastIndexOf(".");
+		String tempstr = filename.substring(0,idx);//鍘绘帀鎵╁睍鍚�
+		//System.out.println(tempstr);
+		idx = tempstr.lastIndexOf("-");
+		tempstr = tempstr.substring(0,idx);
+		//System.out.println(tempstr);
+		idx = tempstr.lastIndexOf("-");
+		tempstr = tempstr.substring(idx+1);
+		//System.out.println(tempstr);
+		return Func.toInt(tempstr);
+	}
+}
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/vo/ReplaceFlowStartVO.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/vo/ReplaceFlowStartVO.java
new file mode 100644
index 0000000..b82009d
--- /dev/null
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/flow/vo/ReplaceFlowStartVO.java
@@ -0,0 +1,20 @@
+package org.springblade.mdm.flow.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDate;
+
+@Data
+@Schema(description = "鏇挎崲娴佺▼鍙戣捣鏁版嵁")
+public class ReplaceFlowStartVO {
+	@Schema(description = "娴佺▼鏍囬")
+	private String title;
+	@Schema(description = "鏇挎崲鐨勭▼搴忓寘鍚峣d")
+	private Long nodeId;
+	@Schema(description = "涓存椂id,prestart鎺ュ彛鍙戦��")
+	private Long tempId;
+
+	@Schema(description = "澶勭悊浜篿d")
+	private Long assignee;
+}
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/entity/NcNode.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/entity/NcNode.java
index 547aba6..21be89d 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/entity/NcNode.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/entity/NcNode.java
@@ -78,7 +78,6 @@
 	 */
 	private String machineCode;
 
-
 	/**
 	 * 鏂囦欢绫诲瀷锛屽彧鏈�
 	 */
@@ -113,7 +112,7 @@
 	/**
 	 * 鏄惁鍥哄寲
 	 */
-	private Integer isCured;
+	private Integer isCured = 0;
 	/**
 	 * 杩囨湡鏃ユ湡
 	 */
diff --git a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcNodeAutoCreateService.java b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcNodeAutoCreateService.java
index e597920..dd2d8c9 100644
--- a/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcNodeAutoCreateService.java
+++ b/blade-service/blade-mdm/src/main/java/org/springblade/mdm/program/service/NcNodeAutoCreateService.java
@@ -167,6 +167,7 @@
 				ncNode.setProcessName(programProperties.getProcessName());
 				ncNode.setMachineCode(programProperties.getMachineCode());
 				ncNode.setProductModel(programProperties.getProductModel());
+				//ncNode.setMachineMode(programProperties.getMachineMode());
 			}
 
 			ncNode.setIsLastEdition(1);
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 a3cf2ea..05f5f1f 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
@@ -73,7 +73,7 @@
 	 * @return
 	 */
 	public List<NcNodeVO> lazyList(Long parentId) {
-// 鍒ゆ柇鐐瑰嚮鎼滅储浣嗘槸娌℃湁鏌ヨ鏉′欢鐨勬儏鍐�
+		// 鍒ゆ柇鐐瑰嚮鎼滅储浣嗘槸娌℃湁鏌ヨ鏉′欢鐨勬儏鍐�
 		if (Func.isEmpty(parentId)) {
 			parentId = 0L;
 		}
diff --git a/blade-service/blade-mdm/src/main/resources/processesbpmn/program-replace.bpmn20.xml b/blade-service/blade-mdm/src/main/resources/processesbpmn/program-replace.bpmn20.xml
new file mode 100644
index 0000000..b2f295c
--- /dev/null
+++ b/blade-service/blade-mdm/src/main/resources/processesbpmn/program-replace.bpmn20.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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-replace" name="鏇挎崲" isExecutable="true">
+    <startEvent id="sid-0e059345-0bf2-4c18-af59-ee7aeef674c7"/>
+    <endEvent id="replaceApproveEnd" name="閫氳繃缁撴潫">
+        <extensionElements>
+            <flowable:executionListener expression="${replaceFinishListener.handle(execution)}" event="end"/>
+        </extensionElements>
+    </endEvent>
+    <userTask id="repalceCheckTask" name="鏁版帶绋嬪簭鏍″" flowable:assignee="${assignee}"/>
+    <userTask id="repalceProgrammingTask" name="鏁版帶绋嬪簭缂栧啓" flowable:assignee="${assignee}"/>
+    <userTask id="replaceApprove" name="绋嬪簭鏇挎崲瀹℃牳" flowable:assignee="${assignee}"/>
+    <sequenceFlow id="sid-bf9c31fa-f8c4-4ff5-b4d9-ce3cc0bd1fa2" sourceRef="replaceApprove" targetRef="replaceApproveEnd">
+      <conditionExpression>${approve=='Y'}</conditionExpression>
+    </sequenceFlow>
+    <sequenceFlow id="sid-318e94d8-f335-428a-b2a1-81cb2e59993f" sourceRef="repalceProgrammingTask" targetRef="repalceCheckTask">
+      <conditionExpression>${approve=='Y'}</conditionExpression>
+    </sequenceFlow>
+    <sequenceFlow id="sid-ffcf7c0a-7775-45fc-8e0a-368d70522633" sourceRef="repalceCheckTask" targetRef="replaceApprove">
+      <conditionExpression>${approve=='Y'}</conditionExpression>
+    </sequenceFlow>
+    <sequenceFlow id="sid-c4180f0a-6120-4504-96e3-28ddd7975c15" sourceRef="replaceApprove" targetRef="repalceCheckTask">
+      <conditionExpression>${approve=='N'}</conditionExpression>
+    </sequenceFlow>
+    <sequenceFlow id="sid-b78c5f58-0487-4cda-8ed8-0ea581b9e934" sourceRef="repalceCheckTask" targetRef="repalceProgrammingTask">
+      <conditionExpression>${approve=='N'}</conditionExpression>
+    </sequenceFlow>
+    <sequenceFlow id="sid-36e913be-1be9-49d3-a8a3-51aadd0e945c" sourceRef="sid-0e059345-0bf2-4c18-af59-ee7aeef674c7" targetRef="repalceCheckTask"/>
+    <endEvent id="sid-75a8afef-26b1-4dce-9ad9-4a1d4efff08c" name="閫�鍑虹粨鏉�">
+      <extensionElements>
+        <flowable:executionListener expression="${repalceFinishListener.handle(execution)}" event="end"/>
+      </extensionElements>
+    </endEvent>
+    <sequenceFlow id="sid-c86f3a13-5e74-423a-b80d-19ef482eb9e1" sourceRef="repalceProgrammingTask" targetRef="sid-75a8afef-26b1-4dce-9ad9-4a1d4efff08c">
+      <conditionExpression>${approve=='N'}</conditionExpression>
+    </sequenceFlow>
+  </process>
+  <bpmndi:BPMNDiagram id="BPMNDiagram_program-replace">
+    <bpmndi:BPMNPlane bpmnElement="program-replace" id="BPMNPlane_program-replace">
+      <bpmndi:BPMNShape id="shape-8139f243-404a-4d0c-b900-fb128511ff41" bpmnElement="sid-0e059345-0bf2-4c18-af59-ee7aeef674c7">
+        <omgdc:Bounds x="-250.0" y="-70.0" width="30.0" height="30.0"/>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="shape-ad73bcd6-a2b7-41a6-a773-09b8a6e6eb72" bpmnElement="replaceApproveEnd">
+        <omgdc:Bounds x="205.0" y="-70.0" width="30.0" height="30.0"/>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="shape-69fea4e5-2bbd-43d3-9bbb-53342e3d898d" bpmnElement="repalceCheckTask">
+        <omgdc:Bounds x="-137.5" y="-105.0" width="50.000004" height="35.0"/>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="shape-9d186c35-7e72-4cff-99f6-88352cb15b55" bpmnElement="repalceProgrammingTask">
+        <omgdc:Bounds x="-145.0" y="2.5" width="45.0" height="35.0"/>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="shape-bd196b3d-c1ab-4167-a264-7cfc2cf6ec9e" bpmnElement="replaceApprove">
+        <omgdc:Bounds x="60.0" y="-97.5" width="55.0" height="45.0"/>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNEdge id="edge-4f9697eb-c584-4ac0-823c-fc168a8e3ba4" bpmnElement="sid-bf9c31fa-f8c4-4ff5-b4d9-ce3cc0bd1fa2">
+        <omgdi:waypoint x="115.0" y="-75.0"/>
+        <omgdi:waypoint x="205.0" y="-55.0"/>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="edge-a8b88d46-e63b-4e07-a925-73611a824a50" bpmnElement="sid-318e94d8-f335-428a-b2a1-81cb2e59993f">
+        <omgdi:waypoint x="-100.0" y="11.25"/>
+        <omgdi:waypoint x="-112.5" y="-70.0"/>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="edge-6b3872c2-4101-4b9e-9d27-98ee21a6b1b5" bpmnElement="sid-ffcf7c0a-7775-45fc-8e0a-368d70522633">
+        <omgdi:waypoint x="-87.5" y="-96.25"/>
+        <omgdi:waypoint x="60.0" y="-86.25"/>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="edge-701c4cc7-5412-4218-9697-cd6f20f6d281" bpmnElement="sid-c4180f0a-6120-4504-96e3-28ddd7975c15">
+        <omgdi:waypoint x="60.0" y="-63.75"/>
+        <omgdi:waypoint x="-100.0" y="-70.0"/>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="edge-7aa67fcc-b2d7-4419-83e5-9f19eb19dfa5" bpmnElement="sid-b78c5f58-0487-4cda-8ed8-0ea581b9e934">
+        <omgdi:waypoint x="-125.0" y="-70.0"/>
+        <omgdi:waypoint x="-122.5" y="2.5"/>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="edge-e186ed3c-77ce-486e-af9b-8616c97278bb" bpmnElement="sid-36e913be-1be9-49d3-a8a3-51aadd0e945c">
+        <omgdi:waypoint x="-220.0" y="-62.5"/>
+        <omgdi:waypoint x="-137.5" y="-96.25"/>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNShape id="shape-3f281eec-371b-43b4-8b6e-b1985a98b3c6" bpmnElement="sid-75a8afef-26b1-4dce-9ad9-4a1d4efff08c">
+        <omgdc:Bounds x="-10.0" y="5.0" width="30.0" height="30.0"/>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNEdge id="edge-57d6332c-3cbf-48e6-ac07-a81e31a72155" bpmnElement="sid-c86f3a13-5e74-423a-b80d-19ef482eb9e1">
+        <omgdi:waypoint x="-100.0" y="28.75"/>
+        <omgdi:waypoint x="-50.0" y="20.0"/>
+        <omgdi:waypoint x="-10.0" y="12.5"/>
+      </bpmndi:BPMNEdge>
+    </bpmndi:BPMNPlane>
+  </bpmndi:BPMNDiagram>
+</definitions>

--
Gitblit v1.9.3