企业级工作流解决方案(十六)--工作流--工作流实体模型


  DDD思想强调先有领域实体模型定义,再有数据库设计,数据库只是做为领域模型的一种持久化介质,但是在工作中,还是习惯性的先做数据库设计,再翻译成领域实体模型。所有我还是以数据库设计为起点,讲解工作流整体设计思路。

  数据库设计的重要性就不用强调了,设计库设计最能反映应用程序的功能和设计思想。

  工作流数据库设计图:

数据库设计详细说明:

多租户

   所有的表都有租户Id,即TenantId,托管于Abp租户管理。

业务表单(WF_FlowForm)

  业务表单是流程引擎与业务之前的桥梁,有两个核心的字段,RoutePrefix和RpcServicePrefix。我这里设计的流程引擎,表单信息定义在一个Xml文件里面,流程定义的时候会读取Xml文件对应的表单模版,运行时也会读取表单模版,并把运行时的值赋值给表单模版里面的字段。RoutePrefix即表单的标识,根据此标识读取Xml实体内容,发起流程的时候,也是根据此标识找到流程定义,发起对应的流程实例。RpcServicePrefix为表单微服务前缀,流程引擎定义业务表单需要实现的接口,流程运行时,由流程引擎在特定的过程中,拼接调用表单微服务的方法,比如在用户提交审批时,流程引擎拼接保存表单微服务方法“RpcServicePrefix.Send”,方法参数和返回值与接口定义的相同,则可以动态的调用到表单的Send服务方法。Xml定义举例如下:

<FrameworkTemplates>
  <FrameworkTemplate Name="OA_Vacation" Type="DomainEntity" DataTableName="OA_Vacation" Inherit="BusinessFullAuditedEntity<int>, IMayHaveTenant, IBusinessEntity">
    <TemplateItem>
      <Field>IdField>
      <CnName>主键CnName>
      <Type>intType>
      <IsRequred>falseIsRequred>
    TemplateItem>
    <TemplateItem>
      <Field>ReasonField>
      <CnName>请假原因CnName>
      <Type>stringType>
      <IsRequred>trueIsRequred>
      <MaxLength>500MaxLength>
    TemplateItem>
    <TemplateItem>
      <Field>StartTimeField>
      <CnName>请假开始时间CnName>
      <Type>datetimeType>
      <IsRequred>trueIsRequred>
    TemplateItem>
    <TemplateItem>
      <Field>EndTimeField>
      <CnName>请假结束时间CnName>
      <Type>datetimeType>
      <IsRequred>trueIsRequred>
    TemplateItem>
    <TemplateItem>
      <Field>VacationDayField>
      <CnName>请假时长CnName>
      <Type>floatType>
      <IsRequred>trueIsRequred>
    TemplateItem>
    <TemplateItem>
      <Field>RemarkField>
      <CnName>备注CnName>
      <Type>stringType>
      <IsRequred>falseIsRequred>
      <MaxLength>4000MaxLength>
    TemplateItem>
  FrameworkTemplate>
FrameworkTemplates>

 流程类型(WF_FlowType)

  流程定义的分类,树形结构,方便分类管理。

流程定义(WF_FlowDefine)

  流程定义表,先有流程定义,才能根据流程定义发起对应的流程实例。

  WorkflowFormId定义表单外键,RoutePrefix和RpcServicePrefix为表单定义带过来的数据,所用见流程表单描述;FlowDefineStatus为流程定义状态,可以为草稿、已发布、取消发布三种状态,草稿状态只能有一条数据,已发布的状态也只能有一条数据,已发布状态的工作流可以取消发布,发起流程实例时,只找到此流程定义发布状态的记录发起流程实例,修改了流程状态对已发起的流程实例不影响;FlowDefineId为流程定义的Id,区别于主键Id,一个流程定义可能有多个版本,可能有多种状态,数据库可能对应多条记录,但是他们的流程定义Id都是相同的。

  FlowDefine为整个工作流的WWF内容Xml格式存储,WWF工作流定义是以Xml格式的形式存储的,包括了设计器定义的活动信息和连线信息,设计时根据此字段还原之前的设计状态,还会存储工作流变量信息,活动自定义的数据信息,比如审批活动定义的任务分配规则、任务路由选择规则、活动表单权限控制规则等,发起流程实例时,也是读取此字段内容来发起工作流实例,运行时流程定义图也是根据这里面的内容画出来的。

流程实例表(WF_FlowInstance)

  流程实例表即为发起的流程实例,一个流程定义对应多个流程实例,FormId存储的是运行时表单的Id,根据此字段与业务运行时表单数据进行关联,InstanceState为实例状态,可以为运行中、已完成、已暂停、已恢复。其他字段看名字应该知道意思。

流程审批项(WF_FlowItem)

  解析运行时活动对应的处理人信息,一个流程实例对应多条流程审批项信息,流程引擎运行时,解析活动规则,审批活动给每一个审批人增加一条审批项信息,活动审批结束,流程引擎自动回收其他未处理的审批信息。TaskId字段为Guid类型,每一个活动的TaskId相同,TaskId定义为WWF里面的书签,审批的过程中,根据TaskId书签还原工作流运行时;TaskType为任务类型,可以为审批人、任务转发、传阅、自动审批、任务委托;TaskState为审批项状态,可以为未处理、处理完成、自动完成、已过期、已阅、自动回收;PartId和PartName为审批人Id和名称;

WWF流程跟踪(WF_FlowWFTrack)

  WWF流程运行时可以记录他里面的活动运行时信息,这张表的作用是运行时根据他动态的展示流程跟踪图,他会记录活动执行的先后顺序,并根据ActivityId与流程定义的ActivityId关联起来,在流程定义图上动太的画出流程执行过程。前端页面根据JS代码,动态的画出流程跟踪。

流程跟踪(WF_FlowTrack)

  活动审批信息存储在此表中,包括用户选择的路由规则或者表单执行的路由规则,活动审批时,先要试运行工作流,找到下一步骤审批人的信息,试运行工作流时,是从活动第一步骤开始的,那么可以根据这张表的数据,还原工作流实例运行过程,并计算出下一审批活动信息。

流程文档(WF_UploadFiles)

  每一个流程实例可以挂一些流程相关的文档,统一保存在这里。

这里只描述了比较核心的部分,具体的功能在后面的文章继续分解。