天天看點

企業級自定義表單引擎解決方案(五)——表單模型管理

作者:spritekuang
  • .net core研發的低代碼自定義表單引擎,采用強大的規則引擎将所有的業務串聯起來的,和其他低代碼平台是有本質的差別的,目标是完全解放繁瑣的CRUD工作,其他很多稱為低代碼的不管界面介紹得多炫酷,本質上還是解決複制粘貼的問題。
  • 正常的業務,在需求以及資料庫設計完成之後,可能就僅僅在界面上幾分鐘的配置就能夠完成所有的開發、測試、部署工作,最後使用者直接使用,完全解放繁瑣的CRUD工作。
  • 表單模闆能夠快速建立正常的業務子產品,系統盡量将正常的業務功能做成模闆,友善快速地建立業務子產品功能,選擇一個模闆之後,會将模闆對應的表單、子表單、子視圖、控件等所有自定義表單相關的定義全部自動建立出來。

之前介紹的自定義表單中的視圖定義為單一功能的封裝,比如清單視圖(定義普通查詢區域,進階查詢區域,清單操作按鈕區域,行操作按鈕區域,分頁控件區域,列顯示區域等)或者表單視圖(封裝表單行列定義,表單驗證等)等,都是具體某個特定功能的實作。而這裡介紹的表單模型,則把它定義為一個容器,容器裡面會進一步定義行列,容器裡面可以包含容器或者表單,每一個頁面會定義唯一一個最外層的表單容器,我們可以把它看作根容器,這樣就整體形成了一棵樹,根節點就是最外層的表單定義,樹的節點可以是子表單、視圖、表單行、表單列、視圖行、視圖列、視圖控件等,整體就可以構造出一樹龐大的樹。

  自定義表單最終會轉換為一棵樹,樹的話就會有樹的特性,樹上的每一個節點,都可以構造一個唯一的Code和PId,自定義表單中的樹節點還會擴充出它屬于哪個視圖或者哪個表單的屬性,那麼這裡就是引申出子表單子視圖,父表單父視圖的概念。

有了樹模型的定義,那麼後面絕大多數内容都是圍繞樹模型來實作的,前端在渲染界面的時候,根據樹節點一層一層地渲染界面,渲染界面的同時,将每個節點的Code和PId,節點屬于哪個表單或者視圖都會指派到每個樹節點控件中,有了樹模型的定義,那麼規則引擎就有了理論支撐,界面中的任何一個事件,都可以定義規則來實作自定義的邏輯(比如點選清單視圖的行編輯按鈕,彈出編輯人員子表單,則大緻的規則引擎執行邏輯為:找到清單視圖特定行編輯按鈕所在的清單視圖,在清單視圖中找到編輯人員子表單,把目前行的Id字段取出來作為參數,用模态對話框彈出子表單,用Id字段執行後端方法擷取單條人員資料,将人員資料綁定到人員表單中)。

  表單模型沒有具體的功能,它的作用是一個容器,它充當視圖與視圖之間互動的橋梁的作用,當然是通過規則引擎來串聯起來的,另外表單也是頁面的入口與緩存的存儲資料的入口。

表單的資料庫設計:

企業級自定義表單引擎解決方案(五)——表單模型管理

表單模型資料庫設計

設計說明:

表單模型拆分為表單主表、表單項、表單行、表單列,關系都為1:n。常見的表單項隻有一個,但像Tab布局或者有先後步驟的Step布局則會有多個。

表單主表關鍵字段說明:

  • Version(版本):每一次修改表單的任何資訊(包括關聯的資料),都會重新生成一個版本号,浏覽器存儲表單資訊,每打開一個頁面,會将本地表單版本和視圖版本傳遞到服務端比較版本号,如果版本号發生變化,重新請求表單資料(一般系統互動後,視圖及表單定義資訊很少會發生變化)。
  • FormType(表單類型):分為正常表單、Tab表單、Div表單等,前端根據此類型找到實作定義好的控件渲染。
  • PropertySettings(表單屬性):存儲前端的一些樣式,前端渲染時,讀取屬性并應用到控件中,一般需要結合具體使用的前端架構設定。
  • RelationInfos(關聯資訊):表單可能會關聯其他表單或視圖,比如彈窗,行存儲的視圖等,這個字段資料庫不存儲,通過動态計算出來放入緩存中。
  • Rules(規則):定義表單的規則,将規則資訊備援序列化存儲到此字段,規則有改動時,會同時更新此字段(表單會備援存儲比較多的内容,這裡的規則為一類,主要是為了以最快的速度讀取表單相關資料,隻需要表單Id通路一張表即可擷取所有的資料)。
  • WrapInfos(表單包裝器):前端在渲染視圖時,如果有包裝器,會用包裝器包裝視圖之後再渲染,常見為彈出框的功能封裝。
  • FormItems(表單項内容):将表單項、表單行、表單列全部讀取出來序列化備援存儲到此字段,同樣是為了讀取效率。
  • IsTemplate(是否為模版):将一些典型的業務定義為模版,同樣存儲在表單中。

表單項、表單行:

  • 對應實體結構的劃分,字段比較好了解。

表單列:

  表單列可以存儲單個控件、子表單、子視圖等

  • ColType(列類型):可以是控件、視圖或者表單
  • PropertySettings(列屬性):存儲前端的一些樣式,前端渲染時,讀取屬性并應用到控件中,一般需要結合具體使用的前端架構設定。
  • ComponentName和ControlSettings(控件名稱和控件設定):如果列類型是控件,則為控件名稱與控件屬性,前端找到對應的控件渲染。
  • ObjId(對象Id):表單或者視圖Id,前端渲染時,根據此字段找到具體的表單或者視圖。
  • WrapConfigs(包裝定義):顯示到表單中的子表單或者子視圖的渲染封裝(表單和視圖可以用到任何需要的地方,相當于在用的地方再次進行樣式封裝,比如用Box樣式再次封裝子表單)。

緩存設計簡單介紹:

  自定義表單是典型的修改非常少,通路非常平凡的,系統的每一個功能都需要讀取自定義表單的定義資訊。為了使自定義表單不影響性能,這裡采用了雙重緩存設計,浏覽器每通路一個頁面,都會将表單和視圖的定義資訊存儲到浏覽器本地資料庫中(IndexDb),應用程式後端将表單和視圖的定義資訊全部放到應用程式記憶體中,且将表單或視圖的相關資訊以字段備援的方式存儲到特定字段中,任何資訊的改變都會重新生成新的版本号并清空記憶體中的緩存,前端請求頁面隻,會帶上浏覽器本地存儲的表單和關聯子表單子視圖版本号與伺服器版本号對比,版本号不同時,重新整理浏覽器緩存資料,再渲染頁面。分布式部署中就存儲緩存一緻的問題,後面單獨寫文章來整體講解緩存這塊的實作。

表單模版:

  自定義表單本來就是要解決繁瑣的低效編碼問題,但是要把一個表單配置出來,還是會花費比較多的時間,且需要對這套表單引擎比較熟悉,配置同樣比較繁瑣且低效,那麼我們同樣可以采用自定義表單的思路,将常見的業務封裝為模版,(比如對單一表單進行的正常清單和表單操作,也就是最常見的CRUD操作。或者一對多表單,清單展示主表資料,點開一條件主表資料,對話框顯示主表資料及子表清單,對子表清單進行操作等),隻需要動态渲染不同的地方,那麼就能夠實作隻需要設定幾個簡單的參數,就能夠自動地生成自定義表單出來,這裡的不同地方無非就是Object對象(Object就定義了不同的字段,在渲染字段的地方全部替換為新的Object的字段),标題内容等少數不同的地方。  

模版的實作思路大緻為:根據模版Id找到表單模型相關的所有表單和視圖,将關聯的所用資料表資料讀取到記憶體中,包括規則、控件、視圖行、表單項、表單列等,再對Id進行Map映射(建立一個字典對象,讀取所有Guid字段的地方,建立映射,Key存儲老的Guid,Value存儲建立的Guid),将所有資料Guid字段替換為将建的Guid值,将Object對象相關的資料全部删除,用将的Object字段重新生成資料,不同的字段類型設定預設的樣式,再将所有内容存儲到資料庫。

随着表單引擎的使用,可以定義更多的表單模版,那麼表單引擎的功能将越來越豐富也越來越容易使用。

部分核心部分代碼可下載下傳源碼檢視

感覺還是沒有把這塊内容描述得特别清楚,很多設計思想用文字還是有點難表現出來!

低代碼自定義表單引擎絕對不是簡單幾個字就能夠概括的,是一個非常龐大技術知識體系。

低代碼自定義表單引擎、流程引擎,整整花了兩年的時間,後續會陸續在頭條上寫一些文章,直接看代碼基本很難整體了解這塊的設計,文章前面部分主要是一些設計思想,後面會偏具體的一些技術以及場景應用。

wike文檔位址:

https://gitee.com/kuangqifu/sprite/wikis/pages

後端開源位址:

https://gitee.com/kuangqifu/sprite

前端開源位址:

https://gitee.com/kuangqifu/spritefronts

繼續閱讀