/*
|
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
|
*
|
* Redistribution and use in source and binary forms, with or without
|
* modification, are permitted provided that the following conditions are met:
|
*
|
* Redistributions of source code must retain the above copyright notice,
|
* this list of conditions and the following disclaimer.
|
* Redistributions in binary form must reproduce the above copyright
|
* notice, this list of conditions and the following disclaimer in the
|
* documentation and/or other materials provided with the distribution.
|
* Neither the name of the dreamlu.net developer nor the names of its
|
* contributors may be used to endorse or promote products derived from
|
* this software without specific prior written permission.
|
* Author: Chill 庄骞 (smallchill@163.com)
|
*/
|
package com.vci.ubcs.flow.engine.service.impl;
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.vci.ubcs.flow.core.constant.ProcessConstant;
|
import com.vci.ubcs.flow.core.dto.FlowTaskDTO;
|
import com.vci.ubcs.flow.core.dto.ProcessStageAttrDTO;
|
import com.vci.ubcs.flow.core.entity.BladeFlow;
|
import com.vci.ubcs.flow.core.entity.FlowTaskUser;
|
import com.vci.ubcs.flow.core.entity.ProcessStageAttr;
|
import com.vci.ubcs.flow.core.utils.TaskUtil;
|
import com.vci.ubcs.flow.engine.entity.*;
|
import com.vci.ubcs.flow.engine.service.FlowEngineService;
|
import com.vci.ubcs.flow.engine.service.FlowTaskUserService;
|
import com.vci.ubcs.flow.engine.service.ProcessStageAttrService;
|
import com.vci.ubcs.flow.engine.service.VICFlowService;
|
import com.vci.ubcs.starter.web.util.BeanUtil;
|
import lombok.AllArgsConstructor;
|
import lombok.extern.slf4j.Slf4j;
|
import org.apache.commons.lang3.StringUtils;
|
import org.flowable.bpmn.model.*;
|
import org.flowable.engine.*;
|
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
|
import org.flowable.engine.repository.ProcessDefinition;
|
import org.flowable.engine.runtime.ProcessInstance;
|
import org.flowable.task.api.Task;
|
import org.springblade.core.log.exception.ServiceException;
|
import org.springblade.core.mp.support.Condition;
|
import org.springblade.core.secure.utils.AuthUtil;
|
import org.springblade.core.tool.api.R;
|
import org.springblade.core.tool.support.Kv;
|
import org.springframework.stereotype.Service;
|
import java.util.*;
|
|
/**
|
* 工作流服务实现类
|
*
|
* @author Chill
|
*/
|
@Slf4j
|
@Service
|
@AllArgsConstructor
|
public class VCIFlowserviceImpl implements VICFlowService {
|
|
private final RuntimeService runtimeService;
|
private final IdentityService identityService;
|
private final RepositoryService repositoryService;
|
private final TaskService taskService;
|
private final FlowTaskUserService flowTaskUserService;
|
private final FlowEngineService flowEngineService;
|
private final HistoryService historyService;
|
private final ProcessStageAttrService processStageAttrService;
|
|
private static String MODELKEY = "modelKey";//前端传过来的模型key
|
private static String TASKID = "taskId";//前端传过来的模型key
|
private static String PROCESSINSTANCEID = "processInstanceId";//前端传过来的模型key
|
@Override
|
public R<BladeFlow> startProcess(FlowTaskDTO flowTaskUserC){
|
Map<String, Object> kvv = flowTaskUserC.getVariables();
|
|
String modelKey = kvv.get(MODELKEY).toString();
|
|
Kv kv = Kv.create().set(ProcessConstant.TASK_VARIABLE_CREATE_USER, AuthUtil.getUserName());
|
|
// 设置流程启动用户
|
identityService.setAuthenticatedUserId(TaskUtil.getTaskUser());
|
|
// 开启流程
|
//查询最新的流程部署id
|
ProcessDefinition latesDefinition = repositoryService.createProcessDefinitionQuery().latestVersion().processDefinitionKey(modelKey).singleResult();
|
String processDefinitionId = latesDefinition.getId();
|
|
//查询每一步审核人
|
List<FlowTaskUser> taskUsers = flowTaskUserC.getFlowTaskUsers();
|
// Set<String> taskIdSet = new HashSet<>();
|
for (FlowTaskUser taskUser:taskUsers){
|
kv.put(taskUser.getTaskId(),TaskUtil.getTaskUser(taskUser.getUserId()));
|
// taskIdSet.add(taskUser.getTaskId());
|
}
|
|
//对比配置的审核人员和流程中节点是否一致,可能存在流程节点变更了,多了或者少了节点,但是配置审核人员的节点没有变
|
// List<Map<String,String>> processTasks = flowEngineService.getNodeByFlowableKey(modelKey);
|
// for (Map<String,String> mi:processTasks){
|
// String taskId = mi.get(flowEngineService.getTaskIdString());
|
// if(!taskIdSet.contains(taskId)){
|
// throw new ServiceException("流程已重新部署,节点已改变,请设置审核人员!");
|
// }
|
// }
|
// if(taskIdSet.size()!=processTasks.size()){
|
// throw new ServiceException("流程已重新部署,节点已改变,请设置审核人员!");
|
// }
|
|
//流程中文件、变量等
|
if(kvv!=null&&!kvv.isEmpty()){
|
kv.putAll(kvv);
|
}
|
|
ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinitionId, modelKey, kv);
|
// 组装流程通用类
|
BladeFlow flow = new BladeFlow();
|
flow.setProcessInstanceId(processInstance.getId());
|
|
// //设置下一步审核人
|
// Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).active().singleResult();
|
// String taskId = task.getTaskDefinitionKey();
|
// String assignee = null;
|
// for (FlowTaskUser taskUser:taskUsers) {
|
// if(taskId.equals(taskUser.getTaskId())){
|
// assignee = taskUser.getUserId();
|
// }
|
// }
|
// if(StringUtils.isEmpty(assignee)){
|
// throw new ServiceException(taskId+"没有配置审核人!");
|
// }
|
// taskService.setAssignee(task.getId(),assignee);
|
return R.data(flow);
|
}
|
|
public static String NODE_NOW = "now";
|
public static String NODE_NEXT = "next";
|
/**
|
* 获取任务节点
|
*
|
* @param node 查询节点选择
|
* @param processInstanceId 流程实例id
|
*/
|
public FlowTaskDTO nextFlowNode(String node, String processInstanceId) {
|
FlowTaskDTO flowTaskDTO = new FlowTaskDTO();
|
List<FlowTaskDTO> taskList = new ArrayList<>();//节点按钮
|
flowTaskDTO.setToTasks(taskList);
|
|
Task task = taskService.createTaskQuery().processInstanceId(processInstanceId).active().singleResult();
|
ExecutionEntity ee = (ExecutionEntity) runtimeService.createExecutionQuery()
|
.executionId(task.getExecutionId()).singleResult();
|
// 当前审批节点
|
String crruentActivityId = ee.getActivityId();
|
BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
|
FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(crruentActivityId);
|
|
//这个实例的所有节点
|
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
|
Map<String, Object> processVariables = processInstance.getProcessVariables();//所有参数
|
flowTaskDTO.setVariables(processVariables);
|
|
String modelKey = processInstance.getProcessDefinitionKey();
|
List<FlowTaskDTO> mis = flowEngineService.getNodeByFlowableKey(modelKey);
|
Map<String,String> taskMap = new HashMap<>();
|
mis.stream().forEach(e->{
|
String taskId = e.getTaskId();
|
String taskName = e.getTaskName();
|
taskMap.put(taskId,taskName);
|
});
|
|
// 输出连线
|
List<SequenceFlow> outFlows = flowNode.getOutgoingFlows();
|
for (SequenceFlow sequenceFlow : outFlows) {
|
String toname = sequenceFlow.getName()==null?"同意":sequenceFlow.getName();
|
//当前审批节点
|
if (NODE_NOW.equals(node)) {
|
FlowElement sourceFlowElement = sequenceFlow.getSourceFlowElement();
|
System.out.println("当前节点: id=" + sourceFlowElement.getId() + ",name=" + sourceFlowElement.getName());
|
} else if (NODE_NEXT.equals(node)) {
|
// 下一个审批节点
|
FlowElement targetFlow = sequenceFlow.getTargetFlowElement();
|
if (targetFlow instanceof UserTask) {
|
FlowTaskDTO flowTaskUserCi = new FlowTaskDTO();
|
//flowTaskUserCi.setConditionKey(null);
|
//flowTaskUserCi.setConditionValue(null);
|
flowTaskUserCi.setToName(toname);
|
flowTaskUserCi.setToTaskId(targetFlow.getId());
|
String taskName = taskMap.get(targetFlow.getId());
|
flowTaskUserCi.setToTaskName(taskName);
|
flowTaskUserCi.setTaskName(taskName);
|
taskList.add(flowTaskUserCi);
|
}
|
|
//结束
|
if (targetFlow instanceof EndEvent) {
|
FlowTaskDTO flowTaskUserCi = new FlowTaskDTO();
|
//flowTaskUserCi.setConditionKey(null);
|
//flowTaskUserCi.setConditionValue(null);
|
flowTaskUserCi.setToName("同意");
|
flowTaskUserCi.setToTaskId(targetFlow.getId());
|
flowTaskUserCi.setToTaskName(targetFlow.getName());
|
taskList.add(flowTaskUserCi);
|
}
|
// 如果下个审批节点为排他网关
|
if (targetFlow instanceof ExclusiveGateway) {
|
|
ExclusiveGateway exclusiveGateway = (ExclusiveGateway) targetFlow;
|
List<SequenceFlow> exclusiveGatewayOutgoingFlows = exclusiveGateway.getOutgoingFlows();
|
for (SequenceFlow nexti:exclusiveGatewayOutgoingFlows){
|
String conditionExpression = nexti.getConditionExpression();//condition
|
String taskId = nexti.getTargetRef();//taskId
|
String name = nexti.getName();//toName,驳回、同意
|
String taskName = taskMap.get(targetFlow.getId());
|
|
for (FlowTaskDTO flowTaskUserCi:mis){
|
if(taskId.equals(flowTaskUserCi.getTaskId())){
|
flowTaskUserCi.setCondition(conditionExpression);
|
if(conditionExpression.contains("=")||conditionExpression.contains("<")||conditionExpression.contains(">")) {
|
conditionExpression = conditionExpression.replace("${","").replace("}","").replaceAll("\"","");
|
String[] conditionExpressionStr = conditionExpression.split("==");
|
if(conditionExpression.contains("<")){
|
conditionExpressionStr = conditionExpression.split("<");
|
}else if(conditionExpression.contains("<=")){
|
conditionExpressionStr = conditionExpression.split("<=");
|
}else if(conditionExpression.contains(">")){
|
conditionExpressionStr = conditionExpression.split(">");
|
}else if(conditionExpression.contains(">=")){
|
conditionExpressionStr = conditionExpression.split(">=");
|
}
|
flowTaskUserCi.setConditionKey(conditionExpressionStr.length>0?conditionExpressionStr[0]:null);
|
flowTaskUserCi.setConditionValue(conditionExpressionStr.length>1?conditionExpressionStr[1]:null);
|
}
|
flowTaskUserCi.setToName(name);
|
flowTaskUserCi.setToTaskId(taskId);
|
flowTaskUserCi.setToTaskName(taskName);
|
flowTaskUserCi.setTaskName(taskName);
|
taskList.add(flowTaskUserCi);
|
}
|
}
|
}
|
}
|
}
|
}
|
|
//流程常量
|
Map<String,Object> variables = runtimeService.getVariables(processInstanceId);
|
if(!variables.isEmpty()){
|
flowTaskDTO.setVariables(variables);
|
}
|
|
//流程阶段
|
Map<String, Object> m = new HashMap<>();
|
String templateId = variables.get("templateId").toString();
|
m.put("template_id", templateId);
|
m.put("task_id", crruentActivityId);
|
m.put("model_key", modelKey);
|
QueryWrapper q = Condition.getQueryWrapper(m, ProcessStageAttr.class)
|
.select("attr_id attrId,attr_name attrName,attr_group attrGroup");
|
List<ProcessStageAttr> stageAttrs = processStageAttrService.list(q);
|
List<ProcessStageAttrDTO> stageAttrsDto = new ArrayList<>();
|
stageAttrs.stream().forEach(e->{
|
ProcessStageAttrDTO dto = new ProcessStageAttrDTO();
|
BeanUtil.convert(e,dto);
|
stageAttrsDto.add(dto);
|
});
|
flowTaskDTO.setStageAttrs(stageAttrsDto);
|
|
//放入流程阶段、流程modelkey
|
variables.put(TASKID,crruentActivityId);
|
variables.put(PROCESSINSTANCEID,processInstanceId);
|
return flowTaskDTO;
|
}
|
}
|