用户任务
单一用户任务
你可以通过属性面板的 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。 |
打开的表单如下: