【Moss开发系列】WF+Aspx进行Moss工作流开发(2)

    上文中,我们利用WF+Aspx页面,实现了一个简单的MOSS审批流程,但这种方案有一定的缺陷,并没能达到我们最终减轻开发量的目的,如果一个流程有几个个审批环节,按照这种方式的话,我们需要建几十个审批内容类型,编写处理代码,然后为每一WF活动绑定内容类型,最后部署,这样下来,我们的流程设计工作量依旧很大,依旧很难适应复杂流程的开发过程。

    如果能对流程表单进行一定程度的封装,然后表单能够灵活的切换而无需重复进行MOSS复杂的部署过程,那么我们处理复杂流程的工作量就会减轻很多。

    由于A公司制度的逐步完善,其请假流程也发生了变化,由原来的一级审批变为三级审批,新的请假流程描述如下:

     1. 请假两天以内,由部门经理直接审批即可通过

     2. 请假三天以上,部门经理审批--->人事部门审批

     3. 请假一周以上(按七天算),部门经理审批--->人事部门审批--->行政部审批

    由于我们原有的审批内容类型页面及请假流程已经在使用中,如果按以前的设计方案,我们的审批有可能要重新设计三个内容类型页面来,然后为这三级审批分别绑定这三个内容类型,这对于我们是不可接受的,尝试着在现有审批页面的基础上加以改造,使之能够灵活应对这次和将来可能出现的部分需求变化是我们应该优先选择的解决方案。

   第一步,审批内容类型页面改造:  

页面前台代码
1 <%@ Page Language="C#" MasterPageFile="~/_layouts/application.master" AutoEventWireup="true"
2 CodeBehind="Approve.aspx.cs" Inherits="Janet.AspxWorkflow.Forms.Approve,Janet.AspxWorkflow.Forms, Version=1.0.0.0, Culture=neutral, PublicKeyToken=4af1d7891f28970c" %>
3
4  <%@ Import Namespace="Microsoft.SharePoint" %>
5 <%@ Register TagPrefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls"
6 Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
7 <%@ Register Src="ItemInfo.ascx" TagName="ItemInfo" TagPrefix="uc1" %>
8 <asp:Content ID="Content1" ContentPlaceHolderID="PlaceHolderPageTitle" runat="server">
9 请假审批流程
10 </asp:Content>
11 <asp:Content ID="Content2" ContentPlaceHolderID="PlaceHolderTitleBreadcrumb" runat="server">
12 &nbsp;
13 </asp:Content>
14 <asp:Content ID="Content3" ContentPlaceHolderID="PlaceHolderPageTitleInTitleArea"
15 runat="server">
16 </asp:Content>
17 <asp:Content ID="Content5" ContentPlaceHolderID="PlaceHolderMain" runat="server">
18 <table width="100%" cellpadding="0" cellspacing="0">
19 <uc1:ItemInfo ID="ItemInfoControl" runat="server" />
20 <BR />
21 <asp:Panel ID="TaskPanel" runat="server">
22 </asp:Panel>
23 </asp:Content>
24

可以看出:页面中增加了一个用户控件,用来显示请假的详细信息,增加了一个TaskPanel控件,用来加载审批审批表单,表单为用户控件,可根据不同情况动态加载表单。

所有的审批类型表单(.ascx)均继承自TaskBase基类:

代码
1 public class TaskBase : UserControl
2 {
3 public SPList TaskList { get; set; } //审批列表
4
5 public SPListItem TaskItem { get; set; } //任务信息项
6
7 public SPListItem ProjectItem { get; set; } //请假信息项
8 }

第二步,审批表单的设计:

对于这个例子,审批表单都是基本相同的,因为三个步骤都是完成审批功能,对于本例来说,其实全可以采用一个表单,但为了展示task2,tak2,task3的效果,我这里制作了三个表单,其代码基本完全一样,只界面颜色略有不同,以便区分每一步骤的效果,下面选取Task1表单的代码来加以说明:

 Task1审批表单前台代码:

审批表单前台代码
1 <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="Task1.ascx.cs" Inherits="Janet.AspxWorkflow.Forms.Task1,Janet.AspxWorkflow.Forms, Version=1.0.0.0, Culture=neutral, PublicKeyToken=4af1d7891f28970c" %>
2 <table width="650" style="font-size: 12px; color: #369; border-bottom-style: solid;
3 border-right-style: solid; border-collapse: collapse; border-top-style: solid;
4 border-left-style: solid" border="1" rules="all" cellspacing="0" cellpadding="4">
5 <tr>
6 <td colspan="2" align="center" style="background:#633;font-weight:bold;color:#fff">
7 部门经理审批表单
8 </td>
9 </tr>
10 <tr>
11 <td>
12 审批意见
13 </td>
14 <td>
15 <asp:TextBox ID="txtMsg" runat="server" TextMode="MultiLine" BorderStyle="Solid" BorderWidth="1px" BorderColor="#666666" Rows="5" Columns="40"></asp:TextBox>
16 </td>
17 </tr>
18 <tr>
19 <td>
20 是否通过
21 </td>
22 <td>
23 <asp:RadioButtonList ID="radioPass" runat="server">
24 <asp:ListItem Value="true" Selected="True">通过</asp:ListItem>
25 <asp:ListItem Value="false">拒绝</asp:ListItem>
26 </asp:RadioButtonList>
27 </td>
28 </tr>
29 <tr>
30 <td>
31 </td>
32 <td>
33 <asp:Button Text="提交" runat="server" ID="BtnSubmit" OnClick="BtnSubmit_Click" />
34 </td>
35 </tr>
36 </table>
37

Task1 审批表单后台部分代码:

审批函数
1 protected void BtnSubmit_Click(object sender, EventArgs e)
2 {
3 try
4 {
5 if (this.TaskItem != null)
6 {
7 SPWeb web = SPContext.Current.Web;
8 web.AllowUnsafeUpdates = true;
9 Hashtable taskHash = new Hashtable();
10 taskHash["ApproveMsg"] = this.txtMsg.Text; //审批信息
11 taskHash["approved"] = this.radioPass.SelectedValue; //审批状态,WF中获取用来判断,是否回退....
12 SPWorkflowTask.AlterTask(this.TaskItem, taskHash, true); //提交任务审批结果
13 SPUtility.Redirect(this.TaskList.DefaultViewUrl, SPRedirectFlags.UseSource, HttpContext.Current);
14 }
15 }
16 catch (Exception ex)
17 {
18 Response.Write(ex.ToString());
19 }
20 }

把每一任务的表单 task1.ascx  task2.ascx ....  ProjectItem.ascx和改动过的内容类型复制到 C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS\MyAspxTask 目录下面,然后把生成的程序集拖到GAC中。

第三步,审批流程的设计:

  

该流程比较简单,就用了两个判断活动来处理二级和三级审批,由于三个审批过程是一致的,审批处理的代码也基本完全相同,在这个流程中就简单进行了代码复制,没去对代码进行封装。 

审批流程代码
1 public sealed partial class Workflow1 : SequentialWorkflowActivity
2 {
3 public Workflow1()
4 {
5 InitializeComponent();
6 }
7
8 public Guid workflowId = default(System.Guid);
9 public SPWorkflowActivationProperties workflowProperties = new SPWorkflowActivationProperties();
10 public Guid taskId1 = default(System.Guid);
11 public SPWorkflowTaskProperties taskProperties1 = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
12 public Guid taskId2 = default(System.Guid);
13 public SPWorkflowTaskProperties taskProperties2 = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
14 public Guid taskId3 = default(System.Guid);
15 public SPWorkflowTaskProperties taskProperties3 = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
16 public String taskOutcome1 = default(System.String);
17 public String taskOutcome2 = default(System.String);
18 public String taskOutcome3 = default(System.String);
19 public int Days = 0;
20 public string ItemTitle = string.Empty;
21
22 private void onWorkflowActivated1_Invoked(object sender, ExternalDataEventArgs e)
23 {
24 this.ItemTitle = this.workflowProperties.Item.DisplayName;
25 this.Days = int.Parse(this.workflowProperties.Item["请假天数"].ToString());
26 }
27
28 private void createTaskWithContentType1_MethodInvoking(object sender, EventArgs e)
29 {
30 this.taskId1 = Guid.NewGuid();
31 this.taskProperties1.AssignedTo = "jasper\\moss_test1";
32 this.taskProperties1.ExtendedProperties["step"] = 1; //指定要加载的表单编号
33 this.taskProperties1.Title = string.Format("请部门经理审批【{0}】", this.ItemTitle);
34 }
35
36 private void onTaskChanged1_Invoked(object sender, ExternalDataEventArgs e)
37 {
38 bool approve = bool.Parse(this.taskProperties1.ExtendedProperties["approved"].ToString());
39 string msg = approve ? "部门经理审批通过:" : "部门经理审批拒绝:";
40 msg += this.taskProperties1.ExtendedProperties["ApproveMsg"].ToString();
41 this.workflowProperties.Workflow.CreateHistoryEvent(approve ? 2 : 8, 0, this.workflowProperties.OriginatorUser, msg, "", ""); //写入工作流历史记录
42 this.taskOutcome1 = approve ? "经理通过" : "经理拒绝";
43 }
44
45 private void createTaskWithContentType2_MethodInvoking(object sender, EventArgs e)
46 {
47 this.taskId2 = Guid.NewGuid();
48 this.taskProperties2.AssignedTo = "jasper\\moss_test2";
49 this.taskProperties2.ExtendedProperties["step"] = 2; //指定要加载的表单编号
50 this.taskProperties2.Title = string.Format("请人事部门审批【{0}】", this.ItemTitle);
51 }
52
53 private void onTaskChanged2_Invoked(object sender, ExternalDataEventArgs e)
54 {
55 bool approve = bool.Parse(this.taskProperties2.ExtendedProperties["approved"].ToString());
56 string msg = approve ? "人事部审批通过:" : "人事部审批拒绝:";
57 msg += this.taskProperties2.ExtendedProperties["ApproveMsg"].ToString();
58 this.workflowProperties.Workflow.CreateHistoryEvent(approve ? 2 : 8, 0, this.workflowProperties.OriginatorUser, msg, "", ""); //写入工作流历史记录
59 this.taskOutcome2 = approve ? "人事部通过" : "人事部拒绝";
60 }
61
62 private void createTaskWithContentType3_MethodInvoking(object sender, EventArgs e)
63 {
64 this.taskId3 = Guid.NewGuid();
65 this.taskProperties3.AssignedTo = "jasper\\moss_test3";
66 this.taskProperties3.ExtendedProperties["step"] = 3; //指定要加载的表单编号
67 this.taskProperties3.Title = string.Format("请行政部门审批【{0}】", this.ItemTitle);
68 }
69
70 private void onTaskChanged3_Invoked(object sender, ExternalDataEventArgs e)
71 {
72 bool approve = bool.Parse(this.taskProperties3.ExtendedProperties["approved"].ToString());
73 string msg = approve ? "行政部审批通过:" : "行政部审批拒绝:";
74 msg += this.taskProperties3.ExtendedProperties["ApproveMsg"].ToString();
75 this.workflowProperties.Workflow.CreateHistoryEvent(approve ? 2 : 8, 0, this.workflowProperties.OriginatorUser, msg, "", ""); //写入工作流历史记录
76 this.taskOutcome3 = approve ? "行政部通过" : "行政部拒绝";
77 }
78 }

到这里,流程设计已经完成,发布流程到MOSS,启动工作流,我们可以看到已经为部门经理分配了审批任务:

点击该审批任务,进行一级审批:

部门经理审批结束后,我们可以看到已经为人事部门分配了审批任务:

人事部门进行二级审批:

人事审批结束,为行政部门分配任务:

行政部进行终审:

行政部门提交审批结果,请假流程结束:

可以看到,我新婚假期的蜜月旅行已经被行政部那无情的小MM给剥夺了,无语中.....

总结:

     这里只是给出了一个Aspx+WF开发MOSS工作流的一个简易的Demo,现实场景中,如果要做一系列复杂的流程,抛开其他支撑系统不说,单这一块还需要很多工作要做,比如对表单的进一步封装、对WF活动进行一定程度的封装等。 

附:  本例项目代码

原文地址:https://www.cnblogs.com/janet/p/1720651.html