mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-26 09:11:52 +08:00
重新实现后端的 bpm 流程图的高亮接口
This commit is contained in:
parent
adc6076deb
commit
676e4f29d9
@ -0,0 +1,40 @@
|
|||||||
|
package cn.iocoder.yudao.adminserver.modules.bpm.controller.task;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmActivityService;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiImplicitParam;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@Api(tags = "流程活动实例")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/bpm/activity")
|
||||||
|
@Validated
|
||||||
|
public class BpmActivityController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private BpmActivityService activityService;
|
||||||
|
|
||||||
|
// TODO 芋艿:注解、权限、validtion
|
||||||
|
|
||||||
|
@ApiOperation(value = "生成指定流程实例的高亮流程图",
|
||||||
|
notes = "只高亮进行中的任务。不过要注意,该接口暂时没用,通过前端的 ProcessViewer.vue 界面的 highlightDiagram 方法生成")
|
||||||
|
@GetMapping("/generate-highlight-diagram")
|
||||||
|
@ApiImplicitParam(name = "id", value = "流程实例的编号", required = true, dataTypeClass = String.class)
|
||||||
|
public void generateHighlightDiagram(@RequestParam("processInstanceId") String processInstanceId,
|
||||||
|
HttpServletResponse response) throws IOException {
|
||||||
|
byte[] bytes = activityService.generateHighlightDiagram(processInstanceId);
|
||||||
|
ServletUtils.writeAttachment(response, StrUtil.format("流程图-{}.svg", processInstanceId), bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -20,7 +20,7 @@ import java.util.List;
|
|||||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||||
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
|
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
|
||||||
|
|
||||||
@Api(tags = "流程任务")
|
@Api(tags = "流程任务实例")
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/bpm/task")
|
@RequestMapping("/bpm/task")
|
||||||
@Validated
|
@Validated
|
||||||
@ -72,14 +72,4 @@ public class BpmTaskController {
|
|||||||
return success(taskService.getTaskListByProcessInstanceId(processInstanceId));
|
return success(taskService.getTaskListByProcessInstanceId(processInstanceId));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 返回高亮的流转图SVG
|
|
||||||
* @param processInstanceId 流程Id
|
|
||||||
*/
|
|
||||||
@GetMapping("/process/highlight-img")
|
|
||||||
public void getHighlightImg(@RequestParam String processInstanceId, HttpServletResponse response) throws IOException {
|
|
||||||
FileResp fileResp = taskService.getHighlightImg(processInstanceId);
|
|
||||||
ServletUtils.writeAttachment(response, fileResp.getFileName(), fileResp.getFileByte());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
// TODO @Li:1)改成 HighlightImgRespVO 吧。2)swagger 注解要补充;3)fileByte => fileContent
|
|
||||||
/**
|
|
||||||
* 文件输出类
|
|
||||||
*
|
|
||||||
* @author yunlongn
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
public class FileResp {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 文件名字
|
|
||||||
*/
|
|
||||||
private String fileName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 文件输出流
|
|
||||||
*/
|
|
||||||
private byte[] fileByte;
|
|
||||||
|
|
||||||
}
|
|
@ -33,7 +33,8 @@ public interface BpmErrorCodeConstants {
|
|||||||
ErrorCode PROCESS_DEFINITION_KEY_NOT_MATCH = new ErrorCode(1009003000, "流程定义的标识期望是({}),当前是({}),请修改 BPMN 流程图");
|
ErrorCode PROCESS_DEFINITION_KEY_NOT_MATCH = new ErrorCode(1009003000, "流程定义的标识期望是({}),当前是({}),请修改 BPMN 流程图");
|
||||||
ErrorCode PROCESS_DEFINITION_NAME_NOT_MATCH = new ErrorCode(1009003001, "流程定义的名字期望是({}),当前是({}),请修改 BPMN 流程图");
|
ErrorCode PROCESS_DEFINITION_NAME_NOT_MATCH = new ErrorCode(1009003001, "流程定义的名字期望是({}),当前是({}),请修改 BPMN 流程图");
|
||||||
ErrorCode PROCESS_DEFINITION_NOT_EXISTS = new ErrorCode(1009003002, "流程定义不存在");
|
ErrorCode PROCESS_DEFINITION_NOT_EXISTS = new ErrorCode(1009003002, "流程定义不存在");
|
||||||
ErrorCode PROCESS_DEFINITION_IS_SUSPENDED = new ErrorCode(1009003002, "流程定义处于挂起状态");
|
ErrorCode PROCESS_DEFINITION_IS_SUSPENDED = new ErrorCode(1009003003, "流程定义处于挂起状态");
|
||||||
|
ErrorCode PROCESS_DEFINITION_BPMN_MODEL_NOT_EXISTS = new ErrorCode(1009003004, "流程定义的模型不存在");
|
||||||
|
|
||||||
// ========== 流程实例 1-009-004-000 ==========
|
// ========== 流程实例 1-009-004-000 ==========
|
||||||
ErrorCode PROCESS_INSTANCE_NOT_EXISTS = new ErrorCode(1009004000, "流程实例不存在");
|
ErrorCode PROCESS_INSTANCE_NOT_EXISTS = new ErrorCode(1009004000, "流程实例不存在");
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
package cn.iocoder.yudao.adminserver.modules.bpm.service.task;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BPM 活动实例 Service 接口
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
public interface BpmActivityService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成指定流程实例的高亮流程图,只高亮进行中的任务
|
||||||
|
*
|
||||||
|
* 友情提示,非该方法的注释。如果想实现更高级的高亮流程图(当前节点红色 + 完成节点为绿色),可参考如下内容:
|
||||||
|
* 博客一:https://blog.csdn.net/qq_40109075/article/details/110939639
|
||||||
|
* 博客二:https://gitee.com/tony2y/RuoYi-flowable/blob/master/ruoyi-flowable/src/main/java/com/ruoyi/flowable/flow/CustomProcessDiagramGenerator.java
|
||||||
|
* 这里不实现的原理,需要自定义实现 ProcessDiagramGenerator 和 ProcessDiagramCanvas,代码量有点大
|
||||||
|
*
|
||||||
|
* 如果你想实现高亮已完成的任务,可参考 https://blog.csdn.net/qiuxinfa123/article/details/119579863 博客。不过测试下来,貌似不太对~
|
||||||
|
*
|
||||||
|
* @param processInstanceId 实例Id
|
||||||
|
* @return 图的字节数组
|
||||||
|
*/
|
||||||
|
byte[] generateHighlightDiagram(String processInstanceId);
|
||||||
|
|
||||||
|
}
|
@ -10,7 +10,7 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 流程任务 Service 接口
|
* 流程任务实例 Service 接口
|
||||||
*
|
*
|
||||||
* @author jason
|
* @author jason
|
||||||
* @author 芋道源码
|
* @author 芋道源码
|
||||||
@ -32,6 +32,14 @@ public interface BpmTaskService {
|
|||||||
*/
|
*/
|
||||||
List<BpmTaskRespVO> getTaskListByProcessInstanceId(String processInstanceId);
|
List<BpmTaskRespVO> getTaskListByProcessInstanceId(String processInstanceId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得流程任务列表
|
||||||
|
*
|
||||||
|
* @param processInstanceId 流程实例的编号
|
||||||
|
* @return 流程任务列表
|
||||||
|
*/
|
||||||
|
List<Task> getTasksByProcessInstanceId(String processInstanceId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得流程任务列表
|
* 获得流程任务列表
|
||||||
*
|
*
|
||||||
@ -101,13 +109,6 @@ public interface BpmTaskService {
|
|||||||
*/
|
*/
|
||||||
void rejectTask(Long userId, @Valid BpmTaskRejectReqVO reqVO);
|
void rejectTask(Long userId, @Valid BpmTaskRejectReqVO reqVO);
|
||||||
|
|
||||||
/**
|
|
||||||
* 返回高亮的流转进程
|
|
||||||
* @param processInstanceId 实例Id
|
|
||||||
* @return {@link FileResp} 返回文件
|
|
||||||
*/
|
|
||||||
FileResp getHighlightImg(String processInstanceId);
|
|
||||||
|
|
||||||
// ========== Task 拓展表相关 ==========
|
// ========== Task 拓展表相关 ==========
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,78 @@
|
|||||||
|
package cn.iocoder.yudao.adminserver.modules.bpm.service.task.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.io.IoUtil;
|
||||||
|
import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmProcessDefinitionService;
|
||||||
|
import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmActivityService;
|
||||||
|
import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmProcessInstanceService;
|
||||||
|
import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmTaskService;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.activiti.bpmn.model.BpmnModel;
|
||||||
|
import org.activiti.engine.HistoryService;
|
||||||
|
import org.activiti.engine.RepositoryService;
|
||||||
|
import org.activiti.engine.RuntimeService;
|
||||||
|
import org.activiti.engine.history.HistoricProcessInstance;
|
||||||
|
import org.activiti.engine.task.Task;
|
||||||
|
import org.activiti.image.ProcessDiagramGenerator;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.PROCESS_DEFINITION_BPMN_MODEL_NOT_EXISTS;
|
||||||
|
import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.PROCESS_INSTANCE_NOT_EXISTS;
|
||||||
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BPM 活动实例 Service 实现类
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
@Validated
|
||||||
|
public class BpmActivityServiceImpl implements BpmActivityService {
|
||||||
|
|
||||||
|
private static final String FONT_NAME = "宋体";
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ProcessDiagramGenerator processDiagramGenerator;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private BpmProcessInstanceService processInstanceService;
|
||||||
|
@Resource
|
||||||
|
private BpmProcessDefinitionService processDefinitionService;
|
||||||
|
@Resource
|
||||||
|
private BpmTaskService taskService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] generateHighlightDiagram(String processInstanceId) {
|
||||||
|
// 获得流程实例
|
||||||
|
HistoricProcessInstance processInstance = processInstanceService.getHistoricProcessInstance(processInstanceId);
|
||||||
|
if (processInstance == null) {
|
||||||
|
throw exception(PROCESS_INSTANCE_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
// 获得流程定义的 BPMN 模型
|
||||||
|
BpmnModel bpmnModel = processDefinitionService.getBpmnModel(processInstance.getProcessDefinitionId());
|
||||||
|
if (bpmnModel == null) {
|
||||||
|
throw exception(PROCESS_DEFINITION_BPMN_MODEL_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果流程已经结束,则无进行中的任务,无法高亮
|
||||||
|
// 如果流程未结束,才需要高亮
|
||||||
|
List<String> highLightedActivities = Collections.emptyList();
|
||||||
|
if (processInstance.getEndTime() == null) {
|
||||||
|
List<Task> tasks = taskService.getTasksByProcessInstanceId(processInstanceId);
|
||||||
|
highLightedActivities = CollectionUtils.convertList(tasks, Task::getTaskDefinitionKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成高亮流程图
|
||||||
|
InputStream inputStream = processDiagramGenerator.generateDiagram(bpmnModel, highLightedActivities, Collections.emptyList(),
|
||||||
|
FONT_NAME, FONT_NAME, FONT_NAME);
|
||||||
|
return IoUtil.readBytes(inputStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -54,7 +54,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.
|
|||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 流程任务 Service 实现类
|
* 流程任务实例 Service 实现类
|
||||||
*
|
*
|
||||||
* @author jason
|
* @author jason
|
||||||
* @author 芋道源码
|
* @author 芋道源码
|
||||||
@ -66,14 +66,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||||||
@Resource
|
@Resource
|
||||||
private TaskService taskService;
|
private TaskService taskService;
|
||||||
@Resource
|
@Resource
|
||||||
private RuntimeService runtimeService;
|
|
||||||
@Resource
|
|
||||||
private HistoryService historyService;
|
private HistoryService historyService;
|
||||||
@Resource
|
|
||||||
private RepositoryService repositoryService;
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private ProcessDiagramGenerator processDiagramGenerator;
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private SysUserService userService;
|
private SysUserService userService;
|
||||||
@ -118,6 +111,14 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||||||
return BpmTaskConvert.INSTANCE.convertList3(tasks, bpmTaskExtDOMap, processInstance, userMap, deptMap);
|
return BpmTaskConvert.INSTANCE.convertList3(tasks, bpmTaskExtDOMap, processInstance, userMap, deptMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Task> getTasksByProcessInstanceId(String processInstanceId) {
|
||||||
|
if (StrUtil.isEmpty(processInstanceId)) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
return taskService.createTaskQuery().processInstanceId(processInstanceId).list();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Task> getTasksByProcessInstanceIds(List<String> processInstanceIds) {
|
public List<Task> getTasksByProcessInstanceIds(List<String> processInstanceIds) {
|
||||||
if (CollUtil.isEmpty(processInstanceIds)) {
|
if (CollUtil.isEmpty(processInstanceIds)) {
|
||||||
@ -270,129 +271,6 @@ public class BpmTaskServiceImpl implements BpmTaskService {
|
|||||||
// taskService.addComment(task.getId(), task.getProcessInstanceId(), reqVO.getComment());
|
// taskService.addComment(task.getId(), task.getProcessInstanceId(), reqVO.getComment());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public FileResp getHighlightImg(String processInstanceId) {
|
|
||||||
// 查询历史
|
|
||||||
//TODO 云扬四海 貌似流程结束后,点击审批进度会报错
|
|
||||||
// TODO @Li:一些 historyService 的查询,貌似比较通用,是不是抽一些小方法出来
|
|
||||||
HistoricProcessInstance hpi = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
|
|
||||||
// 如果不存在实例。 说明数据异常
|
|
||||||
if (hpi == null) {
|
|
||||||
// throw exception(PROCESS_INSTANCE_NOT_EXISTS);
|
|
||||||
throw new RuntimeException("不存在");
|
|
||||||
}
|
|
||||||
// 如果有结束时间 返回model的流程图
|
|
||||||
if (!ObjectUtils.isEmpty(hpi.getEndTime())) {
|
|
||||||
ProcessDefinition pd = repositoryService.createProcessDefinitionQuery().processDefinitionId(hpi.getProcessDefinitionId()).singleResult();
|
|
||||||
String resourceName = Optional.ofNullable(pd.getDiagramResourceName()).orElse(pd.getResourceName());
|
|
||||||
BpmnModel bpmnModel = repositoryService.getBpmnModel(pd.getId());
|
|
||||||
InputStream inputStream = processDiagramGenerator.generateDiagram(bpmnModel, new ArrayList<>(1), new ArrayList<>(1),
|
|
||||||
"宋体", "宋体", "宋体");
|
|
||||||
FileResp fileResp = new FileResp();
|
|
||||||
fileResp.setFileName( resourceName + ".svg");
|
|
||||||
fileResp.setFileByte(IoUtil.readBytes(inputStream));
|
|
||||||
return fileResp;
|
|
||||||
}
|
|
||||||
// 没有结束时间。说明流程在执行过程中
|
|
||||||
// TODO @Li:一些 runtimeService 的查询,貌似比较通用,是不是抽一些小方法出来
|
|
||||||
ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
|
|
||||||
|
|
||||||
List<String> highLightedActivities = new ArrayList<>();
|
|
||||||
// 获取所有活动节点
|
|
||||||
List<HistoricActivityInstance> finishedInstances = historyService.createHistoricActivityInstanceQuery()
|
|
||||||
.processInstanceId(processInstanceId).finished().list();
|
|
||||||
finishedInstances.stream().map(HistoricActivityInstance::getActivityId)
|
|
||||||
.forEach(highLightedActivities::add);
|
|
||||||
// 已完成的节点+当前节点
|
|
||||||
highLightedActivities.addAll(runtimeService.getActiveActivityIds(processInstanceId));
|
|
||||||
|
|
||||||
BpmnModel bpmnModel = repositoryService.getBpmnModel(pi.getProcessDefinitionId());
|
|
||||||
// 经过的流
|
|
||||||
List<String> highLightedFlowIds = getHighLightedFlows(bpmnModel, processInstanceId);
|
|
||||||
|
|
||||||
//设置"宋体"
|
|
||||||
try (InputStream inputStream = processDiagramGenerator.generateDiagram(bpmnModel, highLightedActivities, highLightedFlowIds,
|
|
||||||
"宋体", "宋体", "宋体")){
|
|
||||||
FileResp fileResp = new FileResp();
|
|
||||||
fileResp.setFileName( hpi.getProcessDefinitionName() + ".svg");
|
|
||||||
fileResp.setFileByte(IoUtil.readBytes(inputStream));
|
|
||||||
return fileResp;
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.error("[getHighlightImg][流程({}) 生成图表失败]", processInstanceId, e);
|
|
||||||
throw exception(HIGHLIGHT_IMG_ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO @Li:这个方法的可读性还有一定的优化空间,可以思考下哈。
|
|
||||||
/**
|
|
||||||
* 获取指定 processInstanceId 已经高亮的Flows
|
|
||||||
* 获取已经流转的线 参考: https://blog.csdn.net/qiuxinfa123/article/details/119579863
|
|
||||||
* @param bpmnModel model
|
|
||||||
* @param processInstanceId 流程实例Id
|
|
||||||
* @return 获取已经流转的列表
|
|
||||||
*/
|
|
||||||
private List<String> getHighLightedFlows(BpmnModel bpmnModel, String processInstanceId) {
|
|
||||||
// 获取所有的线条
|
|
||||||
List<HistoricActivityInstance> historicActivityInstances = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId)
|
|
||||||
.orderByHistoricActivityInstanceId().asc().list();
|
|
||||||
// 高亮流程已发生流转的线id集合
|
|
||||||
List<String> highLightedFlowIds = new ArrayList<>();
|
|
||||||
// 全部活动节点
|
|
||||||
List<FlowNode> historicActivityNodes = new ArrayList<>();
|
|
||||||
// 已完成的历史活动节点
|
|
||||||
List<HistoricActivityInstance> finishedActivityInstances = new ArrayList<>();
|
|
||||||
|
|
||||||
for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) {
|
|
||||||
FlowNode flowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(historicActivityInstance.getActivityId(), true);
|
|
||||||
historicActivityNodes.add(flowNode);
|
|
||||||
// 结束时间不为空,则是已完成节点
|
|
||||||
if (historicActivityInstance.getEndTime() != null) {
|
|
||||||
finishedActivityInstances.add(historicActivityInstance);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 提取活动id 是唯一的。塞入Map
|
|
||||||
Map<String, HistoricActivityInstance> historicActivityInstanceMap = CollectionUtils.convertMap(historicActivityInstances, HistoricActivityInstance::getActivityId);
|
|
||||||
// 遍历已完成的活动实例,从每个实例的outgoingFlows中找到已执行的
|
|
||||||
for (HistoricActivityInstance currentActivityInstance : finishedActivityInstances) {
|
|
||||||
// 获得当前活动对应的节点信息及outgoingFlows信息
|
|
||||||
FlowNode currentFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(currentActivityInstance.getActivityId(), true);
|
|
||||||
List<SequenceFlow> sequenceFlows = currentFlowNode.getOutgoingFlows();
|
|
||||||
|
|
||||||
// 遍历outgoingFlows并找到已流转的 满足如下条件认为已已流转:
|
|
||||||
// 1.当前节点是并行网关或兼容网关,则通过outgoingFlows能够在历史活动中找到的全部节点均为已流转
|
|
||||||
// 2.当前节点是以上两种类型之外的,通过outgoingFlows查找到的时间最早的流转节点视为有效流转
|
|
||||||
if (BpmnXMLConstants.ELEMENT_GATEWAY_PARALLEL.equals(currentActivityInstance.getActivityType())
|
|
||||||
|| BpmnXMLConstants.ELEMENT_GATEWAY_INCLUSIVE.equals(currentActivityInstance.getActivityType())) {
|
|
||||||
// 遍历历史活动节点,找到匹配流程目标节点的
|
|
||||||
for (SequenceFlow sequenceFlow : sequenceFlows) {
|
|
||||||
FlowNode targetFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(sequenceFlow.getTargetRef(), true);
|
|
||||||
if (historicActivityNodes.contains(targetFlowNode)) {
|
|
||||||
highLightedFlowIds.add(targetFlowNode.getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
long earliestStamp = 0L;
|
|
||||||
String highLightedFlowId = null;
|
|
||||||
// 循环流出的流
|
|
||||||
for (SequenceFlow sequenceFlow : sequenceFlows) {
|
|
||||||
HistoricActivityInstance historicActivityInstance = historicActivityInstanceMap.get(sequenceFlow.getTargetRef());
|
|
||||||
if (historicActivityInstance == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
final long startTime = historicActivityInstance.getStartTime().getTime();
|
|
||||||
// 遍历匹配的集合,取得开始时间最早的一个
|
|
||||||
if (earliestStamp == 0 || earliestStamp >= startTime) {
|
|
||||||
highLightedFlowId = sequenceFlow.getId();
|
|
||||||
earliestStamp = startTime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
highLightedFlowIds.add(highLightedFlowId);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return highLightedFlowIds;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task getTask(String id) {
|
private Task getTask(String id) {
|
||||||
return taskService.createTaskQuery().taskId(id).singleResult();
|
return taskService.createTaskQuery().taskId(id).singleResult();
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* task 包下,存放的都是 xxx 实例。例如说:
|
||||||
|
* 1. ProcessInstance 是 ProcessDefinition 创建而来的实例;
|
||||||
|
* 2. TaskInstance 是 TaskDefinition 创建而来的实例;
|
||||||
|
* 3. ActivityInstance 是 BPMN 流程图的每个元素创建的实例;
|
||||||
|
*
|
||||||
|
* 考虑到 Task 和 Activity 可以比较明确表示名字,所以对应的 Service 就没有使用 Instance 后缀~
|
||||||
|
* 嘿嘿,其实也是实现到比较后面的阶段,所以就暂时没去统一和修改了~
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
package cn.iocoder.yudao.adminserver.modules.bpm.service.task;
|
Loading…
Reference in New Issue
Block a user