例-常用普通的简单例子

  • 概述

    • 一般的最常用的简单例子,主要介绍整个工作流的一个步骤流程
  • 示例

    这里主要介绍大致的步骤:

    首先,就是画流程图了,可从“系统管理”模块下的“工作流管理”-“业务流程定义”菜单进入:

    ordinary-1

    新建工作流,选择“实体名称”,填写“流程描述”,其他无特殊需要时都可不用设置:

    ordinary-2

    根据业务需求,开始画流程的每个任务步骤和连线:

    ordinary-3

    画好后,就开始设置每个任务步骤,右键对应的任务步骤,在弹出的窗口中设置,

    无特殊要求时,只要设置“任务类型”、“动态指定执行人”,选择添加权限用户或权限角色即可:

    ordinary-4

    ordinary-5

    接着可设置连线的条件,同样是右键对应的连线来打开设置窗口:

    ordinary-6

    当然了,设置条件前,需要先添加作条件的字段,从“数据集合管理”页面来添加:

    ordinary-7

    如果需要用到一些JS处理事件时,就从工具栏打开各步骤的JS设置页面:

    ordinary-8

    以上各步设置时,记得确定保存,最后再点击定义的主页面工具栏的“保存”按钮保存整个

    流程图,至此,一个简单的流程图就画好了。

    接着就是要启动引擎,准备跑下流程,看是否正确,

    点击“启动”按钮启动引擎:

    ordinary-9

    引擎启动后,进入具体业务的网格页面,选择要测试的记录,点“提交”按钮提交工作流,如果设置正确

    的话,就会提示“提交成功”的信息,失败的话,就要找原因,比如引擎和WEB.CONFIG设置是否对应、正确,

    流程图的提交前事件、同实体多流程区分标识的设置等等是否正确。

    提交成功后,进入“我的工作台”下的“工作内容”,双击当前流程记录,开始接下去的审批操作:

    ordinary-10

    这是审批页面,填写意见,点击相应的按钮进行操作,如“同意”、“不同意”、“终止”等:

    ordinary-11

    审批过程中,要注意看下步步骤的审批用户是否和业务要求的一致、当中要修改的数据库相应

    数据是否修改了、流程是否按实际的流向条件走、动态执行人是否按设置的体现等等。

    经过多次跑流程测试(流程图画好后,一定要跑流程测试),一个简单的工作流就完成了。

    如果需发给现场,就用工具栏的导出按钮来导出该工作流的整个对象,发给现场导入即OK。

  • 相关链接

    工作流引擎设置(WorkFlowEngine)

    工作流流程图定义(WorkFlowDesign)

    工作流信息设置

    数据集合管理

    任务步骤设置

    条件设置

    任务步骤按钮JS设置

    工作流前端应用(WorkFlowApply)


例-提交时自动指定或弹窗选择用户

  • 概述

    • 流程提交时,需自动指定相应的用户,或是弹窗选择对应的用户
  • 示例

    submit-1

    在这里设置是否要弹窗选择用户,或是自已写代码处理自动传指定用户。

    <ToolBar UniqueNo="0">
          <UserButtons>
            <Button Target="Grid" Name="cmd提交" Text="提交" ToolTip="提交" Type="Normal" Image="WebToolBar/16_Import.gif" DisplayMode="TextAndImage" Script="WFSubmit()"></Button>
          </UserButtons>
          <Scripts>
            <Script>
              <![CDATA[
    
                 function __WFGetSumbitUserList(){ //重载,返回提交用户ID集合,系统自动会调用执行此函数
    
                     //代码段,如调用Webservice
                     //....
    
                     return "aaaid;bbbid;cccid"; //返回
                 }
    
               ]]>
            </Script>
          </Scripts>
        </ToolBar>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20

例-动态指定下一步骤执行人

  • 概述

    • 和“提交”时的指定是不一样的,这里是指在审批过程中,动态指定下一步骤的审批用户
  • 示例

    例如:A—>B—>C—>D流程,D步骤要由当前记录对应的部门主管来审批,那么这就无法事先在画流程图时就设置好

    权限用户、角色了,所以D步骤的“动态指定执行人”要设置为“是”,表示在C步审批时,动态指定D步的审批用户,

    如下图,C步审批时,在审批页面上会出现“下步执行人”的选择控件,选择好后审批。

    Executive-1

    这里的选择窗口默认是列出全部的用户,但有些业务可能要求不列出全部的用户来供选择,这时就要在D步的

    “用户(动态执行人)”、“角色(动态执行人)”上设置添加这部分供选择的用户,这样选择窗口中就会

    只列出这部分的用户来供选择。

    上面这种方式是需要弹窗手工选择,当然了,有时客户要求不要手工选择,要自动选好下步执行人,那要怎么做呢?

    其实这里就可以变通一下了,我们只要把“下步执行人”的文本框中自动填好指定用户,然后再把“下步执行人”

    整个控件隐藏了,是不是让人看起来就像是自动指定了?对,就是这个效果了。实现这个效果需要我们自己写JS代码,

    设置在D步骤那里的“页面加载事件”,填个方法名。

    Executive-2

    这个JS代码需包括几个内容,如下例子:
        function JSFUN1(){
            var userList="";
    
            //代码段,JS+WebService,获取要指定的用户ID
            //userList=....
    
            $("#DynamicUserValue").val(userList); //将用户ID字符串赋值给“下步执行人”文件框
    
            $("#DynamicObj").hide(); //隐藏“下步执行人”整个控件
        }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

例-审批过程中显示不同的业务展现页面

  • 概述

    • 设置在流程审批过程,不同步骤的审批页面中,“业务展现”可设置成不同的业务FORM页面,

      如果不设置,那所有步骤的审批页面的“业务展现”都是同一个FORM页面。

  • 示例

    如下图,在对应步骤的“页面加载事件”上设置,

    business

    可调用 wm.wf.setFormUniqueNo(FormUniqueNo) 或 wm.wf.setFormUrl(Url) 两个通用函数,一个是通过设置

    UniqueNo,一个是直接设置具体的URL地址

    如:

    wm.wf.setFormUniqueNo('111')

    wm.wf.setFormUrl('../Config/Edit.aspx?Mappingid=123456&UniqueNo=0')


例-审批过程需操作到数据库

  • 概述

    • 在流程审批过程中,如果需要操作到数据库时,下面举出几个例子
  • 示例

    有两种实现方式:

    1.在对应步骤中的“任务步骤设置”页面的“事件”页签中添加记录,选择“存储过程”类型:

    process-1

    注:不管是点击同意、不同意或终止按钮,只要这个步骤审批过后都会去执行存储过程

    所以如果设计上只要求同意后才操作数据库的话,则要在存储过程中加判断,判断是审批同意后

    才去执行存储过程中所要处理的部分。

    2.在“工作流前台JS应用”页面中,相应步骤的相关按钮上增加点击前或点击后的JS事件,

    通过JS+WebService方式去操作数据库:

    process-2

  • 相关链接

    任务步骤设置

    任务步骤按钮JS设置


例-批量审批

  • 概述

    • 批量审批
  • 示例

    1.在流程定义中,“工作流信息”设置页面中,设置该流程为可批量审批

    2.在“工作内容”里的“未审核”页签中,勾选可进行批量审批的业务

    (勾选的记录需为同一实体表),双击,弹出批量审批页面来进行批量审批操作

    3.批量审批页面中的“业务展现”页面,是调用业务的GRID网格页面(需创建虚拟的业务菜单),故相应的业务

    实体配置文件中需配置相关网格页面的UniqueNo,UniqueNo固定为250088(如果一个实体中有多个流程,那么这个UniqueNo

    就要多加上流程的标识,比如流程1的区分标识为“省级”,流程2的区分标识为“市级”,那么UniqueNo应设置为

    250088_省级和250088_市级,也就是说需要创建两个虚拟业务菜单),数据源用自定义数据源,

    过滤条件可从Request取选中的记录ID集合,Reqeust参数为:RecordIds

     <Grid Name="ThisTable" HasPurviewFilter="false" UniqueNo="250088" FreezedIndex="0" AllowEdit="false" HasRowHeader="True" HasChecked="True" OpenCheckedEdit="True"  WinHeight="600px" WinWidth="800px" OpenType="showmodaldialog" EditURL="Config/Edit.aspx">
              <Column Field="Column1" FieldType="VarChar" CaptionText="描述" Width="100"></Column>
              <Column Field="Column2" FieldType="VarChar" CaptionText="描述" Width="100"></Column>
              <DataSource Type="SqlServer">
                  <![CDATA[ 
                     select * from ThisTable where ThisTableId in ({@Request['RecordIds']})
                  ]]>
              </DataSource>
              <DataSource Type="Oracle">
                  <![CDATA[ 
                     select * from ThisTable where ThisTableId in ({@Request['RecordIds']})
                  ]]>
              </DataSource>
          </Grid>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

    注:批量审批仅对于一些比较简单的审批流程的使用,如果有审批前后事件、需选择执行人等处理的话,最好不要使用批量审批,

    ​ 因为这些处理无法调用执行到。


例-不填写审批意见可提交

  • 概述

    • 添加JS后代码后,不填写审批意见直接提交后,审批意见为点击按钮的显示文本。
  • 示例

    在项目根目录下的JavaScript\User\User_WFlow.js中添加代码。
    function takeche()
    {//用来让审批意见可以不填 不填的时候 根据点击按钮的文本值填充进去
        if($("#__OptionCheck").length)
            $("#__OptionCheck").val(true);
    }
    $(takeche);
    
    1
    2
    3
    4
    5
    6
    7

例-审批中手动选择下个步骤

  • 概述

    • 有些业务可能要求在某个步骤审批时,可以手动选择下个审批步骤。
  • 示例

    有些业务可能要求在某个步骤审批时,可以手动选择下个审批步骤,此时可以在该步骤的“任务步骤设置里”基础设置中,

    将“同意时选择下步骤”选项目设置为“是”即可实现该需求。

    审批时,点“同意”按钮,会弹出一个选择窗口来选择下个步骤,如下图,当前步骤是“主管审批”,其直接的下几个步骤有两个,

    选择其中的一个,点确定后,流程就往这个步骤走:

    Manual


例-Visio流程图相关

  • 概述

    • Visio流程图相关例子,包括画图,展现
  • 示例

    • 1.Visio流程图定义页面

      画Visio流程图的页面和工作流定义页面不太一样,地址为:WorkFlow/WorkFlowDesign/WFlowMain.aspx?flowType=Visio

      比工作流定义页面多加了flowType参数,如果项目要用到,需要自己添加业务菜单。

      画流程图和画工作流的是一样的操作。

    • 2.Visio流程图展现

      展现的地址为:WorkFlow/WorkFlowApply/WFlowVisio.aspx?WFObjectId=2fd308bf-c9a1-4956-9ccd-48731a862e44,

      WFObjectId参数为:工作流文件名。

      显示页面如下:

      Visio-1

    • 3.一些可能用到的JS:

      因为流程图展现页面是通用页面,如果要添加一些JS事件,是不能直接在该页面上写JS事件,这时可以在流程图定义那里添加:

      Visio-2

      将加载事件写在User_WFlow.js文件里,然后在加载事件里写自己要处理的JS。

    • 下面是例子(包括给步骤加各种事件,改变颜色等):

      //流程跟踪图加载事件
      function aab()
      {     
         //给每个步骤加点击事件
         for(var i = 0; i < flowObj.Activitys.length; i++){
              var Act = flowObj.Activitys[i]; 
              //01: 填充步骤
              for(var k=0;k<jsonRun.count;k++){
                 if(jsonRun.data[k].RUNNINGSTEP == Act.id){  
                     Act.fillColor = jsonRun.data[k].COLOURCODE;
                     document.getElementById(Act.id).fillColor =jsonRun.data[k].COLOURCODE;   //步骤颜色
                 }
              }   
      
              //02:弹出页面事件
              for(var j=0;j<jsonShow.count;j++){
                 if(jsonShow.data[j].STEPID == Act.id){
                   //绑小图片,可弹出窗口
                   flowObj.attachObjectEvent(Act.id,"activity","onclick","showClick","弹出窗口事件");    //先添加事件到数组中
                 }
              } 
         } 
         flowObj.addEvent();   //真正将事件添加到步骤上
      
         //每个步骤的事件
         for(var i = 0; i < flowObj.Activitys.length; i++){
             var Act = flowObj.Activitys[i]; 
             document.getElementById(Act.id).bind( "click", window["stepClick"]);  //直接绑步骤单击事件    
         } 
      
         //填充线条  
         for(var l=0; l<flowObj.Transitions.length; l++){  
              for(var k=0;k<jsonRun.count;k++)
              {
                  if(jsonRun.data[k].RUNNINGSTEP == flowObj.Transitions[l].fromAct && jsonRun.data[k].NEXTSTEP == flowObj.Transitions[l].toAct)
                  { 
                      $(flowObj.Transitions[l].id)[0].strokecolor= jsonRun.data[k].COLOURCODE; //线条颜色
                  }
              }
         }  
      } 
      
      function stepClick()
      {
        //步骤直接点击事件处理
        //...
      }
      
      function showClick(curStep)
      {   
        //步骤小图片点击事件处理
        //...
      } 
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53

例-自定义权限用户

  • 概述

    • 在流程图相应的任务步骤上设置“自定义权限用户”,可真正实现动态设置审批用户
  • 示例

    经常有这样的需求,提交人提交的申请要提交给对应的上级经理审批,

    原来的做法一般是通过JS调用WebService来取到对应的上级经理,

    现在多了一种方式,直接在流程相应步骤上设置“自定义权限用户”即可,如下图所示,

    可填写Select语句或是存储过程,伪变量只有包含记录ID('{@RecordId}'),

    注:

    第一列返回用户ID,

    第二列返回用户权限(会签一人有特权类型时才用到,1=普通权限,2=否决权限,其他情况下可不传或传1)

    第三列返回判定分值(会签N人有特权类型时才用到,填写分值,如60,其他情况下可不传或传任意大于0的整数)

    jurisdiction

    SQLSERVER存储过程例子:
    ALTER procedure [dbo].[SP_Test]
     @RecordId varchar(50)
    as
    begin
      --第一列用户ID,第二列用户权限(1=普通权限,=否决权限),第三列判定分值
      --第二列和第三列在会签类型(一人有特权、N人有特权)时才用到,其他情况下可只返回第一列
      select '88888888-8888-8888-8888-888888888888',2,60
      union 
      select '49e2a44e-5370-4392-9b70-e7703c1baa13',1,40
    end
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    ORACLE存储过程例子:
    
    CREATE OR REPLACE procedure SP_Test(
    P_RecordId varchar2,
    myCursor out sys_refcursor
    )
    is
    
    begin
    
      open myCursor for
       select '88888888-8888-8888-8888-888888888888',2,60 from dual
       union
      select 'a589da05-bba3-48a0-8d21-67767610a292',1,40 from dual;
    
    end SP_Test;
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16

例-自定义C#代码调用

  • 概述

    • 在自己的C#代码中启动或呼叫工作流引擎
  • 示例

      /// <summary>
      /// 启动新工作流
      /// </summary>
      /// <param name="XMLCon">参数XML</param>
      /// <returns></returns>
      [LogicMethod]
      public string StartWorkFlow(string XMLCon)
      {
      	XmlDocument doc = new XmlDocument();
      	doc.LoadXml(XMLCon);
      	XmlNode root = doc.SelectSingleNode("XMLCon");
    
      	string TableName = root.Attributes["TableName"].Value;
      	string RecordId = root.Attributes["RecordId"].Value;
      	string WFObjectId = root.Attributes["WFObjectId"].Value;
      	string CurrentUserId = root.Attributes["CurrentUserId"].Value;
      	string NewUser = root.Attributes["NewUser"].Value;
      	string SysMappingId = root.Attributes["SysMappingId"].Value;
    
      	//取备注信息
      	string wfMemo = "";
      	string sqlMemo = root.SelectSingleNode("MemoSQL").InnerXml;
      	if (!string.IsNullOrWhiteSpace(sqlMemo))
      	{
      		sqlMemo = sqlMemo.UnCommentXml().Replace("{@RecordId}", RecordId);
      		if (!string.IsNullOrWhiteSpace(sqlMemo))
      		{
      			try
      			{
      				wfMemo = Wima.DAL.SysDba.Adapter.ExecuteScalarForString(sqlMemo);
      			}
      			catch { }
      		}
      	}
    
      	string result = string.Empty;
    
      	string xml = "<Item ";
      	xml += "KeyValue=\"5\" ";
      	xml += "Id=\"" + Guid.NewGuid().ToString() + "\" ";
      	xml += "Type=\"\" ";
      	xml += "WorkflowId=\"" + Guid.NewGuid().ToString() + "\" ";
      	xml += "ActivityId=\"\" ";
      	xml += "User=\"" + CurrentUserId + "\" ";
      	xml += "ToUser=\"\" ";
      	xml += "NewUser=\"" + NewUser + "\" ";
      	xml += "ObjectId=\"" + WFObjectId + "\" ";
      	xml += "RecordId=\"" + RecordId + "\" ";
      	xml += "WFMemo=\"" + wfMemo + "\" ";
      	xml += "SysMappingId=\"" + SysMappingId + "\" ";
      	xml += "RollBackActivity=\"\" ";
      	xml += "Command=\"start\" ";
      	xml += ">";
      	xml += "</Item>";
    
      	bool enableEngine = AppSetting.GetBoolean("enableWorkflowEngine", true);
      	if (enableEngine)
      	{
      		// 流程引擎独立运行或者服务方式运行调用方式
      		byte[] buf = new byte[1024];
      		int count = 0;
      		try
      		{
      			Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
      			socket.Connect(EngineServer, Convert.ToInt32(EnginePost));
      			socket.Send(System.Text.Encoding.Default.GetBytes(xml));
      			count = socket.Receive(buf);
      			socket.Shutdown(SocketShutdown.Both);
      			socket.Close();
    
      			string ret = System.Text.Encoding.Default.GetString(buf, 0, count);
      			return ret.EqualIgnoreCase("ok") ? "1" : "0";
      		}
      		catch(Exception ex)
      		{
      			LogHelper.Write(ex);
      			return "0";
      		}
      	}
      	else
      	{
      		// 流程引擎集成运行方式(单独的dll)调用方式
      		return EngineManager.Instance.Execute(xml) ? "1" : "0";
      	}
      }	
    
      /// <summary>
      /// 呼叫工作流引擎
      /// </summary>
      /// <param name="XMLCon">参数XML</param>
      /// <returns></returns>
      [LogicMethod]
      public string CallWorkFlow(string XMLCon)
      {
      	//XmlDocument doc = new XmlDocument();
      	//doc.LoadXml(XMLCon);
    
      	bool enableEngine = AppSetting.GetBoolean("enableWorkflowEngine", true);
      	if (enableEngine)
      	{
      		// 流程引擎独立运行或者服务方式运行调用方式
      		string r = "";
      		byte[] buf = new byte[1024];
      		int count = 0;
      		try
      		{
      			Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
      			socket.Connect(EngineServer, Convert.ToInt32(EnginePost));
      			socket.Send(System.Text.Encoding.Default.GetBytes(XMLCon));//doc.InnerXml));
      			count = socket.Receive(buf);
      			socket.Shutdown(SocketShutdown.Both);
      			socket.Close();
    
      			string ret = System.Text.Encoding.Default.GetString(buf, 0, count);
      			return ret.EqualIgnoreCase("ok") ? "1" : "0";
      		}
      		catch (Exception ex)
      		{
      			LogHelper.Write(ex);
      			return "0";
      		}
      	}
      	else
      	{
      		// 流程引擎集成运行方式(单独的dll)调用方式
      		return EngineManager.Instance.Execute(XMLCon) ? "1" : "0";
      	}
      }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128