用户任务
概览
用户任务(User task) 是分配给用户或用户组的一种任务类型,在业务流程中需要手动完成。 用户任务是业务流中不可或缺的内容,参与者可以通过执行特定操作、 做出决策或提供输入的方式和流程进行交互。
|
单一执行人和分组 在 BPMN 中,只有执行人才能执行其中的任务。 当我们说“任务分配给了某个用户组”, 其实是表示这里的一组 潜在的执行人,而不是说执行人是一个 UserGroup 对象。 分组的某个人通过 领取 任务而成为真正的执行人。 |
用户任务在图中显示为一个典型的任务(圆角矩形),左上角有一个小的用户图标。
用户任务在 XML 中的定义如下。
其中 id 属性必需,name 属性可选。
<userTask id="user-task-01" name="User task" />
属性
除了通用属性之外,用户任务还有下列特殊属性:
-
Due Date 提醒执行人任务的过期时间。
-
Assignee,可为任务分配单个执行者或可能的执行人(候选人);
-
Form,定义任务的用户界面;
-
Task Listeners,添加任务生命周期事件触发的监听器。
到期时间
用户任务中的 due date 参数指定任务必须完成的截止日期。 该参数对于管理业务流程中的时间敏感型活动至关重要。
| 设置截止日期不会启动任何自动操作。需要手动配置后续的操作。 |
设置到期时间
Due date 支持两种类型的设置:
-
固定日期:填写将来的一个到期时间。 (如果填写的是过去的时间,则该时间会被忽略,任务显示已过期)。
-
时长:从任务创建开始计算的一个时长。
事实上,到期时间的字段是一个文本框,流程引擎在运行时对其内容进行解析。 支持以下格式:
-
ISO8601 格式的文本字符串,表示固定日期或持续时间。
-
以下类型的流程变量:
-
java.lang.String— 必须包含 ISO8601 格式的值。 -
java.util.Date— 必须包含日期值。
-
-
在运行时可以解析为上述类型之一的表达式,例如
$/{someDateVariable/}。
|
ISO 8601 示例
-
固定时期时间:
-
2024-02-01T08:40:37
-
2050-01-01
-
-
时长:
-
PT20M - 20 分钟
-
PT5H - 5 小时
-
PT3D - 3 天
-
编程时处理到期时间
到期时间参数可以通过 Task 类的方法处理:
Task task = taskService.createTaskQuery()
.taskId("taskId").singleResult(); (1)
task.getDueDate(); (2)
task.setDueDate(null); (3)
taskService.saveTask(task); (4)
| 1 | — 通过 ID 获取任务 |
| 2 | — 获取到期时间 |
| 3 | — 设置新的到期时间为 null |
| 4 | — 保存任务对象。 |
因此,可以根据业务逻辑动态修改任务的到期时间。 例如,任务的执行人可以申请将任务延时处理。
使用工作日历
项目中如果安装了 工作日历 扩展组件, 在 Web BPM 建模器 的 General 部分会显示如下内容:
这里可以从下拉列表中选择一个已配置的工作日历。 此时,只能将截止日期设置为持续时长,并且将根据工作日历计算经过的时间。
例如,用户在下午 4:00 收到了任务。
在工作日历中,标准的工作时间设置为上午 10:00 至下午 6:00,
而截止日期参数设置为 3 小时 (PT3H)。
在考虑了工作日历后,截止日期不会设置为晚上的 7:00,而会设置为第二个工作日的早上 7:00。 使用了工作日历后,仅计算工作时间。
|
使用工作日历时,时长只能按小时和分钟设置,不能按天设置。 |
带截止时间的用户任务:
<userTask id="Activity_0gsy9yk" name="User task"
flowable:dueDate="PT3H" (1)
flowable:businessCalendarName="test-calendar"> (2)
. . .
</userTask>
| 1 | — 时长类型的截止时间 |
| 2 | — 工作日历属性 |
详情请参阅 工作日历 扩展组件。
分配用户
任务要有执行人才能最终完成。 一个任务只能有 一个 执行人,此用户称为 assignee。
assignee 属性可以为空,即,没有用户可以在任务列表中看到此任务。
当设置了潜在执行人或 candidates 的列表时,此类任务通常被视为 分组任务。
此外,还可以使用管理页面或以编程方式在运行时设置执行人。
执行人来源
在 Jmix BPM 中,执行人来源(assignee source)是指一种在流程中选择用户作为任务执行人的机制。 有三种选项:
| Expression |
- 表达式。必须返回字符串,包含 username。 |
| Process variable |
- 流程变量。指向一个 User 实体的流程变量。 |
| User provider |
- 一个特定的 Java 类,带有返回 username 的方法。 |
表达式
表达式是默认的执行人来源。
需要编写一个表达式来获取执行人的 username。
例如,User 实体存在名为 manager 的流程变量中,则表达式可以是 ${manager.username}:
<userTask id="user-task-01" name="User task"
flowable:assignee="${manager.username}"
jmix:assigneeSource="expression"
jmix:assigneeValue="${manager.username}" />
如果需要将一个任务直接分配给特定的用户,这里可以直接写该用户的 username:
另外,也可以调用 Spring bean 的方法返回 username:
${smpl_MyBean.evaluateManager(methodParam1, 'methodParam2')}
流程变量
如果选择 Process variable 执行人源,则属性面板中将显示一个 ComboBox。其中可以选择 Entity 类型的字段和流程变量,这些实体类还要求实现了 UserDetails 接口。
预置的 initiator 变量
预置的 initiator 流程变量可以在建模时用来分配任务。包含启动流程的用户实体:
下面是使用流程变量分配任务的示例:
<userTask id="user-task-01" name="User task"
camunda:assignee="${initiator.username}"
jmix:assigneeSource="processVariable"
jmix:assigneeValue="initiator" />
|
如果流程是通过 API 或消息/信号启动的,则 |
可以通过下面的应用程序属性禁用 initiator 变量:
jmix.bpm.process-initiator-variable-enabled=false
还可以修改发起人属性的名称:
jmix.bpm.process-initiator-variable-name=manager
User Provider
如果需要通过复杂的逻辑确定任务的执行人,则建议使用 User provider. 此时,系统会加载已有的 user provider Java 类以供选择:
User Provider 中需要包含一个或多个 String 返回类型的方法。
方法获取在建模器中指定的参数值,并返回可以作为任务执行人的用户名。
使用 User provider 的用户任务:
<userTask id="user-task" name="User task" jmix:assigneeSource="userProvider" jmix:assigneeValue="smpl_MyUserProvider">
<extensionElements>
<jmix:springBean beanName="smpl_MyUserProvider" methodName="getUser" />
</extensionElements>
</userTask>
User provider 类是一个普通的 Spring bean,带有 @UserProvider 注解。
下面是一个 user provider 的示例,其中的方法会根据用户 email 的流程变量从数据库加载用户。
@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();
}
}
在 UserProvider 类中可以实现任意的业务逻辑。
例如,可以从角色或部门中选择一个不太忙的用户;选择下一个轮到的用户;或者从候选人里选择一个随机用户等。
编程式分配任务
如需编程式设置任务的执行人,可以使用 TaskService 的 setAssignee 方法。示例:
Task task = taskService.createTaskQuery()
.taskId("taskId")
.singleResult(); (1)
taskService.setAssignee(task.getId(), "jane"); (2)
| 1 | 通过 Query API 获取任务 |
| 2 | 通过 username 指定执行人 |
获取特定用户以分配的任务,可以用 TaskService 的下列方法:
List<Task> tasks = taskService.createTaskQuery()
.taskAssignee("jane") (1)
.list();
| 1 | username |
候选用户和组
候选(Candidates) 表示可以领取/完成任务的用户和用户组(groups)。 当一个任务有多个候选人时,该任务会在所有候选人的任务列表展示。 第一个领取任务的候选人变成任务的执行人,并可以完成任务。 之后,其他候选人的任务列表中该任务不可见。
|
这里 “groups” 表示一组 User group 的编码。 |
领取组内任务
一种常见的情况是,我们不需要某个特定的用户去执行任务。 例如,对于一个经理来说,具体那个会计对他下达的命令做出决定并不重要。
在这种情况下,Jmix BPM 可以将任务分配给 候选人组 — 其中的任何成员都可以成为任务的执行人。 但该成员必须先领取任务。 领取任务是用户对任务所有权的一个操作。
有多个候选人的的任务会显示在每个候选人组任务(Group tasks)菜单的 我的任务(My tasks) 视图中。
在任何候选人领取任务后,该任务将移至此用户的 已分配任务(Assigned tasks) 列表中,并从其他候选人的 组任务 表中移除。
领取任务是,用户必须打开任务并执行以下操作之一:
-
领取并继续(Claim and resume) - 用户成为任务执行人,任务表单将以正常模式重新打开,该用户可以继续填写表单。
-
领取并关闭(Claim and close) - 用户成为任务执行人后关闭表单;该用户可以稍后在任务列表的 已分配任务 部分中找到该任务:
在建模器中设置候选人
点击下图所示的按钮可以编辑候选人组:
在打开的 候选人组编辑器 中,可以选择组的来源:
-
User groups - 从列表中选择用户组
-
User groups provider — 选择一个能返回用户组列表的特定 Java 类。
-
Expression — 从表达式返回用户组列表,例如,使用之前定义的流程变量。
用户组设置
If you have chosen a User groups option as a source, you can select any from existing user groups:
用户组 Provider
如果需要通过复杂的逻辑设置候选人组,最好选择 User groups provider 选项。
这种方式可以选择已创建的带有 @UserGroupListProvider 注解的一个 Java bean。
Bean 必须实现一个或多个返回 List<String> 表示用户组编码的方法。
@UserGroupListProvider 注解有两个属性:
-
value — 在建模器中显示的名称。
-
description — 方法说明,可选。
示例:
@UserGroupListProvider(value="allGroups",
description = "Returns a list of all groups")
public class MyGroupListProvider {
@Autowired
private UserGroupService userGroupService;
public List<String> getAllUserGroups() {
List<UserGroup> allUserGroups = userGroupService.getAllUserGroups();
if (!allUserGroups.isEmpty()) {
return allUserGroups.stream().map(UserGroup::getCode).toList();
} else {
return Collections.emptyList();
}
}
}
参阅 用户组 章节了解更多内容。
候选用户选项
在 Web BPM 建模器 中设置候选用户与设置候选组类似。 以下是可以选择的来源:
-
Users — 从列表中选择用户
-
Users provider --选择一个能返回用户名列表的特定 Java 类。
-
Expression — 从表达式返回用户名列表。
用户列表 Provider
与 用户组 Provider 类似,可以通过编程方式获取候选用户列表,
对应的 Spring bean 需要带 @UserListProvider 注解:
示例:
@UserListProvider(value = "smpl_UserListProviderDemo",
description = "Get all users")
public class UserListProviderDemo {
@Autowired
private DataManager dataManager;
@Autowired
private SystemAuthenticator authenticator;
public List<String> getAllUsers() {
authenticator.begin();
try {
List<User> users = dataManager.load(User.class).all().list();
return users.stream().map(User::getUsername).toList();
} finally {
authenticator.end();
}
}
}
用户任务流程表单
用户任务可以配置一个 流程表单,协助执行人输入任务所需的数据。收集的数据可以在之后的流程中传递。
多实例
用户任务可以是多实例的。 详情请参阅 多实例活动 部分。
设置任务监听器
Jmix BPM 中的用户任务支持通过任务监听器对特定的事件执行自定义逻辑。 在用户任务触发特定的事件时, 任务监听器中的 Java 类或表达式将执行。
用户任务支持的事件监听器包括:
-
create:当用户任务创建时触发
-
assignment:当用户任务分配给一个用户或用户组时触发
-
complete:当完成用户任务时触发。
-
delete:当删除用户任务时触发。
如需为用户任务配置监听器,可以在 BPMN XML 中使用 flowable:taskListener 扩展元素,
或者用 addTaskListener Java API。
任务监听器为用户任务提供了一种强大的扩展机制, 可以在流程中集成自定义逻辑。 例如发送通知、更新外部系统, 或根据用户任务生命周期中的事件做额外的验证等等。
<userTask id="approve-invoice" name="Approve invoice" jmix:assigneeSource="expression">
<extensionElements>
. . .
<flowable:taskListener class="com.company.demo.listener.ApproverAssignment" (1)
event="assignment" /> (2)
</extensionElements>
. . .
</userTask>
| 1 | 任务监听器类 |
| 2 | 任务事件 |
详情请参阅 任务监听器。
文档
为了给用户提供额外的信息,在 BPMN 中可以使用 documentation 参数,或在 API 中使用 description。 描述的长度不能超过 4000 个字符。
documentation 字段的原来用法是分析师在建模时为流程写的说明。 但是在 用户任务 中,可以作为任务的说明,告诉用户该如何完成任务。
该字段在属性面板的底部。
| 可以在每次修改流程后都更新一下 documentation 字段。 这是为用户提供及时准确信息的最简单方法。 |