移动审批工作流设计与实现

简介:

在企业中,大部分重要的业务需要进行审批,由于具有决定权的领导者事务繁忙或者受环境或低于限制,没法通过互联网进行工作处理。

移动审批,通过手机方便快捷地登陆企业内部网及互联网,即使处于无线的状态下,也能进行远程办公,以此来提高对于突发事件的反应能力,提升企业竞争力。

    这篇文章我将使用iPhone作为移动终端进行设计与实现,iPhone引入了基于大型多触点显示屏和领先性新软件的全新用户界面,让用户用手指即可控制iPhone。iPhone还开创了移动设备软件尖端功能的新纪元,重新定义了移动电话的功能。iPhone开发中,除了比较复杂的游戏开发,还有一种就是跟数据库打交道的应用程序,这可以在本文中得到体现。

   WF4.0是微软提供的一套工作流开发框架,里面包含:流程设计器,各种类型封装好的工作流活动,持久化服务,WCF服务等功能。这篇文章我将结合iPhone+WF4.0实现移动审批工作流。通过一个简单的例子你可以清楚的看到与数据库相关的iPhone应用程序的开发,以及使用iPhone+WCF+WF实现移动审批的各种关键技术的使用。

   设计架构图:由于是使用了WCF的restful服务,所以其它手机平台也会很方便使用此工作流服务。

   iPhone客户端的表单可以通过从服务端设计的表单结构的XML动态产生。

   下面通过一个简单的请假流程说明如何实现:

  用例流程图:

   上面的流程大致为:申请人在iPhone上打开请假流程,填写姓名和请假天数,点击提交,这个流程将走到他的上级,上级进行审批,并将审批结果通过短信知道申请者。

参考上图,通过WF4.0设计器设计一个流程,如下图:

下面我使用WCF将此流程封装到restful服务中。

wcf restful服务设计如下:

复制代码
[ServiceContract]
public interface  IRestServiceImpl
{
/// <summary>
///  获取未审核列表
/// </summary>
/// <returns></returns>
[OperationContract]
[WebInvoke(Method 
= " GET " ,
ResponseFormat 
=  WebMessageFormat.Json,
BodyStyle 
=  WebMessageBodyStyle.Wrapped,
UriTemplate 
= " getleavelist " )]
List
< Leave >  GetLeaveList();
/// <summary>
///  启动流程
/// </summary>
/// <param name="name"></param>
/// <param name="day"></param>
/// <returns></returns>
[OperationContract]
[WebInvoke(Method 
= " POST " ,
ResponseFormat 
=  WebMessageFormat.Xml,
BodyStyle 
=  WebMessageBodyStyle.Wrapped,
UriTemplate 
= " createleave/{name}/{day} " )]
string  CreateLSeave( string  name,  string  day);

/// <summary>
///  审批流程
/// </summary>
/// <param name="id"></param>
/// <param name="comment"></param>
/// <returns></returns>
[OperationContract]
[WebInvoke(Method 
= " POST " ,
ResponseFormat 
=  WebMessageFormat.Xml,
BodyStyle 
=  WebMessageBodyStyle.Wrapped,
UriTemplate 
= " auditingleave/{id}/{comment} " )]
string  AuditingLeave( string  id,  string  comment);
}
复制代码

数据库设计:

1、WF持久化数据表:使用WF自带的数据表。

 

2、业务数据表:请假单,设计如下:

WF流程启动和运行代码:

复制代码
public class  WorkFlowProcess
{
static string  constring  = " Data Source=PC-ZHUQL\\ZHUQL;Initial Catalog=TestDB;Integrated Security=True;Pooling=False " ;
static  AutoResetEvent instanceUnloaded  = new  AutoResetEvent( false );

static  Hashtable InstanceHashtable  = new  Hashtable();

public static string  RunInstance(Guid ID, string  Comment)
{
SqlWorkflowInstanceStore instanceStore 
= new  SqlWorkflowInstanceStore(constring);
WorkflowApplication application1 
= new  WorkflowApplication( new  LeaveProcess());
application1.InstanceStore 
=  instanceStore;
application1.Completed 
=  (workflowApplicationCompletedEventArgs)  =>
{
Console.WriteLine(
" \nWorkflowApplication has Completed in the {0} state. " , workflowApplicationCompletedEventArgs.CompletionState);
};
application1.Unloaded 
=  (workflowApplicationEventArgs)  =>
{
Console.WriteLine(
" WorkflowApplication has Unloaded\n " );
instanceUnloaded.Set();
};
application1.Load(ID);
application1.ResumeBookmark(
" Check " , Comment);
instanceUnloaded.WaitOne();
return " success " ;
}

//  creates a workflow application, binds parameters, links extensions and run it
public static string  CreateAndRun( string  LeaveName,  int  LeaveDay)
{
SqlWorkflowInstanceStore instanceStore 
= new  SqlWorkflowInstanceStore(constring);

InstanceView view 
=  instanceStore.Execute(instanceStore.CreateInstanceHandle(),  new  CreateWorkflowOwnerCommand(), TimeSpan.FromSeconds( 30 ));

instanceStore.DefaultInstanceOwner 
=  view.InstanceOwner;

IDictionary
< string object >  input  = new  Dictionary < string object >  
{
" LeaveName "  , LeaveName },
" LeaveDay "  , LeaveDay }
};

WorkflowApplication application 
= new  WorkflowApplication( new  LeaveProcess(), input);

application.InstanceStore 
=  instanceStore;

application.PersistableIdle 
=  (e)  =>
{
instanceUnloaded.Set();
return  PersistableIdleAction.Unload;

};

application.Unloaded 
=  (e)  =>
{

instanceUnloaded.Set();

};
application.OnUnhandledException 
=  (ex)  =>
{
Console.Write(
" Exception " );
return  UnhandledExceptionAction.Terminate;
};
Guid id 
=  application.Id;
application.Run();
instanceUnloaded.WaitOne();
return " success " ;
}

//  executed when instance is persisted
public static void  OnWorkflowCompleted(WorkflowApplicationCompletedEventArgs e)
{
}

//  executed when instance goes idle
public static void  OnIdle(WorkflowApplicationIdleEventArgs e)
{
}

public static  PersistableIdleAction OnIdleAndPersistable(WorkflowApplicationIdleEventArgs e)
{
return  PersistableIdleAction.Persist;
}
}
复制代码

iPhone客户端调用:

在前一篇文章:iPhone中调用WCF RESTFUL Service,讲解了iPhone中如何调用WCF restful服务,下面用启动流程为例说明:

复制代码
- (IBAction) btnSender:(id)sender
{
NSString 
*  urlString  = @" http://10.5.23.117:8008/RestServiceImpl.svc/createleave/%@/%@ " ;
NSURL 
* url  =  [NSURL URLWithString:[NSString stringWithFormat:urlString,txtName.text,txtDay.text]];
ASIHTTPRequest 
* request  =  [ASIHTTPRequest requestWithURL:url];
[request setRequestMethod:
@" POST " ];
[request startSynchronous];
NSError 
* error  =  [request error];
if  ( ! error) {
NSString 
* response  =  [request responseString];
UIAlertView 
* alertView  =  [[UIAlertView alloc] initWithTitle: @" 杩斿洖缁撴灉 "
message:
@" 鎻愪氦鎴愬姛 "
delegate :nil
cancelButtonTitle:
@" OK "
otherButtonTitles:nil];
[alertView show];
[alertView release];
}
}
复制代码

iPhone界面设计:

1、启动流程界面:

2、填写表单信息:

3、启动流程

4、待审核列表:

5、审核界面:

6、审核结果:

这里是个简单的demo,界面非常的简陋。

总结:本文通过一个简单的用例来说明了移动审批流程的各个层面的各种技术的实现。使用这些技术实现一个工作流服务以及工作流客户端界面将非常简单。

代码:http://files.cnblogs.com/zhuqil/RestService.rar

http://files.cnblogs.com/zhuqil/iPhoneView.zip





本文转自麒麟博客园博客,原文链接:http://www.cnblogs.com/zhuqil/archive/2011/05/07/2039983.html,如需转载请自行联系原作者

相关文章
|
17天前
工作流介绍
工作流介绍
|
10月前
工作流
工作流
126 0
|
11月前
|
jenkins 测试技术 持续交付
任务管理,项目管理和目标管理
任务管理,项目管理和目标管理
142 0
|
存储 弹性计算 监控
浅析数据工作流Prefect
简述 Prefect 是一种新的工作流管理系统,专为现代基础设施而设计,由开源的 Prefect Core 工作流引擎提供支持。 用户只需将任务组织成流程,Prefect 负责其余的工作,可让您非常容易使用数据工作流并添加重试、日志记录、动态映射、缓存、失败通知等语义。
|
开发工具 git
GitFlow工作流
GitFlow工作流
|
运维 Shell 调度