会签实现须在 userTask 节点下的 multi instance 中配置 collection 及 completion condition;
${taskExecutionServiceImpl.findProcessUsers(‘applicant’)} : spring 代理下的 activiti 项目可使用
bean 下配置方法。
${countersignComponent.isComplete(taskId)} 会签实现方法,省略监听类。括号中的字符加单引号就是传递字符串,不加引号就是取当前任务中的变量。
@Component
@RequiredArgsConstructor
public class CountersignComponent {
private final TaskService taskService;
public boolean isComplete(String taskId) {
// 1、参数验证
if(StringUtils.isAnyEmpty(taskId)){
return false;
}
// 2、获取当前任务节点参数及会签判断后重新设置
// 获取流程参数 var,会签人员完成自己的审批任务时会添加流程参数 var,2 为拒绝,1 为同意
String variable = BeanUtil.nullOrUndefinedToEmptyStr(taskService.getVariableLocal(taskId, ActivitiCommonConstant.VAR.getValue()));
// 当值为 2 证明已有人拒绝,返回 true
if(DefaultConstant.TWO_CODE.getKey().equals(variable)){
//会签结束,设置参数 execType 为 4 进行下一步操作。
taskService.setVariableLocal(taskId, ActivitiCommonConstant.EXEC_TYPE.getValue(), DefaultConstant.FIVE_CODE.getKey());
return true;
}
// 当值为 1,判断会签是否结束
Integer complete = (Integer) taskService.getVariable(taskId, ActivitiCommonConstant.NR_OF_COMPLETED_INSTANCES.getValue());
if(complete == 0){
// 会签未结束,后续处理
}
return false;
}
}
@Override
public List findProcessUsers(String code) {
// 1、参数验证
if(StringUtils.isEmpty(code)){
throw new BusinessException(ActivitiConstant.PROCESS_USER_NULL);
}
// 2、查询对应流程人员(具体取人逻辑,根据个人业务变更)
ProcessParameterQuery processParameterQuery = new ProcessParameterQuery();
processParameterQuery.setCode(code);
GostopResponseVo processParameter = dev.findProcessParameter(processParameterQuery);
ProcessParameterVo processParameterVo = processParameter.getResult();
if(Objects.isNull(processParameterVo)){
throw new BusinessException(ActivitiConstant.PROCESS_USER_NULL);
}
List userInfos = processParameterVo.getUserInfos();
if(CollectionUtils.isEmpty(userInfos)){
throw new BusinessException(ActivitiConstant.PROCESS_USER_NULL);
}
return userInfos.stream().map(HospitalUserVo::getId).distinct().collect(Collectors.toList());
}
@Override
public String startProcess(CommonTaskParamVo param) {
// 1、参数验证
if(Objects.isNull(param) || StringUtils.isAnyEmpty(param.getProcessKey())){
throw new BusinessException(ActivitiConstant.EXEC_ERROR_PARAMS_NULL);
}
// 2、启动流程定义,返回流程实例
ProcessInstance pi;
try {
CustomParamVo customParamVo = param.getCustomParamVo();
String paramJson = JSONObject.toJSONString(customParamVo);
Map paramMap = JSONObject.parseObject(paramJson, Map.class);
pi = runtimeService
.startProcessInstanceByKey(param.getProcessKey(), paramMap);
} catch (Exception e) {
log.error(e.getMessage());
throw new BusinessException(ActivitiConstant.PROCESS_NOT_DEPLOYED);
}
return pi.getId();
}
@Override
public String complete(CommonTaskParamVo param) {
// 1、参数验证
if(Objects.isNull(param) || StringUtils.isAnyEmpty(param.getProcessId(), param.getUserId())){
throw new BusinessException(ActivitiConstant.EXEC_ERROR_PARAMS_NULL);
}
// 2、查询当前人任务信息
String userId = param.getUserId();
//与正在执行的任务管理相关的Service
Task task = taskService
.createTaskQuery()
//指定个人任务查询,指定办理人
.taskCandidateUser(userId)
//使用流程实例ID查询
.processInstanceId(param.getProcessId())
//排序
.orderByTaskCreateTime().asc()
//返回列表
.singleResult();
if (Objects.isNull(task)) {
throw new BusinessException(ActivitiConstant.TASK_NULL_ERROR);
}
task.setDescription(param.getDescription());
task.setAssignee(userId);
taskService.saveTask(task);
// 2.1 设置执行人信息
HospitalUserCacheVo userInfo = activitComponent.getUserInfo();
CustomParamVo customParamVo = param.getCustomParamVo();
customParamVo.setExecUserId(userInfo.getId());
customParamVo.setExecUserName(userInfo.getDepartmentName());
customParamVo.setExecTime(DateUtil.date2String(LocalDateTime.now()));
customParamVo.setTaskId(task.getId());
// 2.2 将自定义参数转为 map
String paramJson = JSONObject.toJSONString(customParamVo);
Map paramMap = JSONObject.parseObject(paramJson, Map.class);
taskService.setVariablesLocal(task.getId(), paramMap);
// 3、执行当前节点信息
taskService.complete(task.getId());
return task.getId();
}
@Data
public class CommonTaskParamVo {
/**
* 用户 ID
*/
private String userId;
/***
* 流程图定义 KEY
*/
private String processKey;
/**
* 流程 ID
*/
private String processId;
/**
* 描述
*/
private String description;
/**
* 自定义参数类
*/
private CustomParamVo customParamVo;
}
@Data
public class CustomParamVo {
/**
* 操作类型 (1 同意, 2 回退, 3 驳回, 4 提交 5 删除)
*/
private String execType;
/**
* 节点类型 (1 申请节点 2 审批节点)
*/
private String nodeType;
/**
* 预留参数
*/
private String var;
/**
* 执行人 ID
*/
private String execUserId;
/**
* 执行人名称
*/
private String execUserName;
/**
* 执行时间
*/
private String execTime;
/**
* 任务 ID
*/
private String taskId;
}
使用上述参数类及流程配置后,查询任务流水就变得非常简单。
@Override
public List flowQueryProcess(FlowQuery param) {
// 1、参数验证
if(Objects.isNull(param) || StringUtils.isAnyEmpty(param.getProcessId())){
return new ArrayList<>();
}
// 2、查询任务执行节点信息
HistoricTaskInstanceQuery historicTaskInstanceQuery = historyService.createHistoricTaskInstanceQuery();
List taskInfoArr = historicTaskInstanceQuery.processInstanceId(param.getProcessId()).orderByTaskCreateTime().asc().list();
if(CollectionUtils.isEmpty(taskInfoArr)){
return new ArrayList<>();
}
// 3、查询任务执行参数信息
HistoricVariableInstanceQuery historicVariableInstanceQuery = historyService.createHistoricVariableInstanceQuery();
List variableInstanceList = historicVariableInstanceQuery.processInstanceId(param.getProcessId()).list();
// 4、构建返回信息对象
List resultArr = taskInfoArr.stream().map(taskInfo -> {
FlowDataVo flowDataVo = new FlowDataVo();
flowDataVo.setNodeName(taskInfo.getName());
flowDataVo.setDescription(taskInfo.getDescription());
List variableArr = variableInstanceList.stream().filter(e -> taskInfo.getId().equals(e.getTaskId())).collect(Collectors.toList());
if (CollectionUtils.isEmpty(variableArr)) {
flowDataVo.setStatus(DefaultConstant.ONE_CODE.getKey());
return flowDataVo;
}
JSONObject flowDataJson = (JSONObject) JSONObject.toJSON(flowDataVo);
variableArr.stream().forEach(var -> {
String variableName = var.getVariableName();
String value = BeanUtil.nullOrUndefinedToEmptyStr(var.getValue());
flowDataJson.put(variableName, value);
});
String flowDataJsonString = flowDataJson.toJSONString();
FlowDataVo afterFlowData = JSONObject.parseObject(flowDataJsonString, FlowDataVo.class);
afterFlowData.setStatus(DefaultConstant.TWO_CODE.getKey());
return afterFlowData;
}).collect(Collectors.toList());
return resultArr;
}
@Data
public class FlowQuery {
/**
* 流程 ID
*/
private String processId;
/**
* 用户 ID
*/
private String userId;
}
@Data
public class FlowDataVo {
/**
* 操作类型 (1 同意, 2 回退, 3 驳回, 4 提交 5 删除)
*/
private String execType;
/**
* 节点类型 (1 申请节点 2 审批节点)
*/
private String nodeType;
/**
* 预留参数
*/
private String var;
/**
* 节点名称
*/
private String nodeName;
/**
* 执行状态 1 未执行 2 已执行
*/
private String status;
/**
* 执行人 ID
*/
private String execUserId;
/**
* 执行人名称
*/
private String execUserName;
/**
* 执行时间
*/
private String execTime;
/***
* 描述
*/
private String description;
}