• H3流程开发笔记(二)启动一个新流程(下)


    H3流程开发笔记(二)启动一个新流程(上)

    一:定义表单页面

    1.新建StartInstance.aspx页面,修改页面类继承至BasePage

    该页面显示所有的流程模板,选择模板提交后进入启动页(第一个活动项),该页面表单如下:

    image

    Start按钮事件定义如下:

    protected void btnStart_Click(object sender, EventArgs e)
    {
        if (ddlVersion.SelectedIndex > -1)
        {
            //根据流程类型,名称和板本,得到流程模板
            OThinker.H3.WorkflowTemplate.WorkflowTemplate workflow = OThinker.H3.Server.Engine.WorkflowManager.GetWorkflow(ddlFlowType.Text, ddlFlowName.Text, Convert.ToInt32(ddlVersion.Text));
    
            // 开始节点(活动项)
            OThinker.H3.WorkflowTemplate.ActivityTemplate startActivity = workflow.GetActivity(workflow.StartActivity);
            // 开始的表单
            OThinker.H3.WorkflowTemplate.Sheet startSheet = workflow.GetSheet(startActivity.SheetName);
            // URL参数,传入流程类型,名称和版本,以及操作
            System.Text.StringBuilder instanceParamBuilder = new System.Text.StringBuilder();
            foreach (string key in this.Request.QueryString.Keys)
            {
                string lowerKey = key.ToLower();
                if (lowerKey != "mode" &&
                    lowerKey != "workflowpackage" &&
                    lowerKey != "workflowname" &&
                    lowerKey != "workflowversion")
                {
                    if (instanceParamBuilder.Length > 0)
                    {
                        instanceParamBuilder.Append("&");
                    }
    
                    instanceParamBuilder.Append(key + "=" + this.Request.QueryString[key]);
                }
            }
            string url = GetFlowSheetUrl(startSheet);
            this.Response.Redirect(
                url + "?" + Param_Mode + "=" + SheetMode.Originate + "&" +
                 "workflowpackage=" + System.Web.HttpUtility.UrlEncode(workflow.WorkflowPackageName) + "&" +
                 "workflowname=" + System.Web.HttpUtility.UrlEncode(workflow.WorkflowName) + "&" +
                "workflowversion=" + workflow.WorkflowVersion +
                (instanceParamBuilder.Length == 0 ? null : ("&" + instanceParamBuilder.ToString())));
        }
    }

     

    其中GetFlowSheetUrl在BasePage中定义:

    public string GetFlowSheetUrl(OThinker.H3.WorkflowTemplate.Sheet sheet)
    {
        if (string.IsNullOrEmpty(sheet.SheetAddress)) throw new ArgumentNullException(sheet.SheetName + "没有定义表单", "SheetAddress");
        string m_rootUrl = "http://" + HttpContext.Current.Request.Url.Authority;
        if (!string.IsNullOrEmpty(HttpContext.Current.Request.ApplicationPath))
        {
            m_rootUrl += HttpContext.Current.Request.ApplicationPath;
        }
        if (sheet.SheetAddress[0] == '/')
        {
            m_rootUrl += sheet.SheetAddress;
        }
        else
        {
            m_rootUrl += "/" + sheet.SheetAddress;
        }
        return m_rootUrl;
    }

    2.创建表单页面放到Examples/WorkSheets下面,取名为ApplyLeave.aspx(路径和名称自便,这里只是以本人的习惯取的)

    修改页面类继承至BasePage,设计页面如下,全部用Asp.net自带的控件,不用H3的WorkSheet里的控件,怕不好扩展

    image

    提交事件定义如下:

    protected void btnSubmit_Click(object sender, EventArgs e)
      {
          if (string.IsNullOrEmpty(WorkflowName) || WorkflowVersion < 0)
          {
              return;
          }
          DateTime tempTime;
          //验证数据...
          if (!DateTime.TryParse(txtStartDate.Text, out tempTime))
          {
              return;
          }
          if (!DateTime.TryParse(txtEndDate.Text, out tempTime))
          {
              return;
          }
          //保存到流程引擎
          string InstanceName = base.UserValidator.UserName + "的请假申请";//实例名称
          //获取流程模板
          OThinker.H3.WorkflowTemplate.WorkflowTemplate workflow = OThinker.H3.Server.Engine.WorkflowManager.GetWorkflow(WorkflowPackage, WorkflowName, WorkflowVersion);
          string InstanceId=null;
          string workItemId = null;
          //创建流程实例
          OriginateInstance(workflow, InstanceName, ref InstanceId, ref workItemId);        
          //保存到业务库(这里有个问题,如果业务库的操作失败了怎么办,但该方法又不能写在前面,因为WorkItemId得从H3的接口返回)
          Microsoft.Practices.EnterpriseLibrary.Data.Database dataBase = Microsoft.Practices.EnterpriseLibrary.Data.DatabaseFactory.CreateDatabase();
          string sql = string.Format("insert into [ApplyLeaveInfo]  ([startDate],[endDate] ,[ApplyResult],[WorkItemId]) values('{0}','{1}','false','{2}')", txtStartDate.Text, txtEndDate.Text, workItemId);
          dataBase.ExecuteNonQuery(System.Data.CommandType.Text, sql);
          //返回待处理
          Response.Redirect("../../default.aspx");
         
      }
    其中OriginateInstance为创建流程实例的方法,该方法里保存了实例记录,并且通过Soket通知H3服务一个实例创建的消息,服务接到消息后会在WorkItem中插入一条发起的消息,不过还没完,还得要记录下一步的操作数据,要不然下一步的用户在待处理列表里就看不到了

    /// <summary>
    /// 启动一个流程实例,并且提交起始活动项
    /// </summary>
    /// <param name="Workflow">流程模板对象</param>
    /// <param name="InstanceName">实例名称</param>
    /// <param name="InstanceId">实例编号</param>
    /// <param name="workItemId">起始流动项在OT_WorkItem的ID</param>
    public void OriginateInstance(OThinker.H3.WorkflowTemplate.WorkflowTemplate Workflow, string InstanceName, ref string InstanceId, ref string workItemId)
    {
        OThinker.H3.Acl.UserValidator userValidator = this.UserValidator;
    
        if (Workflow == null)
        {
            throw new ArgumentNullException("流程模板不存在", "Workflow");
        }
        //开始一个流程实例
        InstanceId = OThinker.H3.Server.Engine.InstanceManager.CreateInstance(WorkflowPackage,
           WorkflowName,
           WorkflowVersion,
           InstanceName,
           userValidator.UserID,
           null,
           userValidator.Department,
           false,
           "",
           null,
           -1L);
        OThinker.H3.Messages.MessageEmergencyType normal = OThinker.H3.Messages.MessageEmergencyType.Normal;
        if (Workflow.StartWithSheet)
        {
            normal = OThinker.H3.Messages.MessageEmergencyType.High;
        }
        //发送实例消息给服务
        OThinker.H3.Messages.StartInstanceMessage message = new OThinker.H3.Messages.StartInstanceMessage(
            normal,
            InstanceId,
            null,
           OThinker.H3.Instance.PriorityType.Normal,
           false,
            0L,
            -1L,
            null);
        OThinker.H3.Server.Engine.InstanceManager.SendMessage(message);
        //记录WorkItem,失败后尝试10次
        string[] strArray = null;
        for (int i = 0; i < 10; i++)
        {
            System.Threading.Thread.Sleep(1500);
            strArray = OThinker.H3.Server.Engine.WorkItemManager.Query(null,
                new string[] { InstanceId },
                new string[] { userValidator.UserID },
                DateTime.MinValue,
                DateTime.MaxValue,
                OThinker.H3.WorkItem.WorkItemState.Unfinished
                );
            if ((strArray != null) && (strArray.Length != 0))
            {
                break;
            }
        }
        if ((strArray == null) || (strArray.Length == 0))
        {
            throw new Exception("发起流程失败");
        }
        workItemId = strArray[0];
        //提交起始活动项
        SubmitWorkItem(Workflow, workItemId);
    }
    
    /// <summary>
    /// 提交流程步骤
    /// </summary>
    /// <param name="Workflow">流程模板对象</param>
    /// <param name="workItemId">活动项ID</param>
    public void SubmitWorkItem(OThinker.H3.WorkflowTemplate.WorkflowTemplate Workflow, string workItemId)
    {
        OThinker.H3.Acl.UserValidator userValidator = this.UserValidator;
        OThinker.H3.WorkItem.WorkItem workItem = OThinker.H3.Server.Engine.WorkItemManager.GetWorkItem(workItemId);
        workItem.State = OThinker.H3.WorkItem.WorkItemState.Finished;
        //完成活动
        OThinker.H3.Server.Engine.WorkItemManager.FinishWorkItem(workItemId, this.UserValidator.UserID, null, OThinker.Data.BoolMatchValue.Unspecified, null);
        // 设置操作描述(Portal有这一步骤,不知道去掉后会有影响没)
        string description = "submit";
        OThinker.H3.Server.Engine.TokenPool.AppendDescription(workItem.InstanceId, workItem.TokenId, description);
        OThinker.H3.WorkflowTemplate.ActivityTemplate destActivityTemplate = Workflow.GetActivity(DestActivityName);
        //如果地址栏没有传入下一活动名称
        if (destActivityTemplate == null)
        {
            // 需要通知实例事件管理器结束事件
            OThinker.H3.Messages.AsyncEndMessage endMessage = new OThinker.H3.Messages.AsyncEndMessage(
                    OThinker.H3.Messages.MessageEmergencyType.Normal,
                    workItem.InstanceId,
                    workItem.ActivityName,
                    workItem.ReplyID,
                    true,
                    this.UserValidator.UserID,
                    OThinker.Data.BoolMatchValue.Unspecified,
                    null,
                    null);
            OThinker.H3.Server.Engine.InstanceManager.SendMessage(endMessage);
        }
        else
        {
    
            // 准备触发后面Activity的消息
            OThinker.H3.Messages.ActivateActivityMessage activateMessage
                = new OThinker.H3.Messages.ActivateActivityMessage(
                OThinker.H3.Messages.MessageEmergencyType.Normal,
                workItem.InstanceId,
                destActivityTemplate.Name,
                OThinker.H3.Instance.Token.UnspecifiedID,
                null,
                new long[] { workItem.TokenId },
                false,
                OThinker.H3.Messages.ActivateType.Normal,
                null);
    
            // 通知该活动已经完成
            OThinker.H3.Messages.AsyncEndMessage endMessage =
                new OThinker.H3.Messages.AsyncEndMessage(
                    OThinker.H3.Messages.MessageEmergencyType.Normal,
                    workItem.InstanceId,
                    workItem.ActivityName,
                    workItem.ReplyID,
                    false,
                    userValidator.UserID,
                    OThinker.Data.BoolMatchValue.Unspecified,
                    activateMessage,
                    null);
            OThinker.H3.Server.Engine.InstanceManager.SendMessage(endMessage);
        }
    
    }
    源码下源:FlowSite
    
  • 相关阅读:
    Linux学习笔记六----------文件传输
    Linux学习笔记五----------文本编辑
    Linux学习笔记四----------远程连接和SSH
    Linux学习笔记三----------Linux进阶知识和命令
    Linux学习笔记二----------Linux基础知识和命令
    ArcGIS API for JavaScript3.16 使用中遇到的问题,及解决方法
    ArcGIS API for JavaScript学习
    echarts容器动态变化高度
    好用的流程图js插件
    jeecg-boot + ant-design-vue开发,希望点击菜单打开新窗口页签
  • 原文地址:https://www.cnblogs.com/colys/p/1458011.html
Copyright © 2020-2023  润新知