[TOC]?
## 1.簡介
Flowable是一個(gè)使用Java編寫的輕量級(jí)業(yè)務(wù)流程引擎。Flowable流程引擎可用于部署B(yǎng)PMN 2.0流程定義(用于定義流程的行業(yè)XML標(biāo)準(zhǔn)), 創(chuàng)建這些流程定義的流程實(shí)例,進(jìn)行查詢,訪問運(yùn)行中或歷史的流程實(shí)例與相關(guān)數(shù)據(jù),等等。這個(gè)章節(jié)將用一個(gè)可以在你自己的開發(fā)環(huán)境中使用的例子,逐步介紹各種概念與API。
Flowable可以十分靈活地加入你的應(yīng)用/服務(wù)/構(gòu)架。可以將JAR形式發(fā)布的Flowable庫加入應(yīng)用或服務(wù),來嵌入引擎。 以JAR形式發(fā)布使Flowable可以輕易加入任何Java環(huán)境:Java SE;Tomcat、Jetty或Spring之類的servlet容器;JBoss或WebSphere之類的Java EE服務(wù)器,等等。 另外,也可以使用Flowable REST API進(jìn)行HTTP調(diào)用。也有許多Flowable應(yīng)用(Flowable Modeler, Flowable Admin, Flowable IDM 與 Flowable Task),提供了直接可用的UI示例,可以使用流程與任務(wù)。
所有使用Flowable方法的共同點(diǎn)是核心引擎。核心引擎是一組服務(wù)的集合,并提供管理與執(zhí)行業(yè)務(wù)流程的API。 下面的教程從設(shè)置與使用核心引擎的介紹開始。后續(xù)章節(jié)都建立在之前章節(jié)中獲取的知識(shí)之上。
第一節(jié)展示了以最簡單的方式運(yùn)行Flowable的方法:只使用Java SE的標(biāo)準(zhǔn)Java main方法。這里也會(huì)介紹許多核心概念與API。
**另: Flowable是Activiti(Alfresco持有的注冊(cè)商標(biāo))的fork。在下面的章節(jié)中,你會(huì)注意到包名,配置文件等等,都使用flowable。**
### 1.flowable的五個(gè)引擎
#### 1.1 flowable包含五個(gè)引擎,分別是:
1. 內(nèi)容引擎 ContentEngine
1. 身份識(shí)別引擎 IdmEngine
1. 表單引擎 FormEngine
1. 決策引擎 DmnEngine
1. 流程引擎 ProcessEngine
#### 1.2 引擎包含的服務(wù)
每個(gè)引擎由相對(duì)應(yīng)的 EngineConfiguration進(jìn)行創(chuàng)建,在創(chuàng)建過程中對(duì)每個(gè)引擎使用的服務(wù)進(jìn)行初始化。
##### 1.2.1 內(nèi)容引擎 ContentEngine
**內(nèi)容引擎包含的服務(wù)有: ContentManagementService**
>ContentManagementService提供對(duì)數(shù)據(jù)庫表的管理操作,包括:
>
>Map<String, Long> getTableCount() 獲取每個(gè)表的記錄數(shù)量;
>String getTableName(Class<?> flowableEntityClass); 根據(jù)實(shí)體類獲得對(duì)應(yīng)的數(shù)據(jù)庫表名;
>TableMetaData getTableMetaData(String tableName); 根據(jù)數(shù)據(jù)庫表名獲得表的列名和列類型;
>TablePageQuery createTablePageQuery(); 創(chuàng)建一個(gè)可以進(jìn)行排序、根據(jù)條件分頁的查詢類。
>ContentService
>
>實(shí)現(xiàn)對(duì)內(nèi)容的創(chuàng)建、刪除、保存和獲取的基本操作。
>
>ContentItem newContentItem();
>
>void saveContentItem(ContentItem contentItem);
>
>void saveContentItem(ContentItem contentItem, InputStream inputStream);
>
>InputStream getContentItemData(String contentItemId);
>
>void deleteContentItem(String contentItemId);
>
>void deleteContentItemsByProcessInstanceId(String processInstanceId);
>
>void deleteContentItemsByTaskId(String taskId);
>
>ContentItemQuery createContentItemQuery();
ContentEngineConfiguration
ContentEngineConfiguration最主要的作用是提供Mybatis的封裝,實(shí)現(xiàn)數(shù)據(jù)庫相關(guān)配置的獲取。
同時(shí),內(nèi)容引擎配置還提供了操作系統(tǒng)級(jí)的文件操作的路徑設(shè)置、文件讀取、文件保存的功能。
##### 1.2.2 身份識(shí)別引擎 IdmEngine
**身份識(shí)別引擎包含的服務(wù)有:IdmIdentityService**
>提供用戶的創(chuàng)建、修改、刪除、密碼修改、登錄、用戶頭像設(shè)置等;?
>提供組Group的創(chuàng)建、刪除、用戶與組關(guān)系的關(guān)聯(lián)、刪除關(guān)聯(lián);?
>提供權(quán)限的創(chuàng)建、刪除、關(guān)聯(lián)等。
>
>IdmManagementService
>
>對(duì)身份識(shí)別相關(guān)的數(shù)據(jù)庫表進(jìn)行統(tǒng)計(jì)、獲取表的列信息。
>
>IdmEngineConfiguration
>
>提供數(shù)據(jù)庫配置信息。
##### 1.2.3 表單引擎 FormEngine
>表單引擎包含的服務(wù)有:
>
>FormManagementService
>FormRepositoryService
>FormService
>FormEngineConfiguration
##### 1.2.4 決策引擎 DmnEngine
>決策引擎包含的服務(wù)有:
>
>DmnManagementService
>DmnRepositoryService
>DmnRuleService
>DmnHistoryService
>DmnEngineConfiguration
##### 2.2.5 流程引擎 ProcessEngine
流程引擎包含的服務(wù)有:
> RepositoryService
> RuntimeService
> HistoryService
> IdentityService。
> TaskService。
> FormService。
> ManagementService。
>DynamicBpmnService
## 2.Flowable Api
### 2.1 流程引擎API與服務(wù)
引擎API是與Flowable交互的最常用手段???cè)肟邳c(diǎn)是ProcessEngine。ProcessEngine可以使用多種方式創(chuàng)建。使用ProcessEngine,可以獲得各種提供工作流/BPM方法的服務(wù)。P**rocessEngine與服務(wù)對(duì)象都是線程安全的,因此可以在服務(wù)器中保存并共用同一個(gè)引用。**

**流程引擎中的常用服務(wù)接口**
>提供一系列管理流程部署和流程定義的API。
**RepositoryService:**
RepositoryService repositoryService = processEngine.getRepositoryService();
>在流程運(yùn)行時(shí)對(duì)流程實(shí)例進(jìn)行管理與控制。
**RuntimeService**
RuntimeService runtimeService = processEngine.getRuntimeService();
>對(duì)流程的歷史數(shù)據(jù)進(jìn)行操作,包括查詢、刪除這些歷史數(shù)據(jù)。
**HistoryService**
HistoryService historyService = processEngine.getHistoryService();
>提供對(duì)流程角色數(shù)據(jù)的API,這些角色數(shù)據(jù)包括用戶組、用戶及它們之間的關(guān)系。
**IdentityService**
IdentityService identityService = processEngine.getIdentityService();
> 對(duì)流程任務(wù)進(jìn)行管理,例如任務(wù)提醒、任務(wù)完成和創(chuàng)建任務(wù)等。
**TaskService**
TaskService taskService = processEngine.getTaskService();
> 表單服務(wù)。
**FormService**
FormService formService = processEngine.getFormService();
> 提供對(duì)流程引擎進(jìn)行管理和維護(hù)的服務(wù)。
**ManagementService**
ManagementService managementService = processEngine.getManagementService();
>可用于修改流程定義中的部分內(nèi)容,而不需要重新部署它。例如可以修改流程定義中一個(gè)用戶任務(wù)的辦理人設(shè)置,或者修改一個(gè)服務(wù)任務(wù)中的類名。
**DynamicBpmnService**
DynamicBpmnService dynamicBpmnService = processEngine.getDynamicBpmnService();
* * *
**RepositoryService很可能是使用Flowable引擎要用的第一個(gè)服務(wù)**。這個(gè)服務(wù)提供了管理與控制部署(deployments)與流程定義(process definitions)的操作。在這里簡單說明一下,流程定義是BPMN 2.0流程對(duì)應(yīng)的Java對(duì)象,體現(xiàn)流程中每一步的結(jié)構(gòu)與行為。部署是Flowable引擎中的包裝單元,一個(gè)部署中可以包含多個(gè)BPMN 2.0 XML文件及其他資源。開發(fā)者可以決定在一個(gè)部署中包含的內(nèi)容,可以是單個(gè)流程的BPMN 2.0 XML文件,也可以包含多個(gè)流程及其相關(guān)資源(如’hr-processes’部署可以包含所有與人力資源流程相關(guān)的的東西)。RepositoryService可用于部署這樣的包。部署意味著將它上傳至引擎,引擎將在儲(chǔ)存至數(shù)據(jù)庫之前檢查與分析所有的流程。在部署操作后,可以在系統(tǒng)中使用這個(gè)部署包,部署包中的所有流程都可以啟動(dòng)。
此外,這個(gè)服務(wù)還可以:
- 查詢引擎現(xiàn)有的部署與流程定義。
- 暫?;蚣せ畈渴鹬械哪承┝鞒蹋蛘麄€(gè)部署。暫停意味著不能再對(duì)它進(jìn)行操作,激活剛好相反,重新使它可以操作。
- 獲取各種資源,比如部署中保存的文件,或者引擎自動(dòng)生成的流程圖。
- 獲取POJO版本的流程定義。它可以用Java而不是XML的方式查看流程。
* * *
**RuntimeService用于啟動(dòng)流程定義的新流程實(shí)例**。前面介紹過,流程定義中定義了流程中不同步驟的結(jié)構(gòu)與行為。流程實(shí)例則是流程定義的實(shí)際執(zhí)行過程。同一時(shí)刻,一個(gè)流程定義通常有多個(gè)運(yùn)行中的實(shí)例。RuntimeService也用于讀取與存儲(chǔ)流程變量。流程變量是流程實(shí)例中的數(shù)據(jù),可以在流程的許多地方使用(例如排他網(wǎng)關(guān)經(jīng)常使用流程變量判斷流程下一步要走的路徑)。RuntimeService還可以用于查詢流程實(shí)例與執(zhí)行(Execution)。執(zhí)行也就是BPMN 2.0中 'token' 的概念。通常執(zhí)行是指向流程實(shí)例當(dāng)前位置的指針。最后,還可以在流程實(shí)例等待外部觸發(fā)時(shí)使用RuntimeService,使流程可以繼續(xù)運(yùn)行。流程有許多等待狀態(tài)(wait states),RuntimeService服務(wù)提供了許多操作用于“通知”流程實(shí)例:已經(jīng)接收到外部觸發(fā),流程實(shí)例可以繼續(xù)運(yùn)行。
* * *
Flowable這樣的BPM引擎來說,核心是需要人類用戶操作的任務(wù),**所有任務(wù)相關(guān)的東西都組織在TaskService中**,例如
* 查詢分派給用戶或組的任務(wù)
* 創(chuàng)建獨(dú)立運(yùn)行(standalone)任務(wù)。這是一種沒有關(guān)聯(lián)到流程實(shí)例的任務(wù)。
* 決定任務(wù)的執(zhí)行用戶(assignee),或者將用戶通過某種方式與任務(wù)關(guān)聯(lián)。
* 認(rèn)領(lǐng)(claim)與完成(complete)任務(wù)。認(rèn)領(lǐng)是指某人決定成為任務(wù)的執(zhí)行用戶,也即他將會(huì)完成這個(gè)任務(wù)。完成任務(wù)是指“做這個(gè)任務(wù)要求的工作”,通常是填寫某個(gè)表單。
* * *
**IdentityService**,它用于管理(創(chuàng)建,更新,刪除,查詢……)組與用戶。
Flowable實(shí)際上在運(yùn)行時(shí)并不做任何用戶檢查。例如任務(wù)可以分派給任何用戶,而引擎并不會(huì)驗(yàn)證系統(tǒng)中是否存在該用戶。這是因?yàn)镕lowable有時(shí)要與LDAP、Active Directory等服務(wù)結(jié)合使用。
****
**FormService是可選服務(wù)**。
也就是說Flowable沒有它也能很好地運(yùn)行,而不必犧牲任何功能。這個(gè)服務(wù)引入了開始表單(start form)與任務(wù)表單(task form)的概念。 開始表單是在流程實(shí)例啟動(dòng)前顯示的表單,而任務(wù)表單是用戶完成任務(wù)時(shí)顯示的表單。Flowable可以在BPMN 2.0流程定義中定義這些表單。表單服務(wù)通過簡單的方式暴露這些數(shù)據(jù)。再次重申,表單不一定要嵌入流程定義,因此這個(gè)服務(wù)是可選的。
* * *
**HistoryService** 暴露Flowable引擎收集的所有歷史數(shù)據(jù)。當(dāng)執(zhí)行流程時(shí),引擎會(huì)保存許多數(shù)據(jù)(可配置),例如流程實(shí)例啟動(dòng)時(shí)間、誰在執(zhí)行哪個(gè)任務(wù)、完成任務(wù)花費(fèi)的事件、每個(gè)流程實(shí)例的執(zhí)行路徑,等等。這個(gè)服務(wù)主要提供查詢這些數(shù)據(jù)的能力。
* * *
**ManagementService**
通常在用Flowable編寫用戶應(yīng)用時(shí)不需要使用。它可以讀取數(shù)據(jù)庫表與表原始數(shù)據(jù)的信息,也提供了對(duì)作業(yè)(job)的查詢與管理操作。Flowable中很多地方都使用作業(yè),例如定時(shí)器(timer),異步操作(asynchronous continuation),延時(shí)暫停/激活(delayed suspension/activation)等等。
* * *
**DynamicBpmnService**
可用于修改流程定義中的部分內(nèi)容,而不需要重新部署它。例如可以修改流程定義中一個(gè)用戶任務(wù)的辦理人設(shè)置,或者修改一個(gè)服務(wù)任務(wù)中的類名。
### 2.2 異常策略
**Flowable的異常基類是org.flowable.engine.FlowableException**,這是一個(gè)非受檢異常(unchecked exception)。在任何API操作時(shí)都可能會(huì)拋出這個(gè)異常,javadoc提供了每個(gè)方法可能拋出的異常。例如,從TaskService中摘錄:
```
/**
* 當(dāng)任務(wù)成功執(zhí)行時(shí)調(diào)用。
* @param taskId 需要完成的任務(wù)id,不能為null。
* @throws FlowableObjectNotFoundException 若給定id找不到任務(wù)。
*/
void complete(String taskId);
```
在上例中,如果所用的id找不到任務(wù),就會(huì)拋出異常。并且,**由于javadoc中明確要求taskId不能為null,因此如果傳遞了null值**,會(huì)拋出FlowableIllegalArgumentException異常。
盡管我們想避免過大的異常層次結(jié)構(gòu),但在特定情況下仍然會(huì)拋出下述異常子類。所有流程執(zhí)行與API調(diào)用中發(fā)生的錯(cuò)誤,如果不符合下面列出的異常,**會(huì)統(tǒng)一拋出FlowableExceptions**。
* FlowableWrongDbException: 當(dāng)Flowable引擎檢測(cè)到數(shù)據(jù)庫表結(jié)構(gòu)版本與引擎版本不匹配時(shí)拋出。
* FlowableOptimisticLockingException: 當(dāng)對(duì)同一數(shù)據(jù)實(shí)體的并發(fā)訪問導(dǎo)致數(shù)據(jù)存儲(chǔ)發(fā)生樂觀鎖異常時(shí)拋出。、
* FlowableClassLoadingException: 當(dāng)需要載入的類(如JavaDelegate, TaskListener, …)無法找到,或載入發(fā)生錯(cuò)誤時(shí)拋出。
* FlowableObjectNotFoundException: 當(dāng)請(qǐng)求或要操作的對(duì)象不存在時(shí)拋出。
* FlowableIllegalArgumentException: 當(dāng)調(diào)用Flowable API時(shí)使用了不合法的參數(shù)時(shí)拋出??赡苁且媾渲弥械牟缓戏ㄖ?,或者是API調(diào)用傳遞的不合法參數(shù),也可能是流程定義中的不合法值。
* FlowableTaskAlreadyClaimedException: 當(dāng)對(duì)已被認(rèn)領(lǐng)的任務(wù)調(diào)用taskService.claim(…)時(shí)拋出。
### 2.3 查詢APi
從引擎中查詢數(shù)據(jù)有兩種方式:**查詢API與原生(native)查詢**。查詢API可以使用鏈?zhǔn)紸PI,通過編程方式進(jìn)行類型安全的查詢。你可以在查詢中增加各種條件(所有條件都用做AND邏輯),也可以明確指定排序方式。下面是示例代碼:
```
// 查詢?nèi)蝿?wù) 受理人為kermit ,流程綁定參數(shù)為orderId- 0815的集合數(shù)據(jù),并以日期排序
List<Task> tasks = taskService.createTaskQuery()
.taskAssignee("kermit")
.processVariableValueEquals("orderId", "0815")
.orderByDueDate().asc()
.list();
long count = taskService.createNativeTaskQuery()
.sql("SELECT count(*) FROM " + managementService.getTableName(Task.class) + " T1, " +
managementService.getTableName(VariableInstanceEntity.class) + " V1 WHERE V1.TASK_ID_ = T1.ID_")
.count();?
```
### 2.4 變量
流程實(shí)例按步驟執(zhí)行時(shí),需要使用一些數(shù)據(jù)。在Flowable中,這些數(shù)據(jù)稱作變量(variable),并會(huì)存儲(chǔ)在數(shù)據(jù)庫中。變量可以用在表達(dá)式中(**例如在排他網(wǎng)關(guān)中用于選擇正確的出口路徑**),也可以在Java服務(wù)任務(wù)(service task)中用于調(diào)用外部服務(wù)(例如為服務(wù)調(diào)用提供輸入或結(jié)果存儲(chǔ)),等等。
流程實(shí)例可以持有變量(稱作流程變量 process variables);用戶任務(wù)以及執(zhí)行(executions)——流程當(dāng)前活動(dòng)節(jié)點(diǎn)的指針——也可以持有變量。流程實(shí)例可以持有任意數(shù)量的變量,每個(gè)變量存儲(chǔ)為**ACT_RU_VARIABLE**數(shù)據(jù)庫表的一行。
所有的startProcessInstanceXXX方法都有一個(gè)可選參數(shù),用于在流程實(shí)例創(chuàng)建及啟動(dòng)時(shí)設(shè)置變量。例如,在RuntimeService中:
```
//啟動(dòng)流程實(shí)例, variables為傳遞的流程變量
ProcessInstance startProcessInstanceByKey(String processDefinitionKey, Map<String, Object> variables);
```
也可以在流程執(zhí)行中加入變量。例如,(RuntimeService):
```
void setVariable(String executionId, String variableName, Object value);
void setVariableLocal(String executionId, String variableName, Object value);
void setVariables(String executionId, Map<String, ? extends Object> variables);
void setVariablesLocal(String executionId, Map<String, ? extends Object> variables);
```
請(qǐng)注意可以為給定執(zhí)行(**請(qǐng)記住,流程實(shí)例由一顆執(zhí)行的樹(tree of executions)組成**)設(shè)置局部(local)變量。局部變量將只在該執(zhí)行中可見,對(duì)執(zhí)行樹的上層則不可見。這可以用于 數(shù)據(jù)不應(yīng)該暴露給流程實(shí)例的其他執(zhí)行,或者變量在流程實(shí)例的不同路徑中有不同的值(例如使用并行路徑時(shí))的情況。
可以用下列方法讀取變量。請(qǐng)注意TaskService中有類似的方法。這意味著任務(wù)與執(zhí)行一樣,可以持有局部變量,其生存期為任務(wù)持續(xù)的時(shí)間。
```
Map<String, Object> getVariables(String executionId);
Map<String, Object> getVariablesLocal(String executionId);
Map<String, Object> getVariables(String executionId, Collection<String> variableNames);
Map<String, Object> getVariablesLocal(String executionId, Collection<String> variableNames);
Object getVariable(String executionId, String variableName);
<T> T getVariable(String executionId, String variableName, Class<T> variableClass);
```
變量通常用于Java代理(Java delegates)、表達(dá)式(expressions)、執(zhí)行(execution)、任務(wù)監(jiān)聽器(tasklisteners)、腳本(scripts)等等。在這些結(jié)構(gòu)中,提供了當(dāng)前的execution或task對(duì)象,可用于變量的設(shè)置、讀取。簡單示例如下:
```
execution.getVariables();
execution.getVariables(Collection<String> variableNames);
execution.getVariable(String variableName);
execution.setVariables(Map<String, object> variables);
execution.setVariable(String variableName, Object value);
```
請(qǐng)注意也可以使用上例中方法的局部變量版本。
由于歷史(與向后兼容)原因,當(dāng)調(diào)用上述任何方法時(shí),引擎會(huì)從數(shù)據(jù)庫中取出所有變量。也就是說,如果你有10個(gè)變量,使用getVariable("myVariable")獲取其中的一個(gè),實(shí)際上其他9個(gè)變量也會(huì)從數(shù)據(jù)庫取出并緩存。這并不壞,因?yàn)楹罄m(xù)的調(diào)用可以不必再讀取數(shù)據(jù)庫。比如,如果流程定義包含三個(gè)連續(xù)的服務(wù)任務(wù)(因此它們?cè)谕粋€(gè)數(shù)據(jù)庫事務(wù)里),在第一個(gè)服務(wù)任務(wù)里通過一次調(diào)用獲取全部變量,也許比在每個(gè)服務(wù)任務(wù)里分別獲取需要的變量要好。請(qǐng)注意對(duì)讀取與設(shè)置變量都是這樣。
當(dāng)然,如果使用大量變量,或者你希望精細(xì)控制數(shù)據(jù)庫查詢與流量,上述的做法就不合適了。我們引入了可以更精細(xì)控制的方法。這個(gè)方法有一個(gè)可選的參數(shù),告訴引擎是否需要讀取并緩存所有變量:
```
Map<String, Object> getVariables(Collection<String> variableNames, boolean fetchAllVariables);
Object getVariable(String variableName, boolean fetchAllVariables);
void setVariable(String variableName, Object value, boolean fetchAllVariables);
```
### 2.5 瞬時(shí)變量
### 2.5 任務(wù)監(jiān)聽listener

#### 2.5.1 任務(wù)監(jiān)聽器類型
* create:在任務(wù)創(chuàng)建且所有任務(wù)屬性設(shè)置完成之后才觸發(fā)。
* assignment:在任務(wù)被分配給某個(gè)班里人之后觸發(fā),它是在create事件觸發(fā)前被觸發(fā)。
* complete:在配置了監(jiān)聽器的任務(wù)完成時(shí)觸發(fā),也就是說運(yùn)行期任務(wù)刪除之前觸發(fā)。
* delete:任務(wù)刪除觸發(fā)
#### 2.5.2 任務(wù)監(jiān)聽器的三種監(jiān)聽器執(zhí)行類型
1. 類(class): :需要類的全路徑
例子:
```
public class StartTaskListener implements TaskListener {
@Override
public void notify(DelegateTask delegateTask) {
logger.debug("調(diào)用了任務(wù)監(jiān)聽器");
}
}
```
任務(wù)監(jiān)聽的配置:

2.表達(dá)式(expression):定義一個(gè)表達(dá)式,類似EL的語法

3.委托表達(dá)式(delegateExpression):指的是一個(gè)實(shí)現(xiàn)監(jiān)聽接口
1.自定義接口 實(shí)現(xiàn)TaskListener, @Component 標(biāo)識(shí)
```
@Component(value = "taskBusinessCallListener")
public class TaskBusinessCallListener extends BusinessCallListener implements TaskListener {
/**
* dubbo的類名
*/
private FixedValue clazzName;
/**
* 方法名
*/
private FixedValue method;
/**
* 版本號(hào)
*/
private FixedValue version;
/**
* 參數(shù) 多個(gè)的話用分號(hào)隔開 實(shí)例 userCode:00004737;status:1
*/
private FixedValue params;
@Override
public void notify(DelegateTask delegateTask) {
String processInstanceId = delegateTask.getProcessInstanceId();
//執(zhí)行回調(diào)
this.callBack(processInstanceId, clazzName.getExpressionText(), method.getExpressionText(), version.getExpressionText(), params.getExpressionText());
}
}
```

* * *
* * *
* * *
* * *
* * *
flowable的辦理方式,分為兩種:簽收模式辦理和直接辦理。
術(shù)語:
Assignee: 任務(wù)的受理人,即執(zhí)行人。它有兩種情況(有值,NULL)
Owner: 任務(wù)的委托人。
CandidateGroup: 候選用戶組
CandidateUser: 候選人
delegateTask: 委派任務(wù)/簽收的任務(wù)
resolveTask:? 委派任務(wù)的代辦,任務(wù)的擁有者把任務(wù)委派他人來辦理,他人辦完后,又重新回到任務(wù)擁有者,會(huì)產(chǎn)生流轉(zhuǎn)記錄。
turnTask: 轉(zhuǎn)辦任務(wù),只是改變當(dāng)前任務(wù)的辦理人而已,不會(huì)產(chǎn)生流轉(zhuǎn)記錄。
CompleteTask: 完成任務(wù),或叫辦結(jié)提交下一步。
claimTask:任務(wù)簽收