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

审批界面

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?