From 34981c30a78e8bbd7791131059a9210f9928b62c Mon Sep 17 00:00:00 2001
From: 刘光辉 <347230014@qq.com>
Date: 星期四, 17 九月 2026 09:24:09 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master' into master

---
 jnpf-flowable/jnpf-flowable-biz/src/main/java/jnpf/flowable/util/ButtonUtil.java |  771 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 771 insertions(+), 0 deletions(-)

diff --git a/jnpf-flowable/jnpf-flowable-biz/src/main/java/jnpf/flowable/util/ButtonUtil.java b/jnpf-flowable/jnpf-flowable-biz/src/main/java/jnpf/flowable/util/ButtonUtil.java
new file mode 100644
index 0000000..28d8f50
--- /dev/null
+++ b/jnpf-flowable/jnpf-flowable-biz/src/main/java/jnpf/flowable/util/ButtonUtil.java
@@ -0,0 +1,771 @@
+package jnpf.flowable.util;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.google.common.collect.ImmutableList;
+import jnpf.base.UserInfo;
+import jnpf.base.model.base.SystemBaeModel;
+import jnpf.base.model.systemconfig.SysConfigModel;
+import jnpf.constant.MsgCode;
+import jnpf.exception.WorkFlowException;
+import jnpf.flowable.entity.*;
+import jnpf.flowable.enums.*;
+import jnpf.flowable.mapper.*;
+import jnpf.flowable.model.flowable.FlowAbleUrl;
+import jnpf.flowable.model.flowable.FlowableNodeModel;
+import jnpf.flowable.model.flowable.NextOrPrevFo;
+import jnpf.flowable.model.operator.AddSignModel;
+import jnpf.flowable.model.task.FlowMethod;
+import jnpf.flowable.model.task.FlowModel;
+import jnpf.flowable.model.templatenode.ButtonModel;
+import jnpf.flowable.model.templatenode.TaskNodeModel;
+import jnpf.flowable.model.templatenode.nodejson.FileConfig;
+import jnpf.flowable.model.templatenode.nodejson.NodeModel;
+import jnpf.flowable.model.templatenode.nodejson.PrintConfig;
+import jnpf.flowable.model.templatenode.nodejson.ProperCond;
+import jnpf.flowable.model.util.FlowNature;
+import jnpf.permission.model.authorize.AuthorizeVO;
+import jnpf.util.JsonUtil;
+import jnpf.util.StringUtil;
+import jnpf.util.UserProvider;
+import lombok.RequiredArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Component;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 绫荤殑鎻忚堪
+ *
+ * @author JNPF@YinMai Info. Co., Ltd
+ * @version 5.0.x
+ * @since 2024/5/16 17:35
+ */
+@Component
+@RequiredArgsConstructor
+public class ButtonUtil {
+
+
+    private final FlowAbleUrl flowAbleUrl;
+
+    private final ServiceUtil serviceUtil;
+
+    private final FlowUtil flowUtil;
+
+    private final OperatorMapper operatorMapper;
+
+    private final TaskMapper taskMapper;
+
+    private final RevokeMapper revokeMapper;
+
+    private final EventLogMapper eventLogMapper;
+
+    private final RecordMapper recordMapper;
+
+    private final TemplateMapper templateMapper;
+
+    private final TriggerRecordMapper triggerRecordMapper;
+
+    /**
+     * 鎸夐挳鎺у埗
+     *
+     * @param flowModel 鍙傛暟
+     */
+    public ButtonModel handleButton(FlowModel flowModel) throws WorkFlowException {
+        String opType = flowModel.getOpType();
+        TaskEntity taskEntity = flowModel.getTaskEntity();
+        OperatorEntity operatorEntity = flowModel.getOperatorEntity();
+        RecordEntity recordEntity = flowModel.getRecordEntity();
+        Map<String, Object> formData = flowModel.getFormData();
+        List<TaskNodeModel> nodeList = flowModel.getNodeList();
+        TemplateEntity template = flowModel.getTemplateEntity();
+        UserInfo userInfo = flowModel.getUserInfo() == null ? UserProvider.getUser() : flowModel.getUserInfo();
+        String userId = userInfo.getUserId();
+
+        List<TemplateNodeEntity> nodeEntityList = flowModel.getNodeEntityList();
+        Map<String, NodeModel> nodes = new HashMap<>();
+        for (TemplateNodeEntity nodeEntity : nodeEntityList) {
+            nodes.put(nodeEntity.getNodeCode(), JsonUtil.getJsonToBean(nodeEntity.getNodeJson(), NodeModel.class));
+        }
+        flowModel.setNodes(nodes);
+        RevokeEntity revokeEntity = revokeMapper.getRevokeTask(taskEntity.getId());
+
+        // 鍏ㄥ眬鑺傜偣
+        NodeModel global = nodes.get(NodeEnum.GLOBAL.getType());
+
+        ButtonModel model = new ButtonModel();
+        FlowMethod flowMethod = new FlowMethod();
+        flowMethod.setNodes(nodes);
+        flowMethod.setTaskEntity(taskEntity);
+        flowMethod.setFormData(formData);
+        flowMethod.setPrintNodeList(nodeList);
+        OpTypeEnum type = OpTypeEnum.getType(opType);
+        switch (type) {
+            case LAUNCH_CREATE: // 鎴戝彂璧风殑鏂板缓/缂栬緫
+                // 鏄惁鏄��鍥炴挙鍥炵殑浠诲姟
+                List<Integer> taskStatus = ImmutableList.of(TaskStatusEnum.BACKED.getCode(), TaskStatusEnum.RECALL.getCode());
+                boolean isBack = taskStatus.contains(taskEntity.getStatus());
+                if (isBack) {
+                    // 鏄惁鏄鎵樼殑浠诲姟
+                    boolean isDelegate = StringUtils.isNotBlank(taskEntity.getDelegateUserId());
+                    if (isDelegate && ObjectUtil.equals(taskEntity.getParentId(), FlowNature.PARENT_ID)) {
+
+                        model.setHasDelegateSubmitBtn(this.checkDelegateSubmit(userId, template));
+
+                    }
+                } else {
+                    // 濮旀墭鍙戣捣
+                    if (null == taskEntity.getId()) {
+                        model.setHasDelegateSubmitBtn(this.checkDelegateSubmit(userId, template));
+                    } else {
+                        if (ObjectUtil.equals(taskEntity.getParentId(), FlowNature.PARENT_ID)) {
+                            model.setHasDelegateSubmitBtn(this.checkDelegateSubmit(userId, template));
+                        }
+                    }
+                }
+
+                //鏆傚瓨鍜屽彂璧锋寜閽�
+                boolean commonUser = serviceUtil.isCommonUser(userId);
+                if (commonUser) {
+                    if (null == taskEntity.getId() || ObjectUtil.equals(taskEntity.getParentId(), FlowNature.PARENT_ID)) {
+                        AuthorizeVO authorizeByUser = serviceUtil.getAuthorizeByUser();
+                        List<String> systemIdList = authorizeByUser.getSystemList().stream().filter(t -> !Objects.equals(t.getIsMain(), 1)).map(SystemBaeModel::getId).collect(Collectors.toList());
+                        if (!systemIdList.isEmpty()) {
+                            QueryWrapper<TemplateEntity> queryWrapper = new QueryWrapper<>();
+                            queryWrapper.lambda().in(TemplateEntity::getSystemId, systemIdList)
+                                    .eq(TemplateEntity::getVisibleType, FlowNature.ALL);
+                            queryWrapper.lambda().select(TemplateEntity::getId);
+                            List<TemplateEntity> list = templateMapper.selectList(queryWrapper);
+                            List<String> permissionList = list.stream().map(TemplateEntity::getId).collect(Collectors.toList());
+                            permissionList.addAll(authorizeByUser.getFlowIdList());
+                            if (permissionList.contains(template.getId())) {
+                                model.setHasSubmitBtn(true);
+                                model.setHasSaveBtn(true);
+                            }
+                        }
+                    } else {
+                        model.setHasSubmitBtn(true);
+                        model.setHasSaveBtn(true);
+                    }
+                } else {
+                    model.setHasSubmitBtn(true);
+                    model.setHasSaveBtn(true);
+                }
+                break;
+            case LAUNCH_DETAIL: // 鎴戝彂璧风殑璇︽儏
+                // 鎵撳嵃
+                TemplateNodeEntity start = nodeEntityList.stream().filter(e -> e.getNodeType().equals(NodeEnum.START.getType())).findFirst().orElse(null);
+                if (null != start) {
+                    NodeModel startNode = JsonUtil.getJsonToBean(start.getNodeJson(), NodeModel.class);
+                    flowMethod.setNodeModel(startNode);
+                    model.setHasPrintBtn(this.checkPrint(flowMethod));
+                }
+                // 鍌姙
+                List<Integer> statusList = ImmutableList.of(TaskStatusEnum.RUNNING.getCode(), TaskStatusEnum.REVOKING.getCode());
+                if (Boolean.TRUE.equals(global.getHasInitiatorPressOverdueNode()) && statusList.contains(taskEntity.getStatus())) {
+                    QueryWrapper<OperatorEntity> queryWrapper = new QueryWrapper<>();
+                    queryWrapper.lambda().eq(OperatorEntity::getTaskId, taskEntity.getId()).eq(OperatorEntity::getCompletion, FlowNature.NORMAL)
+                            .ne(OperatorEntity::getStatus, OperatorStateEnum.FUTILITY.getCode())
+                            .isNull(OperatorEntity::getHandleStatus).isNotNull(OperatorEntity::getDuedate);
+                    List<OperatorEntity> operatorList = operatorMapper.selectList(queryWrapper);
+                    if (!operatorList.isEmpty()) {
+                        model.setHasPressBtn(true);
+                    }
+                }
+                // 鎾ゅ洖
+                if (null == revokeEntity) {
+                    flowModel.setFlag(FlowNature.INITIATE_FLAG);
+                    if (this.checkRecall(flowModel)) {
+                        model.setHasRecallLaunchBtn(true);
+                    }
+                }
+                // 鎾ら攢锛屽叏灞�灞炴�у紑鍚� 涓� 鍚屾剰鐘舵�佺殑浠诲姟鎵嶈兘鎾ら攢 涓斾笉鏄瓙娴佺▼
+                if (Boolean.TRUE.equals(global.getHasRevoke()
+                        && Objects.equals(taskEntity.getStatus(), TaskStatusEnum.PASSED.getCode()))
+                        && Objects.equals(taskEntity.getParentId(), FlowNature.PARENT_ID)) {
+                    Boolean isExist = revokeMapper.checkExist(taskEntity.getId());
+                    if (null == revokeEntity && isExist) {
+                        model.setHasRevokeBtn(true);
+                    }
+                }
+                break;
+            case SIGN: // 寰呯浜嬪疁
+                if (Objects.equals(taskEntity.getStatus(), TaskStatusEnum.PAUSED.getCode())) {
+                    break;
+                }
+                model.setHasSignBtn(true);
+                if (null != operatorEntity) {
+                    model.setProxyMark(!ObjectUtil.equals(operatorEntity.getHandleId(), userId));
+                    NodeModel nodeModel = nodes.get(operatorEntity.getNodeCode());
+                    if (this.checkViewStartForm(global, nodeModel)) {
+                        model.setHasViewStartFormBtn(true);
+                    }
+                }
+                break;
+            case TODO: // 寰呭姙浜嬪疁
+                if (Objects.equals(taskEntity.getStatus(), TaskStatusEnum.PAUSED.getCode())) {
+                    break;
+                }
+                if (Boolean.TRUE.equals(global.getHasSignFor())) {
+                    model.setHasReduceSignBtn(true);
+                }
+                model.setHasTransactBtn(true);
+                if (null != operatorEntity) {
+                    NodeModel nodeModel = nodes.get(operatorEntity.getNodeCode());
+                    if (this.checkViewStartForm(global, nodeModel)) {
+                        model.setHasViewStartFormBtn(true);
+                    }
+                }
+                break;
+            case DOING: // 鍦ㄥ姙浜嬪疁
+                if (Objects.equals(taskEntity.getStatus(), TaskStatusEnum.PAUSED.getCode())) {
+                    break;
+                }
+                if (null == operatorEntity) {
+                    break;
+                }
+                // 寰呭姙鐨刼pType浼犵殑涔熸槸3锛屾墍浠ュ緟鍔炵殑浠g悊鏍囪瘑闇�瑕佸啀鍦ㄥ姙鍒ゆ柇
+                model.setProxyMark(!ObjectUtil.equals(operatorEntity.getHandleId(), userId));
+                if (null != revokeEntity) {
+                    model.setHasAuditBtn(true);
+                    model.setHasRejectBtn(true);
+                    break;
+                }
+                NodeModel nodeModel = nodes.get(operatorEntity.getNodeCode());
+                if (null == nodeModel) {
+                    break;
+                }
+                if (this.checkViewStartForm(global, nodeModel)) {
+                    model.setHasViewStartFormBtn(true);
+                }
+                // 鍗忓姙鐘舵�佺殑缁忓姙 鍙湁鍗忓姙淇濆瓨鎸夐挳
+                if (OperatorStateEnum.ASSIST.getCode().equals(operatorEntity.getStatus())) {
+                    model.setHasAssistSaveBtn(true);
+                    break;
+                }
+                // 鎵撳嵃
+                flowMethod.setNodeModel(nodeModel);
+                model.setHasPrintBtn(this.checkPrint(flowMethod));
+                if (Boolean.TRUE.equals(nodeModel.getHasAuditBtn())) {
+                    model.setHasAuditBtn(true);
+                }
+                if (Boolean.TRUE.equals(nodeModel.getHasRejectBtn()) && ObjectUtil.equals(operatorEntity.getIsProcessing(), FlowNature.NOT_PROCESSING)) {
+                    model.setHasRejectBtn(true);
+                }
+                if (Boolean.TRUE.equals(nodeModel.getHasBackBtn()) && taskEntity.getRejectDataId() == null) {
+                    model.setHasBackBtn(true);
+                }
+                if (Boolean.TRUE.equals(nodeModel.getHasSaveAuditBtn())) {
+                    model.setHasSaveAuditBtn(true);
+                }
+                List<Integer> operatorState = ImmutableList.of(OperatorStateEnum.ADD_SIGN.getCode(), OperatorStateEnum.TRANSFER.getCode());
+                if (Boolean.TRUE.equals(nodeModel.getHasFreeApproverBtn()) && !ObjectUtil.equals(operatorEntity.getStatus(), OperatorStateEnum.TRANSFER.getCode())) {
+
+                    model.setHasFreeApproverBtn(this.checkAddSign(operatorEntity, null, false));
+
+                }
+                if (Boolean.TRUE.equals(nodeModel.getHasTransferBtn()
+                        && !operatorState.contains(operatorEntity.getStatus()))
+                        && ObjectUtil.equals(operatorEntity.getParentId(), FlowNature.PARENT_ID)) {
+
+                    model.setHasTransferBtn(true);
+
+                }
+                if (Boolean.TRUE.equals(nodeModel.getHasAssistBtn())) {
+                    model.setHasAssistBtn(true);
+                }
+                break;
+            case DONE: // 宸插姙浜嬪疁
+                if (null == operatorEntity || operatorEntity.getId() == null) {
+                    break;
+                }
+                // 鍑忕
+                NodeModel node = nodes.get(operatorEntity.getNodeCode());
+                // 鑺傜偣灞炴�у紑鍚�佺粡鍔炲瓨鍦ㄥ姞绛句俊鎭�佽褰曟槸鍔犵鎿嶄綔
+                if (node != null) {
+                    if (null != recordEntity) {
+                        if (Boolean.TRUE.equals(node.getHasReduceApproverBtn() && null != operatorEntity.getHandleParameter())
+                                && recordEntity.getHandleType().equals(RecordEnum.ADD_SIGN.getCode())) {
+                            QueryWrapper<OperatorEntity> queryWrapper = new QueryWrapper<>();
+                            queryWrapper.lambda().eq(OperatorEntity::getTaskId, operatorEntity.getTaskId())
+                                    .eq(OperatorEntity::getParentId, operatorEntity.getId())
+                                    .ne(OperatorEntity::getStatus, OperatorStateEnum.FUTILITY.getCode())
+                                    .ne(OperatorEntity::getStatus, OperatorStateEnum.ASSIST.getCode())
+                                    .eq(OperatorEntity::getCompletion, FlowNature.NORMAL).isNull(OperatorEntity::getHandleStatus);
+                            List<OperatorEntity> list = operatorMapper.selectList(queryWrapper);
+                            if (CollUtil.isNotEmpty(list)) {
+                                model.setHasReduceApproverBtn(true);
+                            }
+                        }
+                        // 瀹℃壒鎾ゅ洖
+                        List<Integer> handleTypes = ImmutableList.of(RecordEnum.AUDIT.getCode(), RecordEnum.REJECT.getCode());
+                        if (handleTypes.contains(recordEntity.getHandleType())) {
+                            flowModel.setFlag(FlowNature.APPROVAL_FLAG);
+                            if (this.checkRecall(flowModel)) {
+                                model.setHasRecallAuditBtn(true);
+                            }
+                        }
+                    }
+                    flowMethod.setNodeModel(node);
+                    // 鎵撳嵃
+                    model.setHasPrintBtn(this.checkPrint(flowMethod));
+                    if (this.checkViewStartForm(global, node)) {
+                        model.setHasViewStartFormBtn(true);
+                    }
+                }
+                break;
+            case CIRCULATE: // 鎶勯�佷簨瀹�
+                if (null != operatorEntity) {
+                    NodeModel node1 = nodes.get(operatorEntity.getNodeCode());
+                    if (this.checkViewStartForm(global, node1)) {
+                        model.setHasViewStartFormBtn(true);
+                    }
+                }
+                break;
+            case MONITOR: // 娴佺▼鐩戞帶
+                // 缁堟鐘舵�佷笅鍙湁澶嶆椿
+                if (ObjectUtil.equals(taskEntity.getStatus(), TaskStatusEnum.CANCEL.getCode())
+                        && ObjectUtil.equals(taskEntity.getParentId(), FlowNature.PARENT_ID) && ObjectUtil.equals(template.getStatus(), TemplateStatueEnum.UP.getCode())) {
+                    List<TriggerRecordEntity> triggerRecordList = triggerRecordMapper.getListByTaskId(taskEntity.getId());
+                    long count = triggerRecordList.stream().filter(e -> ObjectUtil.equals(e.getStatus(), TriggerRecordEnum.EXCEPTION.getCode())).count();
+                    if (count == 0) {
+                        model.setHasActivateBtn(true);
+                    }
+                }
+                // 鎸傝捣鐘舵�佷笅鍙湁鎭㈠
+                if (ObjectUtil.equals(taskEntity.getStatus(), TaskStatusEnum.PAUSED.getCode())
+                        && !ObjectUtil.equals(taskEntity.getIsRestore(), FlowNature.NOT_RESTORE)) {
+
+                    model.setHasRebootBtn(true);
+
+                }
+                // 杩愯鐘舵�佷笅锛岀粓姝€�佹寕璧�
+                if (ObjectUtil.equals(taskEntity.getStatus(), TaskStatusEnum.RUNNING.getCode())) {
+                    // 瀛愭祦绋嬩笉鍏佽缁堟
+                    if (ObjectUtil.equals(taskEntity.getParentId(), FlowNature.PARENT_ID)) {
+                        model.setHasCancelBtn(true);
+                    }
+                    model.setHasPauseBtn(true);
+                    if (this.checkAssign(taskEntity, nodes)) {
+                        model.setHasAssignBtn(true);
+                    }
+                }
+                // 褰掓。鎸夐挳
+                FileConfig config = global.getFileConfig();
+                if ((config.getOn() && StringUtils.isNotBlank(config.getTemplateId()))
+                        && (ObjectUtil.isNotEmpty(taskEntity.getEndTime()) || ObjectUtil.equals(taskEntity.getStatus(), TaskStatusEnum.CANCEL.getCode()))
+                        && Boolean.TRUE.equals((serviceUtil.checkFlowFile(taskEntity.getId())))) {
+
+                    model.setHasFileBtn(true);
+
+                }
+                break;
+        }
+        return model;
+    }
+
+    // 鍒ゆ柇鎸囨淳锛屽綋鍓嶈妭鐐瑰叏鏄瓙娴佺▼锛屽氨闅愯棌
+    public boolean checkAssign(TaskEntity taskEntity, Map<String, NodeModel> nodes) {
+        String currentNodeCode = taskEntity.getCurrentNodeCode();
+        if (StringUtils.isNotBlank(currentNodeCode)) {
+            List<String> currentNodeList = Arrays.stream(currentNodeCode.split(",")).collect(Collectors.toList());
+            for (String nodeCode : currentNodeList) {
+                NodeModel nodeModel = nodes.get(nodeCode);
+                if (null != nodeModel && !Objects.equals(nodeModel.getType(), NodeEnum.SUB_FLOW.getType())) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    // 濮旀墭鍙戣捣鎸夐挳
+    public boolean checkDelegateSubmit(String userId, TemplateEntity template) {
+        List<DelegateEntity> delegateList = flowUtil.getByToUserId(userId, 0);
+        if (CollUtil.isNotEmpty(delegateList) && ObjectUtil.equals(template.getStatus(), TemplateStatueEnum.UP.getCode())) {
+            for (DelegateEntity delegateEntity : delegateList) {
+                String flowId = delegateEntity.getFlowId();
+                if (StringUtils.isNotBlank(flowId)) {
+                    if (flowId.contains(template.getId())) {
+                        if (ObjectUtil.equals(template.getVisibleType(), FlowNature.ALL)) {
+                            return true;
+                        }
+                        List<String> launchPermission = serviceUtil.getPermission(delegateEntity.getUserId());
+                        if (launchPermission.contains(template.getId())) {
+                            return true;
+                        }
+                    }
+                } else {
+                    // 鍏ㄩ儴娴佺▼
+                    if (ObjectUtil.equals(template.getVisibleType(), FlowNature.ALL)) {
+                        return true;
+                    }
+                    List<String> launchPermission = serviceUtil.getPermission(delegateEntity.getUserId());
+                    if (launchPermission.contains(template.getId())) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 鏌ョ湅鍙戣捣琛ㄥ崟
+     */
+    public boolean checkViewStartForm(NodeModel global, NodeModel nodeModel) {
+        return null != nodeModel && global.getHasAloneConfigureForms()
+                && StringUtils.isNotBlank(nodeModel.getFormId());
+    }
+
+    /**
+     * 鍒ゆ柇鎾ゅ洖
+     *
+     * @param flowModel 鍙傛暟
+     */
+    public boolean checkRecall(FlowModel flowModel) throws WorkFlowException {
+        String deploymentId = flowModel.getDeploymentId();
+        String currentNodeCode = flowModel.getNodeEntity().getNodeCode();
+        TaskEntity taskEntity = flowModel.getTaskEntity();
+        RecordEntity recordEntity = flowModel.getRecordEntity();
+        Map<String, NodeModel> nodes = flowModel.getNodes();
+        // 鍒ゆ柇鎾ゅ洖鐨勬爣璇�  1.鍙戣捣鎾ゅ洖  2.瀹℃壒鎾ゅ洖
+        int flag = flowModel.getFlag();
+        boolean isException = flowModel.getIsException();
+
+        NodeModel global = nodes.get(NodeEnum.GLOBAL.getType());
+        Integer recallRule = global.getRecallRule();
+
+        // 鍏ㄥ眬鎾ゅ洖閰嶇疆涓�1 鐩存帴涓嶅厑璁告挙鍥� (娴佺▼鎾ゅ洖瑙勫垯  1: 涓嶅厑璁告挙鍥�  2: 鍙戣捣鑺傜偣鍏佽鎾ゅ洖  3:鎵�鏈夎妭鐐瑰厑璁告挙鍥�)
+        if (recallRule == null || Objects.equals(recallRule, FlowNature.NOT_ALLOWED)) {
+            return false;
+        }
+
+        // 涓嶆槸杩涜涓殑浠诲姟銆佸瓨鍦ㄩ��鍥炲喕缁撴暟鎹�
+        if (!Objects.equals(TaskStatusEnum.RUNNING.getCode(), taskEntity.getStatus()) || null != taskEntity.getRejectDataId()) {
+            if (isException) {
+                throw new WorkFlowException(MsgCode.WF036.get());
+            }
+            return false;
+        }
+        // 缁忓姙鏈鎵� 璇存槑鏄凡鎾ゅ洖鐨勶紝涓嶅厑璁告挙鍥�
+        OperatorEntity operator = operatorMapper.getInfo(recordEntity.getOperatorId());
+        if (null != operator) {
+            if (!ObjectUtil.equals(operator.getParentId(), FlowNature.PARENT_ID)) {
+                if (isException) {
+                    throw new WorkFlowException(MsgCode.WF077.get());
+                }
+                return false;
+            }
+            // 鍒ゆ柇渚濇瀹℃壒
+            boolean inTurn = this.checkInTurn(operator, isException);
+            if (!inTurn && !isException) {
+                return false;
+            }
+            //鍒ゆ柇閫愮骇瀹℃壒
+            boolean inStep = this.checkStep(operator, isException);
+            if (!inStep && !isException) {
+                return false;
+            }
+            if (operator.getHandleStatus() == null) {
+                if (isException) {
+                    throw new WorkFlowException(MsgCode.WF006.get());
+                }
+                return false;
+            } else if (null == operator.getHandleTime()) {
+                // 鍚庡姞绛剧殑鍚屾剰鏈湡姝e鎵癸紝涓嶅厑璁告挙鍥�
+                List<OperatorEntity> childList = operatorMapper.getChildList(operator.getId());
+                if (CollUtil.isNotEmpty(childList)) {
+                    if (isException) {
+                        throw new WorkFlowException(MsgCode.WF006.get());
+                    }
+                    return false;
+                }
+            }
+        } else {
+            // 鍙戣捣鎾ゅ洖鐨勬牎楠�
+            QueryWrapper<RecordEntity> recordWrapper = new QueryWrapper<>();
+            recordWrapper.lambda().eq(RecordEntity::getTaskId, taskEntity.getId()).ne(RecordEntity::getStatus, FlowNature.INVALID);
+            List<RecordEntity> recordList = recordMapper.selectList(recordWrapper);
+            if (CollUtil.isNotEmpty(recordList)) {
+                RecordEntity submit = recordList.stream().filter(e -> ObjectUtil.equals(e.getHandleType(), RecordEnum.SUBMIT.getCode())).findFirst().orElse(null);
+                if (null != submit) {
+                    recordList = recordList.stream().filter(e -> !ObjectUtil.equals(e.getNodeCode(), submit.getNodeCode())).collect(Collectors.toList());
+                }
+                if (!recordList.isEmpty()) {
+                    if (isException) {
+                        throw new WorkFlowException(MsgCode.WF006.get());
+                    }
+                    return false;
+                }
+            }
+
+            //澶栭儴鑺傜偣
+            List<EventLogEntity> eventLogList = eventLogMapper.getList(taskEntity.getId()).stream().filter(e -> Objects.equals(FlowNature.SUCCESS, e.getStatus())).collect(Collectors.toList());
+            if (CollUtil.isNotEmpty(eventLogList) && !eventLogList.isEmpty()) {
+                if (isException) {
+                    throw new WorkFlowException(MsgCode.WF006.get());
+                }
+                return false;
+
+            }
+        }
+        // 鑾峰彇鑺傜偣鐨勪笅涓�绾ц妭鐐�,鍒ゆ柇鎾ゅ洖
+        NextOrPrevFo fo = new NextOrPrevFo();
+        fo.setDeploymentId(deploymentId);
+        fo.setTaskKey(currentNodeCode);
+        List<FlowableNodeModel> nextModels = flowAbleUrl.getNext(fo);
+        List<String> nextCodes = nextModels.stream().map(FlowableNodeModel::getId).collect(Collectors.toList());
+        // 瀹℃壒鎾ゅ洖闇�瑕佺敤鍒颁笅涓�绾ц妭鐐�
+        flowModel.setNextCodes(nextCodes);
+
+        if (CollUtil.isNotEmpty(nextCodes)) {
+            QueryWrapper<TaskEntity> queryWrapper = new QueryWrapper<>();
+            queryWrapper.lambda().eq(TaskEntity::getParentId, taskEntity.getId())
+                    .in(TaskEntity::getSubCode, nextCodes);
+            List<TaskEntity> list = taskMapper.selectList(queryWrapper);
+            if (CollUtil.isNotEmpty(list)) {
+                // 寮傛瀛愭祦绋嬶紝涓嶅厑璁告挙鍥�
+                long asyncCount = list.stream().filter(e -> Objects.equals(e.getIsAsync(), FlowNature.CHILD_ASYNC)).count();
+                if (asyncCount > 0) {
+                    return false;
+                }
+                long count = list.stream().filter(e -> !Objects.equals(e.getStatus(), TaskStatusEnum.TO_BE_SUBMIT.getCode())).count();
+                if (count > 0) {
+                    if (isException) {
+                        throw new WorkFlowException(MsgCode.WF036.get());
+                    }
+                    return false;
+                }
+            }
+
+            //澶栭儴鑺傜偣鍙鏈夋垚鍔熸暟鎹紝涓嶅厑璁告挙鍥�
+            List<EventLogEntity> eventLogList = eventLogMapper.getList(taskEntity.getId(), nextCodes).stream().filter(e -> Objects.equals(FlowNature.SUCCESS, e.getStatus())).collect(Collectors.toList());
+            if (CollUtil.isNotEmpty(eventLogList) && !eventLogList.isEmpty()) {
+                if (isException) {
+                    throw new WorkFlowException(MsgCode.WF006.get());
+                }
+                return false;
+
+            }
+        }
+
+        if (Objects.equals(flag, FlowNature.APPROVAL_FLAG) && Objects.equals(recallRule, FlowNature.START_ALLOWED)) {
+            return false;
+        }
+        if (CollUtil.isEmpty(nextCodes)) {
+            return true;
+        }
+        // 瀛樺湪宸插姙鐞嗙殑缁忓姙锛屾挙鍥炲悗鍙互閲嶆柊鎻愪氦锛堜笅涓鎵硅妭鐐瑰彧杩涜浜嗙鏀� 姝ゆ椂杩樺彲浠ユ挙鍥烇級
+        QueryWrapper<OperatorEntity> wrapper = new QueryWrapper<>();
+        wrapper.lambda().eq(OperatorEntity::getTaskId, taskEntity.getId());
+        if (CollUtil.isNotEmpty(nextCodes)) {
+            wrapper.lambda().in(OperatorEntity::getNodeCode, nextCodes);
+        }
+        wrapper.lambda().orderByDesc(OperatorEntity::getCreatorTime);
+        List<OperatorEntity> list = operatorMapper.selectList(wrapper);
+        boolean mark = this.checkDraftAndRecord(list);
+        if (mark) {
+            if (isException) {
+                throw new WorkFlowException(MsgCode.WF077.get());
+            }
+            return false;
+        }
+
+        //鍔犵鍜岃鍔犵浜轰笉鑳芥挙鍥�
+        if (operator != null) {
+            if (!Objects.equals(operator.getParentId(), FlowNature.PARENT_ID)) {
+                return false;
+            }
+            if (StringUtil.isNotEmpty(operator.getHandleParameter())) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    // 渚濇瀹℃壒鐨勬挙鍥炲垽鏂�
+    public boolean checkInTurn(OperatorEntity operator, boolean isException) throws WorkFlowException {
+        if (StringUtils.isNotBlank(operator.getHandleAll())) {
+            List<String> handleIds = Arrays.stream(operator.getHandleAll().split(",")).collect(Collectors.toList());
+            int index = handleIds.indexOf(operator.getHandleId());
+            if (index != -1 && index < handleIds.size() - 1) {
+                String nextHandleId = handleIds.get(index + 1);
+                QueryWrapper<OperatorEntity> queryWrapper = new QueryWrapper<>();
+                queryWrapper.lambda().eq(OperatorEntity::getHandleId, nextHandleId).eq(OperatorEntity::getParentId, operator.getParentId())
+                        .eq(OperatorEntity::getNodeId, operator.getNodeId()).orderByDesc(OperatorEntity::getCreatorTime);
+                List<OperatorEntity> list = operatorMapper.selectList(queryWrapper);
+                if (CollUtil.isNotEmpty(list)) {
+                    OperatorEntity nextOperator = list.get(0);
+                    if (StringUtil.isNotEmpty(nextOperator.getDraftData())) {
+                        if (isException) {
+                            throw new WorkFlowException(MsgCode.WF036.get());
+                        }
+                        return false;
+                    }
+                    QueryWrapper<RecordEntity> recordWrapper = new QueryWrapper<>();
+                    recordWrapper.lambda().eq(RecordEntity::getOperatorId, nextOperator.getId()).ne(RecordEntity::getStatus, FlowNature.INVALID);
+                    List<RecordEntity> recordList = recordMapper.selectList(recordWrapper);
+                    if (CollUtil.isNotEmpty(recordList)) {
+                        if (isException) {
+                            throw new WorkFlowException(MsgCode.WF036.get());
+                        }
+                        return false;
+                    }
+                }
+            }
+        }
+        return true;
+    }
+
+    // 閫愮骇瀹℃壒鐨勬挙鍥炲垽鏂�
+    public boolean checkStep(OperatorEntity operator, boolean isException) throws WorkFlowException {
+        QueryWrapper<OperatorEntity> queryWrapper = new QueryWrapper<>();
+        queryWrapper.lambda().eq(OperatorEntity::getTaskId, operator.getTaskId());
+        List<OperatorEntity> operatorList = operatorMapper.selectList(queryWrapper);
+        List<OperatorEntity> list = operatorList.stream().filter(e -> Objects.equals(e.getHandleAll(), operator.getId())).collect(Collectors.toList());
+        if (CollUtil.isNotEmpty(list)) {
+            OperatorEntity nextOperator = list.get(0);
+            if (StringUtil.isNotEmpty(nextOperator.getDraftData())) {
+                if (isException) {
+                    throw new WorkFlowException(MsgCode.WF036.get());
+                }
+                return false;
+            }
+            QueryWrapper<RecordEntity> recordWrapper = new QueryWrapper<>();
+            recordWrapper.lambda().eq(RecordEntity::getOperatorId, nextOperator.getId()).ne(RecordEntity::getStatus, FlowNature.INVALID);
+            List<RecordEntity> recordList = recordMapper.selectList(recordWrapper);
+            if (CollUtil.isNotEmpty(recordList)) {
+                if (isException) {
+                    throw new WorkFlowException(MsgCode.WF036.get());
+                }
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public boolean checkDraftAndRecord(List<OperatorEntity> list) {
+        return this.checkDraftAndRecord(list, false);
+    }
+
+    // 鍒ゆ柇鑽夌銆佹搷浣滆褰�
+    public boolean checkDraftAndRecord(List<OperatorEntity> list, boolean filterAddSign) {
+        list = list.stream().filter(e -> !ObjectUtil.equals(e.getStatus(), OperatorStateEnum.FUTILITY.getCode())).collect(Collectors.toList());
+        if (CollUtil.isEmpty(list)) {
+            return false;
+        }
+        // 鍙鏈夋搷浣滃氨涓嶈鎾ゅ洖锛岃崏绋挎暟鎹紙鏆傚瓨锛�
+        long draftCount = list.stream().filter(e -> StringUtil.isNotEmpty(e.getDraftData())).count();
+        boolean mark = false;
+        // 涓嶅瓨鍦ㄨ崏绋挎暟鎹紝缁х画鏍规嵁璁板綍鍒ゆ柇
+        if (draftCount == 0) {
+            List<String> collect = list.stream().map(OperatorEntity::getId).collect(Collectors.toList());
+            if (CollUtil.isNotEmpty(collect)) {
+                QueryWrapper<RecordEntity> recordWrapper = new QueryWrapper<>();
+                recordWrapper.lambda().in(RecordEntity::getOperatorId, collect).ne(RecordEntity::getStatus, FlowNature.INVALID);
+                List<RecordEntity> recordList = recordMapper.selectList(recordWrapper);
+                if (filterAddSign) {
+                    List<Integer> status = ImmutableList.of(RecordEnum.ADD_SIGN.getCode(), RecordEnum.SUBTRACT_SIGN.getCode());
+                    recordList = recordList.stream().filter(e -> !status.contains(e.getHandleType())).collect(Collectors.toList());
+                }
+                mark = !recordList.isEmpty();
+            }
+        } else {
+            mark = true;
+        }
+        return mark;
+    }
+
+    /**
+     * 鍒ゆ柇鎵撳嵃
+     */
+    public boolean checkPrint(FlowMethod flowMethod) {
+        NodeModel nodeModel = flowMethod.getNodeModel();
+        TaskEntity taskEntity = flowMethod.getTaskEntity();
+        List<TaskNodeModel> nodeList = flowMethod.getPrintNodeList();
+
+        // 鍙戣捣闄や簡鑽夌鐘舵�侀兘鏄剧ず
+        if (Objects.equals(taskEntity.getStatus(), TaskStatusEnum.TO_BE_SUBMIT.getCode())) {
+            return false;
+        }
+        PrintConfig printConfig = nodeModel.getPrintConfig();
+        if (Boolean.TRUE.equals(printConfig.getOn())) {
+            // 鎵撳嵃娌℃湁閫夋嫨妯$増锛屾寜閽笉鏄剧ず
+            if (CollUtil.isEmpty(printConfig.getPrintIds())) {
+                return false;
+            }
+            switch (PrintEnum.getPrint(printConfig.getConditionType())) {
+                case NONE:
+                    // 涓嶉檺鍒�
+                    return true;
+                case NODE_END:
+                    // 鑺傜偣缁撴潫
+                    // 寮�濮嬭妭鐐圭洿鎺ヨ繑鍥瀟rue锛岄櫎鑽夌鐘舵��
+                    if (nodeModel.getType().equals(NodeEnum.START.getType())
+                            && !taskEntity.getStatus().equals(TaskStatusEnum.TO_BE_SUBMIT.getCode())) {
+                        return true;
+                    }
+                    TaskNodeModel taskNode = nodeList.stream().filter(e -> e.getNodeCode().equals(nodeModel.getNodeId())).findFirst().orElse(null);
+                    if (null != taskNode && Objects.equals(taskNode.getType(), NodeTypeEnum.PASS.getType())) {
+                        return true;
+                    }
+                    break;
+                case FLOW_END:
+                    // 娴佺▼缁撴潫
+                    List<Integer> status = ImmutableList.of(TaskStatusEnum.PASSED.getCode(), TaskStatusEnum.REJECTED.getCode());
+                    if (status.contains(taskEntity.getStatus())) {
+                        return true;
+                    }
+                    break;
+                case CONDITIONS:
+                    // 鏉′欢璁剧疆
+                    List<ProperCond> conditions = printConfig.getConditions();
+                    String matchLogic = printConfig.getMatchLogic();
+                    UserInfo userInfo = UserProvider.getUser();
+                    flowMethod.setUserInfo(userInfo);
+                    flowMethod.setUserEntity(serviceUtil.getUserInfo(userInfo.getUserId()));
+                    flowMethod.setConditions(conditions);
+                    flowMethod.setMatchLogic(matchLogic);
+                    if (FlowJsonUtil.nodeConditionDecide(flowMethod)) {
+                        return true;
+                    }
+                    break;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 鍒ゆ柇鍔犵
+     */
+    public void checkAddSign(OperatorEntity operator, AddSignModel parameter) throws WorkFlowException {
+        this.checkAddSign(operator, parameter, true);
+    }
+
+    public boolean checkAddSign(OperatorEntity operator, AddSignModel parameter, Boolean isException) throws WorkFlowException {
+        int level = 1;
+        if (!ObjectUtil.equals(operator.getParentId(), FlowNature.PARENT_ID)) {
+            OperatorEntity parent = operatorMapper.selectById(operator.getParentId());
+            if (null != parent) {
+                String handleParameter = parent.getHandleParameter() == null ? operator.getHandleParameter() : parent.getHandleParameter();
+                AddSignModel jsonToBean = JsonUtil.getJsonToBean(handleParameter, AddSignModel.class);
+                level = jsonToBean.getLevel() + 1;
+            }
+        }
+        SysConfigModel sysConfig = serviceUtil.getSysConfig();
+        Integer addSignLevel = sysConfig.getAddSignLevel();
+        if (level > addSignLevel) {
+            if (Boolean.TRUE.equals(isException)) {
+                throw new WorkFlowException(MsgCode.WF143.get());
+            }
+            return false;
+        }
+        if (null != parameter) {
+            parameter.setLevel(level);
+        }
+        return true;
+    }
+}

--
Gitblit v1.8.0