有關多表單系統的介紹和設計思路
在企業呆了3年,接觸最多的就是表單了,各式各樣的表單,千變萬化,好在它們之間有共同點,就是“表單內容+動作名稱”。企業辦公最常見的業務就是和表單打交道,不管什么請假申請單,權限申請單等等,都需要經過一系列的工作流程來完成它。由于此類業務頻繁,在信息化發展迅速的今天,開發此類系統是很有必要的。
1.多表單系統是什么?
“多表單系統”,顧名思義,就是多個不同形式的表單構成的一個系統,是一個極其抽象的概念。它在企業內部也是一種常見的管理信息系統,每個表單的內容和流程不盡相同,也可以說每個表單是一個子系統。在企業內部,各單位的需求不一致,以至于設計一個通用的表單系統非常困難。盡管不能通用,并且也避免不了新表單的增加和已有表單的修改,但是還是可以抽象出一些共同的東東來,如表單的動作名稱,因此,我們可以將不變的部分抽象出來,以方便維護和增加新需求。
2.多表單系統的需求
(1).需求概述
某單位主管向軟件開發部提出,我們單位有一個申請單,想把它做成Web網頁形式的。流程是:
本部門工程師填寫申請單;
然后本人來審核,審核不通過,則退回申請人重新申請,審核通過,則跑到處理單位主管那里審核;
處理單位主管審核不通過,則退回申請人重新申請,審核通過,則分派給處理人員處理;
處理人員處理完成,則通知處理單位主管結案、通知申請人。
這個表單流程就算跑完了。流程圖:

(2).功能需求
根據以上需求,我們可以設計如下功能:
表單申請:申請表單1、申請表單2、……、申請表單n
表單查詢:申請表單查詢、歷史表單查詢
表單審核:審核工作、代理審核
代理設置:默認代理設置、代理區間設置
表單管理:工作分派、工作清單、處理狀況
報表管理:報表1、報表2、……、報表n
系統管理:表單設置、角色管理、流程管理、處理單位管理、(包括表單共同部分設置)
(3).表單動作需求
有了系統功能結構,但不同表單還有不同動作,概括起來,表單共有以下動作:
申請 (Apply)
修改 (Modify)
重新申請 (Return)
取消 (Cancel)
檢視 (View)
審核 (Sign)
分派 (Assign)
處理 (Process)
撤單 (Revoke)
結案 (Close)
審核可能有好幾步,如上面例子,申請人主管和處理單位主管審核,有的表單有可能在處理單位主管審核前還有好幾步審核。
(4).UI需求
首先看看UI抽象圖:
從UI層面來分析,表單系統也只有“表單內容”(也就是上圖中陰影部分)在變化,各個表單的內容不一樣,有簡單的,有復雜的。簡單的表單,也就是一個實體(可理解成一張數據庫表)就可以滿足要求。復雜的表單,那就需要n個實體的組合才能滿足需要。
關于UI邏輯,對于不同表單動作,有不同的UI界面,也就是要考慮UI的顯示邏輯,例如某審核頁面需要能修改某個欄位,如“希望完成時間”,甚至有的審核頁面可以修改所有內容,另外表單處理的頁面和表單檢視的頁面也不一樣,處理頁要上傳處理報告,還有根據當前登錄者的角色判斷什么欄位顯示,什么欄位不顯示,什么功能顯示,什么功能不顯示,這就是操作權限和UI的聯系。
關于UI需求應該還有很多,沒有想出來,盼謝大家幫忙補充一下。
(5).業務需求
從業務層面來看,每個表單的動作不一樣,也就是每個動作處理的邏輯不同,簡單的動作只要將資料插入一張表或將某個字段值改一下之類的簡單操作,復雜的動作就是要操作n張表,包括判斷,插入,修改,刪除等等。
業務邏輯這東西不知道怎么講好,這塊在寫起來是比較復雜的,也是系統的最難寫的部分,呵呵,個人體會。
(6).變化需求
像這樣的多表單系統,最煩人的就是用戶不斷地變更需求,這在開發企業管理信息系統中是不可避免的。下面就簡單描述一下幾個常見的變化:
增加欄位。這點只有修改代碼,想不修改也難,除非自動生成表單什么的,但是自動生成有其局限性,不能完全滿足需求。
增加功能。這點也要修改代碼。
增加審核流程。這點需要增加頁面和動作處理邏輯了,這點只要系統的擴展性好(采用接口設計),加一個流程也不是很麻煩。
面對需求變化,我們應該有應對變化的方法,盡量減少我們修改代碼的地方。
3.多表單系統的設計
(1)技術框架
我們采取大家熟悉的.NET平臺來構建B/S模式的多表單系統,以下是主要技術框架:
.NET Framework 3.5
ASP.NET WebForm
ASP.NET Ajax
JQuery
由于企業應用需求變更頻繁,實體修改在所難免,為了修改方便,避免更改多處代碼,所以沒有使用ORM技術,而是直接SQL的方式編寫。
(2)目錄結構
首先看看目錄結構圖:
從圖中我們可以看出工程中有三個項目Booking、Common、Workflow。
Common類庫項目是存放系統公共的業務。
Workflow類庫項目是存放系統工作流業務。
Booking項目是WebApplication,幾個主要文件夾和頁面如圖所示。
(3)系統關鍵設計
系統的關鍵技巧就在于,每個表單子系統所有業務都使用上面圖中幾個頁面來完成作業的,不必為每個表單添加相應功能的頁面。每個頁面(除了一些List頁面)有一個Panel控件,其是每個表單內容呈現的容器,真正的內容是通過動態載入Editor和Viewer來實現的,每個表單有兩個用戶控件(Editor和Viewer)和一個Control類,Editor是表單編輯者,Viewer是表單的監視器,Control是表單的控制者。
下面是各控件和頁面之間的繼承關系圖:
圖中的FormControl的FormApply等表單動作方法都是虛方法,真正的業務邏輯是在Editor和Viewer中覆寫的。FormControl中GetShowMode方法默認申請、修改、重新申請頁面為載入Editor控件,其他頁面載入Viewer控件。若其他頁面需載入Editor控件,則可以在每個表單的Control類中覆寫GetShowMode方法。
#p#
下面是幾個主要類別的代碼:
- public class FormControl : BaseControl
- {
- /// < summary>
- /// 取得頁面顯示模型?
- /// < /summary>
- /// < param name="pageType">頁面類型< /param>
- /// < param name="signStep">審核步驟< /param>
- /// < returns>< /returns>
- public virtual string GetShowMode(Type pageType, string signStep)
- {
- if (pageType == typeof(Web.FormApply)
- || pageType == typeof(Web.FormReturn)
- || pageType == typeof(Web.FormModify))
- {
- return "Editor";
- }
- else
- {
- return "Viewer";
- }
- }
- public virtual void FormApply()
- {
- throw new NotImplementedException();
- }
- public virtual void FormReturn()
- {
- throw new NotImplementedException();
- }
- public virtual void FormModify()
- {
- throw new NotImplementedException();
- }
- public virtual void FormCancel(string cancelReason)
- {
- throw new NotImplementedException();
- }
- public virtual void FormSign(bool isAgree, string signComments)
- {
- throw new NotImplementedException();
- }
- public virtual void FormAssign()
- {
- throw new NotImplementedException();
- }
- public virtual void FormProcess()
- {
- throw new NotImplementedException();
- }
- public virtual void FormRevoke(string revokeType, string revokeReason)
- {
- throw new NotImplementedException();
- }
- public virtual void FormClose(string closeType)
- {
- throw new NotImplementedException();
- }
- }
- public class FormControlFactory
- {
- public static FormControl GetControl(string type)
- {
- string className = String.Format("Known.Booking.{0}Control", type);
- Type controlType = Type.GetType(className);
- if (controlType == null)
- {
- return new FormControl();
- //throw new Exception(String.Format("找不到{0}表單控件類型!", type));
- }
- FormControl control = Activator.CreateInstance(controlType) as FormControl;
- if (control == null)
- {
- throw new Exception(String.Format("找不到{0}表單控件類型!", type));
- }
- return control;
- }
- }
- public class FormPage : BasePage
- {
- public string FormNo
- {
- get { return Request.QueryString["formno"]; }
- }
- public string SignStep
- {
- get { return Request.QueryString["step"]; }
- }
- public string SignRole
- {
- get { return Request.QueryString["role"]; }
- }
- public string FormType
- {
- get
- {
- string formType = Request.QueryString["type"];
- if (String.IsNullOrEmpty(formType))
- {
- formType = Request.QueryString["type"];
- }
- return formType;
- }
- }
- public string FormName
- {
- get { return FormType + "申請單"; }
- }
- private FormControl formControl;
- public FormControl FormControl
- {
- get
- {
- if (formControl == null)
- {
- FormControl form = FormControlFactory.GetControl(FormType);
- string format =
- SysSetting.Instance.FormModelPath.EndsWith("/")
- ? "{0}{1}/{2}.ascx"
- : "{0}/{1}/{2}.ascx";
- string modelPath = String.Format(format, SysSetting.Instance.FormModelPath, FormType, form.GetShowMode(PageType, SignStep));
- formControl = LoadControl(modelPath) as FormControl;
- if (formControl == null)
- {
- throw new Exception(String.Format("請確認{0}是否繼承自FormControl!", modelPath));
- }
- }
- return formControl;
- }
- }
- }
- public class Test1Control : FormControl
- {
- public override string GetShowMode(Type pageType, string signStep)
- {
- if (pageType == typeof(FormSign) && signStep == "AL")
- {
- return "Editor";
- }
- return base.GetShowMode(pageType, signStep);
- }
- }
4.這樣開發優劣在哪里?
優勢:新增一個表單時,只需要在UControls下面添加像Test1一樣的控件,表單的內容和邏輯都在控件中實現,這樣寫不需要為每個表單增加相應的頁面,維護時也不用改動多個頁面,這是集中開發,集中維護。
劣勢:這樣寫就將一切邏輯都集中在一起,造成代碼很長,這點局限也可以讓它有所改變,就是將表單對象數據的組裝和呈現寫在控件中,將業務處理抽出來寫在Control類中。
5.結束語
這個系統的設計,我可能沒有講的太透徹,但是原理是很簡單的,就是動態加載用戶控件,我們把控件看成是一個表單對象,表單對象的動作就在控件中實現,頁面中的功能按鈕事件響應控件中的方法。關鍵的一個類就是FormControl,一切表單的動作都定義在此類中。
以上就介紹了多表單系統的設計思路。本文來自閣老的博客:《多表單系統框架設計》。
【編輯推薦】