package com.xjrsoft.module.workflow.listener;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fasterxml.jackson.core.type.TypeReference;
import com.xjrsoft.common.constant.GlobalConstant;
import com.xjrsoft.common.enums.*;
import com.xjrsoft.common.exception.MyException;
import com.xjrsoft.common.utils.RedisUtil;
import com.xjrsoft.module.liteflow.entity.XjrLiteflowChain;
import com.xjrsoft.module.liteflow.service.IXjrLiteflowChainService;
import com.xjrsoft.module.magicapi.service.IMagicApiService;
import com.xjrsoft.module.magicapi.vo.MagicApiInfoVo;
import com.xjrsoft.module.organization.entity.User;
import com.xjrsoft.module.workflow.constant.WorkflowConstant;
import com.xjrsoft.module.workflow.entity.*;
import com.xjrsoft.module.workflow.model.*;
import com.xjrsoft.module.workflow.service.*;
import com.xjrsoft.module.workflow.utils.WorkFlowUtil;
import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder;
import com.yomahub.liteflow.core.FlowExecutor;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.camunda.bpm.engine.HistoryService;
import org.camunda.bpm.engine.RuntimeService;
import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.camunda.bpm.engine.delegate.ExecutionListener;
import org.camunda.bpm.engine.history.HistoricProcessInstance;
import org.camunda.bpm.engine.history.HistoricTaskInstance;
import org.camunda.bpm.engine.impl.core.model.CoreModelElement;
import org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity;
import org.camunda.bpm.engine.impl.pvm.PvmTransition;
import org.camunda.bpm.engine.impl.pvm.process.TransitionImpl;
import org.camunda.bpm.engine.variable.VariableMap;
import org.camunda.bpm.engine.variable.Variables;
import org.springframework.stereotype.Component;
import org.ssssssss.magicapi.core.service.MagicAPIService;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 执行器间监听器
 *
 * @Author: tzx
 * @Date: 2022/12/7 16:25
 */
@Component
@Slf4j
@AllArgsConstructor
public class ExecutionDelegate implements ExecutionListener {

    private final RedisUtil redisUtil;

    private final IWorkflowRecordService workflowRecordService;

    private final IWorkflowExtraService workflowExtraService;

    private final IWorkflowApproveRecordService workflowApproveRecordService;

    private final IWorkflowCirculatedService circulatedService;

    private final IXjrLiteflowChainService liteflowChainService;

    private final IXjrWorkflowOperateRecordService xjrWorkflowOperateRecordService;

    private final FlowExecutor flowExecutor;

//    private final IWorkflowSchemaService workflowSchemaService;

    @Override
    public void notify(DelegateExecution execution) {
        CoreModelElement eventSource = ((ExecutionEntity) execution).getEventSource();
        if (eventSource == null) {
            return;
        }

        //判断当前流程的 是否有缓存 事件
        String startEventKey = WorkflowConstant.START_EVENT_CACHE_PRE +  ((ExecutionEntity) execution).getProcessDefinition().getDeploymentId() + StringPool.COLON + eventSource.getId() + StringPool.COLON + WorkflowEventType.START.getValue();
        String endEventKey = WorkflowConstant.END_EVENT_CACHE_PRE +  ((ExecutionEntity) execution).getProcessDefinition().getDeploymentId() + StringPool.COLON + eventSource.getId() + StringPool.COLON + WorkflowEventType.END.getValue();

        //如果有当前节点有缓存开始事件数据
        if (redisUtil.containsKey(startEventKey) && execution.getEventName().equals(EVENTNAME_START)) {

            List<NodeEventConfig> startEventConfigs = redisUtil.get(startEventKey, new TypeReference<List<NodeEventConfig>>() {
            });

            if (startEventConfigs.size() > 0) {
                executeEvent(execution, startEventConfigs);
            }
//            //开始事件执行事件
//            if (execution.getEventName().equals(EVENTNAME_START)) {
//                List<NodeEventConfig> startEventConfigs = redisUtil.get(startEventKey, new TypeReference<List<NodeEventConfig>>() {
//                });
//
//                if (startEventConfigs.size() > 0) {
//                    executeEvent(execution, startEventConfigs);
//                }
//            }
        }
        //如果有当前节点有缓存开始事件数据
        if (redisUtil.containsKey(endEventKey) && execution.getEventName().equals(EVENTNAME_END)) {

            List<NodeEventConfig> endEventConfigs = redisUtil.get(endEventKey, new TypeReference<List<NodeEventConfig>>() {
            });

            if (endEventConfigs.size() > 0) {
                executeEvent(execution, endEventConfigs);
            }
//            //开始事件执行事件
//            if (execution.getEventName().equals(EVENTNAME_END)) {
//                List<NodeEventConfig> endEventConfigs = redisUtil.get(endEventKey, new TypeReference<List<NodeEventConfig>>() {
//                });
//
//                if (endEventConfigs.size() > 0) {
//                    executeEvent(execution, endEventConfigs);
//                }
//            }
        }


        //多实例一开始 默认设置变量
        if (StrUtil.equals(StrUtil.toString(eventSource.getProperty(WorkflowConstant.BPMN_EVENT_SOURCE_TYPE_KEY)), "multiInstanceBody")) {
            //多实例任务 开始事件
            if (execution.getEventName().equals(EVENTNAME_START)) {

                String agreeButtonVarName = ((ExecutionEntity) execution).getActivityId().replace(WorkflowConstant.MULTI_INSTANCE_STRING, StringPool.EMPTY) +
                        StringPool.UNDERSCORE + StringPool.UNDERSCORE + StringPool.UNDERSCORE +
                        WorkflowConstant.BUTTON_APPROVE_VAR_FLAG +
                        StringPool.UNDERSCORE + StringPool.UNDERSCORE + StringPool.UNDERSCORE +
                        WorkflowConstant.BUTTON_AGREE_APPROVE_VAR_FLAG;

                String rejectButtonVarName = ((ExecutionEntity) execution).getActivityId().replace(WorkflowConstant.MULTI_INSTANCE_STRING, StringPool.EMPTY) +
                        StringPool.UNDERSCORE + StringPool.UNDERSCORE + StringPool.UNDERSCORE +
                        WorkflowConstant.BUTTON_APPROVE_VAR_FLAG +
                        StringPool.UNDERSCORE + StringPool.UNDERSCORE + StringPool.UNDERSCORE +
                        WorkflowConstant.BUTTON_REJECT_APPROVE_VAR_FLAG;
                execution.setVariable(agreeButtonVarName, 0);
                execution.setVariable(rejectButtonVarName, 0);

            }

            //多实例任务 结束事件
            if (execution.getEventName().equals(EVENTNAME_END)) {

                Object schemaIdObj = execution.getVariable(WorkflowConstant.PROCESS_SCHEMA_ID_KEY);

                Long schemaId = Convert.toLong(schemaIdObj);

                IWorkflowSchemaService workflowSchemaService = SpringUtil.getBean(IWorkflowSchemaService.class);
                WorkflowSchema workflowSchema = workflowSchemaService.getOne(Wrappers.lambdaQuery(WorkflowSchema.class).eq(WorkflowSchema::getId, schemaId));

                WorkflowSchemaConfig workflowSchemaConfig = JSONUtil.toBean(workflowSchema.getJsonContent(), WorkflowSchemaConfig.class);

                Optional<Map<String, Object>> userTaskConfigOp = workflowSchemaConfig.getChildNodeConfig().stream().filter(c -> c.containsValue(StrUtil.replace(((ExecutionEntity) execution).getActivityId(), WorkflowConstant.MULTI_INSTANCE_STRING, StringPool.EMPTY))).findFirst();

                if (!userTaskConfigOp.isPresent()) {
                    return;
                }
                if (userTaskConfigOp.get().containsKey(WorkflowConstant.BPMN_EVENT_SOURCE_TYPE_KEY)) {
                    String type = StrUtil.toString(userTaskConfigOp.get().get(WorkflowConstant.BPMN_EVENT_SOURCE_TYPE_KEY));

                    if (StrUtil.equals(type, WorkflowConstant.BPMN_XML_USER_TASK_TYPE_NAME)) {
                        //将map 转为 java类
                        UserTaskConfig userTaskConfig = Convert.convert(UserTaskConfig.class, userTaskConfigOp.get());

                        //TODO 多实例 传阅人设置
                        List<String> variableNames = ListUtil.toList(
                                WorkflowConstant.PROCESS_SCHEMA_ID_KEY,
                                WorkflowConstant.PROCESS_SCHEMA_NAME_KEY,
                                WorkflowConstant.PROCESS_START_USER_ID_KEY,
                                WorkflowConstant.PROCESS_START_USER_NAME_KEY,
                                WorkflowConstant.PROCESS_SERIAL_NUMBER_KEY);
                        //获取到用户节点的传阅人
                        List<Long> nextUserTaskCirculated = WorkFlowUtil.getUserIdsByMemberConfig(userTaskConfig.getCirculateConfigs(), workflowSchemaConfig.getChildNodeConfig(), execution.getProcessInstanceId());

                        RuntimeService runtimeService = execution.getProcessEngine().getRuntimeService();
                        Map<String, Object> variableMaps = runtimeService.getVariables(execution.getProcessInstanceId(), variableNames);

                        HistoryService historyService = execution.getProcessEngine().getHistoryService();
                        HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().processInstanceId(execution.getProcessInstanceId()).list().get(0);

                        List<WorkflowCirculated> circulatedList = new ArrayList<>();
                        for (Long userId : nextUserTaskCirculated) {
                            WorkflowCirculated workflowCirculated = new WorkflowCirculated();
                            workflowCirculated.setProcessId(execution.getProcessInstanceId());
                            workflowCirculated.setCreateTime(LocalDateTime.now());
                            workflowCirculated.setTaskId(historicTaskInstance.getId());
                            workflowCirculated.setCurrentProgress(userTaskConfig.getCurrentProgress());
                            workflowCirculated.setTaskName(historicTaskInstance.getName());
                            workflowCirculated.setIsRead(YesOrNoEnum.NO.getCode());
                            workflowCirculated.setSchemaId(MapUtil.getLong(variableMaps, WorkflowConstant.PROCESS_SCHEMA_ID_KEY));
                            workflowCirculated.setCirculatedUserId(userId);
                            workflowCirculated.setProcessName(MapUtil.getStr(variableMaps, WorkflowConstant.PROCESS_NAME));
                            workflowCirculated.setStartUserId(MapUtil.getLong(variableMaps, WorkflowConstant.PROCESS_START_USER_ID_KEY));
                            workflowCirculated.setSerialNumber(MapUtil.getLong(variableMaps, WorkflowConstant.PROCESS_SERIAL_NUMBER_KEY));
                            circulatedList.add(workflowCirculated);

                        }

                        NoticePolicyParam param = new NoticePolicyParam();
                        param.setNoticeUserIds(nextUserTaskCirculated);
                        param.setTaskId(historicTaskInstance.getId());
                        param.setTaskName(historicTaskInstance.getName());
                        param.setProcessId(execution.getProcessInstanceId());
                        param.setTaskName(historicTaskInstance.getName());
                        param.setSchemaId(MapUtil.get(variableMaps, WorkflowConstant.PROCESS_SCHEMA_ID_KEY, Long.class));
                        param.setSchemaName(MapUtil.get(variableMaps, WorkflowConstant.PROCESS_SCHEMA_NAME_KEY, String.class));
                        param.setStartUserName(MapUtil.get(variableMaps, WorkflowConstant.PROCESS_START_USER_NAME_KEY, String.class));
                        param.setNoticePolicyConfigs(userTaskConfig.getNoticePolicyConfigs());
                        WorkFlowUtil.sendCirculatedNoticePolicy(param, historicTaskInstance.getName());

                        circulatedService.saveBatch(circulatedList);
                    }
                }


            }
        }
        //判断是否为开始节点
        if (StrUtil.equals(Convert.toStr(eventSource.getProperty(WorkflowConstant.BPMN_EVENT_SOURCE_TYPE_KEY)), WorkflowConstant.BPMN_START_EVENT_TYPE_NAME)) {

            //开始节点 开始事件
            if (execution.getEventName().equals(EVENTNAME_START)) {
                //找到父级
                ExecutionEntity superExecution = ((ExecutionEntity) execution).getSuperExecution();
                //判断是否有父级  如果有父级 就是子流程  或者外部流程
                if (superExecution != null) {
                    log.info("[执行监听器] 节点：外部流程--开始节点 {} 事件: {}", execution.getId(), execution.getEventName());
                    //子流程开始节点 开始事件
                    subProcessStartNodeStartEvent(execution, superExecution);
                } else {
                    log.info("[执行监听器] 节点：普通流程--开始节点 {} 事件: {}", execution.getId(), execution.getEventName());
                    //普通流程开始节点 开始事件
                    processStartNodeStartEvent(execution);
                }

            }

            //开始节点  结束事件
            if (execution.getEventName().equals(EVENTNAME_END)) {
//                //模板id
//                Object schemaIdObj = execution.getVariable(WorkflowConstant.PROCESS_SCHEMA_ID_KEY);
//
//                Long schemaId = Convert.toLong(schemaIdObj);
//
//                IWorkflowSchemaService workflowSchemaService = SpringUtil.getBean(IWorkflowSchemaService.class);
//                WorkflowSchema workflowSchema = workflowSchemaService.getOne(Wrappers.lambdaQuery(WorkflowSchema.class).eq(WorkflowSchema::getId, schemaId));
//
////
////                WorkflowSchema workflowSchema = redisUtil.get(WorkflowConstant.SCHEMA_CACHE_PREFIX + Convert.toStr(schemaId), WorkflowSchema.class);
//
//                WorkflowSchemaConfig workflowSchemaConfig = JSONUtil.toBean(workflowSchema.getJsonContent(), WorkflowSchemaConfig.class);
//
//                Optional<Map<String, Object>> startNodeConfigOp = workflowSchemaConfig.getChildNodeConfig().stream().filter(c -> c.containsValue(((ExecutionEntity) execution).getActivityId())).findFirst();
//
//                if (!startNodeConfigOp.isPresent()) {
//                    return;
//                }
//
//                //将map 转为 java类
//                StartEventConfig startEventConfig = Convert.convert(StartEventConfig.class, startNodeConfigOp.get());
//
//                RuntimeService runtimeService = execution.getProcessEngine().getRuntimeService();
//
//                Object variable = runtimeService.getVariable(execution.getProcessInstanceId(), WorkflowConstant.PROCESS_PARAM_KEY);
//
//                Map<String, Object> processParam = Convert.toMap(String.class, Object.class, variable);
//
//                //执行参数赋值逻辑
//                WorkFlowUtil.invokeParamAssignment(startEventConfig.getAssignmentConfig(), processParam, workflowSchema);
            }
        }

        //判断是否为用户任务
        if (StrUtil.equals(Convert.toStr(eventSource.getProperty(WorkflowConstant.BPMN_EVENT_SOURCE_TYPE_KEY)), WorkflowConstant.BPMN_USER_TASK_TYPE_NAME)) {

            //用户任务task
            if (execution.getEventName().equals(EVENTNAME_START)) {
                log.info("[执行监听器] 节点：用户任务 -- {} 事件: {}", execution.getId(), execution.getEventName());

                Object assignee = execution.getVariable(WorkflowConstant.TASK_ASSIGNEE_VAR_KEY);

                redisUtil.set(WorkflowConstant.MULTI_ASSIGNEE_CACHE_PREFIX + execution.getId(), Convert.toLong(assignee), 5);
            }

            //用户任务  结束事件
            if (execution.getEventName().equals(EVENTNAME_END)) {
                //模板id
                Object schemaIdObj = execution.getVariable(WorkflowConstant.PROCESS_SCHEMA_ID_KEY);

                Long schemaId = Convert.toLong(schemaIdObj);

                IWorkflowSchemaService workflowSchemaService = SpringUtil.getBean(IWorkflowSchemaService.class);
                WorkflowSchema workflowSchema = workflowSchemaService.getOne(Wrappers.lambdaQuery(WorkflowSchema.class).eq(WorkflowSchema::getId, schemaId));

                WorkflowSchemaConfig workflowSchemaConfig = JSONUtil.toBean(workflowSchema.getJsonContent(), WorkflowSchemaConfig.class);

                Optional<Map<String, Object>> userTaskConfigOp = workflowSchemaConfig.getChildNodeConfig().stream().filter(c -> c.containsValue(((ExecutionEntity) execution).getActivityId())).findFirst();

                if (!userTaskConfigOp.isPresent()) {
                    return;
                }

                //将map 转为 java类
                UserTaskConfig userTaskConfig = Convert.convert(UserTaskConfig.class, userTaskConfigOp.get());

                if (userTaskConfig.getAssignmentConfig().getParamAssignmentConfigs().size() > 0) {
                    List<String> formKeys = userTaskConfig.getFormConfigs().stream().map(FormConfig::getKey).collect(Collectors.toList());
                    AssignmentConfig assignmentConfig = userTaskConfig.getAssignmentConfig();
                    paramAssignment(execution, formKeys, assignmentConfig, workflowSchema);
                }

            }

        }

        //判断是否为互斥网关
        if (StrUtil.equals(Convert.toStr(eventSource.getProperty(WorkflowConstant.BPMN_EVENT_SOURCE_TYPE_KEY)), WorkflowConstant.BPMN_EXCLUSIVE_GATEWAY_TYPE_NAME)) {
            if (execution.getEventName().equals(EVENTNAME_START)) {
                List<String> variableNames = ListUtil.toList(
                        WorkflowConstant.PROCESS_SCHEMA_ID_KEY,
                        WorkflowConstant.PROCESS_SCHEMA_NAME_KEY,
                        WorkflowConstant.PROCESS_START_USER_ID_KEY,
                        WorkflowConstant.PROCESS_START_USER_NAME_KEY,
                        WorkflowConstant.PROCESS_SERIAL_NUMBER_KEY,
                        WorkflowConstant.PROCESS_NAME);

                RuntimeService runtimeService = execution.getProcessEngine().getRuntimeService();

                Map<String, Object> variableMaps = runtimeService.getVariables(execution.getProcessInstanceId(), variableNames);

                WorkflowExtra extra = new WorkflowExtra();
                extra.setProcessId(execution.getProcessInstanceId());
                extra.setStartUserId(MapUtil.getLong(variableMaps, WorkflowConstant.PROCESS_START_USER_ID_KEY));
                extra.setStartUserName(MapUtil.getStr(variableMaps, WorkflowConstant.PROCESS_START_USER_NAME_KEY));
                extra.setSchemaId(MapUtil.getLong(variableMaps, WorkflowConstant.PROCESS_SCHEMA_ID_KEY));
                extra.setSchemaName(MapUtil.getStr(variableMaps, WorkflowConstant.PROCESS_SCHEMA_NAME_KEY));
                extra.setSerialNumber(MapUtil.getLong(variableMaps, WorkflowConstant.PROCESS_SERIAL_NUMBER_KEY));
                extra.setStartTime(LocalDateTime.now());
                extra.setLaunchTime(LocalDateTime.now());
                extra.setProcessName(MapUtil.getStr(variableMaps, WorkflowConstant.PROCESS_NAME));

                if (StrUtil.isNotBlank(eventSource.getName())){
                    extra.setTaskName("排他网关");
                }
                workflowExtraService.save(extra);
            }
        }

        //判断是否为流程线 如果 element  的id  前缀为 flow  就是流程线
        if (eventSource.getId().contains(WorkflowConstant.FLOW_ID_PREFIX_STRING)) {
            log.info("[执行监听器] 节点：流程线 -- {} 事件: {}", execution.getId(), execution.getEventName());

            //获取到流程线下一步的节点（多个）
            List<PvmTransition> outgoingTransitions = ((TransitionImpl) eventSource).getSource().getOutgoingTransitions();

            for (PvmTransition outgoingTransition : outgoingTransitions) {
                //判断当前流程线下一步节点是否为多实例  id 包含 #multiInstanceBody  都为多实例
                if (outgoingTransition.getDestination().getId().contains(WorkflowConstant.MULTI_INSTANCE_STRING)) {
                    //多实例需要提前设置用户
                    multiInstanceInitCollection(execution, outgoingTransition.getDestination().getId().replace(WorkflowConstant.MULTI_INSTANCE_STRING, StringPool.EMPTY));

                }
            }
        }


        //判断是否为脚本任务
        if (StrUtil.equals(Convert.toStr(eventSource.getProperty(WorkflowConstant.BPMN_EVENT_SOURCE_TYPE_KEY)), WorkflowConstant.BPMN_SCRIPT_TASK_TYPE_NAME)) {

            if (execution.getEventName().equals(EVENTNAME_START)) {


                List<String> variableNames = ListUtil.toList(
                        WorkflowConstant.PROCESS_SCHEMA_ID_KEY,
                        WorkflowConstant.PROCESS_SCHEMA_NAME_KEY,
                        WorkflowConstant.PROCESS_START_USER_ID_KEY,
                        WorkflowConstant.PROCESS_START_USER_NAME_KEY,
                        WorkflowConstant.PROCESS_SERIAL_NUMBER_KEY,
                        WorkflowConstant.PROCESS_NAME);

                RuntimeService runtimeService = execution.getProcessEngine().getRuntimeService();

                Map<String, Object> variableMaps = runtimeService.getVariables(execution.getProcessInstanceId(), variableNames);

                WorkflowExtra extra = new WorkflowExtra();
                extra.setProcessId(execution.getProcessInstanceId());
                extra.setStartUserId(MapUtil.getLong(variableMaps, WorkflowConstant.PROCESS_START_USER_ID_KEY));
                extra.setStartUserName(MapUtil.getStr(variableMaps, WorkflowConstant.PROCESS_START_USER_NAME_KEY));
                extra.setSchemaId(MapUtil.getLong(variableMaps, WorkflowConstant.PROCESS_SCHEMA_ID_KEY));
                extra.setSchemaName(MapUtil.getStr(variableMaps, WorkflowConstant.PROCESS_SCHEMA_NAME_KEY));
                extra.setSerialNumber(MapUtil.getLong(variableMaps, WorkflowConstant.PROCESS_SERIAL_NUMBER_KEY));
                extra.setStartTime(LocalDateTime.now());
                extra.setLaunchTime(LocalDateTime.now());
                extra.setProcessName(MapUtil.getStr(variableMaps, WorkflowConstant.PROCESS_NAME));

                if (StrUtil.isNotBlank(eventSource.getName())){
                    extra.setTaskName(WorkflowConstant.SCRIPT_TASK_TYPE_NAME);//写死任务名称为脚本任务
                }
                workflowExtraService.save(extra);
            }

            if (execution.getEventName().equals(EVENTNAME_END)) {

                //模板id
                Object schemaIdObj = execution.getVariable(WorkflowConstant.PROCESS_SCHEMA_ID_KEY);

                Long schemaId = Convert.toLong(schemaIdObj);

                IWorkflowSchemaService workflowSchemaService = SpringUtil.getBean(IWorkflowSchemaService.class);
                WorkflowSchema workflowSchema = workflowSchemaService.getOne(Wrappers.lambdaQuery(WorkflowSchema.class).eq(WorkflowSchema::getId, schemaId));

//
//                WorkflowSchema workflowSchema = redisUtil.get(WorkflowConstant.SCHEMA_CACHE_PREFIX + Convert.toStr(schemaId), WorkflowSchema.class);

                WorkflowSchemaConfig workflowSchemaConfig = JSONUtil.toBean(workflowSchema.getJsonContent(), WorkflowSchemaConfig.class);

                Optional<Map<String, Object>> scriptTaskConfigOp = workflowSchemaConfig.getChildNodeConfig().stream().filter(c -> c.containsValue(((ExecutionEntity) execution).getActivityId())).findFirst();

                if (!scriptTaskConfigOp.isPresent()) {
                    return;
                }

                System.out.println("scriptTaskConfigOp内容为" + scriptTaskConfigOp.get());

                //将map 转为 java类
                ScriptTaskConfig scriptTaskConfig = Convert.convert(ScriptTaskConfig.class, scriptTaskConfigOp.get());

                RuntimeService runtimeService = execution.getProcessEngine().getRuntimeService();

                Object processParamObj = runtimeService.getVariable(execution.getProcessInstanceId(), WorkflowConstant.PROCESS_PARAM_KEY);

                Object varObj = runtimeService.getVariables(execution.getProcessInstanceId());
                Map<String, Object> varMap = Convert.toMap(String.class, Object.class, varObj);
                Map<String, Object> processParam = Convert.toMap(String.class, Object.class, processParamObj);

                //TODO 此处编写脚本任务执行API 的代码
                IMagicApiService magicApiService = SpringUtil.getBean(IMagicApiService.class);
                MagicAPIService magicAPIService = SpringUtil.getBean(MagicAPIService.class);
                //如果开启了api开关
                if (scriptTaskConfig.getApi().getEnabled()) {
                    ApiConfig apiConfig = scriptTaskConfig.getApi().getApiConfig();
                    MagicApiInfoVo info = magicApiService.info(apiConfig.getId());
                    Map<String, Object> params = new HashMap<>();
                    Long serialNumber = MapUtil.get(varMap, WorkflowConstant.PROCESS_SERIAL_NUMBER_KEY, Long.class);
                    for (ApiRequestParamsConfig requestParamsConfig : apiConfig.getRequestParamsConfigs()) {
                        WorkFlowUtil.initApiParams(processParam, varMap, params, requestParamsConfig);
                    }
                    for (ApiRequestParamsConfig requestHeaderConfig : apiConfig.getRequestHeaderConfigs()) {
                        WorkFlowUtil.initApiParams(processParam, varMap, params, requestHeaderConfig);
                    }
                    for (ApiRequestParamsConfig requestBodyConfig : apiConfig.getRequestBodyConfigs()) {
                        WorkFlowUtil.initApiParams(processParam, varMap, params, requestBodyConfig);
                    }
                    Object result = magicAPIService.execute(info.getMethod(), info.getPath(), params);
                    log.info("【" + eventSource.getName() + "】执行【" + info.getName() + "】");
                }


                //判断是否需要记录流程信息
                if (scriptTaskConfig.getRecordInfo() == YesOrNoEnum.YES.getCode()) {
                    //新增流程发起流程记录
                    List<WorkflowRecord> recordList = new ArrayList<>();
                    //如果开启执行脚本，就记录流程信息,脚本参数配置
                    if (scriptTaskConfig.getScript().getEnabled()) {
                        WorkflowRecord scriptStart = new WorkflowRecord();
                        scriptStart.setNodeId(eventSource.getId());
                        scriptStart.setNodeName(eventSource.getName());
                        scriptStart.setNodeType(WorkflowConstant.SCRIPT_TASK_TYPE_NAME);
                        scriptStart.setProcessId(execution.getProcessInstanceId());
                        scriptStart.setSchemaId(schemaId);
                        scriptStart.setNodeMultiType(WorkflowMultiInstanceType.NONE.getCode());
                        scriptStart.setRecordTime(LocalDateTime.now());
                        scriptStart.setMessage("【" + eventSource.getName() + "】执行脚本,脚本内容为【" + scriptTaskConfig.getScript().getScriptContent() + "】");
                        recordList.add(scriptStart);
                    }

                    IWorkflowRecordService workflowRecordService = SpringUtil.getBean(IWorkflowRecordService.class);
                    //api配置
                    if (scriptTaskConfig.getApi().getEnabled()) {
                        ApiConfig apiConfig = scriptTaskConfig.getApi().getApiConfig();
                        MagicApiInfoVo info = magicApiService.info(apiConfig.getId());
                        //新增流程发起流程记录
                        WorkflowRecord scriptApiStart = new WorkflowRecord();
                        scriptApiStart.setNodeId(eventSource.getId());
                        scriptApiStart.setNodeName(eventSource.getName());
                        scriptApiStart.setNodeType(WorkflowConstant.SCRIPT_TASK_TYPE_NAME);
                        scriptApiStart.setProcessId(execution.getProcessInstanceId());
                        scriptApiStart.setSchemaId(schemaId);
                        scriptApiStart.setNodeMultiType(WorkflowMultiInstanceType.NONE.getCode());
                        scriptApiStart.setRecordTime(LocalDateTime.now());

                        scriptApiStart.setMessage("【" + eventSource.getName() + "】执行【" + info.getName() + "】");
                        recordList.add(scriptApiStart);
                    }

                    //参数配置api值来源
                    List<ParamAssignmentConfig> paramAssignmentConfigs = scriptTaskConfig.getAssignmentConfig().getParamAssignmentConfigs();
                    for (ParamAssignmentConfig paramAssignmentConfig : paramAssignmentConfigs) {
                        //如果是api
                        if (paramAssignmentConfig.getType() == ParamAssignmentType.API.getCode()) {
                            ApiConfig apiConfig = paramAssignmentConfig.getApiConfig();
                            MagicApiInfoVo info = magicApiService.info(apiConfig.getId());
                            //新增流程发起流程记录
                            WorkflowRecord scriptApiStart = new WorkflowRecord();
                            scriptApiStart.setNodeId(eventSource.getId());
                            scriptApiStart.setNodeName(eventSource.getName());
                            scriptApiStart.setNodeType(WorkflowConstant.SCRIPT_TASK_TYPE_NAME);
                            scriptApiStart.setProcessId(execution.getProcessInstanceId());
                            scriptApiStart.setSchemaId(schemaId);
                            scriptApiStart.setNodeMultiType(WorkflowMultiInstanceType.NONE.getCode());
                            scriptApiStart.setRecordTime(LocalDateTime.now());

                            scriptApiStart.setMessage("【" + eventSource.getName() + "】执行【" + info.getName() + "】");
                            recordList.add(scriptApiStart);
                        }
                    }

                    workflowRecordService.saveBatch(recordList);
                }

                WorkFlowUtil.invokeParamAssignment(scriptTaskConfig.getAssignmentConfig(), processParam, varMap, workflowSchema);

                runtimeService.setVariable(execution.getProcessInstanceId(), WorkflowConstant.PROCESS_PARAM_KEY, processParam);

            }
        }
//        log.info("[执行监听器] 事件: {}", execution.getEventName());

        //判断是否流程结束
        if (StrUtil.equals(Convert.toStr(eventSource.getProperty(WorkflowConstant.BPMN_EVENT_SOURCE_TYPE_KEY)), WorkflowConstant.BPMN_END_NODE_TYPE_NAME)) {

            if (execution.getEventName().equals(EVENTNAME_END)) {
                IWorkflowRecordService workflowRecordService = SpringUtil.getBean(IWorkflowRecordService.class);

                //模板id
                Object schemaIdObj = execution.getVariable(WorkflowConstant.PROCESS_SCHEMA_ID_KEY);

                Long schemaId = Convert.toLong(schemaIdObj);
                //新增流程发起流程记录
                WorkflowRecord record = new WorkflowRecord();
                record.setNodeId(eventSource.getId());
                record.setNodeName(WorkflowConstant.END_NODE_TYPE_NAME);
                record.setNodeType(WorkflowConstant.END_NODE_TYPE_NAME);
                record.setProcessId(execution.getProcessInstanceId());
                record.setSchemaId(schemaId);
                record.setNodeMultiType(WorkflowMultiInstanceType.NONE.getCode());
                record.setRecordTime(LocalDateTime.now().minusSeconds(-1));
                record.setMessage("流程结束");

                workflowRecordService.save(record);

                //新增流程结束流程记录
                XjrWorkflowOperateRecord operateRecord = new XjrWorkflowOperateRecord();
                operateRecord.setNodeId(eventSource.getId());
                operateRecord.setNodeName(WorkflowConstant.END_NODE_TYPE_NAME);
                operateRecord.setNodeType(WorkflowConstant.END_NODE_TYPE_NAME);
                operateRecord.setProcessId(execution.getProcessInstanceId());
                operateRecord.setSchemaId(schemaId);
                operateRecord.setNodeMultiType(WorkflowMultiInstanceType.NONE.getCode());
                operateRecord.setRecordTime(LocalDateTime.now().minusSeconds(-1));
                operateRecord.setUsageScenario(2);
                operateRecord.setOperateInfo("流程结束");

                xjrWorkflowOperateRecordService.save(operateRecord);

                //找到父级
                ExecutionEntity superExecution = ((ExecutionEntity) execution).getSuperExecution();

                //如果有父级  就代表是   外部流程 或者 子流程
                if (superExecution != null) {
                    RuntimeService runtimeService = execution.getProcessEngine().getRuntimeService();
                    //获取到父级流程的SchemaId 用schemaId 查询流程配置
                    Object superSchemaIdObj = runtimeService.getVariable(superExecution.getProcessInstanceId(), WorkflowConstant.PROCESS_SCHEMA_ID_KEY);

                    IWorkflowSchemaService workflowSchemaService = SpringUtil.getBean(IWorkflowSchemaService.class);
                    WorkflowSchema superWorkflowSchema = workflowSchemaService.getOne(Wrappers.lambdaQuery(WorkflowSchema.class).eq(WorkflowSchema::getId, superSchemaIdObj));

                    WorkflowSchemaConfig superWorkflowSchemaConfig = JSONUtil.toBean(superWorkflowSchema.getJsonContent(), WorkflowSchemaConfig.class);

                    Optional<Map<String, Object>> subProcessConfigConfigOp = superWorkflowSchemaConfig.getChildNodeConfig().stream().filter(c -> c.containsValue(superExecution.getActivityId())).findFirst();
                    if (!subProcessConfigConfigOp.isPresent()) {
                        return;
                    }

                    //判断 外部流程  还是 子流程
                    if (StrUtil.equals(Convert.toStr(subProcessConfigConfigOp.get().get(WorkflowConstant.BPMN_EVENT_SOURCE_TYPE_KEY)), WorkflowConstant.BPMN_XML_CALL_ACTIVITY_TYPE_NAME)) {
                        //    将map 转为 java类
                        CallActivityConfig callActivityConfig = Convert.convert(CallActivityConfig.class, subProcessConfigConfigOp.get());

                        //如果是单实例  需要执行 输出参数的逻辑
                        if (callActivityConfig.getCallActivityType() == WorkflowCallActivityType.SINGLE.getCode()) {

                            //获取到主流程的流程参数
                            Object superProcessParamObj = superExecution.getVariable(WorkflowConstant.PROCESS_PARAM_KEY);
                            Map<String, Object> superProcessParamMap = Convert.toMap(String.class, Object.class, superProcessParamObj);
                            //获取到外部的流程参数
                            Object childProcessParamObj = execution.getVariable(WorkflowConstant.PROCESS_PARAM_KEY);
                            Map<String, Object> childProcessParamMap = Convert.toMap(String.class, Object.class, childProcessParamObj);

                            for (CallActivityParamConfig outParam : callActivityConfig.getOutParams()) {

                                //如果包含三个下划线 就代表 选的是表单字段
                                if (outParam.getSource().contains(StringPool.UNDERSCORE + StringPool.UNDERSCORE + StringPool.UNDERSCORE)) {
                                    //获取到来源 的所有参数
                                    String[] sourceSplit = outParam.getSource().split(StringPool.UNDERSCORE + StringPool.UNDERSCORE + StringPool.UNDERSCORE);

                                    ParamSourceTargetModel sourceModel = new ParamSourceTargetModel();
                                    sourceModel.setNodeId(sourceSplit[0]);
                                    sourceModel.setFormKey(sourceSplit[1]);
                                    sourceModel.setChildField(sourceSplit[2]);

                                    //获取到当前配置的发起人  表单数据
                                    Object formDataObj = execution.getVariable(sourceModel.getFormKey());

                                    Map<String, Object> formData = Convert.toMap(String.class, Object.class, formDataObj);

                                    //获取到去向 的所有参数
                                    String[] tagetSplit = outParam.getTarget().split(StringPool.UNDERSCORE + StringPool.UNDERSCORE + StringPool.UNDERSCORE);

                                    //如果包含三个下划线 代表目标是 主流程的表单
                                    if (outParam.getTarget().contains(StringPool.UNDERSCORE + StringPool.UNDERSCORE + StringPool.UNDERSCORE)) {
                                        Object sourceFieldValue = MapUtil.get(formData, sourceModel.getChildField(), Object.class);
                                        //获取到主流程的表单
                                        Object superFormDataObj = superExecution.getVariable(tagetSplit[1]);
                                        Map<String, Object> superFormData = Convert.toMap(String.class, Object.class, superFormDataObj);
                                        if (ObjectUtil.isNull(superFormData)) {
                                            superFormData = new HashMap<>();
                                        }
                                        superFormData.put(tagetSplit[2], sourceFieldValue);

                                        superExecution.setVariable(tagetSplit[1], superFormData);
                                    }
                                    //如果不包含 就代表目标是 子流程的流程参数
                                    else {
                                        //将主流程数据 导入到 主流程  流程参数中
                                        Object sourceFieldValue = MapUtil.get(formData, sourceModel.getChildField(), Object.class);
                                        superProcessParamMap.put(outParam.getTarget(), sourceFieldValue);
                                    }


                                } else {
                                    Object out = MapUtil.get(childProcessParamMap, outParam.getSource(), Object.class);

                                    //如果包含三个下划线 代表目标是 子流程的表单
                                    if (outParam.getTarget().contains(StringPool.UNDERSCORE + StringPool.UNDERSCORE + StringPool.UNDERSCORE)) {

                                        //获取到去向 的所有参数
                                        String[] tagetSplit = outParam.getTarget().split(StringPool.UNDERSCORE + StringPool.UNDERSCORE + StringPool.UNDERSCORE);

                                        //获取到主流程的表单
                                        Object superFormDataObj = superExecution.getVariable(tagetSplit[1]);
                                        Map<String, Object> superFormData = Convert.toMap(String.class, Object.class, superFormDataObj);

                                        if (ObjectUtil.isNull(superFormData)) {
                                            superFormData = new HashMap<>();
                                        }
                                        superFormData.put(tagetSplit[2], out);

                                        superExecution.setVariable(tagetSplit[1], superFormData);
                                    }
                                    //如果不包含 就代表目标是 主流程的流程参数
                                    else {
                                        //将主流程数据 导入到 子流程  流程参数中
                                        superProcessParamMap.put(outParam.getTarget(), out);
                                    }
                                }
                            }
                            //TODO 这里代表外部流程结束  需要记录流程流转记录
                        } else {
                            //TODO 这里代表外部流程结束  需要记录流程流转记录
                        }


                    } else {
                        // 如果是内嵌子流程
                        //    将map 转为 java类
                        SubProcessConfig subProcessConfig = Convert.convert(SubProcessConfig.class, subProcessConfigConfigOp.get());

                    }
                }

            }

        }
        //判断是否外部流程
        if (StrUtil.equals(Convert.toStr(eventSource.getProperty(WorkflowConstant.BPMN_EVENT_SOURCE_TYPE_KEY)), WorkflowConstant.BPMN_CALL_ACTIVITY_TYPE_NAME)) {
            //外部流程开始节点
            if (execution.getEventName().equals(EVENTNAME_START)) {
                List<String> variableNames = ListUtil.toList(
                        WorkflowConstant.PROCESS_SCHEMA_ID_KEY,
                        WorkflowConstant.PROCESS_SCHEMA_NAME_KEY,
                        WorkflowConstant.PROCESS_START_USER_ID_KEY,
                        WorkflowConstant.PROCESS_START_USER_NAME_KEY,
                        WorkflowConstant.PROCESS_SERIAL_NUMBER_KEY,
                        WorkflowConstant.PROCESS_NAME);

                RuntimeService runtimeService = execution.getProcessEngine().getRuntimeService();

                Map<String, Object> variableMaps = runtimeService.getVariables(execution.getProcessInstanceId(), variableNames);

                WorkflowExtra extra = new WorkflowExtra();
                extra.setProcessId(execution.getProcessInstanceId());
                extra.setStartUserId(MapUtil.getLong(variableMaps, WorkflowConstant.PROCESS_START_USER_ID_KEY));
                extra.setStartUserName(MapUtil.getStr(variableMaps, WorkflowConstant.PROCESS_START_USER_NAME_KEY));
                extra.setSchemaId(MapUtil.getLong(variableMaps, WorkflowConstant.PROCESS_SCHEMA_ID_KEY));
                extra.setSchemaName(MapUtil.getStr(variableMaps, WorkflowConstant.PROCESS_SCHEMA_NAME_KEY));
                extra.setSerialNumber(MapUtil.getLong(variableMaps, WorkflowConstant.PROCESS_SERIAL_NUMBER_KEY));
                extra.setProcessName(MapUtil.getStr(variableMaps, WorkflowConstant.PROCESS_NAME));
                extra.setStartTime(LocalDateTime.now().minusSeconds(-1));
                extra.setLaunchTime(LocalDateTime.now());
                extra.setTaskKey(eventSource.getId());
                extra.setTaskName(eventSource.getName());

                if (StrUtil.isNotBlank(eventSource.getName())){
                    extra.setTaskName(WorkflowConstant.CALL_ACTIVITY_TYPE_NAME);//写死
                }

                workflowExtraService.save(extra);
            }
//            if (execution.getEventName().equals(EVENTNAME_END)) {
//                Object schemaIdObj = execution.getVariable(WorkflowConstant.PROCESS_SCHEMA_ID_KEY);
//
//                Long schemaId = Convert.toLong(schemaIdObj);
//
//                IWorkflowSchemaService workflowSchemaService = SpringUtil.getBean(IWorkflowSchemaService.class);
//                WorkflowSchema workflowSchema = workflowSchemaService.getOne(Wrappers.lambdaQuery(WorkflowSchema.class).eq(WorkflowSchema::getId, schemaId));
//
//                WorkflowSchemaConfig workflowSchemaConfig = JSONUtil.toBean(workflowSchema.getJsonContent(), WorkflowSchemaConfig.class);
//
//                Optional<Map<String, Object>> callActivityConfigOp = workflowSchemaConfig.getChildNodeConfig().stream().filter(c -> c.containsValue(((ExecutionEntity) execution).getActivityId())).findFirst();
//
//                if (!callActivityConfigOp.isPresent()) {
//                    return;
//                }
//                //    将map 转为 java类
//                CallActivityConfig callActivityConfig = Convert.convert(CallActivityConfig.class, callActivityConfigOp.get());
//
//
//                //如果是单实例  需要执行 输出参数的逻辑
//                if (callActivityConfig.getCallActivityType() == WorkflowCallActivityType.SINGLE.getCode()) {
//
//                    //找到父级
//                    ExecutionEntity superExecution = ((ExecutionEntity) execution).getParent();
//
//                    //获取到主流程的流程参数
//                    Object superProcessParamObj = superExecution.getVariable(WorkflowConstant.PROCESS_PARAM_KEY);
//                    Map<String, Object> superProcessParamMap = Convert.toMap(String.class, Object.class, superProcessParamObj);
//                    //获取到外部的流程参数
//                    Object childProcessParamObj = execution.getVariable(WorkflowConstant.PROCESS_PARAM_KEY);
//                    Map<String, Object> childProcessParamMap = Convert.toMap(String.class, Object.class, childProcessParamObj);
//
//                    for (CallActivityParamConfig outParam : callActivityConfig.getOutParams()) {
//
//                        //如果包含三个下划线 就代表 选的是表单字段
//                        if (outParam.getSource().contains(StringPool.UNDERSCORE + StringPool.UNDERSCORE + StringPool.UNDERSCORE)) {
//                            //获取到来源 的所有参数
//                            String[] sourceSplit = outParam.getSource().split(StringPool.UNDERSCORE + StringPool.UNDERSCORE + StringPool.UNDERSCORE);
//
//                            ParamSourceTargetModel sourceModel = new ParamSourceTargetModel();
//                            sourceModel.setNodeId(sourceSplit[0]);
//                            sourceModel.setFormKey(sourceSplit[1]);
////                    sourceModel.setFormChildField(sourceSplit[2]);
//                            sourceModel.setChildField(sourceSplit[2]);
//
//                            //获取到当前配置的发起人  表单数据
//                            Object formDataObj = execution.getVariable(sourceModel.getFormKey());
//
//                            Map<String, Object> formData = Convert.toMap(String.class, Object.class, formDataObj);
//
//                            //获取到去向 的所有参数
//                            String[] tagetSplit = outParam.getTarget().split(StringPool.UNDERSCORE + StringPool.UNDERSCORE + StringPool.UNDERSCORE);
//
//                            //如果包含三个下划线 代表目标是 主流程的表单
//                            if (outParam.getTarget().contains(StringPool.UNDERSCORE + StringPool.UNDERSCORE + StringPool.UNDERSCORE)) {
//                                Object sourceFieldValue = MapUtil.get(formData, sourceModel.getChildField(), Object.class);
//                                //获取到主流程的表单
//                                Object superFormDataObj = superExecution.getVariable(tagetSplit[1]);
//                                Map<String, Object> superFormData = Convert.toMap(String.class, Object.class, superFormDataObj);
//                                superFormData.put(tagetSplit[2], sourceFieldValue);
//
//                                superExecution.setVariable(sourceModel.getFormKey(), superFormData);
//                            }
//                            //如果不包含 就代表目标是 子流程的流程参数
//                            else {
//                                //将主流程数据 导入到 主流程  流程参数中
//                                Object sourceFieldValue = MapUtil.get(formData, sourceModel.getChildField(), Object.class);
//                                superProcessParamMap.put(outParam.getTarget(), sourceFieldValue);
//                            }
//
//
//                        } else {
//                            Object out = MapUtil.get(childProcessParamMap, outParam.getSource(), Object.class);
//
//                            //如果包含三个下划线 代表目标是 子流程的表单
//                            if (outParam.getTarget().contains(StringPool.UNDERSCORE + StringPool.UNDERSCORE + StringPool.UNDERSCORE)) {
//
//                                //获取到去向 的所有参数
//                                String[] tagetSplit = outParam.getTarget().split(StringPool.UNDERSCORE + StringPool.UNDERSCORE + StringPool.UNDERSCORE);
//
//                                //获取到主流程的表单
//                                Object superFormDataObj = superExecution.getVariable(tagetSplit[1]);
//                                Map<String, Object> superFormData = Convert.toMap(String.class, Object.class, superFormDataObj);
//                                superFormData.put(tagetSplit[2], out);
//
//                                superExecution.setVariable(tagetSplit[1], superFormData);
//                            }
//                            //如果不包含 就代表目标是 主流程的流程参数
//                            else {
//                                //将主流程数据 导入到 子流程  流程参数中
//                                superProcessParamMap.put(outParam.getTarget(), out);
//                            }
//                        }
//                    }
//                    //TODO 这里代表外部流程结束  需要记录流程流转记录
//                } else {
//                    //TODO 这里代表外部流程结束  需要记录流程流转记录
//                }
//
//            }
        }
    }

    /**
     * 执行事件
     * @param execution
     * @param nodeEventConfigs
     */
    private void executeEvent(DelegateExecution execution, List<NodeEventConfig> nodeEventConfigs) {
        IMagicApiService magicApiService = SpringUtil.getBean(IMagicApiService.class);
        MagicAPIService magicAPIService = SpringUtil.getBean(MagicAPIService.class);


        RuntimeService runtimeService = execution.getProcessEngine().getRuntimeService();

        Object processParamObj = runtimeService.getVariable(execution.getProcessInstanceId(), WorkflowConstant.PROCESS_PARAM_KEY);

        Object varObj = runtimeService.getVariables(execution.getProcessInstanceId());
        Map<String, Object> varMap = Convert.toMap(String.class, Object.class, varObj);
        Map<String, Object> processParam = Convert.toMap(String.class, Object.class, processParamObj);


        for (NodeEventConfig nodeEventConfig : nodeEventConfigs) {
            if (nodeEventConfig.getType() == WorkflowEventExType.API.getCode()) {
                ApiConfig apiConfig = nodeEventConfig.getApiConfig();
                MagicApiInfoVo info = magicApiService.info(apiConfig.getId());
                Map<String, Object> params = new HashMap<>();
                for (ApiRequestParamsConfig requestParamsConfig : apiConfig.getRequestParamsConfigs()) {
                    WorkFlowUtil.initApiParams(processParam, varMap, params, requestParamsConfig);
                }
                for (ApiRequestParamsConfig requestHeaderConfig : apiConfig.getRequestHeaderConfigs()) {
                    WorkFlowUtil.initApiParams(processParam, varMap, params, requestHeaderConfig);
                }
                for (ApiRequestParamsConfig requestBodyConfig : apiConfig.getRequestBodyConfigs()) {
                    WorkFlowUtil.initApiParams(processParam, varMap, params, requestBodyConfig);
                }
                magicAPIService.execute(info.getMethod(), info.getPath(), params);
            }
            //如果是规则引擎
            else {
                String liteflowId = nodeEventConfig.getLiteflowId();
                XjrLiteflowChain chain = liteflowChainService.getById(liteflowId);
                // 更新规则
                LiteFlowChainELBuilder.createChain().setChainName(chain.getChainName()).setEL(chain.getElData()).build();
                // 执行规则
                flowExecutor.execute2Resp(chain.getChainName(), null,varMap);
            }

        }
    }


    private void subProcessStartNodeStartEvent(DelegateExecution execution, ExecutionEntity superExecution) {
        RuntimeService runtimeService = execution.getProcessEngine().getRuntimeService();
        //获取到父级流程的SchemaId 用schemaId 查询流程配置
        Object superSchemaIdObj = runtimeService.getVariable(superExecution.getProcessInstanceId(), WorkflowConstant.PROCESS_SCHEMA_ID_KEY);

        IWorkflowSchemaService workflowSchemaService = SpringUtil.getBean(IWorkflowSchemaService.class);
        WorkflowSchema superWorkflowSchema = workflowSchemaService.getOne(Wrappers.lambdaQuery(WorkflowSchema.class).eq(WorkflowSchema::getId, superSchemaIdObj));

//        WorkflowSchema superWorkflowSchema = redisUtil.get(WorkflowConstant.SCHEMA_CACHE_PREFIX + Convert.toStr(superSchemaIdObj), WorkflowSchema.class);
        WorkflowSchemaConfig superWorkflowSchemaConfig = JSONUtil.toBean(superWorkflowSchema.getJsonContent(), WorkflowSchemaConfig.class);
        Optional<Map<String, Object>> subProcessConfigConfigOp = superWorkflowSchemaConfig.getChildNodeConfig().stream().filter(c -> c.containsValue(superExecution.getActivityId())).findFirst();
        if (!subProcessConfigConfigOp.isPresent()) {
            return;
        }

        //判断 外部流程  还是 子流程
        if (StrUtil.equals(Convert.toStr(subProcessConfigConfigOp.get().get(WorkflowConstant.BPMN_EVENT_SOURCE_TYPE_KEY)), WorkflowConstant.BPMN_XML_CALL_ACTIVITY_TYPE_NAME)) {
            //    将map 转为 java类
            CallActivityConfig callActivityConfig = Convert.convert(CallActivityConfig.class, subProcessConfigConfigOp.get());

            initActivityParam(execution, superExecution, runtimeService, callActivityConfig, superWorkflowSchema);

        } else {
            // 如果是内嵌子流程
            //    将map 转为 java类
            SubProcessConfig subProcessConfig = Convert.convert(SubProcessConfig.class, subProcessConfigConfigOp.get());

            //构建内嵌子流程参数 存入工作流变量表
            initSubProcessParam(execution, superExecution, runtimeService, superWorkflowSchema, subProcessConfig);
        }

    }

    /**
     * 外部流程 构建 默认参数
     *
     * @param execution
     * @param superExecution
     * @param runtimeService
     * @param callActivityConfig
     */
    private void initActivityParam(DelegateExecution execution, ExecutionEntity superExecution, RuntimeService runtimeService, CallActivityConfig callActivityConfig, WorkflowSchema superWorkflowSchema) {
        String schemaId = callActivityConfig.getSchemaId();

        IWorkflowSchemaService workflowSchemaService = SpringUtil.getBean(IWorkflowSchemaService.class);
        WorkflowSchema workflowSchema = workflowSchemaService.getOne(Wrappers.lambdaQuery(WorkflowSchema.class).eq(WorkflowSchema::getId, Long.valueOf(schemaId)));
        //获取到外部流程的schema
//        WorkflowSchema workflowSchema = redisUtil.get(WorkflowConstant.SCHEMA_CACHE_PREFIX + schemaId, WorkflowSchema.class);

        if (workflowSchema == null) {
            workflowSchema = workflowSchemaService.getById(schemaId);
        }

        WorkflowSchemaConfig workflowSchemaConfig = JSONUtil.toBean(workflowSchema.getJsonContent(), WorkflowSchemaConfig.class);

        //获取外部流程的参数配置
        List<ProcessParamConfig> processParamConfigs = workflowSchemaConfig.getProcessConfig().getProcessParamConfigs();

        HistoryService historyService = execution.getProcessEngine().getHistoryService();

        long count = historyService.createHistoricProcessInstanceQuery().count();

        //获取到主流程的参数
        Object superProcessParamObj = superExecution.getVariable(WorkflowConstant.PROCESS_PARAM_KEY);

        User user = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_INFO_KEY, new User());

        Map<String, Object> superProcessParamMap = Convert.toMap(String.class, Object.class, superProcessParamObj);

        //获取到外部流程  所配置的 默认表单
        List<FormConfig> defaultFormList = workflowSchemaConfig.getProcessConfig().getDefaultFormList();

        //默认选择第一个作为 主表单配置
        FormConfig formConfig = defaultFormList.get(0);
        //外部流程开始节点记录
        Optional<Map<String, Object>> startNodeMap = workflowSchemaConfig.getChildNodeConfig().stream().filter(x -> x.containsValue(WorkflowConstant.BPMN_XML_START_EVENT_TYPE_NAME)).findFirst();
        if (!startNodeMap.isPresent()) {
            throw new MyException("当前任务没有开始节点");
        }
        //将map 转为 java类
        StartNodeConfig startNodeConfig = Convert.convert(StartNodeConfig.class, startNodeMap.get());
        String userName = StringPool.EMPTY;
        //如果是单实例
        if (callActivityConfig.getCallActivityType() == WorkflowCallActivityType.SINGLE.getCode()) {
            Object varObj = runtimeService.getVariables(execution.getProcessInstanceId());
            Map<String, Object> varMap = Convert.toMap(String.class, Object.class, varObj);
            //获取外部流程 schema 所配置的 流程参数 因为当前子流程还没创建历史记录数据 所以需要+2
            Map<String, Object> processParam = WorkFlowUtil.getProcessParam(processParamConfigs, workflowSchema, count + 2,varMap);

            Map<String, Object> childFormDataMap = new HashMap<>();
            for (CallActivityParamConfig inParam : callActivityConfig.getInParams()) {

                //如果包含三个下划线 就代表 选的是表单字段
                if (inParam.getSource().contains(StringPool.UNDERSCORE + StringPool.UNDERSCORE + StringPool.UNDERSCORE)) {
                    //获取到来源 的所有参数
                    String[] sourceSplit = inParam.getSource().split(StringPool.UNDERSCORE + StringPool.UNDERSCORE + StringPool.UNDERSCORE);

                    ParamSourceTargetModel sourceModel = new ParamSourceTargetModel();
                    sourceModel.setNodeId(sourceSplit[0]);
                    sourceModel.setFormKey(sourceSplit[1]);
//                    sourceModel.setFormChildField(sourceSplit[2]);
                    sourceModel.setChildField(sourceSplit[2]);

                    //获取到当前配置的发起人  表单数据
                    Object formDataObj = superExecution.getVariable(sourceModel.getFormKey());

                    Map<String, Object> map = Convert.toMap(String.class, Object.class, formDataObj);

                    //获取到去向 的所有参数
                    String[] tagetSplit = inParam.getTarget().split(StringPool.UNDERSCORE + StringPool.UNDERSCORE + StringPool.UNDERSCORE);


                    //如果包含三个下划线 代表目标是 子流程的表单
                    if (inParam.getTarget().contains(StringPool.UNDERSCORE + StringPool.UNDERSCORE + StringPool.UNDERSCORE)) {
                        Object sourceFieldValue = MapUtil.get(map, sourceModel.getChildField(), Object.class);
                        childFormDataMap.put(tagetSplit[2], sourceFieldValue);
                    }
                    //如果不包含 就代表目标是 子流程的流程参数
                    else {
                        //将主流程数据 导入到 子流程  流程参数中
                        Object sourceFieldValue = MapUtil.get(map, sourceModel.getChildField(), Object.class);
                        processParam.put(inParam.getTarget(), sourceFieldValue);
                    }


                } else {
                    Object in = MapUtil.get(superProcessParamMap, inParam.getSource(), Object.class);

                    //如果包含三个下划线 代表目标是 子流程的表单
                    if (inParam.getTarget().contains(StringPool.UNDERSCORE + StringPool.UNDERSCORE + StringPool.UNDERSCORE)) {

                        //获取到去向 的所有参数
                        String[] tagetSplit = inParam.getTarget().split(StringPool.UNDERSCORE + StringPool.UNDERSCORE + StringPool.UNDERSCORE);

                        childFormDataMap.put(tagetSplit[2], in);
                    }
                    //如果不包含 就代表目标是 子流程的流程参数
                    else {
                        //将主流程数据 导入到 子流程  流程参数中

                        processParam.put(inParam.getTarget(), in);
                    }
                }
            }


            //设定全局变量 发起人id、发起人名、模板id 、模板名、页面配置参数值、流水号 因为当前子流程还没创建历史记录数据 所以需要+2

            VariableMap variableMap = Variables.createVariables()
                    .putValue(WorkflowConstant.PROCESS_SCHEMA_ID_KEY, workflowSchema.getId())
                    .putValue(WorkflowConstant.PROCESS_SCHEMA_NAME_KEY, workflowSchema.getName())
                    .putValue(WorkflowConstant.PROCESS_PARAM_KEY, processParam)
                    .putValue(WorkflowConstant.PROCESS_ISRECYCLE_FLAG_KEY, WorkflowIsRecycleType.NO.getCode())
                    .putValue(formConfig.getKey(), childFormDataMap)
                    .putValue(WorkflowConstant.PROCESS_SERIAL_NUMBER_KEY, count + 2);

            //根据规则生成流程名称
            String processName = WorkFlowUtil.generatorProcessName(workflowSchema, workflowSchemaConfig, count + 2, null);
            //根据规则生成流程名称
            variableMap.putValue(WorkflowConstant.PROCESS_NAME, processName);


            String originatorNode = callActivityConfig.getOriginatorNode();
            //如果节点id 是开始节点id  使用主流程的发起人
            if (originatorNode.equals(WorkflowConstant.START_NODE_DEFAULT_ID)) {
                Object startUserIdObj = superExecution.getVariable(WorkflowConstant.PROCESS_START_USER_ID_KEY);
                Object startUserNameObj = superExecution.getVariable(WorkflowConstant.PROCESS_START_USER_NAME_KEY);
                Object startUserPostIdObj = superExecution.getVariable(WorkflowConstant.PROCESS_START_USER_POST_ID_KEY);
                variableMap.putValue(WorkflowConstant.PROCESS_START_USER_ID_KEY, startUserIdObj);
                variableMap.putValue(WorkflowConstant.PROCESS_START_USER_NAME_KEY, startUserNameObj);
                variableMap.putValue(WorkflowConstant.PROCESS_START_USER_POST_ID_KEY, startUserPostIdObj);

                userName = startUserNameObj.toString();
            }
            //如果不是 那就是所选的节点审批人
            else {
                List<WorkflowApproveRecord> list = workflowApproveRecordService.list(Wrappers.lambdaQuery(WorkflowApproveRecord.class)
                        .eq(WorkflowApproveRecord::getProcessId, execution.getProcessInstanceId())
                        .eq(WorkflowApproveRecord::getTaskDefinitionKey, originatorNode)
                );

                if (list.size() > 0) {
                    WorkflowApproveRecord approveRecord = list.get(0);
                    List<User> allUser = redisUtil.get(GlobalConstant.USER_CACHE_KEY, new TypeReference<List<User>>() {
                    });
                    User startUser = allUser.stream().filter(x -> x.getId().equals(approveRecord.getApproveUserId())).findFirst().orElse(new User());

                    variableMap.putValue(WorkflowConstant.PROCESS_START_USER_ID_KEY, startUser.getId());
                    variableMap.putValue(WorkflowConstant.PROCESS_START_USER_NAME_KEY, startUser.getName());
                    variableMap.putValue(WorkflowConstant.PROCESS_START_USER_POST_ID_KEY, startUser.getPostId());

                    userName = startUser.getName();
                }
            }

            //将主表的 子表数据 当作 外部流程的  主表数据 存到变量中
            runtimeService.setVariables(execution.getProcessInstanceId(), variableMap);
            //记录父节点外部流程流程数据
            callActivityNodeRecord(superWorkflowSchema, callActivityConfig, superExecution.getProcessInstanceId(), "【" + userName + "】 创建流程");
            //记录子流程开始节点创建流程数据
            startNodeRecord(workflowSchema, startNodeConfig, execution.getProcessInstanceId(), "【" + userName + "】 创建流程");
        } else {

            //设定全局变量 发起人id、发起人名、模板id 、模板名、页面配置参数值、流水号 因为当前子流程还没创建历史记录数据 所以需要+2
            VariableMap variableMap = Variables.createVariables()
                    .putValue(WorkflowConstant.PROCESS_SCHEMA_ID_KEY, workflowSchema.getId())
                    .putValue(WorkflowConstant.PROCESS_SCHEMA_NAME_KEY, workflowSchema.getName())
                    .putValue(WorkflowConstant.PROCESS_ISRECYCLE_FLAG_KEY, WorkflowIsRecycleType.NO.getCode());

            //根据规则生成流程名称
            String processName = WorkFlowUtil.generatorProcessName(workflowSchema, workflowSchemaConfig, count + 2, null);
            //根据规则生成流程名称
            variableMap.putValue(WorkflowConstant.PROCESS_NAME, processName);

            String originatorConfig = callActivityConfig.getOriginatorConfig();
            String[] split = originatorConfig.split(StringPool.UNDERSCORE + StringPool.UNDERSCORE + StringPool.UNDERSCORE);
            ParamSourceTargetModel model = new ParamSourceTargetModel();
            model.setNodeId(split[0]);
            model.setFormKey(split[1]);
            model.setFormChildField(split[2]);
            model.setChildField(split[3]);

            //获取到当前配置的发起人  表单数据
            Object formDataObj = superExecution.getVariable(model.getFormKey());
            Map<String, Object> formData = Convert.toMap(String.class, Object.class, formDataObj);
            //获取到子表数据
            Object childTableDataObj = formData.get(model.getFormChildField());
            List<Map> childDataMapList = Convert.toList(Map.class, childTableDataObj);


            String indexString = redisUtil.get(WorkflowConstant.CALLACTIVITY_CACHE_PREFIX + superExecution.getProcessInstanceId() + originatorConfig);
            int index = Convert.toInt(indexString);
            //如果主流程开始节点的下一个节点 不是外部流程
            //如果主流程开始节点的下一个节点 是外部流程
            //先判断主流程是否已经插入到数据库
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(superExecution.getProcessInstanceId()).singleResult();

            //如果没有插入  就代表 主流程的开始节点的下一个节点 是外部流程 流水号需要 加上子流程的个数
            if (ObjectUtil.isNull(historicProcessInstance)) {
                //如果是第一个用户任务  第一个子流程的用户任务 流水号 需要+2  因为主流程会根据子流程一起生成  现在的count 是不包含主流程的

                if (index == 0) {
                    count = count + 2;
                } else {
                    //如果是并行  所有的都需要+2
                    if (callActivityConfig.getExecutionType() == YesOrNoEnum.YES.getCode()) {
                        count = count + index + 2;
                    } else {
                        count = count + 1;
                    }
                }
            }
            //如果已经插入了  就代表 主流程的开始节点的下一个节点 不是外部流程  只需要+1就行
            else {
                //如果是并行  所有的都需要加上子流程的个数
                if (callActivityConfig.getExecutionType() == YesOrNoEnum.YES.getCode()) {
                    count = count + index + 1;
                } else {
                    count = count + 1;
                }
            }


            variableMap.putValue(WorkflowConstant.PROCESS_SERIAL_NUMBER_KEY, count);

            //获取外部流程 schema 所配置的 流程参数 因为当前子流程还没创建历史记录数据 所以需要+2
            Object varObj = runtimeService.getVariables(execution.getProcessInstanceId());
            Map<String, Object> varMap = Convert.toMap(String.class, Object.class, varObj);
            Map<String, Object> processParam = WorkFlowUtil.getProcessParam(processParamConfigs, workflowSchema, count,varMap);

            //将父流程的参数  传递  子流程参数中
            for (CallActivityParamConfig inParam : callActivityConfig.getInParams()) {
                Object in = MapUtil.get(superProcessParamMap, inParam.getSource(), Object.class);
                processParam.put(inParam.getTarget(), in);
            }
            variableMap.putValue(WorkflowConstant.PROCESS_PARAM_KEY, processParam);

            Map map = childDataMapList.get(index);

            //获取到当前节点的发起人配置
            String[] startUserSplit = callActivityConfig.getOriginatorConfig().split(StringPool.UNDERSCORE + StringPool.UNDERSCORE + StringPool.UNDERSCORE);

            ParamSourceTargetModel startUserConfig = new ParamSourceTargetModel();
            startUserConfig.setNodeId(startUserSplit[0]);
            startUserConfig.setFormKey(startUserSplit[1]);
            startUserConfig.setFormChildField(startUserSplit[2]);
            startUserConfig.setChildField(startUserSplit[3]);

            //设置发起人
            Object startUserId = map.get(startUserConfig.getChildField());
            List<User> allUser = redisUtil.get(GlobalConstant.USER_CACHE_KEY, new TypeReference<List<User>>() {
            });
            variableMap.putValue(WorkflowConstant.PROCESS_START_USER_ID_KEY, Convert.toLong(startUserId));
            User startUser = allUser.stream().filter(x -> x.getId().equals(Convert.toLong(startUserId))).findFirst().orElse(new User());
            variableMap.putValue(WorkflowConstant.PROCESS_START_USER_NAME_KEY, startUser.getName());

            Map<String, Object> childFormDataMap = new HashMap<>();
            for (CallActivityParamConfig inParam : callActivityConfig.getInParams()) {
                //获取到来源 的所有参数
                String[] sourceSplit = inParam.getSource().split(StringPool.UNDERSCORE + StringPool.UNDERSCORE + StringPool.UNDERSCORE);

                ParamSourceTargetModel sourceModel = new ParamSourceTargetModel();
                sourceModel.setNodeId(sourceSplit[0]);
                sourceModel.setFormKey(sourceSplit[1]);
                sourceModel.setFormChildField(sourceSplit[2]);
                sourceModel.setChildField(sourceSplit[3]);

                //获取到去向 的所有参数
                String[] tagetSplit = inParam.getTarget().split(StringPool.UNDERSCORE + StringPool.UNDERSCORE + StringPool.UNDERSCORE);

                Object sourceFieldValue = MapUtil.get(map, sourceModel.getChildField(), Object.class);
                childFormDataMap.put(tagetSplit[2], sourceFieldValue);

            }

            variableMap.putValue(formConfig.getKey(), childFormDataMap);

            //如果是最后一条数据  清空此缓存
            if (index + 1 == childDataMapList.size()) {
                redisUtil.delete(WorkflowConstant.CALLACTIVITY_CACHE_PREFIX + superExecution.getProcessInstanceId() + originatorConfig);
            } else {
                //设置递增
                redisUtil.incr(WorkflowConstant.CALLACTIVITY_CACHE_PREFIX + superExecution.getProcessInstanceId() + originatorConfig, 1);
            }


            //将主表的 子表数据 当作 外部流程的  主表数据 存到变量中
            runtimeService.setVariables(execution.getProcessInstanceId(), variableMap);
            //记录父节点外部流程流程数据
            callActivityNodeRecord(superWorkflowSchema, callActivityConfig, superExecution.getProcessInstanceId(), "【" + startUser.getName() + "】 创建流程");
            //记录开始节点数据
            startNodeRecord(workflowSchema, startNodeConfig, execution.getProcessInstanceId(), "【" + startUser.getName() + "】 创建流程");
        }


    }


    /**
     * 子流程 构建 默认参数
     *
     * @param execution
     * @param superExecution
     * @param runtimeService
     * @param superWorkflowSchema
     * @param subProcessConfig
     */
    private void initSubProcessParam(DelegateExecution execution, ExecutionEntity superExecution, RuntimeService runtimeService, WorkflowSchema superWorkflowSchema, SubProcessConfig subProcessConfig) {


        //获取到主流程的参数
        Object superProcessParamObj = superExecution.getVariable(WorkflowConstant.PROCESS_PARAM_KEY);
        Map<String, Object> superProcessParamMap = Convert.toMap(String.class, Object.class, superProcessParamObj);

        HistoryService historyService = execution.getProcessEngine().getHistoryService();
        long count = historyService.createHistoricProcessInstanceQuery().count();

        User user = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_INFO_KEY, new User());

        //设定全局变量 发起人id、发起人名、模板id 、模板名、页面配置参数值、流水号
        VariableMap variableMap = Variables.createVariables()
                .putValue(WorkflowConstant.PROCESS_START_USER_ID_KEY, user.getId())
                .putValue(WorkflowConstant.PROCESS_START_USER_NAME_KEY, user.getName())
                .putValue(WorkflowConstant.PROCESS_SCHEMA_ID_KEY, superWorkflowSchema.getId())
                .putValue(WorkflowConstant.PROCESS_SCHEMA_NAME_KEY, superWorkflowSchema.getName())
                .putValue(WorkflowConstant.PROCESS_PARAM_KEY, superProcessParamMap)
                .putValue(WorkflowConstant.PROCESS_ISRECYCLE_FLAG_KEY, WorkflowIsRecycleType.NO.getCode())
                .putValue(WorkflowConstant.PROCESS_SERIAL_NUMBER_KEY, count + 1);


        runtimeService.setVariables(execution.getProcessInstanceId(), variableMap);
    }

    /**
     * 普通流程 开始节点 开始事件 执行逻辑
     * 1、默认插入所有全局变量
     *
     * @param execution
     */
    private void processStartNodeStartEvent(DelegateExecution execution) {

        //        模板id
        Object schemaIdObj = execution.getVariable(WorkflowConstant.PROCESS_SCHEMA_ID_KEY);

        Long schemaId = Convert.toLong(schemaIdObj);

        IWorkflowSchemaService workflowSchemaService = SpringUtil.getBean(IWorkflowSchemaService.class);
        WorkflowSchema workflowSchema = workflowSchemaService.getOne(Wrappers.lambdaQuery(WorkflowSchema.class).eq(WorkflowSchema::getId, schemaId));

//        WorkflowSchema workflowSchema = redisUtil.get(WorkflowConstant.SCHEMA_CACHE_PREFIX + Convert.toStr(schemaId), WorkflowSchema.class);
        //如果能查询到xjr_workflow_extra，扩展表里面有对应流程的数据就拿取到对应的发起人id
        List<WorkflowExtra> workflowExtra = workflowExtraService.list(Wrappers.lambdaQuery(WorkflowExtra.class).eq(WorkflowExtra::getProcessId, execution.getProcessInstanceId()).orderByDesc(WorkflowExtra::getStartTime));
        String userName = StringPool.EMPTY;
        if (workflowExtra.size() > 0){
            userName = workflowExtra.get(0).getStartUserName();
        }else {
            User user = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_INFO_KEY, new User());
            userName = user.getName();
        }
        //获取到整个流程模板的配置
        WorkflowSchemaConfig workflowSchemaConfig = JSONUtil.toBean(workflowSchema.getJsonContent(), WorkflowSchemaConfig.class);

        Optional<Map<String, Object>> startNodeMap = workflowSchemaConfig.getChildNodeConfig().stream().filter(x -> x.containsValue(WorkflowConstant.BPMN_XML_START_EVENT_TYPE_NAME)).findFirst();

        if (!startNodeMap.isPresent()) {
            throw new MyException("当前任务没有开始节点");
        }
        //将map 转为 java类
        StartNodeConfig startNodeConfig = Convert.convert(StartNodeConfig.class, startNodeMap.get());

        //如果说当前流程id已经有了创建流程，则是驳回到开始结点的记录，不需要重复记录
        long startSize = workflowRecordService.count(Wrappers.<WorkflowRecord>query().lambda().eq(WorkflowRecord::getProcessId, execution.getProcessInstanceId()).like(WorkflowRecord::getMessage, "创建流程"));
        if(startSize < 1){
            startNodeRecord(workflowSchema, startNodeConfig, execution.getProcessInstanceId(), "【" + userName + "】 创建流程");
        }
        List<String> formKeys = startNodeConfig.getFormConfigs().stream().map(FormConfig::getKey).collect(Collectors.toList());
        AssignmentConfig assignmentConfig = startNodeConfig.getAssignmentConfig();
        paramAssignment(execution, formKeys, assignmentConfig, workflowSchema);

    }

    /**
     * 参数赋值
     *
     * @param execution
     * @param formKeys         当前节点表单key
     * @param assignmentConfig 赋值配置
     * @param schema           模板schema
     */
    private void paramAssignment(DelegateExecution execution, List<String> formKeys, AssignmentConfig assignmentConfig, WorkflowSchema schema) {

        Object variable = execution.getVariable(WorkflowConstant.PROCESS_PARAM_KEY);

        Map<String, Object> processParam = Convert.toMap(String.class, Object.class, variable);

        RuntimeService runtimeService = execution.getProcessEngine().getRuntimeService();

        formKeys.add(WorkflowConstant.PROCESS_SERIAL_NUMBER_KEY);
        Map<String, Object> variablesMap = runtimeService.getVariables(execution.getProcessInstanceId(), formKeys);

        WorkFlowUtil.invokeParamAssignment(assignmentConfig, processParam, variablesMap, schema);

        runtimeService.setVariable(execution.getProcessInstanceId(), WorkflowConstant.PROCESS_PARAM_KEY, processParam);
    }

    /***
     * 多实例任务  构建 多实例 集合
     * @param execution
     */
    private void multiInstanceInitCollection(DelegateExecution execution, String multiUserTaskId) {
//        模板id
        Object schemaIdObj = execution.getVariable(WorkflowConstant.PROCESS_SCHEMA_ID_KEY);

        Long schemaId = Convert.toLong(schemaIdObj);

        IWorkflowSchemaService workflowSchemaService = SpringUtil.getBean(IWorkflowSchemaService.class);
        WorkflowSchema workflowSchema = workflowSchemaService.getOne(Wrappers.lambdaQuery(WorkflowSchema.class).eq(WorkflowSchema::getId, schemaId));

//        WorkflowSchema workflowSchema = redisUtil.get(WorkflowConstant.SCHEMA_CACHE_PREFIX + Convert.toStr(schemaId), WorkflowSchema.class);

        WorkflowSchemaConfig workflowSchemaConfig = JSONUtil.toBean(workflowSchema.getJsonContent(), WorkflowSchemaConfig.class);

        Optional<Map<String, Object>> nextUserTaskConfigOp = workflowSchemaConfig.getChildNodeConfig().stream().filter(x -> x.containsValue(multiUserTaskId)).findFirst();

        nextUserTaskConfigOp.ifPresent(configMap -> {
            //获取到json中的type类型
            String nodeType = MapUtil.get(configMap, WorkflowConstant.BPMN_EVENT_SOURCE_TYPE_KEY, String.class);
            //如果是否为多实例 外部流程
            if (StrUtil.equals(nodeType, WorkflowConstant.BPMN_XML_CALL_ACTIVITY_TYPE_NAME)) {
                CallActivityConfig callActivityConfig = Convert.convert(CallActivityConfig.class, configMap);

                String originatorConfig = callActivityConfig.getOriginatorConfig();
                String[] split = originatorConfig.split(StringPool.UNDERSCORE + StringPool.UNDERSCORE + StringPool.UNDERSCORE);
                ParamSourceTargetModel model = new ParamSourceTargetModel();
                model.setNodeId(split[0]);
                model.setFormKey(split[1]);
                model.setFormChildField(split[2]);
                model.setChildField(split[3]);
                if (callActivityConfig.getCallActivityType() == WorkflowCallActivityType.SINGLE.getCode()) {

                } else {
                    //获取到当前配置的发起人  表单数据
                    Object formDataObj = execution.getVariable(model.getFormKey());
                    Map<String, Object> formData = Convert.toMap(String.class, Object.class, formDataObj);
                    //获取到子表数据
                    Object childTableDataObj = formData.get(model.getFormChildField());
                    List<Map> maps = Convert.toList(Map.class, childTableDataObj);

                    //获取到子表 指定字段 所有值  作为发起人
                    List<Object> allChildFieldValue = maps.stream().map(x -> x.get(model.getChildField())).collect(Collectors.toList());

                    //将数据设置为变量  存储到变量表
                    RuntimeService runtimeService = execution.getProcessEngine().getRuntimeService();
                    runtimeService.setVariable(execution.getProcessInstanceId(), WorkflowConstant.TASK_MULTI_ASSIGNEE_VAR_KEY + multiUserTaskId, allChildFieldValue);

                    //将数据长度缓存 用户外部流程 获取子表单数据的时候的下标 父节点流程id + 发起人配置
                    redisUtil.set(WorkflowConstant.CALLACTIVITY_CACHE_PREFIX + execution.getProcessInstanceId() + originatorConfig, 0);
                }


            }
            //如果是多实例用户任务
            else {
                //将map 转为 java类
                UserTaskConfig userTaskConfig = Convert.convert(UserTaskConfig.class, configMap);

                CountersignConfig countersignConfig = userTaskConfig.getCountersignConfig();

                //只要多实例
                if (countersignConfig.getMultipleInstancesType() != WorkflowMultiInstanceType.NONE.getCode()) {
                    List<CountersignMemberConfig> checkList = countersignConfig.getCountersignList().stream().filter(CountersignMemberConfig::getChecked).collect(Collectors.toList());
                    List<MemberConfig> memberConfigs = BeanUtil.copyToList(checkList, MemberConfig.class);
                    List<Long> userIds = WorkFlowUtil.getUserIdsByMemberConfig(memberConfigs, workflowSchemaConfig.getChildNodeConfig(), execution.getProcessInstanceId());
                    RuntimeService runtimeService = execution.getProcessEngine().getRuntimeService();
                    runtimeService.setVariable(execution.getProcessInstanceId(), WorkflowConstant.TASK_MULTI_ASSIGNEE_VAR_KEY + multiUserTaskId, userIds.stream().map(Convert::toStr).collect(Collectors.toList()));
                }
            }


        });

    }


    /**
     * 记录外部流程节点信息
     *
     * @param workflowSchema
     * @param callActivityConfig
     * @param processInstanceId
     * @param message
     */
    private void callActivityNodeRecord(WorkflowSchema workflowSchema, CallActivityConfig callActivityConfig, String processInstanceId, String message) {

        //新增流程发起流程记录
        WorkflowRecord startRecord = new WorkflowRecord();
        startRecord.setNodeId(callActivityConfig.getId());
        startRecord.setNodeName(callActivityConfig.getName());
        startRecord.setNodeType(WorkflowConstant.CALL_ACTIVITY_TYPE_NAME);
        startRecord.setProcessId(processInstanceId);
        startRecord.setSchemaId(workflowSchema.getId());
        startRecord.setNodeMultiType(WorkflowMultiInstanceType.NONE.getCode());
        startRecord.setRecordTime(LocalDateTime.now());
        startRecord.setMessage(message);

        workflowRecordService.save(startRecord);

        //新增流程发起流程记录
        XjrWorkflowOperateRecord startOperateRecord = new XjrWorkflowOperateRecord();
        startOperateRecord.setNodeId(callActivityConfig.getId());
        startOperateRecord.setNodeName(callActivityConfig.getName());
        startOperateRecord.setNodeType(WorkflowConstant.CALL_ACTIVITY_TYPE_NAME);
        startOperateRecord.setProcessId(processInstanceId);
        startOperateRecord.setSchemaId(workflowSchema.getId());
        startOperateRecord.setNodeMultiType(WorkflowMultiInstanceType.NONE.getCode());
        startOperateRecord.setRecordTime(LocalDateTime.now());
        startOperateRecord.setUsageScenario(1);
        startOperateRecord.setOperateInfo(message);

        xjrWorkflowOperateRecordService.save(startOperateRecord);
    }

    /**
     * 记录开始节点流程信息
     *
     * @param workflowSchema
     * @param startNodeConfig
     * @param processInstanceId
     * @param message
     */
    private void startNodeRecord(WorkflowSchema workflowSchema, StartNodeConfig startNodeConfig, String processInstanceId, String message) {

        //新增流程发起流程记录
        WorkflowRecord startRecord = new WorkflowRecord();
        startRecord.setNodeId(startNodeConfig.getId());
        startRecord.setNodeName(startNodeConfig.getName());
        startRecord.setNodeType(WorkflowConstant.START_EVENT_TYPE_NAME);
        startRecord.setProcessId(processInstanceId);
        startRecord.setSchemaId(workflowSchema.getId());
        startRecord.setNodeMultiType(WorkflowMultiInstanceType.NONE.getCode());
        startRecord.setRecordTime(LocalDateTime.now());
        startRecord.setMessage(message);

        workflowRecordService.save(startRecord);

        //新增流程发起流程记录
        XjrWorkflowOperateRecord startOperateRecord = new XjrWorkflowOperateRecord();
        startOperateRecord.setNodeId(startNodeConfig.getId());
        startOperateRecord.setNodeName(startNodeConfig.getName());
        startOperateRecord.setNodeType(WorkflowConstant.START_EVENT_TYPE_NAME);
        startOperateRecord.setProcessId(processInstanceId);
        startOperateRecord.setSchemaId(workflowSchema.getId());
        startOperateRecord.setNodeMultiType(WorkflowMultiInstanceType.NONE.getCode());
        startOperateRecord.setRecordTime(LocalDateTime.now());
        startOperateRecord.setUsageScenario(1);
        startOperateRecord.setOperateInfo(message);

        xjrWorkflowOperateRecordService.save(startOperateRecord);
    }

}
