vue專案中使用bpmn-流程圖xml檔案中節點屬性轉json結構

Lemoncool發表於2020-05-15

內容概述

本系列“vue專案中使用bpmn-xxxx”分為七篇,均為自己使用過程中用到的例項,手工原創,目前陸續更新中。主要包括vue專案中bpmn使用例項、應用技巧、基本知識點總結和需要注意事項,具有一定的參考價值,需要的朋友可以參考一下。如果轉載或通過爬蟲直接爬的,格式特別醜,請來原創看:我是作者原文

前情提要

前面我們討論了bpmn流程圖的基本繪製、新增節點顏色等,本次我們來說,如何把xml檔案中各種標籤包裹的節點屬性,轉成前端常用的json格式,方便回顯在頁面。首先,我們通過一張圖看一下流程圖xml檔案中,節點的屬性有哪幾種格式。

思路分析

可以看到,節點的屬性被包含在<bpmn:extensionElements>下的<camunda:inputOutput>標籤下,下一層的每個 <camunda:inputParameter>都是一個屬性,屬性共分為三總格式

    1. <camunda:inputParameter>標籤下沒有子元素
      它的屬性“name”便是節點的屬性名,標籤中值“少年的你”便是節點屬性值。所以我們得到的第一個屬性為“selfName:少年的你“
    2. <camunda:inputParameter>下有子元素

      2.1   子元素為<camunda:map>,map在後端語言裡相當於前端的物件(object),對,沒有錯,這個<camunda:map>標籤表示的就是物件。它的下一級標籤<camunda:entry>表示物件下的各個鍵值對。key是鍵名,標籤值是屬性值。所以,根據<camunda:map>標籤,我們得到節點的第二個屬性:nodeDesc: {  class: '一年一班',age: '8'},看來這個節點是個剛上一年級的8歲小朋友。

      2.2  子元素為<camunda:list>,根據2.1的判斷,聰明的你可能猜到了,list表示的是陣列。陣列沒有鍵值對,所以它下面的<camunda:value>表示陣列的其中一  項。所以,我們得到節點的第三個屬性:interestFood: ['蘋果', '香蕉', '西瓜']。所以,根據這一段xml,我們希望的是,能把它解析成一段前端js讀懂的json資料,例如:
form:{
   selfName:少年的你,
   nodeDesc: {  
      class: '一年一班',
      age: '8'
   },
   interestFood: ['蘋果', '香蕉', '西瓜']
}

 有了這段json,我們就可以將節點屬性以想要的形式,展示在流程圖的外面了。那麼,開動吧~~~

程式碼實現

注意,雖然流程圖檔案是一段xml檔案,但是我們不採用直接讀xml檔案的方式去解析,因為bpmn的element下,為我們提供了“businessObject“,這是個萬能的小可愛,它裡面包含節點的所有資訊。那麼怎樣拿到節點例項element呢,在第二篇中,我們講到拿到節點例項有兩種方式,1是點選事件獲取,2是根據id。此時我們採取第一種,即當點選每個節點時,我們可以拿到e,e.element.businessObject 就是我們想要。

addEventBusListener() {
  let eventBus = this.bpmnModeler.get('eventBus');
  // 註冊節點事件,eventTypes中可以寫多個事件
  let eventTypes = ['element.click'];
  eventTypes.forEach((eventType) => {
    eventBus.on(eventType, (e) => {
      let {element} = e;
      if (!element.parent) return;
      if (!e || element.type === 'bpmn:Process') {
        return false;
      } else {
        if (eventType === 'element.click') {
          let businessObject = element.businessObject || element;
          // 此時的businessObject 是我們想要的萬能的小可愛
          this.splitBusiness2Json(businessObject);
        }
      }
    });
  });
}

拿到businessObject,接下來我們要去拆分它,將屬性轉成json。根據上面的分析,我們已經知道了屬性的三種形式,那麼直接上程式碼吧,splitBusiness2Json是主要方法:

splitBusiness2Json(businessObject) {
  let formData = {};
  let params = this.getExtensionElement(businessObject, 'camunda:InputOutput');
  if (params && params.inputParameters) {
    params.inputParameters.forEach((item) => {
      let definition = item.definition;
      if (definition) {
        if (definition.$type === 'camunda:List') {
          let arr = [];
          definition.items.forEach((itemsItem) => {
            arr.push(itemsItem.value);
          });
          formData[item.name] = arr;
        } else if (definition.$type === 'camunda:Map') {
          let obj = {};
          if (definition.entries) {
            definition.entries.forEach((entriesItem) => {
              obj[entriesItem.key] = entriesItem.value;
            });
            formData[item.name] = obj;
          }
        }
      } else {
        formData[item.name] = item.value;
      }
    });
  }
  this.form = formData;
  console.log('this.form', this.form);
}

getExtensionElement:獲取extensionElement下所有的屬性

getExtensionElement(element, type) {
  if (!element.extensionElements) {
    return;
  }
  return element.extensionElements.values.filter((extensionElement) => {
    return extensionElement.$instanceOf(type);
  })[0];
}

成果驗證

此時,我列印一下this.form,格式如下:

 

bingo~格式和我們開篇時分析的完全相同,說明我們的函式成功了。此時可以把屬性顯示在需要的地方了。

  

我猜,此時你肯定有一個想法,既然屬性可以轉成json展示, 那如果在上圖的表單裡對屬性進行修改,可以將修改得值寫回到xml中,儲存到後端嗎?當然可以,下一篇,我們來說json轉換為流程圖xml。

進行到現在,我們已經實現了將xml中的屬性轉化為json了,完整程式碼是個資料夾,不知道怎樣傳到部落格裡。所以,想要獲取完整程式碼的小夥伴, 可以公眾號聯絡我,掃下面二維碼或公眾號搜“Lemoncool”,即可獲取~

相關文章