add 添加获取运行中流程信息,流程扩展信息,补充注解,删除无用代码

This commit is contained in:
songgaoshuai 2024-02-05 15:27:04 +08:00
parent 16bc2a3944
commit 6273bde2f0
12 changed files with 190 additions and 43 deletions

View File

@ -8,11 +8,6 @@ package org.dromara.workflow.common.constant;
*/
public interface FlowConstant {
/**
* 命名空间
*/
String NAMESPACE = "http://b3mn.org/stencilset/bpmn2.0#";
String MESSAGE_CURRENT_TASK_IS_NULL = "当前任务不存在或你不是任务办理人!";
String MESSAGE_SUSPENDED = "当前任务已挂起不可审批!";
@ -22,6 +17,27 @@ public interface FlowConstant {
*/
String SEQUENCE_FLOW = "sequenceFlow";
/**
* 并行网关
*/
String PARALLEL_GATEWAY = "parallelGateway";
/**
* 排它网关
*/
String EXCLUSIVE_GATEWAY = "exclusiveGateway";
/**
* 包含网关
*/
String INCLUSIVE_GATEWAY = "inclusiveGateway";
/**
* 结束节点
*/
String END_EVENT = "endEvent";
/**
* 流程委派标识
*/
@ -62,17 +78,7 @@ public interface FlowConstant {
/**
* 流程发起人
*/
String INITIATOR = "INITIATOR";
/**
* 设计器中节点设置流程发起人
*/
String INITIATOR_SET = "$INITIATOR";
/**
* 修改设计器设置的变量错误内容
*/
String INITIATOR_SET_UPDATE = "${INITIATOR}";
String INITIATOR = "initiator";
/**
* 开启跳过表达式变量

View File

@ -4,6 +4,7 @@ import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.TableDataInfo;
@ -85,6 +86,7 @@ public class ActProcessDefinitionController extends BaseController {
* @param processDefinitionId 流程定义id
*/
@Log(title = "流程定义管理", businessType = BusinessType.DELETE)
@RepeatSubmit()
@DeleteMapping("/{deploymentId}/{processDefinitionId}")
public R<Void> deleteDeployment(@NotBlank(message = "流程部署id不能为空") @PathVariable String deploymentId,
@NotBlank(message = "流程定义id不能为空") @PathVariable String processDefinitionId) {
@ -97,6 +99,7 @@ public class ActProcessDefinitionController extends BaseController {
* @param processDefinitionId 流程定义id
*/
@Log(title = "流程定义管理", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping("/updateProcessDefState/{processDefinitionId}")
public R<Void> updateProcDefState(@NotBlank(message = "流程定义id不能为空") @PathVariable String processDefinitionId) {
return toAjax(actProcessDefinitionService.updateProcessDefState(processDefinitionId));
@ -109,6 +112,7 @@ public class ActProcessDefinitionController extends BaseController {
* @param fromProcessDefinitionId 需要迁移到的流程定义id
*/
@Log(title = "流程定义管理", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping("/migrationProcessDefinition/{currentProcessDefinitionId}/{fromProcessDefinitionId}")
public R<Void> migrationProcessDefinition(@NotBlank(message = "当前流程定义id") @PathVariable String currentProcessDefinitionId,
@NotBlank(message = "需要迁移到的流程定义id") @PathVariable String fromProcessDefinitionId) {
@ -121,6 +125,7 @@ public class ActProcessDefinitionController extends BaseController {
* @param processDefinitionId 流程定义id
*/
@Log(title = "流程定义管理", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping("/convertToModel/{processDefinitionId}")
public R<Void> convertToModel(@NotEmpty(message = "流程定义id不能为空") @PathVariable String processDefinitionId) {
return toAjax(actProcessDefinitionService.convertToModel(processDefinitionId));
@ -133,6 +138,7 @@ public class ActProcessDefinitionController extends BaseController {
* @param categoryCode 分类
*/
@Log(title = "流程定义管理", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/deployByFile")
public R<Void> deployByFile(@RequestParam("file") MultipartFile file, @RequestParam("categoryCode") String categoryCode) {
return toAjax(actProcessDefinitionService.deployByFile(file, categoryCode));

View File

@ -5,6 +5,7 @@ import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.TableDataInfo;
@ -63,6 +64,16 @@ public class ActProcessInstanceController extends BaseController {
return R.ok("操作成功", actProcessInstanceService.getHistoryProcessImage(processInstanceId));
}
/**
* 通过流程实例id获取历史流程图运行中历史等节点
*
* @param processInstanceId 流程实例id
*/
@GetMapping("/getHistoryProcessList/{processInstanceId}")
public R<Map<String, Object>> getHistoryProcessList(@NotBlank(message = "流程实例id不能为空") @PathVariable String processInstanceId) {
return R.ok("操作成功", actProcessInstanceService.getHistoryProcessList(processInstanceId));
}
/**
* 获取审批记录
*
@ -79,6 +90,7 @@ public class ActProcessInstanceController extends BaseController {
* @param processInvalidBo 参数
*/
@Log(title = "流程实例管理", businessType = BusinessType.DELETE)
@RepeatSubmit()
@PostMapping("/deleteRuntimeProcessInst")
public R<Void> deleteRuntimeProcessInst(@Validated(AddGroup.class) @RequestBody ProcessInvalidBo processInvalidBo) {
return toAjax(actProcessInstanceService.deleteRuntimeProcessInst(processInvalidBo));
@ -90,6 +102,7 @@ public class ActProcessInstanceController extends BaseController {
* @param processInstanceIds 流程实例id
*/
@Log(title = "流程实例管理", businessType = BusinessType.DELETE)
@RepeatSubmit()
@DeleteMapping("/deleteRuntimeProcessAndHisInst/{processInstanceIds}")
public R<Void> deleteRuntimeProcessAndHisInst(@NotNull(message = "流程实例id不能为空") @PathVariable String[] processInstanceIds) {
return toAjax(actProcessInstanceService.deleteRuntimeProcessAndHisInst(Arrays.asList(processInstanceIds)));
@ -101,6 +114,7 @@ public class ActProcessInstanceController extends BaseController {
* @param processInstanceIds 流程实例id
*/
@Log(title = "流程实例管理", businessType = BusinessType.DELETE)
@RepeatSubmit()
@DeleteMapping("/deleteFinishProcessAndHisInst/{processInstanceIds}")
public R<Void> deleteFinishProcessAndHisInst(@NotNull(message = "流程实例id不能为空") @PathVariable String[] processInstanceIds) {
return toAjax(actProcessInstanceService.deleteFinishProcessAndHisInst(Arrays.asList(processInstanceIds)));
@ -112,6 +126,7 @@ public class ActProcessInstanceController extends BaseController {
* @param processInstanceId 流程实例id
*/
@Log(title = "流程实例管理", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/cancelProcessApply/{processInstanceId}")
public R<Void> cancelProcessApply(@NotBlank(message = "流程实例id不能为空") @PathVariable String processInstanceId) {
return toAjax(actProcessInstanceService.cancelProcessApply(processInstanceId));
@ -133,6 +148,7 @@ public class ActProcessInstanceController extends BaseController {
* @param taskUrgingBo 任务催办
*/
@Log(title = "流程实例管理", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/taskUrging")
public R<Void> taskUrging(@RequestBody TaskUrgingBo taskUrgingBo) {
return toAjax(actProcessInstanceService.taskUrging(taskUrgingBo));

View File

@ -108,6 +108,7 @@ public class ActTaskController extends BaseController {
* @param taskId 任务id
*/
@Log(title = "任务管理", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/claim/{taskId}")
public R<Void> claimTask(@NotBlank(message = "任务id不能为空") @PathVariable String taskId) {
try {
@ -125,6 +126,7 @@ public class ActTaskController extends BaseController {
* @param taskId 任务id
*/
@Log(title = "任务管理", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/returnTask/{taskId}")
public R<Void> returnTask(@NotBlank(message = "任务id不能为空") @PathVariable String taskId) {
try {
@ -142,6 +144,7 @@ public class ActTaskController extends BaseController {
* @param delegateBo 参数
*/
@Log(title = "任务管理", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/delegateTask")
public R<Void> delegateTask(@Validated({AddGroup.class}) @RequestBody DelegateBo delegateBo) {
return toAjax(actTaskService.delegateTask(delegateBo));
@ -153,6 +156,7 @@ public class ActTaskController extends BaseController {
* @param terminationBo 参数
*/
@Log(title = "任务管理", businessType = BusinessType.DELETE)
@RepeatSubmit()
@PostMapping("/terminationTask")
public R<Void> terminationTask(@RequestBody TerminationBo terminationBo) {
return toAjax(actTaskService.terminationTask(terminationBo));
@ -164,6 +168,7 @@ public class ActTaskController extends BaseController {
* @param transmitBo 参数
*/
@Log(title = "任务管理", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/transferTask")
public R<Void> transferTask(@Validated({AddGroup.class}) @RequestBody TransmitBo transmitBo) {
return toAjax(actTaskService.transferTask(transmitBo));
@ -175,6 +180,7 @@ public class ActTaskController extends BaseController {
* @param addMultiBo 参数
*/
@Log(title = "任务管理", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/addMultiInstanceExecution")
public R<Void> addMultiInstanceExecution(@Validated({AddGroup.class}) @RequestBody AddMultiBo addMultiBo) {
return toAjax(actTaskService.addMultiInstanceExecution(addMultiBo));
@ -186,6 +192,7 @@ public class ActTaskController extends BaseController {
* @param deleteMultiBo 参数
*/
@Log(title = "任务管理", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/deleteMultiInstanceExecution")
public R<Void> deleteMultiInstanceExecution(@Validated({AddGroup.class}) @RequestBody DeleteMultiBo deleteMultiBo) {
return toAjax(actTaskService.deleteMultiInstanceExecution(deleteMultiBo));
@ -197,6 +204,7 @@ public class ActTaskController extends BaseController {
* @param backProcessBo 参数
*/
@Log(title = "任务管理", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/backProcess")
public R<String> backProcess(@RequestBody BackProcessBo backProcessBo) {
return R.ok(actTaskService.backProcess(backProcessBo));
@ -220,6 +228,7 @@ public class ActTaskController extends BaseController {
* @param userId 办理人id
*/
@Log(title = "任务管理", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping("/updateAssignee/{taskIds}/{userId}")
public R<Void> updateAssignee(@PathVariable String[] taskIds, @PathVariable String userId) {
return toAjax(actTaskService.updateAssignee(taskIds, userId));

View File

@ -82,7 +82,7 @@ public class GlobalFlowableListener implements FlowableEventListener {
if (task != null) {
List<Comment> taskComments = taskService.getTaskComments(task.getId());
if (CollUtil.isEmpty(taskComments)) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), TaskStatusEnum.PASS.getStatus(), "自动审批!");
taskService.addComment(task.getId(), task.getProcessInstanceId(), TaskStatusEnum.PASS.getStatus(), "超时自动审批!");
}
}
}

View File

@ -23,6 +23,14 @@ public interface IActProcessInstanceService {
*/
String getHistoryProcessImage(String processInstanceId);
/**
* 通过流程实例id获取历史流程图运行中历史等节点
*
* @param processInstanceId 流程实例id
* @return 结果
*/
Map<String, Object> getHistoryProcessList(String processInstanceId);
/**
* 分页查询正在运行的流程实例
*

View File

@ -23,6 +23,7 @@ import org.dromara.workflow.service.IWfCategoryService;
import org.flowable.engine.HistoryService;
import org.flowable.engine.ProcessMigrationService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.impl.bpmn.deployer.ResourceNameUtil;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.Model;
import org.flowable.engine.repository.ProcessDefinition;
@ -35,6 +36,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.zip.ZipInputStream;
@ -297,11 +299,13 @@ public class ActProcessDefinitionServiceImpl implements IActProcessDefinitionSer
deployment = repositoryService.createDeployment()
.tenantId(TenantHelper.getTenantId())
.addZipInputStream(new ZipInputStream(inputStream)).name(processName).key(processKey).category(categoryCode).deploy();
} else {
} else if (Arrays.asList(ResourceNameUtil.BPMN_RESOURCE_SUFFIXES).contains(filename)) {
// xml bpmn
deployment = repositoryService.createDeployment()
.tenantId(TenantHelper.getTenantId())
.addInputStream(filename, inputStream).name(processName).key(processKey).category(categoryCode).deploy();
} else {
throw new ServiceException("文件类型上传错误!");
}
// 更新分类
ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).singleResult();

View File

@ -39,6 +39,7 @@ import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.history.HistoricProcessInstanceQuery;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.runtime.ProcessInstanceQuery;
import org.flowable.engine.task.Comment;
@ -50,7 +51,9 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.awt.*;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
@ -211,6 +214,96 @@ public class ActProcessInstanceServiceImpl implements IActProcessInstanceService
return Base64.encode(IOUtils.toByteArray(inputStream));
}
/**
* 通过流程实例id获取历史流程图运行中历史等节点
*
* @param processInstanceId 流程实例id
*/
@Override
public Map<String, Object> getHistoryProcessList(String processInstanceId) {
Map<String, Object> map = new HashMap<>();
List<Map<String, Object>> taskList = new ArrayList<>();
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
StringBuilder xml = new StringBuilder();
ProcessDefinition processDefinition = repositoryService.getProcessDefinition(historicProcessInstance.getProcessDefinitionId());
// 获取节点
List<HistoricActivityInstance> highLightedFlowList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).orderByHistoricActivityInstanceStartTime().asc().list();
for (HistoricActivityInstance tempActivity : highLightedFlowList) {
Map<String, Object> task = new HashMap<>();
if (!FlowConstant.SEQUENCE_FLOW.equals(tempActivity.getActivityType()) &&
!FlowConstant.PARALLEL_GATEWAY.equals(tempActivity.getActivityType()) &&
!FlowConstant.EXCLUSIVE_GATEWAY.equals(tempActivity.getActivityType()) &&
!FlowConstant.INCLUSIVE_GATEWAY.equals(tempActivity.getActivityType())
) {
task.put("key", tempActivity.getActivityId());
task.put("completed", tempActivity.getEndTime() != null);
task.put("activityType", tempActivity.getActivityType());
taskList.add(task);
}
}
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
if (processInstance != null) {
taskList = taskList.stream().filter(e -> !e.get("activityType").equals(FlowConstant.END_EVENT)).collect(Collectors.toList());
}
//查询出运行中节点
List<Map<String, Object>> runtimeNodeList = taskList.stream().filter(e -> !(Boolean) e.get("completed")).collect(Collectors.toList());
if (CollUtil.isNotEmpty(runtimeNodeList)) {
Iterator<Map<String, Object>> iterator = taskList.iterator();
while (iterator.hasNext()) {
Map<String, Object> next = iterator.next();
runtimeNodeList.stream().filter(t -> t.get("key").equals(next.get("key")) && (Boolean) next.get("completed")).findFirst().ifPresent(t -> iterator.remove());
}
}
map.put("taskList", taskList);
List<ActHistoryInfoVo> historyTaskList = getHistoryTaskList(processInstanceId);
map.put("historyList", historyTaskList);
InputStream inputStream;
try {
inputStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getResourceName());
xml.append(IOUtils.toString(inputStream, String.valueOf(StandardCharsets.UTF_8)));
map.put("xml", xml.toString());
} catch (IOException e) {
e.printStackTrace();
}
return map;
}
/**
* 获取历史任务节点信息
*
* @param processInstanceId 流程实例id
*/
private List<ActHistoryInfoVo> getHistoryTaskList(String processInstanceId) {
//查询任务办理记录
List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).orderByHistoricTaskInstanceEndTime().desc().list();
list = StreamUtils.sorted(list, Comparator.comparing(HistoricTaskInstance::getEndTime, Comparator.nullsFirst(Date::compareTo)).reversed());
List<ActHistoryInfoVo> actHistoryInfoVoList = new ArrayList<>();
for (HistoricTaskInstance historicTaskInstance : list) {
ActHistoryInfoVo actHistoryInfoVo = new ActHistoryInfoVo();
BeanUtils.copyProperties(historicTaskInstance, actHistoryInfoVo);
actHistoryInfoVo.setStatus(actHistoryInfoVo.getEndTime() == null ? "待处理" : "已处理");
if (ObjectUtil.isNotEmpty(historicTaskInstance.getDurationInMillis())) {
actHistoryInfoVo.setRunDuration(getDuration(historicTaskInstance.getDurationInMillis()));
}
actHistoryInfoVoList.add(actHistoryInfoVo);
}
List<ActHistoryInfoVo> historyInfoVoList = new ArrayList<>();
Map<String, List<ActHistoryInfoVo>> groupByKey = StreamUtils.groupByKey(actHistoryInfoVoList, ActHistoryInfoVo::getTaskDefinitionKey);
for (Map.Entry<String, List<ActHistoryInfoVo>> entry : groupByKey.entrySet()) {
ActHistoryInfoVo historyInfoVo = new ActHistoryInfoVo();
BeanUtils.copyProperties(entry.getValue().get(0), historyInfoVo);
actHistoryInfoVoList.stream().filter(e -> e.getTaskDefinitionKey().equals(entry.getKey()) && e.getEndTime() == null).findFirst()
.ifPresent(e -> {
historyInfoVo.setStatus("待处理");
historyInfoVo.setStartTime(e.getStartTime());
historyInfoVo.setEndTime(null);
historyInfoVo.setRunDuration(null);
});
historyInfoVoList.add(historyInfoVo);
}
return historyInfoVoList;
}
/**
* 获取审批记录
*

View File

@ -24,10 +24,7 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.rmi.ServerException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
/**
@ -191,4 +188,33 @@ public class ModelUtils {
}
}
}
/**
* 获取全部扩展信息
*
* @param processDefinitionId 流程定义id
*/
public Map<String, List<ExtensionElement>> getExtensionElements(String processDefinitionId) {
Map<String, List<ExtensionElement>> map = new HashMap<>();
List<FlowElement> flowElements = getFlowElements(processDefinitionId);
for (FlowElement flowElement : flowElements) {
if (flowElement instanceof UserTask && CollUtil.isNotEmpty(flowElement.getExtensionElements())) {
map.putAll(flowElement.getExtensionElements());
}
}
return map;
}
/**
* 获取某个节点的扩展信息
*
* @param processDefinitionId 流程定义id
* @param flowElementId 节点id
*/
public Map<String, List<ExtensionElement>> getExtensionElement(String processDefinitionId, String flowElementId) {
BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(processDefinitionId);
Process process = bpmnModel.getMainProcess();
FlowElement flowElement = process.getFlowElement(flowElementId);
return flowElement.getExtensionElements();
}
}

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.workflow.mapper.WfBusinessFormMapper">
</mapper>

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.workflow.mapper.WfFormDefinitionMapper">
</mapper>

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.workflow.mapper.WfFormMapper">
</mapper>