|
@@ -0,0 +1,936 @@
|
|
|
+package com.zkqy.execution.produce.dispersed.runbpm;
|
|
|
+
|
|
|
+
|
|
|
+import com.alibaba.fastjson2.JSON;
|
|
|
+import com.alibaba.fastjson2.JSONArray;
|
|
|
+import com.alibaba.fastjson2.JSONObject;
|
|
|
+import com.fasterxml.jackson.core.JsonProcessingException;
|
|
|
+import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
+import com.zkqy.common.constant.HttpStatus;
|
|
|
+import com.zkqy.common.core.domain.AjaxResult;
|
|
|
+import com.zkqy.common.utils.DateUtils;
|
|
|
+import com.zkqy.common.utils.SecurityUtils;
|
|
|
+import com.zkqy.common.utils.StringUtils;
|
|
|
+import com.zkqy.common.utils.bpm.XmlDataParserUtils;
|
|
|
+import com.zkqy.common.utils.uuid.IdUtils;
|
|
|
+import com.zkqy.execution.produce.dispersed.entity.*;
|
|
|
+import com.zkqy.execution.produce.dispersed.entity.runbpm.*;
|
|
|
+import com.zkqy.execution.produce.dispersed.mapper.*;
|
|
|
+import com.zkqy.execution.produce.dispersed.service.*;
|
|
|
+import com.zkqy.execution.produce.utils.VerifyExecutionProcess;
|
|
|
+import lombok.val;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.scheduling.annotation.EnableAsync;
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.util.*;
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * 预备执行流程工具类
|
|
|
+ *
|
|
|
+ * @author hanzihang
|
|
|
+ * @date 2023/11/15
|
|
|
+ */
|
|
|
+@Component
|
|
|
+@EnableAsync // 异步
|
|
|
+public class PreExecutionToolClass<R> {
|
|
|
+
|
|
|
+ @Autowired // 执行流程
|
|
|
+ private BpmExecuteProcessMapper runBpmExecuteProcessMapper;
|
|
|
+
|
|
|
+ @Autowired // 执行流程中间表
|
|
|
+ private BpmExecuteNodeMiddleMapper runBpmExecuteNodeMiddleMapper;
|
|
|
+
|
|
|
+ @Autowired // 执行流程节点表
|
|
|
+ private BpmExecuteNodeMapper runBpmExecuteNodeMapper;
|
|
|
+
|
|
|
+ @Autowired // 节点脚本表单中间表
|
|
|
+ private IBpmExecuteNodeFormService iBpmExecuteNodeFormService;
|
|
|
+
|
|
|
+ @Autowired // 执行流程service
|
|
|
+ private IBpmExecuteProcessService iBpmExecuteProcessService;
|
|
|
+
|
|
|
+ @Autowired // 定义流程
|
|
|
+ private BpmProcessMapper bpmProcessMapper;
|
|
|
+
|
|
|
+ @Autowired // 定义流程节点详细信息
|
|
|
+ private BpmProcessConfigurationMapper bpmProcessConfigurationMapper;
|
|
|
+
|
|
|
+ @Autowired // 节点执行用户
|
|
|
+ private BpmNodeHandleUserMapper bpmNodeHandleUserMapper;
|
|
|
+
|
|
|
+ @Autowired // 节点执行脚本
|
|
|
+ private BpmNodeScriptRelevanceMapper bpmNodeScriptRelevanceMapper;
|
|
|
+
|
|
|
+ @Autowired // 真正执行脚本
|
|
|
+ private RunImplementationClass iRunImplementationClass;
|
|
|
+
|
|
|
+ @Autowired // 校验执行流程的数据
|
|
|
+ private VerifyExecutionProcess iVerifyExecutionProcess;
|
|
|
+
|
|
|
+ @Autowired // 节点
|
|
|
+ private BpmExecuteNodeFormMapper executeNodeFormMapper;
|
|
|
+
|
|
|
+ @Autowired // 节点日志
|
|
|
+ private IBpmExecuteNodeLogService iBpmExecuteNodeLogService;
|
|
|
+
|
|
|
+ @Autowired // 审批流程中间表
|
|
|
+ private IBpmApprovalStatusService iBpmApprovalStatusService;
|
|
|
+
|
|
|
+ @Autowired // 通用查询
|
|
|
+ private ICommonService commonService;
|
|
|
+
|
|
|
+ @Autowired // 表单组
|
|
|
+ private IDragFormGroupService iDragFormGroupService;
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 预执行流程、自动执行开始节点
|
|
|
+ *
|
|
|
+ * @param commonEntity
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @Transactional
|
|
|
+ public AjaxResult ReadyToExecute(CommonEntity commonEntity) {
|
|
|
+ // 获取发起流程所需数据
|
|
|
+ IntoProduction intoProduction = this.obtainData(commonEntity);
|
|
|
+ /**
|
|
|
+ * 根据流程key校验当前流程数据的完整性,是否可以运行
|
|
|
+ */
|
|
|
+ // if (!iVerifyExecutionProcess.VerifyProcessData(intoProduction.getTaskProcessKey())) {
|
|
|
+ // return AjaxResult.error(HttpStatus.EXECUTEPROCESS, "流程数据验证失败!");
|
|
|
+ // }
|
|
|
+ /**1️⃣1️⃣1️⃣ 得到当前投产需要执行的流程详细信息*/
|
|
|
+ //--得到当前流程的详细信息
|
|
|
+ BpmProcess bpmProcess = bpmProcessMapper.selectBpmProcessByProcessKey(
|
|
|
+ intoProduction.getTaskProcessKey());
|
|
|
+
|
|
|
+ String taskKey = IdUtils.fastSimpleUUID(); // 得到流程的唯一标识
|
|
|
+ if (bpmProcess.getProcessType().toString().equals("1")) { // 当前被发起的流程是审批类型
|
|
|
+ // 发起审批类型的流程逻辑
|
|
|
+ BpmApprovalStatus bpmApprovalStatus = new BpmApprovalStatus();
|
|
|
+ bpmApprovalStatus.setTableName(intoProduction.getTableName());
|
|
|
+ bpmApprovalStatus.setTableId(intoProduction.getGuid());
|
|
|
+ bpmApprovalStatus.setApprovalState("5");// 当前流程发起后更改数据条状态
|
|
|
+ bpmApprovalStatus.setTaskKey(taskKey);
|
|
|
+ // 新增审批关系表
|
|
|
+ iBpmApprovalStatusService.insertBpmApprovalStatus(bpmApprovalStatus);
|
|
|
+ }
|
|
|
+ //---根据流程key得到当前流程的所有节点信息
|
|
|
+ List<BpmProcessConfiguration> bpmProcessConfigurationList =
|
|
|
+ bpmProcessConfigurationMapper.selectBpmProcessConfigurationList(
|
|
|
+ new BpmProcessConfiguration(intoProduction.getTaskProcessKey()));
|
|
|
+ //----根据节点得到所有节点执行用户以及执行脚本的数据 ⬇⬇⬇⬇⬇⬇
|
|
|
+ List<String> nodekeyList = new ArrayList<>(); // 当前流程所有节点
|
|
|
+ // 根据节点表示得到所有脚本以及所有执行用户信息
|
|
|
+ bpmProcessConfigurationList.forEach(item -> nodekeyList.add(item.getNodeKey()));
|
|
|
+ // 当前流程的所有节点详细信息
|
|
|
+ List<BpmUserScriptVo> bpmUserScriptVoList = new ArrayList<>();
|
|
|
+ // 得到当前流程所有脚本数据
|
|
|
+ List<BpmNodeScriptRelevance> bpmNodeScriptRelevanceList = new ArrayList<>();
|
|
|
+ bpmProcessConfigurationList.forEach(item -> {
|
|
|
+ BpmUserScriptVo bpmUserScriptVo = new BpmUserScriptVo();
|
|
|
+ bpmUserScriptVo.setNodeKey(item.getNodeKey());
|
|
|
+ if (item.getNodeRolePermission() != null) {
|
|
|
+ bpmUserScriptVo.setBpmNodeHandleUserList(bpmNodeHandleUserMapper.selectBpmNodeHandleUserList(new BpmNodeHandleUser(item.getNodeRolePermission())));
|
|
|
+ }
|
|
|
+ // 判断流程类型是否是审批类型
|
|
|
+ // 审批类型默认是没有脚本的
|
|
|
+ // if (bpmProcess.getProcessType().equals("1")) {
|
|
|
+ // bpmNodeScriptRelevanceList.addAll(bpmUserScriptVo.getBpmNodeScriptRelevanceList());
|
|
|
+ // bpmUserScriptVoList.add(bpmUserScriptVo);
|
|
|
+ // } else if (bpmProcess.getProcessType().equals("0")) {
|
|
|
+ //
|
|
|
+ // }、
|
|
|
+
|
|
|
+ // -- 流程节点脚本关联表(一个节点可能会同时存在多个脚本-正常脚本、多个异常脚本)
|
|
|
+ bpmUserScriptVo.setBpmNodeScriptRelevanceList(bpmNodeScriptRelevanceMapper.selectBpmNodeScriptRelevanceList(new BpmNodeScriptRelevance(item.getNodeKey())));
|
|
|
+ bpmNodeScriptRelevanceList.addAll(bpmUserScriptVo.getBpmNodeScriptRelevanceList());
|
|
|
+ bpmUserScriptVoList.add(bpmUserScriptVo);
|
|
|
+ });
|
|
|
+ Map<String, String> shunxu = XmlDataParserUtils.getStartNodeAndNextNode(bpmProcess.getProcessXmlContent());
|
|
|
+ /**2️⃣2️⃣2️⃣ 新增执行流程表数据*/
|
|
|
+ BpmExecuteProcess runBpmExecuteProcess = new BpmExecuteProcess();
|
|
|
+ // 当前流程启动的唯一标识
|
|
|
+ runBpmExecuteProcess.setTaskKey(taskKey);
|
|
|
+ // 当前流程名称
|
|
|
+ runBpmExecuteProcess.setTaskProcessName(bpmProcess.getProcessName());
|
|
|
+ // 投产数据条的唯一标识
|
|
|
+ runBpmExecuteProcess.setTaskPlanKey(intoProduction.getGuid().split("=")[1]);
|
|
|
+ // 当前流程任务名称
|
|
|
+ runBpmExecuteProcess.setTaskName("");
|
|
|
+ // 定义表中的流程别名
|
|
|
+ runBpmExecuteProcess.setTaskProcessKey(bpmProcess.getProcessKey());
|
|
|
+ // 定义表中的流程xml标签内容
|
|
|
+ runBpmExecuteProcess.setTaskProcessXmlContent(bpmProcess.getProcessXmlContent());
|
|
|
+ // 启动流程的状态 默认:0 正常 1暂停 2弃用
|
|
|
+ runBpmExecuteProcess.setTaskProcessState(0L);
|
|
|
+ // 当前任务流程的版本注释
|
|
|
+ runBpmExecuteProcess.setTaskProcessNote(bpmProcess.getNote());
|
|
|
+ // 流程类型
|
|
|
+ runBpmExecuteProcess.setTaskProcessType(bpmProcess.getProcessType().toString());
|
|
|
+ // 当前流程执行节点
|
|
|
+ runBpmExecuteProcess.setTaskNodeKey(shunxu.get("startNode"));
|
|
|
+ // 当前流程需要执行的下一个节点
|
|
|
+ runBpmExecuteProcess.setTaskNodeNextKey(shunxu.get("nextNode"));
|
|
|
+ // 执行默认值
|
|
|
+ runBpmExecuteProcess.setDelFlag("0");
|
|
|
+ // *****替换当前执行流程的任务唯一标识
|
|
|
+ intoProduction.setTaskProcessKey(runBpmExecuteProcess.getTaskKey());
|
|
|
+ runBpmExecuteProcess.setCreateById(SecurityUtils.getUserId());
|
|
|
+ runBpmExecuteProcess.setCreateTime(new Date());
|
|
|
+ runBpmExecuteProcess.setCreateBy(SecurityUtils.getUsername());
|
|
|
+ // 执行新增方法
|
|
|
+ runBpmExecuteProcessMapper.insertBpmExecuteProcess(runBpmExecuteProcess);
|
|
|
+ // 新增计划表中绑定任务key编码
|
|
|
+
|
|
|
+
|
|
|
+ /**3️⃣3️⃣3️⃣ 插入所有预执行节点*/
|
|
|
+ List<BpmExecuteNode> runBpmExecuteNodeList = new ArrayList<>();
|
|
|
+ bpmProcessConfigurationList.forEach(item -> {
|
|
|
+ BpmExecuteNode bpmExecuteNode = new BpmExecuteNode();
|
|
|
+ bpmExecuteNode.setTaskProcessKey(runBpmExecuteProcess.getTaskKey());
|
|
|
+ bpmExecuteNode.setTaskNodeKey(item.getNodeKey());
|
|
|
+ bpmExecuteNode.setTaskNodeName(item.getNodeName());
|
|
|
+ bpmExecuteNode.setTaskNodeFormType(item.getNodeFormType());
|
|
|
+ bpmExecuteNode.setTaskNodeFormKey(item.getNodeFormKey()); // 单前节点绑定的表单
|
|
|
+ bpmExecuteNode.setTaskNodeType(item.getNodeType());
|
|
|
+ bpmExecuteNode.setTaskNodeBefore(item.getNodeBefore());
|
|
|
+ bpmExecuteNode.setTaskNodeAfter(item.getNodeAfter());
|
|
|
+ bpmExecuteNode.setTaskNodeRolePermission(item.getNodeRolePermission());
|
|
|
+ bpmExecuteNode.setTaskRemark(item.getRemark());
|
|
|
+ bpmExecuteNode.setTaskNodeState("0"); // 状态默认未执行
|
|
|
+ bpmExecuteNode.setTaskPriority("1"); // 任务优先级 设计是从排产操作时选中的任务优先级
|
|
|
+ bpmExecuteNode.setTaskNodeExecuteType(item.getNodeExecuteType()); // 当前节点上是手动执行还是自动执行 true || false
|
|
|
+ bpmExecuteNode.setTask3(item.getSpare3()); // 审批节点后操作列
|
|
|
+ runBpmExecuteNodeList.add(bpmExecuteNode);
|
|
|
+ });
|
|
|
+ runBpmExecuteNodeMapper.insertBpmExecuteNodeList(runBpmExecuteNodeList);
|
|
|
+ /**3️⃣3️⃣3️⃣ 执行流程任务所有关联数据执行用户、执行脚本等*/
|
|
|
+ List<BpmExecuteNodeMiddle> runBpmExecuteNodeMiddleList = new ArrayList<>();
|
|
|
+ int index = 0;
|
|
|
+ // bpmUserScriptVoList 当前节点的所有执行用户脚本
|
|
|
+ bpmUserScriptVoList.forEach(item -> {
|
|
|
+ BpmExecuteNodeMiddle bpmExecuteNodeMiddle = new BpmExecuteNodeMiddle();
|
|
|
+ // 任务流程编码
|
|
|
+ bpmExecuteNodeMiddle.setTaskProcessKey(runBpmExecuteProcess.getTaskKey());
|
|
|
+ // 节点标识
|
|
|
+ bpmExecuteNodeMiddle.setTaskNodeKey(item.getNodeKey());
|
|
|
+ // 节点执行角色编码
|
|
|
+ if (item.getBpmNodeHandleUserList() != null) {
|
|
|
+ bpmExecuteNodeMiddle.setTaskRealRole(item.getBpmNodeHandleUserList().get(index).getRealRole());
|
|
|
+ }
|
|
|
+ // 节点执行用户id
|
|
|
+ if (item.getBpmNodeHandleUserList() != null) {
|
|
|
+ bpmExecuteNodeMiddle.setTaskExecuteUserNo(item.getBpmNodeHandleUserList().get(index).getExecuteUserNo());
|
|
|
+ }
|
|
|
+ // 节点手动触发脚本
|
|
|
+ List<String> script0 = new ArrayList<>(), script1 = new ArrayList<>(), script2 = new ArrayList<>();// 异常手动触发 // 正常自动触发 // 节点前后自动触发
|
|
|
+ item.getBpmNodeScriptRelevanceList().forEach(stem -> {
|
|
|
+ if (stem.getNodeKey().contains(item.getNodeKey())) {
|
|
|
+ // ⚠️⚠️⚠️ 0L 异常手动触发 1L 正常自动触发 2L 节点前后自动触发
|
|
|
+ if (stem.getScriptTriggerType() == 0L) {
|
|
|
+ script0.add(stem.getScriptKey());
|
|
|
+ } else if (stem.getScriptTriggerType() == 1L) {
|
|
|
+ script1.add(stem.getScriptKey());
|
|
|
+ } else if (stem.getScriptTriggerType() == 2L) {
|
|
|
+ script1.add(stem.getScriptKey());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ // 手动异常触发脚本
|
|
|
+ bpmExecuteNodeMiddle.setTaskArtificialScriptKey(script0.toString().replaceAll("\\[", "").replaceAll("\\]", ""));
|
|
|
+ // 正常节点自动触发脚本
|
|
|
+ bpmExecuteNodeMiddle.setTaskAutomaticScriptTriggerType(script1.toString().replaceAll("\\[", "").replaceAll("\\]", ""));
|
|
|
+ // 节点前后触发脚本
|
|
|
+ bpmExecuteNodeMiddle.setTaskNodeAroundScriptKey(script2.toString().replaceAll("\\[", "").replaceAll("\\]", ""));
|
|
|
+ // 追加节点中间表list
|
|
|
+ runBpmExecuteNodeMiddleList.add(bpmExecuteNodeMiddle);
|
|
|
+ });
|
|
|
+ List<BpmExecuteNodeMiddle> endrunBpmExecuteNodeMiddleList = new ArrayList<>();
|
|
|
+ runBpmExecuteNodeMiddleList.forEach(item -> {
|
|
|
+ String taskArtificialScriptKey = "";
|
|
|
+ String asd[] = item.getTaskArtificialScriptKey().split(",");
|
|
|
+ for (String s : asd) {
|
|
|
+ taskArtificialScriptKey += s.trim() + ",";
|
|
|
+ }
|
|
|
+ item.setTaskArtificialScriptKey(taskArtificialScriptKey.substring(0, taskArtificialScriptKey.lastIndexOf(",")));
|
|
|
+ endrunBpmExecuteNodeMiddleList.add(item);
|
|
|
+ });
|
|
|
+ runBpmExecuteNodeMiddleMapper.insertBpmExecuteNodeMiddleList(endrunBpmExecuteNodeMiddleList);
|
|
|
+ //**3️⃣⚡️5️⃣ 流程任务当中的所有节点关联的表单信息 得到当前流程的所有节点以及当前节点脚本绑定的异常脚本-》处理当前节点脚本、异常脚本绑定的表单到中间表信息 */
|
|
|
+ List<BpmExecuteNodeForm> bpmExecuteNodeFormList = new ArrayList<>();
|
|
|
+ // 当前流程的正常节点、异常节点(理论上无论什么节点都会绑定一个表单)
|
|
|
+ Map<String, String> nodeMap = new HashMap<>();
|
|
|
+ Map<String, BpmProcessConfiguration> nodeInfo = new HashMap<>();
|
|
|
+ bpmProcessConfigurationList.forEach(item -> {
|
|
|
+ if (item.getNodeType().equals("startEvent")) {
|
|
|
+ nodeMap.put("startNodeKey", item.getNodeKey());
|
|
|
+ } else if (item.getNodeType().equals("endEvent")) {
|
|
|
+ nodeMap.put("endNodeKey", item.getNodeKey());
|
|
|
+ }
|
|
|
+ nodeInfo.put(item.getNodeKey(), item);
|
|
|
+ });
|
|
|
+ bpmNodeScriptRelevanceList.forEach(item -> {
|
|
|
+ if (item.getNodeKey().equals(nodeMap.get("startNodeKey")) || item.getNodeKey().equals(nodeMap.get("endNodeKey"))) {
|
|
|
+ // 开始结束节点不做记录
|
|
|
+ } else
|
|
|
+ // 0=:异常脚本;1:正常脚本 2:节点前后自动 节点前后执行的脚本是没有表单的
|
|
|
+ if (item.getScriptTriggerType() != 2L) {
|
|
|
+ BpmExecuteNodeForm bpmExecuteNodeForm = new BpmExecuteNodeForm();
|
|
|
+ bpmExecuteNodeForm.setTaskProcessKey(intoProduction.getTaskProcessKey());
|
|
|
+ bpmExecuteNodeForm.setTaskNodeKey(item.getNodeKey());
|
|
|
+ bpmExecuteNodeForm.setTaskScriptKey(item.getScriptKey());
|
|
|
+ bpmExecuteNodeForm.setTaskNodeName(item.getScriptNodeName());
|
|
|
+ if (item.getScriptTriggerType() == 1L) { // 正常节点脚本
|
|
|
+ // bpmProcessConfigurationList
|
|
|
+ bpmExecuteNodeForm.setTaskNodeFormKey(nodeInfo.get(item.getNodeKey()).getNodeFormKey());
|
|
|
+ bpmExecuteNodeForm.setTaskNodeFormType(nodeInfo.get(item.getNodeKey()).getNodeFormType());
|
|
|
+ // bpmExecuteNodeForm.setTaskNodeFromContent();
|
|
|
+ } else if (item.getScriptTriggerType() == 0L) { // 异常脚本
|
|
|
+ bpmExecuteNodeForm.setTaskNodeFormKey(item.getFormKey());
|
|
|
+ bpmExecuteNodeForm.setTaskNodeFormType(item.getScriptNodeFormType());
|
|
|
+ // bpmExecuteNodeForm.setTaskNodeFromContent();
|
|
|
+ }
|
|
|
+ bpmExecuteNodeFormList.add(bpmExecuteNodeForm);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ // 得到当前流程所有的表单类型
|
|
|
+ Map<String, String> nodeFrom = iBpmExecuteNodeFormService.selectNodeFromInfos(commonEntity.getCommMap().get("process_key").toString());
|
|
|
+ // 得到当前表单的所有信息
|
|
|
+ Map<String, Object> nodeFromInfoMap = this.getNodeFormInfos(nodeFrom);
|
|
|
+
|
|
|
+ bpmExecuteNodeFormList.forEach(item -> {
|
|
|
+ item.setTaskNodeFormContent(nodeFromInfoMap.get(item.getTaskNodeFormKey()).toString());
|
|
|
+ });
|
|
|
+ // 最终提交新增 bpmExecuteNodeFormList
|
|
|
+ bpmExecuteNodeFormList.forEach(item -> {
|
|
|
+ iBpmExecuteNodeFormService.insertBpmExecuteNodeForm(item);
|
|
|
+ });
|
|
|
+ // iBpmExecuteNodeFormService
|
|
|
+ /**4️⃣4️⃣4️⃣ 调用执行节点接口 预执行当前投产流程的开始节点,执行开始节点*/
|
|
|
+ // bpmUserScriptVoList 节点key对应的脚本
|
|
|
+ // 根据节点类型startEvent 筛选得到当前流程的开始节点,进行自动执行 // startEvent 开始节点类型
|
|
|
+ Optional<BpmProcessConfiguration> optionalStartNode = bpmProcessConfigurationList.stream().filter(item -> item.getNodeType().equals("startEvent")).findFirst();
|
|
|
+ // 找到开始节点进行记录
|
|
|
+ runBpmExecuteNodeList.forEach(itme -> {
|
|
|
+ if (itme.getTaskNodeType().equals("startEvent")) {
|
|
|
+ BpmExecuteNodeLog bpmExecuteNodeLog = new BpmExecuteNodeLog(itme);
|
|
|
+ iBpmExecuteNodeLogService.insertBpmExecuteNodeLog(bpmExecuteNodeLog);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ // 0L:表示工业类型 1L表示审批类型
|
|
|
+ if (bpmProcess.getProcessType() == 1L) return AjaxResult.success();
|
|
|
+ if (optionalStartNode.isPresent()) {
|
|
|
+ // optionalStartNode.get().getNodeKey(); 当前流程开始节点key
|
|
|
+ Optional<BpmUserScriptVo> optionalBpmUserScriptVo = bpmUserScriptVoList.stream().filter(item -> item.getNodeKey().equals(optionalStartNode.get().getNodeKey())).findFirst();
|
|
|
+ if (optionalBpmUserScriptVo.isPresent()) {
|
|
|
+ // 得到当前节点需要执行的脚本 只需执行自动执行的脚本即可
|
|
|
+ List<BpmNodeScriptRelevance> scriptAutoList = optionalBpmUserScriptVo.get().getBpmNodeScriptRelevanceList();
|
|
|
+ scriptAutoList.removeIf(item -> item.getScriptTriggerType() == 0L); // 删除异常脚本
|
|
|
+ IScriptEntity iScriptEntity = new IScriptEntity();
|
|
|
+ iScriptEntity.setImplementationName(scriptAutoList.get(0).getScriptKey());
|
|
|
+ iScriptEntity.setScriptNodeKey(optionalBpmUserScriptVo.get().getNodeKey());
|
|
|
+ if (!iRunImplementationClass.RunScriptImplementationClassLogicCode(iScriptEntity, intoProduction)) {
|
|
|
+ // 判断脚本执行状态
|
|
|
+ return AjaxResult.error(HttpStatus.SCRIPTEXCEPTION, "脚本执行异常!");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 数据出现问题
|
|
|
+ return AjaxResult.error(HttpStatus.EXECUTEPROCESS, "流程开始节点数据异常!");
|
|
|
+ }
|
|
|
+ /**5️⃣5️⃣5️⃣ 执行结果返回前端*/
|
|
|
+ return AjaxResult.success();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 执行流程节点共通接口
|
|
|
+ *
|
|
|
+ * @param bpmRunNodeVo
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @Transactional
|
|
|
+ public AjaxResult executionNode(BpmRunNodeVo bpmRunNodeVo) {
|
|
|
+ String taskProcessKey = bpmRunNodeVo.getTaskProcessKey(); // 任务流程编码
|
|
|
+ String taskNodeKey = bpmRunNodeVo.getTaskNodeKey(); // 任务节点编码
|
|
|
+ // 得到当前节点的所有信息-》用于执行节点前后绑定的自动运行的脚本
|
|
|
+ BpmExecuteNode currentBpmExecuteNode = runBpmExecuteNodeMapper.queryBpmExecuteNodeBytaskNodeKey(taskProcessKey, taskNodeKey);
|
|
|
+
|
|
|
+ // 在执行节时得到除当前节点绑定的正常脚本外,有可能会绑定自动执行的脚本(这些自动执行的脚本参数不能确定,无法传递)
|
|
|
+ BpmExecuteNodeMiddle bpmExecuteNodeMiddle = runBpmExecuteNodeMiddleMapper.queryBpmExecuteNodeMiddleByTaskNodeKey(taskProcessKey, taskNodeKey);
|
|
|
+ String script[] = bpmExecuteNodeMiddle.getTaskNodeAroundScriptKey().split(","); // 得到当前节点需要自动执行的脚本
|
|
|
+ //--- 1️⃣1️⃣1️⃣执行节点前绑定的脚本🚀🚀🚀~!!!
|
|
|
+ System.err.println("--- 1️⃣1️⃣1️⃣执行节点前绑定的脚本🚀🚀🚀~!!!");
|
|
|
+ if (currentBpmExecuteNode.getTaskNodeBefore().equals("true")) {
|
|
|
+ // 调用执行脚本接口
|
|
|
+ if (script != null && script.length != 0 && !script[0].isEmpty()) {
|
|
|
+ for (int i = 0; i < script.length; i++) {
|
|
|
+ // 节点执行必要的参数
|
|
|
+ IScriptEntity iScriptEntity = new IScriptEntity();
|
|
|
+ iScriptEntity.setScriptFlowKey(taskProcessKey);
|
|
|
+ iScriptEntity.setScriptNodeKey(taskNodeKey);
|
|
|
+ iScriptEntity.setImplementationName(script[i]);
|
|
|
+ // 调用执行脚本方法
|
|
|
+ if (!iRunImplementationClass.RunScriptImplementationClassLogicCode(iScriptEntity, bpmRunNodeVo)) {
|
|
|
+ // 判断脚本执行状态
|
|
|
+ return AjaxResult.error(HttpStatus.SCRIPTEXCEPTION, "节点前脚本执行失败!");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //--- 2️⃣2️⃣2️⃣执行节点绑定的正常脚本🚀🚀🚀~!!!
|
|
|
+ System.err.println("--- 2️⃣2️⃣2️⃣执行节点绑定的正常脚本🚀🚀🚀~!!!");
|
|
|
+ IRunBPMEntity iRunBPMEntity = new IRunBPMEntity();
|
|
|
+ iRunBPMEntity.setImplementationName(bpmRunNodeVo.getImplementationName());
|
|
|
+ iRunBPMEntity.setExecutionFlowKey(taskProcessKey);
|
|
|
+ iRunBPMEntity.setExecutionNodeKey(taskNodeKey);
|
|
|
+ iRunBPMEntity.setExecutionMap(bpmRunNodeVo.getFormDataMap());
|
|
|
+ iRunBPMEntity.setTableName(bpmRunNodeVo.getTableName());
|
|
|
+ AjaxResult ajaxResult = iRunImplementationClass.RunBPMImplementationClassLogicCode(iRunBPMEntity); // 调用节点绑定逻辑代码
|
|
|
+ if (!ajaxResult.get("code").toString().equals("200")) {
|
|
|
+ return ajaxResult;
|
|
|
+ }else { //只有执行成功的情况下再让他插入日志信息
|
|
|
+ // ⚠️⚠️⚠️ 新增节点执行记录
|
|
|
+ BpmExecuteNodeLog bpmExecuteNodeLog = new BpmExecuteNodeLog(currentBpmExecuteNode);
|
|
|
+ iBpmExecuteNodeLogService.insertBpmExecuteNodeLog(bpmExecuteNodeLog);
|
|
|
+ }
|
|
|
+ //--- 2️⃣⚡️5️⃣ 当节点执行完成后修改节点的状态
|
|
|
+ System.err.println("--- 2️⃣⚡️5️⃣ 当节点执行完成后修改节点的状态");
|
|
|
+ BpmExecuteNode updateNodeStateEn = new BpmExecuteNode();
|
|
|
+ updateNodeStateEn.setTaskProcessKey(taskProcessKey);
|
|
|
+ updateNodeStateEn.setTaskNodeKey(taskNodeKey);
|
|
|
+ updateNodeStateEn.setTaskNodeState("1"); // 状态标识已经执行
|
|
|
+ // 修改当前节点的状态
|
|
|
+ runBpmExecuteNodeMapper.updateNodeState(updateNodeStateEn);
|
|
|
+ //--- 3️⃣3️⃣3️⃣执行节点后绑定的脚本🚀🚀🚀~!!!
|
|
|
+ System.err.println("--- 3️⃣3️⃣3️⃣执行节点后绑定的脚本🚀🚀🚀~!!!");
|
|
|
+ if (currentBpmExecuteNode.getTaskNodeAfter().equals("true")) {
|
|
|
+ // 调用执行脚本接口
|
|
|
+ if (script != null && script.length != 0 && !script[0].isEmpty()) {
|
|
|
+ for (int i = 0; i < script.length; i++) {
|
|
|
+ // 节点执行必要的参数
|
|
|
+ IScriptEntity iScriptEntity = new IScriptEntity();
|
|
|
+ iScriptEntity.setScriptFlowKey(taskProcessKey);
|
|
|
+ iScriptEntity.setScriptNodeKey(taskNodeKey);
|
|
|
+ iScriptEntity.setImplementationName(script[i]);
|
|
|
+ // 调用执行节点
|
|
|
+ if (!iRunImplementationClass.RunScriptImplementationClassLogicCode(iScriptEntity, bpmRunNodeVo)) {
|
|
|
+ // 判断脚本执行状态
|
|
|
+ return AjaxResult.error(HttpStatus.SCRIPTEXCEPTION, "节点后执行脚本失败!");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ BpmExecuteNode bpmExecuteNode = runBpmExecuteNodeMapper.queryBpmExecuteNodeBytaskNodeKey(bpmRunNodeVo.getTaskProcessKey(), bpmRunNodeVo.getNextNodeKey());
|
|
|
+ //---3️⃣⚡️5️⃣ 添加节点执行记录 -》当前执行的节点详细信息
|
|
|
+ // ⚠️⚠️⚠️ 当前节点执行完成新增日志数据,
|
|
|
+ // 理论讲当前节点一旦点击运行操作就要新增日志,最后修改日志的状态
|
|
|
+ // BpmExecuteNodeLog bpmExecuteNodeLog1 = new BpmExecuteNodeLog(currentBpmExecuteNode);
|
|
|
+ // iBpmExecuteNodeLogService.insertBpmExecuteNodeLog(bpmExecuteNodeLog1);
|
|
|
+ // 4️⃣4️⃣4️⃣ 校验当前节点是否为结束节点
|
|
|
+ System.err.println("--- 4️⃣4️⃣4️⃣ 校验当前节点是否为结束节点");
|
|
|
+ if (bpmExecuteNode.getTaskNodeType().equals("endEvent")) {
|
|
|
+ // 节点执行必要的参数
|
|
|
+ IScriptEntity iScriptEntity = new IScriptEntity();
|
|
|
+ iScriptEntity.setScriptFlowKey(taskProcessKey);
|
|
|
+ iScriptEntity.setScriptNodeKey(taskNodeKey);
|
|
|
+ iScriptEntity.setImplementationName("commonEndEvent"); // 直接调用结束节点执行逻辑
|
|
|
+ // 调用执行结束节点
|
|
|
+ if (!iRunImplementationClass.RunScriptImplementationClassLogicCode(iScriptEntity, iScriptEntity)) {
|
|
|
+ // 判断脚本执行状态
|
|
|
+ return AjaxResult.error(HttpStatus.SCRIPTEXCEPTION, "流程结束失败!");
|
|
|
+ }
|
|
|
+ // 记录结束节点
|
|
|
+ BpmExecuteNodeLog bpmExecuteNodeLog11 = new BpmExecuteNodeLog(bpmExecuteNode);
|
|
|
+ iBpmExecuteNodeLogService.insertBpmExecuteNodeLog(bpmExecuteNodeLog11);
|
|
|
+ // 结束当前流程 更新流程状态
|
|
|
+ if (runBpmExecuteProcessMapper.endProcess(bpmRunNodeVo.getTaskProcessKey()) > 1) {
|
|
|
+ AjaxResult.success("流程执行成功!");
|
|
|
+ } else {
|
|
|
+ AjaxResult.error(HttpStatus.PROCESSERROR, "流程结束失败!");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * *** ⤴️🔄♾️❗️校验下一个节点是否需要自动执行
|
|
|
+ * 主动调用的执行接口一定是手动触发的节点
|
|
|
+ * 当手动触发节点后的下一个节点需要判断节点类型是否是自动执行的节点
|
|
|
+ *
|
|
|
+ *
|
|
|
+ * 自动执行节点程序自己调用 自动执行节点绑定的脚本。(递归执行)
|
|
|
+ * !!! 调用自动执行的脚本无法传递除特定参数外的其他用户业务表中的参数
|
|
|
+ */
|
|
|
+ System.err.println("*** ⤴️🔄♾️❗️校验下一个节点是否需要自动执行");
|
|
|
+ if (bpmExecuteNode.getTaskNodeExecuteType().equals("true")) { // 当前节点的下一个节点,。。。。。。,,。是自动执行
|
|
|
+ // 处理数据
|
|
|
+ BpmRunNodeVo bpmRunNodeVo1 = new BpmRunNodeVo();
|
|
|
+ bpmRunNodeVo1.setTaskNodeKey(bpmExecuteNode.getTaskNodeKey());
|
|
|
+ bpmRunNodeVo1.setTaskProcessKey(bpmExecuteNode.getTaskProcessKey());
|
|
|
+ bpmRunNodeVo1.setTaskProcessXmlContent(bpmRunNodeVo.getTaskProcessXmlContent());
|
|
|
+ // 当前节点的下一个节点的编码
|
|
|
+ bpmRunNodeVo1.setNextNodeKey(XmlDataParserUtils.getNextNodeKey(bpmRunNodeVo.getTaskProcessXmlContent(), bpmRunNodeVo.getNextNodeKey()));
|
|
|
+ // 当前节点执行的脚本
|
|
|
+ BpmExecuteNodeMiddle nextBpmExecuteNodeMiddle = runBpmExecuteNodeMiddleMapper.queryBpmExecuteNodeMiddleByTaskNodeKey(bpmRunNodeVo.getTaskProcessKey(), bpmRunNodeVo.getNextNodeKey());
|
|
|
+ // 节点如果是自动的执行方式,那么节点类型一定是正常的(或者单独的节点类型等)
|
|
|
+ bpmRunNodeVo1.setTaskNodeType("userTask");
|
|
|
+ bpmRunNodeVo1.setImplementationName(nextBpmExecuteNodeMiddle.getTaskAutomaticScriptTriggerType());
|
|
|
+ BpmExecuteProcess bpmExecuteProcess = new BpmExecuteProcess();
|
|
|
+ // bug位置,流程节点执行key
|
|
|
+ bpmExecuteProcess.setTaskKey(bpmRunNodeVo.getTaskProcessKey());
|
|
|
+ bpmExecuteProcess.setTaskNodeKey(bpmRunNodeVo.getTaskNodeKey());
|
|
|
+ bpmExecuteProcess.setTaskNodeNextKey(bpmRunNodeVo.getNextNodeKey());
|
|
|
+ runBpmExecuteProcessMapper.updateProcessNode(bpmExecuteProcess);
|
|
|
+ this.executionNode(bpmRunNodeVo1);
|
|
|
+ } else if (bpmExecuteNode.getTaskNodeExecuteType().equals("false")) {
|
|
|
+ System.err.println("✅✅✅节点执行完成!!!");
|
|
|
+ // 判断当前执行的节点是否为回退类型的异常节点
|
|
|
+ // 回退类型的异常节点一定是的任务执行节点的编码是不能被改变的,其他类型的异常可以进行更改
|
|
|
+ if (bpmRunNodeVo.getTaskNodeType().equals("backExceptionTask")) {
|
|
|
+ return AjaxResult.success();
|
|
|
+ }
|
|
|
+ BpmExecuteProcess bpmExecuteProcess = new BpmExecuteProcess();
|
|
|
+ bpmExecuteProcess.setTaskKey(bpmRunNodeVo.getTaskProcessKey());
|
|
|
+ bpmExecuteProcess.setTaskNodeKey(bpmRunNodeVo.getTaskNodeKey());
|
|
|
+ bpmExecuteProcess.setTaskNodeNextKey(bpmRunNodeVo.getNextNodeKey());
|
|
|
+ runBpmExecuteProcessMapper.updateProcessNode(bpmExecuteProcess);
|
|
|
+ return AjaxResult.success();
|
|
|
+ }
|
|
|
+ return AjaxResult.success();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取发起流程数据
|
|
|
+ *
|
|
|
+ * @param commonEntity
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public IntoProduction obtainData(CommonEntity commonEntity) {
|
|
|
+ IntoProduction intoProduction = new IntoProduction(); // 启动流程所需参数实体
|
|
|
+ commonEntity.getConditionMap().entrySet().forEach(item -> {
|
|
|
+ // 得到当前表的主键字段 // 得到当前表的主键值
|
|
|
+ intoProduction.setGuid(item.getKey() + "=" + item.getValue().toString());
|
|
|
+ });
|
|
|
+ // 得到当前表名
|
|
|
+ intoProduction.setTableName(commonEntity.getBasicMap().get("tableName").toString());
|
|
|
+ // 得到需要执行的流程编码
|
|
|
+ intoProduction.setTaskProcessKey(commonEntity.getCommMap().get("process_key").toString());
|
|
|
+ // 得到单前表所需的状态字段,启动流程所需kv
|
|
|
+ intoProduction.setStateMap(commonEntity.getConditionMap());
|
|
|
+ intoProduction.getStateMap().putAll(commonEntity.getBtnParametersMap());
|
|
|
+ return intoProduction;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * * 执行表单查询详情接口,得到当前节点展示表单的数据
|
|
|
+ */
|
|
|
+ public CommonEntity processNodeFormInfoData(BpmRunNodeFromVo bpmRunNodeFromVo) {
|
|
|
+ return iRunImplementationClass.getNodeFormData(bpmRunNodeFromVo);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 共通执行节点表单模版接口
|
|
|
+ * * 目前只有审批节点在调用这个接口
|
|
|
+ */
|
|
|
+ public List<Map> getProcessNodeFormTemplate(BpmRunNodeFromVo bpmRunNodeFromVo) {
|
|
|
+ //任务流程key
|
|
|
+ String taskProcessKey = bpmRunNodeFromVo.getTaskProcessKey();
|
|
|
+ //任务节点key
|
|
|
+ String taskNodeKey = bpmRunNodeFromVo.getTaskNodeKey();
|
|
|
+ //脚本名称
|
|
|
+ // String taskScriptKey = bpmRunNodeFromVo.getTaskScriptKey();
|
|
|
+ //根据流程key和节点key查询节点表单关系表【bpm_execute_node_form】
|
|
|
+ BpmExecuteNodeForm bpmExecuteNodeForm = iBpmExecuteNodeFormService.getBpmExecuteNodeForm(taskProcessKey, taskNodeKey, null);
|
|
|
+ //存放返回结果
|
|
|
+ List<Map> mapList = new ArrayList<>();
|
|
|
+ //节点对应的表单信息不能为空
|
|
|
+ if (bpmExecuteNodeForm != null) {
|
|
|
+ String taskNodeFormContent = bpmExecuteNodeForm.getTaskNodeFormContent();
|
|
|
+ //拿到当前节点对应的表单类型
|
|
|
+ String taskNodeFormType = bpmExecuteNodeForm.getTaskNodeFormType();
|
|
|
+ if (taskNodeFormType.equals("dragForm")) {
|
|
|
+ HashMap hashMap = new HashMap();
|
|
|
+ //解析存进去的表单信息【task_node_from_content】
|
|
|
+ JSONObject taskNodeFromContentJson = JSONObject.parseObject(taskNodeFormContent);
|
|
|
+ //得到sqlKey
|
|
|
+ String sqlKey = taskNodeFromContentJson.get("sqlKey").toString();
|
|
|
+ //根据sqlKey查询表单数据
|
|
|
+
|
|
|
+ // if (!sqlKey.isEmpty()) {
|
|
|
+ // Map<String, String> tableSqlBySqlKey = executeNodeFormMapper.getTableSqlBySqlKey(sqlKey);
|
|
|
+ // hashMap.put("resultMap", tableSqlBySqlKey);
|
|
|
+ // }
|
|
|
+
|
|
|
+ //得到【df_form_sql】
|
|
|
+ String dfFormSql = taskNodeFromContentJson.get("dfFormSql").toString();
|
|
|
+ ObjectMapper objectMapper = new ObjectMapper();
|
|
|
+ Map<String, Object> sqlMap = null;
|
|
|
+ try {
|
|
|
+ sqlMap = objectMapper.readValue(dfFormSql, Map.class);
|
|
|
+ //循环得到每一个sql语句返回结果
|
|
|
+ for (Map.Entry<String, Object> entry : sqlMap.entrySet()) {
|
|
|
+ List<Map<String, Object>> resultMap = executeNodeFormMapper.executeSql(entry.getValue().toString());
|
|
|
+ sqlMap.put(entry.getKey(), resultMap);
|
|
|
+ }
|
|
|
+ //把原来的sql语句替换成下拉框数据
|
|
|
+ taskNodeFromContentJson.put("dfFormSql", JSONObject.toJSONString(sqlMap));
|
|
|
+ } catch (JsonProcessingException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ // 获取当前流程审批的表单数据关系
|
|
|
+ BpmApprovalStatus bpmApprovalStatus = iBpmApprovalStatusService.selectBpmApprovalStatusByTaskKey(bpmRunNodeFromVo.getTaskProcessKey());
|
|
|
+ // 通用查询方法
|
|
|
+ CommonEntity common = new CommonEntity();
|
|
|
+ common.getBasicMap().put("tableName", bpmApprovalStatus.getTableName());
|
|
|
+ common.getQueryMap().put(bpmApprovalStatus.getTableId().split("=")[0], bpmApprovalStatus.getTableId().split("=")[1]);
|
|
|
+ // 添加结果当前回显表单的数据信息
|
|
|
+ taskNodeFromContentJson.put("resultMap", commonService.selectList(common));
|
|
|
+ //表单结构信息
|
|
|
+ hashMap.put("template", taskNodeFromContentJson);
|
|
|
+ //添加到返回集合中
|
|
|
+ mapList.add(hashMap);
|
|
|
+ } else if (taskNodeFormType.equals("dragFormGroup")) { // 当前节点绑定的是表单组类型
|
|
|
+ // 查询表单组信息、
|
|
|
+ HashMap hashMap = new HashMap();
|
|
|
+ //解析存进去的表单信息【task_node_from_content】
|
|
|
+ JSONObject taskNodeFromContentJson = JSONObject.parseObject(taskNodeFormContent);
|
|
|
+
|
|
|
+ // 主表单逻辑
|
|
|
+ if (taskNodeFromContentJson.get("mainForm") != null) {
|
|
|
+ Map<String, Object> mianFormMap = (Map<String, Object>) ((Map) taskNodeFromContentJson.get("mainForm")).get("showTemplate");
|
|
|
+ //得到sqlKey
|
|
|
+ String sqlKey = mianFormMap.get("sqlKey").toString();
|
|
|
+ //根据sqlKey查询表单数据
|
|
|
+ if (!sqlKey.isEmpty()) {
|
|
|
+ Map<String, String> tableSqlBySqlKey = executeNodeFormMapper.getTableSqlBySqlKey(sqlKey);
|
|
|
+ hashMap.put("resultMap", tableSqlBySqlKey);
|
|
|
+ }
|
|
|
+ //得到【df_form_sql】
|
|
|
+ String dfFormSql = mianFormMap.get("dfFormSql").toString();
|
|
|
+ ObjectMapper objectMapper = new ObjectMapper();
|
|
|
+ Map<String, Object> sqlMap = null;
|
|
|
+ try {
|
|
|
+ sqlMap = objectMapper.readValue(dfFormSql, Map.class);
|
|
|
+ //循环得到每一个sql语句返回结果
|
|
|
+ for (Map.Entry<String, Object> entry : sqlMap.entrySet()) {
|
|
|
+ List<Map<String, Object>> resultMap = executeNodeFormMapper.executeSql(entry.getValue().toString());
|
|
|
+ sqlMap.put(entry.getKey(), resultMap);
|
|
|
+ }
|
|
|
+ //把原来的sql语句替换成下拉框数据
|
|
|
+ mianFormMap.put("dfFormSql", JSONObject.toJSONString(sqlMap));
|
|
|
+ } catch (JsonProcessingException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 从表单逻辑
|
|
|
+ if (taskNodeFromContentJson.get("subFormList") != null) {
|
|
|
+ ((ArrayList) taskNodeFromContentJson.get("subFormList")).forEach(item -> {
|
|
|
+ Map<String, Object> itemMap = (Map<String, Object>) ((Map) item).get("showTemplate");
|
|
|
+
|
|
|
+ //得到sqlKey
|
|
|
+ String sqlKey = itemMap.get("sqlKey").toString();
|
|
|
+
|
|
|
+ //根据sqlKey查询表单数据
|
|
|
+ if (!sqlKey.isEmpty()) {
|
|
|
+ Map<String, String> tableSqlBySqlKey = executeNodeFormMapper.getTableSqlBySqlKey(sqlKey);
|
|
|
+ hashMap.put("resultMap", tableSqlBySqlKey);
|
|
|
+ }
|
|
|
+ //得到【df_form_sql】
|
|
|
+ String dfFormSql = itemMap.get("dfFormSql").toString();
|
|
|
+ ObjectMapper objectMapper = new ObjectMapper();
|
|
|
+ Map<String, Object> sqlMap = null;
|
|
|
+ try {
|
|
|
+ sqlMap = objectMapper.readValue(dfFormSql, Map.class);
|
|
|
+ //循环得到每一个sql语句返回结果
|
|
|
+ for (Map.Entry<String, Object> entry : sqlMap.entrySet()) {
|
|
|
+ List<Map<String, Object>> resultMap = executeNodeFormMapper.executeSql(entry.getValue().toString());
|
|
|
+ sqlMap.put(entry.getKey(), resultMap);
|
|
|
+ }
|
|
|
+ //把原来的sql语句替换成下拉框数据
|
|
|
+ itemMap.put("dfFormSql", JSONObject.toJSONString(sqlMap));
|
|
|
+ } catch (JsonProcessingException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ // 获取当前流程审批的表单数据关系
|
|
|
+ BpmApprovalStatus bpmApprovalStatus = iBpmApprovalStatusService.selectBpmApprovalStatusByTaskKey(bpmRunNodeFromVo.getTaskProcessKey());
|
|
|
+ // 通用查询方法
|
|
|
+ CommonEntity common = new CommonEntity();
|
|
|
+ common.getBasicMap().put("tableName", bpmApprovalStatus.getTableName());
|
|
|
+ common.getQueryMap().put(bpmApprovalStatus.getTableId().split("=")[0], bpmApprovalStatus.getTableId().split("=")[1]);
|
|
|
+ // 添加结果当前回显表单的数据信息
|
|
|
+
|
|
|
+ // 主
|
|
|
+ List<CommonEntity> retCommonEntityList = commonService.selectList(common);
|
|
|
+
|
|
|
+ ((Map) taskNodeFromContentJson.get("mainForm")).put("showValue", retCommonEntityList);
|
|
|
+
|
|
|
+ // 从
|
|
|
+ ((ArrayList) taskNodeFromContentJson.get("subFormList")).forEach(item -> {
|
|
|
+ String[] congTableOInfo = ((Map) item).get("formItem").toString().split("\\.");
|
|
|
+ String[] zhuTableOWhere = ((Map) item).get("relateMainItem").toString().split("\\.");
|
|
|
+ CommonEntity congCommon = new CommonEntity();
|
|
|
+ congCommon.getBasicMap().put("tableName", congTableOInfo[0]);
|
|
|
+ Object val = retCommonEntityList.get(0).getResultMap().get(StringUtils.toCamelCase(zhuTableOWhere[1]));
|
|
|
+ congCommon.getQueryMap().put(congTableOInfo[1], val);
|
|
|
+ commonService.selectList(congCommon);
|
|
|
+ ((Map) item).put("showValue", commonService.selectList(congCommon));
|
|
|
+ });
|
|
|
+ taskNodeFromContentJson.put("resultMap", retCommonEntityList);
|
|
|
+ //表单结构信息
|
|
|
+ hashMap.put("template", taskNodeFromContentJson);
|
|
|
+ //添加到返回集合中
|
|
|
+ mapList.add(hashMap);
|
|
|
+ } else if (taskNodeFormType.equals("composeForm")) {
|
|
|
+ //参数为一个数组
|
|
|
+ JSONArray objects = JSON.parseArray(taskNodeFormContent);
|
|
|
+
|
|
|
+ //循环数组元素
|
|
|
+ objects.forEach(item -> {
|
|
|
+ String s = item.toString();
|
|
|
+ JSONObject jsonObject = JSONObject.parseObject(s);
|
|
|
+ String tableSql = jsonObject.get("tableSql").toString();
|
|
|
+ String conditionArrayJson = jsonObject.get("condition").toString();
|
|
|
+ JSONArray jsonArray = JSON.parseArray(conditionArrayJson);
|
|
|
+
|
|
|
+ jsonArray.forEach(conditionItem -> {
|
|
|
+ //处理下这个条件 去掉 #{ 去掉.
|
|
|
+ String conditionString = conditionItem.toString().replace("#{", "").replace(".", "_");
|
|
|
+ //转驼峰
|
|
|
+ String CamelConditionString = StringUtils.toCamelCase(conditionString);
|
|
|
+ //
|
|
|
+ });
|
|
|
+
|
|
|
+ Map<String, String> stringHashMap = executeNodeFormMapper.tableSql(tableSql);
|
|
|
+ jsonObject.put("tableList", stringHashMap);
|
|
|
+ mapList.add(jsonObject);
|
|
|
+ });
|
|
|
+ } else if (taskNodeFormContent.equals("designForm")) {
|
|
|
+ HashMap hashMap = new HashMap();
|
|
|
+ hashMap.put("resultMap", "");
|
|
|
+ hashMap.put("template", "");
|
|
|
+ mapList.add(hashMap);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return mapList;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 查询节点对应的表单信息
|
|
|
+ *
|
|
|
+ * @param nodeForm
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public Map<String, Object> getNodeFormInfos(Map<String, String> nodeForm) {
|
|
|
+ Set<String> nodeKey = nodeForm.keySet();
|
|
|
+ Map resultMap = new HashMap();
|
|
|
+ nodeKey.forEach(item -> {
|
|
|
+ if (nodeForm.get(item).equals("dragForm")) { // 拖拽类型的表单
|
|
|
+ String fromInfo = iBpmExecuteProcessService.getFromInfoByFormKey(item);
|
|
|
+ resultMap.put(item, fromInfo);
|
|
|
+ } else if (nodeForm.get(item).equals("dragFormGroup")) { // 拖拽的表单组
|
|
|
+ // 得到当前表格组的信息
|
|
|
+ DragFormGroup dragFormGroup = iDragFormGroupService.selectDragFormGroupByKey(item);
|
|
|
+ // 根据表单组中的keys信息 获取对应动态表单的信息
|
|
|
+ String[] formKeys = JSON.parseArray(dragFormGroup.getFormKeys()).toArray(String.class);
|
|
|
+ List<CommonEntity> commonEntityList = iBpmExecuteProcessService.getFromInfoByFormKeys(formKeys);
|
|
|
+ // 当前表单组关系
|
|
|
+ Map<String, Object> relationJsonMap = (Map<String, Object>) JSON.parse(dragFormGroup.getRelationJson());
|
|
|
+ // 得到当前主表单key
|
|
|
+ ((Map) relationJsonMap.get("mainForm")).get("formKey");
|
|
|
+ // 主表单增加模版信息
|
|
|
+ commonEntityList.forEach(ctem -> {
|
|
|
+ if (ctem.getResultMap().get("formKey").equals(((Map) relationJsonMap.get("mainForm")).get("formKey"))) {
|
|
|
+ ((Map) relationJsonMap.get("mainForm")).put("showTemplate", ctem.getResultMap());
|
|
|
+ }
|
|
|
+ });
|
|
|
+ // 从表单增加模版信息
|
|
|
+ ((ArrayList) relationJsonMap.get("subFormList")).forEach(rtem -> {
|
|
|
+ ((Map) rtem).put("showTemplate", commonEntityList.stream().filter(ctem -> ctem.getResultMap().get("formKey").equals(((Map) rtem).get("formKey"))).findFirst().get().getResultMap());
|
|
|
+ });
|
|
|
+ // 添加表单组模版布局
|
|
|
+ relationJsonMap.put("layoutJson", dragFormGroup.getLayoutJson());
|
|
|
+ resultMap.put(item, relationJsonMap.toString());
|
|
|
+ } else if (nodeForm.get(item).equals("composeForm")) { // 组合类型的表单
|
|
|
+ String groupTableInfo = iBpmExecuteProcessService.getGroupTableInfo(item);
|
|
|
+ resultMap.put(item, groupTableInfo);
|
|
|
+ } else if (nodeForm.get(item).equals("designForm")) { // 自定义类型表单
|
|
|
+ resultMap.put(item, "");
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return resultMap;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 回退流程节点
|
|
|
+ *
|
|
|
+ * @param bpmBackNodeVo
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public AjaxResult backProcessNode(BpmBackNodeVo bpmBackNodeVo) {
|
|
|
+ BpmExecuteProcess bpmExecuteProcess = runBpmExecuteProcessMapper.selectBpmExecuteProcessByTaskKey(bpmBackNodeVo.getTaskProcessKey());
|
|
|
+ bpmExecuteProcess.getTaskProcessXmlContent(); // 当前流程xml内容
|
|
|
+ Map<String, Object> bpmInfoOrder = XmlDataParserUtils.getAllNodeKey(bpmExecuteProcess.getTaskProcessXmlContent());
|
|
|
+ // 修改流程-> 流程执行的xml文件
|
|
|
+ bpmExecuteProcess.setTaskProcessXmlContent(XmlDataParserUtils.clearExceptionTask(bpmExecuteProcess.getTaskProcessXmlContent(), bpmBackNodeVo.getTaskBackNodeKey()));
|
|
|
+ // 如果触发回退操作的节点是一个异常节点(需要更改当前流程绑定的执行节点)
|
|
|
+ bpmExecuteProcess.setTaskNodeNextKey(bpmBackNodeVo.getTaskBackNodeKey());
|
|
|
+ runBpmExecuteProcessMapper.updateBpmExecuteProcess(bpmExecuteProcess);
|
|
|
+ // 得到当前流程的详细信息
|
|
|
+ Map<String, Object> nodeMap = (Map<String, Object>) bpmInfoOrder.get("nodeMap");
|
|
|
+ List<String> nodeList = (List<String>) bpmInfoOrder.get("nodeList");
|
|
|
+ int index = (int) nodeMap.get(bpmBackNodeVo.getTaskBackNodeKey()); // 得到被回退的节点下标
|
|
|
+ List<String> nodeKeys = new ArrayList<>();
|
|
|
+ for (int i = index; i < nodeList.size(); i++) {
|
|
|
+ nodeKeys.add(nodeList.get(i));
|
|
|
+ }
|
|
|
+ // 修改当前流程节点状态
|
|
|
+ runBpmExecuteNodeMapper.updateNodeStateByKeys(bpmBackNodeVo.getTaskProcessKey(), nodeKeys);
|
|
|
+ BpmExecuteNodeLog bpmExecuteNodeLog = new BpmExecuteNodeLog();
|
|
|
+ bpmExecuteNodeLog.setTaskProcessKey(bpmBackNodeVo.getTaskProcessKey());
|
|
|
+ bpmExecuteNodeLog.setTaskNodeKey(bpmBackNodeVo.getTaskNodeKey());
|
|
|
+ List<BpmExecuteNodeLog> bpmExecuteNodeLogList = iBpmExecuteNodeLogService.selectBpmExecuteNodeLogList(bpmExecuteNodeLog);
|
|
|
+ if (bpmExecuteNodeLogList.size() == 1) {
|
|
|
+ // 问题:当前修改回退节点日志,在此当前回退节点并未执行完成。
|
|
|
+ // 所以并没有日志数据,无法完成修改操作
|
|
|
+ BpmExecuteNodeLog bpmExecuteNodeLog1 = bpmExecuteNodeLogList.get(0);
|
|
|
+ bpmExecuteNodeLog1.setTaskParentNodeKey(bpmBackNodeVo.getTaskNodeKey());
|
|
|
+ iBpmExecuteNodeLogService.updateBpmExecuteNodeLog(bpmExecuteNodeLog1);
|
|
|
+ }
|
|
|
+ nodeKeys.add(bpmBackNodeVo.getTaskBackNodeKey());
|
|
|
+ // 修改回退节点后的所有异常节点信息
|
|
|
+ runBpmExecuteNodeMapper.deleteExceptionNodeByKeys(bpmBackNodeVo.getTaskProcessKey(), nodeKeys);
|
|
|
+ return AjaxResult.success();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 执行审批流程节点
|
|
|
+ *
|
|
|
+ * @param bpmRunNodeVo 当前节点信息
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public AjaxResult approvalNode(BpmRunNodeVo bpmRunNodeVo) {
|
|
|
+ /**
|
|
|
+ * 不能确定某张表可以发起流程,也就是发起审批的这个条数据需要回传后台标识
|
|
|
+ *
|
|
|
+ * 表名以及当前数据条的主键,
|
|
|
+ */
|
|
|
+ /**
|
|
|
+ * 1️⃣1️⃣1️⃣ 准备执行节点所需数据
|
|
|
+ * * 审批节点不过是通过、未通过、驳回等状态信息
|
|
|
+ * * 审批备注与通过、不通过等状态是同一列数据,
|
|
|
+ * * 如果轮回审批,那么备注字段也会是同列,之前审批的状态以及审批备注,需要从日志表中获取
|
|
|
+ * * 把当前流程节点的完整执行记录到日志表中,审批流程的执行只修改状态
|
|
|
+ */
|
|
|
+ String taskProcessKey = bpmRunNodeVo.getTaskProcessKey(); // 任务流程编码
|
|
|
+ String taskNodeKey = bpmRunNodeVo.getTaskNodeKey(); // 任务节点编码
|
|
|
+ String taskNextNodeKey = XmlDataParserUtils.getNextNodeKey(bpmRunNodeVo.getTaskProcessXmlContent(), taskNodeKey);
|
|
|
+ // 获取当前节点的下个节点类型
|
|
|
+ String taskNextNodeType = XmlDataParserUtils.getNodeType(bpmRunNodeVo.getTaskProcessXmlContent(), taskNextNodeKey);
|
|
|
+ // 得到当前执行的流程信息
|
|
|
+ BpmExecuteProcess currentBpmExecuteProcess = runBpmExecuteProcessMapper.selectBpmExecuteProcessByTaskKey(taskProcessKey);
|
|
|
+ // 得到当前节点的所有信息-》审批类型节点会出现节点后给某张表插入数据
|
|
|
+ BpmExecuteNode currentBpmExecuteNode = runBpmExecuteNodeMapper.queryBpmExecuteNodeBytaskNodeKey(taskProcessKey, taskNodeKey);
|
|
|
+ // 审批备注
|
|
|
+ String approvalRemark = bpmRunNodeVo.getApprovalRemark();
|
|
|
+ // 审批状态 pass:通过、noPass:不通过、reject:驳回
|
|
|
+ String approvalStatus = bpmRunNodeVo.getApprovalStatus();
|
|
|
+ // 当前执行的节点全部信息
|
|
|
+ currentBpmExecuteNode.setTaskNodeOtherState(approvalStatus);
|
|
|
+ currentBpmExecuteNode.setTaskRemark(approvalRemark);
|
|
|
+
|
|
|
+ // 当前执行的流程
|
|
|
+ currentBpmExecuteProcess.setTaskNodeKey(taskNodeKey);
|
|
|
+ currentBpmExecuteProcess.setTaskNodeNextKey(taskNextNodeKey);
|
|
|
+
|
|
|
+ // 2️⃣2️⃣2️⃣ 开始执行当前节点
|
|
|
+ // 补充流程节点信息(如若驳回操作,会显示上次审批记录)
|
|
|
+ runBpmExecuteNodeMapper.updateBpmExecuteNode(currentBpmExecuteNode);
|
|
|
+ // --- 修改当前流程执行节点
|
|
|
+ runBpmExecuteProcessMapper.updateProcessNode(currentBpmExecuteProcess);
|
|
|
+ // --- 修改当前审批的数据条状态
|
|
|
+
|
|
|
+
|
|
|
+ // 3️⃣3️⃣3️⃣ 判断当前节点是否存在给其他表插入数据
|
|
|
+ // currentBpmExecuteNode.getTask
|
|
|
+
|
|
|
+ // ⚠️⚠️⚠️ 新增节点执行记录
|
|
|
+ BpmExecuteNodeLog bpmExecuteNodeLog = new BpmExecuteNodeLog(currentBpmExecuteNode);
|
|
|
+ iBpmExecuteNodeLogService.insertBpmExecuteNodeLog(bpmExecuteNodeLog);
|
|
|
+
|
|
|
+ // 4️⃣4️⃣4️⃣ 判断是否结束审批流程 || 不通过流程直接结束 || 驳回流程直接结束
|
|
|
+ if (approvalStatus.equals("noPass") || approvalStatus.equals("reject") || taskNextNodeType.equals("endEvent")) {
|
|
|
+ // 得到当前数据条的表信息,修改当前数据条的审批状态值
|
|
|
+ BpmApprovalStatus bpmApprovalStatus = iBpmApprovalStatusService.selectBpmApprovalStatusByTaskKey(taskProcessKey);
|
|
|
+ // 当前节点是改流程的最后一个节点,默认执行结束节点
|
|
|
+
|
|
|
+ // 审批流程结束,修改当前审批关联数据条的关联数据条的状态(bpm_approval_status)
|
|
|
+ // 具体修改数据条的状态应当是根据结束节点的上个节点的状态来判断
|
|
|
+ String status = getuApprovalStatus(approvalStatus);
|
|
|
+
|
|
|
+ // 更新审批的数据条状态
|
|
|
+ iBpmApprovalStatusService.updateBpmApprovalStatusByTaskKey(new BpmApprovalStatus(status, bpmRunNodeVo.getTaskProcessKey()));
|
|
|
+ // 更新审批主数据条审批状态
|
|
|
+
|
|
|
+ iBpmApprovalStatusService.updateApprovalStatusByTableName(bpmApprovalStatus.getTableName(), status, bpmApprovalStatus.getTableId());
|
|
|
+
|
|
|
+ // 结束当前流程
|
|
|
+ return AjaxResult.success(runBpmExecuteProcessMapper.endProcess(bpmRunNodeVo.getTaskProcessKey()));
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 审批的发起操作,相当于这个流程的开始
|
|
|
+ 那么用户首次调用当前接口,都会就是一级审批
|
|
|
+ 需要当前操作的状态以及审批过后的备注信息 两列数据。
|
|
|
+ 修改节点状态,添加审批的数据,修改流程执行节点的key。
|
|
|
+ 如何当前节点有节点后需要插入的其他表数据则执行。
|
|
|
+
|
|
|
+ 理论上来讲每一个节点的表单都是一样的,都是审批数据条是否通过,以及审批意见
|
|
|
+ 如果需要审批的数据条是多表中的数据,也看作为一条数据来处理。
|
|
|
+
|
|
|
+ 流程发起时的表单数据开始存在用户的表中,所以同生产流程逻辑一样。
|
|
|
+ 在发起这个流程的时候记录当前的数据条的表名以及表主键
|
|
|
+ */
|
|
|
+
|
|
|
+
|
|
|
+ return AjaxResult.success();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // 当前节点在操作最后一个审批节点时根据审批的节点状态来更改当前审批数据条的状态
|
|
|
+ public String getuApprovalStatus(String code) {
|
|
|
+ // 审批状态 pass:通过、noPass:不通过、reject:驳回
|
|
|
+ // '审批状态 (0:已提交、1:已通过、2:不通过、4:驳回、5:审批中)'
|
|
|
+ if ("pass".equals(code)) return "1";
|
|
|
+ if ("noPass".equals(code)) return "2";
|
|
|
+ if ("reject".equals(code)) return "4";
|
|
|
+ return "5";
|
|
|
+ }
|
|
|
+
|
|
|
+ // 撤销申请数据条操作
|
|
|
+ @Transactional
|
|
|
+ public AjaxResult revokeApplication(BpmRunNodeVo bpmRunNodeVo) {
|
|
|
+ // 当前执行流程编号
|
|
|
+ String taskKey = bpmRunNodeVo.getTaskProcessKey();
|
|
|
+ // 得到当前数据条的表信息,修改当前数据条的审批状态值
|
|
|
+ BpmApprovalStatus bpmApprovalStatus = iBpmApprovalStatusService.selectBpmApprovalStatusByTaskKey(taskKey);
|
|
|
+ // 删除申请流程(修改申请数据条的状态)
|
|
|
+ // 在流程状态中4 表示撤销
|
|
|
+ iBpmExecuteProcessService.updateProcessStateByKey("4", taskKey);
|
|
|
+ // 修改提交审批的数据条状态-》 调用共通接口执行
|
|
|
+ // 数据条审批状态(默认字段 0:未提交 1:已提交 2:已撤销 3:已通过)
|
|
|
+ iBpmApprovalStatusService.updateApprovalStatusByTableName(bpmApprovalStatus.getTableName(), "2", bpmApprovalStatus.getTableId());
|
|
|
+ // 修改中间表状态:撤回
|
|
|
+ iBpmApprovalStatusService.updateBpmApprovalStatusByTaskKey(new BpmApprovalStatus("3", taskKey));
|
|
|
+
|
|
|
+ return AjaxResult.success();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+}
|