出处:http://www.cnblogs.com/flyskyer/archive/2009/03/11/1408578.html
最近因为接手离职同事的公文审批(没有使用工作流)维护,感觉很麻烦,于是在我开发的工作流平台上重新写了相关的功能,扩展同事的功能,同时可以支持固定流和任意流功能。希望大哥们给予指点。
固定流就是由发起人定义审批的步骤,流程按照既定步骤执行。
任意流就是由发起人发起,选择下一步审批人审批,然后审批再选择下一步审批人。
当然公文审批支持的电子签名的功能也有,但是不作为本篇讨论内容,还有界面美观。
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 } }
现在支持前进,抄送(平台功能)和终止,还不支持会退和跳批。
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 )
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(); } } }
主要是StepIDList用于记录固定工作流的步骤序号,DocFlow用于记录工作流类型 CurrentIndex 记录当前步骤号
其它的就是分析最小和最大号,找寻下部号,已经相关的流转控制。还有一些是访问后台数据库的服务。
用户操作界面
审批界面