【技術(shù)】ccFlow工作流UI外殼定制攻略(上)

攻殼機(jī)動(dòng)隊(duì)

(關(guān)鍵字:前端栓辜、Web界面锹锰、SDK模式忘衍、QueryObject位他、ORM映射)

目錄

  • 本攻略的好處 = 5萬(wàn)元+
  • 緣起
  • 起步
  • 外包
  • 目標(biāo)(A)已辦、歸檔部服、申請(qǐng)唆姐,三個(gè)一覽型畫(huà)面
  • (A-1)參考模塊——概念集——關(guān)鍵機(jī)制
    • 【參考模塊】“待辦”計(jì)數(shù)器
    • 【參考模塊】“待辦”UC第一部分:獲得流程記錄集(調(diào)用SDK接口)
    • 【參考模塊】“待辦”UC第二部分:渲染記錄一覽表(單一Table,帶GroupBy)
  • (A-2)新模塊——定制解決
    • 【定制模塊】“已辦”計(jì)數(shù)器廓八、“歸檔”計(jì)數(shù)器
    • 【定制模塊】“歸檔”UC第一部分:獲得流程記錄集(調(diào)用SDK接口)
    • 【定制模塊】“歸檔”UC第二部分:渲染記錄一覽表(單一Table奉芦,帶GroupBy)

本攻略的好處 = 5萬(wàn)元+

5萬(wàn)元,是基于.Net國(guó)產(chǎn)開(kāi)源工作流引擎ccFlow定制Web界面外殼**的官方報(bào)價(jià)(5萬(wàn)/人月剧蹂,或12萬(wàn)/次培訓(xùn))声功。
與筆者之前調(diào)研的jBPMN4涅槃之作Activiti引擎相比的話,ccFlow勝在是中文文檔国夜、自帶符合國(guó)內(nèi)用戶習(xí)慣的Web界面(AppDemo包)减噪、并在國(guó)內(nèi)擁有了一定的用戶群;但就這次UI定制開(kāi)發(fā)經(jīng)歷而言车吹、也存在一些問(wèn)題:

  • 代碼易維護(hù)性易讀性略低(如采購(gòu)官方服務(wù)則不構(gòu)成問(wèn)題)
    如一些關(guān)鍵字的英文拼寫(xiě)錯(cuò)誤,C#的非主流用法(字符串拼接/空判斷醋闭、三元表達(dá)式合理運(yùn)用等)降低了代碼易維護(hù)性窄驹;無(wú)注釋卻又無(wú)實(shí)際作用的代碼段提高了代碼解讀成本
  • 對(duì)BPMN2.0國(guó)際標(biāo)準(zhǔn)的支持是在2015年9月新近追加
  • ccFlow6起取消了對(duì)多國(guó)語(yǔ)言的支持
  • 參考資料尚未基于常見(jiàn)開(kāi)發(fā)用例做系統(tǒng)編排
  • 值得注意的是,ccFlow的開(kāi)源遵循的是GPL協(xié)議证逻,商用則無(wú)法閉源

本文僅供已經(jīng)選型ccFlow并需定制界面部分的技術(shù)者參考乐埠,并不代表作者選型偏好。
將比《黑客帝國(guó)》早了10年的神作《攻殼機(jī)動(dòng)隊(duì)》(不過(guò)比《機(jī)械戰(zhàn)警》要晚出2年)用于“渲染”純技術(shù)向的ccFlow攻略囚企,未免有點(diǎn)小眾了丈咐,不過(guò)興致所至、就順著這個(gè)腦洞筆法來(lái)寫(xiě)也無(wú)妨龙宏。

緣起

巴特面前擺放著一本《開(kāi)源工作流引擎ccFlow——從入門(mén)到迷路》棵逊,早已義體化的雙眼則泛著微光直視前方,空無(wú)而深邃银酗。

距離草薙少佐離開(kāi)公安9課已經(jīng)3年多了辆影,八幡宮研究所外也再次隨風(fēng)吹起山桂花的幽香,“人生一世黍特,草木一秋”蛙讥,雖說(shuō)義體比普通人的肢體強(qiáng)健得多,可是——靈魂呢灭衷?

賽博(Cyber)驅(qū)動(dòng)的仿生人(Android)“審核者”是采用公元2003年就發(fā)布的ccFlow引擎作為其“靈魂”(Ghost)的次慢,最初每家采購(gòu)“審核者”的企業(yè)還需要各自維護(hù)其靈魂的升級(jí)(注:當(dāng)對(duì)靈魂做過(guò)定制時(shí)、這種升級(jí)并不總是簡(jiǎn)單),后來(lái)隨著云時(shí)代到來(lái)迫像、以及基于對(duì)定制影響拓?fù)浞治龅膮^(qū)隔熱更新技術(shù)成熟拭抬,靈魂主體部分已經(jīng)上升到了云端∏置桑“審核者”的靈魂的安全強(qiáng)度造虎,也隨之晉級(jí)到了聯(lián)盟區(qū)塊鏈的級(jí)別。

可是纷闺,人的靈魂呢算凿?

在能真正探明人的靈魂“生從何處來(lái),死至何處去”之前犁功,從邏輯上說(shuō)氓轰,恐怕無(wú)法真正回答得了這個(gè)問(wèn)題。除了草薙素子之外浸卦,畢竟還沒(méi)有原生人(包括由人生育后天經(jīng)過(guò)改造的義體人)署鸡、其靈魂能進(jìn)出于賽博世界;而即使是與(傀儡師的)“賽博自主意識(shí)”融合而變強(qiáng)的草薙的靈魂限嫌,她真正人類的部分是否真地已依附電子媒介活得好好的靴庆,還是已只是被賽博讀取了記憶后的克隆體,都并無(wú)法斷言…

【任務(wù)】審核者UI外殼定制(級(jí)別:E怒医,極安全)
荒卷課長(zhǎng)對(duì)仿生人“審核者”的UI外殼不甚滿意炉抒,提出了新的需求

若是以前,巴特一定不會(huì)對(duì)此種內(nèi)部維護(hù)任務(wù)感興趣稚叹,包管找個(gè)理由丟給戶草了事焰薄。可是這次扒袖,“審核者”……

起步

深吸了一口山桂林間的怡人空氣塞茅,巴特飛速輸入“\\Kusanagi:”(注:草薙的日文讀音)對(duì)“審核者”代碼做了全文檢索〖韭剩“只修改過(guò)這點(diǎn)么…”巴特自語(yǔ)到野瘦,“主要都聚集在界面相關(guān)的頁(yè)面.aspx、控件.ascx…恩蚀同,這里有一個(gè)BP.En包中的QueryObject…”

思考戰(zhàn)車塔奇克馬(Tachikoma)上堆放著其他資料缅刽,它一邊烘焙著已泛金黃的桂花曲奇酥煮著玄米茶、一邊為老友切上了一首遠(yuǎn)野魂音版的《那些花兒》蠢络。

依照慣例衰猛,首先列出我(玩巴特這個(gè)人物通關(guān)后)覺(jué)得有用的資料、便于推斷本攻略的參考價(jià)值刹孔,第三方資料幾近于無(wú):

  • 官方文檔(中文原版):http://ccbpm.mydoc.io/
  • 官方社區(qū):QQ=383352596(ccFlow 19號(hào))啡省,論壇=http://bbs.ccflow.org/
    • 馳騁dotNet與java工作流引擎-表結(jié)構(gòu).xlsx(QQ群共享文件)
  • 開(kāi)源碼庫(kù):http://git.oschina.net/opencc/ccflow/tree/master/
  • 開(kāi)發(fā)環(huán)境構(gòu)筑http://git.oschina.net/opencc/ccflow/wikis/使用svn下載
    • 必須:VStudio2010娜睛、.Net 4.0+、數(shù)據(jù)庫(kù)(推薦MSSQL)
    • 可選:SilverLight 4+(用于流程設(shè)計(jì)器卦睹,官方另有HTML5版本)
    • 可選:IIS(VStudio內(nèi)置ASP.Net開(kāi)發(fā)服務(wù)器就夠用)

選用巴特視角進(jìn)入游戲時(shí)畦戒、“審核者”的開(kāi)發(fā)環(huán)境已經(jīng)構(gòu)筑于一臺(tái)虛擬機(jī)之中,只需登錄后打開(kāi)IDE就能進(jìn)行修改-調(diào)試-發(fā)布的整個(gè)過(guò)程(否則需自行構(gòu)筑结序。草薙作為前任開(kāi)發(fā)者留有一段作業(yè)交接視頻障斋,不過(guò)不知是否時(shí)間匆忙、錄制得并不算完整徐鹤。

“幫我加載一個(gè)版本2的AppDemo包做對(duì)照垃环,另外,給這首歌掛個(gè)單曲循環(huán)吧”巴特關(guān)照塔奇克馬返敬。

【道具】AppDemo包(品質(zhì):Rare)
官方的UI外殼范例遂庄,定制的關(guān)鍵。原始版本原本位于開(kāi)源碼庫(kù)的CCFlow\AppDemo劲赠,因?yàn)椴豢芍脑蛞驯还俜健芭R時(shí)下架”涛目,但9課保留了歷史版本

“嘿,連Demo包目錄名都沒(méi)改就用了…那個(gè)人可真夠敷衍了事啊”巴特隨手復(fù)制出一個(gè)AppNew目錄凛澎,用來(lái)存放這次修改的代碼霹肝,“類重名錯(cuò)誤,給每個(gè).aspx.cs都補(bǔ)上namespace就行预厌“⒙酰”

紅圈自動(dòng)差分提示修改范圍,這次的UI外殼定制就從這里出發(fā)轧叽。

外包

“……單單看這一小段交接視頻和這堆混亂的代碼、資料刊棕,不知道要看到猴年馬月…”

猴年馬月炭晒,按照中國(guó)太陰歷,這個(gè)月正是申猴年午馬月甥角⊥希”塔奇克馬呆萌的聲音解釋到。

“……”悻悻地嚼了一口曲奇酥嗤无,巴特首先接駁上公眾終端QQ模塊震束,白色義眼掃入了383-352-596,QQ外殼上立刻顯示出“ccFlow 19號(hào)”当犯,“申請(qǐng)加入” 巴特語(yǔ)音確認(rèn)道垢村。

很快一個(gè)清脆干練的女聲傳來(lái):“您好,客服編號(hào)‘敏’為您服務(wù)嚎卫,請(qǐng)問(wèn)您是需要使用ccflow嗎嘉栓?”

【人物】CCFlow客服‘敏’(原生人,女性)
CCFlow美女工程師兼首席客服,接通QQ群即可收到聯(lián)系侵佃。
NPC麻昼,保留真人玩家以該角色視角在線的可能。
性格開(kāi)朗馋辈,敬業(yè)認(rèn)真抚芦,專業(yè)嫻熟,不過(guò)也曾有過(guò)因客戶頻繁需求變更迈螟、不得不超期駐扎外包現(xiàn)場(chǎng)的經(jīng)歷叉抡。

經(jīng)過(guò)一番簡(jiǎn)短的詢問(wèn),

“50,000RMB/人月…9課近期不會(huì)有這樣一筆預(yù)算給內(nèi)部項(xiàng)目吧井联〔泛荆”巴特心里盤(pán)算著,已經(jīng)有了結(jié)論烙常。

目標(biāo)(A)已辦轴捎、歸檔、申請(qǐng)蚕脏,三個(gè)一覽型畫(huà)面

荒卷老爹的新需求可以簡(jiǎn)化成這張圖來(lái)滿足:

UI外殼改造目標(biāo)

相當(dāng)于新增兩個(gè)位于不同處理狀態(tài)(已辦侦副、歸檔)、和一個(gè)發(fā)起人是自己的流程的一覽畫(huà)面驼鞭,避免都使用查詢畫(huà)面做入口不夠清晰秦驯;這看起來(lái)也是個(gè)很簡(jiǎn)單的需求么,先理清幾個(gè)概念:

【概念 & 相關(guān)代號(hào)】

  • 發(fā)起人:一個(gè)申請(qǐng)流程實(shí)例的發(fā)起者挣棕。變量名/縮寫(xiě)=Starter
  • 處理人:一個(gè)申請(qǐng)流程實(shí)例的審批者译隘,可以有多人。變量名/縮寫(xiě)=Emp洛心、Worker
  • 我的待辦:流程處于“運(yùn)行中”生命周期狀態(tài)固耘、且當(dāng)前處理人是自己。變量名/縮寫(xiě)=EmpWorks
  • 我的已辦:流程處于“運(yùn)行中”生命周期狀態(tài)词身、且自己已處理過(guò)厅目。別名:在途變量名/縮寫(xiě)=Runing(注:[SIC]原拼寫(xiě)就這樣…)
  • 我的歸檔:流程處于“已完成”生命周期狀態(tài)法严,且自己已處理過(guò)损敷。變量名/縮寫(xiě)=Completed
  • 我的申請(qǐng):流程處于任意生命周期狀態(tài),且發(fā)起人是自己深啤。變量名/縮寫(xiě)=Apply

*提示:部分常量定義位于Components\BP.WF\PubLib\Enumlib.cs拗馒,如WFState.Complete(狀態(tài)=已完成)

(A-1)參考模塊——概念集——關(guān)鍵機(jī)制

編程是一個(gè)需要"實(shí)踐記憶"的活動(dòng),單單看“攻略記錄”可是學(xué)不來(lái)的墓塌。建議玩家讀取CCFlow5.sln項(xiàng)目存檔一起操作瘟忱。

“從啟動(dòng)頁(yè)AppNew\Default.aspx看奥额,這個(gè)AppDemo包原來(lái)采用的還是一種古老的UI外殼技術(shù)——Frame,不知是何用意…”巴特審慎地解讀到访诱。

打開(kāi)左側(cè)導(dǎo)航欄所對(duì)應(yīng)的AppNew\Left.aspx垫挨,掃視當(dāng)前版本從“發(fā)起”到“設(shè)置”的5個(gè)鏈接,很容易便能順藤排摸出這個(gè)UI外殼的線路紋理(如下圖):

UI外殼結(jié)構(gòu)規(guī)則
  • 導(dǎo)航欄鏈接會(huì)指向位于WF\\目錄的某個(gè).aspxUI頁(yè)面触菜,要做一覽型UI需參照“待辦”九榔、也就是~WF\EmpWorksSmall.aspx(如前述EmpWorks是“待辦”的代號(hào),Small則標(biāo)識(shí)了頁(yè)面布局風(fēng)格)
  • WF\\目錄下的UI頁(yè)面其實(shí)都是空殼涡相,注冊(cè)重用了UC控件哲泊,如~WF\UC\EmpWorks.ascx
  • WF\\UC\\目錄下的UC控件類,才包含了真正的流程實(shí)例獲取&渲染的代碼

【道具】第一塊參考模塊:我的待辦UC控件 Get!(一覽型UC)
位于~WF\UC\EmpWorks.ascx.cs催蝗。
主要功能是查詢?nèi)〉?/strong>符合特定條件的流程實(shí)例切威,然后渲染為一覽列表
雖說(shuō)繼承自BP.Web.UC.UCBase3類丙号,追根溯源也是一個(gè)ASP.Net的System.Web.UI.UserControl先朦,從Page_Load()方法開(kāi)始解讀即可。
*提示:UCBase3封裝了共3層UC共通功能犬缨,不過(guò)完成此次UI定制#無(wú)需#去費(fèi)時(shí)解讀它們喳魏。

【參考模塊】“待辦”計(jì)數(shù)器

在解構(gòu)EmpWorks.ascx.cs前先解決掉一個(gè)“小目標(biāo)”練手:可以注意到Left.aspx的“待辦”與“抄送”的右邊各有一個(gè)計(jì)數(shù)器、每過(guò)100秒會(huì)自動(dòng)刷新(0表示無(wú)記錄)怀薛。這也是需要模擬的對(duì)象刺彩。

巴特很容易地從Left.aspx.cs中找到了計(jì)數(shù)器的實(shí)現(xiàn),代碼只有寥寥幾行枝恋,通過(guò)直接SQL文查詢視圖WF_EmpWorks實(shí)現(xiàn)创倔,

//Left.aspx頁(yè)面屬性:“待辦”流程的COUNT計(jì)數(shù)值,只讀焚碌。
public int EmpWorks
{
    get
    {
        string sql = @"SELECT COUNT(*) AS Num FROM WF_EmpWorks 
                        WHERE FK_Emp='" + BP.Web.WebUser.No + "' ";
        return BP.DA.DBAccess.RunSQLReturnValInt(sql); //返回Int型計(jì)數(shù)結(jié)果
    }
}

所涉及的“最小概念集”正好值得梳理一下作為入門(mén)三幻。當(dāng)然如果是大腦電子腦化過(guò)的角色(如荒卷課長(zhǎng))、閱讀時(shí)的短期記憶能更快轉(zhuǎn)化為長(zhǎng)期記憶呐能、這一學(xué)習(xí)環(huán)節(jié)就會(huì)更為簡(jiǎn)單,

【概念】流程相關(guān)編碼
掌握數(shù)據(jù)表/視圖/實(shí)體類解讀技能的前置知識(shí)點(diǎn)抑堡。與倉(cāng)庫(kù)計(jì)件一樣摆出,對(duì)運(yùn)行中/運(yùn)行完成的流程、以及流程中的每個(gè)(環(huán)節(jié))節(jié)點(diǎn)首妖,都會(huì)用“編碼”作標(biāo)識(shí)偎漫。

  • WorkID:動(dòng)態(tài)自增序列號(hào),Int64型有缆、全局唯一象踊。一個(gè)流程啟動(dòng)后(運(yùn)行時(shí))生成温亲,標(biāo)識(shí)該流程實(shí)例,所有流程表單杯矩、節(jié)點(diǎn)表單的主鍵都使用該值栈虚。別名:OID
  • 流程編碼:靜態(tài)概念史隆。三位數(shù)String型編號(hào)(最大999)魂务,標(biāo)識(shí)某種流程(如“072:預(yù)算外攻殼更換申請(qǐng)”)。常用于字段FK_Flow(FK=外鍵)
  • 節(jié)點(diǎn)編碼:靜態(tài)概念泌射。流程編碼(e.g.001)+節(jié)點(diǎn)ID(兩位數(shù)Int粘姜,最大99),表示某種流程中的某個(gè)節(jié)點(diǎn)(如“07201:發(fā)起”(預(yù)算外攻殼更換申請(qǐng))熔酷,不同流程中的節(jié)點(diǎn)允許重名)孤紧。常用于字段FK_Node(FK=外鍵)

【道具】第一張數(shù)據(jù)表/視圖:WF_EmpWorks
開(kāi)發(fā)環(huán)境中已有名為ccport的數(shù)據(jù)庫(kù),保管著開(kāi)發(fā)用的數(shù)據(jù)表/視圖拒秘。
WF_EmpWorks是其中專門(mén)為“待辦”流程配置的視圖(用到WF_GenerWorkFlowWF_GenerWorkerlist兩張核心數(shù)據(jù)表号显,篩選條件為IsEnable = 1 AND IsPass = 0(表示未辦理)

  • 數(shù)據(jù)庫(kù)配置:項(xiàng)目的Web.configAppSettings下有AppCenterDSNAppCenterDBType

  • 數(shù)據(jù)庫(kù)命名規(guī)范【重要】

    • Sys前綴=系統(tǒng)表,將用到的是Sys_MapDataSys_MapAttr映射表(任務(wù)后半段分析)
    • Port前綴=組織結(jié)構(gòu)翼抠,如Port_Emp(人員表咙轩,Emp代表Employee)、Port_Dept(部門(mén)表)
    • WF前綴=流程規(guī)則描述阴颖,尤其是WF_GenerXxx系列是流程運(yùn)行控制表活喊,如WF_EmpWorks所用到的WF_GenerWorkFlowWF_GenerWorkerlist,分別維護(hù)著所有運(yùn)行中流程實(shí)例的細(xì)節(jié)量愧、和每個(gè)流程節(jié)點(diǎn)的處理者信息(如IsPass表示是否已被處理者審核通過(guò))钾菊。
    • V前綴=國(guó)際慣例視圖的前綴應(yīng)為V_,卻也有多個(gè)原因不明的例外(如WF_EmpWorks視圖的命名就是)
    • ND前綴=節(jié)點(diǎn)表單(NDxxxxx)偎肃、流程報(bào)表(NDxxxRpt)煞烫、或流程軌跡表(NDxxxTrack)。本次UI外殼任務(wù)不涉及累颂,但屬于基礎(chǔ)知識(shí)滞详。
      當(dāng)CCFlow處于“軌跡模式”時(shí),編輯創(chuàng)建一個(gè)節(jié)點(diǎn)時(shí)就會(huì)創(chuàng)建一個(gè)表與此節(jié)點(diǎn)相對(duì)應(yīng)紊馏,便于記錄節(jié)點(diǎn)級(jí)別的數(shù)據(jù)變化(例如“ND07201:預(yù)算外攻殼更換申請(qǐng)發(fā)起節(jié)點(diǎn)表”包含了該環(huán)節(jié)的表單數(shù)據(jù))料饥。另一個(gè)“合并模式”不常用,不創(chuàng)建節(jié)點(diǎn)表朱监、更快岸啡、但不記錄細(xì)節(jié)。
  • 常見(jiàn)字段含義

    • 每個(gè)節(jié)點(diǎn)表都會(huì)有的字段:OID:工作ID赫编,RDT:記錄日期巡蘸,Rec:記錄人奋隶,CDT:完成時(shí)間,NodeState:節(jié)點(diǎn)狀態(tài)
    • 開(kāi)始節(jié)點(diǎn)(才)有的字段: WFState:流程狀態(tài)

    *提示:字段列的命名有些頗為費(fèi)解悦荒,可通過(guò)列屬性確認(rèn)其含義(如圖)

“計(jì)數(shù)器居然是后臺(tái)代碼直接SQL文讀的唯欣,沒(méi)至少弄個(gè)REST方式的封裝感覺(jué)對(duì)前后端分離不很友好啊” 巴特吐槽到,“算了我也沒(méi)功夫自己弄一個(gè)逾冬∈蚰簦”

接著就開(kāi)始解剖第一個(gè)大的參考模塊EmpWork.ascx.cs控件,如前所述從Page_Load()方法開(kāi)始身腻,

//Step1.調(diào)用SDK接口獲得“待辦”流程的記錄集(DataTable型)賦值給成員變量
dt = BP.WF.Dev2Interface.DB_GenerEmpWorksOfDataTable();

//Step2.基于成員變量dt進(jìn)行一覽表渲染
this.BindList();
【參考模塊】“待辦”UC第一部分:獲得流程記錄集(調(diào)用SDK接口)

首先F12切換到DB_GenerEmpWorksOfDataTable()方法的定義产还,可以看到針對(duì)是否授權(quán)(IsAuthorize)及何種授權(quán)有若干分支,這里#無(wú)需#對(duì)此多糾結(jié)嘀趟、只需參考到其本質(zhì)其實(shí)也是在對(duì)WF_EmpWorks做SQL查詢即可(吐槽:與計(jì)數(shù)器那邊用的同一視圖脐区,一覽這邊卻有著多重條件分歧,兩邊竟然還能匹配得上…不深究)

【武器】BP.WF.Dev2Interface下的
DB_GenerEmpWorksOfDataTable()她按、DB_GenerRuning()等接口
SDK模式開(kāi)發(fā)接口層牛隅。其中DB_GenerXxx系列與完成本次定制任務(wù)有關(guān),其特點(diǎn)是簡(jiǎn)單粗暴易于上手且輸出夠猛烈酌泰,接近于半自動(dòng)型AK-b48媒佣。
輸入:當(dāng)前用戶的編碼BP.Web.WebUser.No (全局變量,string型)
輸出:當(dāng)前用戶的待辦陵刹、已辦等不同特征流程的記錄集(DataTable型)
*注意:用了SELECT * 所以相關(guān)表中所有字段均可在結(jié)果記錄中用到

【道具】BP包
ccFlow官方的核心工具箱默伍,多格。BP標(biāo)志代表"Brain Power"(見(jiàn)官方文檔)衰琐,宣稱著電子腦陣營(yíng)的強(qiáng)大[*需注明出處]也糊。

  • BP.En30:基層實(shí)體類庫(kù),用處多多
    1.數(shù)據(jù)庫(kù)交互
    2.實(shí)體類:實(shí)體的工作基于Map映射(即ORM)
    3.其他數(shù)據(jù)源交互:XML文件等
    4.組織結(jié)構(gòu)類庫(kù):人員羡宙、部門(mén)狸剃、崗位,并提供登錄控制
  • BP.WFv4:W/F(WorkFlow)相關(guān)
* **`BP.WF.Dev2Interface`:SDK模式開(kāi)發(fā)接口層**狗热,僅`DB_GenerXxx`系列有用钞馁。完整列表則可參見(jiàn)[CCFlow5接口說(shuō)明文檔](http://pan.baidu.com/s/1c29QF08)`(官方文檔似乎經(jīng)過(guò)了…削減(?),鏈接到9課緩存吧)`
  • BP.Web.Control:公共Web組件庫(kù)

*相比之下匿刮,CCFlow包下的 WF指攒、WF.UC、WF.Rpt.UC(Rpt代表報(bào)表)更偏應(yīng)用層

【參考模塊】“待辦”UC第二部分:渲染記錄一覽表(單一Table僻焚,帶GroupBy)

得到DataTable記錄集之后轉(zhuǎn)到this.BindList()方法做渲染,迎面猝不及防便是一大段冗余代碼——當(dāng)按照PRI做GroupBy時(shí)將跳轉(zhuǎn)到另一個(gè)BindList_PRI()膝擂,而這兩套BindList卻是猶如雙生子般類似虑啤。

“古老的冗余型防壁么…迫使意圖定制修改者必須肉眼多解讀一倍以上內(nèi)容隙弛,并增加后續(xù)維護(hù)所需耗費(fèi)的精力∧剑” 這里其實(shí)#無(wú)需#閱讀BindList_PRI()全闷,只需參照BindList()就能仿制出自己的UI外殼。

【概念】GroupBy分組
一覽型UC的唯一特色萍启。如下圖总珠,當(dāng)前是按照流程名稱(FlowName)分組的(例如“多次簽證申請(qǐng)”),如果點(diǎn)擊表頭中的狀態(tài)勘纯,會(huì)切換到按狀態(tài)(WFState)分組局服,而狀態(tài)列則會(huì)被當(dāng)前的分組字段流程名稱所替代。


伏筆劇透:這里所能參考到的GroupBy實(shí)現(xiàn)驳遵、其實(shí)只是偽實(shí)現(xiàn)…淫奔。玩家可檢查代碼看能否發(fā)現(xiàn)疑點(diǎn)所在。

巴特點(diǎn)起了一支煙又被塔奇克馬迅速撲滅堤结,只能抿了口玄米茶嘆道:“這BindList()中搞了半天無(wú)非是遍歷dt集合唆迁,把每條dr記錄渲染成行,唯一特色無(wú)非就是得兼顧到GroupBy的因素竞穷,卻又冗余地做成了(GroupBy列數(shù)+1)x記錄數(shù)的遍歷復(fù)雜度唐责,而且對(duì)一次讀入的記錄數(shù)并沒(méi)有限制…”

“嘛,算了瘾带,數(shù)據(jù)庫(kù)里如果真積壓著幾千條“待辦流程”影響到顯示鼠哥、卡死的也就不只是一個(gè)UI外殼而是N個(gè)人腦了。實(shí)際環(huán)境中還是可以用月弛,在新UI外殼里面改掉也就是了肴盏。”

(A-2)新模塊——定制解決

解讀現(xiàn)有模塊完成帽衙,開(kāi)始定制新模塊菜皂。

先從“我的已辦”(=在途)的UI外殼入手。這里有一個(gè)捷徑厉萝,

【道具】AppDemoLigerUI包(品質(zhì):Rare)
同樣是官方的UI外殼范例恍飘,同樣因?yàn)椴豢芍脑虮还俜健芭R時(shí)下架”了,但9課保留了歷史版本谴垫。
除了使用LigerUI技術(shù)風(fēng)格更接近主流外章母,其中還包括了一些AppDemo包中被省略了的內(nèi)容。
*LigerUI技術(shù)本身并不推薦使用翩剪,優(yōu)缺點(diǎn)可參考這篇乳怎。技術(shù)選型真少不了甄別比較、無(wú)論面向靈魂的還是外殼前弯。

AppDemoLigerUI包的導(dǎo)航欄UI

導(dǎo)航鏈接指向\WF\RuningSmall.aspx頁(yè)面蚪缀,“在途的英文…是Runing么秫逝?”巴特也不禁疑惑道,電子眼識(shí)別出是拼寫(xiě)混淆術(shù)询枚。

【概念】英語(yǔ)拼寫(xiě)混淆術(shù)(Spelling Obfuscation)
相比傳統(tǒng)的代碼混淆技術(shù)(Code Obfuscation)违帆,英語(yǔ)拼寫(xiě)混淆術(shù)在非英語(yǔ)母語(yǔ)尤其東亞地區(qū)運(yùn)用較多。相比前者金蜀,拼寫(xiě)混淆更容易打擊解讀者信心刷后,令其懷疑究竟是誤解了單詞含義還是用眼過(guò)度。眩暈對(duì)象0.5秒渊抄,并有小概率引發(fā)爆笑尝胆。

  • 這次任務(wù)會(huì)遇見(jiàn)的混淆/非常規(guī)代號(hào)、及其真實(shí)含義:
    IsExitsContral(=IsExistsControl..)抒线,Runing(=Running)班巩,Sta(=Status),Cash(=Cache!)嘶炭,LGType(=LoGicType)
【定制模塊】“已辦”計(jì)數(shù)器抱慌、“歸檔”計(jì)數(shù)器

“我的已辦”的左側(cè)欄計(jì)數(shù)器,如法炮制的話眨猎,是否也需自己編制一個(gè)WF_Runing視圖呢抑进?答案是不需要。

可以參考到~WF\UC\\下面其實(shí)已經(jīng)有一個(gè)“我的已辦”一覽型UC控件睡陪,它所用到的記錄查詢SDK接口是BP.WF.Dev2Interface.DB_GenerRuning()寺渗,參考就能鐫刻出計(jì)數(shù)器所需的SQL銘文了:

public int Runing
{
    get
    {
        string sql = String.Format(@"SELECT * FROM WF_GenerWorkerList 
                WHERE FK_Emp='{1}' and IsPass=1 AND IsEnable=1", BP.Web.WebUser.No)
        return BP.DA.DBAccess.RunSQLReturnValInt(sql);
    }
}

編譯運(yùn)行即可看到第一個(gè)UI定制成果——導(dǎo)航欄中“我的已辦”計(jì)數(shù)值已正確顯示。

而“我的已辦”一覽UC控件(~\WF\UC\Runing.ascx.cs)經(jīng)驗(yàn)證風(fēng)格與“我的待辦”相同兰迫,可直接鏈接上使用信殊。

快速進(jìn)入下一個(gè)一覽畫(huà)面的打造——“我的歸檔”(Completed)

首先仍是計(jì)數(shù)器部分汁果。這次發(fā)現(xiàn)~WF\UC\\目錄下也沒(méi)有現(xiàn)成的UC控件可用了涡拘,沒(méi)有現(xiàn)成的DB_GenerXxx接口參考,得自己分析SQL銘文据德。

“還是用WF_GenerWorkFlowWF_GenerWorkerList定制出一張‘我的歸檔’視圖鳄乏?”這是巴特的第一反應(yīng)。玩家只需記住一條線索棘利,“我的歸檔”的特征橱野、是WFState=3(3:Complete),然而你在WF_GenerWorkFlowWF_GenerWorkerList中卻找不到一條WFState=3的記錄善玫。

巴特這時(shí)會(huì)切入CCFlow官方社區(qū)查詢水援,再次獲得客服‘敏’的回答,可這次卻是包含著錯(cuò)誤信息的(“History也在WF_GenerWorkFlow中”)

客服‘敏’對(duì)WF_GenerWorkFlow的解釋隱含誤導(dǎo)

正確的解答在這邊——當(dāng)然深度玩家可嘗試自行在資料堆中查找裹唆,

官方文檔:高級(jí)開(kāi)發(fā) > 流程實(shí)例生命周期 > 流程完成后(數(shù)據(jù)歸檔)

節(jié)點(diǎn)數(shù)據(jù)表(NDxxx)的話就意味著有多少種流程就有多少個(gè)誓斥、包括“審核者”上線后新建的,該怎么組成視圖呢许帐?

其實(shí)數(shù)據(jù)庫(kù)中一共也沒(méi)多少視圖,很快就能發(fā)現(xiàn)一張名為V_FlowData的視圖毕谴,包含著WFState字段成畦、并且已經(jīng)是所有NDxxRpt數(shù)據(jù)表的拼接;在“審核者”中新建流程時(shí)涝开,流程編輯器也會(huì)維護(hù)修改該視圖循帐。

【道具】核心視圖:V_FlowData(可改裝為:V_FlowDataPlus)
V_FlowData是數(shù)據(jù)庫(kù)中唯一無(wú)差別維護(hù)著所有種類所有狀態(tài)的流程實(shí)例的視圖(包括“已完成”狀態(tài)的流程實(shí)例),但只維護(hù)被所有種類流程共有的基本字段信息舀武、不包含表單字段業(yè)務(wù)信息拄养。
V_FlowDataPlus是通過(guò)對(duì)V_FlowData增設(shè)一覽型UI所需的三個(gè)名稱字段構(gòu)成:FlowName(流程名稱), FlowStarterName(發(fā)起人名稱), FlowEndNodeName(結(jié)束節(jié)點(diǎn)名稱)

  • 重要字段
    • OID:即WorkID,唯一標(biāo)識(shí)一個(gè)流程實(shí)例
    • FK_Flow:外鍵银舱,流程ID瘪匿,關(guān)聯(lián)到WF_Flow
    • FK_Dept:外鍵,部門(mén)ID寻馏,關(guān)聯(lián)到Port_Dept
    • FlowStarter:流程的發(fā)起者的ID
    • FlowEmps:流程的處理者的ID組棋弥,多人,以特定格式分隔
    • FlowEndNode:流程的結(jié)束節(jié)點(diǎn)ID诚欠,關(guān)聯(lián)到WF_Node

獲得了V_FlowData之后顽染,“我的歸檔”的計(jì)數(shù)器也就輕松完成了。官方文檔會(huì)告訴你“流程狀態(tài)=1轰绵、表示已完成”粉寞,你可以選擇相信它、然后用實(shí)際查詢結(jié)果教育自己左腔。

public int Completed
{
    get
    {
        string sql = @"SELECT COUNT(*) AS Num FROM V_FlowData 
                WHERE WFState=3 AND FlowEmps LIKE '%@" + BP.Web.WebUser.No + ",%' ";
        return BP.DA.DBAccess.RunSQLReturnValInt(sql);
    }
}

“我的歸檔”從UI畫(huà)面~WF\Completed.aspx到UC控件~WF\UC\Completed.ascx都需要自己創(chuàng)建(參照“UI外殼結(jié)構(gòu)規(guī)則”)唧垦,遵照風(fēng)格,真正的代碼也藏到UC控件中翔悠。

【定制模塊】“歸檔”UC第一部分:獲得流程記錄集(調(diào)用SDK接口)

需創(chuàng)建一個(gè)BP.WF.Dev2Interface.DB_GenerCompleted()方法业崖,參考“我的已辦”中用到的DB_GenerRuning()更為方便。

“少佐對(duì)BP.WF.Dev2Interface.DB_GenerRuning()已做過(guò)了精簡(jiǎn)蓄愁,”巴特發(fā)現(xiàn)双炕,

//Kusanagi: 1.コーディングスタイル改善 2.ソーティング
WF.Port.WFEmp emp = (WebUser.IsAuthorize) ? new Port.WFEmp(WebUser.No) : null;
sql = "SELECT a.WorkID FROM WF_GenerWorkFlow A, WF_GenerWorkerlist B WHERE "
        + (string.IsNullOrEmpty(fk_flowNo) ? "" : ("A.FK_Flow='" + fk_flowNo + "' AND "))
        + "A.WorkID=B.WorkID AND B.IsEnable=1 AND B.IsPass=1"
        + " AND B.FK_Emp='" + WebUser.No + "'"
        + (emp == null ? "" : (" AND A.FK_Flow IN " + emp.AuthorFlows));

GenerWorkFlows gwfs = new GenerWorkFlows();
gwfs.RetrieveInSQL(GenerWorkFlowAttr.WorkID, "(" + sql + ")", "RDT", true);
return gwfs.ToDataTableField();

“懶如伊人都忍不住要對(duì)這Coding Style出手改了吧~還有補(bǔ)了Sorting排序〈樽ィ”巴特從注釋中讀到妇斤。

值得注意的是,這里首次出現(xiàn)了ORM映射,就是GenerWorkFlows.RetrieveInSQL()這段(排序也是改在這里)站超。

【概念】ORM映射(Object-Relational Mapping)
實(shí)體類與關(guān)系型數(shù)據(jù)表之間的映射荸恕。以GenerWorkFlow實(shí)體類為例,

  • 實(shí)體類都繼承自BP.En.Entitiy基類(或其輔助用子類)
  • 實(shí)體類都有一個(gè)集合類(如GenerWorkFlows)死相,并繼承自集合型的BP.En.Entities類(或其輔助用子類)
  • 實(shí)體基類的集合型BP.En.Entities中融求,已實(shí)現(xiàn)了從相應(yīng)關(guān)系數(shù)據(jù)表讀取實(shí)體實(shí)例集合的公開(kāi)方法(如RetrieveInSQL()
  • 實(shí)體基類BP.En.Entity中,已實(shí)現(xiàn)了對(duì)應(yīng)到單條關(guān)系數(shù)據(jù)表記錄的CRUD(增刪改查)操作
  • 實(shí)體類中必須重載的算撮,就是只讀屬性EnMap(實(shí)體映射)生宛,需在這里聲明所關(guān)聯(lián)的關(guān)系數(shù)據(jù)表的名稱(如Map map = new Map("WF_GenerWorkFlow"))、追加需映射到實(shí)體類屬性集的數(shù)據(jù)表字段(如map.AddTBIntPK(GenerWorkFlowAttr.WorkID, 0, "WorkID", true, true)添加了從WorkID字段到同名屬性的映射肮柜,并且從方法名可以看出陷舅,該字段可用輸入框渲染(TB)是數(shù)值型(Int)且是主鍵(PK))
  • 實(shí)體類的集合類中必須實(shí)現(xiàn)的,只有只讀屬性GetNewEntity审洞,通常只需象工廠類一樣new一個(gè)實(shí)體類的實(shí)例即可
  • 基本屬性(如GenerWorkFlowAttr中所列出)什么的莱睁、只屬于具體實(shí)體類的個(gè)性/表相,它們會(huì)在EnMapget實(shí)現(xiàn)中被一一映射到關(guān)系數(shù)據(jù)表的字段上

*提示:映射思想是CCFlow的核心靈魂之一(官方語(yǔ))芒澜,貫穿于方方面面:類映射仰剿、UI展現(xiàn)映射、字段關(guān)系映射撰糠、查詢條件映射酥馍、方法映射等等。

“我們用到的是V_FlowData視圖阅酪,需要自己配一個(gè)FlowData實(shí)體類咯旨袒?”巴特繼續(xù)自言自語(yǔ)著…至少有塔奇克馬做伴、做定制開(kāi)發(fā)類任務(wù)時(shí)也都并不孤單吧术辐。

“匹配顯示已有一個(gè)實(shí)體類的代碼中包含了V_FlowData”塔奇克馬提供了一條有價(jià)值的智能助言(IntelliHint)砚尽。

“哦?打開(kāi)看看——果然辉词!實(shí)體類BP.WF.FlowData”巴特為這個(gè)小確幸不由輕揚(yáng)了下嘴角——“你裝的這付義眼有些忒大必孤,大到都無(wú)法再透你的心靈”草薙在時(shí)會(huì)這樣調(diào)侃他。

“我的心靈…守護(hù)天使瑞躺,如果你仍舊在線敷搪,就請(qǐng)繼續(xù)給我些幸運(yùn)吧〈鄙冢”

//BP.WF.FlowData - revision 2
public override Map EnMap
{
    get
    {
        if (this._enMap != null)
            return this._enMap;

        //關(guān)系數(shù)據(jù)表映射
        Map map = new Map("V_FlowDataPlus");  //為獲得名稱使用V_FlowData的改裝體
        ......
        //字段-屬性映射
        map.AddTBIntPKOID(FlowDataAttr.OID, "WorkID");
        map.AddTBInt(FlowDataAttr.FID, 0, "FID", false, false);
        map.AddDDLEntities(FlowDataAttr.FK_Dept, null, "部門(mén)", new Port.Depts(), false);
        map.AddTBString(FlowDataAttr.Title, null, "標(biāo)題", true, true, 0, 100, 100);
        map.AddTBString(FlowDataAttr.FlowStarter, null, "發(fā)起人", true, true, 0, 100, 100);
        ......
        map.AddSearchAttr(FlowDataAttr.FK_NY);
        map.AddSearchAttr(FlowDataAttr.WFState);
        map.AddSearchAttr(FlowDataAttr.FK_Flow);
        map.AddHidden(FlowDataAttr.FlowEmps, " LIKE ", "'%@@WebUser.No%'");

        //方法映射
        RefMethod rm = new RefMethod();
        rm.Title = "工作報(bào)告";
        rm.ClassMethodName = this.ToString() + ".DoOpen";

        this._enMap = map;
        return this._enMap;
    }
}

ORM問(wèn)題解決赡勘,于是BP.WF.Dev2Interface.DB_GenerCompleted()就可以寫(xiě)成,

WF.Port.WFEmp emp = (WebUser.IsAuthorize) ? new Port.WFEmp(WebUser.No) : null;
sql = "SELECT OID FROM V_FlowData WHERE "
        + (string.IsNullOrEmpty(fk_flowNo) ? "" : ("FK_Flow='" + fk_flowNo + "' AND "))
        + "WFState = " + WFState.Complete
        + " AND FlowEmps LIKE '%@" + WebUser.No + ",%'"
        + (emp == null ? "" : (" AND FK_Flow IN " + emp.AuthorFlows));

FlowDatas fds = new FlowDatas();
fds.RetrieveInSQL(FlowDataAttr.OID, "(" + sql + ")", "FlowStartRDT", true);
return fds.ToDataTableField();

當(dāng)山桂花飄香時(shí)捞镰,那段混合著斑駁陽(yáng)光颯颯白衣與那個(gè)人盈盈笑聲的影像就會(huì)再次被加載到記憶里闸与。

“這是真實(shí)的存在毙替,不是幻覺(jué)迷宮〖#”

(未完待續(xù)厂画,繼半自動(dòng)單兵武器站BP.WF.Dev2Interface之后,可組裝中型武器BP.En.QueryObject將登場(chǎng))

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末拷邢,一起剝皮案震驚了整個(gè)濱河市袱院,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌瞭稼,老刑警劉巖坑填,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異弛姜,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)妖枚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)廷臼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人绝页,你說(shuō)我怎么就攤上這事荠商。” “怎么了续誉?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵莱没,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我酷鸦,道長(zhǎng)饰躲,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任臼隔,我火速辦了婚禮嘹裂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘摔握。我一直安慰自己寄狼,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布氨淌。 她就那樣靜靜地躺著泊愧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪盛正。 梳的紋絲不亂的頭發(fā)上删咱,一...
    開(kāi)封第一講書(shū)人閱讀 49,764評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音蛮艰,去河邊找鬼腋腮。 笑死雀彼,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的即寡。 我是一名探鬼主播徊哑,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼聪富!你這毒婦竟也來(lái)了艾恼?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤命贴,失蹤者是張志新(化名)和其女友劉穎囤捻,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體奸披,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡昏名,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了阵面。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片轻局。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖样刷,靈堂內(nèi)的尸體忽然破棺而出仑扑,到底是詐尸還是另有隱情,我是刑警寧澤置鼻,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布镇饮,位于F島的核電站,受9級(jí)特大地震影響箕母,放射性物質(zhì)發(fā)生泄漏储藐。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一司蔬、第九天 我趴在偏房一處隱蔽的房頂上張望邑茄。 院中可真熱鬧,春花似錦俊啼、人聲如沸肺缕。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)同木。三九已至,卻和暖如春跛十,著一層夾襖步出監(jiān)牢的瞬間彤路,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工芥映, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留洲尊,地道東北人远豺。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像坞嘀,于是被迫代替她去往敵國(guó)和親躯护。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容