[关闭]
@ruoli 2016-09-07T10:06:27.000000Z 字数 8101 阅读 3451

Activiti选人页面的实现

Activiti


1、背景

Activiti默认是不带有选人的功能的,它默认的是在调用complete方法的时候自动根据下一个节点的 assignee属性设置下一节点的候选人,也可设置candidate属性或者角色,提交到下一步,流程引擎自动解析为公有任务,需要具体执行人去认领。
但是并不是所有的业务逻辑都符合Activit规定的标准情况,适用于这种操作,用户提交时需要从几个候选人中选择一个,然后发送到下一个环节,被选择的审批人,在下一环节拥有待办,目前Activiti工作流暂不支持原生支持,需要自己扩展。

2、扩展步骤

1、实现原理

1、目前Activiti人员解析逻辑

Activiti自带了23张表,其中有四张组织人员相关表:
1) act_id_group用户组信息表
2) act_id_info用户扩展信息表
3) act_id_membership用户与用户组对应信息表
4) act_id_user用户信息表
原生的Activiti人员解析,需要依赖Activiti内置的四张组织信息表,也提供了一些列的AIP让我们去操作这些表,插入和获取信息。
Activiti本身自带了简易的人员管理功能,角色配置,原生的做法是将人员和角色信息配置到工作流表中,工作流就可以自动解析环节处理时的角色,转换为为处理人,我们具体业务实现不用处理,但是这直接导致了三个问题:
第一:就是工作流自带的人员角色表过于简单,不一定能应对复杂的业务逻辑需求。
第二:需要维护两套人员角色信息,加重了程序设计的复杂性。
第三:不便于扩展,业务程序对工作流人员解析这块完全没有控制权,无法做到选人等业务需求。

2、如何使用自己的选人逻辑

首先我们无需管这四张表,也不 用往这些表中插入任何数据,这样就可以使Actriviti基于角色的选人失效,因为根据角色无法解析到人员。
实现我们自己的选人,同样依赖与流程图的属性配置,具体的逻辑是:
流程图配置好审批角色后,业务逻辑程序在提交下一步之前,提前获取到下一步的审批环节和审批角色,手工解析为多个人员,展示给用户,让其选择一个或多个,再以流程参数的形式设置到流程中,提交下一步,下一步审批环节识别到流程参数,绑定审批人员。

2、具体实现

1、编写流程定义工具类

用户获取流程定义相关信息,ActDefinitionService.java示例为:

  1. package modules.act.service;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import java.util.Set;
  5. import org.activiti.engine.RepositoryService;
  6. import org.activiti.engine.TaskService;
  7. import org.activiti.engine.delegate.Expression;
  8. import org.activiti.engine.impl.RepositoryServiceImpl;
  9. import org.activiti.engine.impl.bpmn.behavior.MultiInstanceActivityBehavior;
  10. import org.activiti.engine.impl.bpmn.behavior.NoneStartEventActivityBehavior;
  11. import org.activiti.engine.impl.bpmn.behavior.UserTaskActivityBehavior;
  12. import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
  13. import org.activiti.engine.impl.pvm.PvmActivity;
  14. import org.activiti.engine.impl.pvm.PvmTransition;
  15. import org.activiti.engine.impl.pvm.delegate.ActivityBehavior;
  16. import org.activiti.engine.impl.pvm.process.ActivityImpl;
  17. import org.activiti.engine.impl.task.TaskDefinition;
  18. import org.activiti.engine.repository.ProcessDefinition;
  19. import org.activiti.engine.task.Task;
  20. import org.springframework.beans.factory.annotation.Autowired;
  21. import org.springframework.stereotype.Service;
  22. import org.springframework.transaction.annotation.Transactional;
  23. import common.utils.StringUtils;
  24. import modules.act.entity.ActTransition;
  25. /**
  26. * 流程定义Service
  27. * @author Ruoli
  28. * 2016.08.23
  29. */
  30. @Service
  31. @Transactional(readOnly = true)
  32. public class ActDefinitionService {
  33. @Autowired
  34. private RepositoryService repositoryService;
  35. @Autowired
  36. private TaskService taskService;
  37. /**
  38. * 查询任务对应的下一步路由
  39. * @param taskId
  40. * @return
  41. */
  42. public List<ActTransition> getApprovalInfo(String taskId){
  43. List<ActTransition> approvalList=new ArrayList<ActTransition>();
  44. //获取当前环节对象
  45. ActivityImpl activityImpl=this.getActivity(taskId);
  46. List<PvmTransition> outTransitions = activityImpl
  47. .getOutgoingTransitions();// 获取从某个节点出来的所有线路
  48. for (PvmTransition tr : outTransitions) {
  49. ActTransition transition=geTransition(tr);
  50. //transition.getTaskRoleList(); //获取角色 集合
  51. approvalList.add(transition);
  52. }
  53. return approvalList;
  54. }
  55. /**
  56. * 根据TaskId获取流程定义环节对象
  57. * @param taskId
  58. * @return
  59. */
  60. public ActivityImpl getActivity(String taskId){
  61. Task task =taskService.createTaskQuery().taskId(taskId).singleResult();
  62. if(task!=null){
  63. ProcessDefinitionEntity def = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
  64. .getDeployedProcessDefinition(task.getProcessDefinitionId());
  65. return def.findActivity(task.getTaskDefinitionKey());
  66. }
  67. return null;
  68. }
  69. /**
  70. * 根据路由Id获取路由对象
  71. * @param transitionId
  72. * @return ActTransition
  73. */
  74. public ActTransition geTransition(String processDefinitionId,String transitionId){
  75. if(StringUtils.isNotEmpty(processDefinitionId) && StringUtils.isNotEmpty(transitionId)){
  76. ProcessDefinitionEntity def = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
  77. .getDeployedProcessDefinition(processDefinitionId);
  78. List<ActivityImpl> activityList=def.getActivities();
  79. for(ActivityImpl activityImpl : activityList){
  80. List<PvmTransition> outTransitions=activityImpl.getOutgoingTransitions();
  81. for (PvmTransition pvmTransition : outTransitions) {
  82. if(transitionId.equals(pvmTransition.getId())){
  83. ActTransition actTransition=geTransition(pvmTransition);
  84. return actTransition;
  85. }
  86. }
  87. }
  88. }
  89. return null;
  90. }
  91. /**
  92. * 根据连线对象获取下一步处理信息
  93. * @param pvmTransition
  94. * @return ActTransition
  95. */
  96. private ActTransition geTransition(PvmTransition pvmTransition){
  97. PvmActivity nextActivity = pvmTransition.getDestination();
  98. ActTransition actTransition=new ActTransition();
  99. actTransition.setId(pvmTransition.getId());
  100. actTransition.setName(pvmTransition.getProperty("name")+"");
  101. actTransition.setDescription(pvmTransition.getProperty("documentation")+"");
  102. actTransition.setCondition(pvmTransition.getProperty("conditionText")+"");
  103. actTransition.setTaskName(nextActivity.getProperty("name")+"");
  104. //判断是否是UserTask
  105. ActivityImpl activity=(ActivityImpl)nextActivity;
  106. ActivityBehavior activityBehavior = activity.getActivityBehavior();
  107. if (activityBehavior instanceof UserTaskActivityBehavior || activityBehavior instanceof MultiInstanceActivityBehavior) {
  108. TaskDefinition taskDefinition=(TaskDefinition)nextActivity.getProperty("taskDefinition");
  109. if(taskDefinition!=null){
  110. Set<Expression> roleSet=taskDefinition.getCandidateGroupIdExpressions();
  111. //List 用户存放下一步审批角色
  112. List<String> roleList=new ArrayList<String>();
  113. for(Expression expression:roleSet){
  114. roleList.add(expression.getExpressionText());
  115. }
  116. actTransition.setTaskRoleList(roleList);
  117. }
  118. }
  119. return actTransition;
  120. }
  121. /**
  122. * 获取首环节处理角色
  123. * @return
  124. */
  125. public List<String> getFristNodeRole(String procDefKey){
  126. List<String> roleList=new ArrayList<String>();
  127. ProcessDefinition processDefinition=repositoryService.createProcessDefinitionQuery().processDefinitionKey(procDefKey)
  128. .orderByProcessDefinitionVersion().desc().list().get(0);
  129. ProcessDefinitionEntity def = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
  130. .getDeployedProcessDefinition(processDefinition.getId());
  131. List<ActivityImpl> activityList=def.getActivities();
  132. for(ActivityImpl activityImpl : activityList){
  133. ActivityBehavior activityBehavior = activityImpl.getActivityBehavior();
  134. if (activityBehavior instanceof NoneStartEventActivityBehavior) {
  135. PvmActivity fristTask=activityImpl.getOutgoingTransitions().get(0).getDestination();
  136. TaskDefinition taskDefinition=(TaskDefinition)fristTask.getProperty("taskDefinition");
  137. Set<Expression> roleSet=taskDefinition.getCandidateGroupIdExpressions();
  138. for(Expression expression:roleSet){
  139. roleList.add(expression.getExpressionText());
  140. }
  141. break;
  142. }
  143. }
  144. return roleList;
  145. }
  146. }

其中依赖实体类ActTransition.java 代码如下:

  1. package modules.act.entity;
  2. import java.util.List;
  3. /**
  4. * 下一步处理信息,此类主要用于人员或路由选择页面
  5. * @author Ruoli
  6. * 2016/08/23
  7. */
  8. public class ActTransition {
  9. private String id;//路由ID
  10. private String name;//路由名称
  11. private String description;//路由描述
  12. private String condition;//路由条件
  13. private String taskName;//下一步环节的名称
  14. private List<String> taskRoleList; //下一步审批角色集合
  15. //可根据业务需求新增更多字段
  16. public String getId() {
  17. return id;
  18. }
  19. public void setId(String id) {
  20. this.id = id;
  21. }
  22. public String getTaskName() {
  23. return taskName;
  24. }
  25. public void setTaskName(String taskName) {
  26. this.taskName = taskName;
  27. }
  28. public List<String> getTaskRoleList() {
  29. return taskRoleList;
  30. }
  31. public void setTaskRoleList(List<String> taskRoleList) {
  32. this.taskRoleList = taskRoleList;
  33. }
  34. public String getName() {
  35. return name;
  36. }
  37. public void setName(String name) {
  38. this.name = name;
  39. }
  40. public String getDescription() {
  41. return description;
  42. }
  43. public void setDescription(String description) {
  44. this.description = description;
  45. }
  46. public String getCondition() {
  47. return condition;
  48. }
  49. public void setCondition(String condition) {
  50. this.condition = condition;
  51. }
  52. }

2、编写选环节Controller方法

  1. /**
  2. * 获取流程审批信息,提供发送时 展示选环节列表
  3. * @param act
  4. * @return
  5. */
  6. @SuppressWarnings("unchecked")
  7. protected List<Map<String, Object>> getApprovalTrack(String taskId){
  8. if(StringUtils.isNotBlank(taskId)){
  9. //1:获取路由信息
  10. List<ActTransition> approvalList=actDefinitionService.getApprovalInfo(taskId); //actTaskService.getApprovalInfo(act.getTaskId());
  11. //2:迭代路由
  12. if(approvalList!=null){
  13. //构建树形Tree-List
  14. List<Map<String, Object>> resultList=new ArrayList<Map<String, Object>>();
  15. for (ActTransition transition : approvalList) {
  16. Map<String, Object> tempMap=new HashMap<String, Object>();
  17. tempMap.put("id",transition.getId());
  18. tempMap.put("name", transition.getTaskName());
  19. tempMap.put("pId",1);
  20. //此处还有验证路由条件的控制,暂时没有实现
  21. //此处可以自己行增加 路由对应的人员信息,可根据角色进行解析,此示例只需要进行选路由即可
  22. resultList.add(tempMap);
  23. }
  24. Map<String, Object> rootMap=new HashMap<String, Object>();
  25. rootMap.put("id","1");
  26. if(resultList.size()==0){
  27. rootMap.put("name","暂无处理环节");
  28. }else{
  29. rootMap.put("name","可被选择的处理环节");
  30. }
  31. rootMap.put("pId","0");
  32. rootMap.put("nocheck",true);//设置根节点不可选中
  33. resultList.add(rootMap);
  34. return resultList;
  35. }
  36. }
  37. return null;
  38. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注