JeeSite 4.x

Spring Boot 最好的快速开发平台

业务流程 BPM、工作流引擎、Flowable、Activiti

特点

  • 基于 Flowable(Activiti)生来具有的稳定工作流引擎
  • 支持在线流程设计器,流程导入导出,符合 BPMN 规范,中国式工作流
  • 支持流程办理、退回、自由流、会签、并行、串行、服务任务等
  • 支持退回任务,退回到指定环节,退回到上一步,退回到发起人
  • 支持转办任务,将任务交接给他人办理,办理完成后继续下一步骤
  • 支持委托任务,将任务委托给他人,他人办理完成后再回到委托人
  • 支持智能提交,相同处理人自动跳过,支持自由指定下一步处理人
  • 支持作废流程,允许发起人快速终止流程,管理员维护终止流程
  • 支持自由流程,根据环节选择,自由跳转到指定环节,特事特办
  • 支持流程跟踪图,流程状态展现,流转信息,任务历史,任务分配信息
  • 支持一个流程模型挂接多个业务单击,如某公司8种费用审批流程,表单不一样,但流程相同
  • 支持一个表单挂接多个流程环节,以表单角度去管理流程,方便业务理解
  • 流程事件脚本在线编写,包括:流程启动、完成、取消;任务分配、创建、结束等
  • 流程脚本管理(Groovy、Beetl),在线编辑、自动完成、脚本测试、多语言脚本模板维护
  • 我的待办任务处理,我的已办任务、我创建的任务查询、流程跟踪、审批记录查询
  • 流程管控,在无关联表单情况下流程调试,如流程发起、挂起;流程定义、实例、任务等查询;任务办理等
  • 支持流程组件标签定义(流程按钮、意见审批、下一步流程信息等)快速与自定义的业务表单建立关系。
  • 版本化管理流程,新调整的流程业务不影响正在运行,未结束的流程继续流转。
  • 计划:任务加签、催办任务、传阅任务、流程委托设置、流水号管理、常用语管理

模块安装

1、前置条件

BPM 模块要求 JeeSite 版本最低为 4.1.8,若你使用的版本低于 4.1.8,请先升级到最新版本,再继续操作。 升级方法:JeeSite 4.x 更新日志

2、引入依赖

打开 web 的 pom.xml,加入如下模块依赖代码

<!-- 业务流程管理 -->
<dependency>
	<groupId>com.jeesite</groupId>
	<artifactId>jeesite-module-bpm</artifactId>
	<version>${project.parent.version}</version>
</dependency>

注意此功能是专业版功能,只有专业版才能使用。

3、初始化数据库

第一种情况:你新启动的一个新项目,使用全新安装方式即可

  1. 运行 jeesite-web-bpm/bin/init-data.bat(sh) 初始化数据库。
  2. 你若先初始化完成了核心功能模块数据库之后,也可以直接运行 com.jeesite.test.InitData.initBpmData() 单元测试,初始化 BPM 模块的表及基础数据。

第二种情况:你正在开发过程或已经上线的项目,后加入 bpm 模块

  1. 无需执行 bpm 模块的 init-data 初始化数据库脚本。
  2. 项目 pom.xml 里加入 bpm 模块依赖后,启动服务,将自动检测并初始化数据库。

快速开始,我的第一个流程

下面让咱们以一个最简单的《请假单》为例,快速体验它的强大。

1、创建流程分类

首先咱们先创建一个流程分类,对咱们新建的流程进行归类。进入菜单:业务流程-> 流程管控 -> 流程分类管理,点击“新增”按钮,新建一个分类,数据如下:

  • 分类名称:办公流程
  • 分类编码:office

2、流程模型设计

请假流程环节业务描述:

  • 申请人发起请假申请,由部门经理审核。
  • 若申请人为部门经理,则自动跳过部门经理节点。
  • 若请假天数大于3天,则需要总经理审核,否则跳过总经理审核。
  • 审核完成后,有人力专员进行备案,并结束流程。
  • 审批不通过任务退回到申请人。

了解业务后,咱们开始进行流程图设计。进入菜单:业务流程-> 流程管控 -> 流程模型设计,点击“创建流程”按钮,填写数据如下:

  • 模型名称:请假流程学习
  • 模型Key:leave_test
  • 描述:我的第一个流程

点击“创建新模型”按钮,接着系统会弹出流程设计界面。

1)画流程图,如下:

注意:已实现中国式流程,无需画“退回”线路。

2)为每个环节设置ID:

设“主键ID”作为环节的编号,如下:

  • 填写申请单,主键ID:edit
  • 部门经理审核,主键ID:dept
  • 总经理审核,主键ID:ceo
  • 人力专员备案,主键ID:har

3)为每个环节“分配用户”:

  • 填写申请单:流程发起人(可以不设置,启动流程后默认自动跳过第一个环节,第一个环节为填写申请单或修改申请单使用)

  • 部门经理审核:身份存储 -> 候选组 -> 部门经理(若没有创建一个部门)

以此类推,继续配置如下环节:

  • 总经理审核:身份存储 -> 分配给单个用户 -> 选择总经理用户
  • 人力专员备案:身份存储 -> 分配给单个用户 -> 选择人力专员用户

4)配置流转条件,如下:

  • 选择“小于等于3天”连接线,流转条件编写:${leaveDays <= 3}
  • 选择“大于3天”连接线,流转条件编写:${leaveDays > 3}

其中:变量 leaveDays 为业务表单字段,后续会说明如何赋值。

5)配置流程变量,方便调试流程

此操作为可选配置(可以配置也可以不配置),主要是在“业务流程 -> 流程管控 -> 流程定义”中直接发起“非关联业务”的流程进行调试时,展现的流程变量列表。

点击流程图空白处,在下方属性列表中,点击“数据对象”,填写信息如下:

6)保存流程模型,并发布流程

点击左上角的“保存”按钮,接着点击“保存和关闭编辑器”按钮,保存流程图。

系统会返回到“流程模型列表”界面,找到刚新建的流程,点击“发布流程模型”按钮:

弹出如下对话框:

选择一个 office 流程分类,点击“发布流程模型”,右下角提示“发布流程成功”即可。

注意:流程表单、流程事件,不需要在流程模型中配置。发布流程后可以在流程定义管理进行关联业务,绑定表单,编写流程事件。

7)调试流程(验证流转是否正确)

进入菜单:业务流程 -> 流程管控 -> 流程定义。

接上一步,流程发布后,在流程定义列表中会出现刚发布的“请假流程”一条数据,点击“调试流程”,可以进行“无关联业务”的流程流转测试,来验证你刚才发布的流程,是否可以正常流转。

点击“启动流程”,会发起该流程(流程名称后会带一个【调试】字样)。

在流程定义列表中点击流程名称,可以查询该流程下的所有实例。

接着点击流程实例名称,可以查询该实例下的任务。

接着点击任务名称,可以签收、办理该任务。

若当前启动人是部门经理,则部门经理审批环节自动跳过。

流程调通之后,接下来,咱们可以进行关联业务表单了。

3、流程与业务关联

现在我们开始准备表单,首先通过 ERMaster 创建一张请假表,如下:

导出DDL并执行,完成数据表的创建。然后通过代码生成工具生成,并创建菜单。

这里主要已流程为主,就不多赘述了具体生成步骤了,最终表单地址如下:

  • 申请单查询:/oa/oaLeave/list
  • 申请单填写:/oa/oaLeave/form
  • 申请单编辑:/oa/oaLeave/form

这里填写和编辑的地址相同,主要用来学习入门,根据业务需要可以分开设计

1)业务关联配置

目前表单和流程都已经准备好,咱们正式开始建立联系。进入“业务流程 -> 流程管控 -> 流程定义”菜单。找到“请假流程”数据行,点击“业务关联”操作按钮,进入“流程表单”界面。

  • 一个流程可以关联多个业务单据,如:某公司8种费用审批流程,表单不一样,但流程相同,这里的表单 key 对应一种费用。表单的版本对应流程的版本,当新发布一个流程定义的时候,流程表单也跟随新增版本。
  • 流程表单是一个树结构,顶级表单定义为全局表单(对所有环节生效);下级表单为环节表单(该表单只对指定环节生效)。若没有定义环节表单的环节,则获取全局表单数据。

点击右上角“新增流程表单”按钮。创建一个表单,数据如下:

  • 表单名称:请假流程
  • 表单Key: leave
  • 表单类型:URL表单
  • 表单标题:${form.currentUser.userName} 在 ${date(),’yyyy-MM-dd’} 发起了 ${form.formName}
  • PC表单地址:/oa/oaLeave/form?id=${task.procIns.bizKey}

其中表单标题和表单地址为 Beetl 语法模板,可以根据业务数据规则动态生成。

若每个环节的表单不同,你可以继续创建下级表单,指定环节名称,则仅对指定环节有效,如下(本例学习可以不用配置):

2)流程事件配置

在“流程表单”界面,找到你刚新建的“请假流程”表单数据行,点击“流程事件”操作按钮,进入“流程事件”界面。

  • 表单下支持定义流程事件,主要用来:更新业务表单数据状态、发送通知、发送邮件、业务处理等。
  • 目前支持的事件包括:流程启动、流程完成、流程终止、任务分配、任务创建、任务完成等;若这些事件缺少你想要的,你也可以自己在字典管理里找到 bpm_event_type 字典类型,添加 Flowable 流程事件,更多的流程事件编码,详见:org.flowable.common.engine.api.delegate.event.FlowableEngineEventType 枚举类。
  • 流程事件脚本为 Groovy 语言,它是一个脚本语言,无需编译直接运行;可以完全使用 Java 语法,能够很好和 Java 代码进行结合;又可以使用 Groovy 自身的特性,简化 Java 语法的编写。
  • 提供强大的脚本编辑器,自动提醒,自动完成常用语法。

点击右上角“新增”按钮。连续创建三个事件,数据如下:

  • 事件名称:更新业务表状态(审核、退回)
  • 是否异步:否
  • 事件类型:任务创建
  • 事件脚本:如下
    import com.jeesite.common.entity.DataEntity;
    import com.jeesite.modules.bpm.utils.BpmUtils;
    if (BpmUtils.isCurrentCmd(execution, 'back')){ // 如果当前执行的是退回命令,则更新状态为审批退回
      BpmUtils.updateStatus(execution, 'oaLeaveService', DataEntity.STATUS_AUDIT_BACK);
    }else{
      BpmUtils.updateStatus(execution, 'oaLeaveService', DataEntity.STATUS_AUDIT);
    }
    
  • 事件名称:更新业务表状态(流程完成)
  • 是否异步:否
  • 事件类型:流程完成
  • 事件脚本:如下
    import com.jeesite.common.entity.DataEntity;
    import com.jeesite.modules.bpm.utils.BpmUtils;
    BpmUtils.updateStatus(execution, 'oaLeaveService', DataEntity.STATUS_NORMAL);
    
  • 事件名称:更新业务表状态(流程终止)
  • 是否异步:否
  • 事件类型:流程取消
  • 事件脚本:如下
    import com.jeesite.common.entity.DataEntity;
    import com.jeesite.modules.bpm.utils.BpmUtils;
    BpmUtils.updateStatus(execution, 'oaLeaveService', DataEntity.STATUS_DELETE);
    

3)增加流程相关后台代码

将实体类的父类替换为 BpmEntity 实体,该实体里包含提交流程的相关参数。

import com.jeesite.modules.bpm.entity.BpmEntity;
public class OaLeave extends BpmEntity<OaLeave> {}

修改 OaLeaveService 的 save 方法,增加流程处理代码,如下:

import com.jeesite.modules.bpm.utils.BpmUtils;
public void save(OaLeave oaLeave) {
	
	// 如果未设置状态,则指定状态为审核状态,以提交审核流程
	if (StringUtils.isBlank(oaLeave.getStatus())){
		oaLeave.setStatus(OaLeave.STATUS_AUDIT);
	}
	
	// 如果状态为正常,则代表不正常操作,可能前端进行了数据参数修改
	if (OaLeave.STATUS_NORMAL.equals(oaLeave.getStatus())){
		throw new ServiceException(text("非法操作,前端数据被劫持!"));
	}
	
	// 如果状态为草稿或审核状态,才可以保存业务数据
	if (OaLeave.STATUS_DRAFT.equals(oaLeave.getStatus())
			|| OaLeave.STATUS_AUDIT.equals(oaLeave.getStatus())){
		super.save(oaLeave);
	}

	// 如果为审核状态,则进行审批流操作
	if (OaLeave.STATUS_AUDIT.equals(oaLeave.getStatus())){
		
        // 指定请假天数流程变量,作为流程条件,决定流转方向
		Map<String, Object> variables = MapUtils.newHashMap();
		variables.put("leaveDays", oaLeave.getLeaveDays());
		
		// 如果流程实例为空,任务编号也为空,则:启动流程
		if (StringUtils.isBlank(oaLeave.getBpm().getProcInsId())
				&& StringUtils.isBlank(oaLeave.getBpm().getTaskId())){
			BpmUtils.start(oaLeave, "leave", variables, null);
		}
		// 如果有任务信息,则:提交任务
		else{
			BpmUtils.complete(oaLeave, variables, null);
		}
	}
}

关注:BpmUtils 的 start 和 complete 方法,这才是流程的重点。上面的几步判断,只是一些数据存储和验证。

4)增加流程相关视图代码

请假管理列表中增加“流程追踪”按钮:

$('#dataGrid').dataGrid({
	columnModel: [
		// ... 此处省略 ... 
		{header:'${text("操作")}', name:'actions', width:120, sortable:false, title:false, formatter: function(val, obj, row, act){
			var actions = [];
		    // ... 此处省略 ...
            // 如果表单已启动流程,则可以显示流程追踪按钮,其中:formKey 是创建表单时的Key,bizKey 是当前业务的主键
			if (row.status != Global.STATUS_DRAFT){ 
				actions.push('<a href="${ctx}/bpm/bpmRuntime/trace?formKey=leave&bizKey='+row.id+'" class="btnList" title="${text("流程追踪")}" data-layer="true"><i class="fa fa-file-picture-o"></i></a>&nbsp;');
			}
			return actions.join('');
		}}
	]
});

替换原来的提交按钮(如果需要暂存功能,可以增加暂存按钮,否则可以不加):

<% if (hasPermi('oa:oaLeave:edit')){ %>
	<#form:hidden path="status"/>
	<% if (oaLeave.isNewRecord || oaLeave.status == '9'){ %>
		<button type="submit" class="btn btn-sm btn-info" id="btnDraft"><i class="fa fa-save"></i> ${text('暂 存')}</button>&nbsp;
	<% } %>
	<#bpm:button bpmEntity="${oaLeave}" formKey="leave" completeText="${text('提 交')}"/>
<% } %>
<script>
// 业务实现草稿按钮
$('#btnDraft').click(function(){
	$('#status').val(Global.STATUS_DRAFT);
});
// 流程按钮提交事件
BpmButton = window.BpmButton || {};
BpmButton.complete = function($this, task){
	$('#status').val(Global.STATUS_AUDIT);
};
</script>

在表单部分增加“审批意见”和“下一步任务信息”控件(如果不需要可以不加)

<% if(isNotBlank(oaLeave.bpm.taskId)){ %>
<div class="row">
	<div class="col-xs-12">
		<div class="form-group">
			<label class="control-label col-xs-2">${text('审批意见')}:</label>
			<div class="col-xs-10">
				<#bpm:comment bpmEntity="${oaLeave}" />
			</div>
		</div>
	</div>
</div>
<% } %>
<#bpm:nextTaskInfo bpmEntity="${oaLeave}" />

5)一切就绪,测试效果

到这一步说明一个请假流程就算完成了,下面贴图展示:

请假单列表:

任务办理:

  • 要求完成时间:下一步任务的要求完成时限,提醒作用
  • 任务优先级:根据任务的等级排序,优先级越高越靠前
  • 下一步处理人:下一步任务的执行人设定,若不设置,则有流程引擎自动分配
  • 流程分配的下一步处理人若与当前人想符合,流程自动跳过

任务退回:

任务转办:

任务委托:

自由跳转(特事特办):

流程终止(作废):

流程跟踪信息:

附:API

BpmEntity 业务流程实体

public class BpmEntity<T extends DataEntity<?>> extends DataEntity<T> {
	
	private BpmParams bpm;		// 流程相关参数

}

BpmParams 流程接受参数

public class BpmParams implements Serializable {

	private static final long serialVersionUID = 1L;
	
	private String taskId; 			// 任务编号
	private String procInsId; 		// 实例编号
	private String activityId; 		// 活动编号
	
	private String comment;			// 审批意见

    private Date dueDate;			// 任务期限
    private Integer priority;		// 任务优先级
    private String nextUserCodes;	// 下一步处理人用户编码
    
	private boolean isView;			// 是否为查看表单(来自:已办、我创建、查询等)
		
}

button 流程按钮组件

var p = {

	// 业务流程实体对象
	bpmEntity: bpmEntity!,
	
	// 业务表单Key
	formKey: formKey!,
	
	// 按钮的标签,设置为空,则不显示按钮
	claimText: claimText!text('签 收'),
	completeText: completeText!text('提 交'),
	backText: backText!text('退 回'),			// 退回到之前办理过的任务环节
	turnText: turnText!text('转 办'),			// 将任务转交他人办理,办理完成后继续流转
	delegateText: delegateText!text('委 托'),	// 任务交由被委托人办理,办理完成后返回委托人
	stopText: stopText!text('终 止'),			// 单据作废,结束流程实例
	moveText: moveText!text('自由跳转'), 		// 特事特办,自由流
	traceText: traceText!text('流程追踪'),
	
};

comment 审批意见组件

var p = {

	// 业务流程实体对象
	bpmEntity: bpmEntity!,
	
};

nextTaskInfo 下一步任务信息

var p = {

	// 业务流程实体对象
	bpmEntity: bpmEntity!,
	
};

关注 JeeSite 公众号,了解最新动态