ASP.NET MVC5+EF6+EasyUI 后台管理系统(53)-工作流设计-我的批阅
前言:由于工作原因工作流一直没时间更新,虽然没有更新,但是批阅和申请差不多,改变一下数据的状态字段就行,有几个园友已经率先完成了
说句实话,一个工作流用文章表达很难,我起初以为这是一个很简单的工作流程,但是要花很多时间考虑很多业务场景,这也是导致停滞不前的原因。
最近空出点时时间更新了皮肤,让系统看起来奇葩一点,顺便也把工作流梳理了一遍,最后跑通了整个流程的多个场景完成从提交表单到审批驳回结束流程
事隔已久需要重新梳理流程,辣么开始吧(由于我自己更新了皮肤,截图与之前有点不一样,但是除UI层之外其他还是一样的)
1.开始代码之前需要更新个枚举,这样不容易出错
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Apps.Models.Enum
{
public enum FlowStateEnum
{
/// <summary>
/// 驳回
/// </summary>
Reject =,
/// <summary>
/// 通过
/// </summary>
Pass = , /// <summary>
/// 进行中
/// </summary>
Progress =, /// <summary>
/// 关闭
/// </summary>
Closed =
} public enum FlowRuleEnum
{
/// <summary>
/// 上级
/// </summary>
Lead =,
/// <summary>
/// 人员
/// </summary>
Person = ,
/// <summary>
/// 自选
/// </summary>
Customer = ,
/// <summary>
/// 职位
/// </summary>
Position = ,
/// <summary>
/// 部门
/// </summary>
Department =,
}
public enum FlowFormLevelEnum
{
/// <summary>
/// 普通
/// </summary>
Ordinary = ,
/// <summary>
/// 重要
/// </summary>
Major = ,
/// <summary>
/// 紧急
/// </summary>
Urgent = } }
FlowStateEnum.cs
有时间就要把那些123换成枚举值
2.审批列表
通过 起草新申请 将获得这个页面的列表
[HttpPost]
public JsonResult GetListByUserId(GridPager pager, string queryStr)
{
List<Flow_FormContentModel> list = formContentBLL.GeExaminetListByUserId(ref pager, queryStr, GetUserId());
var json = new
{
total = pager.totalRows,
rows = (from r in list
select new Flow_FormContentModel()
{ Id = r.Id,
Title = r.Title,
UserId = r.UserId,
FormId = r.FormId,
FormLevel = r.FormLevel,
CreateTime = r.CreateTime,
TimeOut = r.TimeOut,
CurrentStep = formContentBLL.GetCurrentFormStep(r),
CurrentState = formContentBLL.GetCurrentFormState(r),
Action = "<a href='#' title='管理' onclick='ManageFlow(\"" + r.Title + "\",\"" + r.FormId + "\",\"" + r.Id + "\")'>管理</a> | <a href='#' title='图例' onclick='LookFlow(\"" + r.FormId + "\")'>图例</a>" }).ToArray() };
return Json(json);
}
Controller
public List<Flow_FormContentModel> GeExaminetListByUserId(ref GridPager pager, string queryStr, string userId)
{
IQueryable<Flow_FormContent> queryData = null;
if (!string.IsNullOrWhiteSpace(queryStr))
{
queryData = m_Rep.GeExamineListByUserId(db, userId).Where(a => a.Title.Contains(queryStr));
}
else
{
queryData = m_Rep.GeExamineListByUserId(db, userId);
}
pager.totalRows = queryData.Count();
queryData = LinqHelper.SortingAndPaging(queryData, pager.sort, pager.order, pager.page, pager.rows);
return CreateModelList(ref queryData);
}
BLL
public List<Flow_FormContentModel> GeExaminetListByUserId(ref GridPager pager, string queryStr, string userId)
{
IQueryable<Flow_FormContent> queryData = null;
if (!string.IsNullOrWhiteSpace(queryStr))
{
queryData = m_Rep.GeExamineListByUserId(db, userId).Where(a => a.Title.Contains(queryStr));
}
else
{
queryData = m_Rep.GeExamineListByUserId(db, userId);
}
pager.totalRows = queryData.Count();
queryData = LinqHelper.SortingAndPaging(queryData, pager.sort, pager.order, pager.page, pager.rows);
return CreateModelList(ref queryData);
}
private List<Flow_FormContentModel> CreateModelList(ref IQueryable<Flow_FormContent> queryData)
{ List<Flow_FormContentModel> modelList = (from r in queryData
select new Flow_FormContentModel
{
Id = r.Id,
Title = r.Title,
UserId = r.UserId,
FormId = r.FormId,
FormLevel = r.FormLevel,
CreateTime = r.CreateTime,
AttrA = r.AttrA,
AttrB = r.AttrB,
AttrC = r.AttrC,
AttrD = r.AttrD,
AttrE = r.AttrE,
AttrF = r.AttrF,
AttrG = r.AttrG,
AttrH = r.AttrH,
AttrI = r.AttrI,
AttrJ = r.AttrJ,
AttrK = r.AttrK,
AttrL = r.AttrL,
AttrM = r.AttrM,
AttrN = r.AttrN,
AttrO = r.AttrO,
AttrP = r.AttrP,
AttrQ = r.AttrQ,
AttrR = r.AttrR,
AttrS = r.AttrS,
AttrT = r.AttrT,
AttrU = r.AttrU,
AttrV = r.AttrV,
AttrW = r.AttrW,
AttrX = r.AttrX,
AttrY = r.AttrY,
AttrZ = r.AttrZ,
CustomMember = r.CustomMember,
TimeOut = r.TimeOut
}).ToList();
return modelList;
}
DAL
@using Apps.Web.Core;
@using Apps.Common;
@using Apps.Models.Sys;
@using Apps.Models.Enum;
@using Apps.Locale;
@{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Index_Layout.cshtml";
List<permModel> perm = (List<permModel>)ViewBag.Perm;
if (perm == null)
{
perm = new List<permModel>();
}
} <table id="List"></table> <div id="modalwindow" class="easyui-window" data-options="modal:true,closed:true,minimizable:false,shadow:false"></div>
@Html.Partial("~/Views/Shared/_Partial_AutoGrid.cshtml")
<script type="text/javascript">
$(function () {
$('#List').datagrid({
url: '@Url.Action("GetListByUserId")',
width: SetGridWidthSub(),
methord: 'post',
height: SetGridHeightSub(),
fitColumns: true,
sortName: 'CreateTime',
sortOrder: 'desc',
idField: 'Id',
pageSize: ,
pageList: [, , , , ],
pagination: true,
striped: true, //奇偶行是否区分
singleSelect: true,//单选模式
rownumbers: true,//行号
columns: [[
{ field: 'Id', title: '@BaseRes.TitleID', width: , hidden: true },
{ field: 'Title', title: '标题', width: , sortable: true },
{ field: 'UserId', title: '发起用户', width: , sortable: true, hidden: true },
{ field: 'FormId', title: '对应表单', width: , sortable: true, hidden: true },
{ field: 'FormLevel', title: '公文级别', width: , sortable: true,align:'center',
formatter: function (value) {
if(value==@((int)FlowFormLevelEnum.Ordinary)){return "<span>普通</span>";}
if(value==@((int)FlowFormLevelEnum.Major)){return "<span class='color-yellow'>重要/span>";}
if(value==@((int)FlowFormLevelEnum.Urgent)){return "<span class='color-red'>紧急</span>";}
return "";
}
},
{ field: 'CreateTime', title: '@BaseRes.TitleCreateTime', width: , sortable: true},
{ field: 'TimeOut', title: '截至时间', width: , sortable: true, formatter: function (value) { return SubStrYMD(value) } },
{ field: 'CurrentStep', title: '当前环节', width: , sortable: true, align: 'center' },
{
field: 'CurrentState', title: '当前状态', width: , sortable: true, align: 'center',
formatter: function (value, row, index) {
var _pass = "<span class='color-green fa fa-circle'></span>";
var _progress = "<span class='color-blue fa fa-circle'></span>";
var _reject = "<span class='color-red fa fa-circle'></span>";
var _close = "<span class='color-gray fa fa-circle'></span>";
if(value==@((int)FlowStateEnum.Pass)){ return _pass;}
if(value==@((int)FlowStateEnum.Progress)){ return _progress;}
if(value==@((int)FlowStateEnum.Reject)){ return _reject;}
return _close;
} },
{ field: 'Action', title: '操作', width: , sortable: true, align: 'center' }
]]
});
});
//ifram 返回
function frameReturnByClose() {
$("#modalwindow").window('close');
}
function frameReturnByReload(flag) {
if (flag)
$("#List").datagrid('load');
else
$("#List").datagrid('reload');
}
function frameReturnByMes(mes) {
$.messageBox5s('@BaseRes.Tip', mes);
}
function LookFlow(formId) {
$("#modalwindow").html("<iframe width='100%' height='100%' scrolling='auto' frameborder='0' src='@Url.Action("Details")?id=" + formId + "&Ieguid=" + GetGuid() + "'></iframe>");
$("#modalwindow").window({ title: '图例', width: , height: , iconCls: 'fa fa-list' }).window('open');
}
function ManageFlow(title, formId, id) {
var href = "@Url.Action("Edit")?formId=" + formId + "&id=" + id + "&Ieguid=" + GetGuid() + "";
if(isExitsFunction(window.parent.addTab))
{
window.parent.addTab(title, href, 'fa fa-pencil');
}else
{
window.open(href);
}
}
</script>
Index.cshtml
依次添加没有难度
3.审批页面
审批页面基本和我的申请的编辑一致
4.先看看审批的代码执行流程图:
审批有点难度,需要覆盖上面图示流程。以下代码
[HttpPost]
[SupportFilter]
public JsonResult Edit(string Remark, string TheSeal, string FormId, int Flag, string ContentId,string UserList)
{
string stepCheckId = formContentBLL.GetCurrentStepCheckId(FormId, ContentId);
if (stepCheckId == "")
{
return Json(JsonHandler.CreateMessage(, BaseRes.EditFail));
}
Flow_FormContentStepCheckStateModel stepCheckStateModel = stepCheckStateBLL.GetByStepCheckId(stepCheckId);
if (stepCheckStateModel.UserId != GetUserId())
{
return Json(JsonHandler.CreateMessage(, "越权操作!"));
}
stepCheckStateModel.Reamrk = Remark;
stepCheckStateModel.TheSeal = TheSeal;
stepCheckStateModel.CheckFlag = Flag;
if (stepCheckStateBLL.Edit(ref errors, stepCheckStateModel))
{
//获取当前步骤
Flow_FormContentStepCheckModel stepCheckModel = stepCheckBLL.GetById(stepCheckStateModel.StepCheckId);
//获得当前的步骤模板
Flow_StepModel currentStepModel = stepBLL.GetById(stepCheckModel.StepId);
//驳回直接终止审核
if(Flag==(int)FlowStateEnum.Reject)
{
stepCheckModel.State = Flag;
stepCheckModel.StateFlag = false;
stepCheckBLL.Edit(ref errors, stepCheckModel);
//重置所有步骤的状态
stepCheckBLL.ResetCheckStateByFormCententId(ContentId, (int)FlowStateEnum.Progress, (int)FlowStateEnum.Progress);
LogHandler.WriteServiceLog(GetUserId(), "Id" + stepCheckStateModel.Id + ",StepCheckId" + stepCheckStateModel.Reamrk, "成功", "修改", "Flow_FormContentStepCheckState");
return Json(JsonHandler.CreateMessage(, BaseRes.CheckSucceed));
}
else if (currentStepModel.IsAllCheck)
{
//启用会签
//获得同步骤的同批审核人
List<Flow_FormContentStepCheckStateModel> stepCheckStateList = stepCheckStateBLL.GetListByStepCheckId(ref setNoPagerAscById, stepCheckStateModel.StepCheckId);
//查看自己是否是最后一个审核人
bool complete = stepCheckStateList.Where(a => a.CheckFlag == (int)FlowStateEnum.Progress).Count() == ;
if (complete)
{
stepCheckModel.State = Flag;
stepCheckModel.StateFlag = true;
stepCheckBLL.Edit(ref errors, stepCheckModel);
}
else {
//让审核人继续执行这个步骤直到完成
LogHandler.WriteServiceLog(GetUserId(), "Id" + stepCheckStateModel.Id + ",StepCheckId" + stepCheckStateModel.Reamrk, "成功", "修改", "Flow_FormContentStepCheckState");
return Json(JsonHandler.CreateMessage(, BaseRes.CheckSucceed));
}
}
else
{
//不是会签,任何一个审批都通过
stepCheckModel.State = Flag;
stepCheckModel.StateFlag = true;
stepCheckBLL.Edit(ref errors, stepCheckModel);
} if (!stepCheckModel.IsEnd)
{
List<Flow_FormContentStepCheckModel> stepCheckList = stepCheckBLL.GetListByFormId(FormId, ContentId);
int j = ;
for (int i = stepCheckList.Count() - ; i >= ; i--)
{
if (stepCheckId == stepCheckList[i].Id)
{
j = i;
}
}
//查看是否还有下一步步骤
if(j-<=stepCheckList.Count())
{
//查有第二步骤,查看是否是自选
Flow_StepModel stepModel = stepBLL.GetById(stepCheckList[j + ].StepId);
if (stepModel.FlowRule==(int)FlowRuleEnum.Customer)
{
foreach (string userId in UserList.Split(','))
{
//批量建立步骤审核人表
CreateCheckState(stepCheckList[j + ].Id, userId);
}
}
else {
//批量建立审核人员表
foreach (string userId in GetStepCheckMemberList(stepCheckList[j + ].StepId))
{
//批量建立步骤审核人表
CreateCheckState(stepCheckList[j + ].Id, userId);
}
} } } LogHandler.WriteServiceLog(GetUserId(), "Id" + stepCheckStateModel.Id + ",StepCheckId" + stepCheckStateModel.Reamrk, "成功", "修改", "Flow_FormContentStepCheckState");
return Json(JsonHandler.CreateMessage(, BaseRes.CheckSucceed));
}
else
{
string ErrorCol = errors.Error;
LogHandler.WriteServiceLog(GetUserId(), "Id" + stepCheckStateModel.Id + ",StepCheckId" + stepCheckStateModel.Reamrk + "," + ErrorCol, "失败", "修改", "Flow_FormContentStepCheckState");
return Json(JsonHandler.CreateMessage(, BaseRes.CheckFail + ErrorCol));
} }
USE [AppsDB]
GO
/****** Object: StoredProcedure [dbo].[P_Flow_ResetCheckStepState] Script Date: 2016/1/13 21:48:59 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
ALTER PROCEDURE [dbo].[P_Flow_ResetCheckStepState]
@ContentId varchar(),
@CheckState int,
@CheckFlag int
AS
BEGIN
--重新设置当前表单步骤的状态
update Flow_FormContentStepCheck set State=@CheckState where ContentId=@ContentId
--根据表单步骤设置其子下步骤分解的状态
declare FormContentStepCheckState_Cursor cursor scroll for
select Id from Flow_FormContentStepCheckState where StepCheckId in
(
select Id from Flow_FormContentStepCheck where ContentId=@ContentId
)
open FormContentStepCheckState_Cursor
declare @tempId varchar()
fetch next from FormContentStepCheckState_Cursor into @tempId
while @@FETCH_STATUS=
begin
update Flow_FormContentStepCheckState set CheckFlag=@CheckFlag where Id=@tempId
fetch next from FormContentStepCheckState_Cursor into @tempId
end
close FormContentStepCheckState_Cursor
deallocate FormContentStepCheckState_Cursor
END
P_Flow_ResetCheckStepState
涉及重置所有步骤的状态存储过程。
代码分析:
1.获取当前步骤
2.获得当前的步骤模板
3.驳回直接终止审核(重置所有步骤的状态)
4.会签,获得同步骤的同批审核人
ASP.NET MVC5+EF6+EasyUI 后台管理系统(53)-工作流设计-我的批阅的更多相关文章
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(1)-前言与目录(持续更新中...)
开发工具:VS2015(2012以上)+SQL2008R2以上数据库 您可以有偿获取一份最新源码联系QQ:729994997 价格 666RMB 升级后界面效果如下: 任务调度系统界面 http: ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(1)-前言与目录(转)
开发工具:VS2015(2012以上)+SQL2008R2以上数据库 您可以有偿获取一份最新源码联系QQ:729994997 价格 666RMB 升级后界面效果如下: 日程管理 http://ww ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(63)-Excel导入和导出-自定义表模导入
系列目录 前言 上一节使用了LinqToExcel和CloseXML对Excel表进行导入和导出的简单操作,大家可以跳转到上一节查看: ASP.NET MVC5+EF6+EasyUI 后台管理系统(6 ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统-WebApi的用法与调试
1:ASP.NET MVC5+EF6+EasyUI 后台管理系统(1)-WebApi与Unity注入 使用Unity是为了使用我们后台的BLL和DAL层 2:ASP.NET MVC5+EF6+Easy ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(51)-系统升级
系统很久没有更新内容了,期待已久的更新在今天发布了,最近花了2个月的时间每天一点点,从原有系统 MVC4+EF5+UNITY2.X+Quartz 2.0+easyui 1.3.4无缝接入 MVC5+E ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(58)-DAL层重构
系列目录 前言:这是对本文系统一次重要的革新,很久就想要重构数据访问层了,数据访问层重复代码太多.主要集中增删该查每个模块都有,所以本次是为封装相同接口方法 如果你想了解怎么重构普通的接口DAL层请查 ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(34)-文章发布系统①-简要分析
系列目录 最新比较闲,为了学习下Android的开发构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(1)-前言与,虽然有点没有目的的学习,但还是了解了Andro ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(54)-工作流设计-所有流程监控
系列目录 先补充一个平面化登陆页面代码,自己更换喜欢的颜色背景 @using Apps.Common; @{ Layout = null; } <!DOCTYPE html> <ht ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(56)-插件---单文件上传与easyui使用fancybox
系列目录 https://yunpan.cn/cZVeSJ33XSHKZ 访问密码 0fc2 今天整合lightbox插件Fancybox1.3.4,发现1.3.4版本太老了.而目前easyui 1 ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(38)-Easyui-accordion+tree漂亮的菜单导航
系列目录 本节主要知识点是easyui 的手风琴加树结构做菜单导航 有园友抱怨原来菜单非常难看,但是基于原有树形无限级别的设计,没有办法只能已树形展示 先来看原来的效果 改变后的效果,当然我已经做好了 ...
随机推荐
- Python中的多进程与多线程(一)
一.背景 最近在Azkaban的测试工作中,需要在测试环境下模拟线上的调度场景进行稳定性测试.故而重操python旧业,通过python编写脚本来构造类似线上的调度场景.在脚本编写过程中,碰到这样一个 ...
- Java 8五大主要功能为开发者提供了哪些便利?
两年前当Java 8发布后,立即受到了业界的欢迎,因为它大大提高了Java的性能.它独特的卖点是,顾及了编程语言的每一个方面,包括JVM(Java虚拟机)和编译器,并且改良了其它帮助系统. Java是 ...
- HTML 事件(一) 事件的介绍
本篇主要介绍HTML中的事件知识:事件相关术语.DOM事件规范.事件对象. 其他事件文章 1. HTML 事件(一) 事件的介绍 2. HTML 事件(二) 事件的注册与注销 3. HTML 事件(三 ...
- Node.js:进程、子进程与cluster多核处理模块
1.process对象 process对象就是处理与进程相关信息的全局对象,不需要require引用,且是EventEmitter的实例. 获取进程信息 process对象提供了很多的API来获取当前 ...
- [C#] 简单的 Helper 封装 -- RegularExpressionHelper
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- Java 为值传递而不是引用传递
——reference Java is Pass by Value and Not Pass by Reference 其实这个问题是一个非常初级的问题,相关的概念初学者早已掌握,但是时间长了还是容易 ...
- 利用poi导出Excel
import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.r ...
- HTML学习笔记
HTML学习笔记 2016年12月15日整理 Chapter1 URL(scheme://host.domain:port/path/filename) scheme: 定义因特网服务的类型,常见的为 ...
- 安卓GreenDao框架一些进阶用法整理
大致分为以下几个方面: 一些查询指令整理 使用SQL语句进行特殊查询 检测表字段是否存在 数据库升级 数据库表字段赋初始值 一.查询指令整理 1.链式执行的指令 return mDaoSession. ...
- Ubuntu 16.04 安装 arm-linux-gcc 嵌入式交叉编译环境 问题汇总
闲扯: 实习了将近半年一直在做硬件以及底层的驱动,最近要找工作了发现了对linux普遍要求很高,而且工作岗位也非常多,所以最近一些时间在时不时地接触linux. 正文:(我一时兴起开始写博客,准备不充 ...