系列目錄javascript
建立新表單以後,咱們就能夠起草申請了,申請按照嚴格的表單步驟和分支執行。html
起草的同時,咱們分解流轉的規則中的審批人並保存,具體流程以下java
接下來建立DrafContoller控制器,此控制器只有2個頁面,一個Create(起草頁面)Index(表單列表)ajax
表單列表顯示我的想法,我是根據分類直接獲取其下表單,即Flow_Type下的Flow_Form算法
public ActionResult Index() { List<Flow_TypeModel> list = m_BLL.GetList(ref setNoPagerAscBySort, ""); foreach (var v in list) { v.formList = new List<Flow_FormModel>(); List<Flow_FormModel> formList = formBLL.GetListByTypeId(v.Id); v.formList = formList; } ViewBag.DrafList = list; return View(); }
@using App.Admin; @using App.Common; @using App.Models.Sys; @using App.Lang; @{ ViewBag.Title = "起草申請"; Layout = "~/Views/Shared/_Index_Layout.cshtml"; } <div style="padding:10px;"> @foreach (var v in (List<App.Models.Flow.Flow_TypeModel>)ViewBag.DrafList) { <fieldset class="accordion" style="margin: 0px; padding: 0px; padding-bottom:10px; margin-bottom: 10px;"> <legend class="tabs-header panel-title" style="border: 0px; padding: 5px; margin: 20px; margin-bottom:5px;">@v.Name</legend> <div style="padding-left:20px;color:#808080">備註:@v.Remark</div> <div style="padding: 0px 20px 40px 20px;"> @foreach (var r in v.formList) { <div style="float: left; width: 120px; margin:10px 0px 10px 0px;"> <a href="javascript:void(0)" class="easyui-linkbutton" data-options="plain:true,iconCls:'icon-details'" onclick="javascript:window.parent.addTab('@r.Name','/Flow/Draf/Create?id=@r.Id','icon-add')">@r.Name</a> </div> } </div> </fieldset> } </div>
上面的表單列表簡單完成以後,進入最複雜的一步,獲取字段組成表單json
獲取字段組成表單能夠作得很漂亮,即在設計表單的時候設計佈局,直接讀取佈局,不然按照表單的控件順序讀取佈局。mvc
具體對好比下:ide
VS佈局
明顯前者更利於打印和閱讀。咱們先佈局第二種形式ui
根據表Flow_FormContent設置Create頁面的固定頭尾
@model App.Models.Flow.Flow_FormContentModel @using App.Common; @using App.Models.Flow; @using App.Admin; @using App.Models.Sys; @{ ViewBag.Title = "建立"; Layout = "~/Views/Shared/_Index_Layout.cshtml"; List<permModel> perm = (List<permModel>)ViewBag.Perm; if (perm == null) { perm = new List<permModel>(); } } <script src="~/Scripts/My97DatePicker/WdatePicker.js"></script> <script type="text/javascript"> $(function () { $("#btnSave").click(function () { if ($("#Title").val() == "") { $.messageBox5s("提示", "表單標題必須填寫!"); return false; } if (CheckForm()) { $.ajax({ url: "@Url.Action("Create")", type: "Post", data: $("form").serialize(), dataType: "json", success: function (data) { if (data.type == 1) { $.messageBox5s("添加成功!", data.message); $("#btnSave").hide(); } else { window.parent.frameReturnByMes(data.message); } } }); } return false; }); $("#btnReturn").click(function () { if ($("#btnSave").is(":hidden")) { window.parent.CloseCurrentWin(); } else { $.messager.confirm('提示', '沒有保存的數據將會丟失,你肯定要返回嗎?', function (r) { if (r) { window.parent.CloseCurrentWin(); } }); } }); }); </script> @Html.Raw(ViewBag.HtmlJS) <div class="mvctool "> @Html.ToolButton("btnSave", "icon-save", "保存", perm, "Create", true) @Html.ToolButton("btnReturn", "icon-return", "返回",false) </div> @using (Html.BeginForm()) { <table class="fromEditTable setTextWidth300"> <tbody> @Html.HiddenFor(model => model.Id) @Html.HiddenFor(model => model.FormId) @Html.HiddenFor(model => model.UserId) <input id="CreateTime" type="hidden" name="CreateTime" value="2000-1-1" /> <input id="TimeOut" type="hidden" name="TimeOut" value="2111-1-1" /> <tr> <td style="width:100px; text-align:right;"> @Html.LabelFor(model => model.Title): </td> <td style="width:310px"> @Html.EditorFor(model => model.Title) </td> <td>@Html.ValidationMessageFor(model => model.Title)</td> </tr> @Html.Raw(ViewBag.Html) <tr><td style='width:100px; text-align:right;'>緊急程度 :</td><td><select name="FormLevel" id="FormLevel"><option value="普通">普通</option><option value="重要">重要</option><option value="緊急">緊急</option></select></td></tr> </tbody> </table> }
代碼
@Html.Raw(ViewBag.Html)就是咱們的表單核心部分。因此Create必須返回ViewBag.Html內容爲設計表單的JS和字段
這裏代碼有點彆扭,由於有26個字段,因此要循環26個字段去判斷是否有關聯來讀取。很麻煩。能夠用反射來作能夠省不少代碼
先建立一個類,這個類是輔助工做流的通用類
using App.Models.Flow; using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace App.Admin { public class FlowHelper { //獲取指定類型的HTML表單 public string GetInput(string type, string id, string attrNo) { string str = ""; if (type == "文本") { str = "<input id='" + id + "' name='" + attrNo + "' type='text' />"; } else if (type == "多行文本") { str = "<textarea id='" + id + "' name='" + attrNo + "' cols='60' style='height: 80px;' rows='5'></textarea>"; } else if (type == "日期") { str = "<input type='text' name='" + attrNo + "' class='Wdate' onfocus=\"WdatePicker({dateFmt:'yyyy-MM-dd'})\" id='" + id + "' />"; } else if (type == "時間") { str = "<input type='text' name='" + attrNo + "' class='Wdate' onfocus=\"WdatePicker({dateFmt:'yyyy-MM-dd HH:mm'})\" id='" + id + "' />"; } else if (type == "數字") { str = "<input type='number' name='" + attrNo + "' id='" + id + "' />"; } return str; } } }
[SupportFilter] public ActionResult Create(string id) { ViewBag.Perm = GetPermission(); ViewBag.Html = ExceHtmlJs(id); Flow_FormContentModel model = new Flow_FormContentModel(); model.FormId = id; return View(model); } //根據設定公文,生成表單及控制條件 private string ExceHtmlJs(string id) { //定義一個sb爲生成HTML表單 StringBuilder sbHtml = new StringBuilder(); StringBuilder sbJS = new StringBuilder(); sbJS.Append("<script type='text/javascript'>function CheckForm(){"); Flow_FormModel model = formBLL.GetById(id); #region 判斷流程是否有字段,有就生成HTML表單 //得到對象的類型,model Type formType = model.GetType(); //查找名稱爲"A-Z"的屬性 string[] arrStr = { "AttrA", "AttrB", "AttrC", "AttrD", "AttrE", "AttrF", "AttrG", "AttrH", "AttrI", "AttrJ", "AttrK" , "AttrL", "AttrM", "AttrN", "AttrO", "AttrP", "AttrQ", "AttrR", "AttrS", "AttrT", "AttrU" , "AttrV", "AttrW", "AttrX", "AttrY", "AttrZ"}; foreach (string str in arrStr) { object o = formType.GetProperty(str).GetValue(model, null); if (o != null) { sbHtml.Append(JuageExc(o.ToString(), str, ref sbJS)); } } #endregion sbJS.Append("return true}</script>"); ViewBag.HtmlJS = sbJS.ToString(); return sbHtml.ToString(); } private string JuageExc(string attr, string no,ref StringBuilder sbJS) { if (!string.IsNullOrEmpty(attr)) { return GetHtml(attr, no, ref sbJS); } return ""; } //獲取指定名稱的HTML表單 private string GetHtml(string id, string no, ref StringBuilder sbJS) { StringBuilder sb = new StringBuilder(); Flow_FormAttrModel attrModel = formAttrBLL.GetById(id); sb.AppendFormat("<tr><td style='width:100px; text-align:right;'>{0} :</td>", attrModel.Title); //獲取指定類型的HTML表單 sb.AppendFormat("<td>{0}</td></tr>", new FlowHelper().GetInput(attrModel.AttrType, attrModel.Name, no)); sbJS.Append(attrModel.CheckJS); return sb.ToString(); }
引入命名空間using System;
代碼結構:上面沒有什麼特殊算法。主要是26個字段用反射來讀取。本身細細消化一下就行
應該能夠用了,點擊請假申請看看!
完成。能夠起草新的申請了。接下來就是保存申請...
保存是最複雜的一步要取得表單,分解步驟,分解分支,最後指定審覈人
看Create方法
public JsonResult Create(Flow_FormContentModel model) { model.Id = ResultHelper.NewId; model.CreateTime = ResultHelper.NowTime; model.UserId = GetUserId(); if (model != null && ModelState.IsValid) { if (formContentBLL.Create(ref errors, model)) { //當前的Form模版 Flow_FormModel formModel = formBLL.GetById(model.FormId); //建立成功後把步驟取出 List<Flow_StepModel> stepModelList = stepBLL.GetList(ref setNoPagerAscBySort,model.FormId); //查詢步驟 bool IsEnd = true; foreach (Flow_StepModel stepModel in stepModelList) { List<Flow_StepRuleModel> stepRuleModelList = stepRuleBLL.GetList(stepModel.Id); //獲取規則判斷流轉方向 foreach (Flow_StepRuleModel stepRuleModel in stepRuleModelList) { string val =new FlowHelper().GetFormAttrVal(stepRuleModel.AttrId, formModel, model); //有知足不流程結束的條件 if (!JudgeVal(stepRuleModel.AttrId, val, stepRuleModel.Operator, stepRuleModel.Result)) { if (stepRuleModel.NextStep != "0") { IsEnd = false; } } } //插入步驟審覈表 Flow_FormContentStepCheckModel stepCheckModel = new Flow_FormContentStepCheckModel(); stepCheckModel.Id = ResultHelper.NewId; stepCheckModel.ContentId = model.Id; stepCheckModel.StepId = stepModel.Id; stepCheckModel.State = 2;//0不經過1經過2審覈中 stepCheckModel.StateFlag = false;//true此步驟審覈完成 stepCheckModel.CreateTime = ResultHelper.NowTime; stepCheckModel.IsEnd = IsEnd;//是否流程的最後一步 if (stepCheckBLL.Create(ref errors, stepCheckModel))//新建步驟成功 { //得到流轉規則下的審覈人員 List<string> userIdList = GetStepCheckMemberList(stepModel.Id,model.Id); foreach (string userId in userIdList) { //批量創建步驟審覈人表 Flow_FormContentStepCheckStateModel stepCheckModelState = new Flow_FormContentStepCheckStateModel(); stepCheckModelState.Id = ResultHelper.NewId; stepCheckModelState.StepCheckId = stepCheckModel.Id; stepCheckModelState.UserId = userId; stepCheckModelState.CheckFlag = 2; stepCheckModelState.Reamrk = ""; stepCheckModelState.TheSeal = ""; stepCheckModelState.CreateTime = ResultHelper.NowTime; stepCheckStateBLL.Create(ref errors, stepCheckModelState); } } if (IsEnd)//若是是最後一步就無須要下面繼續了 { break; } IsEnd = true; } LogHandler.WriteServiceLog(GetUserId(), "Id" + model.Id + ",AttrA" + model.AttrA, "成功", "建立", "Flow_FormContent"); return Json(JsonHandler.CreateMessage(1, Suggestion.InsertSucceed)); } else { string ErrorCol = errors.Error; LogHandler.WriteServiceLog(GetUserId(), "Id" + model.Id + ",AttrA" + model.AttrA + "," + ErrorCol, "失敗", "建立", "Flow_FormContent"); return Json(JsonHandler.CreateMessage(0, Suggestion.InsertFail + ErrorCol)); } } else { return Json(JsonHandler.CreateMessage(0, Suggestion.InsertFail)); } }
//無分頁獲取 public GridPager setNoPagerAscBySort = new GridPager() { rows = 1000, page = 1, sort = "Sort", order = "asc" }; //無分頁獲取 public GridPager setNoPagerDescBySort = new GridPager() { rows = 1000, page = 1, sort = "Sort", order = "desc" };
using System.Collections.Generic; using System.Linq; using System.Web.Mvc; using App.Common; using App.IBLL; using App.Models.Sys; using Microsoft.Practices.Unity; using App.Flow.IBLL; using App.Models.Flow; using System.Text; using System; namespace App.Admin.Areas.Flow.Controllers { public class DrafController : BaseController { [Dependency] public ISysUserBLL userBLL { get; set; } [Dependency] public IFlow_TypeBLL m_BLL { get; set; } [Dependency] public IFlow_FormBLL formBLL { get; set; } [Dependency] public IFlow_FormAttrBLL formAttrBLL { get; set; } [Dependency] public IFlow_FormContentBLL formContentBLL { get; set; } [Dependency] public IFlow_StepBLL stepBLL { get; set; } [Dependency] public IFlow_StepRuleBLL stepRuleBLL { get; set; } [Dependency] public IFlow_FormContentStepCheckBLL stepCheckBLL { get; set; } [Dependency] public IFlow_FormContentStepCheckStateBLL stepCheckStateBLL { get; set; } ValidationErrors errors = new ValidationErrors(); public ActionResult Index() { List<Flow_TypeModel> list = m_BLL.GetList(ref setNoPagerAscBySort, ""); foreach (var v in list) { v.formList = new List<Flow_FormModel>(); List<Flow_FormModel> formList = formBLL.GetListByTypeId(v.Id); v.formList = formList; } ViewBag.DrafList = list; return View(); } [HttpPost] [SupportFilter] public JsonResult Create(Flow_FormContentModel model) { model.Id = ResultHelper.NewId; model.CreateTime = ResultHelper.NowTime; model.UserId = GetUserId(); if (model != null && ModelState.IsValid) { if (formContentBLL.Create(ref errors, model)) { //當前的Form模版 Flow_FormModel formModel = formBLL.GetById(model.FormId); //建立成功後把步驟取出 List<Flow_StepModel> stepModelList = stepBLL.GetList(ref setNoPagerAscBySort,model.FormId); //查詢步驟 bool IsEnd = true; foreach (Flow_StepModel stepModel in stepModelList) { List<Flow_StepRuleModel> stepRuleModelList = stepRuleBLL.GetList(stepModel.Id); //獲取規則判斷流轉方向 foreach (Flow_StepRuleModel stepRuleModel in stepRuleModelList) { string val =new FlowHelper().GetFormAttrVal(stepRuleModel.AttrId, formModel, model); //有知足流程結束的條件 if (!JudgeVal(stepRuleModel.AttrId, val, stepRuleModel.Operator, stepRuleModel.Result)) { if (stepRuleModel.NextStep != "0") { IsEnd = false; } } } //插入步驟審覈表 Flow_FormContentStepCheckModel stepCheckModel = new Flow_FormContentStepCheckModel(); stepCheckModel.Id = ResultHelper.NewId; stepCheckModel.ContentId = model.Id; stepCheckModel.StepId = stepModel.Id; stepCheckModel.State = 2;//0不經過1經過2審覈中 stepCheckModel.StateFlag = false;//true此步驟審覈完成 stepCheckModel.CreateTime = ResultHelper.NowTime; stepCheckModel.IsEnd = IsEnd;//是否流程的最後一步 if (stepCheckBLL.Create(ref errors, stepCheckModel))//新建步驟成功 { //得到流轉規則下的審覈人員 List<string> userIdList = GetStepCheckMemberList(stepModel.Id,model.Id); foreach (string userId in userIdList) { //批量創建步驟審覈人表 Flow_FormContentStepCheckStateModel stepCheckModelState = new Flow_FormContentStepCheckStateModel(); stepCheckModelState.Id = ResultHelper.NewId; stepCheckModelState.StepCheckId = stepCheckModel.Id; stepCheckModelState.UserId = userId; stepCheckModelState.CheckFlag = 2; stepCheckModelState.Reamrk = ""; stepCheckModelState.TheSeal = ""; stepCheckModelState.CreateTime = ResultHelper.NowTime; stepCheckStateBLL.Create(ref errors, stepCheckModelState); } } if (IsEnd)//若是是最後一步就無須要下面繼續了 { break; } IsEnd = true; } LogHandler.WriteServiceLog(GetUserId(), "Id" + model.Id + ",AttrA" + model.AttrA, "成功", "建立", "Flow_FormContent"); return Json(JsonHandler.CreateMessage(1, Suggestion.InsertSucceed)); } else { string ErrorCol = errors.Error; LogHandler.WriteServiceLog(GetUserId(), "Id" + model.Id + ",AttrA" + model.AttrA + "," + ErrorCol, "失敗", "建立", "Flow_FormContent"); return Json(JsonHandler.CreateMessage(0, Suggestion.InsertFail + ErrorCol)); } } else { return Json(JsonHandler.CreateMessage(0, Suggestion.InsertFail)); } } public List<string> GetStepCheckMemberList(string stepId,string formContentId) { List<string> userModelList = new List<string>(); Flow_StepModel model = stepBLL.GetById(stepId); if (model.FlowRule == "上級") { SysUserModel userModel = userBLL.GetById(GetUserId()); string[] array = userModel.Lead.Split(',');//得到領導,可能有多個領導 foreach (string str in array) { userModelList.Add(str); } } else if (model.FlowRule == "職位") { string[] array = model.Execution.Split(',');//得到領導,可能有多個領導 foreach (string str in array) { List<SysUserModel> userList = userBLL.GetListByPosId(str); foreach (SysUserModel userModel in userList) { userModelList.Add(userModel.Id); } } } else if (model.FlowRule == "部門") { GridPager pager = new GridPager() { rows = 10000, page = 1, sort = "Id", order = "desc" }; string[] array = model.Execution.Split(',');//得到領導,可能有多個領導 foreach (string str in array) { List<SysUserModel> userList = userBLL.GetUserByDepId(ref pager, str, ""); foreach (SysUserModel userModel in userList) { userModelList.Add(userModel.Id); } } } else if (model.FlowRule == "人員") { string[] array = model.Execution.Split(',');//得到領導,可能有多個領導 foreach (string str in array) { userModelList.Add(str); } } else if (model.FlowRule == "自選") { string users = formContentBLL.GetById(formContentId).CustomMember; string[] array = users.Split(',');//得到領導,可能有多個領導 foreach (string str in array) { userModelList.Add(str); } } return userModelList; } //對比 private bool JudgeVal(string attrId, string rVal, string cVal, string lVal) { string attrType = formAttrBLL.GetById(attrId).AttrType; return new FlowHelper().Judge(attrType, rVal, cVal, lVal); } [SupportFilter] public ActionResult Create(string id) { ViewBag.Perm = GetPermission(); ViewBag.Html = ExceHtmlJs(id); Flow_FormContentModel model = new Flow_FormContentModel(); model.FormId = id; return View(model); } //根據設定公文,生成表單及控制條件 private string ExceHtmlJs(string id) { //定義一個sb爲生成HTML表單 StringBuilder sbHtml = new StringBuilder(); StringBuilder sbJS = new StringBuilder(); sbJS.Append("<script type='text/javascript'>function CheckForm(){"); Flow_FormModel model = formBLL.GetById(id); #region 判斷流程是否有字段,有就生成HTML表單 //得到對象的類型,model Type formType = model.GetType(); //查找名稱爲"A-Z"的屬性 string[] arrStr = { "AttrA", "AttrB", "AttrC", "AttrD", "AttrE", "AttrF", "AttrG", "AttrH", "AttrI", "AttrJ", "AttrK" , "AttrL", "AttrM", "AttrN", "AttrO", "AttrP", "AttrQ", "AttrR", "AttrS", "AttrT", "AttrU" , "AttrV", "AttrW", "AttrX", "AttrY", "AttrZ"}; foreach (string str in arrStr) { object o = formType.GetProperty(str).GetValue(model, null); if (o != null) { sbHtml.Append(JuageExc(o.ToString(), str, ref sbJS)); } } #endregion sbJS.Append("return true}</script>"); ViewBag.HtmlJS = sbJS.ToString(); return sbHtml.ToString(); } private string JuageExc(string attr, string no,ref StringBuilder sbJS) { if (!string.IsNullOrEmpty(attr)) { return GetHtml(attr, no, ref sbJS); } return ""; } //獲取指定名稱的HTML表單 private string GetHtml(string id, string no, ref StringBuilder sbJS) { StringBuilder sb = new StringBuilder(); Flow_FormAttrModel attrModel = formAttrBLL.GetById(id); sb.AppendFormat("<tr><td style='width:100px; text-align:right;'>{0} :</td>", attrModel.Title); //獲取指定類型的HTML表單 sb.AppendFormat("<td>{0}</td></tr>", new FlowHelper().GetInput(attrModel.AttrType, attrModel.Name, no)); sbJS.Append(attrModel.CheckJS); return sb.ToString(); } } }
public List<string> GetStepCheckMemberList(string stepId,string formContentId) { List<string> userModelList = new List<string>(); Flow_StepModel model = stepBLL.GetById(stepId); if (model.FlowRule == "上級") { SysUserModel userModel = userBLL.GetById(GetUserId()); string[] array = userModel.Lead.Split(',');//得到領導,可能有多個領導 foreach (string str in array) { userModelList.Add(str); } } else if (model.FlowRule == "職位") { string[] array = model.Execution.Split(',');//得到領導,可能有多個領導 foreach (string str in array) { List<SysUserModel> userList = userBLL.GetListByPosId(str); foreach (SysUserModel userModel in userList) { userModelList.Add(userModel.Id); } } } else if (model.FlowRule == "部門") { GridPager pager = new GridPager() { rows = 10000, page = 1, sort = "Id", order = "desc" }; string[] array = model.Execution.Split(',');//得到領導,可能有多個領導 foreach (string str in array) { List<SysUserModel> userList = userBLL.GetUserByDepId(ref pager, str, ""); foreach (SysUserModel userModel in userList) { userModelList.Add(userModel.Id); } } } else if (model.FlowRule == "人員") { string[] array = model.Execution.Split(',');//得到領導,可能有多個領導 foreach (string str in array) { userModelList.Add(str); } } else if (model.FlowRule == "自選") { string users = formContentBLL.GetById(formContentId).CustomMember; string[] array = users.Split(',');//得到領導,可能有多個領導 foreach (string str in array) { userModelList.Add(str); } } return userModelList; }
代碼分析:
1.填充表單內容Flow_FormContent
2.得到表單步驟Flow_Step
3.根據步驟得到Flow_StepRule
4.取得判斷流程方向的標示(是否結束)
5.插入審批人
須要慢慢消化,分解過程比較複雜