会签可能会有很多解释或定义,本文讲的会签是指在一个流程中的某一步操作有多个用户同时参与,这些用户的操作界面一般是一样的。

QuickFlow的会签是通过MultiTask实现的,MultiTask实现了多个任务同时分配的逻辑,它具有以下控制属性:

image

1)ExecutionType--指定任务的分配是串行还是并行,如果是串行,则上一个用户完成任务后才会给下一个用户分配任务,如果是并行,则所有任务同时分配。

2)CompletionMode--任务的完成模式,可以为RequireOne和RequireAll,如果RequireOne,则无论这一步分配了几个任务,只要一个用户完成,步骤即结束,未完成的任务会被自动取消,如果是RequireAll,并且没有指定CompleteRule,则要求所有用户都完成任务。

3)CompleteRule--CompleteRule是一个Condition类型的属性,可以为CodeConditon或DeclareRuleConditon。当CompletionMode为RequireAll时,可以利用CompleteRule进一步控制审批步骤何时结束。我们经常碰到的如下的业务场景:当多个人参与审批,所有人都同意则到下一步,如果只要有一个用户不同意,则流程退回或结束,即使其他用户还没有审批。这种情况即可利用CompleteRule。

下面看一个示例:

流程很简单,第一步多人会签审批,如果有一人不同意则结束流程,如果所有人都同意则到经理审批。

Step1)画出如下的流程图

其中“开始”节点对应Start活动,“会签审批”对应MultiTask活动,“经理审批”对应Task活动,“结束”对应End活动。

image

注意:如果你已经画好了流程图中的线,然后改了活动的名字,可能需要将画好的线删掉重新画线,不然会出现活动找不到错误。

Step2)处理“会签审批”

指定会签审批的CompletionMode为RequireAll,ExecutionType为Parallel。

将“会签审批”的TaskOutcomes属性绑定到工作流的字段:

image

处理“会签审批”的Initialized事件:

private void 会签审批_Initialized(object sender, EventArgs e)
       {
           this.会签审批.Users.Add("dc\\user1");
           this.会签审批.Users.Add("dc\\user2");
           this.会签审批.Users.Add("dc\\user3");
           //如果是串行分配任务,这里的顺序就决定了任务分配的顺序
       }

设置“会签审批”的CompleteRule:

image 

说明:只要有一个人的审批结果是Reject,则此条件为true。

Step3)设置“会签审批”后的路由判断

设置decision的Conditon为code conditon:

private void allAgree(object sender, ConditionalEventArgs e)
       {
           e.Result = this.会签审批.TaskOutcomes.Filter("Reject") == 0; //没有reject的
       }

Step4) 处理“经理审批”,设置其TaskCreating事件:

private void managerTaskCreating(object sender, QuickFlow.TaskEventArgs e)
       {
           e.TaskProperties.AssignedTo = "dc\\manager";
       }

完成!

 

关于GroupTask

每次使用MulitiTask时都要写代码指定审批人,这是一个不好的习惯,通常,审批人可以按照某些规则来获取,比如来自SharePoint组,来自AD组,来自第三方的角色管理系统,很显然我们应该将这些常用的用户获取逻辑做个封装。

GroupTask继承于MultiTask,它的代码很简单,只是在MultiTask的Initialized事件中将用户从某个组中取出来添加到Users集合中,这样,如果我们要将任务分配给SharePoint用户组中的用户,直接用GroupTask,设置一下它的Group属性即可:

//GroupTask获取用户的代码

void GroupTask_Initialized(object sender, EventArgs e)
        {

            if (this.WorkflowProperties == null)
                throw new Exception("WorkflowProperties is null , please bind it to correct field");

            SPRoleUserProvider up = new SPRoleUserProvider();

            IList<User> users = null;
            try
            {
                if (this.DeptInherits)
                {
                    User user = up.GetUser( this.WorkflowProperties.Web , this.WorkflowProperties.Originator);
                    users = up.GetRoleUsers( this.WorkflowProperties.Web, this.Group,user.Department );
                }
                else
                {
                    users = up.GetRoleUsers(this.WorkflowProperties.Web, this.Group);
                }
            }
            catch (Exception ex)
            {
                ActivityUtil.Log(this, SPWorkflowHistoryEventType.WorkflowError, null, "获取组用户出错[" + this.Group + "]", ex.Message);
                throw ex;
            }

            foreach (User u in users)
            {
                this.Users.Add(u.LoginName);
            }
        }

GroupTask有个DeptInherit属性,这个是来做什么的呢?

假设有一步审批是“部门经理审批”,而这个公司是一个有多个部门的大公司,每个提交人发起的审批,都需要“他所在的部门的经理”进行审批,如何实现?
一种方式是将部门经理作为用户的AD属性,在AD中进行维护,那么只要用Task活动,写代码从用户的AD属性中获取即可,这种方式的一个缺点是维护工作量太大了。

还有个简单的方式:在网站建个部门经理的组,SharePoing中每个用户都有个“部门”属性,提交人和“本部门经理”的部门属性一定是一样的,那么用提交人的部门属性从部门经理组中进行一下过滤,即可取到“本部门经理”,当DeptInerit设置为true时,GroupTask即会进行这个操作。当然这个方法要求AD中用户的“部门”属性一定要维护正确,然后正确同步到UserProfile中(AD中维护后1小时)。

这两种方法是不开发专门的“用户角色管理系统”的前提下的,如果您有完善的角色管理系统,可能实现的就更“优美”了。

 

用过K2的朋友可以比较下,这个MultiTask和GroupTask跟K2的ClientEvent是很类似的。

 

示例代码下载:

https://files.cnblogs.com/jianyi0115/QuickFlowExample_%E4%BC%9A%E7%AD%BE.zip

注意:此代码并没有经过测试,只能作为参考。

posted on 2009-09-07 21:23  jianyi  阅读(3076)  评论(5编辑  收藏  举报