简单的camunda流程处理开发记录
package cn.git.camunda.service.impl;
import cn.git.camunda.consts.CamundaConst;
import cn.git.camunda.dto.*;
import cn.git.camunda.entity.*;
import cn.git.camunda.mapper.ActReProcdefMapper;
import cn.git.camunda.mapper.CamundaJumpPointMapper;
import cn.git.camunda.mapper.CamundaUnfinishedFlowMapper;
import cn.git.camunda.page.CamundaFlowPage;
import cn.git.camunda.page.PageUtil;
import cn.git.camunda.service.CamundaCommonService;
import cn.git.camunda.util.CamundaFlowTypeEnum;
import cn.git.camunda.util.CamundaSysEnum;
import cn.git.camunda.util.CamundaTenantEnum;
import cn.git.camunda.util.CamundaUtil;
import cn.git.common.exception.ServiceException;
import cn.git.common.page.PaginationContext;
import cn.git.common.util.LogUtil;
import cn.git.common.util.WebUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.camunda.bpm.engine.*;
import org.camunda.bpm.engine.history.*;
import org.camunda.bpm.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.camunda.bpm.engine.impl.pvm.PvmActivity;
import org.camunda.bpm.engine.impl.pvm.PvmTransition;
import org.camunda.bpm.engine.impl.pvm.process.ActivityImpl;
import org.camunda.bpm.engine.repository.Deployment;
import org.camunda.bpm.engine.repository.ProcessDefinition;
import org.camunda.bpm.engine.repository.ProcessDefinitionQuery;
import org.camunda.bpm.engine.runtime.ProcessInstance;
import org.camunda.bpm.engine.runtime.ProcessInstanceModificationInstantiationBuilder;
import org.camunda.bpm.engine.runtime.ProcessInstantiationBuilder;
import org.camunda.bpm.engine.task.Comment;
import org.camunda.bpm.engine.task.Task;
import org.camunda.bpm.engine.task.TaskQuery;
import org.camunda.bpm.engine.variable.VariableMap;
import org.camunda.bpm.engine.variable.Variables;
import org.camunda.bpm.model.bpmn.BpmnModelInstance;
import org.camunda.bpm.model.bpmn.impl.instance.ProcessImpl;
import org.camunda.bpm.model.bpmn.impl.instance.UserTaskImpl;
import org.camunda.bpm.model.bpmn.instance.FlowNode;
import org.camunda.bpm.model.bpmn.instance.Process;
import org.camunda.bpm.model.bpmn.instance.SequenceFlow;
import org.camunda.bpm.model.bpmn.instance.UserTask;
import org.camunda.bpm.model.xml.instance.ModelElementInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* @description: camunda通用方法service
* @program: bank-credit-sy
* @author: lixuchun
* @create: 2023-09-12 09:12:05
*/
@Slf4j
@Service
public class CamundaCommonServiceImpl implements CamundaCommonService {
@Autowired
private TaskService taskService;
@Autowired
private RuntimeService runtimeService;
@Autowired
private IdentityService identityService;
@Autowired
private RepositoryService repositoryService;
@Autowired
private HistoryService historyService;
@Autowired
private ProcessEngine processEngine;
@Autowired
private CamundaUnfinishedFlowMapper camundaUnfinishedFlowMapper;
@Autowired
private ActReProcdefMapper actReProcdefMapper;
@Autowired
private CamundaJumpPointMapper camundaJumpPointMapper;
@Autowired
private FormService formService;
@Autowired
private PageUtil pageUtil;
@Autowired
private CamundaUtil camundaUtil;
@Autowired
private HttpServletResponse response;
@Autowired
private WebUtil webUtil;
/**
* 发起流程
*
* @param startProcessDTO 参数dto
* @return rspDTO
*/
@Override
@Transactional(rollbackFor = Exception.class)
public CamundaStartRspDTO startProcess(CamundaStartProcessDTO startProcessDTO) {
// 发起流程key
String businessKey = startProcessDTO.getBusinessKey();
log.info("businessKey[{}]准备发起流程,入参startProcessDTO为[{}]",
businessKey,
JSONObject.toJSONString(startProcessDTO));
// 设置发起流程操作员标识,以及认证信息(group组信息,tenantId租户信息)
String creator = startProcessDTO.getUserCd().concat(StrUtil.COLON).concat(startProcessDTO.getOrgCd());
identityService.setAuthentication(creator,
Arrays.asList(startProcessDTO.getCamundaTenantEnum().getGroup()),
Arrays.asList(startProcessDTO.getCamundaTenantEnum().getTenantId()));
log.info("businessKey[{}]发起流程设置操作员信息成功", businessKey);
// 设置传递参数信息
VariableMap variableMap = Variables.createVariables();
// 流程发起用户id
variableMap.put(CamundaConst.USER_ID_FLAG, creator);
// 流程模板id
variableMap.put(CamundaConst.PROCESS_TEMPLATE_KEY, startProcessDTO.getCamundaFlowTypeEnum().getProcessTemplateKey());
// 流程业务id
variableMap.put(CamundaConst.BUSINESS_KEY_FLAG, startProcessDTO.getBusinessKey());
// 流程业务类型
variableMap.put(CamundaConst.PROCESS_BIZ_TYPE, startProcessDTO.getCamundaFlowTypeEnum().getBizType());
// 流程业务名称
variableMap.put(CamundaConst.PROCESS_BIZ_NAME, startProcessDTO.getCamundaFlowTypeEnum().getBizName());
// 流程发起人
variableMap.put(CamundaConst.PROCESS_CREATOR, creator);
// 设置机构信息
variableMap.put(CamundaConst.ORG_NAME_FLAG, webUtil.getCurrentOrgName());
// 客户名称
variableMap.put(CamundaConst.CUSTOMER_NAME_FLAG, startProcessDTO.getCustomerName());
// 客户编号
variableMap.put(CamundaConst.CUSTOMER_NUM_FLAG, startProcessDTO.getCustomerNum());
// 发起系统来源
variableMap.put(CamundaConst.SYSTEM, startProcessDTO.getCamundaSysEnum().getSystemFlag());
// 设置自定义参数信息
if (ObjectUtil.isNotEmpty(startProcessDTO.getVariableMap())) {
variableMap.putAll(startProcessDTO.getVariableMap());
log.info("businessKey[{}]发起流程设置操作参数信息成功,参数为[{}]", businessKey, JSONObject.toJSONString(variableMap));
}
// 发起流程
log.info("businessKey[{}]装备发起流程!", businessKey);
String templateKey = startProcessDTO.getCamundaFlowTypeEnum().getProcessTemplateKey();
ProcessInstantiationBuilder builder = runtimeService.createProcessInstanceByKey(templateKey)
.processDefinitionTenantId(startProcessDTO.getCamundaTenantEnum().getTenantId())
.businessKey(startProcessDTO.getBusinessKey())
.setVariables(variableMap);
ProcessInstance processInstance = builder.execute();
// 设置响应信息
CamundaStartRspDTO camundaStartRspDTO = null;
if (ObjectUtil.isNotNull(processInstance)) {
camundaStartRspDTO = new CamundaStartRspDTO();
// 流程processId
String processInstanceId = processInstance.getProcessInstanceId();
// 通过 processId,获取task信息进行返回
Task task = taskService.createTaskQuery()
.tenantIdIn(startProcessDTO.getCamundaTenantEnum().getTenantId())
.processInstanceId(processInstanceId).singleResult();
if (ObjectUtil.isNotNull(task)) {
camundaStartRspDTO.setProcessId(processInstanceId);
camundaStartRspDTO.setTaskId(task.getId());
camundaStartRspDTO.setTaskName(task.getName());
// 当前流程任务定义key
camundaStartRspDTO.setTaskDefinitionKey(task.getTaskDefinitionKey());
log.info("businessKey[{}],发起流程后,获取任务信息为[{}]",
businessKey,
JSONObject.toJSONString(camundaStartRspDTO));
// 新增业务插入到在途业务表中,自定义代办任务记录表,业务系统方便查询。
CamundaUnfinishedFlow camundaUnfinishedFlow = new CamundaUnfinishedFlow();
camundaUnfinishedFlow.setId(IdUtil.simpleUUID());
camundaUnfinishedFlow.setOptionOrgCd(startProcessDTO.getUserCd());
camundaUnfinishedFlow.setOptionOrgCd(startProcessDTO.getOrgCd());
camundaUnfinishedFlow.setCustomerNum(startProcessDTO.getCustomerNum());
camundaUnfinishedFlow.setCustomerName(startProcessDTO.getCustomerName());
camundaUnfinishedFlow.setBusinessKey(startProcessDTO.getBusinessKey());
camundaUnfinishedFlow.setProcessId(processInstanceId);
camundaUnfinishedFlow.setBizName(startProcessDTO.getCamundaFlowTypeEnum().getBizName());
camundaUnfinishedFlow.setProcessTemplateKey(startProcessDTO.getCamundaFlowTypeEnum().getProcessTemplateKey());
if (ObjectUtil.isNotNull(startProcessDTO.getCamundaSysEnum())) {
camundaUnfinishedFlow.setSystemFlag(startProcessDTO.getCamundaSysEnum().getSystemFlag());
} else {
camundaUnfinishedFlow.setSystemFlag(CamundaSysEnum.DICS.getSystemFlag());
}
camundaUnfinishedFlowMapper.insert(camundaUnfinishedFlow);
}
}
return camundaStartRspDTO;
}
/**
* 通过柜员编号和机构编号获取代办未分类列表信息
*
* @param camundaUndoCountDTO 参数dto
* @return
*/
@Override
public CamundaFlowPage<List<CamundaUndoCount>> getUndoCountList(CamundaUndoCountDTO camundaUndoCountDTO) {
// 创建一个查询接口,进行传入操作标识人员代办任务查询
String userId = camundaUndoCountDTO.getUserCd().concat(StrUtil.COLON).concat(camundaUndoCountDTO.getOrgCd());
TaskQuery taskQuery = taskService.createTaskQuery()
// 具体操作人员标识
.taskAssignee(userId)
// 未被挂起任务
.active()
// 租户信息
.tenantIdIn(camundaUndoCountDTO.getCamundaTenantEnum().getTenantId())
// 获取参数信息
.matchVariableNamesIgnoreCase();
// 设定查询模板类型
if (StrUtil.isNotBlank(camundaUndoCountDTO.getProcessTemplateKey())) {
taskQuery.processDefinitionKey(camundaUndoCountDTO.getProcessTemplateKey());
}
// 查询带如下参数的流程信息
Map<String, Object> paramMap = camundaUndoCountDTO.getParamMap();
if (ObjectUtil.isNotEmpty(paramMap)) {
for (String key : camundaUndoCountDTO.getParamMap().keySet()) {
taskQuery.processVariableValueEquals(key, paramMap.get(key));
}
}
// 计算从哪条开始取,如何取出数据
List<Task> taskList = taskQuery.list();
// 对代办数据进行分类求count处理
List<CamundaUndoCount> camundaUndoCountList = new ArrayList<>();
if (ObjectUtil.isNotEmpty(taskList)) {
// 获取所有任务代办任务类型数据
List<String> processIdList = taskList.stream().map(Task::getProcessInstanceId).collect(Collectors.toList());
QueryWrapper<CamundaUnfinishedFlow> unfinishedFlowQueryWrapper = new QueryWrapper<>();
unfinishedFlowQueryWrapper.lambda().in(CamundaUnfinishedFlow::getProcessId, processIdList);
List<CamundaUnfinishedFlow> unfinishedFlowList = camundaUnfinishedFlowMapper
.selectList(unfinishedFlowQueryWrapper);
// 将查询数据转换为map信息
Map<String, CamundaUnfinishedFlow> unfinishedFlowMap = unfinishedFlowList.stream().collect(
Collectors.toMap(
CamundaUnfinishedFlow::getProcessId, Function.identity(), (k1, k2) -> k1
)
);
Map<String, CamundaUndoCount> undoCountMap = new HashMap<>(CamundaConst.INT_16);
taskList.forEach(task -> {
// 对任务进行分类计算count信息
CamundaUnfinishedFlow unfinishedFlow = unfinishedFlowMap.get(task.getProcessInstanceId());
if (ObjectUtil.isNotNull(unfinishedFlow)) {
// 获取流程模板id以及流程模板枚举类型
String processTemplateKey = unfinishedFlow.getProcessTemplateKey();
CamundaFlowTypeEnum flowTypeEnum = camundaUtil.getCamundaEnumByTemplateKey(processTemplateKey);
if (ObjectUtil.isNotNull(flowTypeEnum)) {
// 如果此类型有值,则count数进行加一
if (ObjectUtil.isNotNull(undoCountMap.get(processTemplateKey))) {
CamundaUndoCount currentUndoCount = undoCountMap.get(processTemplateKey);
currentUndoCount.setBizCount(currentUndoCount.getBizCount() + 1);
undoCountMap.put(processTemplateKey, currentUndoCount);
} else {
// 首次添加
CamundaUndoCount camundaUndoCount = new CamundaUndoCount();
camundaUndoCount.setBizCount(CamundaConst.INT_1);
camundaUndoCount.setBizTypeName(flowTypeEnum.getBizName());
camundaUndoCount.setBizType(flowTypeEnum.getBizType());
undoCountMap.put(processTemplateKey, camundaUndoCount);
}
}
}
});
// 封装返回信息list
if (ObjectUtil.isNotEmpty(undoCountMap)) {
undoCountMap.forEach((key, value) -> {
camundaUndoCountList.add(value);
});
}
}
return pageUtil.setFlowListPage(camundaUndoCountList, PaginationContext.getPageNum(), PaginationContext.getPageSize());
}
/**
* 查询代办分类后单一业务列表信息
*
* @param camundaUndoTaskDTO 参数dto
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public CamundaFlowPage<CamundaUndoTask> getUndoTaskList(CamundaUndoTaskDTO camundaUndoTaskDTO) {
// 创建一个查询接口,进行传入操作标识人员代办任务查询
String userId = camundaUndoTaskDTO.getUserCd().concat(StrUtil.COLON).concat(camundaUndoTaskDTO.getOrgCd());
TaskQuery taskQuery = taskService.createTaskQuery()
// 具体操作人员标识
.taskAssignee(userId)
// 未被挂起任务
.active()
// 租户信息
.tenantIdIn(camundaUndoTaskDTO.getCamundaTenantEnum().getTenantId())
// 获取参数信息
.matchVariableNamesIgnoreCase()
.orderByTaskCreateTime()
.desc();
// 设定查询模板类型
String processTemplateKey = camundaUndoTaskDTO.getProcessTemplateKey();
if (StrUtil.isNotBlank(processTemplateKey)) {
taskQuery.processDefinitionKey(processTemplateKey);
} else {
throw new ServiceException("单一业务模板查询必填!");
}
// 查询总条数信息
int totalCount = (int) taskQuery.count();
// 分页查询
int firstResultNum = pageUtil.getStartSizeNum(PaginationContext.getPageNum(), PaginationContext.getPageSize());
List<Task> taskList = taskQuery.listPage(firstResultNum, PaginationContext.getPageSize());
// 查询获取列表信息,封装最终返回信息
List<CamundaUndoTask> camundaUndoTaskList = new ArrayList<>();
if (ObjectUtil.isNotEmpty(taskList)) {
taskList.forEach(task -> {
// 获取参数信息以及业务枚举类型
Map<String, Object> variableMap = runtimeService.getVariables(task.getExecutionId());
CamundaFlowTypeEnum camundaFlowTypeEnum = camundaUtil.getCamundaEnumByTemplateKey(processTemplateKey);
// 封装返回类型信息
CamundaUndoTask camundaUndoTask = new CamundaUndoTask();
camundaUndoTask.setTaskId(task.getId());
camundaUndoTask.setOrgCd(StrUtil.toString(variableMap.get(CamundaConst.PROCESS_CREATOR)));
camundaUndoTask.setOrgName(StrUtil.toString(variableMap.get(CamundaConst.ORG_NAME_FLAG)));
camundaUndoTask.setProcessId(task.getProcessInstanceId());
camundaUndoTask.setBizType(camundaFlowTypeEnum.getBizType());
camundaUndoTask.setBizName(camundaFlowTypeEnum.getBizName());
camundaUndoTask.setProcessTemplateKey(camundaFlowTypeEnum.getProcessTemplateKey());
camundaUndoTask.setBusinessKey(StrUtil.toString(variableMap.get(CamundaConst.BUSINESS_KEY_FLAG)));
camundaUndoTask.setActivityId(task.getTaskDefinitionKey());
camundaUndoTask.setCreator(StrUtil.toString(variableMap.get(CamundaConst.PROCESS_CREATOR)));
camundaUndoTask.setProcessCreateDate(task.getCreateTime());
camundaUndoTask.setCustomerName(StrUtil.toString(variableMap.get(CamundaConst.CUSTOMER_NAME_FLAG)));
camundaUndoTask.setCustomerNum(StrUtil.toString(variableMap.get(CamundaConst.CUSTOMER_NAME_FLAG)));
camundaUndoTaskList.add(camundaUndoTask);
});
}
CamundaFlowPage<CamundaUndoTask> camundaFlowPage = new CamundaFlowPage<>();
camundaFlowPage.setPageSize(PaginationContext.getPageSize());
camundaFlowPage.setPageNum(PaginationContext.getPageNum());
// 返回分页信息
return pageUtil.setCountFlowListPage(camundaUndoTaskList,
PaginationContext.getPageNum(),
PaginationContext.getPageSize(),
totalCount);
}
/**
* 结束任务
*
* @param endTaskDTO 参数dto
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void endProcess(CamundaEndTaskDTO endTaskDTO) {
// 获取任务信息以及流程实例信息
Task task = taskService.createTaskQuery()
// 租户id
.tenantIdIn(endTaskDTO.getCamundaTenantEnum().getTenantId())
// 任务id
.taskId(endTaskDTO.getTaskId())
.singleResult();
if (ObjectUtil.isNull(task)) {
throw new ServiceException(StrUtil.format("通过taskId[{}]以及租户id[{}]获取任务信息为空!"));
}
// 获取流程实例信息
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
// 流程实例id
.processInstanceId(task.getProcessInstanceId())
// 租户信息
.tenantIdIn(endTaskDTO.getCamundaTenantEnum().getTenantId())
.singleResult();
// 空值校验
if (ObjectUtil.isNull(processInstance)) {
throw new ServiceException(StrUtil.format("通过taskId[{}]以及租户id[{}]获取流程实例信息为空,请确认!",
task.getProcessInstanceId(),
endTaskDTO.getCamundaTenantEnum().getTenantId()));
}
// 流程定义id
String processId = processInstance.getProcessInstanceId();
// 获取流程定义信息,获取结束任务对应节点,如果强制结束则直接获取流程中end结束节点进行结束任务
ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) repositoryService
.getProcessDefinition(processInstance.getProcessDefinitionId());
List<ActivityImpl> activityList = processDefinition.getActivities();
// 强制结束分支,如果一个节点没有 OutgoingTransitions 则为结束节点
ActivityImpl activityEndPoint = activityList.stream().filter(filterAct ->
ObjectUtil.isEmpty(filterAct.getOutgoingTransitions())
).findFirst().orElse(null);
// 设置评论信息
if (StrUtil.isNotBlank(endTaskDTO.getOpinion())) {
taskService.createComment(task.getId(), task.getProcessInstanceId(), endTaskDTO.getOpinion());
}
// 获取当前节点
ActivityImpl currentActivity = processDefinition.findActivity(task.getTaskDefinitionKey());
// 进行任务结束处理,判定当前节点是否为end节点
if (currentActivity.getActivityId().equals(activityEndPoint.getActivityId())) {
// 非强制结束,当前节点为end节点,调用complete方法即可
if (ObjectUtil.isNotEmpty(endTaskDTO.getParamsMap())) {
taskService.complete(task.getId(), endTaskDTO.getParamsMap());
} else {
taskService.complete(task.getId());
}
} else {
// 非end节点,进行强制结束,不是在结束任务,需要任务流转(跳节点),判断流转节点是否为空
if (ObjectUtil.isNotEmpty(endTaskDTO.getParamsMap())) {
// 带参数结束任务
runtimeService.createProcessInstanceModification(processInstance.getProcessInstanceId())
// 取消当前节点所有活动中的Task任务
.cancelAllForActivity(currentActivity.getActivityId())
// 目标节点Id,在流程图中看
.startBeforeActivity(activityEndPoint.getActivityId())
// 参数信息
.setVariables(endTaskDTO.getParamsMap())
// 意见信息
.setAnnotation(endTaskDTO.getOpinion())
.execute();
} else {
// 不带参数结束任务
runtimeService.createProcessInstanceModification(processInstance.getProcessInstanceId())
// 取消当前节点所有活动中的Task任务
.cancelAllForActivity(currentActivity.getActivityId())
// 目标节点Id,在流程图中看
.startBeforeActivity(activityEndPoint.getActivityId())
// 意见信息
.setAnnotation(endTaskDTO.getOpinion())
.execute();
}
// 未完成任务列表信息设置为删除状态
QueryWrapper<CamundaUnfinishedFlow> unfinishedFlowQueryWrapper = new QueryWrapper<>();
unfinishedFlowQueryWrapper.lambda().eq(CamundaUnfinishedFlow::getProcessId, processId);
camundaUnfinishedFlowMapper.delete(unfinishedFlowQueryWrapper);
}
}
/**
* 撤销任务
*
* @param camundaCancelDTO
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void cancelProcess(CamundaCancelDTO camundaCancelDTO) {
// 获取流程实例
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
.tenantIdIn(camundaCancelDTO.getCamundaTenantEnum().getTenantId())
.processInstanceId(camundaCancelDTO.getProcessId())
.singleResult();
if (ObjectUtil.isNull(processInstance)) {
throw new ServiceException(StrUtil.format("通过流程实例id[{}]以及租户id[{}]获取流程实例为空,撤销失败!",
camundaCancelDTO.getProcessId(),
camundaCancelDTO.getCamundaTenantEnum().getTenantId()));
}
// 进行撤销操作
runtimeService.deleteProcessInstance(camundaCancelDTO.getProcessId(), camundaCancelDTO.getCancelReason());
// 未完成任务列表信息设置为删除状态
QueryWrapper<CamundaUnfinishedFlow> unfinishedFlowQueryWrapper = new QueryWrapper<>();
unfinishedFlowQueryWrapper.lambda().eq(CamundaUnfinishedFlow::getProcessId, camundaCancelDTO.getProcessId());
camundaUnfinishedFlowMapper.delete(unfinishedFlowQueryWrapper);
}
/**
* 提交普通任务
*
* @param camundaSubmitTaskDTO 参数dto
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public CamundaSubmitTaskRspDTO submitNormalTask(CamundaSubmitTaskDTO camundaSubmitTaskDTO) {
// 获取task任务信息
Task task = taskService.createTaskQuery()
// 租户id
.tenantIdIn(camundaSubmitTaskDTO.getCamundaTenantEnum().getTenantId())
// 任务id
.taskId(camundaSubmitTaskDTO.getTaskId()).singleResult();
if (ObjectUtil.isNull(task)) {
throw new ServiceException("提交普通任务,获取task信息为空!");
}
// 获取流程实例信息
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
// 租户id
.tenantIdIn(camundaSubmitTaskDTO.getCamundaTenantEnum().getTenantId())
// 流程实例id
.processInstanceId(task.getProcessInstanceId())
.singleResult();
if (ObjectUtil.isNull(processInstance)) {
throw new ServiceException("提交普通任务,获取流程实例为空!");
}
// 设置评论信息
String approver = camundaSubmitTaskDTO.getNextUserCd().concat(StrUtil.COLON).concat(camundaSubmitTaskDTO.getNextOrgCd());
// 设置认证身份信息
identityService.setAuthentication(approver,
Arrays.asList(camundaSubmitTaskDTO.getCamundaTenantEnum().getGroup()),
Arrays.asList(camundaSubmitTaskDTO.getCamundaTenantEnum().getTenantId()));
// 将处理人填入
runtimeService.setVariable(task.getExecutionId(), "approver", approver);
// 设置评论信息
taskService.createComment(camundaSubmitTaskDTO.getTaskId(), processInstance.getProcessInstanceId(), camundaSubmitTaskDTO.getOpinion());
// 正常提交任务信息
if (ObjectUtil.isNotEmpty(camundaSubmitTaskDTO.getVariableMap())) {
taskService.complete(camundaSubmitTaskDTO.getTaskId(), camundaSubmitTaskDTO.getVariableMap());
} else {
taskService.complete(camundaSubmitTaskDTO.getTaskId());
}
// 获取提交之后的task信息
List<Task> taskList = taskService.createTaskQuery()
// 租戶信息
.tenantIdIn(camundaSubmitTaskDTO.getCamundaTenantEnum().getTenantId())
// 流程实例id
.processInstanceId(processInstance.getProcessInstanceId())
.orderByFollowUpDate()
.desc()
.list();
CamundaSubmitTaskRspDTO camundaSubmitTaskRspDTO = null;
if (ObjectUtil.isNotEmpty(taskList)) {
// 设定任务执行人信息
Task currentTask = taskList.get(CamundaConst.INT_0);
if (ObjectUtil.isNotNull(currentTask) && StrUtil.isBlank(task.getAssignee())) {
// 类似于setAssignee,设定执行人信息
taskService.claim(currentTask.getId(), approver);
}
// 设置下一处理task任务信息
camundaSubmitTaskRspDTO = new CamundaSubmitTaskRspDTO();
camundaSubmitTaskRspDTO.setNextTaskId(currentTask.getId());
camundaSubmitTaskRspDTO.setNextTaskName(currentTask.getName());
camundaSubmitTaskRspDTO.setTaskDefKey(currentTask.getTaskDefinitionKey());
}
return camundaSubmitTaskRspDTO;
}
/**
* 获取下一处理岗位信息
*
* @param camundaNextPositionDTO
* @return
*/
@Override
public CamundaNextPositionRspDTO getNextPositionList(CamundaNextPositionDTO camundaNextPositionDTO) {
// 最终响应参数信息
CamundaNextPositionRspDTO positionRspDTO = new CamundaNextPositionRspDTO();
// 通过taskId获取task实例信息
Task task = taskService.createTaskQuery()
// 租户id
.tenantIdIn(camundaNextPositionDTO.getCamundaTenantEnum().getTenantId())
// 任务id
.taskId(camundaNextPositionDTO.getTaskId())
.singleResult();
// 空值校验
if (ObjectUtil.isNull(task)) {
throw new ServiceException(StrUtil.format("通过taskId[{}]以及租户id[{}]获取下一处理岗位获取task实例信息为空!",
camundaNextPositionDTO.getTaskId(),
camundaNextPositionDTO.getCamundaTenantEnum().getTenantId()));
}
positionRspDTO.setCurrentPositionDefinitionKey(task.getTaskDefinitionKey());
// 获取流程实信息
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
// 租户id
.tenantIdIn(camundaNextPositionDTO.getCamundaTenantEnum().getTenantId())
// 流程实例id
.processInstanceId(task.getProcessInstanceId())
.singleResult();
// 空值校验
if (ObjectUtil.isNull(processInstance)) {
throw new ServiceException(StrUtil.format("通过流程实例id[{}]以及租户id[{}]获取流程定义信息获取为空!",
task.getProcessInstanceId(),
camundaNextPositionDTO.getCamundaTenantEnum().getTenantId()));
}
// 获取整体流程定义信息
ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) repositoryService
.getProcessDefinition(processInstance.getProcessDefinitionId());
// 获取当前节点定义信息
ActivityImpl currentActivity = processDefinition.findActivity(task.getTaskDefinitionKey());
// 获取当前节点传入参数信息
Map<String, Object> variablesMap = runtimeService.getVariables(task.getExecutionId());
// 最终获取全部下一处理岗位定义节点
List<PvmActivity> finalActivityList = new ArrayList<>();
// 获取当前节点对外指向,并且对指向进行分析
List<PvmTransition> transitionList = currentActivity.getOutgoingTransitions();
if (ObjectUtil.isNotEmpty(transitionList)) {
for (PvmTransition transition : transitionList) {
// 获取目标节点
PvmActivity destinationActivity = transition.getDestination();
String activityNodeType = StrUtil.toString(destinationActivity.getProperty(CamundaConst.CAMUNDA_NODE_TYPE));
// 目标节点不同类型进行不同处理,
if (CamundaConst.EXCLUSIVE_GATEWAY.equals(activityNodeType) || CamundaConst.INCLUSIVE_GATEWAY.equals(activityNodeType)) {
// 注意此处为 节点->排他网关/包含网关->节点 形式,更复杂形式需要针对业务进行调整
List<PvmActivity> exclusiveGateActivityList = getNextPositionByExclusiveGateway(destinationActivity, variablesMap);
finalActivityList.addAll(exclusiveGateActivityList);
} else if (CamundaConst.PARALLEL_GATEWAY.equals(activityNodeType)) {
// 并行网关 节点->并行网关->节点
List<PvmActivity> parallelGateActivityList = getNextPositionByParallelGateway(destinationActivity);
finalActivityList.addAll(parallelGateActivityList);
} else if (CamundaConst.USER_TASK.equals(activityNodeType)) {
// 普通用户任务 节点->节点
finalActivityList.add(destinationActivity);
} else {
throw new ServiceException(StrUtil.format("当前获取下一岗位信息暂时activityNodeType[{}]暂时不支持!", activityNodeType));
}
}
// 返回信息进行封装
List<CamundaNextPositionRspDTO.NextPosition> nextPositionList = new ArrayList<>();
if (ObjectUtil.isNotEmpty(finalActivityList)) {
nextPositionList = finalActivityList.stream().map(pvmActivity -> {
ActivityImpl activity = (ActivityImpl)pvmActivity;
CamundaNextPositionRspDTO.NextPosition nextPosition = new CamundaNextPositionRspDTO.NextPosition();
nextPosition.setNextPositionName(activity.getName());
nextPosition.setNextPositionDefinitionKey(activity.getActivityId());
return nextPosition;
}).collect(Collectors.toList());
}
// 查看是否有跳岗信息
String processDefinitionId = task.getProcessDefinitionId();
ActReProcdef actReProcdef = actReProcdefMapper.selectById(processDefinitionId);
if (ObjectUtil.isNull(actReProcdef)) {
throw new ServiceException(StrUtil.format("通过流程定义id[{}]获取流程实例定义信息为空!",
processDefinitionId));
}
// 获取版本,机构,模板key,机构以及task定义id查询跳岗信息
QueryWrapper<CamundaJumpPoint> jumpPointQueryWrapper = new QueryWrapper<>();
jumpPointQueryWrapper.lambda().eq(CamundaJumpPoint::getProcessTemplateKey, actReProcdef.getKey())
.eq(CamundaJumpPoint::getTemplateVersion, actReProcdef.getVersion())
.eq(CamundaJumpPoint::getActivityId, task.getTaskDefinitionKey())
.eq(CamundaJumpPoint::getOwnOrg, camundaNextPositionDTO.getOrgCd());
CamundaJumpPoint camundaJumpPoint = camundaJumpPointMapper.selectOne(jumpPointQueryWrapper);
// 如果当前没有获取到配置的机构,则向上获取上级机构配置,直到最*配置机构0001,如果没有配置,则认为当前你岗位不能跳岗,整体跳岗原则为就近原则
if (ObjectUtil.isNotNull(camundaJumpPoint) && StrUtil.isNotBlank(camundaJumpPoint.getJumpActivityIds())) {
// 获取跳岗信息字符串,多个岗位使用逗号分隔
List<String> activityIdList = Arrays.asList(camundaJumpPoint.getJumpActivityIds().split(StrUtil.COMMA).clone());
jumpPointQueryWrapper = new QueryWrapper<>();
jumpPointQueryWrapper.lambda().in(CamundaJumpPoint::getProcessTemplateKey, actReProcdef.getKey())
.eq(CamundaJumpPoint::getTemplateVersion, actReProcdef.getVersion())
.in(CamundaJumpPoint::getActivityId, activityIdList)
.eq(CamundaJumpPoint::getOwnOrg, camundaNextPositionDTO.getOrgCd());
List<CamundaJumpPoint> camundaJumpPointList = camundaJumpPointMapper.selectList(jumpPointQueryWrapper);
if (ObjectUtil.isNotEmpty(camundaJumpPointList)) {
// 封装跳岗信息
List<CamundaNextPositionRspDTO.NextPosition> jumpPositionList = camundaJumpPointList.stream().map(jumpPoint -> {
CamundaNextPositionRspDTO.NextPosition nextPosition = new CamundaNextPositionRspDTO.NextPosition();
nextPosition.setNextPositionName(jumpPoint.getActivityName());
nextPosition.setNextPositionDefinitionKey(jumpPoint.getActivityId());
return nextPosition;
}).collect(Collectors.toList());
// 添加跳岗信息
nextPositionList.addAll(jumpPositionList);
}
}
positionRspDTO.setNextPositionList(nextPositionList);
}
return positionRspDTO;
}
/**
* 获取任务变量信息
*
* @param camundaVariablesDTO 参数DTO
* @return
*/
@Override
public Map<String, Object> getTaskVariables(CamundaVariablesDTO camundaVariablesDTO) {
// 通过taskId获取task实例信息
Task task = taskService.createTaskQuery()
// 租户信息
.tenantIdIn(camundaVariablesDTO.getCamundaTenantEnum().getTenantId())
// 任务id
.taskId(camundaVariablesDTO.getTaskId())
.singleResult();
if (ObjectUtil.isNull(task)) {
throw new ServiceException(StrUtil.format("通过taskId[{}]以及租户id[{}]获取任务实例失败,请确认taskId传入正确!",
camundaVariablesDTO.getTaskId(),
camundaVariablesDTO.getCamundaTenantEnum().getTenantId()));
}
// 获取参数信息
Map<String, Object> variablesMap = taskService.getVariables(camundaVariablesDTO.getTaskId());
if (ObjectUtil.isNotEmpty(variablesMap) && ObjectUtil.isNotEmpty(camundaVariablesDTO.getVariableKeyList())) {
// 进行值过滤,过滤非筛选值
Map<String, Object> innerMap = variablesMap.entrySet().stream().filter(entry ->
camundaVariablesDTO.getVariableKeyList().contains(entry.getKey())
).collect(Collectors.toMap(
Map.Entry::getKey, Map.Entry::getValue)
);
return innerMap;
}
return variablesMap;
}
/**
* 删除参数key值
*
* @param taskId 任务id
* @param removeKey 参数key
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void removeVariable(String taskId, String removeKey, CamundaTenantEnum tenantEnum) {
// 获取task实例信息
Task task = taskService.createTaskQuery()
// 租户信息
.tenantIdIn(tenantEnum.getTenantId())
// 任务id
.taskId(taskId).singleResult();
if (ObjectUtil.isNull(task)) {
throw new ServiceException(StrUtil.format("删除参数通过taskId[{}]以及租户id[{}]查询task实例信息为空!",
taskId,
tenantEnum.getTenantId()));
}
taskService.removeVariable(taskId, removeKey);
}
/**
* 新增或者修改参数
*
* @param addOrUpdateVariableDTO 参数dto
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void addOrUpdateVariable(CamundaAddOrUpdateVariableDTO addOrUpdateVariableDTO) {
// 获取taskId以及租户信息
String taskId = addOrUpdateVariableDTO.getTaskId();
String tenantId = addOrUpdateVariableDTO.getCamundaTenantEnum().getTenantId();
// 获取任务实例信息,空值判定
Task task = taskService.createTaskQuery()
.tenantIdIn(tenantId)
.taskId(taskId)
.singleResult();
if (ObjectUtil.isNull(task)) {
throw new ServiceException(StrUtil.format("修改参数通过taskId[{}]以及租户id[{}]查询task实例信息为空!",
taskId,
tenantId));
}
// 修改参数
taskService.setVariable(taskId, addOrUpdateVariableDTO.getParamKey(), addOrUpdateVariableDTO.getParamValue());
}
/**
* 部署流程定义信息到本地库表中
*
* @param processDefinitionId 流程实例key
* @param orgCd 配置属于哪个机构
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void loadProcessDefinition(String processDefinitionId, String orgCd) {
// 流程定义信息
BpmnModelInstance bpmnModelInstance = repositoryService.getBpmnModelInstance(processDefinitionId);
if(ObjectUtil.isNull(bpmnModelInstance)){
throw new ServiceException(StrUtil.format("通过processDefinitionId[{}]查询流程定义实例信息为空", processDefinitionId));
}
// 获取process定义信息,服务名称
String processDefinitionName = null;
String processDefinitionKey = null;
Collection<Process> processCollection = bpmnModelInstance.getModelElementsByType(Process.class);
if (ObjectUtil.isNotNull(processCollection)) {
Optional<Process> optionalProcess = processCollection.stream().findFirst();
ProcessImpl processImpl = (ProcessImpl) optionalProcess.get();
// 获取流程定义名称 eg: camunda流程测试请假
processDefinitionName = processImpl.getName();
// 获取流程定义key eg: getRestDays
processDefinitionKey = processImpl.getId();
}
// 获取流程定义信息
ActReProcdef actReProcdef = actReProcdefMapper.selectById(processDefinitionId);
if (ObjectUtil.isNull(actReProcdef)) {
throw new ServiceException(StrUtil.format("通过processDefinitionId[{}]查询流程定义实例信息为空", processDefinitionId));
}
// 删除原有信息
QueryWrapper<CamundaJumpPoint> jumpPointQueryWrapper = new QueryWrapper<>();
jumpPointQueryWrapper.lambda().eq(CamundaJumpPoint::getProcessTemplateKey, processDefinitionKey)
.eq(CamundaJumpPoint::getOwnOrg, orgCd)
.eq(CamundaJumpPoint::getTemplateVersion, actReProcdef.getVersion());
camundaJumpPointMapper.delete(jumpPointQueryWrapper);
// 获取所有userTask任务节点信息
Collection<UserTask> userTaskCollection = bpmnModelInstance.getModelElementsByType(UserTask.class);
// 整合任务节点信息
List<UserTaskImpl> userTaskImplList = null;
if (ObjectUtil.isNotEmpty(userTaskCollection)) {
userTaskImplList = userTaskCollection.stream().map(userTask -> {
UserTaskImpl userTaskImpl = (UserTaskImpl) userTask;
return userTaskImpl;
}).collect(Collectors.toList());
}
// 开始进行落数
String finalProcessDefinitionKey = processDefinitionKey;
String finalProcessDefinitionName = processDefinitionName;
userTaskImplList.forEach(userTask -> {
// 获取流程task任务定义id以及定义name
String activityId = userTask.getId();
String activityName = userTask.getName();
// 封装跳转参数信息
CamundaJumpPoint camundaJumpPoint = new CamundaJumpPoint();
camundaJumpPoint.setId(IdUtil.simpleUUID());
// 所属机构
camundaJumpPoint.setOwnOrg(orgCd);
// 流程任务节点定义id
camundaJumpPoint.setActivityId(activityId);
// 任务节点定义名称
camundaJumpPoint.setActivityName(activityName);
// 模板key
camundaJumpPoint.setProcessTemplateKey(finalProcessDefinitionKey);
// 模板名称
camundaJumpPoint.setProcessTemplateName(finalProcessDefinitionName);
// 是否禁止跳岗标识
camundaJumpPoint.setNoJumpFlag(CamundaConst.STR_0);
// 版本信息
camundaJumpPoint.setTemplateVersion(actReProcdef.getVersion().toString());
// 插入信息
camundaJumpPointMapper.insert(camundaJumpPoint);
});
}
/**
* 操作跳跃节点信息
*
* @param camundaJumpPointSetDTO 参数dto
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void optionJumpPoint(CamundaJumpPointSetDTO camundaJumpPointSetDTO) {
// 跳跃节点不能包含当前节点信息
if (ObjectUtil.isNotEmpty(camundaJumpPointSetDTO.getJumpPoints())
&& camundaJumpPointSetDTO.getJumpPoints().contains(camundaJumpPointSetDTO.getCurrentActivityId())) {
throw new ServiceException("跳跃节点不能包含当前节点信息");
}
// 通过流程定义id获取流程定义信息
String processDefinitionId = camundaJumpPointSetDTO.getProcessDefinitionId();
ActReProcdef actReProcdef = actReProcdefMapper.selectById(processDefinitionId);
if (ObjectUtil.isNull(actReProcdef)) {
throw new ServiceException(StrUtil.format("通过processDefinitionId[{}]查询流程定义实例信息为空", processDefinitionId));
}
// 获取流程名称以及定义key以及version信息
String processTemplateName = actReProcdef.getName();
String processTemplateKey = actReProcdef.getKey();
String version = actReProcdef.getVersion().toString();
// 查询预设置跳岗信息
QueryWrapper<CamundaJumpPoint> camundaJumpPointQueryWrapper = new QueryWrapper<>();
camundaJumpPointQueryWrapper.lambda().eq(CamundaJumpPoint::getActivityId, camundaJumpPointSetDTO.getCurrentActivityId())
.eq(CamundaJumpPoint::getProcessTemplateKey, processTemplateKey)
.eq(CamundaJumpPoint::getProcessTemplateName, processTemplateName)
.eq(CamundaJumpPoint::getTemplateVersion, version)
.eq(CamundaJumpPoint::getOwnOrg, camundaJumpPointSetDTO.getOrgCd());
CamundaJumpPoint camundaJumpPoint = camundaJumpPointMapper.selectOne(camundaJumpPointQueryWrapper);
if (ObjectUtil.isNull(camundaJumpPoint)) {
throw new ServiceException(StrUtil.format("获取设置跳岗节点信息为空!"));
}
// 开始设置节点信息
if (StrUtil.isNotBlank(camundaJumpPointSetDTO.getJumpPoints())) {
camundaJumpPoint.setJumpActivityIds(camundaJumpPointSetDTO.getJumpPoints());
camundaJumpPointMapper.updateById(camundaJumpPoint);
} else {
// 跳转节点为空,则设置不能跳转
camundaJumpPointMapper.deleteJumpPointsById(camundaJumpPoint.getId());
}
}
/**
* 获取全部流程定义列表信息
*
* @param camundaDeployDTO 参数dto
* @return
*/
@Override
public CamundaFlowPage<ActReProcdef> getReProcessDeployPage(CamundaDeployDTO camundaDeployDTO) {
// 进行信息查询
QueryWrapper<ActReProcdef> queryWrapper = new QueryWrapper<>();
queryWrapper.eq(StrUtil.isNotBlank(camundaDeployDTO.getProcessTemplateKey()), "KEY_", camundaDeployDTO.getProcessTemplateKey())
.like(StrUtil.isNotBlank(camundaDeployDTO.getProcessTemplateName()), "NAME_", camundaDeployDTO.getProcessTemplateName())
.eq(StrUtil.isNotBlank(camundaDeployDTO.getVersion()), "VERSION_", camundaDeployDTO.getVersion());
List<ActReProcdef> actReProcdefList = actReProcdefMapper.selectList(queryWrapper);
return pageUtil.setFlowListPage(actReProcdefList, PaginationContext.getPageNum(), PaginationContext.getPageSize());
}
/**
* 获取任务节点信息
*
* @param camundaJumpPointPageDTO 参数dto
* @return
*/
@Override
public CamundaFlowPage<CamundaJumpPoint> getJumpPointPage(CamundaJumpPointPageDTO camundaJumpPointPageDTO) {
// 获取流程定义信息
ActReProcdef actReProcdef = actReProcdefMapper.selectById(camundaJumpPointPageDTO.getProcessDefinitionId());
if (ObjectUtil.isNull(actReProcdef)) {
throw new ServiceException(StrUtil.format("通过processDefinitionId[{}]查询流程定义实例信息为空", camundaJumpPointPageDTO.getProcessDefinitionId()));
}
// 获取流程名称以及定义key以及version信息
String processTemplateName = actReProcdef.getName();
String processTemplateKey = actReProcdef.getKey();
String version = actReProcdef.getVersion().toString();
// 查询预设置跳岗信息
List<String> unExpectActivityIdList = camundaJumpPointPageDTO.getUnExpectActivityIdList();
QueryWrapper<CamundaJumpPoint> camundaJumpPointQueryWrapper = new QueryWrapper<>();
camundaJumpPointQueryWrapper.lambda()
.eq(CamundaJumpPoint::getProcessTemplateKey, processTemplateKey)
.eq(CamundaJumpPoint::getProcessTemplateName, processTemplateName)
.eq(CamundaJumpPoint::getTemplateVersion, version)
// 跳跃节点设置权限失效标识 0 生效, 1 失效
.eq(CamundaJumpPoint::getIsDel, CamundaConst.STR_0)
.eq(CamundaJumpPoint::getOwnOrg, camundaJumpPointPageDTO.getOrgCd())
// 排除自定义无用节点
.notIn(ObjectUtil.isNotEmpty(unExpectActivityIdList), CamundaJumpPoint::getActivityId, unExpectActivityIdList);
List<CamundaJumpPoint> camundaJumpPointList = camundaJumpPointMapper.selectList(camundaJumpPointQueryWrapper);
return pageUtil.setFlowListPage(camundaJumpPointList, PaginationContext.getPageNum(), PaginationContext.getPageSize());
}
/**
* 获取跟踪列表信息
* 以任务角度出发,可能会出现一个businessKey对应多个task任务,因为此人在流程中多次审批,以不同岗位
*
* @param camundaTraceHistoryDTO 参数dto
* @return
*/
@Override
public CamundaFlowPage<List<CamundaTraceHistory>> getCamundaTracePage(CamundaTraceHistoryDTO camundaTraceHistoryDTO) {
// 封装列表参数信息
List<CamundaTraceHistory> camundaTraceHistoryList = new ArrayList<>();
// 封装查询参数信息 userCd:orgCd
String handleUser = camundaTraceHistoryDTO.getUserCd()
.concat(StrUtil.COLON)
.concat(camundaTraceHistoryDTO.getOrgCd());
// 封装查询参数信息
HistoricTaskInstanceQuery historicTaskInstanceQuery = historyService.createHistoricTaskInstanceQuery()
.tenantIdIn(camundaTraceHistoryDTO.getCamundaTenantEnum().getTenantId())
.taskInvolvedUser(handleUser)
.orderByProcessInstanceId()
.desc()
.matchVariableNamesIgnoreCase();
// 条件参数确认,任务模板查询
if (StrUtil.isNotBlank(camundaTraceHistoryDTO.getProcessTemplateKey())) {
historicTaskInstanceQuery.processVariableValueEquals(CamundaConst.PROCESS_TEMPLATE_KEY, camundaTraceHistoryDTO.getProcessTemplateKey());
}
// 客户名称查询
if (StrUtil.isNotBlank(camundaTraceHistoryDTO.getCustomerName())) {
historicTaskInstanceQuery.processVariableValueEquals(CamundaConst.CUSTOMER_NAME_FLAG, camundaTraceHistoryDTO.getCustomerName());
}
// 发起业务系统
if (StrUtil.isNotBlank(camundaTraceHistoryDTO.getSystem())) {
historicTaskInstanceQuery.processVariableValueEquals(CamundaConst.SYSTEM, camundaTraceHistoryDTO.getSystem());
}
// 流程在途结束判定
if (CamundaConst.RUNNING.equals(camundaTraceHistoryDTO.getStatus())) {
// 在途任务查询
historicTaskInstanceQuery.processUnfinished();
} else if (CamundaConst.FINISHED.equals(camundaTraceHistoryDTO.getStatus())) {
// 已经结束任务查询参数封装
historicTaskInstanceQuery.processFinished();
} else {
throw new ServiceException("查询跟踪列信息,是否在途参数获取为空!");
}
// 获取所有任务列表信息
List<HistoricTaskInstance> historicTaskInstanceList = historicTaskInstanceQuery.list();
// 进行数据封装
int totalCount = 0;
if (ObjectUtil.isNotEmpty(historicTaskInstanceList)) {
// 查询历史记录参数信息为map信息
Map<String, Map<String, Object>> historyVariablesMap = new HashMap<>(CamundaConst.INT_16);
Set<String> processIdList = historicTaskInstanceList.stream().
map(HistoricTaskInstance::getProcessInstanceId)
.collect(Collectors.toSet());
// 获取processInstance实例列表信息
int firstResultNum = pageUtil.getStartSizeNum(PaginationContext.getPageNum(), PaginationContext.getPageSize());
HistoricProcessInstanceQuery processInstanceQuery = historyService.createHistoricProcessInstanceQuery()
.processInstanceIds(processIdList)
.orderByProcessInstanceStartTime()
.desc()
.matchVariableValuesIgnoreCase();
// 流程实例历史信息进行分页查询
totalCount = (int)processInstanceQuery.count();
List<HistoricProcessInstance> historicProcessInstanceList = processInstanceQuery
.listPage(firstResultNum, PaginationContext.getPageSize());
// 组装查询variables 参数信息idArray
String[] processIdArray = processIdList.toArray(new String[processIdList.size()]);
List<HistoricVariableInstance> variableInstanceList = historyService.createHistoricVariableInstanceQuery()
// 租户信息
.tenantIdIn(camundaTraceHistoryDTO.getCamundaTenantEnum().getTenantId())
// 流程实例id列表
.processInstanceIdIn(processIdArray)
.list();
// 开始封装参数map key 为processInstanceId,value为当前processInstanceId下个属性map信息
if (ObjectUtil.isNotEmpty(variableInstanceList)) {
variableInstanceList.forEach(variableInstance-> {
String processInstanceId = variableInstance.getProcessInstanceId();
// 当前那processInstanceId加入过map
Map<String, Object> currentMap;
if (ObjectUtil.isNotEmpty(historyVariablesMap.get(processInstanceId))) {
currentMap = historyVariablesMap.get(processInstanceId);
} else {
// 首次加入map信息
currentMap = new HashMap<>(CamundaConst.INT_16);
}
currentMap.put(variableInstance.getName(), variableInstance.getValue());
historyVariablesMap.put(processInstanceId, currentMap);
});
}
historicProcessInstanceList.forEach(processInstance -> {
// 获取参数信息
Map<String, Object> variablesMap = historyVariablesMap.get(processInstance.getId());
CamundaTraceHistory camundaTraceHistory = new CamundaTraceHistory();
camundaTraceHistory.setBizType(StrUtil.toString(variablesMap.get(CamundaConst.PROCESS_BIZ_TYPE)));
camundaTraceHistory.setBusinessKey(StrUtil.toString(variablesMap.get(CamundaConst.BUSINESS_KEY_FLAG)));
camundaTraceHistory.setCreator(StrUtil.toString(variablesMap.get(CamundaConst.PROCESS_CREATOR)));
camundaTraceHistory.setOrgCd(StrUtil.toString(variablesMap.get(CamundaConst.PROCESS_CREATOR)));
camundaTraceHistory.setCustomerName(StrUtil.toString(variablesMap.get(CamundaConst.CUSTOMER_NAME_FLAG)));
camundaTraceHistory.setCustomerNum(StrUtil.toString(variablesMap.get(CamundaConst.CUSTOMER_NAME_FLAG)));
camundaTraceHistory.setProcessId(processInstance.getId());
camundaTraceHistory.setCreateDate(processInstance.getStartTime());
if (CamundaConst.FINISHED.equals(camundaTraceHistoryDTO.getStatus())) {
camundaTraceHistory.setStatus(CamundaConst.FINISHED);
} else {
camundaTraceHistory.setStatus(CamundaConst.RUNNING);
}
camundaTraceHistoryList.add(camundaTraceHistory);
});
}
// 返回分页信息
return pageUtil.setCountFlowListPage(camundaTraceHistoryList,
PaginationContext.getPageNum(),
PaginationContext.getPageSize(),
totalCount);
}
/**
* 跟踪列表处理人列表信息
*
* @param camundaTraceApproveHistoryDTO 参数dto
* @return
*/
@Override
public CamundaFlowPage<CamundaTraceApproveHistory> getCamundaTraceApprovePage(CamundaTraceApproveHistoryDTO camundaTraceApproveHistoryDTO) {
// 获取流程实例id
String processInstanceId = camundaTraceApproveHistoryDTO.getProcessId();
// 获取历史任务查询类
HistoricTaskInstanceQuery historicTaskInstanceQuery = historyService.createHistoricTaskInstanceQuery()
// 租户信息
.tenantIdIn(camundaTraceApproveHistoryDTO.getCamundaTenantEnum().getTenantId())
// 流程实例id
.processInstanceId(processInstanceId)
.orderByHistoricActivityInstanceStartTime()
.desc()
.matchVariableNamesIgnoreCase();
// 分页查询
int totalCount = (int) historicTaskInstanceQuery.count();
int firstResultNum = pageUtil.getStartSizeNum(PaginationContext.getPageNum(), PaginationContext.getPageSize());
List<HistoricTaskInstance> historicTaskInstanceList = historicTaskInstanceQuery.listPage(firstResultNum, PaginationContext.getPageSize());
// 最终返回分页信息
List<CamundaTraceApproveHistory> camundaTraceApproveHistoryList = new ArrayList<>();
// 进行数据封装
if (ObjectUtil.isNotEmpty(historicTaskInstanceList)) {
// 查询历史记录参数信息为map信息
Map<String, Object> historyVariablesMap = new HashMap<>(CamundaConst.INT_16);
// 组装查询variables
List<HistoricVariableInstance> variableInstanceList = historyService.createHistoricVariableInstanceQuery()
// 租户信息
.tenantIdIn(camundaTraceApproveHistoryDTO.getCamundaTenantEnum().getTenantId())
// 流程实例id
.processInstanceIdIn(processInstanceId)
.list();
// 开始封装参数map key 为processInstanceId,value为当前 processInstanceId 下个属性map信息
if (ObjectUtil.isNotEmpty(variableInstanceList)) {
variableInstanceList.forEach(variableInstance -> {
historyVariablesMap.put(variableInstance.getName(), variableInstance.getValue());
});
}
historicTaskInstanceList.forEach(historicTaskInstance -> {
// 获取参数信息
CamundaTraceApproveHistory camundaTraceApproveHistory = new CamundaTraceApproveHistory();
// 业务编号
camundaTraceApproveHistory.setBusinessKey(StrUtil.toString(historyVariablesMap.get(CamundaConst.BUSINESS_KEY_FLAG)));
// 流程实例id
camundaTraceApproveHistory.setProcessId(historicTaskInstance.getProcessInstanceId());
// 创建时间
camundaTraceApproveHistory.setCreateDate(historicTaskInstance.getStartTime());
// 结束时间
camundaTraceApproveHistory.setEndDate(historicTaskInstance.getEndTime());
// 操作岗位名称
camundaTraceApproveHistory.setPositionName(historicTaskInstance.getName());
// 机构信息 assign 截取
camundaTraceApproveHistory.setOrgCd(historicTaskInstance.getAssignee());
// 柜员信息 assign 截取
camundaTraceApproveHistory.setUserCd(historicTaskInstance.getAssignee());
// 获取评论信息
String commentMessage = null;
String taskId = historicTaskInstance.getId();
List<Comment> commentList = taskService.getTaskComments(taskId);
if (ObjectUtil.isNotEmpty(commentList)) {
commentMessage = commentList.get(CamundaConst.INT_0).getFullMessage();
}
camundaTraceApproveHistory.setOpinion(commentMessage);
camundaTraceApproveHistoryList.add(camundaTraceApproveHistory);
});
}
return pageUtil.setCountFlowListPage(camundaTraceApproveHistoryList,
PaginationContext.getPageNum(),
PaginationContext.getPageSize(),
totalCount);
}
/**
* 获取已经部署流程模板列表信息
*
* @param camundaLoadTemplateDTO 参数dto
* @return
*/
@Override
public CamundaFlowPage<CamundaLoadTemplate> getLoadTemplatePage(CamundaLoadTemplateDTO camundaLoadTemplateDTO) {
// 定义查询类
ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
// 设置爱租户信息
processDefinitionQuery.tenantIdIn(camundaLoadTemplateDTO.getCamundaTenantEnum().getTenantId());
// 流程定义条件查询,分别是定义key,以及流程定义名称还有版本号
if (StrUtil.isNotBlank(camundaLoadTemplateDTO.getTemplateKey())) {
processDefinitionQuery.processDefinitionKeyLike(camundaLoadTemplateDTO.getTemplateKey());
}
// 版本编号如果为空,则默认设置为最终版本
if (ObjectUtil.isNotNull(camundaLoadTemplateDTO.getVersion())) {
processDefinitionQuery.processDefinitionVersion(camundaLoadTemplateDTO.getVersion());
} else {
processDefinitionQuery.latestVersion();
}
// 开始查询列表信息
List<ProcessDefinition> definitionList = processDefinitionQuery
.orderByProcessDefinitionKey()
.asc()
.list();
// 封装返回分页信息
List<CamundaLoadTemplate> camundaLoadTemplateList = new ArrayList<>();
if (ObjectUtil.isNotEmpty(definitionList)) {
camundaLoadTemplateList = definitionList.stream().filter(definition -> {
if (StrUtil.isBlank(camundaLoadTemplateDTO.getTemplateName())) {
return true;
} else if (ObjectUtil.isNull(definition) || StrUtil.isBlank(definition.getName())) {
return false;
} else {
return definition.getName().contains(camundaLoadTemplateDTO.getTemplateName());
}
}).map(definition -> {
CamundaLoadTemplate camundaLoadTemplate = new CamundaLoadTemplate();
camundaLoadTemplate.setId(definition.getDeploymentId());
camundaLoadTemplate.setTemplateKey(definition.getKey());
camundaLoadTemplate.setTemplateName(definition.getName());
camundaLoadTemplate.setVersion(definition.getVersion());
// 通过deploymentId获取deployment部署时间信息
String deploymentId = definition.getDeploymentId();
Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId)
.singleResult();
if (ObjectUtil.isNotNull(deployment)) {
camundaLoadTemplate.setCreateTime(DateUtil.format(deployment.getDeploymentTime(), DatePattern.NORM_DATETIME_PATTERN));
}
return camundaLoadTemplate;
}).collect(Collectors.toList());
}
return pageUtil.setCountFlowListPage(camundaLoadTemplateList,
PaginationContext.getPageNum(),
PaginationContext.getPageSize(),
definitionList.size());
}
/**
* 任务驳回到发起岗或者上一岗位
*
* @param camundaRejectTaskDTO 驳回参数DTO
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean rejectTaskToStartNode(CamundaRejectTaskDTO camundaRejectTaskDTO) {
// 获取当前任务信息
Task currentTask = taskService.createTaskQuery()
// 租户信息
.tenantIdIn(camundaRejectTaskDTO.getCamundaTenantEnum().getTenantId())
.taskId(camundaRejectTaskDTO.getTaskId())
.singleResult();
if (ObjectUtil.isNull(currentTask)) {
throw new ServiceException(StrUtil.format("通过taskId[{}]获取当前任务信息为空!", camundaRejectTaskDTO.getTaskId()));
}
// 通过task任务信息获取流程实例信息
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
// 租户信息
.tenantIdIn(camundaRejectTaskDTO.getCamundaTenantEnum().getTenantId())
// 流程实例id
.processInstanceId(currentTask.getProcessInstanceId())
.singleResult();
if (ObjectUtil.isNull(processInstance)) {
throw new ServiceException(StrUtil.format("通过processId[{}]获取流程实例信息为空!", processInstance.getProcessInstanceId()));
}
// 获取已经结束的历史节点信息
List<HistoricActivityInstance> activityInstanceList = historyService.createHistoricActivityInstanceQuery()
// 租户信息
.tenantIdIn(camundaRejectTaskDTO.getCamundaTenantEnum().getTenantId())
// 流程实例id
.processInstanceId(processInstance.getProcessInstanceId())
// 节点类型
.activityType(CamundaConst.USER_TASK)
// 已经结束的
.finished()
// 按照结束时间进行升序排序
.orderByHistoricActivityInstanceEndTime()
.asc()
.list();
// 空值校验
if (ObjectUtil.isEmpty(activityInstanceList)) {
throw new ServiceException("获取历史userTask任务信息为空!");
}
// 首个任务节点
HistoricActivityInstance startInstance = activityInstanceList.get(CamundaConst.INT_0);
// 设置退回操作员信息以及退回节点activityId信息
String activityId = null;
String assignee = null;
// 强制退回到发起节点判定
if (camundaRejectTaskDTO.getIfRejectToStartNode()) {
// 如果历史userTask节点没有或者只有一个,则不能进行驳回操作
if (activityInstanceList.size() < CamundaConst.INT_1) {
throw new ServiceException("首个用户操作节点无法驳回!");
}
// 获取跳转节点信息,目标节点id以及节点操作员信息
activityId = startInstance.getActivityId();
assignee = startInstance.getAssignee();
} else {
// 退回到上一节点判定,当前节点为首个节点,无法退回
if (currentTask.getTaskDefinitionKey().equals(startInstance.getActivityId())) {
throw new ServiceException("首个用户操作节点无法驳回!");
}
// 判断当前任务是否已经退回过
List<HistoricActivityInstance> equalCurrentActivityList = activityInstanceList.stream().filter(instance -> {
if (instance.getActivityId().equals(currentTask.getTaskDefinitionKey())) {
return true;
}
return false;
}).collect(Collectors.toList());
// 首次退回
if (ObjectUtil.isEmpty(equalCurrentActivityList)) {
// 倒数第一个为上一岗位信息
HistoricActivityInstance historicActivityInstance = activityInstanceList.get(activityInstanceList.size() - 1);
activityId = historicActivityInstance.getActivityId();
assignee = historicActivityInstance.getAssignee();
} else {
// 经过退回操作,eg: 1 2 3 4,4个节点当前节点信息如果在3,则表示该节点是从4退回来的,如果再退回则需要退回到2,再到1
for (int index = 0; index < activityInstanceList.size(); index ++) {
// 获取循环对象
HistoricActivityInstance loopActivityInstance = activityInstanceList.get(index);
// 如果当前循环activity信息不是第一节点,并且循环节点等于当前任务节点,则上一节点就为应退回节点
if (index > CamundaConst.INT_0
&& loopActivityInstance.getActivityId().equals(currentTask.getTaskDefinitionKey())) {
HistoricActivityInstance backActivityInstance = activityInstanceList.get(index - CamundaConst.INT_1);
activityId = backActivityInstance.getActivityId();
assignee = backActivityInstance.getAssignee();
}
}
}
}
// 设置参数以及拒绝任务的原因参数信息
Map<String, Object> variablesMap = new HashMap<>();
variablesMap.put(CamundaConst.APPROVE, assignee);
taskService.createComment(currentTask.getId(), processInstance.getProcessInstanceId(), camundaRejectTaskDTO.getRejectReason());
// 获取流程定义信息,获取结束任务对应节点,如果强制结束则直接获取流程中end结束节点进行结束任务
ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) repositoryService
.getProcessDefinition(processInstance.getProcessDefinitionId());
// 获取当前节点
ActivityImpl currentActivity = processDefinition.findActivity(currentTask.getTaskDefinitionKey());
runtimeService.createProcessInstanceModification(processInstance.getProcessInstanceId())
// 驳回原因
.setAnnotation(camundaRejectTaskDTO.getRejectReason())
// 取消当前活动的所有任务
.cancelAllForActivity(currentActivity.getActivityId())
// 目标节点Id,在流程图中看
.startBeforeActivity(activityId)
// 参数信息
.setVariables(variablesMap)
.execute();
return true;
}
/**
* 跳转到目标节点
*
* @param camundaGotoDTO
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean gotoDestinationTask(CamundaGotoDTO camundaGotoDTO) {
// 获取当前节点task任务信息
Task currentTask = taskService.createTaskQuery()
// 租户信息
.tenantIdIn(camundaGotoDTO.getCamundaTenantEnum().getTenantId())
// 任务节点信息
.taskId(camundaGotoDTO.getCurrentTaskId()).singleResult();
if (ObjectUtil.isNull(currentTask)) {
throw new ServiceException(StrUtil.format("通过taskId[{}]获取task信息为空!", camundaGotoDTO.getCurrentTaskId()));
}
// 校验节点是否可以跳跃,获取流程定义id,当前节点activityId以及机构信息
String processDefinitionId = currentTask.getProcessDefinitionId();
String currentActivityId = currentTask.getTaskDefinitionKey();
String ownOrgCd = camundaGotoDTO.getOrgCd();
// 查询当前节点是否配置可跳跃节点信息
ActReProcdef actReProcdef = actReProcdefMapper.selectById(processDefinitionId);
if (ObjectUtil.isNull(actReProcdef)) {
throw new ServiceException(StrUtil.format("通过流程定义id[{}],获取流程定义信息为空!", processDefinitionId));
}
// 获取当前节点配置信息
QueryWrapper<CamundaJumpPoint> jumpPointQueryWrapper = new QueryWrapper<>();
jumpPointQueryWrapper.lambda().eq(CamundaJumpPoint::getActivityId, currentActivityId)
.eq(CamundaJumpPoint::getTemplateVersion, actReProcdef.getVersion())
.eq(CamundaJumpPoint::getOwnOrg, ownOrgCd)
.eq(CamundaJumpPoint::getProcessTemplateKey, actReProcdef.getKey());
CamundaJumpPoint camundaJumpPoint = camundaJumpPointMapper.selectOne(jumpPointQueryWrapper);
if (ObjectUtil.isNull(camundaJumpPoint)) {
throw new ServiceException(StrUtil.format("当前模板[{}]对应机构[{}]对应岗位未配置跳岗信息,请确认!",
actReProcdef.getKey(),
ownOrgCd));
}
// 岗位配置正确性校验,可跳跃节点不好含当前跳跃节点,则直接返回异常信息
if (StrUtil.isNotBlank(camundaJumpPoint.getJumpActivityIds())
&& !camundaJumpPoint.getJumpActivityIds().contains(camundaGotoDTO.getDestActivityId())) {
throw new ServiceException("当前岗位不能跳转到选定岗位,请配置后再试!");
}
// 设置意见信息
taskService.createComment(currentTask.getId(), currentTask.getProcessInstanceId(), camundaGotoDTO.getOpinion());
// 进行跳岗信息
ProcessInstanceModificationInstantiationBuilder instantiationBuilder = runtimeService
.createProcessInstanceModification(currentTask.getProcessInstanceId())
// 取消当前活动的所有任务
.cancelAllForActivity(currentActivityId)
// 跳转原因
.setAnnotation(camundaGotoDTO.getOpinion())
// 目标节点Id,在流程图中看
.startBeforeActivity(camundaGotoDTO.getDestActivityId());
// 参数信息
if (ObjectUtil.isNotEmpty(camundaGotoDTO.getVariablesMap())) {
instantiationBuilder.setVariables(camundaGotoDTO.getVariablesMap());
}
// 执行节点跳跃
instantiationBuilder.execute();
return true;
}
/**
* 获取当前任务完成节点,连线,未完成节点信息
* todo: 后续可以加入自定义的完成节点,退回操作记录表,更准确展示当前节点任务高亮信息
*
* @param camundaTaskImageDTO 参数dto
* @return
*/
@Override
public CamundaTaskImageNodeRspDTO getCamundaTaskImage(CamundaTaskImageDTO camundaTaskImageDTO) {
// 最终返回参数信息
CamundaTaskImageNodeRspDTO camundaTaskImageNodeRspDTO = new CamundaTaskImageNodeRspDTO();
// 根据taskId获取任务信息
String taskId = camundaTaskImageDTO.getTaskId();
Task currentTask = taskService.createTaskQuery()
.tenantIdIn(camundaTaskImageDTO.getCamundaTenantEnum().getTenantId())
.taskId(taskId)
.singleResult();
if (ObjectUtil.isNull(currentTask)) {
throw new ServiceException(StrUtil.format("通过taskId[{}]以及租户id[{}]获取task信息为空!",
taskId,
camundaTaskImageDTO.getCamundaTenantEnum().getTenantId()));
}
// 获取processInstance信息
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
// 租户id
.tenantIdIn(camundaTaskImageDTO.getCamundaTenantEnum().getTenantId())
// 流程实例id
.processInstanceId(currentTask.getProcessInstanceId())
.singleResult();
if (ObjectUtil.isNull(processInstance)) {
throw new ServiceException(StrUtil.format("通过processId[{}]获取流程实例信息为空!", currentTask.getProcessInstanceId()));
}
// 流程实例id
String processInstanceId = processInstance.getProcessInstanceId();
// 获取已经完成的任务节点
List<HistoricActivityInstance> finishedActivityInstanceList = historyService.createHistoricActivityInstanceQuery()
.tenantIdIn(camundaTaskImageDTO.getCamundaTenantEnum().getTenantId())
.processInstanceId(processInstanceId)
.finished()
.orderByHistoricActivityInstanceStartTime()
.asc()
.list();
if (ObjectUtil.isNotEmpty(finishedActivityInstanceList)) {
List<String> finishedActivityIdList = finishedActivityInstanceList
.stream()
.map(HistoricActivityInstance::getActivityId)
.collect(Collectors.toList());
camundaTaskImageNodeRspDTO.setFinishedActivityIdList(finishedActivityIdList);
}
// 未完成节点信息
List<HistoricActivityInstance> unfinishedActivityInstanceList = historyService.createHistoricActivityInstanceQuery()
.tenantIdIn(camundaTaskImageDTO.getCamundaTenantEnum().getTenantId())
.processInstanceId(processInstanceId)
.unfinished()
.list();
if (ObjectUtil.isNotEmpty(unfinishedActivityInstanceList)) {
List<String> unfinishedActivityIdList = unfinishedActivityInstanceList
.stream()
.map(HistoricActivityInstance::getActivityId)
.collect(Collectors.toList());
camundaTaskImageNodeRspDTO.setUnfinishedActivityIdList(unfinishedActivityIdList);
}
// 自己办理任务获取
String optionUser = camundaTaskImageDTO.getUserCd().concat(StrUtil.COLON).concat(camundaTaskImageDTO.getOrgCd());
List<HistoricTaskInstance> selfOptionTaskInstanceList = historyService.createHistoricTaskInstanceQuery()
.tenantIdIn(camundaTaskImageDTO.getCamundaTenantEnum().getTenantId())
.taskAssignee(optionUser)
.finished()
.processInstanceId(processInstanceId)
.list();
if (ObjectUtil.isNotEmpty(selfOptionTaskInstanceList)) {
List<String> selfOptionIdList = selfOptionTaskInstanceList
.stream()
.map(HistoricTaskInstance::getTaskDefinitionKey)
.collect(Collectors.toList());
camundaTaskImageNodeRspDTO.setSelfOptionActivityIdList(selfOptionIdList);
}
// 获取流程中的高亮线,获取流程定义的bpmn模型
List<String> highLineList = new ArrayList<>();
BpmnModelInstance bpmnModelInstance = repositoryService.getBpmnModelInstance(processInstance.getProcessDefinitionId());
for (HistoricActivityInstance finishedActivity : finishedActivityInstanceList) {
// 获取 bpmn 元素
ModelElementInstance modelElementInstance = bpmnModelInstance.getModelElementById(finishedActivity.getActivityId());
// 将节点转换为 flowNode 流程节点,获取输入输出线
FlowNode flowNode = (FlowNode)modelElementInstance;
// 获取outgoing线信息
Collection<SequenceFlow> outgoingCollection = flowNode.getOutgoing();
if (ObjectUtil.isEmpty(outgoingCollection)) {
continue;
}
// 循环outgoing信息
outgoingCollection.forEach(outgoing -> {
// 线段目标节点信息
String targetId = outgoing.getTarget().getId();
// 完成任务,多次循环,所有完成任务对应outgoing线全部高亮
for (HistoricActivityInstance innerFinished : finishedActivityInstanceList) {
String optionActivityId = innerFinished.getActivityId();
// 循环任务为target目标节点,并且 则高亮
if(targetId.equals(optionActivityId)){
if(finishedActivity.getEndTime().equals(innerFinished.getStartTime())){
highLineList.add(outgoing.getId());
}
}
}
// 待完成任务高亮节点
for (HistoricActivityInstance unfinishedActivityInstance : unfinishedActivityInstanceList) {
String optionActivityId = unfinishedActivityInstance.getActivityId();
if(targetId.equals(optionActivityId)){
if(finishedActivity.getEndTime().equals(unfinishedActivityInstance.getStartTime())){
highLineList.add(outgoing.getId());
}
}
}
});
camundaTaskImageNodeRspDTO.setHighLineList(highLineList);
}
return camundaTaskImageNodeRspDTO;
}
/**
* 通过版本号,流程定义processDefinitionKey获取流程定义xml信息
*
* @param processDefinitionKey
* @param version 版本编号
* @param tenantEnum 租户枚举信息
*/
@Override
public String getDefinitionXMLByKeyAndVersion(String processDefinitionKey, Integer version, CamundaTenantEnum tenantEnum) throws IOException {
// 获取流程定义信息
List<ProcessDefinition> processDefinitionList = repositoryService.createProcessDefinitionQuery()
// 租户id
.tenantIdIn(tenantEnum.getTenantId())
.processDefinitionKey(processDefinitionKey)
.list();
// 空值判定
if (ObjectUtil.isEmpty(processDefinitionList)) {
throw new ServiceException(StrUtil.format("通过processDefinitionKey[{}]获取流程定义信息为空!",
processDefinitionKey));
}
// 获取对应版本的信息
ProcessDefinition processDefinition = processDefinitionList.stream().filter(definition ->
version.equals(definition.getVersion())
).findFirst().orElse(null);
// 空值判定
if (ObjectUtil.isNull(processDefinition)) {
throw new ServiceException(StrUtil.format("通过processDefinitionKey[{}]获取版本号[{}]的流程定义信息为空,未找到对应版本定义信息!",
processDefinitionKey,
version));
}
// 获取文件输入流信息
InputStream xmlStream = repositoryService.getProcessModel(processDefinition.getId());
// 通过 inputStream 获取xml字符串信息
String xmlStr = IOUtils.toString(xmlStream, StandardCharsets.UTF_8);
return xmlStr;
}
/**
* 获取流程图
*
* @param processId 流程实例id
*/
@Override
public void getDefinitionXMLByProcessId(String processId, CamundaTenantEnum camundaTenantEnum) throws IOException {
// 通过runtimeService获取processDefinitionId
String processDefinitionId = runtimeService.createProcessInstanceQuery()
// 租户信息
.tenantIdIn(camundaTenantEnum.getTenantId())
.processInstanceId(processId)
.singleResult()
.getProcessDefinitionId();
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
// 租户信息
.tenantIdIn(camundaTenantEnum.getTenantId())
.processDefinitionId(processDefinitionId)
.singleResult();
InputStream xmlStream = repositoryService.getProcessModel(processDefinition.getId());
// 设置响应头信息,比如Content-Type和Content-Disposition
response.setContentType("application/xml");
// 根据实际文件类型设置MIME类型,这里是XML文件
response.setHeader("Content-Disposition", "attachment;filename=\"" + processDefinition.getKey() + "\"");
try (OutputStream out = response.getOutputStream()) {
byte[] buffer = new byte[1024]; // 缓冲区大小,可以根据实际情况调整
int bytesRead;
// 从xmlStream读取数据并写入到responseOutputStream
while ((bytesRead = xmlStream.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
}
} catch (IOException e) {
// 处理IO异常
String errorMessage = LogUtil.getStackTraceInfo(e);
throw new ServiceException(StrUtil.format("下载文件异常,异常信息为[{}]", errorMessage));
} finally {
response.flushBuffer();
}
}
/**
* 获取流程图XML字符串
*
* @param processId 流程实例id
* @param camundaTenantEnum 租户枚举信息
*/
@Override
public String getDefinitionXMLStrByProcessId(String processId, CamundaTenantEnum camundaTenantEnum) throws IOException {
// 通过runtimeService获取processDefinitionId
String processDefinitionId = runtimeService.createProcessInstanceQuery()
// 租户信息
.tenantIdIn(camundaTenantEnum.getTenantId())
.processInstanceId(processId)
.singleResult()
.getProcessDefinitionId();
// 空值判定
if (StrUtil.isBlank(processDefinitionId)) {
throw new ServiceException("通过processId获取流程定义processDefinitionId为空!");
}
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.tenantIdIn(camundaTenantEnum.getTenantId())
.processDefinitionId(processDefinitionId)
.singleResult();
// 空值判定
if (ObjectUtil.isNull(processDefinition)) {
throw new ServiceException(StrUtil.format("通过processDefinitionId[{}]获取流程定义信息为空!",
processDefinitionId));
}
InputStream xmlStream = repositoryService.getProcessModel(processDefinition.getId());
// 通过 inputStream 获取xml字符串信息
String xmlStr = IOUtils.toString(xmlStream, StandardCharsets.UTF_8);
return xmlStr;
}
/**
* 部署流程
*
* @param file 文件
* @param tenantEnum 租户枚举
*/
@Override
@Transactional(rollbackFor = Exception.class)
public String deployProcess(MultipartFile file, CamundaTenantEnum tenantEnum) throws IOException {
// 文件校验
if (file.isEmpty()) {
throw new ServiceException("部署新流程,流程文件为空!");
}
// 开始部署流程
Deployment deployment = repositoryService.createDeployment()
.addInputStream(file.getOriginalFilename(), file.getInputStream())
.tenantId(tenantEnum.getTenantId())
.name(file.getOriginalFilename())
.deploy();
// 通过deploymentId获取流程定义集合信息(首次部署,只有一个流程定义信息)
String deploymentId = deployment.getId();
List<ProcessDefinition> definitionList = repositoryService.createProcessDefinitionQuery()
// 租户id
.tenantIdIn(tenantEnum.getTenantId())
.deploymentId(deploymentId)
.list();
// 通过流程定义信息获取流程定义key
if (ObjectUtil.isNotEmpty(definitionList)) {
// 首次部署,取第一个定义信息即可
ProcessDefinition processDefinition = definitionList.get(0);
return processDefinition.getKey();
} else {
throw new ServiceException(StrUtil.format("流程已经部署,通过部署deploymentId[{}]获取流程定义信息为空!",
deploymentId));
}
}
/**
* 获取排他网关正确的下一节点信息
* @param currentActivity 当前节点信息
* @param currentVariablesMap 当前节点处参数信息
* @return
*/
public List<PvmActivity> getNextPositionByExclusiveGateway(PvmActivity currentActivity, Map<String, Object> currentVariablesMap) {
// 返回结果信息
List<PvmActivity> activityList = new ArrayList<>();
// 获取当前节点对外连接信息,并且计算最终选择哪条路线
List<PvmTransition> transitionList = currentActivity.getOutgoingTransitions();
for (PvmTransition transition : transitionList) {
// 获取当前任务判定条件,注意此处不是节点,为对外条件flowSequence
Object condition = transition.getProperty(CamundaConst.CONDITION_TEXT);
// 节点条件判定是否满足
if (ObjectUtil.isNotNull(condition) && camundaUtil.camundaEvalExpress(condition, currentVariablesMap)) {
// 此处为对外指向flowSequence指向满足条件的节点
activityList.add(transition.getDestination());
}
}
return activityList;
}
/**
* 获取并行网关正确的下一节点信息
* @param currentActivity 当前节点信息
* @return
*/
public List<PvmActivity> getNextPositionByParallelGateway(PvmActivity currentActivity) {
// 返回结果信息
List<PvmActivity> activityList = new ArrayList<>();
// 获取当前并行网关节点对外连接信息 transitionList 为并行网关对外的 -> 连线
List<PvmTransition> transitionList = currentActivity.getOutgoingTransitions();
for (PvmTransition transition : transitionList) {
// 获取当前任务判定条件,注意此处不是节点,为对外条件 flowSequence,获取destination则为 -> 对应后面的节点
PvmActivity destinationActivity = transition.getDestination();
String activityNodeType = StrUtil.toString(destinationActivity.getProperty(CamundaConst.CAMUNDA_NODE_TYPE));
// 如果目标节点为userTask节点,则直接加入执行节点
if (CamundaConst.USER_TASK.equals(activityNodeType)) {
activityList.add(transition.getDestination());
}
}
return activityList;
}
}