最近因为接手离职同事的公文审批(没有使用工作流)维护,感觉很麻烦,于是在我开发的工作流平台上重新写了相关的功能,扩展同事的功能,同时可以支持固定流和任意流功能。希望大哥们给予指点。
固定流就是由发起人定义审批的步骤,流程按照既定步骤执行。
任意流就是由发起人发起,选择下一步审批人审批,然后审批再选择下一步审批人。
当然公文审批支持的电子签名的功能也有,但是不作为本篇讨论内容,还有界面美观。
1.服务代码。
Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.ComponentModel;
namespace StateMachineService
{
[Serializable]
public class DocFlowEventArgs:ExternalDataEventArgs
{
public DocFlowEventArgs(string userID,Guid uninstand): base(uninstand)
{
this.uninstand = uninstand;
this.userID = userID;
}
private Guid uninstand = Guid.Empty;
public Guid Uninstand
{
get { return this.uninstand; }
set { this.uninstand = value; }
}
private string userID = string.Empty;
public string UserID
{
get { return this.userID; }
set { this.userID = value; }
}
}
[ExternalDataExchange]
public interface IDocFlowService
{
event EventHandler<DocFlowEventArgs> Next;
event EventHandler<DocFlowEventArgs> Jump;
event EventHandler<DocFlowEventArgs> Stop;
void SetFixNextApprover(int NextStpeID, string uninstand);
void SetFixEnableApprover(int CurrentStpeID, string uninstand);
void SetAutoNextApprover();
void SetAutoEnableApprover(string uninstand);
void ChangeStatus();
}
[Serializable]
public class DocFlowService:IDocFlowService
{
IDAL.IWFreeNode iwfreenode;
Guid T;
string UserID;
Dictionary<string, EventHandler<DocFlowEventArgs>> list = new Dictionary<string, EventHandler<DocFlowEventArgs>>();
public void RaiseEventer(string eventName,Guid uninstand,string userID)
{
if(list[eventName]!=null)
{
try
{
EventHandler<DocFlowEventArgs> eventHandler=list[eventName];
DocFlowEventArgs args= new DocFlowEventArgs(userID ,uninstand);
args.WaitForIdle = true;
eventHandler.Invoke(null, args );
this.T = uninstand;
this.UserID = userID;
}
catch
{
}
}
}
IDocFlowService 成员#region IDocFlowService 成员
public event EventHandler<DocFlowEventArgs> Next
{
add
{
this.list.Add("Next", value);
}
remove
{
this.list.Remove("Next");
}
}
public event EventHandler<DocFlowEventArgs> Jump
{ add
{
this.list.Add("Jump", value);
}
remove
{
this.list.Remove("Jump");
}
}
public event EventHandler<DocFlowEventArgs> Stop
{
add
{
this.list.Add("Stop", value);
}
remove
{
this.list.Remove("Stop");
}
}
public void ChangeStatus()
{
throw new NotImplementedException();
}
#endregion
IDocFlowService 成员#region IDocFlowService 成员
public void SetFixNextApprover(int NextStpeID,string uninstand)
{
iwfreenode = DALFactory.WFreeNode.CreateInstance();
string script = "update WFreeNode set [ExceteState]=1 where Uninstand='"+uninstand+"' and StepID="+NextStpeID;
iwfreenode.Update(script);
//throw new NotImplementedException();
}
#endregion
IDocFlowService 成员#region IDocFlowService 成员
public void SetFixEnableApprover(int CurrentStpeID,string uninstand)
{
iwfreenode = DALFactory.WFreeNode.CreateInstance();
string script = "update WFreeNode set [ExceteState]=2 where Uninstand='" +uninstand+ "' and userID='" + this.UserID + "' and StepID=" + CurrentStpeID;
iwfreenode.Update(script);
//throw new NotImplementedException();
}
#endregion
IDocFlowService 成员#region IDocFlowService 成员
public void SetAutoNextApprover()
{
//throw new NotImplementedException();
}
public void SetAutoEnableApprover(string uninstand)
{
iwfreenode = DALFactory.WFreeNode.CreateInstance();
string script = "update WFreeNode set [ExceteState]=2 where Uninstand='" +uninstand + "' and userID='" + this.UserID + "'";
iwfreenode.Update(script);
}
#endregion
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.ComponentModel;
namespace StateMachineService
{
[Serializable]
public class DocFlowEventArgs:ExternalDataEventArgs
{
public DocFlowEventArgs(string userID,Guid uninstand): base(uninstand)
{
this.uninstand = uninstand;
this.userID = userID;
}
private Guid uninstand = Guid.Empty;
public Guid Uninstand
{
get { return this.uninstand; }
set { this.uninstand = value; }
}
private string userID = string.Empty;
public string UserID
{
get { return this.userID; }
set { this.userID = value; }
}
}
[ExternalDataExchange]
public interface IDocFlowService
{
event EventHandler<DocFlowEventArgs> Next;
event EventHandler<DocFlowEventArgs> Jump;
event EventHandler<DocFlowEventArgs> Stop;
void SetFixNextApprover(int NextStpeID, string uninstand);
void SetFixEnableApprover(int CurrentStpeID, string uninstand);
void SetAutoNextApprover();
void SetAutoEnableApprover(string uninstand);
void ChangeStatus();
}
[Serializable]
public class DocFlowService:IDocFlowService
{
IDAL.IWFreeNode iwfreenode;
Guid T;
string UserID;
Dictionary<string, EventHandler<DocFlowEventArgs>> list = new Dictionary<string, EventHandler<DocFlowEventArgs>>();
public void RaiseEventer(string eventName,Guid uninstand,string userID)
{
if(list[eventName]!=null)
{
try
{
EventHandler<DocFlowEventArgs> eventHandler=list[eventName];
DocFlowEventArgs args= new DocFlowEventArgs(userID ,uninstand);
args.WaitForIdle = true;
eventHandler.Invoke(null, args );
this.T = uninstand;
this.UserID = userID;
}
catch
{
}
}
}
IDocFlowService 成员#region IDocFlowService 成员
public event EventHandler<DocFlowEventArgs> Next
{
add
{
this.list.Add("Next", value);
}
remove
{
this.list.Remove("Next");
}
}
public event EventHandler<DocFlowEventArgs> Jump
{ add
{
this.list.Add("Jump", value);
}
remove
{
this.list.Remove("Jump");
}
}
public event EventHandler<DocFlowEventArgs> Stop
{
add
{
this.list.Add("Stop", value);
}
remove
{
this.list.Remove("Stop");
}
}
public void ChangeStatus()
{
throw new NotImplementedException();
}
#endregion
IDocFlowService 成员#region IDocFlowService 成员
public void SetFixNextApprover(int NextStpeID,string uninstand)
{
iwfreenode = DALFactory.WFreeNode.CreateInstance();
string script = "update WFreeNode set [ExceteState]=1 where Uninstand='"+uninstand+"' and StepID="+NextStpeID;
iwfreenode.Update(script);
//throw new NotImplementedException();
}
#endregion
IDocFlowService 成员#region IDocFlowService 成员
public void SetFixEnableApprover(int CurrentStpeID,string uninstand)
{
iwfreenode = DALFactory.WFreeNode.CreateInstance();
string script = "update WFreeNode set [ExceteState]=2 where Uninstand='" +uninstand+ "' and userID='" + this.UserID + "' and StepID=" + CurrentStpeID;
iwfreenode.Update(script);
//throw new NotImplementedException();
}
#endregion
IDocFlowService 成员#region IDocFlowService 成员
public void SetAutoNextApprover()
{
//throw new NotImplementedException();
}
public void SetAutoEnableApprover(string uninstand)
{
iwfreenode = DALFactory.WFreeNode.CreateInstance();
string script = "update WFreeNode set [ExceteState]=2 where Uninstand='" +uninstand + "' and userID='" + this.UserID + "'";
iwfreenode.Update(script);
}
#endregion
}
}
现在支持前进,抄送(平台功能)和终止,还不支持会退和跳批。
2.数据库结构
Code
CREATE TABLE [dbo].[DocFlow](
[Uninstand] [uniqueidentifier] NOT NULL,
[UserID] [varchar](50) NOT NULL,
[Date] [datetime] NULL,
[Title] [varchar](400) NULL,
[Remark] [varchar](500) NULL,
[DocLevel] [varchar](50) NULL,
[FlowType] [varchar](10) NULL,
[Depart] [varchar](50) NULL
)
CREATE TABLE [dbo].[DocFlow](
[Uninstand] [uniqueidentifier] NOT NULL,
[UserID] [varchar](50) NOT NULL,
[Date] [datetime] NULL,
[Title] [varchar](400) NULL,
[Remark] [varchar](500) NULL,
[DocLevel] [varchar](50) NULL,
[FlowType] [varchar](10) NULL,
[Depart] [varchar](50) NULL
)
3.流程图
a.
b.
2.
3.
4.
流程代码
Code
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;
using System.Linq;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
namespace StateMachineLibrary
{
public partial class DocFlow: StateMachineWorkflowActivity
{
public static DependencyProperty DocFlowTypeProperty = DependencyProperty.Register("DocFlowType", typeof(string), typeof(DocFlow));
public string DocFlowType
{
get { return (string)base.GetValue(DocFlow.DocFlowTypeProperty); }
set { base.SetValue(DocFlow.DocFlowTypeProperty, value); }
}
public static DependencyProperty StepIDListProperty = DependencyProperty.Register("StepIDList", typeof(System.Collections.Generic.List<int>), typeof(DocFlow));
public System.Collections.Generic.List<int> StepIDList
{
get { return (System.Collections.Generic.List<int>)base.GetValue(DocFlow.StepIDListProperty); }
set { base.SetValue(DocFlow.StepIDListProperty, value); }
}
public static DependencyProperty UninstandProperty = DependencyProperty.Register("Uninstand",typeof(string),typeof(DocFlow));
public string Uninstand
{
get { return (string)base.GetValue(DocFlow.UninstandProperty); }
set { base.SetValue(DocFlow.UninstandProperty, value); }
}
public static DependencyProperty CurrentIndexProperty = DependencyProperty.Register("CurrentIndex", typeof(int), typeof(DocFlow));
public int CurrentIndex
{
get { return (int)base.GetValue(DocFlow.CurrentIndexProperty); }
set { base.SetValue(DocFlow.CurrentIndexProperty, value); }
}
private int MaxIndex = 0;
private int MinIndex = 0;
private void autoResearch(object sender, EventArgs e)
{
if(this.DocFlowType.Equals("fix",StringComparison.OrdinalIgnoreCase))
{
this.FindMinMax();
}
}
private void FindMinMax()
{
this.StepIDList.Sort(new Comparison<int>((x, y) => x.CompareTo(y)));
this.MinIndex = this.StepIDList[0];
this.MaxIndex = this.StepIDList[this.StepIDList.Count-1];
this.CurrentIndex = this.MinIndex;
}
private void FixCurrentRemove(object sender, EventArgs e)
{
if (this.DocFlowType.Equals("fix", StringComparison.OrdinalIgnoreCase))
{
this.StepIDList.Remove(this.CurrentIndex);
}
}
private void CheckDocType(object sender, ConditionalEventArgs e)
{
if (this.DocFlowType.Equals("fix", StringComparison.OrdinalIgnoreCase))
{
e.Result = true;
}
else
{
e.Result = false;
}
}
private void CurrentIsOve(object sender, ConditionalEventArgs e)
{
if (this.StepIDList.FindAll(p => p == this.CurrentIndex).Count == 0)
{
e.Result = true;
}
else
{
e.Result = false;
}
}
private void CalCurrentStep(object sender, EventArgs e)
{
this.StepIDList.Sort(new Comparison<int>((x, y) => x.CompareTo(y)));
if(this.StepIDList.Count>0)
{
this.CurrentIndex = this.StepIDList[0];
}
}
private void FixIsFinal(object sender, ConditionalEventArgs e)
{
if (this.CurrentIndex == this.MaxIndex && this.StepIDList.FindAll(p => p == this.CurrentIndex).Count <= 1)
{
e.Result = true;
}
else
{
e.Result = false;
}
}
private void GetWorkflowID(object sender, EventArgs e)
{
this.Uninstand = this.WorkflowInstanceId.ToString();
}
}
}
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;
using System.Linq;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
namespace StateMachineLibrary
{
public partial class DocFlow: StateMachineWorkflowActivity
{
public static DependencyProperty DocFlowTypeProperty = DependencyProperty.Register("DocFlowType", typeof(string), typeof(DocFlow));
public string DocFlowType
{
get { return (string)base.GetValue(DocFlow.DocFlowTypeProperty); }
set { base.SetValue(DocFlow.DocFlowTypeProperty, value); }
}
public static DependencyProperty StepIDListProperty = DependencyProperty.Register("StepIDList", typeof(System.Collections.Generic.List<int>), typeof(DocFlow));
public System.Collections.Generic.List<int> StepIDList
{
get { return (System.Collections.Generic.List<int>)base.GetValue(DocFlow.StepIDListProperty); }
set { base.SetValue(DocFlow.StepIDListProperty, value); }
}
public static DependencyProperty UninstandProperty = DependencyProperty.Register("Uninstand",typeof(string),typeof(DocFlow));
public string Uninstand
{
get { return (string)base.GetValue(DocFlow.UninstandProperty); }
set { base.SetValue(DocFlow.UninstandProperty, value); }
}
public static DependencyProperty CurrentIndexProperty = DependencyProperty.Register("CurrentIndex", typeof(int), typeof(DocFlow));
public int CurrentIndex
{
get { return (int)base.GetValue(DocFlow.CurrentIndexProperty); }
set { base.SetValue(DocFlow.CurrentIndexProperty, value); }
}
private int MaxIndex = 0;
private int MinIndex = 0;
private void autoResearch(object sender, EventArgs e)
{
if(this.DocFlowType.Equals("fix",StringComparison.OrdinalIgnoreCase))
{
this.FindMinMax();
}
}
private void FindMinMax()
{
this.StepIDList.Sort(new Comparison<int>((x, y) => x.CompareTo(y)));
this.MinIndex = this.StepIDList[0];
this.MaxIndex = this.StepIDList[this.StepIDList.Count-1];
this.CurrentIndex = this.MinIndex;
}
private void FixCurrentRemove(object sender, EventArgs e)
{
if (this.DocFlowType.Equals("fix", StringComparison.OrdinalIgnoreCase))
{
this.StepIDList.Remove(this.CurrentIndex);
}
}
private void CheckDocType(object sender, ConditionalEventArgs e)
{
if (this.DocFlowType.Equals("fix", StringComparison.OrdinalIgnoreCase))
{
e.Result = true;
}
else
{
e.Result = false;
}
}
private void CurrentIsOve(object sender, ConditionalEventArgs e)
{
if (this.StepIDList.FindAll(p => p == this.CurrentIndex).Count == 0)
{
e.Result = true;
}
else
{
e.Result = false;
}
}
private void CalCurrentStep(object sender, EventArgs e)
{
this.StepIDList.Sort(new Comparison<int>((x, y) => x.CompareTo(y)));
if(this.StepIDList.Count>0)
{
this.CurrentIndex = this.StepIDList[0];
}
}
private void FixIsFinal(object sender, ConditionalEventArgs e)
{
if (this.CurrentIndex == this.MaxIndex && this.StepIDList.FindAll(p => p == this.CurrentIndex).Count <= 1)
{
e.Result = true;
}
else
{
e.Result = false;
}
}
private void GetWorkflowID(object sender, EventArgs e)
{
this.Uninstand = this.WorkflowInstanceId.ToString();
}
}
}
主要是StepIDList用于记录固定工作流的步骤序号,DocFlow用于记录工作流类型 CurrentIndex 记录当前步骤号
其它的就是分析最小和最大号,找寻下部号,已经相关的流转控制。还有一些是访问后台数据库的服务。
用户操作界面
审批界面