在工作流处理表中,首先我们区分流程模板和流程实例两个部分,这个其实就是类似模板和具体文档的概念,我们一份模板可以创建很多个类似的文档,文档样式结构类似的。同理,流程模板实例为流程实例后,就是具体的一个流程表单信息了,其中流程模板和流程实例表单都包括了各个流程步骤。在流程实例的层次上,我们运行的时候,需要记录一些日志方便跟踪,如流程步骤的处理日志,流程实例表单的处理日志等这些信息。

一旦流程实例根据模板创建后,流程先根据模板初始化后,在处理过程还可以动态增加一些审批步骤,使得我们的处理更加弹性化。如下所示。

我们在系统中动态定义很多业务表单,因此需要动态展示创建表单的入口;另外每种业务表单的创建和查看也需要实现动态的构建,才能更好的实现我们业务流程的处理规则。

1、动态显示流程业务入口

我们在工作流模块中,有一个统一的业务创建入口,方便用户的使用,我们需要创建什么类型的业务表单,从中选择创建接口,是一个便利的入口。

我们实现这个展示会相对比较简单,但是创建业务表单的入口需要动态的处理,是根据用户配置的参数进行动态的处理的。

上述的界面是通过在数据库里面动态获取信息,并创建不同的按钮的,因此可以实现流程入口的动态显示,不需要硬编码带来后期的修改。实现的逻辑就是在右侧内容区域的流布局区域,根据表单信息动态创建按钮,并实现对应的事件响应即可,实现代码如下所示。

        /// <summary>
/// 绑定表单列表的展示
/// </summary>
private void BindData()
{
//使用流布局,清空
this.flowLayoutPanel1.Controls.Clear(); //根据条件获取表单列表,并动态创建按钮
string where = GetConditionSql();
List<FormInfo> list = BLLFactory<BLL.Form>.Instance.Find(where);
int i = ;
foreach (FormInfo info in list)
{
//在流布局中动态加入按钮
SimpleButton button = CreateButton(info, i++);
this.flowLayoutPanel1.Controls.Add(button);
}
}
/// <summary>
/// 根据流程模板的表单信息,动态创建入口按钮
/// </summary>
/// <param name="info">模板的表单信息</param>
/// <param name="imageIndex">图标</param>
/// <returns></returns>
private SimpleButton CreateButton(FormInfo info, int imageIndex)
{
//定义按钮,在流布局的图标、位置、偏移空间、字体颜色等
SimpleButton button = new SimpleButton();
button.ImageList = this.imageCollection1;
button.ImageLocation = ImageLocation.TopCenter;
button.Padding = new Padding(, , , );
button.Size = new Size(, );
button.Margin = new Padding(, , , );
button.ImageIndex = imageIndex;
button.Font = new Font("宋体", 9f, FontStyle.Bold);
button.ForeColor = Color.Blue;
button.Text = info.FormName;
button.Tag = info.ID;
if (!string.IsNullOrEmpty(info.Remark))
{
button.ToolTip = info.Remark;
button.ToolTipIconType = DevExpress.Utils.ToolTipIconType.Information;
}
//所有按钮统一处理事件
button.Click += new EventHandler(button_Click); return button;
}

按钮的处理有一个统一的事件实现新建业务表单的赋值和显示窗体。实现的代码如下所示。

        /// <summary>
/// 单击某个动态生成的按钮,触发的申请表单创建界面
/// </summary>
void button_Click(object sender, EventArgs e)
{
SimpleButton button = sender as SimpleButton;
if (button != null)
{
//获取模板表单必要的信息
var formId = button.Tag.ToString();
var formInfo = BLLFactory<BLL.Form>.Instance.FindByID(formId);
if (formInfo != null && !string.IsNullOrEmpty(formInfo.ApplyWin))
{
try
{
//动态构建创建申请单的界面窗体并赋值
var dlg = Assembly.GetExecutingAssembly().CreateInstance(formInfo.ApplyWin) as FrmAddApply;
dlg.FormID = button.Tag.ToString();
dlg.ShowDialog();
}
catch(Exception ex)
{
LogHelper.Error(ex);
MessageDxUtil.ShowError(ex.Message);
}
}
else
{
MessageDxUtil.ShowTips(button.Text + "暂未开通");
}
}
}

2、动态显示和创建业务表单的处理

有了上面动态列表的显示,以及统一的按钮处理,事情就好办很多。

我们刚才也涉及到了业务表单的创建调用,是通过反射处理实现业务表单创建窗口的赋值和显示的。

    //动态构建创建申请单的界面窗体并赋值
var dlg = Assembly.GetExecutingAssembly().CreateInstance(formInfo.ApplyWin) as FrmAddApply;
dlg.FormID = button.Tag.ToString();
dlg.ShowDialog();

这其中涉及的配置信息就是我们创建一个业务窗口所需要的参数的,如下数据表所示。

其实通过创建这些业务表,我们在封装继承上也做了很多工作,以极大简化业务表单的处理,以下是业务表单新建、编辑、查看的处理操作,它们已经继承自各自的处理类,因此在反射的时候,统一转换为基类即可实现处理。

首先我们来了解一下业务表单的对应关系,一般创建一个业务流程处理,都需要有一个具体的创建业务表单的界面,以及一个查看处理表单的界面。

为了方便,我们尽可能减少代码编写,我们需要把大多数的逻辑处理放在基类实现,这样我们在新增一个业务表单的时候就可以减少很多代码编写及维护了。

例如对于请假申请的业务表单,它们的窗体定义如下所示。

而查看请假申请的业务表单则是如下。

从上面关系我们可以看到,其中对于工作流业务表单的窗体界面都可以实现标准的处理了,继承自某个基类,然后整合相关的数据处理规则即可。

那么我们提炼业务信息后,可以使用代码生成工具快速生成,这样可以极大提高我们的开发效率。

下面就是使用我们定制的框架代码生成工具 Database2Sharp,就可以极大简化工作流业务表单的生成处理了。

3、查看申请单的处理动态化

在我的待办业务列表里面,就可以看到刚才的表单了,双击可以进行查看,以及相关的审批处理工作。

对于一个流程处理操作,我们知道一般有审批通过、拒绝、退回到某步骤、转发到内部阅读、阅读等处理步骤,以及包括起草者能撤销表单呢等操作,当然如果还有一些具体的业务,可能还会有一些流程的处理才操作,不过基本上也可以归结为上面几种,只是他们每步处理的数据内容不同而已。因此审批的操作步骤分类如下所示。

除了上面这些基础的表单处理动作,有时候还会定义多个处理人共同处理的会签步骤,只有全部通过才算通过的处理流程。

会签是指创建一个或多个子流程供相关人员进行审批,等待全部人员完成处理后再次回到主流程上,然后决定是否继续流转到下一个流程步骤上去,一般的申请单的主流程如下所示。

这里设置的会签处理就是其中一个步骤,一旦会签处理步骤发起会签,就会构建多个可供审批的子流程了,如下所示。

针对上面的业务介绍,那么显示申请单的处理就必须处理这些步骤是否可用,或者决定进入哪一个流程步骤的了。

对于审批性质的表单,如下是界面的审批操作

而如果是发起【发起会签】的处理操作,那么则是把相关的投票权发送给处理人进行会签处理。

以上就是工作流表单里面设计到的几个动态处理的业务场景,同时我们通过利用动态的信息处理,可以减少硬编码的可能性,同时增加系统的弹性处理,非常方便,由于相关工作流的基类设计较为合理,因此在代码生成的时候,只需要关注简单的界面展示调整即可,通过这种处理方式,可以在多个层面降低开发工作流界面的复杂度,同时系统又增加了很多可扩展性的处理,如可以动态增加表单、动态增加流程步骤、动态指定不同的业务处理类型等等。

通过这些的介绍,我们就是系统在开发的时候,尽可能提取不变的内容或者规则,从而在实际增量开发的过程中降低开发的时间,减少难度,同时统一处理做法,既可以提高效率,又可以提高稳定性和统一性。

Winform开发框架中工作流模块的动态处理的更多相关文章

  1. Winform开发框架中工作流模块之申请单草稿处理

    在我们开发工作流模块的时候,有时候填写申请单过程中,暂时不想提交审批,那么可以暂存为草稿,以供下次继续填写或者提交处理,那么这个草稿的功能是比较实用的,否则对于一些填写内容比较多的申请单,每次要重填写 ...

  2. 参照企业微信审批业务,在Winform开发框架中工作流模块的实现业务审批

    目前微信的企业号已经切换到企业微信里面,这个是一个APP程序,提供了很丰富的企业应用,其中包括了业务审批处理,审批业务包括请假.报销.费用.出差等很多个审批场景,在Winform开发框架中工作流模块这 ...

  3. Winform开发框架中工作流模块之审批会签操作(2)

    前面随笔介绍了请假申请单和报销申请单两个不同的业务表单的流程处理,一个是单表信息,一个包含明细的主从表信息,后者包含了条件流程的处理,在流程审批中,一般还有一种流程处理就是会签的操作,会签处理是几个审 ...

  4. Winform开发框架中工作流模块之审批会签操作

    在前面介绍了框架中工作流的几个开发过程,本篇随笔重点介绍一下日常审批环节中的具体处理过程,从开始创建表单,以及各个审批.会签过程的流转过程,希望大家对其中流程的处理有一个大概的印象. 1.请假申请表单 ...

  5. Winform开发框架中工作流模块的业务表单开发

    在我们开发工作流的时候,往往需要设计到具体业务表单信息的编辑,有些是采用动态编辑的,有些则是在开发过程中处理的,各有各的优点,动态编辑的则方便维护各种各样的表单,但是数据的绑定及处理则比较麻烦,而自定 ...

  6. Winform开发框架中工作流模块的表设计分析

    在较早博客随笔里面写过文章<Winform开发框架之简易工作流设计>之后,很久没有对工作流部分进行详细的介绍了,本篇继续这个主题,详细介绍其中的设计.实现及效果给大家,这个工作流在好几年前 ...

  7. 在Winform开发框架中,利用DevExpress控件实现数据的快速录入和选择

    在实际的项目开发过程中,有好的控件或者功能模块,我都是想办法尽可能集成到我的WInform开发框架中,这样后面开发项目起来,就可以节省很多研究时间,并能重复使用,非常高效方便.在我很早之前的一篇博客& ...

  8. 在Winform开发框架中实现对数据库的加密支持

    在很多情况下,我们需要对数据库进行加密,特别是Access数据库.Sqlite数据库,这些直接部署在客户端的数据,因为数据也是客户的资产,数据库总是存在很多相关的秘密或者重要的业务数据,所以一般来说, ...

  9. Winform开发框架中的综合案例Demo

    在实际的系统开发中,我们往往需要一些简单的的案例代码,基于此目的我把Winform开发框架中各种闪光点和不错的功能,有些是我们对功能模块的简单封装,而有些则是引入了一些应用广泛的开源组件进行集成使用, ...

随机推荐

  1. Spring源码情操陶冶#task:executor解析器

    承接Spring源码情操陶冶-自定义节点的解析.线程池是jdk的一个很重要的概念,在很多的场景都会应用到,多用于处理多任务的并发处理,此处借由spring整合jdk的cocurrent包的方式来进行深 ...

  2. Java提高班(五)深入理解BIO、NIO、AIO

    导读:本文你将获取到:同/异步 + 阻/非阻塞的性能区别:BIO.NIO.AIO 的区别:理解和实现 NIO 操作 Socket 时的多路复用:同时掌握 IO 最底层最核心的操作技巧. BIO.NIO ...

  3. git http服务免登录实现(免去每次请求用户名密码输入,Visual Studio可用)

    最近用了Bonobo搭起了Git服务,弄了个批处理文件来避免每次都要输入用户名密码. 此脚本分为三个步骤:1.添加用户变量HOME:2.添加用户_netrc文件:3.添加windows普通凭据(因为V ...

  4. 使用表类型(Table Type-SqlServer)实现百万级别的数据一次性毫秒级别插入

    使用表类型(Table Type)实现百万级别的数据一次性插入 思路 1 创建表类型(TaBleType)         2 创建添加存储过程         3 使用C#语言构建一个DataTab ...

  5. MySQL 笔记整理(5) --深入浅出索引(下)

    笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> 5) --深入浅出索引(下) 这次的笔记从一个简单的查询开始: 建表语句是这样的 mysql> create table T ...

  6. .NET Core[MVC] 利用特性捕捉异常

    声明:本方式适用于MVC.本代码只适用于.NET Core MVC. 先创建一个类继承ExceptionFilterAttribute这个抽象类,并override它的方法OnException. 代 ...

  7. 使用微软PinYinConverter查询汉字拼音

    通过汉字,如何查询拼音? 微软有相应的DLL可直接使用 引用方式 Nuget包管理安装 DLL下载后,引用 可以从微软的网站上下载相关文字处理的类库,下载地址如下: http://download.m ...

  8. 第六讲 smart qq C#开发总结

    smart qqC#开发总结: 整个开发下来其实一点都不是很难,从一开始二维码 获取到最终的收发消息,基本上都是模拟浏览器的操作.都是基于http通讯.一下就是 本次新手学习http协议的最关键的一个 ...

  9. PHP中的Define和Const区别

    我们经常把不经常变的值定义成常量,常量一般用全部大写来表示,前面不加美元符号,那么define和const有什么区别呢? 常量是一个简单的标识符.在脚本执行期间该值不能改变(除了所谓的魔术常量,他们其 ...

  10. 让Mongo在Spring中跑起来

    本文标题为<让Mongo在Spring中跑起来>,旨在Spring中如何成功连接MongoDB并对其进行增删改查等操作,由于笔者也是刚接触,对其中的一些原由也不甚了解,若有错误之处,敬请指 ...