項目地址:activiti-workflow,歡迎star。
在流程審批中,在某一個節點需要抄送某人,被抄送人看查看流程,不需要審批。這裏是通過對activit擴展,自定義BPMN標籤,追加了抄送屬性。
對普通用戶節點設置抄送屬性,繼承UserTask
/**
* @description: 自定義用戶節點
* @author lhj
* @param
* @return
* @date 2020-6-11 10:50
*/
public class CustomUserTask extends UserTask {
//抄送用戶
protected List<String> candidateNotifyUsers = new ArrayList();
public List<String> getCandidateNotifyUsers() {
return candidateNotifyUsers;
}
public void setCandidateNotifyUsers(List<String> candidateNotifyUsers) {
this.candidateNotifyUsers = candidateNotifyUsers;
}
public CustomUserTask clone() {
CustomUserTask clone = new CustomUserTask();
clone.setValues(this);
return clone;
}
public void setValues(CustomUserTask otherElement) {
super.setValues(otherElement);
this.setCandidateNotifyUsers(otherElement.getCandidateNotifyUsers());
}
}
解析BPMN的xml和json是設置該屬性
if (StringUtils.isNotEmpty(xtr.getAttributeValue(ACTIVITI_EXTENSIONS_NAMESPACE, ATTRIBUTE_TASK_USER_CANDIDATE_NOTIFY_USERS))) {
String expression = xtr.getAttributeValue(ACTIVITI_EXTENSIONS_NAMESPACE, ATTRIBUTE_TASK_USER_CANDIDATE_NOTIFY_USERS);
userTask.getCandidateNotifyUsers().addAll(parseDelimitedList(expression));
}
task.setCandidateNotifyUsers(getValueAsList(CANDIDATE_NOTIFY_USERS, assignmentDefNode));
bpmn文件格式
<userTask id="sid-254390AD-30E7-4390-8B97-E2A395C4A15C" name="主管審批" activiti:assignee="lisi" activiti:candidateNotifyUsers="wangwu,zhangsan">
<extensionElements>
<modeler:initiator-can-complete xmlns:modeler="http://activiti.com/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
</extensionElements>
</userTask>
在流程流轉過程中將抄送人落地,存入數據庫,處理邏輯主要在UserTaskActivityBehavior,通過繼承實現
//保存抄送人
if (candidateNotifyUsers != null && !candidateNotifyUsers.isEmpty()) {
for (String notify : candidateNotifyUsers) {
Expression userIdExpr = expressionManager.createExpression(notify);
Object value = userIdExpr.getValue(execution);
if (value instanceof String) {
List<String> userIds = extractCandidates((String) value);
for (String userId : userIds) {
Context.getCommandContext().getIdentityLinkEntityManager().addUserIdentityLink(task, userId, ProcessConstants.NOTIFY);
}
} else if (value instanceof Collection) {
Iterator userIdSet = ((Collection) value).iterator();
while (userIdSet.hasNext()) {
Context.getCommandContext().getIdentityLinkEntityManager().addUserIdentityLink(task, (String)userIdSet.next(), ProcessConstants.NOTIFY);
}
throw new ActivitiException("Expression did not resolve to a string or collection of strings");
}
}
}
到此,抄送定義和數據保存都已實現,剩下就是如何查詢數據,這就要看具體業務需要是怎麼樣的。這裏做簡單實現,根據待辦一起查詢抄送。通過activiti提供的擴展Mybatis實現。
/**
* 查詢待審批任務
* @param taskUnFinishQuery 查詢條件
* @return
*/
@Override
public PageBean<ProcessTaskResult> queryUnFinishTask(TaskUnFinishQuery taskUnFinishQuery){
PageUtil<ProcessTaskResult, TaskUnFinishQuery> pageUtil = new PageUtil<>();
Long count = managementService.executeCustomSql(new AbstractCustomSqlExecution<CustomActivitiDatabaseMapper, Long>(CustomActivitiDatabaseMapper.class) {
@Override
public Long execute(CustomActivitiDatabaseMapper customActivitiDatabaseMapper) {
return customActivitiDatabaseMapper.selectUnFinishTaskCount(taskUnFinishQuery);
}
});
//沒有查詢到,就直接返回空
if(count <= 0){
return pageUtil.buildPage(Collections.emptyList(), taskUnFinishQuery, 0);
}
List<ProcessTaskResult> list = managementService.executeCustomSql(new AbstractCustomSqlExecution<CustomActivitiDatabaseMapper, List<ProcessTaskResult>>(CustomActivitiDatabaseMapper.class) {
@Override
public List<ProcessTaskResult> execute(CustomActivitiDatabaseMapper customActivitiDatabaseMapper) {
return customActivitiDatabaseMapper.selectUnFinishTask(taskUnFinishQuery);
}
});
return pageUtil.buildPage(list,taskUnFinishQuery,count);
}
還有額外處理,抄送可能是針對整個流程,但並不是某個節點。因此在存抄送人時,不但存taskId,還保存了processInstanceId實例ID
@Override
public IdentityLinkEntity addIdentityLink(TaskEntity taskEntity, String userId, String groupId, String type) {
IdentityLinkEntity identityLinkEntity = (IdentityLinkEntity)this.identityLinkDataManager.create();
taskEntity.getIdentityLinks().add(identityLinkEntity);
identityLinkEntity.setTask(taskEntity);
identityLinkEntity.setUserId(userId);
identityLinkEntity.setGroupId(groupId);
if (ProcessConstants.NOTIFY.equals(type)) {
identityLinkEntity.setProcessInstanceId(taskEntity.getProcessInstanceId());
}
identityLinkEntity.setType(type);
this.insert(identityLinkEntity);
if (userId != null && taskEntity.getProcessInstanceId() != null) {
this.involveUser(taskEntity.getProcessInstance(), userId, "participant");
}
return identityLinkEntity;
}
這裏給出一種實現思路,只供參考。具體代碼可到github項目中查看。
關於擴展BPMN遇到的問題,參考