工作流加签,修改加签节点决策项

栏目:云苍穹知识作者:金蝶来源:金蝶云社区发布:2024-09-23浏览:3

工作流加签,修改加签节点决策项

一、需求描述

1.工作流加签时,默认有2个决策项(同意和驳回),现在需求自定义决策项。

2.在自定义决策项的基础上,配置“任务处理时执行”,执行对应的单据操作。


二、思路与方案

  1. 通过扩展加签弹窗页面(如下图这个页面)(wf_addsignpage),注册新的页面插件。

  2. 如果想要查看节点有哪些属性可以加,可以查询和解析流程资源表T_WF_GEBYTEARRAY的fcontent字段。

  3. 重写customEvent事件,在点击加签确认按钮后,触发该事件,构造加签节点决策项的数据包,把数据包传递给工作流服务,完成加签节点的修改。

   注意:自定义决策项,无需开发工作流插件,需要开发的是页面插件。

三、实现过程

1.扩展加签弹窗页面

1.1 开发平台,扩展工作流服务


1.2 扩展加签弹窗页面(标识为:wf_addsignpage)


1.3 注册页面插件


2.查询工作流的审核节点有哪些参数

为了完成设置加签节点决策项的代码,我们需要知道决策项的数据结构,可以通过查询分析器查询流程资源表。sql语句如下:

select fcontent from T_WF_GEBYTEARRAY where fid=

(select fresourceid from T_WF_PROCDEF where fkey='流程编码' and fversion='流程版本号')



fcontent是这个流程的各个节点的配置信息(以json结构承载),解析决策项结构。例如:

  • 某个审核节点的决策项的json结构,可以查看key为“decisionOptions”的json,如下:


  • 决策项对应的操作,可以查看key为“taskListeners”的json


3.编写插件代码

重写customEvent事件,部分关键代码如下:

判断是否加签页面点击了确定按钮,确认开始加签

if(e != null && BeforeAddSignConfirmCustomEvent.SELECT_ADDSIGNCONFIRM_ISOLATION.equals(e.getKey())
        && e instanceof BeforeAddSignConfirmCustomEvent)


判断是否针对某个业务实体做加签决策项修改

BeforeAddSignConfirmCustomEvent bac = (BeforeAddSignConfirmCustomEvent) e;
TaskEntityImpl taskInfo = (TaskEntityImpl)WorkflowServiceHelper.findTaskById(bac.getTaskId());
if ("单据标识".equals( taskInfo.getDynamicObject().get("billtype") )) {
    // 加签业务逻辑
}


添加“同意”加签决策项(驳回决策项请查看完整代码)。

Map<String, Object> extProps = bac.getExtProps();
extProps.put("decisionOptions", initDecisionOptions());
private List<Map<String,Object>> initDecisionOptions() {

    List<Map<String,Object>> decisionOptions = new ArrayList<>();

    decisionOptions.add(createDecisionOption1());
    
    // ......
    
    return decisionOptions;
}
// 同意决策项
private Map<String,Object> createDecisionOption1 () {
    Map<String,Object> decisionOption1 = new HashMap<>();
    // 决策编码
    decisionOption1.put("number", "Consent");
    // 决策场景,固定写法
    decisionOption1.put("decisionScene", "approve");
    // 决策名称
    decisionOption1.put("name", "同意1");
    // 决策类型,如果决策项是同意,则固定写为"approve"
    decisionOption1.put("auditType", "approve");
    // 同意为默认决策项
    decisionOption1.put("defaultDecision", true);
    return decisionOption1;
}


加签节点设置禁止批量同意(禁止批量驳回代码请查看完整代码)。加签节点,如果自定义了决策项,建议关闭批量同意和批量驳回。批量同意的决策编码是Consent,批量驳回的编码是RejectToEdit。如果我们自定义的决策项的编码不是这两个,则需要关闭批量同意和批量驳回。

Map<String, Object> extProps = bac.getExtProps();
extProps.put("decisionOptions", initDecisionOptions());
private Map<String,Object> initBatchApprove() {
    Map<String,Object> batchApprove = new HashMap<>();
    batchApprove.put("batchApprove", false);
    batchApprove.put("batchApproveDec", "Consent");
    return batchApprove;
}


处理时执行,在末尾的完整代码中,我会添加一个“RejectToEdit1”的决策项,当选择这个决策项时,会驳回到提交节点,此时做撤销操作。效果类似于这样:

注意:这里仅作为一个代码案例展示,通常情况下,提交节点会设置“驳回进入时”进行撤销(unsubmit),这段代码通常是不需要加的。有部分供应链云的旧流程,例如(注册资料审批审批流程,编码:Proc_srm_supplierreg_audit_1),提交节点没有配置撤销(unsubmit),可以使用此代码完善加签节点的相应功能。

// 处理时执行
private List<Map<String,Object>> initTaskListeners() {

    List<Map<String,Object>> taskListeners = new ArrayList<>();
    taskListeners.add(taskListener1());

    return taskListeners;
}

// 驳回到提交节点时,需要进行“撤销”操作,将单据状态改为“暂存”
private Map<String,Object> taskListener1 () {
    Map<String,Object> map = new HashMap();
    map.put("implementationtype","operation");
    //map.put("id","1966934829480018944");
    map.put("event","complete");
    // 当决策项为RejectToEdit1时
    map.put("operation","RejectToEdit1");

    JSONObject jsonObjectOperation = new JSONObject();
    JSONObject jsonObjectOperationValue = new JSONObject();

    jsonObjectOperation.put("type", "operation");
    // 当决策项为RejectToEdit1时,执行撤销操作
    jsonObjectOperationValue.put("forward", "unsubmit");
    jsonObjectOperationValue.put("forward_name", "撤销");
    jsonObjectOperationValue.put("withdraw", "");
    jsonObjectOperationValue.put("withdraw_name", "");
    jsonObjectOperation.put("value", jsonObjectOperationValue);
    map.put("implementation", jsonObjectOperation.toJSONString());

    return map;
}


完整代码如下

import kd.bos.form.events.CustomEventArgs;
import kd.bos.form.plugin.AbstractFormPlugin;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;
import kd.bos.servicehelper.workflow.WorkflowServiceHelper;
import kd.bos.workflow.engine.impl.persistence.entity.task.TaskEntityImpl;
import kd.bos.workflow.taskcenter.plugin.validate.BeforeAddSignConfirmCustomEvent;

import java.util.*;

// 加签,调整决策项
public class ChangeDecisionSignPlugin  extends AbstractFormPlugin {

    private static final Log log = LogFactory.getLog(ChangeDecisionSignPlugin.class);

    @Override
    public void customEvent(CustomEventArgs e) {

        if(e != null && BeforeAddSignConfirmCustomEvent.SELECT_ADDSIGNCONFIRM_ISOLATION.equals(e.getKey())
                && e instanceof BeforeAddSignConfirmCustomEvent) {
            BeforeAddSignConfirmCustomEvent bac = (BeforeAddSignConfirmCustomEvent) e;

            TaskEntityImpl taskInfo = (TaskEntityImpl)WorkflowServiceHelper.findTaskById(bac.getTaskId());

            // 所有的加签都会走这个方法,而我们这个案例里面,是针对特定的单据在加签时,做决策项的修改
            // 所以这里要判断一下是否为目标单据,kdec_reqbill3就是本案例的单据标识,我们只针对kdec_reqbill3在加签时,修改其决策项
            if ("kdec_reqbill3".equals( taskInfo.getDynamicObject().get("billtype") )) {

                Map<String, Object> extProps = bac.getExtProps();
                // 添加3个决策项
                extProps.put("decisionOptions", initDecisionOptions());
                // 禁止批量同意和批量驳回
                extProps.put("batchApprove", initBatchApprove());
                extProps.put("batchReject", initBatchReject());
                
                // 设置插件,任务处理时执行
                                extProps.put("taskListeners", initTaskListeners());

                // 判断是前加签"addsignbefore",还是后加签"addsignafter",
                // 本案例中,我不需要判断前/后加签,所以只打了一个日志,如果开发者有需要判断,可以按下面代码进行判断
                if ("addsignafter".equals(bac.getAddSignInfo().getAddSignType())) {
                    log.info("ChangeDecisionSignPlugin, 后加签");
                } else if ("addsignbefore".equals(bac.getAddSignInfo().getAddSignType())) {
                    log.info("ChangeDecisionSignPlugin, 前加签");
                }

            }

        }
    }

    // 加签节点,如果自定义了决策项,建议关闭批量同意和批量驳回
    // 批量同意的决策编码是Consent,批量驳回的编码是RejectToEdit
    // 如果我们自定义的决策项的编码不是这两个,则需要关闭批量同意和批量驳回
    private Map<String,Object> initBatchApprove() {
        Map<String,Object> batchApprove = new HashMap<>();
        batchApprove.put("batchApprove", false);
        batchApprove.put("batchApproveDec", "Consent");
        return batchApprove;
    }
    private Map<String,Object> initBatchReject() {
        Map<String,Object> batchReject = new HashMap<>();
        batchReject.put("batchReject", false);
        batchReject.put("batchRejectDec", "RejectToEdit");
        return batchReject;
    }

    // 构建decisionOptions决策项
    private List<Map<String,Object>> initDecisionOptions() {

        List<Map<String,Object>> decisionOptions = new ArrayList<>();

        decisionOptions.add(createDecisionOption1());

        decisionOptions.add(createDecisionOption2());

        decisionOptions.add(createDecisionOption3());

        return decisionOptions;
    }

    // 同意
    private Map<String,Object> createDecisionOption1 () {
        Map<String,Object> decisionOption1 = new HashMap<>();
        decisionOption1.put("number", "Consent");
        decisionOption1.put("decisionScene", "approve");
        decisionOption1.put("name", "同意1");
        decisionOption1.put("auditType", "approve");
        decisionOption1.put("defaultDecision", true);
        return decisionOption1;
    }

    // 驳回到提交节点
    private Map<String,Object> createDecisionOption2 () {
        Map<String,Object> decisionOption = new HashMap<>();

        // 构建驳回节点
        List<Map<String,Object>> rejectOptions = new ArrayList<>();
        // 驳回节点1,驳回到一级审批节点
        Map<String,Object> rejectOption1 = new HashMap<>();
        // 注意:这里的驳回节点itemId不能照抄代码,根据开发者设计的流程不同,itemId也是不同的
        rejectOption1.put("itemId", "Proc_kdec_reqbill3_audit_1_UserTask3");
        rejectOption1.put("name", "采购申请单3_工作流加签提交");
        rejectOptions.add(rejectOption1);

        decisionOption.put("rejectOptions", rejectOptions);
        decisionOption.put("number", "RejectToEdit1");
        decisionOption.put("decisionScene", "rejectToEditNode");
        decisionOption.put("name", "驳回至提交节点");
        decisionOption.put("auditType", "reject");
        decisionOption.put("defaultDecision", false);
        return decisionOption;
    }

    // 驳回到已选节点(有3个已选节点),请开发者根据你们的流程
    private Map<String,Object> createDecisionOption3 () {
        Map<String,Object> decisionOption = new HashMap<>();

        // 构建驳回节点
        List<Map<String,Object>> rejectOptions = new ArrayList<>();
        // 驳回节点1,驳回到一级审批节点
        Map<String,Object> rejectOption1 = new HashMap<>();
        // 这个节点的id是,流程编码+节点编码
        rejectOption1.put("itemId", "Proc_kdec_reqbill3_audit_1_AuditTask5");
        rejectOption1.put("name", "一级审批");
        rejectOptions.add(rejectOption1);
        // 驳回节点2,驳回到二级审批节点
        Map<String,Object> rejectOption2 = new HashMap<>();
        rejectOption2.put("itemId", "Proc_kdec_reqbill3_audit_1_AuditTask0");
        rejectOption2.put("name", "二级审批");
        rejectOptions.add(rejectOption2);
        // 驳回节点3,驳回到提交节点
        Map<String,Object> rejectOption3 = new HashMap<>();
        rejectOption3.put("itemId", "Proc_kdec_reqbill3_audit_1_UserTask3");
        rejectOption3.put("name", "采购申请单3_工作流加签提交");
        rejectOptions.add(rejectOption3);

        decisionOption.put("rejectOptions", rejectOptions);
        decisionOption.put("number", "RejectToEdit2");
        decisionOption.put("decisionScene", "rejectToAllAuditNode");
        decisionOption.put("name", "驳回到指定节点");
        decisionOption.put("auditType", "reject");
        decisionOption.put("defaultDecision", false);
        return decisionOption;
    }
    
        // 处理时执行
        private List<Map<String,Object>> initTaskListeners() {
        
            List<Map<String,Object>> taskListeners = new ArrayList<>();
            taskListeners.add(taskListener1());
        
            return taskListeners;
        }
        
        // 驳回到提交节点时,需要进行“撤销”操作,将单据状态改为“暂存”
        private Map<String,Object> taskListener1 () {
            Map<String,Object> map = new HashMap();
            map.put("implementationtype","operation");
            //map.put("id","1966934829480018944");
            map.put("event","complete");
            // 当决策项为RejectToEdit1时
            map.put("operation","RejectToEdit1");
        
            JSONObject jsonObjectOperation = new JSONObject();
            JSONObject jsonObjectOperationValue = new JSONObject();
        
            jsonObjectOperation.put("type", "operation");
            // 当决策项为RejectToEdit1时,执行撤销操作
            jsonObjectOperationValue.put("forward", "unsubmit");
            jsonObjectOperationValue.put("forward_name", "撤销");
            jsonObjectOperationValue.put("withdraw", "");
            jsonObjectOperationValue.put("withdraw_name", "");
            jsonObjectOperation.put("value", jsonObjectOperationValue);
            map.put("implementation", jsonObjectOperation.toJSONString());
        
            return map;
        }

}


四、效果图

当前参与人处理审批流,设置张三为加签节点处理人。


进入张三账号,发现批量同意,批量驳回不可点击。


进入审批详情界面,发现了代码添加的几个决策项



五、注意事项

  1. 本案例基于苍穹V6.0,苍穹6.0版本才有“驳回至上一节点”、“驳回至提交节点”决策项,如果是苍穹V5.0的版本,要添加“驳回”决策项,需要从实现过程的第2点开始,解析加签决策项,用Map表构造对应的驳回决策项。

  2. 由于开发的工作流不同,驳回至指定节点的驳回项的“itemid”参数是不同的。

  3. 如果加签节点的决策项编码与默认的编码不一致,建议参考上述代码,设置禁止批量同意和批量驳回。


工作流加签,修改加签节点决策项

一、需求描述1.工作流加签时,默认有2个决策项(同意和驳回),现在需求自定义决策项。2.在自定义决策项的基础上,配置“任务处理时执行”...
点击下载文档
确认删除?
回到顶部
客服QQ
  • 客服QQ点击这里给我发消息