一講到工作流筐付,很多人第一反應(yīng)就是這個(gè)東西很深?yuàn)W奥秆,有時(shí)候又覺(jué)得離我們較為遙遠(yuǎn),確實(shí)完善的工作流設(shè)計(jì)很多方面傅是,而正是由于需要兼顧很多方面匪燕,一般通用的工作流都難做到盡善盡美。微軟也提供了幾個(gè)版本的WF框架支持喧笔,也有一些廠家是基于這個(gè)框架基礎(chǔ)上開(kāi)發(fā)的工作流應(yīng)用帽驯。
以前由于項(xiàng)目的需要,參與過(guò)一些工作流的項(xiàng)目開(kāi)發(fā)溃斋,其中有些是基于我簡(jiǎn)易工作流的原理上進(jìn)行拓展的界拦,包括一個(gè)廣州市各區(qū)縣使用的行業(yè)審批業(yè)務(wù)平臺(tái),由于基于自己的流程處理梗劫,界面設(shè)計(jì)、流程流轉(zhuǎn)等方面可以很好符合客戶需求截碴,定制的彈性較好梳侨,缺點(diǎn)是不夠通用,也需要編寫表單部分代碼日丹。
后面由于業(yè)務(wù)的需要走哺,工作流方面的業(yè)務(wù)逐漸顯得迫切,公司是想采用一個(gè)較為通用工作流框架來(lái)組織目前的業(yè)務(wù)哲虾,因此找了廣州一家做工作流的公司丙躏,購(gòu)買了他們的產(chǎn)品择示,雖然號(hào)稱完全通過(guò)后臺(tái)配置,零代碼實(shí)現(xiàn)工作流業(yè)務(wù)表單的處理晒旅,但是由于客戶對(duì)表單的設(shè)計(jì)要求比較多栅盲,有時(shí)候需要結(jié)合一些外部的數(shù)據(jù)接口,流程處理方面也有著進(jìn)一步的需要废恋,這樣可能就打破了他們?cè)瓉?lái)的格局谈秫,導(dǎo)致無(wú)論在表單設(shè)計(jì)、流程配置等方面鱼鼓,都需要購(gòu)買他們工程師的現(xiàn)場(chǎng)服務(wù)拟烫,來(lái)進(jìn)一步完善整個(gè)項(xiàng)目的內(nèi)容,導(dǎo)致整個(gè)項(xiàng)目進(jìn)展緩慢迄本,遭遇水土不服的處境硕淑。
因此感覺(jué),一個(gè)工作流模塊嘉赎,號(hào)稱再?gòu)?qiáng)大置媳,如果不能很好結(jié)合項(xiàng)目應(yīng)用,即使零代碼的功能配置曹阔,也可能使你處于尷尬的境況之中半开,因?yàn)橥ㄟ^(guò)配置,可能在代碼里面平常很容易實(shí)現(xiàn)的表單功能赃份,要通過(guò)零代碼配置寂拆,花費(fèi)的時(shí)間更多更難掌握,因?yàn)榱愦a是有代價(jià)的抓韩,需要您很好利用他們的API纠永,他們的業(yè)務(wù)對(duì)象,有時(shí)候還需要很曲折的摸索參數(shù)谒拴,而這一切可能就是非常致命的弱點(diǎn)尝江。
1、簡(jiǎn)易工作流的設(shè)計(jì)模型
在沒(méi)有第三方工作流模塊的情況下英上,簡(jiǎn)易工作流就是利用數(shù)據(jù)庫(kù)和業(yè)務(wù)對(duì)象之間的協(xié)作關(guān)系炭序,構(gòu)建的一個(gè)半模塊化的流程引擎,它能通過(guò)整合到項(xiàng)目代碼中進(jìn)行更好的融合以便實(shí)現(xiàn)工作流的相關(guān)功能苍日。
首先我們知道惭聂,我們?cè)贠ffice里面創(chuàng)建任何文檔,都有一個(gè)模板的概念相恃,這樣我們方便利用一些現(xiàn)成的數(shù)據(jù)和布局辜纲,工作流也一樣,有一個(gè)流程模板的概念,如下所示耕腾。
然后每個(gè)流程模板见剩,本身會(huì)預(yù)定義了一系列的處理流程,以便在流程實(shí)例里面進(jìn)行不同的處理扫俺,因此流程模板還包含了多個(gè)流程步驟對(duì)象苍苞,他們的關(guān)系構(gòu)成如下。
每個(gè)流程實(shí)例牵舵,除了他們自己的流程數(shù)據(jù)和字段信息外柒啤,它本身還有一個(gè)表單設(shè)計(jì)的問(wèn)題,如費(fèi)用審批畸颅,可能包含填寫的費(fèi)用清單數(shù)據(jù)等担巩,所以流程實(shí)例還應(yīng)該包含了流程的業(yè)務(wù)表單對(duì)象。
這樣他們構(gòu)成了一個(gè)完整的流程業(yè)務(wù)對(duì)象關(guān)系没炒,如下所示涛癌。
2、流程審批的操作
對(duì)于一個(gè)流程處理操作送火,我們知道一般有審批通過(guò)拳话、拒絕、退回到某步驟种吸、轉(zhuǎn)發(fā)到內(nèi)部閱讀弃衍、閱讀,以及包括起草者能撤銷表單呢等操作坚俗,當(dāng)然如果還有一些具體的業(yè)務(wù)镜盯,可能還會(huì)有一些流程的處理才操作,不過(guò)基本上也可以歸結(jié)為上面幾種猖败,只是他們每步處理的數(shù)據(jù)內(nèi)容不同而已速缆。因此審批的操作步驟分類如下所示。
這些操作我們都可以通過(guò)一些界面操作的封裝實(shí)現(xiàn)恩闻,因?yàn)樗麄兓旧隙际峭ㄓ玫囊彰樱覀儌魅胍恍┝鞒蘄D等相關(guān)標(biāo)識(shí)后,就能交給這些標(biāo)準(zhǔn)的操作界面完成了幢尚。
如審批界面如下所示破停,里面包含了通過(guò)、拒絕尉剩,跳回到某步驟辱挥,增加步驟等功能集合。
上面的界面是審批過(guò)程中边涕,對(duì)于某一個(gè)流程處理人員實(shí)現(xiàn)的操作,而有時(shí)候,我們可能需要針對(duì)多個(gè)人進(jìn)行某個(gè)步驟的處理功蜓,如傳遞給內(nèi)部人員進(jìn)行分閱操作园爷,那么就應(yīng)該選定多個(gè)人員進(jìn)行處理,大概的處理界面效果如下所示式撼。
當(dāng)然童社,若申請(qǐng)人的申請(qǐng)單填寫錯(cuò)誤,需要撤銷的話著隆,那么也應(yīng)該有這個(gè)操作扰楼,撤銷表單后,就可以重新填寫表單美浦,然后再次提交進(jìn)行流程弦赖。
3、流程審批的表單處理
在表單的動(dòng)態(tài)設(shè)計(jì)和顯示方面浦辨,一直沒(méi)有好的思路蹬竖,因此我覺(jué)得把流程模塊作為半模塊化即可,把部分界面通過(guò)代碼編寫方式進(jìn)行整合流酬,因此把表單的填寫币厕,表單查看做到用戶控件里面,然后在界面里面引用即可芽腾。
如下面的表單填寫操作界面如下所示旦装,對(duì)不同的流程表單,在項(xiàng)目中增加一個(gè)表單的填寫界面和保存操作即可摊滔。
查看并處理的表單操作阴绢,我們可以先做一個(gè)查看表單信息的界面,然后整合流程的處理工具欄惭载,組合成一個(gè)查看旱函、處理操作一體化的流程操作。
當(dāng)然描滔,如果是能夠有動(dòng)態(tài)設(shè)計(jì)表單棒妨,然后進(jìn)行無(wú)縫整合當(dāng)然更加完美,不過(guò)這樣的操作含长,界面設(shè)計(jì)上也不會(huì)很麻煩券腔,一般普通的開(kāi)發(fā)人員都能勝任,因此拘泞,對(duì)于其他流程表單纷纫,依葫蘆畫瓢就可以完成不同的表單了。
而且里面的工具欄代碼都是可以操作的陪腌,雖然可能集成了不同業(yè)務(wù)的處理方式辱魁,但是我們還是動(dòng)態(tài)進(jìn)行處理烟瞧,處理代碼如下所示。
private void InitToolBar()
{
//如果流程是可以撤銷染簇,且表單狀態(tài)為處理中参滴,那么可以“撤銷”操作可用
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);
//判斷是否需要顯示閱辦狀態(tài)
bool isReadStatus = BLLFactory<ApplyRead>.Instance.IsReadSatus(ApplyId, base.LoginUserInfo.ID);
this.btnRead.ToVisibility(isReadStatus);
//如果不是當(dāng)前審批人隱藏審批按鈕
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;//綁定流程內(nèi)容
button.ImageIndex = 3;
button.LargeImageIndex = 3;
button.PaintStyle = BarItemPaintStyle.CaptionGlyph;
button.ItemClick += new ItemClickEventHandler(button_ItemClick);
this.bar1.AddItem(button);
}
}
}
上面對(duì)于流程步驟的處理,就交給一個(gè)獨(dú)立的按鈕事件進(jìn)行判斷處理即可锻弓,根據(jù)不同的業(yè)務(wù)步驟名稱進(jìn)行不同的處理砾赔,這樣就能夠進(jìn)行很好的控制處理。