思路为:
流程点上添加手工分配标志,那么在流程流转的任意节点都可获取可以手工分配执行人的节点,即可设置相应的执行人。设置完成后可以保存该手工分配的任务;
不过该任务需新建一张表来存储手工分配的任务;
第一步,新建存储手工分配的任务的表
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;
/**
* 用于分配执行人时记录可以更换执行人的任务节点.
*/
@Entity
@Table(name="ACTC_MANUALASSIGNTASK")
public class ManualAssignTask implements Serializable{
private static final long serialVersionUID = 1L;
@Id
private String id;
/**
* 业务主键
*/
private String businessKey;
private String processInstanceId;
/**
* 流程点Id
*/
private String processPointId;
/**
* 流程点名称
*/
private String processPointName;
/**
* 该流程点的执行人
*/
private String operator;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getBusinessKey() {
return businessKey;
}
public void setBusinessKey(String businessKey) {
this.businessKey = businessKey;
}
public String getProcessPointId() {
return processPointId;
}
public void setProcessPointId(String processPointId) {
this.processPointId = processPointId;
}
public String getProcessPointName() {
return processPointName;
}
public void setProcessPointName(String processPointName) {
this.processPointName = processPointName;
}
public String getOperator() {
return operator;
}
public void setOperator(String operator) {
this.operator = operator;
}
public String getProcessInstanceId() {
return processInstanceId;
}
public void setProcessInstanceId(String processInstanceId) {
this.processInstanceId = processInstanceId;
}
}
第二步,在流程点类中添加手工分配标志,同时在部署流程时,对用户任务写入与其他不同的取用户的表达式
对标记为手工分配节点的任务设置不同的取执行人表达式
private void addUserTask(BpmnModel bpmnModel,Process process,ProcessPoint point){
UserTask userTask=new UserTask();
userTask.setId(point.getId());
userTask.setName(point.getName());
userTask.setIncomingFlows(new ArrayList<>());
userTask.setOutgoingFlows(new ArrayList<>());
userTask.setDocumentation("${businessKey}");
if(point.getProcessPointType().equals(ProcessPointType.USER_TASK)){
if(point.isManualAssign()){
userTask.setAssignee(buildManualAssigneeExpression(point));
}
// else {
// userTask.setAssignee(buildAssigneeExpression(point));
// }
if(point.getCandidateUsers() != null && !"".equals(point.getCandidateUsers())){
userTask.setCandidateUsers(Collections.singletonList(buildCandidatesUsersExpression(point)));
}
if(point.getCandidateGroups() != null && !"".equals(point.getCandidateGroups())){
userTask.setCandidateGroups(Collections.singletonList(buildCandidatesGroupsExpression(point)));
}
}
if(point.getProcessPointType().equals(ProcessPointType.SIGN_TASK)){
MultiInstanceLoopCharacteristics miInfo= new MultiInstanceLoopCharacteristics();
miInfo.setSequential(false);
miInfo.setInputDataItem("${activitiCallBackService.getMultiInstanceTaskAssignment(execution"+
",'"+point.getId()+"'"+
",'"+ConvertUtil.null2EmptyStr(point.getCandidateUsers()).trim()+"'"+
",'"+ConvertUtil.null2EmptyStr(point.getCandidateGroups()).trim()+"'"+
")}"
);
miInfo.setElementVariable("assign");
userTask.setLoopCharacteristics(miInfo);
userTask.setAssignee("${assign}");
}
if(point.getListeners()!=null&&!"".equals(point.getListeners())){
Stream.of(point.getListeners().split(",")).forEach(handler->{
TaskEventEnum taskEvent=providerManager.getTaskEventByHandler(handler);
ActivitiListener activitiListener=new ActivitiListener();
activitiListener.setEvent(taskEvent.name().toLowerCase());
activitiListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_EXPRESSION);
activitiListener.setImplementation(this.buildListenerExpression(point,handler));
userTask.getTaskListeners().add(activitiListener);
});
}
process.addFlowElement(userTask);
GraphicInfo graphicInfo = new GraphicInfo();
graphicInfo.setElement(userTask);
graphicInfo.setX(point.getLeftPosition());
graphicInfo.setY(point.getTopPosition());
graphicInfo.setHeight(point.getHeight());
graphicInfo.setWidth(point.getWidth());
bpmnModel.addGraphicInfo(userTask.getId(),graphicInfo);
if(point.getProcessPointType().equals(ProcessPointType.SIGN_TASK)) {
ExclusiveGateway gateway = new ExclusiveGateway();
gateway.setId(GATEWAY_ID_PREFIX+userTask.getId());
process.addFlowElement(gateway);
graphicInfo = new GraphicInfo();
graphicInfo.setElement(gateway);
graphicInfo.setX(point.getLeftPosition());
graphicInfo.setY(point.getTopPosition());
graphicInfo.setHeight(point.getHeight());
graphicInfo.setWidth(point.getWidth());
bpmnModel.addGraphicInfo(gateway.getId(),graphicInfo);
}
}
private String buildManualAssigneeExpression(ProcessPoint point){
return "${activitiCallBackService.getManualAssignAssignee(execution)}";
}
第三步,流程流转时,获取可手工分配流程点,并保存手工分配任务
public List<String> getOutgoingFlowsByTask(TaskRepresentation taskRepresentation) {
Task task1 = taskService.createTaskQuery().taskId(taskRepresentation.getId()).singleResult();
if(task1!=null) {
List<String> outGoings = getOutgoingFlows(task1);
List<String> conditions=new ArrayList<>();
//去ProviderName以及去重
for(String oneCondition:outGoings){
int firstDotPosition=oneCondition.indexOf(".");
if(firstDotPosition>0){
String providerName=oneCondition.substring(0,firstDotPosition);
String trueCondition=oneCondition.substring(firstDotPosition+1);
ConditionProvider conditionProvider=providerManager.getConditionProviderByName(providerName);
if(conditionProvider!=null)
conditions.add(trueCondition);
else
conditions.add(oneCondition);
}
else
conditions.add(oneCondition);
}
return conditions.stream().distinct().collect(Collectors.toList());
}
else
return null;
}
/**
* 获取当前任务的所有分支条件集合
* 例如:["审核.通过"},{"审核.不通过"}]
* @param task
* @return
*/
public List<String> getOutgoingFlows(Task task) {
try {
String processDefinitionId = task.getProcessDefinitionId();
BpmnModel bpmnModel = processEngine.getRepositoryService().getBpmnModel(processDefinitionId);
Execution execution = processEngine.getRuntimeService().createExecutionQuery().executionId(task.getExecutionId()).singleResult();
String activityId = execution.getActivityId();
execution.getProcessInstanceId();
FlowNode flowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(activityId);
List<SequenceFlow> sequenceFlows = flowNode.getOutgoingFlows();
return returnOutgoingString(sequenceFlows,bpmnModel);
}catch (Exception e){
log.error("activitiService getOutgoingFlows error:"+e);
return null;
}
}
public List<String> returnOutgoingString(List<SequenceFlow> sequenceFlows, BpmnModel bpmnModel){
List<String> result = new ArrayList<>();
for (SequenceFlow sequenceFlow : sequenceFlows) {
if(sequenceFlow.getTargetFlowElement() instanceof ExclusiveGateway){
FlowElement flowElement = sequenceFlow.getTargetFlowElement();
FlowNode flowNode1 = (FlowNode) bpmnModel.getMainProcess().getFlowElement(flowElement.getId());
List<String> subOutgoingMaps = returnOutgoingString(flowNode1.getOutgoingFlows(),bpmnModel);
if(subOutgoingMaps.size()>0 && subOutgoingMaps!=null) {
result.addAll(subOutgoingMaps);
}
} else {
Matcher m = pattern.matcher(sequenceFlow.getConditionExpression().trim());
Matcher m1 = mutiInstanceFlowPattern.matcher(sequenceFlow.getConditionExpression().trim());
String condition = null;
if(m.find() && m.group(1) != null && !"".equals(m.group(1))){
condition = m.group(1);
} else if(m1.find() && m1.group(1) != null && !"".equals(m1.group(1))){
condition = m1.group(1);
}
if(condition != null){
//返回给前端流转时选择的内容不带ProviderName
if(condition.indexOf("|")>0)
condition=condition.split("\\|")[1];
if(!result.contains(condition)){
result.add(condition);
}
}
}
}
return result;
}
第四步,当流程流转时,分析用户任务上的表达式,得到该任务的执行人
/**
* 获得手工分配执行人
* @param execution
* @return
*/
public String getManualAssignAssignee(DelegateExecution execution){
String businessKey = execution.getProcessInstanceBusinessKey();
String processInstanceId = execution.getProcessInstanceId();
String processPointId = execution.getCurrentFlowElement().getId();
Object startObj = execution.getVariable("start");
if(startObj!=null){
if((boolean)startObj){
ManualAssignTask manualAssignTask = manualAssignTaskRepository.findByBusinessKeyAndProcessPointId(businessKey,processPointId);
manualAssignTask.setProcessInstanceId(processInstanceId);
manualAssignTaskRepository.save(manualAssignTask);
return manualAssignTask.getOperator();
}
}
if(businessKey!=null && processPointId!=null) {
return manualAssignTaskRepository.findByBusinessKeyAndProcessPointIdAndProcessInstanceId(businessKey, processPointId,processInstanceId).getOperator();
}
return null;
}
至此,手工分配任务完成。