最近突然让我做一个工作流跳转和退回到指定节点,说是用activiti写的,这我哪会,直接措手不及啊
回去以后恶补了一下,大概是了解了,不多说,直接进入正题。
一上手,直接面向网络了一波,结果发现都让我改模型,改了不就崩了吗,我不能理解。
首先分析一下,要实现跳转得搞清楚几个问题,首先我们是改模型或者实例还是改数据(就是改这个流程现在的人员),首先排除改数据,数据改了,流程不还是继续往前吗,明显不行,再排除改模型,改了模型重新部署,这整个流程不就不对了吗,最后只剩下改实例了
//获取任务信息
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
// 获取实例id
String processDefinitionId = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult().getProcessDefinitionId();
// 获取模型配置信息
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
// 获取实例信息
Execution execution = runtimeService.createExecutionQuery().executionId(task.getExecutionId()).singleResult();
这个时候遇到问题了,完蛋了,我回退啥啊,我都不知道回退到哪,我咋回退,所以我们还需要写一个查询当前节点以前所有节点递归接口
/**
* 递归查找当前节点前用户节点
* @param currentFlowNode 当前节点
* @param map 所有节点map
* @param chooseNode 可选的节点集
* @return
*/
public List<FlowElement> recursionSearch(FlowNode currentFlowNode, Map<String, List<FlowElement>> map, List<FlowElement> chooseNode,List<SequenceFlow> lineList) {
// 获取输入线
List<SequenceFlow> incomingFlows = currentFlowNode.getIncomingFlows();
// 判断输入线类型
for (SequenceFlow incomingFlow : incomingFlows) {
// 判断是否是网关节点
if (map.get("gateway").stream().filter(e -> e.getId().equals(incomingFlow.getSourceRef())).collect(Collectors.toList()).size() > 0) {
//是网关节点,继续找上个节点找到后继续加入递归
List<FlowElement> gateway = map.get("gateway").stream().filter(e -> e.getId().equals(incomingFlow.getSourceRef())).collect(Collectors.toList());
FlowNode gatewayNode = (FlowNode)gateway.get(0);
List<SequenceFlow> gatewayNodeIncomingFlows = gatewayNode.getIncomingFlows();
List<SequenceFlow> outgoingFlows = gatewayNode.getOutgoingFlows();
if(gatewayNodeIncomingFlows.size() > 0){
List<FlowElement> userTask = map.get("userTask").stream().filter(e -> e.getId().equals(gatewayNodeIncomingFlows.get(0).getSourceRef())).collect(Collectors.toList());
List<String> targetRefs = outgoingFlows.stream().map(t -> t.getTargetRef()).collect(Collectors.toList());
List<String> startOrEnd = map.get("startOrEnd").stream().map(t -> t.getId()).collect(Collectors.toList());
targetRefs.retainAll(startOrEnd);
if(userTask.size() > 0 && targetRefs.size() == 0){
if(Objects.nonNull(lineList)){
lineList.add((incomingFlow));
lineList.addAll(gatewayNodeIncomingFlows);
}
FlowNode flowNode= (FlowNode)userTask.get(0);
chooseNode.add(flowNode);
chooseNode.add(gateway.get(0));
recursionSearch(flowNode,map,chooseNode,lineList);
}else {
continue;
}
}else {
continue;
}
}
// 判断是开始节点,直接加入数组,结束循环
else if (map.get("startOrEnd").stream().filter(e -> e.getId().equals(incomingFlow.getSourceRef())).collect(Collectors.toList()).size() > 0) {
if(Objects.nonNull(lineList)){
lineList.add((incomingFlow));
}
List<FlowElement> startOrEnd = map.get("startOrEnd").stream().filter(e -> e.getId().equals(incomingFlow.getSourceRef())).collect(Collectors.toList());
if (Objects.nonNull(startOrEnd.get(0))){
chooseNode.add(startOrEnd.get(0));
}
}
// 非网关节点,非开始节点,即用户节点,加入当前节点,继续递归
else if(map.get("userTask").stream().filter(e -> e.getId().equals(incomingFlow.getSourceRef())).collect(Collectors.toList()).size() > 0){
if(Objects.nonNull(lineList)){
lineList.add((incomingFlow));
}
chooseNode.add(currentFlowNode);
// 找到上个节点
List<FlowElement> userTask = map.get("userTask").stream().filter(e -> e.getId().equals(incomingFlow.getSourceRef())).collect(Collectors.toList());
FlowNode flowElement = (FlowNode)userTask.get(0);
recursionSearch(flowElement,map,chooseNode,lineList);
}else {
continue;
}
}
return chooseNode;
}
这个查节点其实有一定的约束性,遇到并行可选的节点可能需要根据具体做出改变。
这样下来节点有了,可以开始下一步了
/**
* 强制跳转节点
* @param taskId 任务id
* @param sid 节点id
* @param comment
* @param variables
* @return
*/
@Override
public Boolean forceNode1(String taskId, String sid,String comment,Map<String, Object> variables,Long flowVoId){
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
String processDefinitionId = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult().getProcessDefinitionId();
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
Execution execution = runtimeService.createExecutionQuery().executionId(task.getExecutionId()).singleResult();
String activityId = execution.getActivityId();
FlowNode currentFlowNode = (FlowNode)bpmnModel.getMainProcess().getFlowElement(activityId);
FlowNode targetFlowNode = (FlowNode)bpmnModel.getMainProcess().getFlowElement(sid);
//拉线
List<SequenceFlow> sequenceFlowList = new ArrayList<>();
SequenceFlow sequenceFlow = new SequenceFlow();
sequenceFlow.setId("newFlow");
sequenceFlow.setSourceFlowElement(currentFlowNode);
sequenceFlow.setTargetFlowElement(targetFlowNode);
sequenceFlowList.add(sequenceFlow);
// 备份原有
List<SequenceFlow> dataflows = currentFlowNode.getOutgoingFlows();
List<SequenceFlow> oriSequenceFlows = new ArrayList<SequenceFlow>();
oriSequenceFlows.addAll(dataflows);
currentFlowNode.getOutgoingFlows().clear();
currentFlowNode.setOutgoingFlows(sequenceFlowList);
comment = "【回退】"+comment;
taskService.addComment(taskId, task.getProcessInstanceId(), comment);
// taskService.resolveTask(taskId, variables);
taskService.claim(taskId, ShiroUtils.getLoginName());
taskService.complete(taskId);
currentFlowNode.setOutgoingFlows(oriSequenceFlows);
return true;
}
注意一点,你改完线以后一定要先备份,再拉回去,不然下一个实例会有问题,但是多线程会不会有问题呢,这个值得思考一下
到这就结束了?
写了,用户难道不查历史的吗,你这样历史不乱套了吗
所以在历史上还得动手脚
可以先查出所有历史,给加签节点赋值时间,最后按节点时间排序不就成了
List<FlowVo> flowVoList = results.stream().filter(e -> e.getTaskId() != null && e.getTaskId().equals(bizIncrease.getTaskId()) && e.getTaskName() != "加签节点").collect(Collectors.toList());
if(taskName == null || taskName.length() == 0 || taskName.equals("加签节点")){
if(flowVoList.size() > 0){
// 说明是历史
for (FlowVo vo : flowVoList) {
FlowVo newFlow = new FlowVo();
BeanUtils.copyProperties(vo, newFlow);
newFlow.setTaskId(bizIncrease.getTaskId());
newFlow.setTaskName("加签节点");
if(bizIncrease.getIsHandle().equals("0")){
newFlow.setStartTime(bizIncrease.getTaskCreateTime());
}else {
newFlow.setStartTime(bizIncrease.getStartTime());
}
SysUser sysUser = userMapper.selectUserByLoginName(vo.getApplyUser());
newFlow.setApplyUserName(sysUser.getUserName());
newFlow.setEndTime(bizIncrease.getStartTime());
results.add(newFlow);
}
}else {
// 说明是当前的
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(bizIncrease.getInstanceId()).singleResult();
String businessKey = processInstance.getBusinessKey();
FlowVo flow1 = activityJobMapper.selectActivityJobById(new Long(businessKey));
flow1.setTaskId(bizIncrease.getTaskId());
flow1.setTaskName("加签节点");
flow1.setEndTime(bizIncrease.getStartTime());
if(bizIncrease.getIsHandle().equals("0")){
flow1.setStartTime(bizIncrease.getTaskCreateTime());
}else {
flow1.setStartTime(bizIncrease.getStartTime());
}
SysUser sysUser = userMapper.selectUserByLoginName(flow1.getApplyUser());
flow1.setApplyUserName(sysUser.getUserName());
results.add(flow1);
}