Winform开发框架中工作流模块的动态处理

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

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

image

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

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

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

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

image

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

        /// <summary>
        /// 绑定表单列表的展示
        /// </summary>
        private void BindData()
        {
            //使用流布局,清空
            this.flowLayoutPanel1.Controls.Clear();

            //根据条件获取表单列表,并动态创建按钮
            string where = GetConditionSql();
            List<FormInfo> list = BLLFactory<BLL.Form>.Instance.Find(where);
            int i = 0;
            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(10, 10, 10, 10);
            button.Size = new Size(102, 114);
            button.Margin = new Padding(10, 10, 10, 10);
            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();

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

image

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

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

image

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

image

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

image

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

image

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

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

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

image

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

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

image

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

image

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

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

image

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

image

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

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

image

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

image

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

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容