用户任务
单一用户任务
你可以通过属性面板的 Assignee source(执行人来源) 下拉列表选项指定一个任务执行人:
表达式
你需要编写一个表达式,用来提供执行人的 username
。例如,如果 User
实体保存在名为 manager
的流程变量中,则表达式为:${manager.username}
。此时,如果想要将任务分配给特定用户,可以直接输入用户名。
还有,你也可以调用 Spring bean 的方法返回 username:${smpl_MyBean.evaluateManager(methodParam1, 'methodParam2')}
。
流程变量
如果你选择 Process variable(流程变量)
执行人来源,属性面板会展示 ComboBox
组件。该组件显示 Entity
类型的字段和流程变量,这些实体类需要实现 UserDetails
接口。
为流程建模时,也可用内置的 initiator
流程变量分配任务。它包含启动流程的用户实体。
可以用下面的应用程序属性禁用 initiator
流程变量:
jmix.bpm.process-initiator-variable-enabled=false
还有,通过下面的配置可以修改 initiator
的名称:
jmix.bpm.process-initiator-variable-name=manager
当流程启动时,如果没有用到启动流程表单,流程变量可以通过 API 传递。此时,如果你需要将任务分配给某个用户,而用户从流程变量中获取,你可以为执行人编写一个显式的表达式,或者将流程变量的信息添加至 Process variables 区域。
用户提供者
如果需要在运行时确定执行人,可以使用用户提供者(user provider)。用户提供者是 Spring bean,需要使用 @UserProvider
注解。该注解有两个属性:
-
value
- 展示在建模器中的名称。 -
description
- 描述方法的作用,可选。
用户提供者需要至少实现一个返回 String
的方法。该方法获取从建模器指定的参数值,并返回用户的 username,改用户将作为任务的执行人。这个用户提供者的例子中,读取带有用户 email 信息的流程变量,在数据库找到该用户,并返回其 username。
@UserProvider(value = "smpl_MyUserProvider", description = "Returns a user with the specified email")
public class MyUserProvider {
@Autowired
private DataManager dataManager;
public String getUserByEmail(String parameter) {
return dataManager.load(User.class)
.query("select u from smpl_User u where u.email = :email")
.parameter("email", parameter)
.one()
.getUsername();
}
}
在建模器中,你可以从下拉列表中选择创建的 bean 和方法。选中方法后,会展示一个用于输入方法参数值的面板。
请注意 is var(是否变量) 复选框,主要是对字符串参数起作用。如果没有勾选,参数值会带有单引号写入结果表达式。如果勾选,则没有单引号,而是传给方法一个你提供的名称的变量。
多实例任务
一个用户任务可以分配给多个用户。例如,一个任务需要多个人审批。审批者可以同时审批,或者一个接一个审批。参阅 Flowable 文档 了解基本信息。
我们看看流程模型 XML 中的 userTask
元素:
<userTask id="myTask" name="My Task" flowable:assignee="${assignee}">
<multiInstanceLoopCharacteristics isSequential="true"
flowable:collection="${collectionVariable}" flowable:elementVariable="assignee" >
</multiInstanceLoopCharacteristics>
</userTask>
当为流程建模时,你需要填写 multiInstanceLoopCharacteristics
元素的 collection
和 elementVariable
字段。然后,elementVariable
的值会用来作为 userTask
元素的 assignee
。
如果在流程变量中有用户列表的话,BPM 建模器会帮助你填写所有这些属性。User Task
模型元素在属性面板中有 Multi instance(多实例) 区域。将多实例类型从 None
修改为 Parallel
或 Sequential
时,面板会展示新的字段。
我们假设,在启动流程表单中,approvers
字段定义为 Entity list(实体列表)
类型,且实体类实现了 UserDetails
接口,例如 User
。该字段会包含用户集合。对于当前用户任务,你可以选择 Process variable
集合源,并在 Process variable
下拉框选择 approvers
字段。
此时,系统会建议自动填写 collection
、elementVariable
和 assignee
字段。
任务候选用户和组
对于一个用户任务,可以指定一组候选的执行人,参阅 Flowable 文档 了解基本信息。每个候选执行人可以在 My tasks(我的任务) 界面中的 Group tasks(组任务) 列表中看到这些任务。任何一个候选执行人领取了任务之后,任务就会移到领取人的 Assigned tasks(已分配的任务) 列表中,其他候选执行人的 Group tasks 将不再显示。
通过用户任务属性面板的 Candidate groups(候选组) 或 Candidate users(候选用户) 字段可以定义候选人。
在 Candidate groups edit(候选组编辑器) 对话框中,可以定义 Group source(组来源):
-
User groups(用户组)。可以在列表中选择一个或多个用户组。参阅 用户组 章节了解更多信息。
-
User groups provider(用户组提供者)。如果用户组需要靠代码确定,可以使用这个类型。需要选择带有
@UserGroupListProvider
注解的 Spring bean。 该注解有两个属性:-
value
- 展示在建模器中的名称。 -
description
- 描述方法的作用,可选。
Bean 需要至少实现一个返回
List<String>
类型的方法。该方法获取从建模器指定的参数值,并返回用户组编码的列表。 -
-
Expression(表达式)。可以为流程引擎提供一个表达式。表达式需要返回用户组编码的列表。它会被写入
userTask
元素的flowable:candidateGroups
属性中。
在 Candidate users edit(候选用户编辑器) 对话框,可以定义下列 User source(用户来源):
-
Users(用户)。可以在列表中选择一个或多个用户。
-
Users provider(用户提供者)。如果用户组要靠代码确定,可以使用这个类型。需要选择带有
@UserListProvider
注解的 Spring bean。 该注解有两个属性:-
value
- 展示在建模器中的名称。 -
description
- 描述方法的作用,可选。
Bean 需要至少实现一个返回
List<String>
类型的方法。该方法获取从建模器指定的参数值,并返回 username 列表。 -
-
Expression。可以为流程引擎提供一个表达式。表达式需要返回 username 列表。它会被写入
userTask
元素的flowable:candidateUsers
属性中。
用户任务输出
当用户要完成一个任务时,经常是需要做一个决定,例如,批准还是驳回这个任务。然后,流程会以一种或者另一种方式继续。你可以使用任务输出对这种情况建模。
当用户要完成任务时,输出会作为按钮在表单展示。
当用户点击一个输出按钮,任务会完成,用户的决定会写入一个特殊的流程变量,该变量的名称按照这种格式命名:<user-task-id>_result
。变量值包含用户完成的任务以及他们选择的输出信息。
在为任务设置输出之后,你还需要在互斥网关元素之后指定序列流的条件。可以编写一个条件表达式,或者直接从下拉列表选择输出。
我们看看配置序列流的示例。Approve
是一个多实例任务。
如需指定 approved
序列流的条件,在画布选中它,然后配置其属性:
-
将 Condition source(条件来源) 更改为 User task outcome(用户任务输出) 并在下拉列表中选择该任务及其输出。另外,也可以选择 Expression 条件源。
-
由于用户任务是多实例的,还需要指定一个额外的参数 - Condition type(条件类型)。在我们的例子中,只要所有同等的审批人都使用
approve
输出完成这个任务,流程会使用这个序列流继续执行。
附加属性面板
这里可以定义值类型为 String
的属性,然后在界面控制器和服务中通过 getElementExtensionProperties
方法获取并使用。
下面示例中,我们展示在流程表单用户任务的 Extension properties(附加属性) 面板中定义的 Priority
属性:
@Autowired
private ProcessFormContext processFormContext;
@Autowired
private BpmModelService bpmModelService;
@Autowired
private TextField<String> priority;
@Subscribe
public void onInit(InitEvent event) {
String processDefinitionId = processFormContext.getTask().getProcessDefinitionId(); (1)
String elementId = processFormContext.getTask().getTaskDefinitionKey();
String priorityValue = bpmModelService.getElementExtensionProperties(processDefinitionId, elementId)
.get(0)
.getValue(); (2)
priority.setValue(priorityValue); (3)
}
1 | 从 processFormContext 对象获取 processDefinitionId 和 elementId 。 |
2 | 获取属性值。 |
3 | 将值写入 TextField 。 |
打开的表单如下: