最近接手公司的crm系统,针对原先的工作流模块方面进行业务拓展 新增了转办、驳回到任意节点(跳回驳回节点)、跳过相同审批人等业务。
原系统activiti版本是6.0,之前只接触过5.x版本。acitviti6.x版本把pvm包都删了,执行计划的代码也进行了改造
参考了segmentfault.com/a/119000001… 大侠的博客
1:获取历史执行节点
/**
* 记录当前操作人为节点审批人 记录审批时长
* @Author: ruiwu
* @param param 转办他人参数
* @return 状态值
* @CreateDate: 2021/2/20 10:17
* @version: 1.0
* @status: done
*/
public List<HisNodeVo> getRunNodes(String procInstId) {
//procInstId 流程实例id
//查询流程运行到哪个节点了
Execution execution = runtimeService.createExecutionQuery()
.processInstanceId(procInstId)
.orderByProcessInstanceId()
.desc()
.list().get(0);
String activityId = execution.getActivityId();
Map<String,String> map= new LinkedHashMap<>();
// 获取流程历史中已执行节点,并按照节点在流程中执行先后顺序排序
List<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery()
.processInstanceId(procInstId)
//用户任务
.activityType("userTask")
//已经执行的任务节点
.finished()
.orderByHistoricActivityInstanceEndTime()
.asc()
.list();
// 已执行的节点ID集合
if(CollUtil.isNotEmpty(historicActivityInstanceList)){
for (HistoricActivityInstance historicActivityInstance:historicActivityInstanceList){
String hisActId = historicActivityInstance.getActivityId();
if (hisActId.equals(activityId)){
break;
}
if(!map.containsKey(historicActivityInstance.getActivityId())){
map.put(historicActivityInstance.getActivityId(),historicActivityInstance.getActivityName());
}
}
}
if (CollUtil.isNotEmpty(map)){
return map.entrySet()
.stream()
.map(HisNodeVo::new)
.collect(Collectors.toList());
}
return Collections.emptyList();
}
此处引用了lombox
@Data
@ApiModel("历史节点")
@NoArgsConstructor
public class HisNodeVo {
@ApiModelProperty("节点id")
private String activityId;
@ApiModelProperty("节点名")
private String activityName;
public HisNodeVo(Entry<String, String> node) {
this.activityId = node.getKey();
this.activityName = node.getValue();
}
}
实现效果
2:驳回
public BaseResult<String> approve(ApproveParam param) {
// 办理人userId
String taskId = param.getTaskId();
// 审核意见
String opinion = param.getOpinion();
// 审批人的姓名+审批意见
Map<String, Object> map = new LinkedHashMap<>();
// 设置审批人
map.put(Constants.APPROVER_KEY,
Optional.ofNullable(SecurityUser.getUserId()).orElse(""));
// 审批 批准
if (param.getApproveStatus() == 0) {
//当前任务
Task currentTask = taskService.createTaskQuery().taskId(taskId).singleResult();
String executionId = currentTask.getExecutionId();
//获取流程定义
Object variable = runtimeService.getVariable(executionId,"turnDownNode");
if (variable != null){
String nodeAssign = runtimeService
.getVariable(executionId,"turnDownNodeAssign").toString();
map.put(Constants.COMMENTS_KEY, "【批准】" + opinion);
//设置流程变量
setVariablesByTaskIdAsMap(taskId, map);
//驳回重新提交
String targetNodeId = String.valueOf(variable);
managementService.executeCommand(new SetFlowNodeAndGoCmd(
currentTask.getId(), targetNodeId,nodeAssign));
runtimeService.removeVariable (executionId, "turnDownNode");
}else{
//审批结果
map.put(Constants.COMMENTS_KEY, "【批准】" + opinion);
map.put("approvalResult", "同意");
boolean mark = StringUtils.isNotBlank(param.getProcInstType()) &&
(param.getProcInstType().contains(Constants.KEY_NEWCLASS) ||
param.getProcInstType().contains(Constants.KEY_PRECLASS));
taskService.setAssignee(taskId,SecurityUser.getUserId());
// 设置流程变量
setVariablesByTaskIdAsMap(taskId, map);
setVariablesByTaskId(taskId, "批准");
//审批结果添加到缓存
cacheService.set(Constants.COMMENTS_KEY + param.getProcInstId(), Constant.ONE + "");
//完成任务
completeMyPersonalTask(taskId);
}
} else {
//驳回
map.put(Constants.COMMENTS_KEY, "【驳回】" + opinion);
map.put("approvalResult", "驳回");
//设置流程变量
setVariablesByTaskIdAsMap(taskId, map);
if (param.getApproveType() == Constant.FAIL){
setVariablesByTaskId(taskId, "驳回");
//审批结果添加到缓存
cacheService.set(Constants.COMMENTS_KEY + param.getProcInstId(), Constant.FAIL + "");
//完成任务
completeMyPersonalTask(taskId);
//记录流程状态-可忽略
this.updateProcessStatus(param.getProcInstId(),Constant.TWO);
}else{
//驳回到任意节点
//历史节点执行人
String targetNodeAssign = this.getRunNodes(param.getProcInstId(), param.getRunNodeId());
log.info("驳回 历史节点执行人= " + targetNodeAssign);
//当前任务
if (param.getTurnType() == Constant.ONE){
Task currentTask = taskService.createTaskQuery().taskId(taskId).singleResult();
String executionId = currentTask.getExecutionId();
//驳回到目标节点携带参数,标记当前节点,然后直接跳转
runtimeService.setVariable (executionId, "turnDownNode",
currentTask.getTaskDefinitionKey());
runtimeService.setVariable (executionId, "turnDownNodeAssign",
currentTask.getAssignee());
}
managementService.executeCommand(new SetFlowNodeAndGoCmd(
param.getTaskId(), param.getRunNodeId() ,targetNodeAssign));
}
//驳回推送钉钉消息-可忽略
ruTaskService.sendRejectProcessNotice(param.getProcInstId());
}
return new BaseResult<String>().ok();
}
/**
* 根据提供节点和执行对象id,进行跳转命令
* @author yzyx
*/
@Slf4j
public class SetFlowNodeAndGoCmd implements Command<Void> {
/**
* 任务id
*/
private String taskId;
/**
* 目标节点
*/
private String runNodeId;
/**
* 目标节点审批人
*/
private String targetNodeAssign;
public SetFlowNodeAndGoCmd(String taskId,String runNodeId,String targetNodeAssign){
this.taskId = taskId;
this.runNodeId = runNodeId;
this.targetNodeAssign = targetNodeAssign;
}
@Override
public Void execute(CommandContext commandContext){
ActivitiEngineAgenda agenda = commandContext.getAgenda();
TaskEntityManager taskEntityManager = commandContext.getTaskEntityManager();
TaskEntity taskEntity = taskEntityManager.findById(taskId);
// 执行实例 id
String executionId = taskEntity.getExecutionId();
log.info("executionId = " + executionId);
String processDefinitionId = taskEntity.getProcessDefinitionId();
ExecutionEntityManager executionEntityManager = commandContext.getExecutionEntityManager();
HistoryManager historyManager = commandContext.getHistoryManager();
// 执行实例对象
ExecutionEntity executionEntity = executionEntityManager.findById(executionId);
Process process = ProcessDefinitionUtil.getProcess(processDefinitionId);
FlowElement flowElement = process.getFlowElement(runNodeId);
if (flowElement == null) {
throw new RuntimeException("目标节点不存在");
}
executionEntity.setVariable("USER_ID",targetNodeAssign);
//去掉无用的变量,不去掉,会导致很多莫名奇妙的问题
executionEntity.removeVariable("loopCounter");
//去掉多实例的变量,如果变量不知道是啥,自己从节点定义里查
executionEntity.removeVariable("cdp_atuser");
//要激活交路径
executionEntity.setActive(true);
// 将历史活动表更新
historyManager.recordActivityEnd(executionEntity, "jump");
// 设置当前流程
executionEntity.setCurrentFlowElement(flowElement);
// 跳转, 触发执行实例运转
agenda.planContinueProcessInCompensation(executionEntity);
// 从runtime 表中删除当前任务
taskEntityManager.delete(taskId);
// 将历史任务表更新, 历史任务标记为完成
historyManager.recordTaskEnd(taskId, "jump");
return null;
}
}
/***
* 查询历史节点执行人
* @param procInstId procInstId
* @param targetNodeId 目标节点
* @return 执行人
*/
private String getRunNodes(String procInstId, String targetNodeId) {
String assignee =SecurityUser.getUserId();
// 获取流程历史中已执行节点,并按照节点在流程中执行先后顺序排序
List<HistoricActivityInstance> instanceList = historyService.createHistoricActivityInstanceQuery()
.processInstanceId(procInstId)
//用户任务
.activityId(targetNodeId)
//已经执行的任务节点
.finished()
.orderByHistoricActivityInstanceEndTime()
.asc()
.list();
if (CollUtil.isNotEmpty(instanceList)){
assignee = instanceList.get(0).getAssignee();
}
Date endTime = instanceList.get(0).getEndTime();
if (CollUtil.isNotEmpty(instanceList)){
for (HistoricActivityInstance activityInstance : instanceList) {
if (activityInstance.getActivityType().equals("olduserTask")){
assignee = activityInstance.getAssignee();
break;
}else{
if (endTime.getTime() < activityInstance.getEndTime().getTime()){
endTime = activityInstance.getEndTime();
assignee = activityInstance.getAssignee();
}
}
}
}
return assignee;
}
@Data
@ApiModel("审批参数")
public class ApproveParam {
@ApiModelProperty("任务Id")
private String taskId;
@ApiModelProperty("流程实例id")
private String procInstId;
@ApiModelProperty("通过-0,拒绝-1")
private int approveStatus;
@ApiModelProperty("0 驳回到发起节点 即原先的驳回重新提交 1 驳回到非发起节点")
private int approveType = 0;
@ApiModelProperty("审核意见")
private String opinion;
@ApiModelProperty(value = "流程类型")
private String procInstType;
@ApiModelProperty("开班申请需-传教师Id")
private String teacherId;
@ApiModelProperty("驳回 指定的运行节点id")
private String runNodeId;
@ApiModelProperty("0 驳回重新流转 1驳回审批通过后返回本节点")
private int turnType;
}