单据审批时,如何知道其他审批人此时正在审批
1 问题描述
业务单据在多人操作打开时,会有网络互斥,提示“xxx正在编辑”;而审批页面的网络互斥是在提交审批时触发,并不会在进入时提示。在节点多人审批的场景下,如希望进入审批界面即提示“他人正在编辑”,可以减少重复审批的时间、提高审批效率。
2 解决思路
由于对应单据的审批页面在打开时不进行网络互斥的校验,所以需要写插件处理。
可以使用接口kd.bos.mutex.DataMutex#batchrequire与kd.bos.mutex.DataMutex#batchRelease进行申请和释放互斥锁来实现逻辑。
3 解决方案
1、首先,batchrequire的使用示例如下:
(上图为官网接口文档内容DataMutex (SDK) (kingdee.com))
其中需要注意到,因为当前场景属于标准操作(view)的互斥,所以groupId使用默认;
entityKey即为当前单据的实体标识;
PARAMNAME_DATAOBJID为数据ID,可使用fid。可以通过如下代码获取到fid:
Object pkValue = this.getModel().getDataEntity().getPkValue();
PARAMNAME_DATA_OBJ_NUMBER为数据编码,单据为单据编号、基础资料为编码;同上,billNo也可以通过代码获取
Object billNo = this.getModel().getDataEntity().get("billNo");
PARAMNAME_OPERATIONKEY为操作标识,如修改:modify 提交:submit。当前场景为查看,即"view";
其余参数,使用默认或自定义即可。
2、 如互斥锁申请成功,需要执行第五步的操作,获取当前用户并放入缓存;如已有互斥锁,可以进行弹窗提示或其他操作:
if (ret) { //申请互斥成功;获取当前用户,用于释放互斥锁 long currentUserId = UserServiceHelper.getCurrentUserId(); pageCache.put("currentUserId", Long.toString(currentUserId)); } else { Map<String, String> lockInfo = dataMutex.getLockInfo(objId, groupId, entityKey); if (lockInfo != null) { //申请锁失败,提示已经存在的锁信息 this.getView().showTipNotification("已有其他人打开此单据"); } }
3 、为了防止与单据列表点击后进入的相同单据冲突,可以进行打开方式为工作流的校验:
Map<String, Object> customParams = this.getView().getFormShowParameter().getCustomParams(); String openType=(String) customParams.get("SOURCE"); if("WF".equals(openType)){ //业务逻辑 }
4 、至此,获取互斥锁已经完成,还需考虑释放互斥锁。释放的话可以考虑在事件pageRelease中进行(pageRelease事件),因为此时页面已经释放,所以释放互斥锁需要的一些参数需要在申请互斥锁时,存到缓存里,然后在pageRelease事件获取到进行释放。
5、 还需要考虑的一点:以防其他用户在页面关闭时释放了当前用户的互斥锁,所以还需要记录申请锁的用户,存入缓存后,在释放互斥锁中进行判断。
完整代码如下:
package nm21.plugin.formPlugin; import com.esotericsoftware.minlog.Log; import kd.bos.bill.AbstractBillPlugIn; import kd.bos.form.IPageCache; import kd.bos.form.control.Control; import kd.bos.mutex.DataMutex; import kd.sdk.plugin.Plugin; import java.util.*; /** * 单据界面插件 */ public class ErrShowPlugin extends AbstractBillPlugIn implements Plugin { //如果需要和标准操作(如保存、提交、审核...)互斥,则可使用default_netctrl(默认分组),不需要和标准操作互斥则需要用自定义的groupId String groupId = "default_netctrl"; String entityKey = "nm21_520test"; @Override public void afterLoadData(EventObject e) { super.afterLoadData(e); //检测打开方式为工作流 Map<String, Object> customParams = this.getView().getFormShowParameter().getCustomParams(); String openType = (String) customParams.get("SOURCE"); if ("WF".equals(openType)) { IPageCache pageCache = this.getPageCache(); pageCache.put("SOURCE", "WF"); try (DataMutex dataMutex = DataMutex.create()) { //申请网络互斥锁 List<Map<String, Object>> mutexRequireList = new ArrayList<>(1); Map<String, Object> requireParam = new HashMap<>(); //fid Object pkValue = this.getModel().getDataEntity().getPkValue(); //billNo Object billNo = this.getModel().getDataEntity().get("billNo"); pageCache.put("fid", pkValue.toString()); requireParam.put(DataMutex.PARAMNAME_DATAOBJID, pkValue.toString()); requireParam.put(DataMutex.PARAMNAME_DATA_OBJ_NUMBER, billNo.toString()); requireParam.put(DataMutex.PARAMNAME_GROUPID, groupId); requireParam.put(DataMutex.PARAMNAME_ENTITYKEY, entityKey); requireParam.put(DataMutex.PARAMNAME_OPERATIONKEY, "view"); requireParam.put(DataMutex.PARAMNAME_ISSTRICT, true); //建议设置自定义标识,用于后续区分标准操作和自定义申请的网控 requireParam.put(DataMutex.PARAMNAME_DATA_CALL_SOURCE, "testxixi"); mutexRequireList.add(requireParam); Map<String, Boolean> mutexResult = dataMutex.batchrequire(mutexRequireList); // 分析网控申请结果 for (Map.Entry<String, Boolean> mutexItem : mutexResult.entrySet()) { String objId = mutexItem.getKey(); Boolean ret = mutexItem.getValue(); if (ret) { //申请互斥成功的;获取当前用户,用于释放互斥锁 long currentUserId = UserServiceHelper.getCurrentUserId(); pageCache.put("currentUserId", Long.toString(currentUserId)); } else { Map<String, String> lockInfo = dataMutex.getLockInfo(objId, groupId, entityKey); if (lockInfo != null) { //申请锁失败,提示已经存在的锁信息 this.getView().showTipNotification("已有其他人打开此单据"); } } } } catch (Exception err) { Log.error(String.valueOf(err)); } } } @Override public void pageRelease(EventObject e) { super.pageRelease(e); IPageCache pageCache = this.getPageCache(); String source = pageCache.get("SOURCE"); String currentUserId = pageCache.get("currentUserId"); if ("WF".equals(source) && null != currentUserId && currentUserId.equals(Long.toString(UserServiceHelper.getCurrentUserId()))) { //释放网络互斥锁 try (DataMutex dataMutex = DataMutex.create()) { List<Map<String, Object>> releaseMutexList = new ArrayList<>(1); Map<String, Object> releaseParam = new HashMap<>(); String fid = pageCache.get("fid"); releaseParam.put(DataMutex.PARAMNAME_DATAOBJID, fid); releaseParam.put(DataMutex.PARAMNAME_GROUPID, groupId); releaseParam.put(DataMutex.PARAMNAME_ENTITYKEY, entityKey); releaseParam.put(DataMutex.PARAMNAME_OPERATIONKEY, "view"); releaseMutexList.add(releaseParam); Map<String, Boolean> releaseResult = dataMutex.batchRelease(releaseMutexList); // 分析释放结果 for (Map.Entry<String, Boolean> releaseItem : releaseResult.entrySet()) { boolean releaseRet = releaseItem.getValue(); if (!releaseRet) { //记录释放失败的锁 } } } catch (Exception err) { Log.error(String.valueOf(err)); } } } }
最后,如多人同时打开审批页面,后续审批人会有如下提示:
3 适用版本
演示环境为金蝶云·苍穹V6.0.1。
4 注意事项
该实现方案为单据级别,需要将插件注册到相关单据上。
5 参考资料
单据审批时,如何知道其他审批人此时正在审批
本文2024-09-23 00:17:35发表“云苍穹知识”栏目。
本文链接:https://wenku.my7c.com/article/kingdee-cangqiong-138537.html