先整體介紹一下大概的架構和核心模塊設計。先上一張總體設計圖前端
概念仍是有點多,有一些概念可能比較新,若是熟悉K2自定義表單,可能比較好理解一些。代碼地址:https://gitee.com/kuangqifu/sprite,或者QQ交流:523477776git
對核心的一些功能模塊進行整體介紹以下(用.net core實現,其餘語言總體設計思路相差不大)數據庫
基礎設施:
自定義表單主要涉及到數據存儲,包括表單定義信息和真實的業務表存儲管理,可支持不一樣的數據庫存儲,Redis主要用在緩存更新通知上,Redis不存儲表單定義緩存後端
基礎組件:
表單基礎框架,.net core實現,用Dapper作ORM存儲,封裝了UnitOfWork,另外還包括了模塊管理、租戶/應用管理等基礎功能,不包括權限相關功能。瀏覽器
表單定義信息對於自定義表單來講,訪問特別的頻繁,真實業務變動極少,須要很多的過濾查詢,若是存儲到Redis,涉及到頻繁的訪問以及數據過濾,對總體性能影響也比較大,因此這裏考慮把表單定義信息存儲到每個應用程序內存中,直接從內存中訪問表單定義信息,表單定義信息改變時,通知全部應用表單定義對應的數據已經更新,應用程序讀取數據時,會從數據庫讀取最新的數據存儲到內存中。表單定義信息還會存儲到瀏覽器Indexdb中,一條總的原則就是訪問自定義表單定義信息必定要快,就近獲取。緩存
數據字典(用戶信息)也能夠存儲到本地緩存,管理方式同表單定義本地緩存,數據字典變動極少,訪問大;業務表每每只存儲用戶Id,展現須要用戶名稱,因此也存儲到本地緩存中。架構
修改了表單定義信息或者數據字典等,經過Redis通知全部應用程序清空本地緩存,再次讀取數據時,應用程序從數據庫或者接口讀取數據再填充到內存中。若是檢測到Redis斷開鏈接,則直接從數據庫或者接口讀取數據,待Redis恢復,再從內存讀取數據。Redis可由其餘有發佈訂閱中間件服務替換。app
只提供接口定義,對接具體的框架實現具體的邏輯,好比框架使用Abp框架,則從Abp的ICurrentUser讀取用戶當前用戶信息。框架
暫時未遷移,見做者其餘博客描述。函數
對自定義表單數據在租戶和應用級別進行隔離,以支持Saas服務。
Sprite Comon:
自定義表單公共組件/模塊
自定義表單比較核心的內容之一,全部對業務表的常規CRUD,都是經過動態拼接Sql語句完成以及動態參數,這裏面涉及到大量的JObject操做,也就是開發者用得比較多的Newtonsoft.Json組件部份內容。
對Sql的參數查詢,查詢條件定義爲一棵查詢樹,而後根據樹完成Sql查詢條件Where子句的字符串拼接。
也是一棵樹,每個節點爲一種函數或者取值,好比邏輯表達式、日期轉換函數、從方法獲取值、固定值等,根據根節點類型返回對應動態值
自定義表單靈魂所在,有了表單規則定義,才能稱之爲表單引擎,可定義視圖或者表單規則;
好比用戶列表視圖新增按鈕點擊事件,部門樹用戶列表表單部門樹視圖樹節點選中節點變化事件,用戶列表視圖彈出對話框保存事件等,能夠是視圖/表單自己或者控件觸發,也能夠是子表單/子視圖自己或者控件觸發
當某一個規則定義的事件被觸發,可定義執行一系列執行動做,好比"用戶列表視圖新增按鈕點擊事件"觸發時,定義執行設置用戶列表選中部門參數、獲取用戶列表查詢參數定義、執行後端獲取用戶分頁數據方法、將執行結果傳遞給用戶列表等一系列動做。再好比"用戶列表視圖彈出對話框保存事件"事件觸發,驗證用戶Item視圖、驗證經過
自定義表單不須要寫代碼,則驗證就顯得很是的重要了,定義時各個模型以前數據是否正確,規則定義是否正確,運行時參數等是否正確等
表單定義存儲每每是結構化的數據,不少定義信息可能以字符串的方式存儲,但JS前端每每須要Json數據,則須要進行序列化與反序列化操做。
Sprite Object:
自定義表單對象管理,包括對象、屬性、方法
Object管理與業務表須要徹底同步,添加Object時,須要動態生成業務表的建立Sql語句,並在業務庫中建立具體業務表,業務表名稱與Object的Name字段對應,動態Sql是根據Object定義信息拼接Sql語句並在真實業務庫中執行Sql語句。
Object定義表,Property定義字段,自定義表單定義一些審計相關的字段並進行維護,包括Creator,CreationTime,IsDeleted等
定義方法,能夠是執行Sql語句、調用微服務、反射調用,幷包括方法可以成功執行的附加信息定義,並對執行參數進行驗證,對業務表常規的操做已經定義到了自定義表單中,好比Create,Update,Get,List,PageList,TreeList等,不須要格外定義方法
對Object和Property的管理,同步更新業務表表結構,他們之間須要徹底的對應。
Sprite View and Form:
自定義表單最小功能單元定義,好比用戶Item,用戶列表視圖,部門樹視圖等,抽離出Item視圖、列表視圖、樹視圖等各個單元視圖。
自定義表單視圖容器,表單不處理任何具體業務,只是將各類視圖聚合起來統一管理,能夠對視圖進行佈局,能夠定義規則在視圖與視圖之間傳遞數據等。
統必定義不一樣視圖/表單固定區域的控件,好比列表視圖查詢區域控件,列表功能控件,新增,刷新,批量刪除等,或者列表行控件等,再或者表單流程相關控制按鈕
視圖或者表單只定義自身須要的功能,但用到哪些地方自身是不知道的,好比用戶Item視圖放入用戶列表彈出框中,部門樹表單用Card佈局等
按照Grid佈局,定義常規的行列布局管理
表單列或者視圖列的內容能夠是子表單或者子視圖,運行時當發現是子視圖或者子表單,則動態再加載配置的視圖或者表單。
視圖或者表單自己或者任何關聯數據改變,都會從新生成版本號,並通知全部應用對應緩存變動並刪除應用本地緩存,瀏覽器每請求一個頁面,發現視圖或者表單版本號改變了也會更新瀏覽器本地存儲數據。
視圖和表單均可以定義自身規則,規則見上文描述。
宿主框架:
計劃將自定義表單宿主到Abp框架中,Abp框架負責登陸認證,登陸用戶管理等,自定義表單公開Api供使用端調用。
前端(我的是作後端的,前端水平有限):
使用此框架,可替換其餘框架,但各個控件須要作相應的修改。
定義視圖Layout、Item、列表、Tree等視圖。
定義普通表單、Div表單等
對視圖或表單進行包裝,包括Div、對話框、Card佈局等各類包裝。
對前端各類控件進行二次封裝,注入規則,容許觸發事件和執行規則。
IndexedDb存儲視圖/表單定義等信息,每次打開一個頁面時,遍歷全部關聯的視圖和表單Id和版本信息,與後端緩存數據進行比較,不一樣則更新本地緩存。
視圖、表單、控件在建立的時候,都會注入規則,用戶進行某個操做時,若是有對應的事件定義,則找到規則定義,進而執行一系列規定。
爲一棵樹,同後端動態表達式比較相似。
自定義功能:
自定義表單也不可能抽象出全部的數據模型,特殊的業務可編寫代碼,徹底自定義功能實現。後端一些報表或者某些業務模塊,開發人員本身寫業務邏輯,經過微服務或者反射配置方法,執行具體的自定義功能。前端則可編寫不一樣的自定義控件,並註冊到Vue框架中,自定義表單在某個功能上配置自定義控件名稱便可。
前端技術選型不要選擇angular,angular的動態控件比較死板,動態控件不能動態添加指令,還有其餘不少限制,基本上斷了自定義表單的路了。