案例-流程根据对照流程自动流转

发布于 2026-07-09

需求描述

需求概括

流程表单内选择另一个流程,当流程提交到下个节点后,判断另一个流程的对应节点的操作者是否与当前流程操作者相同并且已提交,如符合则自动提交当前流程。

详细描述

在流程内选择另一个已归档流程,当操作中提及后流转到下个节点后,需要判断:

  • 另一个流程里的对应节点的操作者是否与当前流程当前节点操作者相同
  • 另一个流程里的对应节点的操作者是否已提交

如符合上述条件,则当前流程的当前节点自动提交,提交之后再对下个节点进行相同的检查,如符合则继续提交。当前流程与对照流程之间的节点关系映射通过建模来配置,例如流程1表单里需要选择流程2,则在建模里配置流程1与流程2节点的映射关系,只有流程流转到建模配置的节点才进行开发处理。

建模配置界面

实现思路

1.首先在建模配置两个流程的节点对应关系,当流程1流转到配置的节点时,将判断另一个流程的对应节点

2.后端代理 RequestSubmitCmd 类,当提交流程后触发此代理,执行 nextExecute() 让流程流转到下个节点,再执行以下步骤的逻辑

3.判断当前流程的当前节点是否配置在建模内,如果没有则结束处理

4.获取到当前流程节点、当前流程操作者、关联流程节点和操作者,判断两个流程节点的操作者是否相同,如不相同则结束处理 5.如符合条件,调用 WorkflowRequestOperatePAImpl.submitRequest() 方法进行提交流程,此方法是对外流程提交接口的执行方法,因为调用比较简单所以用这个。这里采用递归调用,当执行提交之后再判断当前流程的节点是否符合条件,如符合则再次提交,如此反复知道条件不符合为止。

RequestSubmitCmd代理类代码:

package com.customization.proxy.yll.stw.autoflow;

import com.alibaba.fastjson.JSONObject;
import com.engine.common.util.ServiceUtil;
import com.engine.core.cfg.annotation.CommandDynamicProxy;
import com.engine.core.interceptor.AbstractCommandProxy;
import com.engine.core.interceptor.Command;
import com.engine.workflow.cmd.requestForm.RequestSubmitCmd;
import com.engine.workflow.constant.PAResponseCode;
import com.engine.workflow.constant.requestForm.RequestExecuteType;
import com.engine.workflow.entity.publicApi.PAResponseEntity;
import com.engine.workflow.entity.publicApi.ReqOperateRequestEntity;
import com.engine.workflow.entity.requestForm.RequestOperationResultBean;
import com.engine.workflow.publicApi.WorkflowRequestOperatePA;
import com.engine.workflow.publicApi.impl.WorkflowRequestOperatePAImpl;
import com.engine.workflow.util.HttpServletRequestUtil;
import weaver.conn.RecordSet;
import weaver.file.Prop;
import weaver.general.Util;
import weaver.hrm.User;
import weaver.integration.logging.Logger;
import weaver.integration.logging.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 姚礼林
 * @desc 流程自动流程开发。流程表单内选择另一个流程,当流程提交到下个节点后,判断另一个流程的对应节点的操作者是否与当前流程操作者
 * 相同并且已提交,如符合则自动提交当前流程。
 * @date 2023/6/2
 */
@CommandDynamicProxy(target = RequestSubmitCmd.class)
public class SubmitCmdProxy extends AbstractCommandProxy<Map<String, Object>> {
    public static final String CONFIGURATION_FILE = "FW20230706_stwautoflow";
    public static final String MODE_TABLE_PROP_NAME = "modeTable";
    public static final String DETAIL_TABLE_PROP_NAME = "detailTable";
    public static final String CONFIG_WORKFLOW_FIELD_NAME_PROP_NAME = "configWorkflowFieldName";
    public static final String RELATIVE_WORKFLOW_FIELD_NAME_PROP_NAME = "relativeWorkflowFieldName";
    public static final String OPERATE_NODE_ID_FIELD_NAME_PROP_NAME = "operateNodeIdFieldName";
    public static final String RELATIVE_NODE_ID_FIELD_NAME_PROP_NAME = "relativeNodeIdFieldName";
    public static final String IS_ADD_REMARK_PROP_NAME = "isAddRemark";
    public static final String REMARK_PROP_NAME = "remark";
    private final Logger logger = LoggerFactory.getLogger(this.getClass().getName() + "-自定义流程自动流程");

    @Override
    public Map<String, Object> execute(Command<Map<String, Object>> command) {
        RequestSubmitCmd requestSubmitCmd = (RequestSubmitCmd) command;
        Map<String, Object> result = nextExecute(requestSubmitCmd);
        RequestOperationResultBean resultBean = (RequestOperationResultBean) result.get("data");
        if (resultBean == null || resultBean.getType() != RequestExecuteType.SUCCESS){
            return result;
        }
        Map<String, Object> params = requestSubmitCmd.getParams();
        String workflowId = (String) params.get("workflowid");
        String requestId = String.valueOf(resultBean.getSubmitParams().get("requestid"));
        String formId = (String) params.get("formid");
        RecordSet recordSet = new RecordSet();
        // 获取建模配置
        Map<String, Object> modeConfiguration = getConfiguration(workflowId, recordSet);
        if (modeConfiguration.isEmpty()) {
            return result;
        }
        String relativeWorkflowFiledName = (String) modeConfiguration.get("relativeWorkflowFieldName");
        // 获取关联流程的请求ID
        String relativeWorkflowRequestId = getRelativeWorkflowRequestId(relativeWorkflowFiledName,
                formId, requestId, recordSet);
        if ("".equals(relativeWorkflowRequestId)) {
            return result;
        }

        flowNextNode(requestId, relativeWorkflowRequestId, (Map<String, String>) modeConfiguration.get("node"), recordSet);

        return result;
    }

    /**
     * 获取另一个流程的请求id
     *
     * @param relativeWorkflowFieldName 流程表单选择另一个流程的字段名
     * @param formId 当前流程的表单id
     * @param requestId 当前流程的请求id
     * @param recordSet recordSet
     * @return 另一个流程的请求id
     */
    private String getRelativeWorkflowRequestId(String relativeWorkflowFieldName, String formId,
                                                String requestId, RecordSet recordSet) {
        String sql = "select " + relativeWorkflowFieldName + " from " +
                "formtable_main_" + formId.substring(1) + " where requestid = ?";
        if (!recordSet.executeQuery(sql, requestId)){
            logger.error("查询关联流程的请求id失败,sql:"+sql);
            return "";
        }
        recordSet.next();
        return recordSet.getString(relativeWorkflowFieldName);
    }

    /**
     * 获取建模配置信息
     * @param workflowId 流程id
     * @param recordSet 请求id
     * @return 模配置信息,包含节点映射关系
     */
    private Map<String, Object> getConfiguration(String workflowId, RecordSet recordSet) {
        Map<String, Object> params = new HashMap<>(5);
        // 查询建模主表数据
        String sql = "select id," + getPropValue(CONFIG_WORKFLOW_FIELD_NAME_PROP_NAME)
                + "," + getPropValue(RELATIVE_WORKFLOW_FIELD_NAME_PROP_NAME) + " from "
                + getPropValue(MODE_TABLE_PROP_NAME) + " where " + getPropValue(CONFIG_WORKFLOW_FIELD_NAME_PROP_NAME)
                + "=?";
        try {
            if (!recordSet.executeQuery(sql, workflowId)) {
                logger.error("查询建模配置失败,sql:" + sql);
                return new HashMap<>(0);
            }
        } catch (Exception e) {
            logger.error("查询建模配置失败,sql:" + sql + " ,msg:" + e.getMessage() + "\n" + e.getCause());
            e.printStackTrace();
        }
        if (recordSet.next()) {
            int mainId = recordSet.getInt("id");
            params.put("relativeWorkflowFieldName", recordSet.getString(getPropValue(RELATIVE_WORKFLOW_FIELD_NAME_PROP_NAME)));
            // 查询建模明细数据
            String queryDetailSql = "select " + getPropValue(OPERATE_NODE_ID_FIELD_NAME_PROP_NAME) + ","
                    + getPropValue(RELATIVE_NODE_ID_FIELD_NAME_PROP_NAME) + " from " + getPropValue(DETAIL_TABLE_PROP_NAME)
                    + " where mainid = ?";
            try {
                if (!recordSet.executeQuery(queryDetailSql, mainId)) {
                    logger.error("查询建模明细出错,sql:" + queryDetailSql);
                    return new HashMap<>(0);
                }
            } catch (Exception e) {
                e.printStackTrace();
                logger.error("查询建模明细出错,sql:" + queryDetailSql + ",msg:" + e.getMessage() + "\n" + e.getCause());
                return new HashMap<>(0);
            }
            Map<String, String> nodeMap = new HashMap<>();
            while (recordSet.next()) {
                nodeMap.put(recordSet.getString(getPropValue(OPERATE_NODE_ID_FIELD_NAME_PROP_NAME)),
                        recordSet.getString(getPropValue(RELATIVE_NODE_ID_FIELD_NAME_PROP_NAME)));
            }
            params.put("node", nodeMap);
        }
        return params;
    }

    private String getPropValue(String propName) {
        return Prop.getPropValue(CONFIGURATION_FILE, propName);
    }

    private PAResponseEntity flowNextNode(String requestId, String relativeWorkflowRequestId,
                                          Map<String, String> nodeMap, RecordSet recordSet) {
        // 获取当前流程节点
        String sql = "select currentnodeid,lastoperator from workflow_requestbase where requestid = ?";
        recordSet.executeQuery(sql, requestId);
        recordSet.next();
        String nodeId = recordSet.getString("currentnodeid");
        if (!nodeMap.containsKey(nodeId)) {
            return null;
        }
        String relativeNode = nodeMap.get(nodeId);
        // 查询当前流程的操作者
        recordSet.executeQuery("SELECT userid from workflow_currentoperator where requestid = ? and NODEID = ? " +
                "order by id desc ", requestId, nodeId);
        recordSet.next();
        String currentOperator = recordSet.getString("userid");
        // 获取关联流程节点的操作者
        String getRelativeWorkflowOperatorSql = "SELECT operator from workflow_requestlog l where NODEID = ? and " +
                "(logtype = 0 or logtype=2) and REQUESTID = ? ORDER BY LOGID desc";
        recordSet.executeQuery(getRelativeWorkflowOperatorSql, relativeNode, relativeWorkflowRequestId);
        recordSet.next();
        String relativeWorkflowOperator = Util.null2String(recordSet.getString("operator"));
        if (!currentOperator.equals(relativeWorkflowOperator)) {
            return null;
        }

        ReqOperateRequestEntity operateEntity;
        JSONObject rqJson = new JSONObject();
        rqJson.put("requestId", requestId);
        // 判断是否需要加上流转意见
        if ("1".equals(getPropValue(IS_ADD_REMARK_PROP_NAME))){
            String remark = Util.null2String(getPropValue(REMARK_PROP_NAME));
            if (!"".equals(remark)){
                rqJson.put("remark",remark);
            }
        }

        operateEntity = HttpServletRequestUtil.json2Obj(rqJson.toJSONString(), ReqOperateRequestEntity.class);
        WorkflowRequestOperatePA operatePA = ServiceUtil.getService(WorkflowRequestOperatePAImpl.class);

        PAResponseEntity result = operatePA.submitRequest(new User(Integer.parseInt(currentOperator)), operateEntity);
        if (result.getCode() == PAResponseCode.SUCCESS){
            flowNextNode(requestId,relativeWorkflowRequestId,nodeMap,recordSet);
        }
        return result;
    }
}

源码

20230706-v1-正式包-上通五流程自动流转-姚礼林.zip