Jeeplus框架工作流的使用实战(采购计划的制定流程)

一、采购计划制定的业务流程

采购计划制定的业务流程如下:(其中开始节点就是启动采购计划录入任务,即打开采购计划的录入界面)

二、建立工作流模型

(一)、工作流模型的基本信息

打开新建模型页面后,点击任意空白处,下方即弹出如下窗口。根据实际业务流程信息来填写 流程名称,名称以及描述。其中流程名称较为关键,后面编程中启动工作流需要用到。

 

(二)、开始节点

点击开始节点后,将弹出下面信息框。需要填写的关键信息为 Id,名称,发起人,自定义表单。

 

其中:

1、Id将对应 工作流任务(Task)的taskDefinitionKey

2、名称就是这个任务活动的名称(在流转信息中显示)

3、发起人填写自定义的“发起人”变量名,如applyUserId。(主要的用处就是:如果后面的活动任务需要指定改发起人做,就在对应任务节点的代理中填写此处定义的发起人变量名。如这个例子中的采购计划重新申请 就只能是原制单人做,故在对应活动节点的代理人框中需输入${applyUserId})

4、自定义表单表示 这个任务活动启动后要打开的页面连接;这个开始活动节点的自定义表单就是 工作流启动后的起始页面;在这个采购计划的例子中 自定义表单就应该填 采购计划制定的录入 对应的页面链接。

 (三)、一般的活动任务节点(领导审批任务为例)

 

 

 点击领导审批节点(活动任务节点)后,将弹出下面信息框。需要填写的关键信息为 Id,名称,代理,自定义表单。

其中:

1、Id将对应 工作流任务(Task)的taskDefinitionKey

2、名称就是这个任务活动的名称(在流转信息中显示)

3、点击代理弹出如下窗口:

代理人:任务执行人,设置系统中的“登录名”(loginName)。

候选人:任务执行人,多个用逗号“,”隔开。

候选组:任务执行组,多个用逗号“,”隔开,设置系统中的“角色英文名(enname)”。

注意:代理人和候选人、候选组为互斥关系;即指定了代理人,后面再指定候选人或候选组将不起作用。

代理人和候选人的区别是:代理人不需要签收任务,直接可执行任务;候选人和候选组为竞争方式分配任务,被指定人待办中都有一条任务,谁先签收谁就获得任务的执行权。
参与者可指定流程变量(EL表达式),动态指定参与者,如:${processer}

4、自定义表单 和上述第(二)节所述的开始节点一样,表示 当前活动任务节点使用的页面链接。

(四)、互斥网关

互斥网关(排他网关):条件计算为true的顺序流会被选择继续流程,有且只有一条出口,如果出现多个条件为true,则会默认选择第一条true来执行,如果没有条件输出true,流程走到这一步的时候则会报错。

互斥网关本身不需要设置任何参数,关键在于它输出的流转条件设置。

互斥网关的流转条件:

领导审批任务执行后有三个流转条件:(1)当申请单总额大于等于1万并且审核通过,流转到总经理审批(2)当申请单总额小于1万并且审核通过,流转到下达任务(3)审核不通过,流转回制单人重新申请。

流转条件(1)所填的参数信息如下:

需要填写项为 名称,流转条件;其中流转条件里的EL表达式中的变量为自定义,需要与后面代码开发的对应上,并且值只能为true或者false(布尔型)

流转条件(2)所填的参数信息如下:

 

流转条件(3)所填的参数信息如下:

 

无网关的流传:

该采购计划案例中涉及到无网关流转的有 计划下达 和 结案这两个任务节点。

无条件流转不需要做任何流转条件的设置,活动之间的流转就是单纯的页面切换。

(五)、结束节点

                    

 

结束节点简单地填写一下Id和名称即可,不用做其他设置。

 

三、代码开发部分

(一)数据库表的修改和流程类的继承

1.业务主表中必须要增加 proc_ins_id 字段(记录流程实例);

2.对应业务主表的实体需要继承ActEntity<T> (T为自己的业务实体类)

 

(二)界面部分的代码修改

界面部分的修改主要针对 所有form页面文件。(如采购计划这部分要修改的页面文件包括了purPlanMainCloseForm.jsp;purPlanMainDraftForm.jsp;purPlanMainForm.jsp;purPlanMainOrderForm.jsp;purPlanMainQueryForm.jsp)

其次,需要增加一个审核界面(原来旧的审核页面不能用)

1、form页面的修改

针对上述所述的所有form页面文件中,需要在这些页面隐藏域里加入以下流程变量:

<%--工作流涉及的变量--%>
<form:hidden path="act.taskId"/>
<form:hidden path="act.taskName"/>
<form:hidden path="act.taskDefKey"/>
<form:hidden path="act.procInsId"/>
<form:hidden path="act.procDefId"/>
<form:hidden id="flag" path="act.flag"/>

页面底部(按钮下面)加入以下代码(用来显示详细的流转信息;注意把purPlanMain替换成相应的对象):

<act:flowChart procInsId="${purPlanMain.act.procInsId}"/> 
<act:histoicFlow procInsId="${purPlanMain.act.procInsId}"/>

2、增加一个审核页面

这部分可以直接从该模块中任意一个form页面复制过来,然后加入上述1中需要添加的代码,再做如下修改:

1)添加审核人意见填写框(审核人意见保存在act.comment属性里)

<div class="form-group">
  <label class="control-label">您的意见:</label>
  <form:textarea path="act.comment" class="form-control required" rows="5" maxlength="20"/>
</div>

2)为审核通过和不通过按钮添加事件 

if(whichBtn=="审核通过"){
$("#flag").val("yes");  
form.submit();
}else if(whichBtn=="审核不通过"){
$("#flag").val("no");
form.submit();
}

 

(三)后台JAVA代码

1、开始节点的后台处理代码(工作流启动)

工作流启动代码一般写在service中某个函数里(也可直接写在Controller里),在开始节点对应的页面中 点击提交按钮时被调用,以下是涉及工作流启动的代码,其中标红的是工作流启动的关键代码:

//结构{对应第一节所述的工作流模型里的流程名称业务表名}
public static final String[] PUR_PLAN_AUDIT = new String[]{"pur_plan", "pur_planmain"};
/**
* 提交操作 保存并且启动工流
* @param purPlanMain
*/
@Transactional(readOnly = false)
public void submitSave(PurPlanMain purPlanMain) {

/**-------------------------------业务操作----------------------**/
    save(purPlanMain);
/**-------------工作流启动操作------------------**/

    // 申请发起
    if (StringUtils.isBlank(purPlanMain.getId())||"".equals(purPlanMain.getAct().getTaskId())||purPlanMain.getAct().getTaskId()==null){



        // 用来设置启动流程的人员ID,引擎会自动把用户ID保存到activiti:initiator中
        identityService.setAuthenticatedUserId(purPlanMain.getCurrentUser().getLoginName());
        // 启动流程
        actTaskService.startProcess(PUR_PLAN_AUDIT[0], PUR_PLAN_AUDIT[1], purPlanMain.getId(), purPlanMain.getBillNum()); //后两个参数分别表示业务表的主键ID和在代办任务页面里显示的标题。这里就直接把业务表的单据编号作为代办任务的标题了
    }
    else{   // 重新编辑申请
        purPlanMain.getAct().setComment(("yes".equals(purPlanMain.getAct().getFlag())?"[重申] ":"[作废] ")+purPlanMain.getAct().getComment());
        // 完成流程任务
        Map<String, Object> vars = Maps.newHashMap();
        vars.put("reApply", "yes".equals(purPlanMain.getAct().getFlag())? true : false);
        actTaskService.complete(purPlanMain.getAct().getTaskId(), purPlanMain.getAct().getProcInsId(), purPlanMain.getAct().getComment(), purPlanMain.getBillNum(), vars);
    }
}

2、活动任务节点的后台处理代码

采购计划的工作流模型中各个活动节点

 

工作流模型中各活动节点的后台处理代码如下,在各活动节点对应的页面中 点击提交按钮时被调用。

/**
 * 保存业务表数据和工作流数据
 * @param purPlanMain
 */
@Transactional(readOnly = false)
public void auditSave(PurPlanMain purPlanMain) {

    Map<String, Object> vars = Maps.newHashMap();
    // 对不同环节的业务逻辑进行操作
    String taskDefKey = purPlanMain.getAct().getTaskDefKey();
    // 流程环节
    if ("planAudit1".equals(taskDefKey)){                       //判断该环节是否为 领导审批环节;此处的taskDefKey即对应着第二节(三)部分所述的活动任务节点ID
        vars.put("auditPass1", "yes".equals(purPlanMain.getAct().getFlag())? true : false);   //调用getFlag()获取审核人在前端页面中点击了审核通过还是不通过
        vars.put("sum",purPlanMain.getPlanPriceSum());                        //此处的auditPass1和sum变量对应着第二节(四)部分所述的流转条件里EL表达式中自定义变量
        purPlanMain.getAct().setComment(("yes".equals(purPlanMain.getAct().getFlag())?"[同意] ":"[不同意] ")+purPlanMain.getAct().getComment()); //调用getComment()获取审核人在前端页面填写的审核意见并加上通过 或 不通过结论
        if("yes".equals(purPlanMain.getAct().getFlag())) {       //通过且金额小于1万
            if(purPlanMain.getPlanPriceSum()<10000){
                purPlanMain.setBillStateFlag("E");             //总额少于1万且通过领导审核,就可把业务表状态设为通过审核状态 (依赖于工作流模型,该工作流模型中只有两层审核,只需要通过领导和总经理两层人员的审批)
            }
        }else{
            purPlanMain.setBillStateFlag("B");               //否者把业务表状态设置为不通过
        }
    }
    else if("planAudit2".equals(taskDefKey)){
        vars.put("auditPass1", "yes".equals(purPlanMain.getAct().getFlag())? true : false);
        vars.put("sum",purPlanMain.getPlanPriceSum());
        purPlanMain.getAct().setComment(("yes".equals(purPlanMain.getAct().getFlag())?"[同意] ":"[不同意] ")+purPlanMain.getAct().getComment());
        if("yes".equals(purPlanMain.getAct().getFlag())) {
           purPlanMain.setBillStateFlag("E");                        //总经理审批通过,就可把业务表状态设为通过审核状态 (这里依赖于工作流模型,该工作流模型中只有两层审核,只需要通过领导和总经理两层人员的审批)
          
        }else{
            purPlanMain.setBillStateFlag("B");          
        }
    }
    else if ("reInput".equals(taskDefKey)){
        vars.put("reApply", "yes".equals(purPlanMain.getAct().getFlag())? true : false);
        purPlanMain.getAct().setComment(("yes".equals(purPlanMain.getAct().getFlag())?"[重申] ":"[作废] ")+purPlanMain.getAct().getComment());
        if( "yes".equals(purPlanMain.getAct().getFlag())){
            purPlanMain.setBillStateFlag("W");//选择了重申就把业务表状态设为录入状态
        }else{
            purPlanMain.setBillStateFlag("V");//作废业务表
        }
    }
    else if("planClose".equals(taskDefKey)){ //是否为结案环节
        vars.put("billFlag",purPlanMain.getBillStateFlag()); 
    }
    else if("planOrder".equals(taskDefKey)){ //是否为下达环节
        vars.put("billFlag",purPlanMain.getBillStateFlag());
    }
    else if ("end".equals(taskDefKey)){   //是否为结束环节

    }

    // 未知环节,直接返回
    else{
        return;
    }

    // 提交流程任务(工作流的任务ID,工作流实例ID,审核意见,自定义的条件变量<MAP结构>)
    actTaskService.complete(purPlanMain.getAct().getTaskId(), purPlanMain.getAct().getProcInsId(), purPlanMain.getAct().getComment(), vars);
    //保存业务表状态
    save(purPlanMain);
}

 

posted on 2018-06-07 11:56  BonSan  阅读(1982)  评论(0)    收藏  举报

导航