增加任务流程预测功能,预测未审批等待审批的任务流程。

This commit is contained in:
kemengkai 2022-05-16 16:25:16 +08:00
parent d43006dce8
commit a0d574ad20
11 changed files with 380 additions and 326 deletions

View File

@ -65,7 +65,6 @@
<tencentcloud-sdk-java.version>3.1.471</tencentcloud-sdk-java.version>
<yunpian-java-sdk.version>1.2.7</yunpian-java-sdk.version>
<justauth.version>1.4.0</justauth.version>
<dom4j.version>2.1.3</dom4j.version>
</properties>
<dependencyManagement>
@ -579,13 +578,6 @@
<artifactId>justauth-spring-boot-starter</artifactId> <!-- 社交登陆(例如说,个人微信、企业微信等等) -->
<version>${justauth.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.dom4j/dom4j -->
<!-- XML读写框架 -->
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>${dom4j.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

View File

@ -10,10 +10,6 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>yudao-module-bpm-biz</artifactId>
<properties>
<dom4j.version>2.1.3</dom4j.version>
</properties>
<name>${project.artifactId}</name>
<description>
bpm-base 模块,实现公用的工作流的逻辑,提供给 bpm-activiti 和 bpm-flowable 复用
@ -30,6 +26,11 @@
<artifactId>yudao-module-system-api</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-system-biz</artifactId>
<version>${revision}</version>
</dependency>
<!-- 业务组件 -->
<dependency>
@ -85,11 +86,10 @@
<version>1.4.196</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.dom4j/dom4j -->
<!-- XML读写框架 -->
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.1.3</version>
</dependency>
</dependencies>
</project>

View File

@ -7,9 +7,6 @@ import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.apache.ibatis.annotations.Param;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.engine.TaskService;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@ -18,7 +15,6 @@ import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
import java.util.Objects;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
@ -55,13 +51,6 @@ public class BpmTaskController {
return success(taskService.getTaskListByProcessInstanceId(processInstanceId));
}
@GetMapping("/get")
@ApiOperation(value = "获取审批单详情", notes = "包括完成的、未完成的")
@ApiImplicitParam(name = "taskId", value = "任务Id", required = true, dataTypeClass = String.class)
public CommonResult<Object> getTask(@Param("taskId") String processInstanceId) {
return success(taskService.getTaskInfo(processInstanceId));
}
@PutMapping("/approve")
@ApiOperation("通过任务")
@PreAuthorize("@ss.hasPermission('bpm:task:update')")

View File

@ -32,4 +32,6 @@ public interface BpmTaskAssignRuleMapper extends BaseMapperX<BpmTaskAssignRuleDO
.eq("task_definition_key", taskDefinitionKey));
}
}

View File

@ -21,6 +21,16 @@ public interface BpmTaskExtMapper extends BaseMapperX<BpmTaskExtDO> {
return selectList(BpmTaskExtDO::getTaskId, taskIds);
}
/**
* 查询全部任务
*
* @return 返回任务
*/
@TenantIgnore
default List<BpmTaskExtDO> listAll() {
return selectList();
}
/**
* 查询任务
*

View File

@ -67,15 +67,6 @@ public interface BpmTaskService {
*/
List<BpmTaskRespVO> getTaskListByProcessInstanceId(String processInstanceId);
/**
* 获取任务详情
*
* @param processInstanceId 流程实例的编号
*
* @return 流程任务列表
*/
List<BpmTaskRespVO> getTaskInfo(String processInstanceId);
/**
* 通过任务
*
@ -95,7 +86,6 @@ public interface BpmTaskService {
/**
* 回退任务
*
* @param userId 用户id
* @param reqVO 回退任务信息
*/
CommonResult<Boolean> backTask(BpmTaskBackReqVO reqVO);

View File

@ -18,8 +18,8 @@ import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmTaskExtMapper;
import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskAssignRuleTypeEnum;
import cn.iocoder.yudao.module.bpm.domain.enums.task.BpmProcessInstanceResultEnum;
import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService;
import cn.iocoder.yudao.module.business.hi.task.inst.service.HiTaskInstService;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import lombok.extern.slf4j.Slf4j;
@ -45,7 +45,6 @@ import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*;
/**
@ -79,6 +78,8 @@ public class BpmTaskServiceImpl implements BpmTaskService {
private BpmTaskAssignRuleMapper taskAssignRuleMapper;
@Resource
private BpmActivityMapper bpmActivityMapper;
@Resource
private HiTaskInstService hiTaskInstService;
@Override
public PageResult<BpmTaskTodoPageItemRespVO> getTodoTaskPage(Long userId, BpmTaskTodoPageReqVO pageVO) {
@ -160,22 +161,22 @@ public class BpmTaskServiceImpl implements BpmTaskService {
@Override
public List<BpmTaskRespVO> getTaskListByProcessInstanceId(String processInstanceId) {
// 获得任务列表
List<HistoricTaskInstance> tasks =
/* List<HistoricTaskInstance> tasks =
historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId)
.orderByHistoricTaskInstanceStartTime().desc() // 创建时间倒序
.list();
if (CollUtil.isEmpty(tasks)) {
return Collections.emptyList();
}
}*/
// 获得 TaskExtDO Map
// List<BpmTaskExtDO> bpmTaskExtDOList =
// taskExtMapper.selectListByTaskIds(convertSet(tasks, HistoricTaskInstance::getId));
List<BpmTaskExtDO> bpmTaskExtDOList = taskExtMapper.listByProcInstId(processInstanceId);
// List<BpmTaskExtDO> bpmTaskExtDOList = taskExtMapper.listByProcInstId(processInstanceId);
// List<BpmTaskExtDO> bpmTaskExtDOList = BpmTaskConvert.INSTANCE.distinct(tmpBpmTaskExtDOList);
// bpmTaskExtDOList.forEach(var -> log.info("var = " + var));
Map<String, BpmTaskExtDO> bpmTaskExtDoMap = convertMap(bpmTaskExtDOList, BpmTaskExtDO::getTaskId);
/*Map<String, BpmTaskExtDO> bpmTaskExtDoMap = convertMap(bpmTaskExtDOList, BpmTaskExtDO::getTaskId);
// 获得 ProcessInstance Map
HistoricProcessInstance processInstance = processInstanceService.getHistoricProcessInstance(processInstanceId);
// 获得 User Map
@ -183,28 +184,11 @@ public class BpmTaskServiceImpl implements BpmTaskService {
userIds.add(NumberUtils.parseLong(processInstance.getStartUserId()));
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds);
// 获得 Dept Map
Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));*/
// 拼接数据
return BpmTaskConvert.INSTANCE.convertList3(tasks, bpmTaskExtDoMap, processInstance, userMap, deptMap);
}
@Override
public List<BpmTaskRespVO> getTaskInfo(String processInstanceId) {
List<BpmTaskExtDO> bpmTaskExtDOList = taskExtMapper.listByProcInstId(processInstanceId);
Map<String, BpmTaskExtDO> bpmTaskExtDoMap = convertMap(bpmTaskExtDOList, BpmTaskExtDO::getTaskId);
// 获得 ProcessInstance Map
HistoricProcessInstance processInstance = processInstanceService.getHistoricProcessInstance(processInstanceId);
// 获得 User Map
Set<Long> userIds = bpmTaskExtDOList.stream().map(BpmTaskExtDO::getAssigneeUserId).collect(Collectors.toSet());
userIds.add(NumberUtils.parseLong(processInstance.getStartUserId()));
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds);
// 拼接数据
return new ArrayList<>();
List<BpmTaskExtDO> tmpBpmTaskExtDOList = taskExtMapper.listByProcInstId(processInstanceId);
return hiTaskInstService.taskGetComment(tmpBpmTaskExtDOList, "");
}
@Override

View File

@ -1,4 +1,4 @@
package net.lab1024.smartadmin.module.business.approve.camunda.hi.task.inst.domain;
package cn.iocoder.yudao.module.business.hi.task.inst.domain;
import lombok.AllArgsConstructor;
import lombok.Data;

View File

@ -1,4 +1,4 @@
package net.lab1024.smartadmin.module.business.approve.camunda.hi.task.inst.domain.vo;
package cn.iocoder.yudao.module.business.hi.task.inst.domain.vo;
import lombok.Data;
import java.util.Date;

View File

@ -0,0 +1,350 @@
package cn.iocoder.yudao.module.business.hi.task.inst.service;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskTodoPageItemRespVO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO;
import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmTaskAssignRuleMapper;
import cn.iocoder.yudao.module.bpm.domain.enums.definition.BpmTaskAssignRuleTypeEnum;
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.dept.DeptMapper;
import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.*;
import org.flowable.common.engine.impl.de.odysseus.el.ExpressionFactoryImpl;
import org.flowable.common.engine.impl.de.odysseus.el.util.SimpleContext;
import org.flowable.common.engine.impl.javax.el.ExpressionFactory;
import org.flowable.common.engine.impl.javax.el.ValueExpression;
import org.flowable.engine.*;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.variable.api.history.HistoricVariableInstance;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* [ ]
*
* @author 孟凯
* @version 1.0
*/
@Slf4j
@Service
public class HiTaskInstService {
@Resource
private HistoryService historyService;
@Resource
private RepositoryService repositoryService;
@Resource
private BpmTaskAssignRuleMapper bpmTaskAssignRuleMapper;
@Resource
private BpmProcessInstanceService processInstanceService;
@Resource
private AdminUserMapper adminUserApi;
@Resource
private DeptMapper deptMapper;
/**
* 获取任务具体流程信息
*
* @param taskList 任务信息
* @param approved 任意选择条件
*
* @return 返回流程信息
*/
@TenantIgnore
public List<BpmTaskRespVO> taskGetComment(List<BpmTaskExtDO> taskList, Object approved) {
BpmTaskExtDO task = taskList.get(taskList.size() - 1);
Map<String, BpmTaskExtDO> bpmTaskMap =
taskList.stream().collect(Collectors.toMap(BpmTaskExtDO::getTaskId, Function.identity()));
// 获得 ProcessInstance Map
HistoricProcessInstance procInst =
processInstanceService.getHistoricProcessInstance(task.getProcessInstanceId());
Map<Long, AdminUserDO> userDoMap =
adminUserApi.selectList().stream().collect(Collectors.toMap(AdminUserDO::getId, Function.identity()));
Map<Long, DeptDO> deptMap =
deptMapper.selectList().stream().collect(Collectors.toMap(DeptDO::getId, Function.identity()));
List<HistoricTaskInstance> hisTaskInstList =
historyService.createHistoricTaskInstanceQuery().processInstanceId(task.getProcessInstanceId())
.orderByHistoricTaskInstanceStartTime().desc().list();
LinkedList<BpmTaskRespVO> bpmTaskRespVOList =
nowTaskFormat(procInst, hisTaskInstList, bpmTaskMap, userDoMap, deptMap);
//ProcessInstanceId流程实例
String procInstId = task.getProcessInstanceId();
List<BpmTaskAssignRuleDO> tmpBpmTaskAssignRuleDOList =
bpmTaskAssignRuleMapper.selectListByProcessDefinitionId(task.getProcessDefinitionId(), null);
List<HistoricVariableInstance> hisVarInstList =
historyService.createHistoricVariableInstanceQuery().processInstanceId(procInstId).list();
Map<String, Object> hisVarInstMap = new HashMap<>();
for (HistoricVariableInstance hisVarInst : hisVarInstList) {
hisVarInstMap.put(hisVarInst.getVariableName(), hisVarInst.getValue());
}
hisVarInstMap.put("approved", approved);
//获取bpm模型对象
BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
getFlow(bpmnModel, task.getTaskDefKey(), tmpBpmTaskAssignRuleDOList, bpmTaskRespVOList, userDoMap, deptMap,
hisVarInstMap);
return bpmTaskRespVOList;
}
/**
* 格式化任务信息
*/
private LinkedList<BpmTaskRespVO> nowTaskFormat(HistoricProcessInstance procInst, List<HistoricTaskInstance> taskList,
Map<String, BpmTaskExtDO> bpmTaskExtDoMap, Map<Long, AdminUserDO> userMap, Map<Long, DeptDO> deptMap) {
LinkedList<BpmTaskRespVO> bpmTaskRespVOList = new LinkedList<>();
for (HistoricTaskInstance hisTaskInst : taskList) {
BpmTaskRespVO respVO = initRespVo(hisTaskInst, bpmTaskExtDoMap, procInst, userMap);
AdminUserDO user = userMap.get(Long.valueOf(hisTaskInst.getAssignee()));
if (BeanUtil.isNotEmpty(user)) {
respVO.setAssigneeUser(setUser(user));
DeptDO dept = deptMap.get(user.getDeptId());
if (BeanUtil.isNotEmpty(dept)) {
respVO.getAssigneeUser().setDeptName(dept.getName());
}
}
bpmTaskRespVOList.addFirst(respVO);
}
return bpmTaskRespVOList;
}
private BpmTaskRespVO initRespVo(Object taskInst, Map<String, BpmTaskExtDO> bpmTaskExtDoMap,
HistoricProcessInstance procInst, Map<Long, AdminUserDO> userMap) {
BpmTaskRespVO respVO = new BpmTaskRespVO();
if (taskInst instanceof HistoricTaskInstance) {
respVO = setBpmnTaskRespVo((HistoricTaskInstance)taskInst);
BeanUtil.copyProperties(taskInst, respVO);
BpmTaskExtDO bpmTaskExtDO = bpmTaskExtDoMap.get(respVO.getId());
if (ObjectUtil.isNotEmpty(bpmTaskExtDO)) {
BeanUtil.copyProperties(bpmTaskExtDO, respVO);
respVO.setId(bpmTaskExtDO.getTaskId());
}
}
if (taskInst instanceof BpmTaskExtDO) {
respVO = setBpmnTaskRespVo((BpmTaskExtDO)taskInst);
BeanUtil.copyProperties(taskInst, respVO);
}
// copyTo(bpmTaskExtDO, respVO);
if (procInst != null) {
AdminUserDO startUser = userMap.get(Long.valueOf(procInst.getStartUserId()));
if (BeanUtil.isEmpty(startUser)) {
throw new RuntimeException("查找不到审批用户!!!");
}
respVO.setProcessInstance(setProcInst(procInst, startUser));
}
return respVO;
}
private BpmTaskRespVO.User setUser(AdminUserDO bean) {
if (bean == null) {
return null;
}
BpmTaskRespVO.User user = new BpmTaskRespVO.User();
user.setId(bean.getId());
user.setNickname(bean.getNickname());
user.setDeptId(bean.getDeptId());
return user;
}
private BpmTaskRespVO setBpmnTaskRespVo(BpmTaskExtDO bean) {
if (bean == null) {
return null;
}
BpmTaskRespVO bpmTaskRespVO = new BpmTaskRespVO();
bpmTaskRespVO.setDefinitionKey(bean.getTaskDefKey());
bpmTaskRespVO.setId(bean.getTaskId());
bpmTaskRespVO.setName(bean.getName());
bpmTaskRespVO.setCreateTime(bean.getCreateTime());
return bpmTaskRespVO;
}
public BpmTaskRespVO setBpmnTaskRespVo(HistoricTaskInstance bean) {
if (bean == null) {
return null;
}
BpmTaskRespVO bpmTaskRespVO = new BpmTaskRespVO();
bpmTaskRespVO.setDefinitionKey(bean.getTaskDefinitionKey());
bpmTaskRespVO.setId(bean.getId());
bpmTaskRespVO.setName(bean.getName());
bpmTaskRespVO.setClaimTime(bean.getClaimTime());
bpmTaskRespVO.setCreateTime(bean.getCreateTime());
bpmTaskRespVO.setEndTime(bean.getEndTime());
bpmTaskRespVO.setDurationInMillis(bean.getDurationInMillis());
return bpmTaskRespVO;
}
public BpmTaskTodoPageItemRespVO.ProcessInstance setProcInst(HistoricProcessInstance processInstance,
AdminUserDO startUser) {
if (processInstance == null && startUser == null) {
return null;
}
BpmTaskTodoPageItemRespVO.ProcessInstance processInstanceResult =
new BpmTaskTodoPageItemRespVO.ProcessInstance();
if (processInstance != null) {
processInstanceResult.setId(processInstance.getId());
processInstanceResult.setName(processInstance.getName());
if (processInstance.getStartUserId() != null) {
processInstanceResult.setStartUserId(Long.parseLong(processInstance.getStartUserId()));
}
processInstanceResult.setProcessDefinitionId(processInstance.getProcessDefinitionId());
}
if (startUser != null) {
processInstanceResult.setStartUserNickname(startUser.getNickname());
}
return processInstanceResult;
}
private void getFlow(BpmnModel bpmnModel, String taskDefKey, List<BpmTaskAssignRuleDO> tmpBpmTaskAssignRuleDOList,
LinkedList<BpmTaskRespVO> bpmTaskRespVOList, Map<Long, AdminUserDO> userDoMap, Map<Long, DeptDO> deptMap,
Map<String, Object> taskVarMap) {
//传节点定义key获取当前节点
FlowNode flowNode = (FlowNode)bpmnModel.getFlowElement(taskDefKey);
//输出连线
List<SequenceFlow> outgoingFlows = flowNode.getOutgoingFlows();
//遍历返回下一个节点信息
for (SequenceFlow outgoingFlow : outgoingFlows) {
//类型自己判断获取下个节点是网关还是节点
FlowElement targetFlowElement = outgoingFlow.getTargetFlowElement();
getFlow(bpmnModel, targetFlowElement, tmpBpmTaskAssignRuleDOList, bpmTaskRespVOList, userDoMap, deptMap,
taskVarMap);
}
}
private void getFlow(BpmnModel bpmnModel, FlowElement targetFlowElement,
List<BpmTaskAssignRuleDO> tmpBpmTaskAssignRuleDOList, LinkedList<BpmTaskRespVO> bpmTaskRespVOList,
Map<Long, AdminUserDO> userDoMap, Map<Long, DeptDO> deptMap, Map<String, Object> taskVarMap) {
// 下一个taskDefKey
String nextTaskDefKey = null;
//下个是节点
if (targetFlowElement instanceof UserTask) {
// 判断是否是为并行任务
List<BpmTaskAssignRuleDO> bpmTaskAssignRuleDOList = tmpBpmTaskAssignRuleDOList.stream().filter(
bpmTaskAssignRuleDO -> bpmTaskAssignRuleDO.getTaskDefinitionKey().equals(targetFlowElement.getId()))
.collect(Collectors.toList());
if (CollUtil.isEmpty(bpmTaskAssignRuleDOList)) {
throw new RuntimeException("任务key不存在!!!");
}
for (BpmTaskAssignRuleDO bpmTaskAssignRuleDO : bpmTaskAssignRuleDOList) {
nextTaskDefKey = bpmTaskAssignRuleDO.getTaskDefinitionKey();
for (Long userId : bpmTaskAssignRuleDO.getOptions()) {
BpmTaskRespVO bpmTaskRespVO =
(BpmTaskRespVO)new BpmTaskRespVO().setName(targetFlowElement.getName());
bpmTaskRespVOList.addFirst(bpmTaskRespVO);
AdminUserDO adminUserDO = userDoMap.get(userId);
DeptDO deptDO = deptMap.get(adminUserDO.getDeptId());
bpmTaskRespVO.setAssigneeUser(setUser(adminUserDO));
bpmTaskRespVO.getAssigneeUser().setDeptName(deptDO.getName());
if (!bpmTaskAssignRuleDO.getType().equals(BpmTaskAssignRuleTypeEnum.USER_OR_SIGN.getType())
&& !bpmTaskAssignRuleDO.getType().equals(BpmTaskAssignRuleTypeEnum.USER_SIGN.getType())) {
break;
}
}
}
getFlow(bpmnModel, nextTaskDefKey, tmpBpmTaskAssignRuleDOList, bpmTaskRespVOList, userDoMap, deptMap,
taskVarMap);
// 下个节点是网关调用下面的方法
} else if (targetFlowElement instanceof ExclusiveGateway) {
String defaultFlow = ((ExclusiveGateway)targetFlowElement).getDefaultFlow();
FlowElement nexFlowElement = getExclusiveGateway(targetFlowElement, taskVarMap, defaultFlow);
getFlow(bpmnModel, nexFlowElement, tmpBpmTaskAssignRuleDOList, bpmTaskRespVOList, userDoMap, deptMap,
taskVarMap);
}
}
/**
* 获取排他网关分支名称分支表达式下一级任务节点
*
* @param flowElement 任务节点
* @param taskVarMap 审批数据
*/
private FlowElement getExclusiveGateway(FlowElement flowElement, Map<String, Object> taskVarMap,
String defaultFlow) {
// 获取所有网关分支
List<SequenceFlow> targetFlows = ((ExclusiveGateway)flowElement).getOutgoingFlows();
Boolean elExpressionFlag = Boolean.FALSE;
FlowElement sequenceFlowResult = null;
FlowElement defaultSequenceFlow = null;
// 循环每个网关分支
for (SequenceFlow sequenceFlow : targetFlows) {
if (defaultFlow.equals(sequenceFlow.getId())) {
defaultSequenceFlow = sequenceFlow.getTargetFlowElement();
continue;
}
elExpressionFlag = elExpression(sequenceFlow.getConditionExpression(), taskVarMap);
if (elExpressionFlag) {
// 获取下一个网关和节点数据
FlowElement targetFlowElement = sequenceFlow.getTargetFlowElement();
// 网关的下个节点是用户节点
if (targetFlowElement instanceof UserTask) {
sequenceFlowResult = targetFlowElement;
break;
} else if (targetFlowElement instanceof EndEvent) {
log.info("排他网关的下一节点是EndEvent: 结束节点");
} else if (targetFlowElement instanceof ServiceTask) {
log.info("排他网关的下一节点是ServiceTask: 内部方法");
} else if (targetFlowElement instanceof ExclusiveGateway) {
defaultFlow = ((ExclusiveGateway)targetFlowElement).getDefaultFlow();
return getExclusiveGateway(targetFlowElement, taskVarMap, defaultFlow);
} else if (targetFlowElement instanceof SubProcess) {
log.info("排他网关的下一节点是SubProcess: 内部子流程");
}
}
}
if (!elExpressionFlag) {
if (defaultSequenceFlow instanceof UserTask) {
sequenceFlowResult = defaultSequenceFlow;
} else if (defaultSequenceFlow instanceof ExclusiveGateway) {
defaultFlow = ((ExclusiveGateway)defaultSequenceFlow).getDefaultFlow();
return getExclusiveGateway(defaultSequenceFlow, taskVarMap, defaultFlow);
}
}
return sequenceFlowResult;
}
/**
* 网关分叉条件判断网关分叉必须要有默认出口
*
* @param elExpression el表达式
* @param variableMap 流程所有变量
*
* @return 返回true或false
*/
private Boolean elExpression(String elExpression, Map<String, Object> variableMap) {
ExpressionFactory factory = new ExpressionFactoryImpl();
SimpleContext context = new SimpleContext();
for (String k : variableMap.keySet()) {
if (variableMap.get(k) != null) {
context.setVariable(k,
factory.createValueExpression(variableMap.get(k), variableMap.get(k).getClass()));
}
}
ValueExpression e = factory.createValueExpression(context, elExpression, Boolean.class);
//el表达式和variables得到的结果
return (Boolean)e.getValue(context);
}
}

View File

@ -1,263 +0,0 @@
package cn.iocoder.yudao.module.business.hi.task.inst.service;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.module.bpm.domain.vo.ApproveProcInstVO;
import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.impl.de.odysseus.el.util.SimpleContext;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.TaskService;
import org.flowable.variable.api.history.HistoricVariableInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
/**
* [ ]
*
* @author 孟凯
* @version 1.0
* @company 1024创新实验室(www.1024lab.net)
* @copyright (c) 1024创新实验室( www.1024lab.net )Inc. All rights reserved.
* @date 2022-01-17 15:14:27
* @since JDK1.8
*/
@Slf4j
@Service
public class HiTaskinstService {
@Autowired
private TaskService taskService;
@Autowired
private HistoryService historyService;
@Autowired
private RepositoryService repositoryService;
/**
* 获取任务具体流程信息
*
* @param procInstId 流程id
* @param procDefId 流程部署id
*
* @return 返回流程信息
*/
public List<ApproveProcInstVO> taskGetComment(String procInstId, String procDefId) {
Map<String, Object> variableMap = new HashMap<>(50);
List<HistoricVariableInstance> hisVarInstList =
historyService.createHistoricVariableInstanceQuery().processInstanceId(procInstId).list();
hisVarInstList.forEach(hisVarInst -> {
variableMap.put(hisVarInst.getName(), hisVarInst.getValue());
});
List<ApproveProcInstVO> procInstVOList = hiTaskinstDao.listByProcInstIdAndNotDelete(procInstId);
BpmnModelInstance bpmnModelInstance = repositoryService.getBpmnModel(procDefId);
DomElement document1 = bpmnModelInstance.getDocument().getElementById(procDefId.split(":")[0]);
LinkedHashMap<String, DomElement> domElementMap = new LinkedHashMap<>(50);
getChildElementToMap(document1, domElementMap);
getChildNode(procInstVOList, domElementMap, variableMap);
return procInstVOList;
}
/**
* 获取子节点信息存储到map中
*
* @param domElement 父节点
* @param domElementMap 节点map
*/
private void getChildElementToMap(DomElement domElement, LinkedHashMap<String, DomElement> domElementMap) {
List<DomElement> childElements = domElement.getChildElements();
for (DomElement childElement : childElements) {
if ("BPMNDiagram".equals(childElement.getLocalName())) {
break;
}
if ("extensionElements".equals(childElement.getLocalName())) {
break;
}
if (!"outgoing".equals(childElement.getLocalName()) && !"incoming".equals(childElement.getLocalName())) {
domElementMap.put(childElement.getAttribute("id"), childElement);
}
getChildElementToMap(childElement, domElementMap);
}
}
/**
* 获取子节点信息
*
* @param procInstVOList 流程VO列表
* @param domElementMap 节点map
* @param variableMap 流程所有的变量
*/
private void getChildNode(List<ApproveProcInstVO> procInstVOList, LinkedHashMap<String, DomElement> domElementMap,
Map<String, Object> variableMap) {
DomElement domElement = domElementMap.get(procInstVOList.get(procInstVOList.size() - 1).getTaskDefKey());
for (DomElement childElement : domElement.getChildElements()) {
if ("outgoing".equals(childElement.getLocalName())) {
DomElement tmpDomElement = domElementMap.get(childElement.getTextContent());
getChildNode(procInstVOList, domElementMap, variableMap, tmpDomElement);
}
}
}
/**
* 获取子节点信息
*
* @param procInstVOList 流程VO列表
* @param domElementMap 节点map
* @param variableMap 流程所有的变量
* @param domElement 父节点信息
*/
private void getChildNode(List<ApproveProcInstVO> procInstVOList, LinkedHashMap<String, DomElement> domElementMap,
Map<String, Object> variableMap, DomElement domElement) {
if ("exclusiveGateway".equals(domElement.getLocalName())) {
DomElement domElementChild = getNodeExclusiveGateway(domElementMap, variableMap, domElement);
getChildNode(procInstVOList, domElementMap, variableMap, domElementChild);
} else if ("userTask".equals(domElement.getLocalName())) {
getProcInstVO(procInstVOList, domElement, variableMap);
for (DomElement childElement : domElement.getChildElements()) {
if ("outgoing".equals(childElement.getLocalName())) {
DomElement tmpDomElement = domElementMap.get(childElement.getTextContent());
DomElement domElementChild = getNodeBySequenceFlow(domElementMap, tmpDomElement);
if ("endEvent".equals(domElementChild.getLocalName())) {
return;
}
getChildNode(procInstVOList, domElementMap, variableMap, domElementChild);
}
}
} else {
DomElement domElementChild = getNodeBySequenceFlow(domElementMap, domElement);
if (BeanUtil.isEmpty(domElementChild)) {
throw new RuntimeException("无流程可执行!!!");
}
if ("endEvent".equals(domElementChild.getLocalName())) {
return;
}
getChildNode(procInstVOList, domElementMap, variableMap, domElementChild);
}
}
/**
* 获取网关节点的子节点
*
* @param domElementMap 流程所有的节点
* @param variableMap 流程所有的变量
* @param domElement 父节点信息
*
* @return 返回子节点信息
*/
private DomElement getNodeExclusiveGateway(LinkedHashMap<String, DomElement> domElementMap,
Map<String, Object> variableMap, DomElement domElement) {
Boolean elExpressionFlag = Boolean.FALSE;
ArrayList<DomElement> nullChildSequenceFlowList = new ArrayList<>();
for (DomElement exclusiveGatewayChild : domElement.getChildElements()) {
if ("outgoing".equals(exclusiveGatewayChild.getLocalName()) && BooleanUtil.isFalse(elExpressionFlag)) {
DomElement sequenceFlowDomElement = domElementMap.get(exclusiveGatewayChild.getTextContent());
if (CollUtil.isNotEmpty(sequenceFlowDomElement.getChildElements())
&& sequenceFlowDomElement.getChildElements().size() > 0) {
for (DomElement conditionExpression : sequenceFlowDomElement.getChildElements()) {
if ("conditionExpression".equals(conditionExpression.getLocalName())) {
elExpressionFlag = elExpression(conditionExpression.getTextContent(), variableMap);
if (BooleanUtil.isTrue(elExpressionFlag)) {
break;
}
}
}
} else {
nullChildSequenceFlowList.add(sequenceFlowDomElement);
}
if (elExpressionFlag) {
return getNodeBySequenceFlow(domElementMap, sequenceFlowDomElement);
}
}
}
if (CollUtil.isEmpty(nullChildSequenceFlowList) && nullChildSequenceFlowList.size() < 1) {
throw new RuntimeException("网关缺少无条件流程可执行!!!");
}
if (nullChildSequenceFlowList.size() > 1) {
throw new RuntimeException("无条件流程大于1条");
}
return getNodeBySequenceFlow(domElementMap, nullChildSequenceFlowList.get(0));
}
/**
* 获取流程序列流的子节点
*
* @param domElementMap 流程所有节点
* @param domElement 父节点信息
*
* @return 返回子节点
*/
private DomElement getNodeBySequenceFlow(LinkedHashMap<String, DomElement> domElementMap, DomElement domElement) {
String targetRef = domElement.getAttribute("targetRef");
return domElementMap.get(targetRef);
}
/**
* 设置节点信息进ApproveProcInstVO
*
* @param procInstVOList ApproveProcInstVOList
* @param domElement 节点信息
* @param variableMap 流程所有变量
*/
private void getProcInstVO(List<ApproveProcInstVO> procInstVOList, DomElement domElement,
Map<String, Object> variableMap) {
String camundaNameSpaceUri = "http://camunda.org/schema/1.0/bpmn";
boolean userListFlag = false;
List<Object> approveProcInstVOList = new ArrayList<>();
for (DomElement childElement : domElement.getChildElements()) {
if ("multiInstanceLoopCharacteristics".equals(childElement.getLocalName())) {
userListFlag = true;
String collectionVar = childElement.getAttribute(camundaNameSpaceUri, "collection");
Object taskUserList = variableMap.get(collectionVar);
approveProcInstVOList = JSONUtil.parseArray(taskUserList);
}
}
if (userListFlag) {
approveProcInstVOList.forEach(tmpAssignee -> {
String assignee = String.valueOf(tmpAssignee);
ApproveProcInstVO approveProcInstVO = new ApproveProcInstVO();
approveProcInstVO.setName(domElement.getAttribute("name"));
approveProcInstVO.setTaskDefKey(domElement.getAttribute("id"));
approveProcInstVO.setAssignee(assignee);
approveProcInstVO.setAssigneeName(employeeDao.getByLoginName(assignee, 0).getActualName());
procInstVOList.add(approveProcInstVO);
});
} else {
ApproveProcInstVO approveProcInstVO = new ApproveProcInstVO();
approveProcInstVO.setName(domElement.getAttribute("name"));
approveProcInstVO.setTaskDefKey(domElement.getAttribute("id"));
approveProcInstVO.setAssignee(domElement.getAttribute(camundaNameSpaceUri, "assignee"));
approveProcInstVO.setAssigneeName(
employeeDao.getByLoginName(approveProcInstVO.getAssignee(), 0).getActualName());
procInstVOList.add(approveProcInstVO);
}
}
/**
* 网关分叉条件判断网关分叉必须要有默认出口
*
* @param elExpression el表达式
* @param variableMap 流程所有变量
*
* @return 返回true或false
*/
private Boolean elExpression(String elExpression, Map<String, Object> variableMap) {
ExpressionFactory factory = new ExpressionFactoryImpl();
SimpleContext context = new SimpleContext();
for (String k : variableMap.keySet()) {
if (variableMap.get(k) != null) {
context.setVariable(k,
factory.createValueExpression(variableMap.get(k), variableMap.get(k).getClass()));
}
}
ValueExpression e = factory.createValueExpression(context, elExpression, Boolean.class);
//el表达式和variables得到的结果
return (Boolean)e.getValue(context);
}
}