工作流加签,修改加签节点决策项
一、需求描述
1.工作流加签时,默认有2个决策项(同意和驳回),现在需求自定义决策项。
2.在自定义决策项的基础上,配置“任务处理时执行”,执行对应的单据操作。
二、思路与方案
通过扩展加签弹窗页面(如下图这个页面)(wf_addsignpage),注册新的页面插件。
如果想要查看节点有哪些属性可以加,可以查询和解析流程资源表T_WF_GEBYTEARRAY的fcontent字段。
重写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; } }
四、效果图
当前参与人处理审批流,设置张三为加签节点处理人。
进入张三账号,发现批量同意,批量驳回不可点击。
进入审批详情界面,发现了代码添加的几个决策项
五、注意事项
本案例基于苍穹V6.0,苍穹6.0版本才有“驳回至上一节点”、“驳回至提交节点”决策项,如果是苍穹V5.0的版本,要添加“驳回”决策项,需要从实现过程的第2点开始,解析加签决策项,用Map表构造对应的驳回决策项。
由于开发的工作流不同,驳回至指定节点的驳回项的“itemid”参数是不同的。
如果加签节点的决策项编码与默认的编码不一致,建议参考上述代码,设置禁止批量同意和批量驳回。
工作流加签,修改加签节点决策项
本文2024-09-23 00:17:12发表“云苍穹知识”栏目。
本文链接:https://wenku.my7c.com/article/kingdee-cangqiong-138501.html