Commit 676e4f29d908de2d55d537bef6823b2d6642d3ae
1 parent
adc6076d
重新实现后端的 bpm 流程图的高亮接口
Showing
9 changed files
with
176 additions
and
175 deletions
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/BpmActivityController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.bpm.controller.task; | |
| 2 | + | |
| 3 | +import cn.hutool.core.util.StrUtil; | |
| 4 | +import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmActivityService; | |
| 5 | +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; | |
| 6 | +import io.swagger.annotations.Api; | |
| 7 | +import io.swagger.annotations.ApiImplicitParam; | |
| 8 | +import io.swagger.annotations.ApiOperation; | |
| 9 | +import org.springframework.validation.annotation.Validated; | |
| 10 | +import org.springframework.web.bind.annotation.GetMapping; | |
| 11 | +import org.springframework.web.bind.annotation.RequestMapping; | |
| 12 | +import org.springframework.web.bind.annotation.RequestParam; | |
| 13 | +import org.springframework.web.bind.annotation.RestController; | |
| 14 | + | |
| 15 | +import javax.annotation.Resource; | |
| 16 | +import javax.servlet.http.HttpServletResponse; | |
| 17 | +import java.io.IOException; | |
| 18 | + | |
| 19 | +@Api(tags = "流程活动实例") | |
| 20 | +@RestController | |
| 21 | +@RequestMapping("/bpm/activity") | |
| 22 | +@Validated | |
| 23 | +public class BpmActivityController { | |
| 24 | + | |
| 25 | + @Resource | |
| 26 | + private BpmActivityService activityService; | |
| 27 | + | |
| 28 | + // TODO 芋艿:注解、权限、validtion | |
| 29 | + | |
| 30 | + @ApiOperation(value = "生成指定流程实例的高亮流程图", | |
| 31 | + notes = "只高亮进行中的任务。不过要注意,该接口暂时没用,通过前端的 ProcessViewer.vue 界面的 highlightDiagram 方法生成") | |
| 32 | + @GetMapping("/generate-highlight-diagram") | |
| 33 | + @ApiImplicitParam(name = "id", value = "流程实例的编号", required = true, dataTypeClass = String.class) | |
| 34 | + public void generateHighlightDiagram(@RequestParam("processInstanceId") String processInstanceId, | |
| 35 | + HttpServletResponse response) throws IOException { | |
| 36 | + byte[] bytes = activityService.generateHighlightDiagram(processInstanceId); | |
| 37 | + ServletUtils.writeAttachment(response, StrUtil.format("流程图-{}.svg", processInstanceId), bytes); | |
| 38 | + } | |
| 39 | + | |
| 40 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/BpmTaskController.java
| ... | ... | @@ -20,7 +20,7 @@ import java.util.List; |
| 20 | 20 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 21 | 21 | import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId; |
| 22 | 22 | |
| 23 | -@Api(tags = "流程任务") | |
| 23 | +@Api(tags = "流程任务实例") | |
| 24 | 24 | @RestController |
| 25 | 25 | @RequestMapping("/bpm/task") |
| 26 | 26 | @Validated |
| ... | ... | @@ -72,14 +72,4 @@ public class BpmTaskController { |
| 72 | 72 | return success(taskService.getTaskListByProcessInstanceId(processInstanceId)); |
| 73 | 73 | } |
| 74 | 74 | |
| 75 | - /** | |
| 76 | - * 返回高亮的流转图SVG | |
| 77 | - * @param processInstanceId 流程Id | |
| 78 | - */ | |
| 79 | - @GetMapping("/process/highlight-img") | |
| 80 | - public void getHighlightImg(@RequestParam String processInstanceId, HttpServletResponse response) throws IOException { | |
| 81 | - FileResp fileResp = taskService.getHighlightImg(processInstanceId); | |
| 82 | - ServletUtils.writeAttachment(response, fileResp.getFileName(), fileResp.getFileByte()); | |
| 83 | - } | |
| 84 | - | |
| 85 | 75 | } | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/controller/task/vo/task/FileResp.java deleted
| 1 | -package cn.iocoder.yudao.adminserver.modules.bpm.controller.task.vo.task; | |
| 2 | - | |
| 3 | -import lombok.Data; | |
| 4 | - | |
| 5 | -// TODO @Li:1)改成 HighlightImgRespVO 吧。2)swagger 注解要补充;3)fileByte => fileContent | |
| 6 | -/** | |
| 7 | - * 文件输出类 | |
| 8 | - * | |
| 9 | - * @author yunlongn | |
| 10 | - */ | |
| 11 | -@Data | |
| 12 | -public class FileResp { | |
| 13 | - | |
| 14 | - /** | |
| 15 | - * 文件名字 | |
| 16 | - */ | |
| 17 | - private String fileName; | |
| 18 | - | |
| 19 | - /** | |
| 20 | - * 文件输出流 | |
| 21 | - */ | |
| 22 | - private byte[] fileByte; | |
| 23 | - | |
| 24 | -} |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/enums/BpmErrorCodeConstants.java
| ... | ... | @@ -33,7 +33,8 @@ public interface BpmErrorCodeConstants { |
| 33 | 33 | ErrorCode PROCESS_DEFINITION_KEY_NOT_MATCH = new ErrorCode(1009003000, "流程定义的标识期望是({}),当前是({}),请修改 BPMN 流程图"); |
| 34 | 34 | ErrorCode PROCESS_DEFINITION_NAME_NOT_MATCH = new ErrorCode(1009003001, "流程定义的名字期望是({}),当前是({}),请修改 BPMN 流程图"); |
| 35 | 35 | ErrorCode PROCESS_DEFINITION_NOT_EXISTS = new ErrorCode(1009003002, "流程定义不存在"); |
| 36 | - ErrorCode PROCESS_DEFINITION_IS_SUSPENDED = new ErrorCode(1009003002, "流程定义处于挂起状态"); | |
| 36 | + ErrorCode PROCESS_DEFINITION_IS_SUSPENDED = new ErrorCode(1009003003, "流程定义处于挂起状态"); | |
| 37 | + ErrorCode PROCESS_DEFINITION_BPMN_MODEL_NOT_EXISTS = new ErrorCode(1009003004, "流程定义的模型不存在"); | |
| 37 | 38 | |
| 38 | 39 | // ========== 流程实例 1-009-004-000 ========== |
| 39 | 40 | ErrorCode PROCESS_INSTANCE_NOT_EXISTS = new ErrorCode(1009004000, "流程实例不存在"); | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/BpmActivityService.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.bpm.service.task; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * BPM 活动实例 Service 接口 | |
| 5 | + * | |
| 6 | + * @author 芋道源码 | |
| 7 | + */ | |
| 8 | +public interface BpmActivityService { | |
| 9 | + | |
| 10 | + /** | |
| 11 | + * 生成指定流程实例的高亮流程图,只高亮进行中的任务 | |
| 12 | + * | |
| 13 | + * 友情提示,非该方法的注释。如果想实现更高级的高亮流程图(当前节点红色 + 完成节点为绿色),可参考如下内容: | |
| 14 | + * 博客一:https://blog.csdn.net/qq_40109075/article/details/110939639 | |
| 15 | + * 博客二:https://gitee.com/tony2y/RuoYi-flowable/blob/master/ruoyi-flowable/src/main/java/com/ruoyi/flowable/flow/CustomProcessDiagramGenerator.java | |
| 16 | + * 这里不实现的原理,需要自定义实现 ProcessDiagramGenerator 和 ProcessDiagramCanvas,代码量有点大 | |
| 17 | + * | |
| 18 | + * 如果你想实现高亮已完成的任务,可参考 https://blog.csdn.net/qiuxinfa123/article/details/119579863 博客。不过测试下来,貌似不太对~ | |
| 19 | + * | |
| 20 | + * @param processInstanceId 实例Id | |
| 21 | + * @return 图的字节数组 | |
| 22 | + */ | |
| 23 | + byte[] generateHighlightDiagram(String processInstanceId); | |
| 24 | + | |
| 25 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/BpmTaskService.java
| ... | ... | @@ -10,7 +10,7 @@ import java.util.List; |
| 10 | 10 | import java.util.Map; |
| 11 | 11 | |
| 12 | 12 | /** |
| 13 | - * 流程任务 Service 接口 | |
| 13 | + * 流程任务实例 Service 接口 | |
| 14 | 14 | * |
| 15 | 15 | * @author jason |
| 16 | 16 | * @author 芋道源码 |
| ... | ... | @@ -35,6 +35,14 @@ public interface BpmTaskService { |
| 35 | 35 | /** |
| 36 | 36 | * 获得流程任务列表 |
| 37 | 37 | * |
| 38 | + * @param processInstanceId 流程实例的编号 | |
| 39 | + * @return 流程任务列表 | |
| 40 | + */ | |
| 41 | + List<Task> getTasksByProcessInstanceId(String processInstanceId); | |
| 42 | + | |
| 43 | + /** | |
| 44 | + * 获得流程任务列表 | |
| 45 | + * | |
| 38 | 46 | * @param processInstanceIds 流程实例的编号数组 |
| 39 | 47 | * @return 流程任务列表 |
| 40 | 48 | */ |
| ... | ... | @@ -101,13 +109,6 @@ public interface BpmTaskService { |
| 101 | 109 | */ |
| 102 | 110 | void rejectTask(Long userId, @Valid BpmTaskRejectReqVO reqVO); |
| 103 | 111 | |
| 104 | - /** | |
| 105 | - * 返回高亮的流转进程 | |
| 106 | - * @param processInstanceId 实例Id | |
| 107 | - * @return {@link FileResp} 返回文件 | |
| 108 | - */ | |
| 109 | - FileResp getHighlightImg(String processInstanceId); | |
| 110 | - | |
| 111 | 112 | // ========== Task 拓展表相关 ========== |
| 112 | 113 | |
| 113 | 114 | /** | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/impl/BpmActivityServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.adminserver.modules.bpm.service.task.impl; | |
| 2 | + | |
| 3 | +import cn.hutool.core.io.IoUtil; | |
| 4 | +import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmProcessDefinitionService; | |
| 5 | +import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmActivityService; | |
| 6 | +import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmProcessInstanceService; | |
| 7 | +import cn.iocoder.yudao.adminserver.modules.bpm.service.task.BpmTaskService; | |
| 8 | +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | |
| 9 | +import lombok.extern.slf4j.Slf4j; | |
| 10 | +import org.activiti.bpmn.model.BpmnModel; | |
| 11 | +import org.activiti.engine.HistoryService; | |
| 12 | +import org.activiti.engine.RepositoryService; | |
| 13 | +import org.activiti.engine.RuntimeService; | |
| 14 | +import org.activiti.engine.history.HistoricProcessInstance; | |
| 15 | +import org.activiti.engine.task.Task; | |
| 16 | +import org.activiti.image.ProcessDiagramGenerator; | |
| 17 | +import org.springframework.stereotype.Service; | |
| 18 | +import org.springframework.validation.annotation.Validated; | |
| 19 | + | |
| 20 | +import javax.annotation.Resource; | |
| 21 | +import java.io.InputStream; | |
| 22 | +import java.util.Collections; | |
| 23 | +import java.util.List; | |
| 24 | + | |
| 25 | +import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.PROCESS_DEFINITION_BPMN_MODEL_NOT_EXISTS; | |
| 26 | +import static cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants.PROCESS_INSTANCE_NOT_EXISTS; | |
| 27 | +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | |
| 28 | + | |
| 29 | +/** | |
| 30 | + * BPM 活动实例 Service 实现类 | |
| 31 | + * | |
| 32 | + * @author 芋道源码 | |
| 33 | + */ | |
| 34 | +@Service | |
| 35 | +@Slf4j | |
| 36 | +@Validated | |
| 37 | +public class BpmActivityServiceImpl implements BpmActivityService { | |
| 38 | + | |
| 39 | + private static final String FONT_NAME = "宋体"; | |
| 40 | + | |
| 41 | + @Resource | |
| 42 | + private ProcessDiagramGenerator processDiagramGenerator; | |
| 43 | + | |
| 44 | + @Resource | |
| 45 | + private BpmProcessInstanceService processInstanceService; | |
| 46 | + @Resource | |
| 47 | + private BpmProcessDefinitionService processDefinitionService; | |
| 48 | + @Resource | |
| 49 | + private BpmTaskService taskService; | |
| 50 | + | |
| 51 | + @Override | |
| 52 | + public byte[] generateHighlightDiagram(String processInstanceId) { | |
| 53 | + // 获得流程实例 | |
| 54 | + HistoricProcessInstance processInstance = processInstanceService.getHistoricProcessInstance(processInstanceId); | |
| 55 | + if (processInstance == null) { | |
| 56 | + throw exception(PROCESS_INSTANCE_NOT_EXISTS); | |
| 57 | + } | |
| 58 | + // 获得流程定义的 BPMN 模型 | |
| 59 | + BpmnModel bpmnModel = processDefinitionService.getBpmnModel(processInstance.getProcessDefinitionId()); | |
| 60 | + if (bpmnModel == null) { | |
| 61 | + throw exception(PROCESS_DEFINITION_BPMN_MODEL_NOT_EXISTS); | |
| 62 | + } | |
| 63 | + | |
| 64 | + // 如果流程已经结束,则无进行中的任务,无法高亮 | |
| 65 | + // 如果流程未结束,才需要高亮 | |
| 66 | + List<String> highLightedActivities = Collections.emptyList(); | |
| 67 | + if (processInstance.getEndTime() == null) { | |
| 68 | + List<Task> tasks = taskService.getTasksByProcessInstanceId(processInstanceId); | |
| 69 | + highLightedActivities = CollectionUtils.convertList(tasks, Task::getTaskDefinitionKey); | |
| 70 | + } | |
| 71 | + | |
| 72 | + // 生成高亮流程图 | |
| 73 | + InputStream inputStream = processDiagramGenerator.generateDiagram(bpmnModel, highLightedActivities, Collections.emptyList(), | |
| 74 | + FONT_NAME, FONT_NAME, FONT_NAME); | |
| 75 | + return IoUtil.readBytes(inputStream); | |
| 76 | + } | |
| 77 | + | |
| 78 | +} | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/impl/BpmTaskServiceImpl.java
| ... | ... | @@ -54,7 +54,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. |
| 54 | 54 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| 55 | 55 | |
| 56 | 56 | /** |
| 57 | - * 流程任务 Service 实现类 | |
| 57 | + * 流程任务实例 Service 实现类 | |
| 58 | 58 | * |
| 59 | 59 | * @author jason |
| 60 | 60 | * @author 芋道源码 |
| ... | ... | @@ -66,14 +66,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { |
| 66 | 66 | @Resource |
| 67 | 67 | private TaskService taskService; |
| 68 | 68 | @Resource |
| 69 | - private RuntimeService runtimeService; | |
| 70 | - @Resource | |
| 71 | 69 | private HistoryService historyService; |
| 72 | - @Resource | |
| 73 | - private RepositoryService repositoryService; | |
| 74 | - | |
| 75 | - @Resource | |
| 76 | - private ProcessDiagramGenerator processDiagramGenerator; | |
| 77 | 70 | |
| 78 | 71 | @Resource |
| 79 | 72 | private SysUserService userService; |
| ... | ... | @@ -119,6 +112,14 @@ public class BpmTaskServiceImpl implements BpmTaskService { |
| 119 | 112 | } |
| 120 | 113 | |
| 121 | 114 | @Override |
| 115 | + public List<Task> getTasksByProcessInstanceId(String processInstanceId) { | |
| 116 | + if (StrUtil.isEmpty(processInstanceId)) { | |
| 117 | + return Collections.emptyList(); | |
| 118 | + } | |
| 119 | + return taskService.createTaskQuery().processInstanceId(processInstanceId).list(); | |
| 120 | + } | |
| 121 | + | |
| 122 | + @Override | |
| 122 | 123 | public List<Task> getTasksByProcessInstanceIds(List<String> processInstanceIds) { |
| 123 | 124 | if (CollUtil.isEmpty(processInstanceIds)) { |
| 124 | 125 | return Collections.emptyList(); |
| ... | ... | @@ -270,129 +271,6 @@ public class BpmTaskServiceImpl implements BpmTaskService { |
| 270 | 271 | // taskService.addComment(task.getId(), task.getProcessInstanceId(), reqVO.getComment()); |
| 271 | 272 | } |
| 272 | 273 | |
| 273 | - @Override | |
| 274 | - public FileResp getHighlightImg(String processInstanceId) { | |
| 275 | - // 查询历史 | |
| 276 | - //TODO 云扬四海 貌似流程结束后,点击审批进度会报错 | |
| 277 | - // TODO @Li:一些 historyService 的查询,貌似比较通用,是不是抽一些小方法出来 | |
| 278 | - HistoricProcessInstance hpi = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); | |
| 279 | - // 如果不存在实例。 说明数据异常 | |
| 280 | - if (hpi == null) { | |
| 281 | -// throw exception(PROCESS_INSTANCE_NOT_EXISTS); | |
| 282 | - throw new RuntimeException("不存在"); | |
| 283 | - } | |
| 284 | - // 如果有结束时间 返回model的流程图 | |
| 285 | - if (!ObjectUtils.isEmpty(hpi.getEndTime())) { | |
| 286 | - ProcessDefinition pd = repositoryService.createProcessDefinitionQuery().processDefinitionId(hpi.getProcessDefinitionId()).singleResult(); | |
| 287 | - String resourceName = Optional.ofNullable(pd.getDiagramResourceName()).orElse(pd.getResourceName()); | |
| 288 | - BpmnModel bpmnModel = repositoryService.getBpmnModel(pd.getId()); | |
| 289 | - InputStream inputStream = processDiagramGenerator.generateDiagram(bpmnModel, new ArrayList<>(1), new ArrayList<>(1), | |
| 290 | - "宋体", "宋体", "宋体"); | |
| 291 | - FileResp fileResp = new FileResp(); | |
| 292 | - fileResp.setFileName( resourceName + ".svg"); | |
| 293 | - fileResp.setFileByte(IoUtil.readBytes(inputStream)); | |
| 294 | - return fileResp; | |
| 295 | - } | |
| 296 | - // 没有结束时间。说明流程在执行过程中 | |
| 297 | - // TODO @Li:一些 runtimeService 的查询,貌似比较通用,是不是抽一些小方法出来 | |
| 298 | - ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); | |
| 299 | - | |
| 300 | - List<String> highLightedActivities = new ArrayList<>(); | |
| 301 | - // 获取所有活动节点 | |
| 302 | - List<HistoricActivityInstance> finishedInstances = historyService.createHistoricActivityInstanceQuery() | |
| 303 | - .processInstanceId(processInstanceId).finished().list(); | |
| 304 | - finishedInstances.stream().map(HistoricActivityInstance::getActivityId) | |
| 305 | - .forEach(highLightedActivities::add); | |
| 306 | - // 已完成的节点+当前节点 | |
| 307 | - highLightedActivities.addAll(runtimeService.getActiveActivityIds(processInstanceId)); | |
| 308 | - | |
| 309 | - BpmnModel bpmnModel = repositoryService.getBpmnModel(pi.getProcessDefinitionId()); | |
| 310 | - // 经过的流 | |
| 311 | - List<String> highLightedFlowIds = getHighLightedFlows(bpmnModel, processInstanceId); | |
| 312 | - | |
| 313 | - //设置"宋体" | |
| 314 | - try (InputStream inputStream = processDiagramGenerator.generateDiagram(bpmnModel, highLightedActivities, highLightedFlowIds, | |
| 315 | - "宋体", "宋体", "宋体")){ | |
| 316 | - FileResp fileResp = new FileResp(); | |
| 317 | - fileResp.setFileName( hpi.getProcessDefinitionName() + ".svg"); | |
| 318 | - fileResp.setFileByte(IoUtil.readBytes(inputStream)); | |
| 319 | - return fileResp; | |
| 320 | - } catch (IOException e) { | |
| 321 | - log.error("[getHighlightImg][流程({}) 生成图表失败]", processInstanceId, e); | |
| 322 | - throw exception(HIGHLIGHT_IMG_ERROR); | |
| 323 | - } | |
| 324 | - } | |
| 325 | - | |
| 326 | - // TODO @Li:这个方法的可读性还有一定的优化空间,可以思考下哈。 | |
| 327 | - /** | |
| 328 | - * 获取指定 processInstanceId 已经高亮的Flows | |
| 329 | - * 获取已经流转的线 参考: https://blog.csdn.net/qiuxinfa123/article/details/119579863 | |
| 330 | - * @param bpmnModel model | |
| 331 | - * @param processInstanceId 流程实例Id | |
| 332 | - * @return 获取已经流转的列表 | |
| 333 | - */ | |
| 334 | - private List<String> getHighLightedFlows(BpmnModel bpmnModel, String processInstanceId) { | |
| 335 | - // 获取所有的线条 | |
| 336 | - List<HistoricActivityInstance> historicActivityInstances = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId) | |
| 337 | - .orderByHistoricActivityInstanceId().asc().list(); | |
| 338 | - // 高亮流程已发生流转的线id集合 | |
| 339 | - List<String> highLightedFlowIds = new ArrayList<>(); | |
| 340 | - // 全部活动节点 | |
| 341 | - List<FlowNode> historicActivityNodes = new ArrayList<>(); | |
| 342 | - // 已完成的历史活动节点 | |
| 343 | - List<HistoricActivityInstance> finishedActivityInstances = new ArrayList<>(); | |
| 344 | - | |
| 345 | - for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) { | |
| 346 | - FlowNode flowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(historicActivityInstance.getActivityId(), true); | |
| 347 | - historicActivityNodes.add(flowNode); | |
| 348 | - // 结束时间不为空,则是已完成节点 | |
| 349 | - if (historicActivityInstance.getEndTime() != null) { | |
| 350 | - finishedActivityInstances.add(historicActivityInstance); | |
| 351 | - } | |
| 352 | - } | |
| 353 | - // 提取活动id 是唯一的。塞入Map | |
| 354 | - Map<String, HistoricActivityInstance> historicActivityInstanceMap = CollectionUtils.convertMap(historicActivityInstances, HistoricActivityInstance::getActivityId); | |
| 355 | - // 遍历已完成的活动实例,从每个实例的outgoingFlows中找到已执行的 | |
| 356 | - for (HistoricActivityInstance currentActivityInstance : finishedActivityInstances) { | |
| 357 | - // 获得当前活动对应的节点信息及outgoingFlows信息 | |
| 358 | - FlowNode currentFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(currentActivityInstance.getActivityId(), true); | |
| 359 | - List<SequenceFlow> sequenceFlows = currentFlowNode.getOutgoingFlows(); | |
| 360 | - | |
| 361 | - // 遍历outgoingFlows并找到已流转的 满足如下条件认为已已流转: | |
| 362 | - // 1.当前节点是并行网关或兼容网关,则通过outgoingFlows能够在历史活动中找到的全部节点均为已流转 | |
| 363 | - // 2.当前节点是以上两种类型之外的,通过outgoingFlows查找到的时间最早的流转节点视为有效流转 | |
| 364 | - if (BpmnXMLConstants.ELEMENT_GATEWAY_PARALLEL.equals(currentActivityInstance.getActivityType()) | |
| 365 | - || BpmnXMLConstants.ELEMENT_GATEWAY_INCLUSIVE.equals(currentActivityInstance.getActivityType())) { | |
| 366 | - // 遍历历史活动节点,找到匹配流程目标节点的 | |
| 367 | - for (SequenceFlow sequenceFlow : sequenceFlows) { | |
| 368 | - FlowNode targetFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(sequenceFlow.getTargetRef(), true); | |
| 369 | - if (historicActivityNodes.contains(targetFlowNode)) { | |
| 370 | - highLightedFlowIds.add(targetFlowNode.getId()); | |
| 371 | - } | |
| 372 | - } | |
| 373 | - } else { | |
| 374 | - long earliestStamp = 0L; | |
| 375 | - String highLightedFlowId = null; | |
| 376 | - // 循环流出的流 | |
| 377 | - for (SequenceFlow sequenceFlow : sequenceFlows) { | |
| 378 | - HistoricActivityInstance historicActivityInstance = historicActivityInstanceMap.get(sequenceFlow.getTargetRef()); | |
| 379 | - if (historicActivityInstance == null) { | |
| 380 | - continue; | |
| 381 | - } | |
| 382 | - final long startTime = historicActivityInstance.getStartTime().getTime(); | |
| 383 | - // 遍历匹配的集合,取得开始时间最早的一个 | |
| 384 | - if (earliestStamp == 0 || earliestStamp >= startTime) { | |
| 385 | - highLightedFlowId = sequenceFlow.getId(); | |
| 386 | - earliestStamp = startTime; | |
| 387 | - } | |
| 388 | - } | |
| 389 | - highLightedFlowIds.add(highLightedFlowId); | |
| 390 | - } | |
| 391 | - | |
| 392 | - } | |
| 393 | - return highLightedFlowIds; | |
| 394 | - } | |
| 395 | - | |
| 396 | 274 | private Task getTask(String id) { |
| 397 | 275 | return taskService.createTaskQuery().taskId(id).singleResult(); |
| 398 | 276 | } | ... | ... |
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/service/task/package-info.java
0 → 100644
| 1 | +/** | |
| 2 | + * task 包下,存放的都是 xxx 实例。例如说: | |
| 3 | + * 1. ProcessInstance 是 ProcessDefinition 创建而来的实例; | |
| 4 | + * 2. TaskInstance 是 TaskDefinition 创建而来的实例; | |
| 5 | + * 3. ActivityInstance 是 BPMN 流程图的每个元素创建的实例; | |
| 6 | + * | |
| 7 | + * 考虑到 Task 和 Activity 可以比较明确表示名字,所以对应的 Service 就没有使用 Instance 后缀~ | |
| 8 | + * 嘿嘿,其实也是实现到比较后面的阶段,所以就暂时没去统一和修改了~ | |
| 9 | + * | |
| 10 | + * @author 芋道源码 | |
| 11 | + */ | |
| 12 | +package cn.iocoder.yudao.adminserver.modules.bpm.service.task; | ... | ... |