我的微型工作流引擎-办公应用实战

一、前言

    前面已经给大家介绍了我的工作流引擎的总体设计及的API设计,这篇是实战篇说说怎么实际应用了,这就得涉及到UI界面了。首先我们常用的工作流个人办公应用系统至少要包括发起流程、待办事项、已办事项等。我们设计了一个尽量简单的系统,能够满足个人办公的基本需求,只实现以下功能:
    1、发起流程
    2、待办事项
    3、已办事项
    4、我的流程
    5、我的消息
    6、我的委办

这些功能基本就是流程能正常的运行流转基础,其实只应用了我们引擎的一小部分功能,其它功能如果有需要可以在这基本上再添加。

二、页面设计及实现

    1、发起流程,很简单的一个页面,左边显示已发布流程列表,右边放置一个iframe用于显示对应的启动表单image

左边流程列表数据:

select * 
  from bpm_definition_process
 where state = 'Deploy'

左边根据流程定义的分类显示为树形结构,点击选择左边流程时,右边iframe打开对应流程的启动表单页面即可。

点击发起流程按钮时,调用ajax处理,把表单数据传到后台,后台处理逻辑如下:

//1 保存表单返回表单数据id
var id = ...;

//2 启动流程
 var process = bpm.NewProcessIntance(processId, id);
 var task = process.Start();

 //3 发送到下一步审批
 task.SetRecord(id);
 task.Signal();

 

2、待办事项,也就是我的任务工作的列表image

列表的数据查询:

select * 
  from bpm_instance_task
 where state = 'Run'
   and actor_id = @user_id

双单或点击办理时,打开表单展示页面:
表单审批页签,在这里可以查看表单录入的数据,查看历史审批情况,或进行审批操作,可设置签章
image

当然每个审批节点都可以有自己的表单也可以通过参数,来控制以下各元素的是否需要显示:审批选项、审批意见、添加附件、指定下一步审批人
image
按钮逻辑
保存即只保存表单数据怎么保存可以自己定义
转交下一步逻辑:

//加载任务实例
var task = bpm.LoadTaskInstance(taskInstanceId);

//如果有新表单,保存表单数据返回ID,
var id = ...;
task.SetRecord(id)

//如果有附件,保存附件,返回附件ID列表
var attachments = ...;
task.SetAttach(attachments); 

//如果需要设置下一步审批人
 task.SetReceiver(receiver); 

//如果需要设置自由跳转的目标工作项
task.SetFreeRedirect(redirect); 

//设置审批意见
task.SetOpinion(choice, comment);    

//设置审批签章
task.SetSignature(signature);        
 
//转交下一步
task.Signal();

基本信息页签:
image

流程图页签:
image

流程图是我通过raphaeljs实现的,接收工作项及路由(连接线)的数据展现图形,根据数据自动计算每个工作任务的位置和连线,目前只实现了图形展示功能,还没有去实现拖拉设计的功能。
image

关于我的表单的设计和流程图的展示,后续有时间我会跟大家详细介绍。不过这和工作流引擎没什么关系了,这两块每个人的设计可能都会不尽相同,但并不会影响工作流引擎的使用。
这个页面还有一个委办的功能
image

后台逻辑:

bpm.NewDeputeService(user.Id, tarActorId)    //委托人、受托人
   .ForTaskInstance(taskInstanceId)          //工作项ID
   .SetDateRange(effectDate,expireDate)      //生效时间、失效时间
   .SetMemo(memo)                            //委托备注
   .Depute();

 

3、已办事项,即我的已完成的工作列表
image

数据列表中的查询:

select * 
  from bpm_instance_task
 where state = 'Complete'
   and actor_id = @user_id

仅仅一个查询页面,非常简单,双击时也打开表单展示页面,但是当前节点不是运行状态时是只能查看不能编辑的。

4、我的流程,这些页面都是一个数据查询页,没有什么逻辑,所以都很简单
image
催办逻辑:

//工作催办
var taskInstanceId = '当前运行节点实例id';
var task = bpm.LoadTaskInstance(taskInstanceId);
task.Urge("很急,请经理尽快处理,在线等!");

5、我的消息
image

数据列表查询:

select * 
  from bpm_application_notify
 where reciever_id = @user_id
   and push_type = 'System'

6、我的委托
image

数据列表查询:

select * 
  from bpm_application_depute
 where src_actor_id = @user_id
   and effect_date <= @now
   and expire_date >= @now

 

三、流程定义及表单设计

    这块的东西做到在页面上很方便的拖拉定义而且还要好用的话,是有一定难度的,其实我们有做一些页面尝试设计定义,但是都不好用而且很费时间折腾。其实这一块是开发人员使用的比较多,并不会影响客户使用,所以优先级靠后点,以后有精力再来开发。
    我们现在的解决方案是,在项目目录下建了一个Definitions的目录:
image
每个流程新建一个目录,比如合同审批目录下存放,“流程定义.xml”及“合同审批表.cshtml”
image
对这个流程定义的修改,直接修改这两个文件即可,两个文件内容如下:
1、流程定义.xml

<?xml version="1.0" encoding="UTF-8"?>

<process name="合同审批流程" category="项目流程">  
  
  <start name="合同审批开始" app-form="合同审批表.cshtml" app-enable-attach="true">
    <transition to="项目负责人或材料负责人"></transition>
  </start>
    
  <task name="项目负责人或材料负责人" >
    <transition to="分管副总"></transition>
    <action  script="log.Debug('项目负责人或材料负责人签字');"></action>
    <assignment owner="pan"></assignment>
  </task>
  
  <task name="分管副总" >
    <transition to="工程经营部"></transition>
    <action  script="log.Debug('分管副总签字');"></action>
    <assignment owner="lhs"></assignment>
  </task>
  
  <task name="工程经营部" >
    <transition to="财务部"></transition>
    <action  script="log.Debug('工程经营部签字');"></action>
    <assignment owner="pan"></assignment>
  </task>

  <task name="财务部" >
    <transition to="法务部"></transition>
    <action  script="log.Debug('财务部签字');"></action>
    <assignment owner="yrh"></assignment>
  </task>
  
  <task name="法务部" >
    <transition to="常务副总"></transition>
    <action  script="log.Debug('法务部签字');"></action>
    <assignment owner="czm"></assignment>
  </task>
  
  <task name="常务副总" >
    <transition to="总经理"></transition>
    <action  script="log.Debug('常务副总签字');"></action>
    <assignment owner="zfg"></assignment>
  </task>
  
  <task name="总经理" >
    <transition to="合同审批结束"></transition>
    <action  script="log.Debug('总经理签字');"></action>
    <assignment owner="lhs"></assignment>
  </task>


  <end name="合同审批结束">
    
  </end>
</process>

2、合同审批表.cshtml

<table class="form-body">
    <colgroup>
        <col style="width:15%"  />
        <col style="width:35%"  />
        <col style="width:15%"  />
        <col style="width:35%"  />
    </colgroup>
    <tr>
        <td class="title" >所属项目</td>
        <td class="input">@Controls.Render("input","project_name")</td>
        <td class="title" >合同编号</td>
        <td class="input">@Controls.Render("input","contract_id")</td>
    </tr>
    <tr>        
        <td class="title" >合同名称</td>
        <td class="input">@Controls.Render("input","contract_name")</td>
        <td class="title" >报批时间</td>
        <td class="input">@Controls.Render("datebox","audit_date")</td>
    </tr>     
    <tr>
        <td class="title" >合同己方</td>
        <td class="input">@Controls.Render("input","contract_own")</td>
        <td class="title" >合同对方</td>
        <td class="input">@Controls.Render("input","contract_other")</td>
    </tr>
    <tr>
        <td class="title" >合同金额</td>
        <td class="input">@Controls.Render("input","amount_contract")</td>
        <td class="title" >预算金额</td>
        <td class="input">@Controls.Render("input","amount_budget")</td>
    </tr>
     <tr>
        <td class="title" >合作方式</td>
        <td class="input">@Controls.Render("input","procurement_method")</td>
        <td class="title" >合同份数</td>
        <td class="input">@Controls.Render("input","copies_contract")</td>
    </tr>
</table>

修改完这两个文件后,运行“流程定义工具.bat”实现上是调用一个我写的控制台应用程序,输入“deploy 流程名称”即可完成发布
image

这样使用对于开发人员来说还是很方便的,但是对于不懂开发的人来说就有一定难度了
1、把xml编辑变成图形拖拉
2、把cshtml文件编辑变成控件拖拉
这两点我们以后再想办法实现,无论怎样,现在这样是可以使用了,除了自定义流程,其它都没有任何问题。

四、总结说明

    这个示例程序是拿我们以前的项目UI来实现的,用什么界面都没问题,主要是给大家介绍下这款工作流引擎的实际应用。关于流程设计器及表单设计器这个我以后有时间间精力会慢慢开发。如果大家有什么意见或建议欢迎给我留言。

posted @ 2015-09-29 10:13  萧秦  阅读(8184)  评论(14编辑  收藏  举报