Browse Source

11482-【CR】【投资系统】增加审批流程-流程参数改动

hxy 3 months ago
parent
commit
8ced3381a9

+ 5 - 2
ruoyi-flowable/src/main/java/com/ruoyi/flowable/service/IFlowInstanceService.java

@@ -3,9 +3,9 @@ package com.ruoyi.flowable.service;
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.flowable.domain.vo.FlowTaskVo;
 import org.flowable.engine.history.HistoricProcessInstance;
-import org.flowable.task.api.Task;
+import org.flowable.engine.runtime.ProcessInstance;
+
 
-import java.util.List;
 import java.util.Map;
 
 /**
@@ -53,4 +53,7 @@ public interface IFlowInstanceService {
      * @return
      */
     AjaxResult startProcessInstanceById(String procDefId, Map<String, Object> variables);
+
+    String getFormProperties(ProcessInstance processInstance);
+
 }

+ 63 - 0
ruoyi-flowable/src/main/java/com/ruoyi/flowable/service/IFlowService.java

@@ -0,0 +1,63 @@
+package com.ruoyi.flowable.service;
+
+
+import org.flowable.engine.runtime.ProcessInstance;
+import org.flowable.task.api.Task;
+
+import java.util.Map;
+
+
+public interface IFlowService {
+
+
+    /**
+     * 根据任务Id获取流程实例信息
+     */
+    public ProcessInstance getProcessInstance(String taskId);
+    
+    /**
+     * 根据任务对象获取流程实例信息
+     */
+    public ProcessInstance getProcessInstance(Task task);
+    
+    /**
+     * 获取节点的formkey值
+     */
+    /*public String getFormKey(String pInstId, String taskId, String opType);*/
+    
+    /**
+     * 获取表单信息, 如果 taskId 不为空则获取指定taskId的表单,否则就根据pDefId获取流程开始节点定义的表单
+     */
+
+	public Map<String, Object> getFormProperties(String pDefId, String taskId);
+    
+    /**
+     * 给指定的表单map赋值,并返回 表单form的字符串表示形式
+     */
+
+	public String getFormProperties(Map<String, Object> fpMap, Map<String, String[]> mapParams);
+
+	public Map<String, Object> taskComplete(String taskId, boolean isOk, Map<String, Object> map, String loginId) throws Exception ;
+	/**
+	 *
+	 * @Description (跳转任意目标节点)
+	 * @author liuwei
+	 * @Date 2021年11月3日上午10:23:00
+	 * @version 1.0.0
+	 * @param map
+	 *            taskId,destTaskKey,rejectMessage,outcome
+	 */
+/*	public void skipStipulationTask(Map<String, Object> map) ;*/
+
+	/**
+	 *
+	 * @Description (通过任务key,获取对应的节点信息)
+	 * @author liuwei
+	 * @Date 2021年11月3日下午1:53:29
+	 * @version 1.0.0
+	 * @param destTaskKey
+	 * @param processDefinitionId
+	 * @return
+	 */
+	//public ActivityImpl getActivityImpl(String destTaskKey, String processDefinitionId) ;
+}

+ 24 - 5
ruoyi-flowable/src/main/java/com/ruoyi/flowable/service/impl/FlowInstanceServiceImpl.java

@@ -1,6 +1,7 @@
 package com.ruoyi.flowable.service.impl;
 
 
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.flowable.domain.vo.FlowTaskVo;
@@ -9,14 +10,12 @@ import com.ruoyi.flowable.service.IFlowInstanceService;
 import lombok.extern.slf4j.Slf4j;
 import org.flowable.common.engine.api.FlowableObjectNotFoundException;
 import org.flowable.engine.history.HistoricProcessInstance;
-import org.flowable.task.api.Task;
+import org.flowable.engine.runtime.ProcessInstance;
+
 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.Objects;
+import java.util.*;
 
 /**
  * <p>工作流流程实例管理<p>
@@ -119,4 +118,24 @@ public class FlowInstanceServiceImpl extends FlowServiceFactory implements IFlow
             return AjaxResult.error("流程启动错误");
         }
     }
+    @Override
+    public String getFormProperties(ProcessInstance processInstance){
+        // 获取流程变量
+        Map<String, Object> variables = runtimeService.getVariables(processInstance.getId());
+
+        // 创建 ObjectMapper 实例
+        ObjectMapper objectMapper = new ObjectMapper();
+        String variablesAsString="";
+        try {
+            // 将 Map 转换为 JSON 字符串
+            variablesAsString = objectMapper.writeValueAsString(variables);
+
+            // 现在可以将 variablesAsString 存储到数据库或其他地方
+            // ...
+        } catch (Exception e) {
+            e.printStackTrace();
+            // 处理异常
+        }
+        return variablesAsString;
+    }
 }

+ 381 - 0
ruoyi-flowable/src/main/java/com/ruoyi/flowable/service/impl/FlowServiceImpl.java

@@ -0,0 +1,381 @@
+package com.ruoyi.flowable.service.impl;
+
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.flowable.factory.FlowServiceFactory;
+import com.ruoyi.flowable.service.IFlowService;
+import org.flowable.engine.*;
+import org.flowable.engine.form.FormProperty;
+import org.flowable.engine.impl.form.StartFormDataImpl;
+import org.flowable.engine.impl.form.TaskFormDataImpl;
+import org.flowable.engine.runtime.ProcessInstance;
+import org.flowable.task.api.Task;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Service
+public class FlowServiceImpl extends FlowServiceFactory implements IFlowService {
+
+	@Autowired
+    private TaskService taskService;
+	@Autowired
+    private HistoryService historyService;
+    @Autowired
+    private RuntimeService runtimeService;
+    @Autowired
+    private FormService formService;
+    @Autowired
+	private IdentityService identityService;
+    @Autowired
+    private RepositoryService repositoryService;
+
+    /**
+     * 根据任务Id获取流程实例信息
+     */
+	@Override
+    public ProcessInstance getProcessInstance(String taskId){
+    	
+    	ProcessInstance pInstan = null;
+    	try{
+    		Task task = taskService.createTaskQuery().taskId(taskId).active().singleResult();
+    		
+    		if(task != null){
+    			String processInstanceId = task.getProcessInstanceId();
+    			
+    			pInstan = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).active().singleResult();
+    		}
+    	}catch(Exception e){
+    		e.printStackTrace();
+    	}
+    	
+    	return pInstan;
+    }
+    
+    /**
+     * 根据任务对象获取流程实例信息
+     */
+	@Override
+    public ProcessInstance getProcessInstance(Task task){
+    	
+    	ProcessInstance pInstan = null;
+    	
+    	try{
+    		if(task != null){
+    			String processInstanceId = task.getProcessInstanceId();
+    			
+    			pInstan = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).active().singleResult();
+    		}
+    		
+    	}catch(Exception e){
+    		e.printStackTrace();
+    	}
+    	
+    	return pInstan;
+    }
+    
+    /**
+     * 获取节点的formkey值
+     */
+	/*@Override
+    public String getFormKey(String pInstId, String taskId, String opType){
+    	
+    	String formKey = "";
+    	
+    	if(StringUtils.isNotBlank(pInstId)) {
+    		if(StringUtils.isNotBlank(taskId)){
+    			formKey = formService.getTaskFormKey(pInstId, taskId);
+    		}
+    		// 如果指定的任务没有设置 formkey, 则取表单开始节点设置的 formkey
+    		if(StringUtils.isBlank(formKey) || "detail".equals(opType)){
+    			formKey = formService.getStartFormKey(pInstId);
+    			
+    			if(StringUtils.isNotBlank(formKey)){
+    				
+    				*//**
+    				 *  以流程开始节点为基准, 根据opType参数和固定的规则来构建 表单请求路径
+    				 *//*
+    				
+    				// 申请表单 -- 因为开始节点设置的 formkey 就是申请表单,所以暂时不需要处理
+    				if(AcOperateTypeEnum.CREATE.eq(opType)){
+    					
+    				}else if(AcOperateTypeEnum.DETAIL.eq(opType)){ // 表单详情
+    					int index = formKey.lastIndexOf("/");
+    					formKey = formKey.substring(0, index) + "/detail";
+    				}else if(AcOperateTypeEnum.AUDIT.eq(opType)){ // 表单审核
+    					int index = formKey.lastIndexOf("/");
+    					formKey = formKey.substring(0, index) + "/audit";
+    				}
+    			}
+    		}
+    	}
+    	
+    	return formKey;
+    }*/
+    
+    /**
+     * 获取表单信息, 如果 taskId 不为空则获取指定taskId的表单,否则就根据pDefId获取流程开始节点定义的表单
+     */
+    @SuppressWarnings("unchecked")
+	@Override
+	public Map<String, Object> getFormProperties(String pDefId, String taskId){
+    	
+    	Map<String, Object> rs = new HashMap<>();
+    	
+    	try{
+    		
+    		List<FormProperty> formProperties = null;
+    		
+    		if(StringUtils.isNotBlank(taskId)) {
+    			TaskFormDataImpl taskFormData = (TaskFormDataImpl) formService.getTaskFormData(taskId);
+    			// 设置task为null,否则输出json的时候会报错
+    	        taskFormData.setTask(null);
+    	        
+    	        formProperties = taskFormData.getFormProperties();
+    			
+    			rs.put("form", taskFormData);
+    			
+    		} else if(StringUtils.isNotBlank(pDefId)){
+    			StartFormDataImpl startFormData = (StartFormDataImpl) formService.getStartFormData(pDefId);
+    			startFormData.setProcessDefinition(null);
+    			
+    			formProperties = startFormData.getFormProperties();
+    			
+    			rs.put("form", startFormData);
+    		}
+    		
+    		if(formProperties != null){
+    			for (FormProperty formProperty : formProperties) {
+    	            Map<String, String> values = (Map<String, String>) formProperty.getType().getInformation("values");
+    	            
+    	            if (values != null) {
+    	                for (Map.Entry<String, String> enumEntry : values.entrySet()) {
+    	                }
+    	                rs.put(formProperty.getId(), values);
+    	            }
+    	        }
+    		}
+    		
+    	}catch(Exception e){
+    		e.printStackTrace();
+    	}
+    	
+    	return rs;
+    }
+    
+    /**
+     * 给指定的表单map赋值,并返回 表单form的字符串表示形式
+     */
+
+	@Override
+	public String getFormProperties(Map<String, Object> fpMap, Map<String, String[]> mapParams) {
+    	
+    	String fpMapStr = "";
+    	
+    	try {
+    		
+    		if(fpMap != null && mapParams != null){
+    			
+    			ObjectMapper objMapper = new ObjectMapper();
+    			fpMapStr = objMapper.writeValueAsString(fpMap);
+    			
+    			Map<String, Object> fpMapNew = objMapper.readValue(fpMapStr, Map.class);
+    			
+    			Object oFormMap = fpMapNew.get("form");
+    			if(oFormMap != null){
+    				
+    				Map<String, Object> formMap = (Map<String, Object>)oFormMap;
+    				Object oFormProperties = formMap.get("formProperties");
+    				if(oFormProperties != null){
+    					List<Map<String, Object>> lstFpMap = (List<Map<String, Object>>)oFormProperties;
+    					
+    					for(Map<String, Object> fp : lstFpMap){
+    						String id = "fp_" + fp.get("id").toString();
+    						
+    						if(mapParams.containsKey(id)){
+    							fp.put("value", mapParams.get(id)[0]);
+    						}
+    					}
+    				}
+    			}
+    			
+    			return objMapper.writeValueAsString(fpMapNew);
+    		}
+			
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+    	
+    	return fpMapStr;
+    }
+	@Override
+	public Map<String, Object> taskComplete(String taskId, boolean isOk, Map<String, Object> map, String loginId) throws Exception {
+
+		Map<String, Object> rs = new HashMap<String, Object>();
+
+		rs.put("status", false);
+
+		Map<String, Object> formProperties = new HashMap<String, Object>();
+		TaskFormDataImpl taskFormData = (TaskFormDataImpl) formService.getTaskFormData(taskId);
+
+		if (taskFormData != null) {
+			// 设置task为null,否则输出json的时候会报错
+			taskFormData.setTask(null);
+
+			List<FormProperty> lstFormProperties = taskFormData.getFormProperties();
+			if (lstFormProperties != null) {
+				for (FormProperty formProperty : lstFormProperties) {
+					if (!formProperty.isWritable()) {
+						continue;
+					}
+					formProperties.put(formProperty.getId(), formProperty.getValue());
+				}
+			}
+		}
+
+		for (Map.Entry<String, Object> mm : map.entrySet()) {
+			formProperties.put(mm.getKey(), mm.getValue());
+		}
+		// 从request中读取参数然后转换
+		formProperties.put("isOk", String.valueOf(isOk));
+
+		try {
+			// 设置审批人,以及提交审批信息
+			identityService.setAuthenticatedUserId(loginId);
+			taskService.complete(taskId, formProperties);
+//        	formService.submitTaskFormData(taskId, formProperties);
+			rs.put("status", true);
+			// String msg = isOk ? "审核完成,同意成功!" : "审核完成,驳回成功!";
+			String msg = "审核完成!";
+			rs.put("msg", msg);
+
+		} catch (Exception e) {
+			e.printStackTrace();
+			rs.put("status", false);
+			rs.put("msg", "审核失败!");
+		} finally {
+			identityService.setAuthenticatedUserId(null);
+		}
+
+		return rs;
+	}
+
+	/**
+	 *
+	 * @Description (跳转任意目标节点)
+	 * @author liuwei
+	 * @Date 2021年11月3日上午10:23:00
+	 * @version 1.0.0
+	 * @param map
+	 *            taskId,destTaskKey,rejectMessage,outcome
+	 */
+	/*@Override
+	public void skipStipulationTask(Map<String, Object> map) {
+		String taskId = (String) map.get("taskId");
+		// 目标任务key
+		String destTaskKey = (String) map.get("destTaskKey");
+		//审批消息
+		String rejectMessage = (String) map.get("rejectMessage");
+		//流程线
+		String outcome = (String) map.get("outcome");
+		//业务的用户ID
+		String uid = (String) map.get("uid");
+		//审批消息
+		String message = (String) map.get("message");
+		// 使用任务ID,获取任务信息
+		Task taskEntity = taskService.createTaskQuery().taskId(taskId).singleResult();
+		// 获得当前任务的流程实例ID
+		String processInstanceId = taskEntity.getProcessInstanceId();
+
+		// 获得当前任务的流程定义ID
+		String processDefinitionId = taskEntity.getProcessDefinitionId();
+		// 当前任务key
+		String currtaskDefKey = taskEntity.getTaskDefinitionKey();
+
+		// 获得当前活动节点和驳回的目标节点"draft"
+		ActivityImpl currActiviti = null;// 当前活动节点
+		ActivityImpl destActiviti = null;// 驳回目标节点
+
+		currActiviti = getActivityImpl(currtaskDefKey, processDefinitionId);
+		destActiviti = getActivityImpl(destTaskKey, processDefinitionId);
+
+		// 保存当前活动节点的流程流出参数
+
+		List<PvmTransition> hisPvmTransitionList = new ArrayList<PvmTransition>(0);
+
+		for (PvmTransition pvmTransition : currActiviti.getOutgoingTransitions()) {
+			hisPvmTransitionList.add(pvmTransition);
+		}
+		// 清空当前活动节点的所有流出项
+
+		currActiviti.getOutgoingTransitions().clear();
+		// 为当前节点动态创建新的流出项
+
+		TransitionImpl newTransitionImpl = currActiviti.createOutgoingTransition();
+		// 为当前活动节点新的流出项指定为目标流程节点
+		newTransitionImpl.setDestination(destActiviti);
+		// 保存驳回意见
+		taskEntity.setDescription(rejectMessage);// 设置驳回意见
+		taskService.saveTask(taskEntity);
+
+		*//**
+		 * 注意:添加批注的时候,由于Activiti底层代码是使用: String userId =
+		 * Authentication.getAuthenticatedUserId(); CommentEntity comment = new
+		 * CommentEntity(); comment.setUserId(userId);
+		 * 所有需要从Session中获取当前登录人,作为该任务的办理人(审核人),对应act_hi_comment表中的User_ID的字段,
+		 * 不添加审核人,该字段为null
+		 * 所以要求,添加配置执行使用Authentication.setAuthenticatedUserId();添加当前任务的审核人
+		 *//*
+		Authentication.setAuthenticatedUserId(uid);
+		taskService.addComment(taskId, processInstanceId, message);
+
+		// 设定驳回标志
+		Map<String, Object> variables = new HashMap<String, Object>(0);
+		variables.put("outcome", outcome);
+		// 执行当前任务驳回到目标任务draft
+		taskService.complete(taskEntity.getId(), variables);
+		// 清除目标节点的新流入项
+		destActiviti.getIncomingTransitions().remove(newTransitionImpl);
+		// 清除原活动节点的临时流程项
+		currActiviti.getOutgoingTransitions().clear();
+		// 还原原活动节点流出项参数
+		currActiviti.getOutgoingTransitions().addAll(hisPvmTransitionList);
+	}*/
+
+	/**
+	 *
+	 * @Description (通过任务key,获取对应的节点信息)
+	 * @author liuwei
+	 * @Date 2021年11月3日下午1:53:29
+	 * @version 1.0.0
+	 * @param destTaskKey
+	 * @param processDefinitionId
+	 * @return
+	 */
+	/*public ActivityImpl getActivityImpl(String destTaskKey, String processDefinitionId) {
+		// 获得当前流程的定义模型
+		ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
+				.getDeployedProcessDefinition(processDefinitionId);
+
+		// 获得当前流程定义模型的所有任务节点
+
+		List<ActivityImpl> activitilist = processDefinition.getActivities();
+		// 获得当前活动节点和驳回的目标节点"draft"
+		ActivityImpl descActiviti = null;// 当前活动节点
+
+		for (ActivityImpl activityImpl : activitilist) {
+			// 获取节点对应的key
+			String taskKey = activityImpl.getId();
+			// 确定当前活动activiti节点
+			if (destTaskKey.equals(taskKey)) {
+				descActiviti = activityImpl;
+				break;
+			}
+		}
+		return descActiviti;
+	}*/
+}

+ 2 - 0
ruoyi-ui/src/components/Process/index.vue

@@ -37,10 +37,12 @@
           </div>
         </div>
       </el-header>
+      <!-- 流程设计页面 -->
       <el-container style="align-items: stretch">
         <el-main style="padding: 0;">
           <div ref="canvas" class="canvas" />
         </el-main>
+        <!--右侧属性栏-->
         <el-aside style="width: 400px; min-height: 650px; background-color: #f0f2f5">
           <panel v-if="modeler" :modeler="modeler" :users="users" :groups="groups" :exps="exps" :categorys="categorys" />
         </el-aside>

+ 1 - 0
ruoyi-ui/src/views/flowable/definition/index.vue

@@ -298,6 +298,7 @@ export default {
       formList: [],
       formTotal:0,
       formConf: {}, // 默认表单数据
+      formData: {}, // 默认表单数据
       readImage:{
         open: false,
         src: "",

+ 1 - 1
ruoyi-ui/src/views/invest/components/fileItem.vue

@@ -167,4 +167,4 @@ export default {
 }
 .fileBox {
 }
-</style>
+</style>

+ 1 - 1
ruoyi-ui/src/views/invest/pool/detail.vue

@@ -644,4 +644,4 @@ export default {
   margin-left: 10px;
 }
 
-</style>
+</style>