步驟設計很重要,特別是規則的選擇。
我這里分為幾個規則
1.按自行選擇(在起草時候自行選審批人,比較靈活)
2.按上級(無需指定,當時需要知道用戶的上司是誰,可以在職位管理設置,或者在用戶表直接設置)
3.按職位(選擇職位,直接獲得該職位的人員)
4.按部門(按部門,直接獲得該部分的人員)
5.按人員(設置步驟時就指定人員)
以上用戶必須和部門,職位,上級有所關聯,只要做好一個其實全部都同理
表結構分析:Flow_FormStep中有IsAllCheck字段我設計這個的目的是批量審核,比如我選擇了部門,那么這個步驟要全部門的人都審核通過才算通過否則其中一人審核即可
先創建一個新的表單,必須有新的表單才能設置步驟
OK,新建好表單的字段之后,就可以設置步驟了
步驟設置很簡單,就是一個從表關系,對應了表單的ID。從表可以直接簡單看出關系,但設計其實比較有復雜,當選擇組織架構,按職位,按指定人。都必須彈出窗口來進行選擇,所以還要設計多3個彈出窗口,我這里只設計按人員篩選為例,因為按人員之前在權限管理的角色組管理已經實現
我這里“又”設計成了一個手風琴,具體實現如下
新建步驟和修改步驟=設計步驟
核心Action

[SupportFilter(ActionName = "Edit")] public ActionResult EditStep(string id) { ViewBag.Perm = GetPermission(); Flow_FormModel flowFormModel = m_BLL.GetById(id); List<Flow_StepModel> stepList = stepBLL.GetList(ref setNoPagerDescBySort, flowFormModel.Id);//獲得全部步驟 foreach (var r in stepList)//獲取步驟下面的步驟規則 { r.stepRuleList = GetStepRuleListByStepId(r.Id); } flowFormModel.stepList = stepList;//獲取表單關聯的步驟 ViewBag.Form = flowFormModel; Flow_StepModel model = new Flow_StepModel(); model.FormId = flowFormModel.Id; model.IsEditAttr = true; return View(model); } [HttpPost] [SupportFilter(ActionName = "Edit")] public JsonResult EditStep(Flow_StepModel model) { model.Id = ResultHelper.NewId; if (model != null && ModelState.IsValid) { if (stepBLL.Create(ref errors, model)) { LogHandler.WriteServiceLog(GetUserId(), "Id" + model.Id + ",Name" + model.Name, "成功", "創建", "Flow_Step"); return Json(JsonHandler.CreateMessage(1, Suggestion.InsertSucceed, model.Id)); } else { string ErrorCol = errors.Error; LogHandler.WriteServiceLog(GetUserId(), "Id" + model.Id + ",Name" + model.Name + "," + ErrorCol, "失敗", "創建", "Flow_Step"); return Json(JsonHandler.CreateMessage(0, Suggestion.InsertFail + ErrorCol)); } } else { return Json(JsonHandler.CreateMessage(0, Suggestion.InsertFail)); } }
完整EditStep.cshtml代碼

@model App.Models.Flow.Flow_StepModel @using App.Common; @using App.Models.Flow; @using App.Admin; @using App.Models.Sys; @{ ViewBag.Title = "創建"; Layout = "~/Views/Shared/_Index_LayoutEdit.cshtml"; List<permModel> perm = (List<permModel>)ViewBag.Perm; if (perm == null) { perm = new List<permModel>(); } Flow_FormModel formModel = (Flow_FormModel)ViewBag.Form; } <style> .stepContent table td { padding: 3px; } .lineheight { line-height: 20px; } </style> <script type="text/javascript"> $(function () { $(".icon-delete").click(function () { if ($(this).next("a").attr("class") == "accordion-collapse accordion-expand") { $(this).next("a").trigger("click"); } }); $("#FlowRule").change(function () { $("#Execution").val(""); $("#ExecutionName").val(""); if ($("#FlowRule").val() == "上級" || $("#FlowRule").val() == "自選") { $("#ruleExecution").hide(); } else if ($("#FlowRule").val() == "職位") { $("#selExc").html("審批職位"); $("#ruleExecution").show(); } else if ($("#FlowRule").val() == "部門") { $("#selExc").html("審批部門"); $("#ruleExecution").show(); } else if ($("#FlowRule").val() == "人員") { $("#selExc").html("審批人員"); $("#ruleExecution").show(); } }); $("#selExc").click(function () { var html = $("#selExc").html() if (html == "審批人員") { $("#modalwindow").html("<iframe width='100%' height='100%' scrolling='no' frameborder='0'' src='/SysHelper/UserLookUp'></iframe>"); $("#modalwindow").window({ title: '選擇人員', width: 620, height: 388, iconCls: 'icon-add' }).window('open'); } else if (html == "審批職位") { $("#modalwindow").html("<iframe width='100%' height='100%' scrolling='no' frameborder='0'' src='/SysHelper/PosMulLookUp'></iframe>"); $("#modalwindow").window({ title: '選擇職位', width: 620, height: 388, iconCls: 'icon-add' }).window('open'); } else if (html == "審批部門") { $("#modalwindow").html("<iframe width='100%' height='100%' scrolling='no' frameborder='0'' src='/SysHelper/DepMulLookUp'></iframe>"); $("#modalwindow").window({ title: '選擇部門', width: 320, height: 300, iconCls: 'icon-add' }).window('open'); } }); }); var idx = @(formModel.stepList.Count()); function Create() { if ($("form").valid()) { $.ajax({ url: "@Url.Action("EditStep")", type: "Post", data: $("form").serialize(), dataType: "json", success: function (data) { var stepId = data.value; var currentIDX = idx + 1; $('#stepList').accordion('add', { title: '第 ' + (idx + 1) + ' 步', iconCls: 'pic_244', content: '<div class="stepContent" style="padding:5px"><table class="wid100f"><tr><td style="width:100px;" class="tr">步驟名稱:</td><td>'+$("#Name").val()+'</td></tr><tr><td class="tr">步驟說明:</td><td>'+$("#Remark").val()+'</td></tr></table></div>', tools: [{ iconCls: 'icon-delete', handler: function (i) { DeleteStep(stepId); } }] }); idx++; $("#Sort").val(idx); $(".icon-delete").click(function () { if ($(this).next("a").attr("class") == "accordion-collapse accordion-expand") { $(this).next("a").trigger("click"); } }); } }); } } function DeleteStep(stepId) { $.messager.confirm('提示', '你要刪除當前步驟及條件嗎?', function (r) { if (r) { $.post("@Url.Action("DeleteStep")?id=" + stepId, function (data) {//從數據庫刪除 if (data.type == 1) { var pp = $('#stepList').accordion('getSelected'); if (pp) { var index = $('#stepList').accordion('getPanelIndex', pp) $('#stepList').accordion('remove', index); idx--; //刪除后需要重新設置標題 $("#stepList .panel .panel-title").each(function (i) { $(this).html('第 ' + (i + 1) + ' 步'); }) } $.messageBox5s('提示', data.message); } }, "json"); } }); } function SetSelResult(result,resultName) { $("#Execution").val(result); $("#ExecutionName").val(resultName); } function GetSelResult() { var arrayObj = new Array() arrayObj[0]= $("#Execution").val(); arrayObj[1]= $("#ExecutionName").val(); return arrayObj; } //ifram 返回 function frameReturnByClose() { $("#modalwindow").window('close'); } </script> <div id="modalwindow" class="easyui-window" data-options="modal:true,closed:true,minimizable:false,shadow:false"></div> <table style="height: 393px;"> <tr> <td style="width: 480px; border-right: 1px #ccc solid; vertical-align: top"> @using (Html.BeginForm()) { @Html.HiddenFor(model => model.FormId) @Html.HiddenFor(model => model.Sort) <table class="fromEditTable setTextWidth100" style="width: 100%"> <tbody> <tr> <td style="width: 100px; text-align: right;">表單名稱: </td> <td colspan="2"> @Html.DisplayFor(model => formModel.Name) </td> </tr> <tr> <td style="width: 100px; text-align: right;"> @Html.LabelFor(model => model.Name): </td> <td> @Html.EditorFor(model => model.Name) </td> <td>@Html.ValidationMessageFor(model => model.Name)</td> </tr> <tr> <td style="width: 100px; text-align: right;"> @Html.LabelFor(model => model.Remark): </td> <td colspan="2"> @Html.TextAreaFor(model => model.Remark, new { @style = "width:330px;height:50px" }) </td> </tr> <tr> <td style="width: 100px; text-align: right;"> @Html.LabelFor(model => model.FlowRule): </td> <td> <select id="FlowRule" name="FlowRule"> <option value="自選">自行指定人</option> <option value="上級">按上級</option> <option value="職位">按職位</option> <option value="部門">按部門</option> <option value="人員">按人員</option> </select> </td> <td>@Html.ValidationMessageFor(model => model.FlowRule)</td> </tr> <tr id="ruleExecution" style="display: none"> <td style="width: 100px; text-align: right;"> @Html.LabelFor(model => model.Execution): </td> <td colspan="2"> @Html.HiddenFor(model => model.Execution) <input id="ExecutionName" disabled="disabled" type="text" style="width: 200px" /> <a class="icon-add" id="selExc" href="#" ></a> </td> <td>@Html.ValidationMessageFor(model => model.Execution)</td> </tr> <tr style="display:none"> <td style="width: 100px; text-align: right;"> @Html.LabelFor(model => model.IsAllCheck): </td> <td colspan="2"> @Html.CheckBoxFor(model => model.IsAllCheck, new { @checked = "checked" }) <span class="gray">當規則或者角色被選擇為多人時候,是否啟用多人審核才通過</span> </td> </tr> <tr> <td style="width: 100px; text-align: right;"> @Html.LabelFor(model => model.CompulsoryOver): </td> <td colspan="2"> @Html.CheckBoxFor(model => model.CompulsoryOver) <span class="gray">審核人是否可以強制完成整個流程</span> </td> </tr> <tr> <td style="width: 100px; text-align: right;"> @Html.LabelFor(model => model.IsEditAttr): </td> <td colspan="2"> @Html.CheckBoxFor(model => model.IsEditAttr) <span class="gray">審核者是否可以編輯發起者的附件</span> </td> </tr> <tr> <td style="width: 100px; text-align: right;"></td> <td colspan="2"> <a href="javascript:Create()" class="easyui-linkbutton" data-options="iconCls:'icon-add'">添加步驟</a> </td> </tr> </tbody> </table> } </td> <td style="width: 414px;"> <div id="stepList" class="easyui-accordion" data-options="animate:false" style="width: 414px; height: 393px; overflow-y: auto; border: 0px;"> @for (int i = 0; i < formModel.stepList.Count(); i++) { <div title="第 @(i + 1) 步" data-options="iconCls:'pic_244' ,tools: [{ iconCls: 'icon-delete', handler: function (i) { DeleteStep('@(@formModel.stepList[i].Id)'); } }]"> <div class="stepContent" style="padding: 5px"> <table class="wid100f"> <tr> <td style="width: 100px;" class="tr">步驟名稱:</td> <td>@formModel.stepList[i].Name</td> </tr> <tr> <td class="tr">步驟說明:</td> <td>@formModel.stepList[i].Remark</td> </tr> </table> </div> </div> } </div> </td> </tr> </table>
代碼分析,控制器中的刪除,修改,直接復制代碼生成器生成的即可。
ActionResult EditStep,返回Flow_Step模型的同時也返回了Flow_Form的模型。
我修改了Flow_FormModel,讓他支持自己的從表關系,必須添加以下2段即可
public List<Flow_FormAttrModel> attrList { get; set; }
public List<Flow_StepModel> stepList { get; set; }
注:本節一點懸念和技術點都沒有,就是一個主表和從表的關系,只不過我是換了另一種方式來顯示罷了