系列目录

前言:由于工作原因工作流一直没时间更新,虽然没有更新,但是批阅和申请差不多,改变一下数据的状态字段就行,有几个园友已经率先完成了

说句实话,一个工作流用文章表达很难,我起初以为这是一个很简单的工作流程,但是要花很多时间考虑很多业务场景,这也是导致停滞不前的原因。

最近空出点时时间更新了皮肤,让系统看起来奇葩一点,顺便也把工作流梳理了一遍,最后跑通了整个流程的多个场景完成从提交表单到审批驳回结束流程

事隔已久需要重新梳理流程,辣么开始吧(由于我自己更新了皮肤,截图与之前有点不一样,但是除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)-工作流设计-我的批阅的更多相关文章

  1. ASP.NET MVC5+EF6+EasyUI 后台管理系统(1)-前言与目录(持续更新中...)

    开发工具:VS2015(2012以上)+SQL2008R2以上数据库  您可以有偿获取一份最新源码联系QQ:729994997 价格 666RMB  升级后界面效果如下: 任务调度系统界面 http: ...

  2. ASP.NET MVC5+EF6+EasyUI 后台管理系统(1)-前言与目录(转)

    开发工具:VS2015(2012以上)+SQL2008R2以上数据库 您可以有偿获取一份最新源码联系QQ:729994997 价格 666RMB 升级后界面效果如下: 日程管理   http://ww ...

  3. ASP.NET MVC5+EF6+EasyUI 后台管理系统(63)-Excel导入和导出-自定义表模导入

    系列目录 前言 上一节使用了LinqToExcel和CloseXML对Excel表进行导入和导出的简单操作,大家可以跳转到上一节查看: ASP.NET MVC5+EF6+EasyUI 后台管理系统(6 ...

  4. ASP.NET MVC5+EF6+EasyUI 后台管理系统-WebApi的用法与调试

    1:ASP.NET MVC5+EF6+EasyUI 后台管理系统(1)-WebApi与Unity注入 使用Unity是为了使用我们后台的BLL和DAL层 2:ASP.NET MVC5+EF6+Easy ...

  5. ASP.NET MVC5+EF6+EasyUI 后台管理系统(51)-系统升级

    系统很久没有更新内容了,期待已久的更新在今天发布了,最近花了2个月的时间每天一点点,从原有系统 MVC4+EF5+UNITY2.X+Quartz 2.0+easyui 1.3.4无缝接入 MVC5+E ...

  6. ASP.NET MVC5+EF6+EasyUI 后台管理系统(58)-DAL层重构

    系列目录 前言:这是对本文系统一次重要的革新,很久就想要重构数据访问层了,数据访问层重复代码太多.主要集中增删该查每个模块都有,所以本次是为封装相同接口方法 如果你想了解怎么重构普通的接口DAL层请查 ...

  7. ASP.NET MVC5+EF6+EasyUI 后台管理系统(34)-文章发布系统①-简要分析

    系列目录 最新比较闲,为了学习下Android的开发构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(1)-前言与,虽然有点没有目的的学习,但还是了解了Andro ...

  8. ASP.NET MVC5+EF6+EasyUI 后台管理系统(54)-工作流设计-所有流程监控

    系列目录 先补充一个平面化登陆页面代码,自己更换喜欢的颜色背景 @using Apps.Common; @{ Layout = null; } <!DOCTYPE html> <ht ...

  9. ASP.NET MVC5+EF6+EasyUI 后台管理系统(56)-插件---单文件上传与easyui使用fancybox

    系列目录 https://yunpan.cn/cZVeSJ33XSHKZ  访问密码 0fc2 今天整合lightbox插件Fancybox1.3.4,发现1.3.4版本太老了.而目前easyui 1 ...

  10. ASP.NET MVC5+EF6+EasyUI 后台管理系统(38)-Easyui-accordion+tree漂亮的菜单导航

    系列目录 本节主要知识点是easyui 的手风琴加树结构做菜单导航 有园友抱怨原来菜单非常难看,但是基于原有树形无限级别的设计,没有办法只能已树形展示 先来看原来的效果 改变后的效果,当然我已经做好了 ...

随机推荐

  1. 使用 Nodejs 搭建简单的Web服务器

    使用Nodejs搭建Web服务器是学习Node.js比较全面的入门教程,因为要完成一个简单的Web服务器,你需要学习Nodejs中几个比较重要的模块,比如:http协议模块.文件系统.url解析模块. ...

  2. HTML 事件(二) 事件的注册与注销

    本篇主要介绍HTML元素事件的注册.注销的方式. 其他事件文章 1. HTML 事件(一) 事件的介绍 2. HTML 事件(二) 事件的注册与注销 3. HTML 事件(三) 事件流.事件委托 4. ...

  3. JQuery 选择器

    选择器是JQuery的根基,在JQuery中,对事件的处理,遍历DOM和AJAX操作都依赖于选择器.如果能够熟练地使用选择器,不仅能简化代码,而且还可以事半功倍. JQuery选择器的优势 1.简洁的 ...

  4. 《JavaScript设计模式与开发实践》整理

    最近在研读一本书<JavaScript设计模式与开发实践>,进阶用的. 一.高阶函数 高阶函数是指至少满足下列条件之一的函数. 1. 函数可以作为参数被传递. 2. 函数可以作为返回值输出 ...

  5. [开发笔记]yum错误

    yum 错误TypeError: rpmdb open failed 解决办法 是因为RPM数据库出现损坏导致的,它导致所有的软件的升级.安装甚至是删除都会出现问题,终端出现乱码,YUMEX也用不成, ...

  6. 深入理解javascript的getTime方法

    1.理解getTime getTime() 方法返回一个时间的格林威治时间数值. 可以使用这个方法把一个日期时间赋值给另一个Date 对象. 语法: dateObj.getTime() 参数: 无. ...

  7. Android 关于ijkplayer

    基于ijkplayer封装支持简单界面UI定制的视频播放器 可以解析ts格式的so库 怎样编译出可以解析ts等格式的so库?就是编译的时候需要在哪一步修改配置? 一些电视台的m3u8 CCTV1综合, ...

  8. Linux基础介绍【第八篇】

    Linux网络基础 网线 568A 568B 线序:橙白橙 绿白蓝 蓝白绿 棕白棕 交换机.路由器 交换机:DLINK.H3C.CISCO 交换机(Switch)是一种用于电信号转发的网络设备.它可以 ...

  9. Linux命令

    系统信息 arch 显示机器的处理器架构(1) uname -m 显示机器的处理器架构(2) uname -r 显示正在使用的内核版本 dmidecode -q 显示硬件系统部件 - (SMBIOS ...

  10. Selenium-java-获取当前时间

    1 获取当前时间 // 获取当前时分秒 Calendar now = Calendar.getInstance(); int is = now.get(Calendar.HOUR_OF_DAY); i ...