用户任务

单一用户任务

你可以通过属性面板的 Assignee source(执行人来源) 下拉列表选项指定一个任务执行人:

single assignee

表达式

你需要编写一个表达式,用来提供执行人的 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 和方法。选中方法后,会展示一个用于输入方法参数值的面板。

provider

请注意 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 元素的 collectionelementVariable 字段。然后,elementVariable 的值会用来作为 userTask 元素的 assignee

如果在流程变量中有用户列表的话,BPM 建模器会帮助你填写所有这些属性。User Task 模型元素在属性面板中有 Multi instance(多实例) 区域。将多实例类型从 None 修改为 ParallelSequential 时,面板会展示新的字段。

我们假设,在启动流程表单中,approvers 字段定义为 Entity list(实体列表) 类型,且实体类实现了 UserDetails 接口,例如 User。该字段会包含用户集合。对于当前用户任务,你可以选择 Process variable 集合源,并在 Process variable 下拉框选择 approvers 字段。

multi instance

此时,系统会建议自动填写 collectionelementVariableassignee 字段。

collection

任务候选用户和组

对于一个用户任务,可以指定一组候选的执行人,参阅 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 属性中。

用户任务输出

当用户要完成一个任务时,经常是需要做一个决定,例如,批准还是驳回这个任务。然后,流程会以一种或者另一种方式继续。你可以使用任务输出对这种情况建模。

对于 Jmix 界面 表单,输出定义在界面控制器中。对于 输入对话框 表单,输出定义在属性面板的 Outcomes(输出) 区域。

panel outcomes

当用户要完成任务时,输出会作为按钮在表单展示。

complete task

当用户点击一个输出按钮,任务会完成,用户的决定会写入一个特殊的流程变量,该变量的名称按照这种格式命名:<user-task-id>_result。变量值包含用户完成的任务以及他们选择的输出信息。

在为任务设置输出之后,你还需要在互斥网关元素之后指定序列流的条件。可以编写一个条件表达式,或者直接从下拉列表选择输出。

我们看看配置序列流的示例。Approve 是一个多实例任务。

multi instance task

如需指定 approved 序列流的条件,在画布选中它,然后配置其属性:

flow conditions
  1. Condition source(条件来源) 更改为 User task outcome(用户任务输出) 并在下拉列表中选择该任务及其输出。另外,也可以选择 Expression 条件源。

  2. 由于用户任务是多实例的,还需要指定一个额外的参数 - Condition type(条件类型)。在我们的例子中,只要所有同等的审批人都使用 approve 输出完成这个任务,流程会使用这个序列流继续执行。

附加属性面板

建模器还为用户任务提供一个 Extension properties(附加属性) 面板。服务任务脚本任务 元素也带有此面板。

priority panel

这里可以定义值类型为 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 对象获取 processDefinitionIdelementId
2 获取属性值。
3 将值写入 TextField

打开的表单如下:

priority form