博客 / 詳情

返回

流程表單初體驗

@[toc]
有小夥伴在星球上催了好幾次了,今天鬆哥就來和大家聊一聊流程中的表單。

1. 表單分類

整體上來説,我們可以將表單分為三種不同的類型:

  1. 動態表單:這種表單定義方式我們可以配置表單中每一個字段的可讀性、可寫性、是否必填等信息,不過不能定義完整的表單頁面。
  2. 外置表單:外置表單我們只需要定義一下表單的 key,至於這個 key 對應的表單是什麼樣子,則由開發者自己去維護。
  3. 內置表單:這是內置的表單定義以及渲染引擎,鬆哥在之前的一個不用寫代碼的案例,來看看Flowable到底給我們提供了哪些功能?一文中所使用的表單,就是這種。

另外小夥伴們需要注意,Flowable 中有很多不同類型的節點,但是隻有開始節點和任務節點是支持表單定義的,其他節點均不支持表單定義。

2. 動態表單

今天我們就先來看看動態表單的玩法。

假設我有如下一個請假流程:

在第一個任務節點中,需要填寫請假的基本信息,那麼我們選中該節點,然後點擊動態表單屬性,如下圖:

然後就可以開啓動態表單屬性的配置了:

我這裏一共配置了四個屬性,這些屬性的含義應該都好理解,我就不一一贅述了。

接下來我們來下載這個流程圖。

流程的 XML 文件下載下來之後,我們可以在看到在 UserTask 節點中多了 flowable:formProperty 標籤,現在,如果我想將 UserTask 節點中的動態表單屬性拷貝到啓動節點中,直接拷貝即可,如下:

<process id="FormDemo01" name="FormDemo01" isExecutable="true">
  <documentation>FormDemo01</documentation>
  <startEvent id="startEvent1" flowable:formFieldValidation="true">
    <extensionElements>
      <flowable:formProperty id="startTime" name="請假開始時間" type="date" datePattern="yyyy-MM-dd HH:mm" required="true"></flowable:formProperty>
      <flowable:formProperty id="endTime" name="請假結束時間" type="date" datePattern="yyyy-MM-dd HH:mm" required="true"></flowable:formProperty>
      <flowable:formProperty id="reason" name="請假理由" type="string" required="true"></flowable:formProperty>
      <flowable:formProperty id="days" name="請假天數" type="long" required="true"></flowable:formProperty>
    </extensionElements>
    </startEvent>
  <userTask id="sid-F4DE03F1-D09F-4527-9267-0E5C276D08B8" name="提交請假申請" flowable:formFieldValidation="true">
    <extensionElements>
      <flowable:formProperty id="startTime" name="請假開始時間" type="date" datePattern="yyyy-MM-dd HH:mm" required="true"></flowable:formProperty>
      <flowable:formProperty id="endTime" name="請假結束時間" type="date" datePattern="yyyy-MM-dd HH:mm" required="true"></flowable:formProperty>
      <flowable:formProperty id="reason" name="請假理由" type="string" required="true"></flowable:formProperty>
      <flowable:formProperty id="days" name="請假天數" type="long" required="true"></flowable:formProperty>
    </extensionElements>
  </userTask>
  <sequenceFlow id="sid-2A8D19F2-927C-4FCE-AF31-534425B1CA18" sourceRef="startEvent1" targetRef="sid-F4DE03F1-D09F-4527-9267-0E5C276D08B8"></sequenceFlow>
  <userTask id="sid-9136F312-F00B-467E-A61B-F2932BA9068A" name="請假審批" flowable:formFieldValidation="true"></userTask>
  <sequenceFlow id="sid-877A95AB-B8A4-47FE-BC9F-0998FEAEC52C" sourceRef="sid-F4DE03F1-D09F-4527-9267-0E5C276D08B8" targetRef="sid-9136F312-F00B-467E-A61B-F2932BA9068A"></sequenceFlow>
  <endEvent id="sid-E26593D4-C67B-4784-98EE-772B9659F805"></endEvent>
  <sequenceFlow id="sid-1A5C4E8C-6705-4148-A0E3-E7769631BFD9" sourceRef="sid-9136F312-F00B-467E-A61B-F2932BA9068A" targetRef="sid-E26593D4-C67B-4784-98EE-772B9659F805"></sequenceFlow>
</process>

可以看到,在 startEvent 和第一個 userTask 中都有 flowable:formProperty 標籤。

接下來,按照我們之前所講的,我們來部署一下這個流程。部署完成之後,我們可以通過如下方式來查詢流程中的動態表單信息:

@Autowired
FormService formService;

@Test
void test01() {
    ProcessDefinition pd = repositoryService.createProcessDefinitionQuery().processDefinitionKey("FormDemo01").latestVersion().singleResult();
    StartFormData startFormData = formService.getStartFormData(pd.getId());
    System.out.println("startFormData.getDeploymentId() = " + startFormData.getDeploymentId());
    System.out.println("startFormData.getFormKey() = " + startFormData.getFormKey());
    List<FormProperty> formProperties = startFormData.getFormProperties();
    for (FormProperty fp : formProperties) {
        String value = fp.getValue();
        String id = fp.getId();
        boolean readable = fp.isReadable();
        boolean writable = fp.isWritable();
        boolean required = fp.isRequired();
        String name = fp.getName();
        FormType type = fp.getType();
        String key = "";
        if (type instanceof EnumFormType) {
            key = "values";
        } else if (type instanceof DateFormType) {
            key = "datePattern";
        }
        Object information = type.getInformation(key);
        logger.info("value:{},id:{},readable:{},writeable:{},required:{},name:{},info:{}", value, id, readable, writable, required, name, information);
    }
}

小夥伴們可以看到,這個查詢是通過流程定義查詢的,所以這裏查詢到的信息,其實也是和流程實例無關的。只是單純的查看一下啓動節點上有哪些動態表單需要輸入,以及這些動態表單的類型。最終輸出日誌如下:

3. 啓動帶表單的實例

動態表單,其實跟普通的變量有點像,啓動的時候我們可以通過表單服務類來啓動,代碼如下:

@Test
void test02() {
    ProcessDefinition pd = repositoryService.createProcessDefinitionQuery().processDefinitionKey("FormDemo01").latestVersion().singleResult();
    Map<String, String> vars = new HashMap<>();
    vars.put("startTime", "2022-10-10 10:10");
    vars.put("endTime", "2022-10-12 10:10");
    vars.put("reason", "玩兩天");
    vars.put("days", "3");
    ProcessInstance pi = formService.submitStartFormData(pd.getId(), vars);
}

小夥伴們看到,我們這裏通過 formService.submitStartFormData 方法來啓動流程實例,啓動的時候,傳入了 vars 變量。

流程實例啓動成功之後,我們在 ACT_RU_VARIABLE 表中就可以看到這些動態表單的信息。

從這裏可以看到我們剛剛存入的數據。

4. 查詢任務上的表單

現在我們的流程走到了 提交請假申請 這一步了,我們在繪製流程圖的時候,提交請假申請 這個 UserTask 中也是有動態表單的,前面啓動流程時傳遞的動態表單信息,現在已經傳到 提交請假申請 這一步了,我們可以通過如下方式來進行查詢:

@Test
void test03() {
    Task task = taskService.createTaskQuery().singleResult();
    TaskFormData taskFormData = formService.getTaskFormData(task.getId());
    List<FormProperty> formProperties = taskFormData.getFormProperties();
    for (FormProperty fp : formProperties) {
        String value = fp.getValue();
        String id = fp.getId();
        boolean readable = fp.isReadable();
        boolean writable = fp.isWritable();
        boolean required = fp.isRequired();
        String name = fp.getName();
        FormType type = fp.getType();
        String key = "";
        if (type instanceof EnumFormType) {
            key = "values";
        } else if (type instanceof DateFormType) {
            key = "datePattern";
        }
        Object information = type.getInformation(key);
        logger.info("value:{},id:{},readable:{},writeable:{},required:{},name:{},info:{}", value, id, readable, writable, required, name, information);
    }
}

小夥伴們看到,調用 formService.getTaskFormData 方法傳入 TaskId 即可進行查詢。這個時候查詢出來的內容就有值了:

可能有的小夥伴會説,這跟用變量有啥區別呀,用變量不也是這樣嗎?

變量是散的,而表單是整的。

在上面的代碼中,一個方法就可以提取出來所有的表單信息了,然後就遍歷就行了。

另外還需要注意,如果 提交請假申請 中的動態表單和啓動節點的動態表單不一致的話,提交請假申請 節點中有哪些動態表單,就能拿到哪些數據,其他的數據就不能通過表單拿到。

以上面的案例來説,startEvent 中有 startTime、endTime、reason 以及 days 四個動態表單屬性,如果 提交請假申請 中只有 reason 和 days 兩個動態表單屬性的話,那麼就只能獲取這兩個動態表單屬性,其他的動態表單屬性則可以通過變量去獲取。

5. 保存與完成

對於 UserTask 上的表單,我們首先可以通過如下方式來提交表單數據:

@Test
void test04() {
    Task task = taskService.createTaskQuery().singleResult();
    Map<String, String> vars = new HashMap<>();
    vars.put("startTime", "2022-10-11 11:11");
    vars.put("endTime", "2022-10-19 11:11");
    formService.saveFormData(task.getId(), vars);
}

這個方法只是保存動態表單變量,並不會完成當前 Task。

如果想在提交表單變量的同時順便完成當前 UserTask,方式如下:

@Test
void test04() {
    Task task = taskService.createTaskQuery().singleResult();
    Map<String, String> vars = new HashMap<>();
    vars.put("startTime", "2022-10-11 11:11");
    vars.put("endTime", "2022-10-19 11:11");
    formService.submitTaskFormData(task.getId(), vars);
}

該方法在提交表單變量的同時,還會順便 complete 當前 UserTask。

好啦,這就是關於動態表單鬆哥和大家介紹的內容啦~

動態表單用法簡單,很多小夥伴想不明白為什麼要用表單,用變量不行嗎?技術上來説,變量當然可以,但是變量是一個一個的,是零散的,而表單是整的,整存整取的。

just this。

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.