一講到工做流,不少人第一反應就是這個東西很深奧,有時候又以爲離咱們較爲遙遠,確實完善的工做流設計不少方面,而正是因爲須要兼顧不少方面,通常通用的工做流都難作到盡善盡美。微軟也提供了幾個版本的WF框架支持,也有一些廠家是基於這個框架基礎上開發的工做流應用。數據庫
之前因爲項目的須要,參與過一些工做流的項目開發,其中有些是基於我簡易工做流的原理上進行拓展的,包括一個廣州市各區縣使用的行業審批業務平臺,因爲基於本身的流程處理,界面設計、流程流轉等方面能夠很好符合客戶需求,定製的彈性較好,缺點是不夠通用,也須要編寫表單部分代碼。框架
後面因爲業務的須要,工做流方面的業務逐漸顯得迫切,公司是想採用一個較爲通用工做流框架來組織目前的業務,所以找了廣州一家作工做流的公司,購買了他們的產品,雖然號稱徹底經過後臺配置,零代碼實現工做流業務表單的處理,可是因爲客戶對錶單的設計要求比較多,有時候須要結合一些外部的數據接口,流程處理方面也有着進一步的須要,這樣可能就打破了他們原來的格局,致使不管在表單設計、流程配置等方面,都須要購買他們工程師的現場服務,來進一步完善整個項目的內容,致使整個項目進展緩慢,遭遇水土不服的處境。模塊化
所以感受,一個工做流模塊,號稱再強大,若是不能很好結合項目應用,即便零代碼的功能配置,也可能使你處於尷尬的境況之中,由於經過配置,可能在代碼裏面日常很容易實現的表單功能,要經過零代碼配置,花費的時間更多更難掌握,由於零代碼是有代價的,須要您很好利用他們的API,他們的業務對象,有時候還須要很曲折的摸索參數,而這一切可能就是很是致命的弱點。工具
在沒有第三方工做流模塊的狀況下,簡易工做流就是利用數據庫和業務對象之間的協做關係,構建的一個半模塊化的流程引擎,它能經過整合到項目代碼中進行更好的融合以便實現工做流的相關功能。佈局
首先咱們知道,咱們在Office裏面建立任何文檔,都有一個模板的概念,這樣咱們方便利用一些現成的數據和佈局,工做流也同樣,有一個流程模板的概念,以下所示。this
而後每一個流程模板,自己會預約義了一系列的處理流程,以便在流程實例裏面進行不一樣的處理,所以流程模板還包含了多個流程步驟對象,他們的關係構成以下。spa
每一個流程實例,除了他們本身的流程數據和字段信息外,它自己還有一個表單設計的問題,如費用審批,可能包含填寫的費用清單數據等,因此流程實例還應該包含了流程的業務表單對象。設計
這樣他們構成了一個完整的流程業務對象關係,以下所示。code
對於一個流程處理操做,咱們知道通常有審批經過、拒絕、退回到某步驟、轉發到內部閱讀、閱讀,以及包括起草者能撤銷表單呢等操做,固然若是還有一些具體的業務,可能還會有一些流程的處理才操做,不過基本上也能夠歸結爲上面幾種,只是他們每步處理的數據內容不一樣而已。所以審批的操做步驟分類以下所示。對象
這些操做咱們均可以經過一些界面操做的封裝實現,由於他們基本上都是通用的,咱們傳入一些流程ID等相關標識後,就能交給這些標準的操做界面完成了。
如審批界面以下所示,裏面包含了經過、拒絕,跳回到某步驟,增長步驟等功能集合。
上面的界面是審批過程當中,對於某一個流程處理人員實現的操做,而有時候,咱們可能須要針對多我的進行某個步驟的處理,如傳遞給內部人員進行分閱操做,那麼就應該選定多我的員進行處理,大概的處理界面效果以下所示。
固然,若申請人的申請單填寫錯誤,須要撤銷的話,那麼也應該有這個操做,撤銷表單後,就能夠從新填寫表單,而後再次提交進行流程。
在表單的動態設計和顯示方面,一直沒有好的思路,所以我以爲把流程模塊做爲半模塊化便可,把部分界面經過代碼編寫方式進行整合,所以把表單的填寫,表單查看作到用戶控件裏面,而後在界面裏面引用便可。
以下面的表單填寫操做界面以下所示,對不一樣的流程表單,在項目中增長一個表單的填寫界面和保存操做便可。
查看並處理的表單操做,咱們能夠先作一個查看錶單信息的界面,而後整合流程的處理工具欄,組合成一個查看、處理操做一體化的流程操做。
固然,若是是可以有動態設計表單,而後進行無縫整合固然更加完美,不過這樣的操做,界面設計上也不會很麻煩,通常普通的開發人員都能勝任,所以,對於其餘流程表單,依葫蘆畫瓢就能夠完成不一樣的表單了。
並且裏面的工具欄代碼都是能夠操做的,雖然可能集成了不一樣業務的處理方式,可是咱們仍是動態進行處理,處理代碼以下所示。
private void InitToolBar() { //若是流程是能夠撤銷,且表單狀態爲處理中,那麼能夠「撤銷」操做可用 bool mayCancel = BLLFactory<AppApply>.Instance.IsApplyMayCancel(ApplyId, base.LoginUserInfo.ID); this.btnCancel.ToVisibility(mayCancel); //可退回從新編輯 bool mayBackToEdit = BLLFactory<AppApply>.Instance.IsApplyMayBackEdit(ApplyId, base.LoginUserInfo.ID); this.btnEdit.ToVisibility(mayBackToEdit); //判斷是否須要顯示閱辦狀態 bool isReadStatus = BLLFactory<ApplyRead>.Instance.IsReadSatus(ApplyId, base.LoginUserInfo.ID); this.btnRead.ToVisibility(isReadStatus); //若是不是當前審批人隱藏審批按鈕 bool canDeal = BLLFactory<BLL.ApplyUser>.Instance.IsCheckPermission(ApplyId, base.LoginUserInfo.ID); if (canDeal) { ApplyFlowInfo flowInfo = BLLFactory<ApplyFlow>.Instance.GetFirstUnHandledFlow(ApplyId); if (flowInfo != null) { string procTypeName = BLLFactory<AppProc>.Instance.GetProcType(flowInfo.ProcType); BarButtonItem button = new BarButtonItem(); button.Caption = procTypeName; button.Name = procTypeName; button.Tag = flowInfo;//綁定流程內容 button.ImageIndex = 3; button.LargeImageIndex = 3; button.PaintStyle = BarItemPaintStyle.CaptionGlyph; button.ItemClick += new ItemClickEventHandler(button_ItemClick); this.bar1.AddItem(button); } } }
上面對於流程步驟的處理,就交給一個獨立的按鈕事件進行判斷處理便可,根據不一樣的業務步驟名稱進行不一樣的處理,這樣就可以進行很好的控制處理。