package com.qmth.distributed.print.business.service.impl;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.qmth.boot.api.exception.ApiException;
import com.qmth.distributed.print.business.activiti.custom.service.DefaultInstanceConvertToMultiInstance;
import com.qmth.distributed.print.business.activiti.custom.service.MultiWorkFlow;
import com.qmth.distributed.print.business.bean.flow.*;
import com.qmth.distributed.print.business.bean.flow.link.FlowTaskLink;
import com.qmth.distributed.print.business.bean.flow.link.FlowTaskNode;
import com.qmth.distributed.print.business.bean.result.*;
import com.qmth.distributed.print.business.entity.*;
import com.qmth.distributed.print.business.enums.*;
import com.qmth.distributed.print.business.service.*;
import com.qmth.teachcloud.common.bean.params.ApproveUserResult;
import com.qmth.teachcloud.common.bean.params.SysRoleGroupMemberMatch;
import com.qmth.teachcloud.common.bean.params.SysRoleGroupMemberMatchParams;
import com.qmth.teachcloud.common.bean.result.SysRoleGroupMemberMatchResult;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.SysOrg;
import com.qmth.teachcloud.common.entity.SysUser;
import com.qmth.teachcloud.common.enums.*;
import com.qmth.teachcloud.common.service.CommonCacheService;
import com.qmth.teachcloud.common.service.SysRoleGroupMemberService;
import com.qmth.teachcloud.common.service.SysUserService;
import com.qmth.teachcloud.common.util.JacksonUtil;
import com.qmth.teachcloud.common.util.RedisUtil;
import com.qmth.teachcloud.common.util.ResultUtil;
import com.qmth.teachcloud.common.util.ServletUtil;
import org.activiti.bpmn.BpmnAutoLayout;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.*;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.impl.bpmn.behavior.MultiInstanceActivityBehavior;
import org.activiti.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior;
import org.activiti.engine.impl.bpmn.behavior.SequentialMultiInstanceBehavior;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Description: activiti service impl
 * @Param:
 * @return:
 * @Author: wangliang
 * @Date: 2021/7/12
 */
@Service
public class ActivitiServiceImpl implements ActivitiService {
    private final static Logger log = LoggerFactory.getLogger(ActivitiServiceImpl.class);

    @Resource
    RuntimeService runtimeService;

    @Resource
    TaskService taskService;

    @Resource
    RepositoryService repositoryService;

    @Resource
    TFFlowApproveService tfFlowApproveService;

    @Resource
    TFFlowLogService tfFlowLogService;

    @Resource
    ExamTaskService examTaskService;

    @Resource
    RedisUtil redisUtil;

    @Resource
    SysUserService sysUserService;

    @Resource
    TFFlowJoinService tfFlowJoinService;

    @Resource
    MultiWorkFlow multiWorkFlow;

    @Resource
    TFCustomFlowService tfCustomFlowService;

    @Resource
    TFCustomFlowEntityService tfCustomFlowEntityService;

    @Resource
    CommonCacheService commonCacheService;

    @Resource
    SysRoleGroupMemberService sysRoleGroupMemberService;

    @Resource
    BasicMessageService basicMessageService;

    /**
     * 启动流程
     *
     * @param map
     * @return
     */
    @Override
    public ProcessInstance flowStart(Map<String, Object> map) {
        Long approveId = Objects.nonNull(map.get(SystemConstant.APPROVE_ID)) ? (Long) map.get(SystemConstant.APPROVE_ID) : null;
        String id = (String) map.get(SystemConstant.ID);
        Long objectId = (Long) map.get(SystemConstant.OBJECT_ID);
        TFCustomTypeEnum flowType = (TFCustomTypeEnum) map.get(SystemConstant.FLOW_TYPE);
        Object o = map.get(SystemConstant.OBJECT_DATA);
        Boolean flowSubmit = (Boolean) map.get(SystemConstant.FLOW_SUBMIT);
        Map flowProcessVarMap = (Map) map.get(SystemConstant.FLOW_PROCESS_VAR_MAP);
        Map<String, CustomFlowVarDto> agginessMap = (Map<String, CustomFlowVarDto>) flowProcessVarMap.get(SystemConstant.AGGINESS_MAP);
        SysRoleGroupMemberMatchParams roleGroupMemberMatchParams = null;
        Map<String, SysRoleGroupMemberMatch> flowRoleGroupMemberMatchMap = null;
        Map<String, Object> varMap = new HashMap<>();
        Gson gson = new Gson();
        for (Map.Entry<String, CustomFlowVarDto> entry : agginessMap.entrySet()) {
            CustomFlowVarDto customFlowVarDto = gson.fromJson(gson.toJson(entry.getValue()), CustomFlowVarDto.class);
            if (Objects.nonNull(customFlowVarDto.getFlowTaskVar()) && customFlowVarDto.getFlowTaskVar().contains(DefaultInstanceConvertToMultiInstance.DEFAULT_ASSIGNEE_LIST)) {
                if (Objects.nonNull(customFlowVarDto.getModelType()) && customFlowVarDto.getModelType() == TFCustomModelTypeEnum.USER_FIXED) {
                    if (customFlowVarDto.getApproveUserType() == CustomFlowApproveUserTypeEnum.USER) {
                        Set<String> set = new LinkedHashSet(customFlowVarDto.getApproveIds());
                        if (customFlowVarDto.getMultipleUserApproveType() == CustomFlowMultipleUserApproveTypeEnum.SOME) {
                            varMap.computeIfAbsent(customFlowVarDto.getFlowTaskVar(), s -> set.toString().replaceAll("\\[", "").replaceAll("\\]", "").trim());
                        } else {
                            varMap.computeIfAbsent(customFlowVarDto.getFlowTaskVar(), s -> set);
                        }
                    } else if (customFlowVarDto.getApproveUserType() == CustomFlowApproveUserTypeEnum.ROLE) {
                        roleGroupMemberMatchParams = Objects.isNull(roleGroupMemberMatchParams) ? new SysRoleGroupMemberMatchParams() : roleGroupMemberMatchParams;
                        if (Objects.isNull(roleGroupMemberMatchParams.getFlowRoleGroupMemberMatchMap()) || roleGroupMemberMatchParams.getFlowRoleGroupMemberMatchMap().size() == 0) {
                            flowRoleGroupMemberMatchMap = new LinkedHashMap<>();
                        } else {
                            flowRoleGroupMemberMatchMap = roleGroupMemberMatchParams.getFlowRoleGroupMemberMatchMap();
                        }
                        if (flowRoleGroupMemberMatchMap.size() == 0) {
                            flowRoleGroupMemberMatchMap.computeIfAbsent(entry.getKey(), v -> new SysRoleGroupMemberMatch(customFlowVarDto.getApproveRoleIds().stream().map(s -> SystemConstant.convertIdToLong(s)).collect(Collectors.toList()), approveId));
                        } else {
                            flowRoleGroupMemberMatchMap.computeIfAbsent(entry.getKey(), v -> new SysRoleGroupMemberMatch(customFlowVarDto.getApproveRoleIds().stream().map(s -> SystemConstant.convertIdToLong(s)).collect(Collectors.toList())));
                        }
                        roleGroupMemberMatchParams.setFlowRoleGroupMemberMatchMap(flowRoleGroupMemberMatchMap);
                    }
                } else if (Objects.nonNull(customFlowVarDto.getModelType()) && customFlowVarDto.getModelType() == TFCustomModelTypeEnum.APPROVE_SET) {
                    varMap.computeIfAbsent(customFlowVarDto.getFlowTaskVar(), s -> customFlowVarDto.getApproveIds());
                }
            } else {
                varMap.computeIfAbsent(customFlowVarDto.getFlowTaskVar(), s -> customFlowVarDto.getApproveIds().get(0));
            }
        }
        if (Objects.nonNull(roleGroupMemberMatchParams)) {
            Map<String, SysRoleGroupMemberMatchResult> sysRoleGroupMemberMatchResultMap = sysRoleGroupMemberService.matchList(roleGroupMemberMatchParams);
            if (Objects.nonNull(sysRoleGroupMemberMatchResultMap) && sysRoleGroupMemberMatchResultMap.size() > 0) {
                sysRoleGroupMemberMatchResultMap.forEach((k, v) -> {
                    String userTaskId = k.substring(k.length() - 1, k.length());
                    CustomFlowVarDto customFlowVarDto = gson.fromJson(gson.toJson(agginessMap.get(k)), CustomFlowVarDto.class);
                    if (Objects.isNull(v)) {
                        throw ExceptionResultEnum.ERROR.exception("流程第" + userTaskId + "个审批节点没有审批人或成员数据已发生改变，请重新选择！");
                    }
                    int count = sysRoleGroupMemberService.findByIdsCount(v.getSysRoleGroupMemberIdList());
                    if (count == 0 || count != v.getSysRoleGroupMemberIdList().size()) {
                        throw ExceptionResultEnum.ERROR.exception("流程第" + userTaskId + "个审批节点成员数据已发生改变，请重新选择！");
                    }
                    List<ApproveUserResult> approveUserResultList = v.getApproveUserResultList();
                    List<String> approveUserList = new ArrayList<>();
                    StringJoiner approveUserNamesSj = new StringJoiner("");
                    for (ApproveUserResult a : approveUserResultList) {
                        approveUserList.add(String.valueOf(a.getId()));
                        approveUserNamesSj.add(a.getRealName()).add("(").add(a.getOrgName()).add(")").add(",");
                    }
                    customFlowVarDto.setApproveIds(approveUserList);
                    Set<String> set = new LinkedHashSet(approveUserList);
                    String approveUserNames = approveUserNamesSj.toString();
                    approveUserNames = !Objects.equals(approveUserNames, "") ? approveUserNames.substring(0, approveUserNames.length() - 1) : null;
                    customFlowVarDto.setApproveUserNames(approveUserNames);
                    if (customFlowVarDto.getMultipleUserApproveType() == CustomFlowMultipleUserApproveTypeEnum.SOME) {
                        varMap.put(customFlowVarDto.getFlowTaskVar(), set.toString().replaceAll("\\[", "").replaceAll("\\]", "").trim());
                    } else {
                        varMap.put(customFlowVarDto.getFlowTaskVar(), set);
                    }
                    agginessMap.put(k, customFlowVarDto);
                });
            }
            flowProcessVarMap.put(SystemConstant.AGGINESS_MAP, agginessMap);
        }
        varMap.computeIfAbsent(SystemConstant.OBJECT_ID, v -> objectId);
        varMap.computeIfAbsent(SystemConstant.OBJECT_DATA, v -> o);
        varMap.computeIfAbsent(SystemConstant.FLOW_TYPE, v -> flowType);
        varMap.computeIfAbsent(SystemConstant.FLOW_SUBMIT, v -> flowSubmit);

        //启动流程
        ProcessInstance processInstance = varMap.size() > 0 ? runtimeService.startProcessInstanceByKey(id, varMap) : runtimeService.startProcessInstanceByKey(id);
        map.computeIfAbsent(SystemConstant.PROCESS_DEFINITION_ID, v -> processInstance.getProcessDefinitionId());
        map.computeIfAbsent(SystemConstant.FLOW_ID, v -> processInstance.getProcessInstanceId());
        map.computeIfAbsent(SystemConstant.FLOW_STATUS, v -> FlowStatusEnum.START);
        this.createFlowPicture(map);
        this.flowApproveStart(map);
        return processInstance;
    }

    /**
     * 创建流程图片
     *
     * @param map
     */
    protected void createFlowPicture(Map<String, Object> map) {
        String id = (String) map.get(SystemConstant.FLOW_ENTITY_ID);
        String processDefinitionId = (String) map.get(SystemConstant.PROCESS_DEFINITION_ID);
        String bpmnPngName = id + DefaultInstanceConvertToMultiInstance.FLOW_BPMN_PNG_NAME;

        //保存png图片(这一步可做可不做)
        InputStream processDiagram = repositoryService.getProcessDiagram(processDefinitionId);
        try {
            FileUtils.copyInputStreamToFile(processDiagram, new File(SystemConstant.TEMP_FILES_DIR + File.separator + DefaultInstanceConvertToMultiInstance.BPMN_NAME + File.separator + bpmnPngName));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 部署流程
     *
     * @param map
     * @return
     */
    protected Deployment flowDeployment(Map<String, Object> map) {
        String id = (String) map.get(SystemConstant.ID);
        BpmnModel model = (BpmnModel) map.get(SystemConstant.MODEL);
        Integer version = (Integer) map.get(SystemConstant.VERSION);

        //部署流程
        String bpmnName = id + DefaultInstanceConvertToMultiInstance.FLOW_BPMN_MODEL_NAME;
        String bpmnDeploymentName = id + DefaultInstanceConvertToMultiInstance.FLOW_BPMN_DEPLOYMENT_NAME;
        String bpmnProcessName = id + "_v" + version + DefaultInstanceConvertToMultiInstance.FLOW_BPMN_PROCESS_NAME;

        Deployment deployment = repositoryService.createDeployment().addBpmnModel(bpmnName, model).name(bpmnDeploymentName).deploy();
        map.remove(SystemConstant.MODEL);

        //保存xml文件(这一步可做可不做)
        InputStream processBpmn = repositoryService.getResourceAsStream(deployment.getId(), bpmnName);
        try {
            FileUtils.copyInputStreamToFile(processBpmn, new File(SystemConstant.TEMP_FILES_DIR + File.separator + DefaultInstanceConvertToMultiInstance.BPMN_NAME + File.separator + bpmnProcessName));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return deployment;
    }

    /**
     * 根据流程id直接结束流程
     *
     * @param flowId
     */
    @Override
    @Transactional
    public void flowEnd(String flowId) {
        boolean lock = redisUtil.lock(SystemConstant.REDIS_LOCK_FLOW_PREFIX + flowId, SystemConstant.REDIS_LOCK_FLOW_TIME_OUT);
        if (!lock) {
            throw ExceptionResultEnum.ERROR.exception("正在终止中，请稍候再试！");
        }
        try {
            SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
            TFFlowJoin tfFlowJoin = tfFlowJoinService.findByFlowId(SystemConstant.convertIdToLong(flowId));
            Object o = null;
            if (Objects.nonNull(tfFlowJoin.getObjectTable()) && Objects.equals(tfFlowJoin.getObjectTable(), TFCustomTypeEnum.ELECTRON_FLOW.getTable())) {
                o = examTaskService.findByFlowId(SystemConstant.convertIdToLong(flowId));
            }
            //流程审批
            TFFlowApprove tfFlowApprove = tfFlowApproveService.findByFlowId(SystemConstant.convertIdToLong(flowId));
            if (Objects.isNull(tfFlowApprove)) {
                tfFlowApprove = new TFFlowApprove(sysUser.getSchoolId(), sysUser.getOrgId(), SystemConstant.convertIdToLong(flowId), sysUser.getId(), FlowStatusEnum.END, sysUser.getId());
            } else {
                tfFlowApprove.setStatus(FlowStatusEnum.END);
                tfFlowApprove.setSetup(FlowApproveSetupEnum.END.getSetup());
                tfFlowApprove.updateInfo(sysUser.getId());
            }
            tfFlowApproveService.saveOrUpdate(tfFlowApprove);

            //流程流水日志
            TFFlowLog tfFlowLog = new TFFlowLog(sysUser.getSchoolId(), sysUser.getOrgId(), tfFlowJoin.getFlowId(), tfFlowJoin.getObjectId(), sysUser.getId(), sysUser.getId(), FlowApproveSetupEnum.END.getTitle(), tfFlowJoin.getObjectTable());
            tfFlowLog.setApproveOperation(FlowApproveOperationEnum.END);
            tfFlowLog.setApproveSetup(FlowApproveSetupEnum.END.getSetup());
            tfFlowLogService.save(tfFlowLog);

            //命题任务修改
//            examTask.setFlowId(null);
            if (Objects.nonNull(o) && o instanceof ExamTask) {
                ExamTask examTask = (ExamTask) o;
                examTask.setStatus(ExamStatusEnum.STAGE);
                examTask.updateInfo(sysUser.getId());
                examTaskService.updateById(examTask);
            }
            runtimeService.deleteProcessInstance(flowId, FlowApproveSetupEnum.END.getTitle());
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
            if (e instanceof ApiException) {
                ResultUtil.error((ApiException) e, e.getMessage());
            } else {
                ResultUtil.error(e.getMessage());
            }
        } finally {
            redisUtil.releaseLock(SystemConstant.REDIS_LOCK_FLOW_PREFIX + flowId);
        }
    }

    /**
     * 流程审批启动
     *
     * @param map
     */
    protected void flowApproveStart(Map<String, Object> map) {
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        Optional.ofNullable(map.get(SystemConstant.FLOW_ID)).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程id不能为空"));
        String flowId = (String) map.get(SystemConstant.FLOW_ID);
        TFCustomTypeEnum flowType = (TFCustomTypeEnum) map.get(SystemConstant.FLOW_TYPE);

        Optional.ofNullable(map.get(SystemConstant.FLOW_STATUS)).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程状态不能为空"));
        FlowStatusEnum flowStatusEnum = (FlowStatusEnum) map.get(SystemConstant.FLOW_STATUS);

        String approveId = Objects.nonNull(map.get(SystemConstant.APPROVE_ID)) ? String.valueOf((Long) map.get(SystemConstant.APPROVE_ID)) : null;

        TFFlowApprove tfFlowApprove = null;
        FlowJoinTypeEnum flowJoinTypeEnum = (FlowJoinTypeEnum) map.get(SystemConstant.FLOW_JOIN_TYPE);
        if (Objects.nonNull(flowJoinTypeEnum) && flowJoinTypeEnum == FlowJoinTypeEnum.RESTART) {//重新提交
            Long oldFlowId = (Long) map.get(SystemConstant.OLD_FLOW_ID);
            tfFlowApprove = tfFlowApproveService.findByFlowId(oldFlowId);
            tfFlowApprove.insertInfo(sysUser.getId());
            tfFlowApprove.updateInfo(sysUser.getId());
            tfFlowApprove.setFlowId(SystemConstant.convertIdToLong(flowId));
            tfFlowApprove.setStatus(flowStatusEnum);
            tfFlowApprove.setSetup(FlowApproveSetupEnum.SUBMIT.getSetup());
        } else {
            tfFlowApprove = new TFFlowApprove(sysUser.getSchoolId(), sysUser.getOrgId(), SystemConstant.convertIdToLong(flowId), sysUser.getId(), flowStatusEnum, sysUser.getId());
        }
        tfFlowApproveService.save(tfFlowApprove);

        Long objectId = (Long) map.get(SystemConstant.OBJECT_ID);
//        //TODO 测试用
//        if (flowType == TFCustomTypeEnum.ELECTRON_FLOW) {//如果是电子交卷审核，就查询命题任务
//            ExamTask examTask = examTaskService.getById(objectId);
//            examTask.setFlowId(SystemConstant.convertIdToLong(flowId));
//            examTaskService.updateById(examTask);
//        }
//
//        String id = (String) map.get(SystemConstant.FLOW_ENTITY_ID);
//        List<TFFlowJoin> tfFlowJoinList = tfFlowJoinService.findByObjectId(objectId);
//        tfFlowJoinList.get(0).setFlowEntityId(SystemConstant.convertIdToLong(id));
//        tfFlowJoinList.get(0).setFlowId(SystemConstant.convertIdToLong(flowId));
//        tfFlowJoinList.get(0).setObjectTable(flowType.getTable());
//        tfFlowJoinService.updateById(tfFlowJoinList.get(0));
        tfFlowLogService.save(new TFFlowLog(sysUser.getSchoolId(), sysUser.getOrgId(), SystemConstant.convertIdToLong(flowId), objectId, sysUser.getId(), sysUser.getId(), "提交流程", approveId, FlowApproveOperationEnum.SUBMIT, flowType.getTable()));
    }

    /**
     * 审批任务
     *
     * @param map
     */
    @Override
    @Transactional
    public Map<String, Object> taskApprove(Map<String, Object> map) {
        String flowTaskId = null;
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        Optional.ofNullable(map.get(SystemConstant.FLOW_TASK_ID)).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程任务id不能为空"));
        flowTaskId = (String) map.get(SystemConstant.FLOW_TASK_ID);
        Task task = taskService.createTaskQuery().taskId(flowTaskId).singleResult();
        Optional.ofNullable(task).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程任务为空或该流程已被他人审核，请刷新再试！"));
        Long flowId = SystemConstant.convertIdToLong(task.getProcessInstanceId());
        boolean lock = redisUtil.lock(SystemConstant.REDIS_LOCK_FLOW_TASK_PREFIX + flowId, SystemConstant.REDIS_LOCK_FLOW_TASK_TIME_OUT);
        if (!lock) {
            throw ExceptionResultEnum.ERROR.exception("正在审批中，请稍候再试！");
        }
        try {
            TFFlowJoin tfFlowJoin = tfFlowJoinService.findByFlowId(flowId);
            Object o = null;
            if (Objects.nonNull(tfFlowJoin.getObjectTable()) && Objects.equals(tfFlowJoin.getObjectTable(), TFCustomTypeEnum.ELECTRON_FLOW.getTable())) {
                o = examTaskService.findByFlowId(flowId);
            }

            //获取当前流程节点
            String currActivityId = task.getTaskDefinitionKey();
            BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
            FlowNode currFlow = (FlowNode) bpmnModel.getMainProcess().getFlowElement(currActivityId);

            //流程审批
            TFFlowApprove tfFlowApprove = tfFlowApproveService.findByFlowId(flowId);
            tfFlowApprove = Objects.isNull(tfFlowApprove) ? new TFFlowApprove(sysUser.getSchoolId(), sysUser.getOrgId(), flowId, sysUser.getId(), FlowStatusEnum.FINISH, sysUser.getId()) : tfFlowApprove;

            TFFlowLog tfFlowLog = null;

            TFCustomFlowEntity tfCustomFlowEntity = tfCustomFlowEntityService.findByFlowId(flowId);
            Map<String, Object> flowProcessVarMap = this.getFlowProcessVarMap(tfCustomFlowEntity);

            TFCustomFlow tfCustomFlow = tfCustomFlowService.getById(tfCustomFlowEntity.gettFCustomFlowId());
            Optional.ofNullable(tfCustomFlow).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("自定义流程数据为空"));

            if (Objects.isNull(tfCustomFlow.getEnable()) || !tfCustomFlow.getEnable()) {
                throw ExceptionResultEnum.ERROR.exception("自定义流程未启用");
            }
            String remark = null;
            FlowTaskResult currFlowTaskResult = null, nextFlowTaskResult = null;
            Map<String, CustomFlowVarDto> agginessMap = (Map<String, CustomFlowVarDto>) flowProcessVarMap.get(SystemConstant.AGGINESS_MAP);
            if (Objects.nonNull(tfFlowApprove.getTransferAssignee())) {
                agginessMap = JacksonUtil.readJson(tfFlowApprove.getTransferAssignee(), Map.class);
            }
            Gson gson = new Gson();
            Integer nrOfCompletedInstances = null, nrOfInstances = null;
            boolean multiInstance = false;
            FlowApprovePassEnum approvePass = null;
            if (currFlow instanceof UserTask) {
                UserTask userTask = (UserTask) currFlow;
                String id = userTask.getId().substring(userTask.getId().length() - 1, userTask.getId().length());
                if (currFlow.getBehavior() instanceof MultiInstanceActivityBehavior) {
                    nrOfCompletedInstances = (Integer) taskService.getVariable(task.getId(), DefaultInstanceConvertToMultiInstance.NR_OF_COMPLETED_INSTANCES);
                    nrOfCompletedInstances++;
                    nrOfInstances = (Integer) taskService.getVariable(task.getId(), DefaultInstanceConvertToMultiInstance.NR_OF_INSTANCES);
                    multiInstance = true;
                }
                remark = Objects.nonNull(map.get(SystemConstant.APPROVE_REMARK)) ? map.get(SystemConstant.APPROVE_REMARK).toString() : null;
                //流程流水日志
                tfFlowLog = new TFFlowLog(sysUser.getSchoolId(), sysUser.getOrgId(), flowId, tfFlowJoin.getObjectId(), sysUser.getId(), sysUser.getId(), remark, tfFlowJoin.getObjectTable());
                //判断流程审批是通过还是驳回
                approvePass = (FlowApprovePassEnum) map.get(SystemConstant.APPROVE_OPERATION);
                Map<String, FlowTaskResult> setupMap = (Map<String, FlowTaskResult>) flowProcessVarMap.get(SystemConstant.SETUP_MAP);
                //获取当前流程和下一流程setup
                currFlowTaskResult = gson.fromJson(gson.toJson(setupMap.get(userTask.getId())), FlowTaskResult.class);
                if (approvePass == FlowApprovePassEnum.PASS) {
                    int currSetup = currFlowTaskResult.getSetup().intValue();
                    currSetup = currSetup == setupMap.size() - 1 ? 0 : currSetup + 1;
                    //驳回再提交时，可能需要走网关路线
                    //获取驳回路线
                    FlowTaskResult flowTaskResultRejectLinkDto = null;
                    Map<String, FlowTaskResult> rejectLinkMap = null;
                    if (Objects.nonNull(tfFlowApprove.getRejectLink())) {
                        rejectLinkMap = JacksonUtil.readJson(tfFlowApprove.getRejectLink(), Map.class);
                        if (Objects.nonNull(rejectLinkMap.get(userTask.getId()))) {
                            flowTaskResultRejectLinkDto = gson.fromJson(gson.toJson(rejectLinkMap.get(userTask.getId())), FlowTaskResult.class);
                        }
                    }

                    nextFlowTaskResult = this.getNextFlowTaskResult(nrOfCompletedInstances,
                            nrOfInstances,
                            currFlowTaskResult,
                            nextFlowTaskResult,
                            Objects.nonNull(flowTaskResultRejectLinkDto) ? flowTaskResultRejectLinkDto.getSetup() : currSetup,
                            setupMap,
                            gson,
                            approvePass);

                    this.approvePass(currFlowTaskResult,
                            setupMap,
                            multiInstance,
                            nrOfCompletedInstances,
                            nrOfInstances,
                            tfFlowApprove,
                            tfFlowLog,
                            nextFlowTaskResult,
                            map,
                            id);

                    if (Objects.nonNull(flowTaskResultRejectLinkDto)) {
                        rejectLinkMap.remove(userTask.getId());
                        tfFlowApprove.setRejectLink(rejectLinkMap.size() == 0 ? null : JacksonUtil.parseJson(rejectLinkMap));
                    }
                } else if (approvePass == FlowApprovePassEnum.REJECT || approvePass == FlowApprovePassEnum.CANCEL) {
                    Optional.ofNullable(map.get(SystemConstant.APPROVE_SETUP)).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程驳回节点不能为空"));
                    Integer rejectSetup = Integer.parseInt(map.get(SystemConstant.APPROVE_SETUP).toString());

                    nextFlowTaskResult = this.getNextFlowTaskResult(nrOfCompletedInstances,
                            nrOfInstances,
                            currFlowTaskResult,
                            nextFlowTaskResult,
                            rejectSetup,
                            setupMap,
                            gson,
                            approvePass);

                    this.approveReject(multiInstance,
                            map,
                            id,
                            currFlowTaskResult,
                            nextFlowTaskResult,
                            tfFlowApprove,
                            tfFlowLog,
                            agginessMap,
                            gson,
                            approvePass);
                }
                //获取流程变量
                this.getAgginess(nextFlowTaskResult,
                        gson,
                        map,
                        agginessMap,
                        approvePass,
                        flowProcessVarMap,
                        tfCustomFlowEntity,
                        currFlow,
                        setupMap,
                        tfFlowApprove);
            }
            this.setApproveInfo(tfFlowApprove,
                    tfFlowLog,
                    sysUser,
                    map,
                    currFlow,
                    nrOfCompletedInstances,
                    nrOfInstances,
                    currFlowTaskResult,
                    nextFlowTaskResult,
                    gson,
                    agginessMap,
                    o,
                    approvePass);
            //当前实例的执行到哪个节点
            taskService.complete(String.valueOf(flowTaskId), map);
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
            if (e instanceof ApiException) {
                ResultUtil.error((ApiException) e, e.getMessage());
            } else {
                ResultUtil.error(e.getMessage());
            }
        } finally {
            redisUtil.releaseLock(SystemConstant.REDIS_LOCK_FLOW_TASK_PREFIX + flowId);
        }
        return map;
    }

    /**
     * 设置审批信息
     *
     * @param tfFlowApprove
     * @param tfFlowLog
     * @param sysUser
     * @param map
     * @param currFlow
     * @param nrOfCompletedInstances
     * @param nrOfInstances
     * @param currFlowTaskResult
     * @param nextFlowTaskResult
     * @param gson
     * @param agginessMap
     * @param o
     * @param approvePass
     */
    protected void setApproveInfo(TFFlowApprove tfFlowApprove,
                                  TFFlowLog tfFlowLog,
                                  SysUser sysUser,
                                  Map<String, Object> map,
                                  FlowNode currFlow,
                                  Integer nrOfCompletedInstances,
                                  Integer nrOfInstances,
                                  FlowTaskResult currFlowTaskResult,
                                  FlowTaskResult nextFlowTaskResult,
                                  Gson gson,
                                  Map<String, CustomFlowVarDto> agginessMap,
                                  Object o,
                                  FlowApprovePassEnum approvePass) {
        tfFlowApprove.updateInfo(sysUser.getId());
        if (tfFlowLog.getApproveOperation() == FlowApproveOperationEnum.APPROVE) {
            tfFlowApprove.setApproveSetup(nrOfCompletedInstances);
            tfFlowApprove.setApproveMaxSetup(nrOfInstances);
        } else {
            tfFlowApprove.setApproveSetup(null);
            tfFlowApprove.setApproveMaxSetup(null);
        }
        tfFlowApprove.setApproveId(sysUser.getId());
        tfFlowLog.setApproveSetup(currFlowTaskResult.getSetup());
        tfFlowLog.setApproveMultiSetup(nrOfCompletedInstances);
        tfFlowLog.setPaperAttachmentId((String) map.get(SystemConstant.PAPAER_ATTACHMENT_IDS));
        CustomFlowVarDto customFlowVarDto = gson.fromJson(gson.toJson(agginessMap.get(nextFlowTaskResult.getTaskKey())), CustomFlowVarDto.class);
        if (Objects.nonNull(customFlowVarDto)) {
            if (tfFlowLog.getApproveOperation() == FlowApproveOperationEnum.APPROVE && Objects.nonNull(nrOfCompletedInstances)
                    && Objects.nonNull(nrOfInstances)
                    && nrOfCompletedInstances.intValue() != nrOfInstances.intValue()) {
                if (currFlow.getBehavior() instanceof SequentialMultiInstanceBehavior) {//串行
                    tfFlowLog.setPendApproveId(customFlowVarDto.getApproveIds().subList(nrOfCompletedInstances, nrOfInstances).toString().replaceAll("\\[", "").replaceAll("\\]", ""));
                } else if (currFlow.getBehavior() instanceof ParallelMultiInstanceBehavior) {//并行
                    Map<String, CustomFlowVarDto> allAgginessMap = null;
                    CustomFlowVarDto customFlowVarAllDto = null;
                    if (Objects.nonNull(tfFlowApprove.getAllAssignee())) {
                        allAgginessMap = JacksonUtil.readJson(tfFlowApprove.getAllAssignee(), Map.class);
                        customFlowVarAllDto = gson.fromJson(gson.toJson(allAgginessMap.get(nextFlowTaskResult.getTaskKey())), CustomFlowVarDto.class);
                    } else {
                        allAgginessMap = new HashMap<>();
                        customFlowVarAllDto = customFlowVarDto;
                    }
                    allAgginessMap.put(nextFlowTaskResult.getTaskKey(), customFlowVarAllDto);
                    List<String> approveIds = customFlowVarAllDto.getApproveIds();
                    approveIds.remove(String.valueOf(sysUser.getId()));
                    if (Objects.nonNull(approveIds) && approveIds.size() > 0) {
                        tfFlowLog.setPendApproveId(approveIds.toString().replaceAll("\\[", "").replaceAll("\\]", ""));
                    }
                    tfFlowApprove.setAllAssignee(JacksonUtil.parseJson(allAgginessMap));
                }
            } else {
                if (Objects.nonNull(tfFlowApprove.getAllAssignee())) {
                    Map<String, CustomFlowVarDto> allAgginessMap = JacksonUtil.readJson(tfFlowApprove.getAllAssignee(), Map.class);
                    allAgginessMap.remove(currFlowTaskResult.getTaskKey());
                    tfFlowApprove.setAllAssignee(allAgginessMap.size() == 0 ? null : JacksonUtil.parseJson(allAgginessMap));
                }
                tfFlowLog.setPendApproveId(customFlowVarDto.getApproveIds().toString().replaceAll("\\[", "").replaceAll("\\]", ""));
            }
            CustomFlowVarDto currCustomFlowVarDto = gson.fromJson(gson.toJson(agginessMap.get(currFlowTaskResult.getTaskKey())), CustomFlowVarDto.class);
            //说明在两个审批节点交界处
            if (approvePass == FlowApprovePassEnum.PASS && currCustomFlowVarDto.getMultipleUserApproveType() != customFlowVarDto.getMultipleUserApproveType()) {
                tfFlowLog.setApproveMultiSetup(null);
            }
            tfFlowLog.setApproveUserApproveType(customFlowVarDto.getMultipleUserApproveType());
        }
        map.put(SystemConstant.APPROVE_TF_FLOW_LOG, tfFlowLog);
        map.put(SystemConstant.AGGINESS_MAP, agginessMap);
        tfFlowApproveService.saveOrUpdate(tfFlowApprove);
        tfFlowLogService.save(tfFlowLog);
        if (Objects.nonNull(o) && o instanceof ExamTask) {
            ExamTask examTask = (ExamTask) o;
            examTask.updateInfo(sysUser.getId());
            examTaskService.updateById(examTask);
        }
    }

    /**
     * 获取审批人
     *
     * @param nextFlowTaskResult
     * @param gson
     * @param map
     * @param agginessMap
     * @param approvePass
     * @param flowProcessVarMap
     * @param tfCustomFlowEntity
     * @param currFlow
     * @param setupMap
     */
    protected void getAgginess(FlowTaskResult nextFlowTaskResult,
                               Gson gson,
                               Map<String, Object> map,
                               Map<String, CustomFlowVarDto> agginessMap,
                               FlowApprovePassEnum approvePass,
                               Map<String, Object> flowProcessVarMap,
                               TFCustomFlowEntity tfCustomFlowEntity,
                               FlowNode currFlow,
                               Map<String, FlowTaskResult> setupMap,
                               TFFlowApprove tfFlowApprove) {
        if (Objects.nonNull(agginessMap.get(nextFlowTaskResult.getTaskKey()))) {
            CustomFlowVarDto customFlowVarDto = gson.fromJson(gson.toJson(agginessMap.get(nextFlowTaskResult.getTaskKey())), CustomFlowVarDto.class);
            if (Objects.nonNull(nextFlowTaskResult.getModelType()) && nextFlowTaskResult.getModelType() == TFCustomModelTypeEnum.APPROVE_SET) {
                List<Long> approveUserIds = (List<Long>) map.get(SystemConstant.APPROVE_USER_IDS);
                if (approvePass == FlowApprovePassEnum.PASS && Objects.nonNull(approveUserIds) && approveUserIds.size() > 0) {
                    boolean freshen = false;
                    if (Objects.equals(currFlow.getId(), nextFlowTaskResult.getTaskKey())) {
                        nextFlowTaskResult = this.getNextFlowTaskResult(setupMap, gson, (nextFlowTaskResult.getSetup().intValue() + 1), nextFlowTaskResult);
                        customFlowVarDto = gson.fromJson(gson.toJson(agginessMap.get(nextFlowTaskResult.getTaskKey())), CustomFlowVarDto.class);
                        freshen = true;
                    }
                    List<String> approveIds = approveUserIds.stream().map(s -> String.valueOf(s)).collect(Collectors.toList());
                    nextFlowTaskResult.setApproveIds(approveIds);
                    customFlowVarDto.setApproveIds(nextFlowTaskResult.getApproveIds());
                    Set<String> set = new LinkedHashSet(customFlowVarDto.getApproveIds());
                    ApproveUserResult approveUserResult = sysUserService.findByIds(set.stream().map(x -> SystemConstant.convertIdToLong(x)).collect(Collectors.toList()));
                    customFlowVarDto.setApproveUserNames(approveUserResult.getPendApproveUsers());
                    agginessMap.put(nextFlowTaskResult.getTaskKey(), customFlowVarDto);

                    if (Objects.nonNull(tfFlowApprove.getTransferAssignee())) {
                        Map<String, CustomFlowVarDto> agginessTransferMap = JacksonUtil.readJson(tfFlowApprove.getTransferAssignee(), Map.class);
                        agginessTransferMap.put(nextFlowTaskResult.getTaskKey(), customFlowVarDto);
                        tfFlowApprove.setTransferAssignee(JacksonUtil.parseJson(agginessTransferMap));
                    }

                    if (Objects.nonNull(tfFlowApprove.getAllAssignee())) {
                        Map<String, CustomFlowVarDto> agginessAllMap = JacksonUtil.readJson(tfFlowApprove.getAllAssignee(), Map.class);
                        agginessAllMap.put(nextFlowTaskResult.getTaskKey(), customFlowVarDto);
                        tfFlowApprove.setAllAssignee(JacksonUtil.parseJson(agginessAllMap));
                    }

                    flowProcessVarMap.put(SystemConstant.AGGINESS_MAP, agginessMap);
                    Map<String, Object> varMap = JacksonUtil.readJson(tfCustomFlowEntity.getFlowProcessVar(), Map.class);
                    varMap.put(SystemConstant.FLOW_PROCESS_VAR_MAP, flowProcessVarMap);
                    tfCustomFlowEntity.setFlowProcessVar(JacksonUtil.parseJson(varMap));
                    tfCustomFlowEntityService.updateById(tfCustomFlowEntity);

                    customFlowVarDto = freshen ? gson.fromJson(gson.toJson(agginessMap.get(currFlow.getId())), CustomFlowVarDto.class) : customFlowVarDto;
                }
                setFlowTaskVar(customFlowVarDto, map);
            } else {
                setFlowTaskVar(customFlowVarDto, map);
            }
        }
        map.put(SystemConstant.SETUP_MAP, setupMap);
    }

    /**
     * 设置下一步值
     *
     * @param customFlowVarDto
     * @param map
     */
    protected void setFlowTaskVar(CustomFlowVarDto customFlowVarDto, Map<String, Object> map) {
        if (Objects.nonNull(customFlowVarDto.getFlowTaskVar()) && customFlowVarDto.getFlowTaskVar().contains(DefaultInstanceConvertToMultiInstance.DEFAULT_ASSIGNEE_LIST)) {
            Set<String> set = new LinkedHashSet(customFlowVarDto.getApproveIds());
            if (Objects.isNull(set) || set.size() == 0) {
                throw ExceptionResultEnum.ERROR.exception("未设置审批人");
            }
            if (customFlowVarDto.getMultipleUserApproveType() == CustomFlowMultipleUserApproveTypeEnum.SOME) {
                map.computeIfAbsent(customFlowVarDto.getFlowTaskVar(), s -> set.toString().replaceAll("\\[", "").replaceAll("\\]", "").trim());
            } else {
                map.computeIfAbsent(customFlowVarDto.getFlowTaskVar(), s -> set);
            }
        } else {
            map.computeIfAbsent(customFlowVarDto.getFlowTaskVar(), v -> customFlowVarDto.getApproveIds().get(0));
        }
    }

    /**
     * 审批驳回
     *
     * @param multiInstance
     * @param map
     * @param id
     * @param currFlowTaskResult
     * @param nextFlowTaskResult
     * @param tfFlowApprove
     * @param tfFlowLog
     * @param agginessMap
     * @param gson
     * @param approvePass
     */
    protected void approveReject(boolean multiInstance,
                                 Map<String, Object> map,
                                 String id,
                                 FlowTaskResult currFlowTaskResult,
                                 FlowTaskResult nextFlowTaskResult,
                                 TFFlowApprove tfFlowApprove,
                                 TFFlowLog tfFlowLog,
                                 Map<String, CustomFlowVarDto> agginessMap,
                                 Gson gson,
                                 FlowApprovePassEnum approvePass) {
        if (multiInstance) {
            map.computeIfAbsent(FlowApproveOperationEnum.REJECT.getId() + id, v -> 1);
        }
        map.put(SystemConstant.APPROVE, nextFlowTaskResult.getTaskKey());
        tfFlowApprove.setSetup(nextFlowTaskResult.getSetup());
        tfFlowApprove.setStatus(FlowStatusEnum.convertToEnum(approvePass.name()));
        tfFlowLog.setApproveOperation(FlowApproveOperationEnum.convertToEnum(approvePass.name()));
        CustomFlowVarDto customFlowVarDto = gson.fromJson(gson.toJson(agginessMap.get(currFlowTaskResult.getTaskKey())), CustomFlowVarDto.class);
        if (approvePass == FlowApprovePassEnum.REJECT && Objects.nonNull(customFlowVarDto) && customFlowVarDto.getRejectResubmitType() == CustomFlowRejectResubmitTypeEnum.PREV_STEP) {
            Map<String, FlowTaskResult> rejectLinkMap = null;
            if (Objects.nonNull(tfFlowApprove.getRejectLink())) {
                rejectLinkMap = JacksonUtil.readJson(tfFlowApprove.getRejectLink(), Map.class);
            } else {
                rejectLinkMap = new HashMap<>();
            }
            rejectLinkMap.put(nextFlowTaskResult.getTaskKey(), currFlowTaskResult);
            tfFlowApprove.setRejectLink(JacksonUtil.parseJson(rejectLinkMap));
        }
    }

    /**
     * 获取下级审核节点
     *
     * @param nrOfCompletedInstances
     * @param nrOfInstances
     * @param currFlowTaskResult
     * @param nextFlowTaskResult
     * @param currSetup
     * @param setupMap
     * @param gson
     * @param approvePass
     * @return
     */
    protected FlowTaskResult getNextFlowTaskResult(Integer nrOfCompletedInstances,
                                                   Integer nrOfInstances,
                                                   FlowTaskResult currFlowTaskResult,
                                                   FlowTaskResult nextFlowTaskResult,
                                                   int currSetup,
                                                   Map<String, FlowTaskResult> setupMap,
                                                   Gson gson,
                                                   FlowApprovePassEnum approvePass) {
        if (approvePass == FlowApprovePassEnum.PASS) {
            if (Objects.nonNull(nrOfCompletedInstances)
                    && Objects.nonNull(nrOfInstances)
                    && nrOfCompletedInstances.intValue() != nrOfInstances.intValue()) {
                nextFlowTaskResult = currFlowTaskResult;
            } else {
                nextFlowTaskResult = this.getNextFlowTaskResult(setupMap, gson, currSetup, nextFlowTaskResult);
            }
        } else if (approvePass == FlowApprovePassEnum.REJECT || approvePass == FlowApprovePassEnum.CANCEL) {
            nextFlowTaskResult = this.getNextFlowTaskResult(setupMap, gson, currSetup, nextFlowTaskResult);
        }
        Optional.ofNullable(nextFlowTaskResult).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("该节点不能审批通过"));
        return nextFlowTaskResult;
    }

    /**
     * 获取下级审核节点
     *
     * @param setupMap
     * @param gson
     * @param currSetup
     * @param nextFlowTaskResult
     * @return
     */
    @Override
    public FlowTaskResult getNextFlowTaskResult(Map<String, FlowTaskResult> setupMap,
                                                Gson gson,
                                                int currSetup,
                                                FlowTaskResult nextFlowTaskResult) {
        for (Map.Entry<String, FlowTaskResult> entry : setupMap.entrySet()) {
            FlowTaskResult flowTaskResultTemp = gson.fromJson(gson.toJson(entry.getValue()), FlowTaskResult.class);
            if (flowTaskResultTemp.getSetup().intValue() == currSetup) {
                nextFlowTaskResult = flowTaskResultTemp;
                break;
            }
        }
        return nextFlowTaskResult;
    }

    /**
     * 审批通过
     *
     * @param currFlowTaskResult
     * @param setupMap
     * @param multiInstance
     * @param nrOfCompletedInstances
     * @param nrOfInstances
     * @param tfFlowApprove
     * @param tfFlowLog
     * @param nextFlowTaskResult
     * @param map
     * @param id
     */
    protected void approvePass(FlowTaskResult currFlowTaskResult,
                               Map<String, FlowTaskResult> setupMap,
                               boolean multiInstance,
                               Integer nrOfCompletedInstances,
                               Integer nrOfInstances,
                               TFFlowApprove tfFlowApprove,
                               TFFlowLog tfFlowLog,
                               FlowTaskResult nextFlowTaskResult,
                               Map<String, Object> map,
                               String id) {
        if (multiInstance) {
            map.computeIfAbsent(FlowApproveOperationEnum.REJECT.getId() + id, v -> 0);
        }
        if (currFlowTaskResult.getSetup().intValue() == setupMap.size() - 1) {
            if (multiInstance && Objects.nonNull(nrOfCompletedInstances)
                    && Objects.nonNull(nrOfInstances)
                    && nrOfCompletedInstances.intValue() == nrOfInstances.intValue()) {
                tfFlowApprove.setStatus(FlowStatusEnum.FINISH);
                tfFlowApprove.setSetup(FlowApproveSetupEnum.FINISH.getSetup());
            } else if (!multiInstance) {
                tfFlowApprove.setStatus(FlowStatusEnum.FINISH);
                tfFlowApprove.setSetup(FlowApproveSetupEnum.FINISH.getSetup());
            } else {
                tfFlowApprove.setStatus(FlowStatusEnum.AUDITING);
                tfFlowApprove.setSetup(nextFlowTaskResult.getSetup());
            }
        } else {
            tfFlowApprove.setStatus(FlowStatusEnum.AUDITING);
            tfFlowApprove.setSetup(nextFlowTaskResult.getSetup());
        }
        if (tfFlowApprove.getStatus() == FlowStatusEnum.START) {
            tfFlowLog.setApproveOperation(FlowApproveOperationEnum.SUBMIT);
        } else {
            tfFlowLog.setApproveOperation(FlowApproveOperationEnum.APPROVE);
        }
        map.put(SystemConstant.APPROVE, nextFlowTaskResult.getTaskKey());
    }

    /**
     * 获取所有流程节点
     *
     * @param flowId
     * @return
     */
    @Override
    public List<FlowTaskResult> getTaskAll(String flowId) {
        TFCustomFlowEntity tfCustomFlowEntity = tfCustomFlowEntityService.findByFlowId(SystemConstant.convertIdToLong(flowId));
        Optional.ofNullable(tfCustomFlowEntity).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("自定义流程实体数据为空"));
        return this.getFlowTaskResult(tfCustomFlowEntity);
    }

    /**
     * 获取流程节点信息
     *
     * @param o
     * @return
     */
    protected List<FlowTaskResult> getFlowTaskResult(Object o) {
        Long flowId = null;
        if (o instanceof TFCustomFlow) {
            o = (TFCustomFlow) o;
        } else if (o instanceof TFCustomFlowEntity) {
            o = (TFCustomFlowEntity) o;
            flowId = ((TFCustomFlowEntity) o).getFlowId();
        }
        Map<String, Object> flowProcessVarMap = this.getFlowProcessVarMap(o);
        Map<String, FlowTaskResult> setupMap = (Map<String, FlowTaskResult>) flowProcessVarMap.get(SystemConstant.SETUP_MAP);
        Optional.ofNullable(setupMap).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程没有步骤数据！"));

        List<FlowTaskResult> flowTaskResultList = new ArrayList<>(setupMap.size());
        Gson gson = new Gson();
        for (Map.Entry<String, FlowTaskResult> entry : setupMap.entrySet()) {
            FlowTaskResult flowTaskResult = gson.fromJson(gson.toJson(entry.getValue()), FlowTaskResult.class);
            if (flowTaskResult.getSetup() > 0) {
                flowTaskResult.setFlowId(flowId);
                flowTaskResultList.add(flowTaskResult);
            }
        }
        Collections.sort(flowTaskResultList, Comparator.comparing(FlowTaskResult::getSetup));
        return flowTaskResultList;
    }

    /**
     * 流程节点转他人审批
     *
     * @param userId
     * @param taskId
     * @return
     */
    @Override
    @Transactional
    public boolean taskApproverExchange(String userId, String taskId) {
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        SysOrg sysOrg = commonCacheService.orgCache(sysUser.getOrgId());
        if (Objects.equals(String.valueOf(sysUser.getId()), userId)) {
            throw ExceptionResultEnum.ERROR.exception("不能转给自己");
        }
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        Optional.ofNullable(task).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程任务为空或该流程已被他人审核，请刷新再试！"));
        String flowId = task.getProcessInstanceId();
        TFFlowApprove tfFlowApprove = tfFlowApproveService.findByFlowId(SystemConstant.convertIdToLong(flowId));
        Optional.ofNullable(tfFlowApprove).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("未找到流程状态记录"));
        if (tfFlowApprove.getSetup() <= 0) {
            throw ExceptionResultEnum.ERROR.exception("流程已结束或已终止");
        }

        TFCustomFlowEntity tfCustomFlowEntity = tfCustomFlowEntityService.findByFlowId(tfFlowApprove.getFlowId());
        Map<String, Object> flowProcessVarMap = this.getFlowProcessVarMap(tfCustomFlowEntity);
        Map<String, CustomFlowVarDto> agginessMap = (Map<String, CustomFlowVarDto>) flowProcessVarMap.get(SystemConstant.AGGINESS_MAP);
        if (Objects.nonNull(tfFlowApprove.getTransferAssignee())) {
            agginessMap = JacksonUtil.readJson(tfFlowApprove.getTransferAssignee(), Map.class);
        }

        //获取当前流程节点
        String currActivityId = task.getTaskDefinitionKey();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
        FlowNode currFlow = (FlowNode) bpmnModel.getMainProcess().getFlowElement(currActivityId);

        UserTask userTask = null;
        if (currFlow instanceof UserTask) {
            userTask = (UserTask) currFlow;
        }

        Gson gson = new Gson();
        Integer nrOfCompletedInstances = null, nrOfInstances = null;
        boolean multiInstance = false;
        if (currFlow.getBehavior() instanceof MultiInstanceActivityBehavior) {//会签
            nrOfCompletedInstances = (Integer) taskService.getVariable(task.getId(), DefaultInstanceConvertToMultiInstance.NR_OF_COMPLETED_INSTANCES);
            nrOfInstances = (Integer) taskService.getVariable(task.getId(), DefaultInstanceConvertToMultiInstance.NR_OF_INSTANCES);
            multiInstance = true;

            CustomFlowVarDto customFlowVarDto = gson.fromJson(gson.toJson(agginessMap.get(userTask.getId())), CustomFlowVarDto.class);
            if (Objects.nonNull(customFlowVarDto)) {
                List<String> approveIds = customFlowVarDto.getApproveIds();
                if (Objects.nonNull(approveIds) && approveIds.size() > 0 && approveIds.contains(userId)) {
                    throw ExceptionResultEnum.ERROR.exception("该审批人已有审批权限，无需流转");
                }
            }
        } else {//或签
            Task taskUser = taskService.createTaskQuery().taskId(taskId).taskCandidateOrAssigned(userId).singleResult();
            if (Objects.nonNull(taskUser)) {
                throw ExceptionResultEnum.ERROR.exception("该审批人已有审批权限，无需流转");
            }
        }
        TFFlowJoin tfFlowJoin = tfFlowJoinService.findByFlowId(SystemConstant.convertIdToLong(flowId));
        Object o = null;
        if (Objects.nonNull(tfFlowJoin.getObjectTable()) && Objects.equals(tfFlowJoin.getObjectTable(), TFCustomTypeEnum.ELECTRON_FLOW.getTable())) {
            o = examTaskService.findByFlowId(SystemConstant.convertIdToLong(flowId));
        }
        SysUser exchangeUser = sysUserService.getById(userId);
        SysOrg exchangeSysOrg = commonCacheService.orgCache(exchangeUser.getOrgId());

        String remark = Objects.nonNull(sysOrg) ? sysOrg.getName() : "无机构";
        String exchangeRemark = Objects.nonNull(exchangeSysOrg) ? exchangeSysOrg.getName() : "无机构";
        //流程流水日志
        TFFlowLog tfFlowLog = new TFFlowLog(sysUser.getSchoolId(), sysUser.getOrgId(), tfFlowJoin.getFlowId(), tfFlowJoin.getObjectId(), sysUser.getId(), sysUser.getRealName() + "(" + remark + ")转" + exchangeUser.getRealName() + "(" + exchangeRemark + ")审批", FlowApproveOperationEnum.EXCHANGE, sysUser.getId(), String.valueOf(exchangeUser.getId()), tfFlowJoin.getObjectTable());
        CustomFlowVarDto customFlowVarDto = gson.fromJson(gson.toJson(agginessMap.get(userTask.getId())), CustomFlowVarDto.class);
        if (customFlowVarDto.getApproveIds().size() == 1) {
            customFlowVarDto.setApproveIds(new ArrayList<>(Arrays.asList(userId)));
        } else {
            if (multiInstance && Objects.nonNull(nrOfCompletedInstances)) {
                if (currFlow.getBehavior() instanceof SequentialMultiInstanceBehavior) {//串行
                    List<String> approveIds = customFlowVarDto.getApproveIds();
                    approveIds.remove(nrOfCompletedInstances.intValue());
                    approveIds.add(nrOfCompletedInstances.intValue(), userId);
                    tfFlowLog.setPendApproveId(approveIds.subList(nrOfCompletedInstances, nrOfInstances).toString().replaceAll("\\[", "").replaceAll("\\]", ""));
                } else if (currFlow.getBehavior() instanceof ParallelMultiInstanceBehavior) {//并行
                    removeApproveUserId(customFlowVarDto, String.valueOf(sysUser.getId()), userId);
                    if (Objects.nonNull(tfFlowApprove.getAllAssignee())) {
                        Map<String, CustomFlowVarDto> allAgginessMap = JacksonUtil.readJson(tfFlowApprove.getAllAssignee(), Map.class);
                        if (Objects.nonNull(allAgginessMap.get(userTask.getId()))) {
                            CustomFlowVarDto customFlowVarAllDto = gson.fromJson(gson.toJson(allAgginessMap.get(userTask.getId())), CustomFlowVarDto.class);
                            List<String> approveIds = customFlowVarAllDto.getApproveIds();
                            approveIds.remove(String.valueOf(sysUser.getId()));
                            approveIds.add(userId);
                            Set<String> set = new LinkedHashSet(approveIds);
                            allAgginessMap.put(userTask.getId(), customFlowVarAllDto);
                            tfFlowLog.setPendApproveId(set.toString().replaceAll("\\[", "").replaceAll("\\]", ""));
                        }
                        tfFlowApprove.setAllAssignee(JacksonUtil.parseJson(allAgginessMap));
                    } else {
                        tfFlowLog.setPendApproveId(customFlowVarDto.getApproveIds().subList(nrOfCompletedInstances, nrOfInstances).toString().replaceAll("\\[", "").replaceAll("\\]", ""));
                    }
                }
            } else {
                Set<String> set = removeApproveUserId(customFlowVarDto, String.valueOf(sysUser.getId()), userId);
                tfFlowLog.setPendApproveId(set.toString().replaceAll("\\[", "").replaceAll("\\]", ""));
            }
        }
        Set<String> set = new LinkedHashSet(customFlowVarDto.getApproveIds());
        ApproveUserResult approveUserResult = sysUserService.findByIds(set.stream().map(x -> SystemConstant.convertIdToLong(x)).collect(Collectors.toList()));
        customFlowVarDto.setApproveUserNames(approveUserResult.getPendApproveUsers());
        agginessMap.put(userTask.getId(), customFlowVarDto);
        tfFlowApprove.setTransferAssignee(JacksonUtil.parseJson(agginessMap));
        tfFlowApproveService.updateById(tfFlowApprove);

        tfFlowLog.setApproveMultiSetup(Objects.nonNull(nrOfCompletedInstances) ? ++nrOfCompletedInstances : nrOfCompletedInstances);
        tfFlowLog.setApproveSetup(tfFlowApprove.getSetup());
        tfFlowLog.setApproveUserApproveType(customFlowVarDto.getMultipleUserApproveType());
        tfFlowLogService.save(tfFlowLog);

        if (!multiInstance) {
            if (Objects.equals(currActivityId, CustomFlowTypeEnum.USER_TASK.getId() + DefaultInstanceConvertToMultiInstance.DEFAULT_USER_TASK)) {
                taskService.setAssignee(taskId, userId);
            } else {
                taskService.deleteCandidateUser(taskId, String.valueOf(sysUser.getId()));
                taskService.addCandidateUser(taskId, userId);
            }
        } else {
            taskService.setAssignee(taskId, userId);
        }
        ApproveUserResult approveUserResultExchange = gson.fromJson(gson.toJson(exchangeUser), ApproveUserResult.class);
        if (Objects.nonNull(o) && o instanceof ExamTask) {
            basicMessageService.sendNoticeTaskAuditFlow((ExamTask) o, Arrays.asList(approveUserResultExchange), MessageEnum.NOTICE_OF_AUDIT_CREATED);
        }
        return true;
    }

    /**
     * 删除审批人
     *
     * @param customFlowVarDto
     * @param userId
     * @param exchangeUserId
     */
    protected Set removeApproveUserId(CustomFlowVarDto customFlowVarDto, String userId, String exchangeUserId) {
        List<String> approveIds = customFlowVarDto.getApproveIds();
        approveIds.remove(userId);
        approveIds.add(exchangeUserId);
        return new LinkedHashSet(approveIds);
    }

    /**
     * 动态创建流程图
     *
     * @param customFlowSaveDto
     * @param id
     * @param version
     * @return
     * @throws IOException
     */
    @Override
    @Transactional
    public Map<String, Object> dynamicBuildBpmn(CustomFlowSaveDto customFlowSaveDto, String id, Integer version) throws IOException {
        BpmnModel model = new BpmnModel();
        Process process = new Process();
        model.addProcess(process);
        process.setId(id);

        List<CustomFlowDto> customFlowLists = customFlowSaveDto.getCustomFlowLists();
        Map<CustomFlowTypeEnum, CustomFlowDto> customFlowTypeEnumCustomFlowDtoMap = new HashMap<>();
        FlowTaskLink flowTaskLink = new FlowTaskLink();//流程双向链表
        Map<String, Object> flowProcessVarMap = new HashMap<>();//流程变量
        Map<String, CustomFlowVarDto> agginessMap = new LinkedHashMap<>();//流程审核人数据
        Map<String, CustomFlowGatewayDto> approveDataMap = new HashMap<>();//流程审批数据
        Map<String, FlowTaskResult> setupMap = new LinkedHashMap<>();//流程审批步骤map
        LinkedMultiValueMap<String, CustomFlowSequenceDto> approvePassMap = new LinkedMultiValueMap<>();//流程审批通过数据
        LinkedMultiValueMap<String, CustomFlowSequenceDto> approveRejectMap = new LinkedMultiValueMap<>();//流程审批驳回数据
        flowProcessVarMap.computeIfAbsent(SystemConstant.AGGINESS_MAP, v -> agginessMap);
        flowProcessVarMap.computeIfAbsent(SystemConstant.APPROVE_PASS_MAP, v -> approvePassMap);
        flowProcessVarMap.computeIfAbsent(SystemConstant.APPROVE_REJECT_MAP, v -> approveRejectMap);
        flowProcessVarMap.computeIfAbsent(SystemConstant.SETUP_MAP, v -> setupMap);
        AtomicInteger gatewayId = new AtomicInteger(1);//流程网关id
        AtomicInteger sequenceId = new AtomicInteger(1);//流程连接id
        AtomicInteger setup = new AtomicInteger(2);//流程步骤id
        CustomFlowDto customFlowDefaultDto = null;
        for (int i = 0; i < customFlowLists.size(); i++) {
            CustomFlowDto customFlowDto = customFlowLists.get(i);
            FlowTaskNode node = new FlowTaskNode(customFlowDto);
            flowTaskLink.add(node);
            switch (customFlowDto.getType()) {
                case START://开始节点
                    if (customFlowTypeEnumCustomFlowDtoMap.containsKey(CustomFlowTypeEnum.START)) {
                        throw ExceptionResultEnum.ERROR.exception("流程只能有一个开始节点！");
                    } else {
                        customFlowTypeEnumCustomFlowDtoMap.computeIfAbsent(CustomFlowTypeEnum.START, v -> customFlowDto);
                    }
                    customFlowDto.setFlowTaskId(CustomFlowTypeEnum.START.getId());
                    process.addFlowElement(createStartEvent());
                    //默认在开始节点后新增一个审批节点
                    customFlowDefaultDto = multiWorkFlow.createDefaultUserTask(customFlowDto, flowTaskLink, DefaultInstanceConvertToMultiInstance.DEFAULT_USER_TASK);
                    setupMap.put(customFlowDefaultDto.getFlowTaskId(), new FlowTaskResult(customFlowDefaultDto.getContent(), customFlowDefaultDto.getFlowTaskId(), customFlowDefaultDto.getSetup(), customFlowSaveDto.getModelType()));
                    agginessMap.computeIfAbsent(customFlowDefaultDto.getFlowTaskId(), v -> new CustomFlowVarDto(SystemConstant.APPROVE_ID, new ArrayList(Arrays.asList("")), null, null, null, null, null, null, customFlowSaveDto.getModelType()));
                    process.addFlowElement(createUserTask(CustomFlowTypeEnum.USER_TASK.getId() + DefaultInstanceConvertToMultiInstance.DEFAULT_USER_TASK, Objects.nonNull(flowTaskLink.getLast().getTask().getContent()) && !Objects.equals(flowTaskLink.getLast().getTask().getContent(), "") ? flowTaskLink.getLast().getTask().getContent() : DefaultInstanceConvertToMultiInstance.DEFAULT_USER_TASK_NAME, DefaultInstanceConvertToMultiInstance.APPROVE_ID_EXP));
                    break;
                case PROCESS://过程节点
                    customFlowDto.setSetup(setup.getAndIncrement());
                    customFlowDto.setFlowTaskId(CustomFlowTypeEnum.USER_TASK.getId() + i);
                    FlowTaskResult flowTaskResult = new FlowTaskResult(Objects.nonNull(customFlowDto.getContent()) && !Objects.equals(customFlowDto.getContent(), "") ? customFlowDto.getContent() : DefaultInstanceConvertToMultiInstance.USER_TASK_APPROVE_NAME, customFlowDto.getFlowTaskId(), customFlowDto.getSetup());
                    setupMap.put(customFlowDto.getFlowTaskId(), flowTaskResult);
                    CustomFlowPropertyDto customFlowPropertyDto = customFlowDto.getProperty();
                    List<String> approveUserIds = new ArrayList<>();//审批用户
                    List<String> copyUserIds = new ArrayList<>();//抄送用户
                    List<String> approveRoleIds = null;//审批角色
                    List<String> approveUserSelectRolesIds = null;//发起人指定审批角色
                    ApproveUserResult approveUserResult = null;
                    ApproveUserResult approveUserResultCopyUser = null;
                    //抄送用户
                    if (Objects.nonNull(customFlowPropertyDto.getCopyForUsers()) && customFlowPropertyDto.getCopyForUsers().size() > 0) {
                        copyUserIds.addAll(customFlowPropertyDto.getCopyForUsers().stream().map(x -> String.valueOf(x.getId())).collect(Collectors.toList()));
                    }
                    if (Objects.nonNull(customFlowDto.getProperty())) {
                        if (customFlowSaveDto.getModelType() == TFCustomModelTypeEnum.APPROVE_SET) {
                            if ((Objects.nonNull(customFlowPropertyDto.getApproveUserSelectRange())
                                    && customFlowPropertyDto.getApproveUserSelectRange() == CustomFlowApproveUserSelectRangeEnum.ROLE)
                                    && (Objects.nonNull(customFlowPropertyDto.getApproveUserSelectRoles()) &&
                                    customFlowPropertyDto.getApproveUserSelectRoles().size() > 0)) {
                                approveUserSelectRolesIds = customFlowPropertyDto.getApproveUserSelectRoles().stream().map(x -> String.valueOf(x.getId())).collect(Collectors.toList());
                            }
                        } else if (customFlowSaveDto.getModelType() == TFCustomModelTypeEnum.USER_FIXED) {
                            //选人属性
                            switch (customFlowPropertyDto.getApproveUserType()) {
                                case USER://用户
                                    if (Objects.nonNull(customFlowPropertyDto.getApproveUsers()) && customFlowPropertyDto.getApproveUsers().size() > 0) {
                                        approveUserIds.addAll(customFlowPropertyDto.getApproveUsers().stream().map(x -> String.valueOf(x.getId())).collect(Collectors.toList()));
                                    }
                                    break;
                                case ROLE://角色
                                    if (Objects.nonNull(customFlowPropertyDto.getApproveRoles()) && customFlowPropertyDto.getApproveRoles().size() > 0) {
                                        approveRoleIds = customFlowPropertyDto.getApproveRoles().stream().map(x -> String.valueOf(x.getId())).collect(Collectors.toList());
                                    }
                                    break;
                                default:
                                    break;
                            }
                            if (approveUserIds.size() > 0) {
                                Set<String> set = new LinkedHashSet(approveUserIds);
                                approveUserResult = sysUserService.findByIds(set.stream().map(x -> SystemConstant.convertIdToLong(x)).collect(Collectors.toList()));
                            }
                            if (copyUserIds.size() > 0) {
                                Set<String> copyUserSet = new LinkedHashSet(copyUserIds);
                                approveUserResultCopyUser = sysUserService.findByIds(copyUserSet.stream().map(x -> SystemConstant.convertIdToLong(x)).collect(Collectors.toList()));
                            }
                        }
                        agginessMap.put(node.getTask().getFlowTaskId(), new CustomFlowVarDto(DefaultInstanceConvertToMultiInstance.DEFAULT_ASSIGNEE_LIST + i, approveUserIds, node.getTask().getProperty().getApproveUserType(), node.getTask().getProperty().getMultipleUserApproveType(), node.getTask().getProperty().getRejectType(), node.getTask().getProperty().getRejectResubmitType(), Objects.nonNull(approveUserResult) ? approveUserResult.getPendApproveUsers() : null, copyUserIds, Objects.nonNull(approveUserResultCopyUser) ? approveUserResultCopyUser.getPendApproveUsers() : null, approveRoleIds, approveUserSelectRolesIds, customFlowPropertyDto.getApproveUserCountType(), customFlowPropertyDto.getApproveUserSelectRange(), customFlowSaveDto.getModelType()));
                        if (Objects.nonNull(customFlowPropertyDto.getRejectType()) && !Objects.equals(customFlowPropertyDto.getRejectType(), "")) {
                            //驳回属性
                            switch (customFlowPropertyDto.getRejectType()) {
                                case PREV://上一节点
                                    String flowTaskId = null;
                                    Integer flowSetup = null;
                                    FlowTaskNode flowTaskNode = node.getBefore();
                                    boolean isProcess = false;
                                    while (!isProcess) {
                                        if (flowTaskNode.getTask().getType() == CustomFlowTypeEnum.PROCESS) {
                                            isProcess = true;
                                            flowTaskId = flowTaskNode.getTask().getFlowTaskId();
                                            flowSetup = flowTaskNode.getTask().getSetup();
                                        }
                                        flowTaskNode = flowTaskNode.getBefore();
                                    }
                                    this.createCustomFlowExclusiveGatewayAfter(node,
                                            flowTaskLink,
                                            approveDataMap,
                                            process,
                                            gatewayId,
                                            flowTaskId,
                                            false,
                                            flowSetup);
                                    break;
                                case START://发起人节点
                                    this.createCustomFlowExclusiveGatewayAfter(node,
                                            flowTaskLink,
                                            approveDataMap,
                                            process,
                                            gatewayId,
                                            customFlowDefaultDto.getFlowTaskId(),
                                            false,
                                            customFlowDefaultDto.getSetup());
                                    break;
                                case PREV_ALL://该节点前全部节点
                                    flowTaskNode = node.getBefore();
                                    while (Objects.nonNull(flowTaskNode)) {
                                        if (flowTaskNode.getTask().getType() == CustomFlowTypeEnum.PROCESS) {
                                            flowTaskId = flowTaskNode.getTask().getFlowTaskId();
                                            flowSetup = flowTaskNode.getTask().getSetup();
                                            this.createCustomFlowExclusiveGatewayAfter(node,
                                                    flowTaskLink,
                                                    approveDataMap,
                                                    process,
                                                    gatewayId,
                                                    flowTaskId,
                                                    false,
                                                    flowSetup);
                                        }
                                        flowTaskNode = flowTaskNode.getBefore();
                                    }
                                    break;
                                default:
                                    break;
                            }
                            //驳回再提交属性
                            switch (customFlowPropertyDto.getRejectResubmitType()) {
                                case PREV_STEP://提交到驳回节点
                                    CustomFlowGatewayDto customFlowGatewayDto = approveDataMap.get(node.getTask().getFlowTaskId());
                                    Map<String, List<CustomFlowSequenceDto>> flowTaskIds = customFlowGatewayDto.getFlowTaskIds();
                                    List<CustomFlowSequenceDto> customFlowSequenceDtoList = flowTaskIds.get(customFlowGatewayDto.getAfterExclusiveGatewayId());
                                    for (int y = 1; y < flowTaskLink.size(); y++) {
                                        FlowTaskNode nodeTemp = flowTaskLink.get(y);
                                        for (CustomFlowSequenceDto c : customFlowSequenceDtoList) {
                                            if (Objects.equals(nodeTemp.getTask().getFlowTaskId(), c.getAfterFlowTaskId())) {
                                                if (nodeTemp.getNext().getTask().getType() == CustomFlowTypeEnum.EXCLUSIVE_GATE_WAY) {
                                                    this.createCustomFlowExclusiveGatewayBefore(node,
                                                            flowTaskLink,
                                                            y + 1,
                                                            approveDataMap,
                                                            process,
                                                            gatewayId,
                                                            node.getTask().getFlowTaskId(),
                                                            true,
                                                            nodeTemp.getNext(),
                                                            node.getTask().getSetup());
                                                } else {
                                                    this.createCustomFlowExclusiveGatewayBefore(node,
                                                            flowTaskLink,
                                                            y + 1,
                                                            approveDataMap,
                                                            process,
                                                            gatewayId,
                                                            node.getTask().getFlowTaskId(),
                                                            true,
                                                            null,
                                                            node.getTask().getSetup());
                                                }
                                            }
                                        }
                                    }
                                    break;
                                default:
                                    break;
                            }
                        }
                    }
                    flowTaskResult.setInfo(approveRoleIds,
                            customFlowPropertyDto.getApproveUserType(),
                            customFlowSaveDto.getModelType(),
                            customFlowPropertyDto.getApproveUserCountType(),
                            customFlowPropertyDto.getApproveUserSelectRange(),
                            customFlowPropertyDto.getApproveUserSelectRoles());
                    process.addFlowElement(createUserTask(CustomFlowTypeEnum.USER_TASK.getId() + i, Objects.nonNull(customFlowDto.getContent()) && !Objects.equals(customFlowDto.getContent(), "") ? customFlowDto.getContent() : DefaultInstanceConvertToMultiInstance.USER_TASK_APPROVE_NAME, approveUserIds, customFlowPropertyDto.getMultipleUserApproveType()));
                    break;
                case END://结束节点
                    if (customFlowTypeEnumCustomFlowDtoMap.containsKey(CustomFlowTypeEnum.END)) {
                        throw ExceptionResultEnum.ERROR.exception("流程只能有一个结束节点！");
                    } else {
                        customFlowTypeEnumCustomFlowDtoMap.computeIfAbsent(CustomFlowTypeEnum.END, v -> customFlowDto);
                    }
                    customFlowDto.setSetup(0);
                    customFlowDto.setFlowTaskId(CustomFlowTypeEnum.END.getId());
                    setupMap.put(customFlowDto.getFlowTaskId(), new FlowTaskResult(customFlowDto.getContent(), customFlowDto.getFlowTaskId(), customFlowDto.getSetup()));
                    process.addFlowElement(createEndEvent());
                    break;
                default:
                    break;
            }
        }

        for (int i = 1; i < flowTaskLink.size(); i++) {
            FlowTaskNode flowTaskNode = flowTaskLink.get(i);
            String normalSequenceId = DefaultInstanceConvertToMultiInstance.SEQUENCE_NAME + sequenceId.getAndIncrement();
            if (flowTaskNode.getBefore().getTask().getType() == CustomFlowTypeEnum.EXCLUSIVE_GATE_WAY) {
                String conditionExp = DefaultInstanceConvertToMultiInstance.EXP_PREFIX + SystemConstant.APPROVE + DefaultInstanceConvertToMultiInstance.EXP_EQUAL + "'" + flowTaskNode.getTask().getFlowTaskId() + "'" + DefaultInstanceConvertToMultiInstance.EXP_SUFFIX;
                if (flowTaskNode.getBefore().getTask().getType() == CustomFlowTypeEnum.EXCLUSIVE_GATE_WAY) {
                    approvePassMap.add(flowTaskNode.getBefore().getBefore().getTask().getFlowTaskId(), new CustomFlowSequenceDto(flowTaskNode.getTask().getFlowTaskId(), conditionExp, true, flowTaskNode.getTask().getSetup()));
                } else {
                    approvePassMap.add(flowTaskNode.getBefore().getTask().getFlowTaskId(), new CustomFlowSequenceDto(flowTaskNode.getTask().getFlowTaskId(), conditionExp, true, flowTaskNode.getTask().getSetup()));
                }
//                log.info("1 start:{},end:{}", flowTaskNode.getBefore().getTask().getFlowTaskId(), flowTaskNode.getTask().getFlowTaskId());
                process.addFlowElement(createSequenceFlow(flowTaskNode.getBefore().getTask().getFlowTaskId(), flowTaskNode.getTask().getFlowTaskId(), normalSequenceId, FlowApprovePassEnum.PASS.getTitle(), conditionExp));
            } else {
                if (flowTaskNode.getBefore().getTask().getType() == CustomFlowTypeEnum.EXCLUSIVE_GATE_WAY) {
                    approvePassMap.add(flowTaskNode.getBefore().getBefore().getTask().getFlowTaskId(), new CustomFlowSequenceDto(flowTaskNode.getTask().getFlowTaskId(), true, flowTaskNode.getTask().getSetup()));
                } else {
                    approvePassMap.add(flowTaskNode.getBefore().getTask().getFlowTaskId(), new CustomFlowSequenceDto(flowTaskNode.getTask().getFlowTaskId(), true, flowTaskNode.getTask().getSetup()));
                }
//                log.info("2 start:{},end:{}", flowTaskNode.getBefore().getTask().getFlowTaskId(), flowTaskNode.getTask().getFlowTaskId());
                process.addFlowElement(createSequenceFlow(flowTaskNode.getBefore().getTask().getFlowTaskId(), flowTaskNode.getTask().getFlowTaskId(), normalSequenceId, FlowApprovePassEnum.PASS.getTitle(), null));
            }
            List<CustomFlowSequenceDto> beforeFlowTaskIdsList = flowTaskNode.getTask().getBeforeFlowTaskIds();
            beforeFlowTaskIdsList = Objects.isNull(beforeFlowTaskIdsList) ? new ArrayList<>() : beforeFlowTaskIdsList;
            if (Objects.nonNull(beforeFlowTaskIdsList)) {
                for (CustomFlowSequenceDto c : beforeFlowTaskIdsList) {
                    String gatewaySequenceId = DefaultInstanceConvertToMultiInstance.SEQUENCE_NAME + sequenceId.getAndIncrement();
                    if (Objects.nonNull(c.getBeforeFlowTaskId())) {
                        approvePassMap.add(flowTaskNode.getBefore().getTask().getFlowTaskId(), c);
//                        log.info("3 start:{},end:{}", flowTaskNode.getTask().getFlowTaskId(), c.getBeforeFlowTaskId());
                        process.addFlowElement(createSequenceFlow(flowTaskNode.getTask().getFlowTaskId(), c.getBeforeFlowTaskId(), gatewaySequenceId, FlowApprovePassEnum.PASS.getTitle(), c.getConditionExp()));
                    }
                }
            }
            List<CustomFlowSequenceDto> afterFlowTaskIdsList = flowTaskNode.getTask().getAfterFlowTaskIds();
            if (Objects.nonNull(afterFlowTaskIdsList)) {
                for (CustomFlowSequenceDto c : afterFlowTaskIdsList) {
                    String gatewaySequenceId = DefaultInstanceConvertToMultiInstance.SEQUENCE_NAME + sequenceId.getAndIncrement();
                    if (Objects.nonNull(c.getAfterFlowTaskId())) {
                        approveRejectMap.add(flowTaskNode.getBefore().getTask().getFlowTaskId(), c);
//                        log.info("4 start:{},end:{}", flowTaskNode.getTask().getFlowTaskId(), c.getAfterFlowTaskId());
                        process.addFlowElement(createSequenceFlow(flowTaskNode.getTask().getFlowTaskId(), c.getAfterFlowTaskId(), gatewaySequenceId, FlowApprovePassEnum.REJECT.getTitle(), c.getConditionExp()));
                    }
                }
            }
        }
        //生成图像信息
        new BpmnAutoLayout(model).execute();

        Map<String, Object> map = new HashMap<>();
        map.computeIfAbsent(SystemConstant.ID, v -> id);
        map.computeIfAbsent(SystemConstant.MODEL, v -> model);
        map.computeIfAbsent(SystemConstant.FLOW_PROCESS_VAR_MAP, v -> flowProcessVarMap);
        map.computeIfAbsent(SystemConstant.VERSION, v -> version);
        this.flowDeployment(map);
        return map;
    }

    /**
     * 创建当前节点驳回网关
     *
     * @param node
     * @param flowTaskLink
     * @param approveVarMap
     * @param process
     * @param gatewayId
     * @param flowTaskId
     * @param pass
     */
    protected void createCustomFlowExclusiveGatewayAfter(FlowTaskNode node,
                                                         FlowTaskLink flowTaskLink,
                                                         Map<String, CustomFlowGatewayDto> approveVarMap,
                                                         Process process,
                                                         AtomicInteger gatewayId,
                                                         String flowTaskId,
                                                         boolean pass,
                                                         Integer setup) {
        CustomFlowGatewayDto customFlowGatewayDto = null;
        FlowTaskNode customFlowExclusiveGatewayTaskNode = null;
        List<CustomFlowSequenceDto> customFlowSequenceDtoList = null;
        if (approveVarMap.containsKey(node.getTask().getFlowTaskId())) {
            customFlowGatewayDto = approveVarMap.get(node.getTask().getFlowTaskId());
        } else {
            customFlowGatewayDto = new CustomFlowGatewayDto();
        }
        //是否存在驳回网关
        if (Objects.isNull(customFlowGatewayDto.getAfterExclusiveGatewayId())) {
            customFlowExclusiveGatewayTaskNode = createCustomFlowExclusiveGateway(flowTaskLink, -1, process, gatewayId);
            customFlowGatewayDto.setAfterExclusiveGatewayId(customFlowExclusiveGatewayTaskNode.getTask().getFlowTaskId());
        } else {
            customFlowExclusiveGatewayTaskNode = node.getNext();
        }
        CustomFlowSequenceDto customFlowSequenceRejectDto = new CustomFlowSequenceDto(flowTaskId, DefaultInstanceConvertToMultiInstance.EXP_PREFIX + SystemConstant.APPROVE + DefaultInstanceConvertToMultiInstance.EXP_EQUAL + "'" + flowTaskId + "'" + DefaultInstanceConvertToMultiInstance.EXP_SUFFIX, pass, setup);
        Map<String, List<CustomFlowSequenceDto>> flowTaskIds = customFlowGatewayDto.getFlowTaskIds();
        flowTaskIds = Objects.isNull(flowTaskIds) ? new HashMap<>() : flowTaskIds;
        if (flowTaskIds.containsKey(customFlowGatewayDto.getAfterExclusiveGatewayId())) {
            customFlowSequenceDtoList = flowTaskIds.get(customFlowGatewayDto.getAfterExclusiveGatewayId());
        } else {
            customFlowSequenceDtoList = new ArrayList<>();
        }
        customFlowSequenceDtoList.add(customFlowSequenceRejectDto);
        flowTaskIds.put(customFlowGatewayDto.getAfterExclusiveGatewayId(), customFlowSequenceDtoList);
        customFlowGatewayDto.setFlowTaskIds(flowTaskIds);
        approveVarMap.put(node.getTask().getFlowTaskId(), customFlowGatewayDto);
        customFlowExclusiveGatewayTaskNode.getTask().setAfterFlowTaskIds(flowTaskIds.get(customFlowExclusiveGatewayTaskNode.getTask().getFlowTaskId()));
    }

    /**
     * 创建当前节点审批网关
     *
     * @param node
     * @param flowTaskLink
     * @param index
     * @param approveDataMap
     * @param process
     * @param gatewayId
     * @param flowTaskId
     * @param pass
     * @param exclusiveGatewayTaskNode
     * @param setup
     */
    protected void createCustomFlowExclusiveGatewayBefore(FlowTaskNode node,
                                                          FlowTaskLink flowTaskLink,
                                                          int index,
                                                          Map<String, CustomFlowGatewayDto> approveDataMap,
                                                          Process process,
                                                          AtomicInteger gatewayId,
                                                          String flowTaskId,
                                                          boolean pass,
                                                          FlowTaskNode exclusiveGatewayTaskNode,
                                                          Integer setup) {
        CustomFlowGatewayDto customFlowGatewayDto = null;
        FlowTaskNode customFlowExclusiveGatewayTaskNode = exclusiveGatewayTaskNode;
        List<CustomFlowSequenceDto> customFlowSequenceDtoList = null;
        if (approveDataMap.containsKey(node.getTask().getFlowTaskId())) {
            customFlowGatewayDto = approveDataMap.get(node.getTask().getFlowTaskId());
        } else {
            customFlowGatewayDto = new CustomFlowGatewayDto();
        }
        //是否存在审批网关
        if (Objects.isNull(customFlowExclusiveGatewayTaskNode) && (Objects.isNull(customFlowGatewayDto.getBeforeExclusiveGatewayId()) || customFlowGatewayDto.getBeforeExclusiveGatewayId().size() == 0)) {
            customFlowExclusiveGatewayTaskNode = createCustomFlowExclusiveGateway(flowTaskLink, index, process, gatewayId);
        }
        List<String> beforeExclusiveGatewayIdList = customFlowGatewayDto.getBeforeExclusiveGatewayId();
        beforeExclusiveGatewayIdList.add(customFlowExclusiveGatewayTaskNode.getTask().getFlowTaskId());
        customFlowGatewayDto.setBeforeExclusiveGatewayId(beforeExclusiveGatewayIdList);

        CustomFlowSequenceDto customFlowSequenceRejectDto = new CustomFlowSequenceDto(flowTaskId, DefaultInstanceConvertToMultiInstance.EXP_PREFIX + SystemConstant.APPROVE + DefaultInstanceConvertToMultiInstance.EXP_EQUAL + "'" + flowTaskId + "'" + DefaultInstanceConvertToMultiInstance.EXP_SUFFIX, pass, setup);
        Map<String, List<CustomFlowSequenceDto>> flowTaskIds = customFlowGatewayDto.getFlowTaskIds();
        flowTaskIds = Objects.isNull(flowTaskIds) ? new HashMap<>() : flowTaskIds;
        if (flowTaskIds.containsKey(customFlowGatewayDto.getBeforeExclusiveGatewayId())) {
            customFlowSequenceDtoList = flowTaskIds.get(customFlowGatewayDto.getBeforeExclusiveGatewayId());
        } else {
            customFlowSequenceDtoList = new ArrayList<>();
        }
        customFlowSequenceDtoList.add(customFlowSequenceRejectDto);
        flowTaskIds.put(customFlowExclusiveGatewayTaskNode.getTask().getFlowTaskId(), customFlowSequenceDtoList);
        customFlowGatewayDto.setFlowTaskIds(flowTaskIds);
        approveDataMap.put(node.getTask().getFlowTaskId(), customFlowGatewayDto);
        List<CustomFlowSequenceDto> customFlowSequenceGateWayDtoList = customFlowExclusiveGatewayTaskNode.getTask().getBeforeFlowTaskIds();
        customFlowSequenceGateWayDtoList = Objects.isNull(customFlowSequenceGateWayDtoList) ? new ArrayList<>() : customFlowSequenceGateWayDtoList;
        customFlowSequenceGateWayDtoList.addAll(flowTaskIds.get(customFlowExclusiveGatewayTaskNode.getTask().getFlowTaskId()));
        customFlowExclusiveGatewayTaskNode.getTask().setBeforeFlowTaskIds(customFlowSequenceGateWayDtoList);
    }

    /**
     * 创建自定义流程排他网关dto
     *
     * @param flowTaskLink
     * @param index
     * @param process
     * @param gatewayId
     * @return
     */
    protected FlowTaskNode createCustomFlowExclusiveGateway(FlowTaskLink flowTaskLink,
                                                            int index,
                                                            Process process,
                                                            AtomicInteger gatewayId) {
        int exclusiveGatewayId = gatewayId.getAndIncrement();
        CustomFlowDto customFlowExclusiveGatewayDto = new CustomFlowDto(DefaultInstanceConvertToMultiInstance.GATEWAY_NAME + exclusiveGatewayId, CustomFlowTypeEnum.EXCLUSIVE_GATE_WAY, CustomFlowTypeEnum.EXCLUSIVE_GATE_WAY.getTitle(), CustomFlowTypeEnum.EXCLUSIVE_GATE_WAY.getId() + exclusiveGatewayId);
        FlowTaskNode exclusiveGatewayNode = new FlowTaskNode(customFlowExclusiveGatewayDto);
        if (index <= -1) {
            flowTaskLink.add(exclusiveGatewayNode);
        } else {
            flowTaskLink.add(index, exclusiveGatewayNode);
        }
        process.addFlowElement(createExclusiveGateway(customFlowExclusiveGatewayDto.getFlowTaskId(), CustomFlowTypeEnum.EXCLUSIVE_GATE_WAY.getTitle()));
        return exclusiveGatewayNode;
    }

    /**
     * 启动自定义流程
     *
     * @param map
     */
    @Override
    @Transactional
    public Map<String, Object> customFlowStart(Map<String, Object> map) {
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        Long approveId = (Long) map.get(SystemConstant.APPROVE_ID);
        TFCustomFlow tfCustomFlow = tfCustomFlowService.findMaxVersion(sysUser.getSchoolId(), null, TFCustomTypeEnum.ELECTRON_FLOW);
        Optional.ofNullable(tfCustomFlow).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("未找到自定义流程数据"));

        TFCustomFlowEntity tfCustomFlowEntity = null;
        Map<String, Object> flowProcessVarMap = null;
        FlowJoinTypeEnum flowJoinTypeEnum = (FlowJoinTypeEnum) map.get(SystemConstant.FLOW_JOIN_TYPE);
        if (Objects.nonNull(flowJoinTypeEnum) && flowJoinTypeEnum == FlowJoinTypeEnum.RESTART) {//重新提交
            Long oldFlowId = (Long) map.get(SystemConstant.OLD_FLOW_ID);
            tfCustomFlowEntity = tfCustomFlowEntityService.findByFlowId(oldFlowId);
            tfCustomFlowEntity.insertInfo(sysUser.getId());
            tfCustomFlowEntity.updateInfo(sysUser.getId());
            flowProcessVarMap = this.getFlowProcessVarMap(tfCustomFlowEntity);
        } else {//否则新增
            tfCustomFlowEntity = new TFCustomFlowEntity(tfCustomFlow.getId(), sysUser.getId());
            flowProcessVarMap = this.getFlowProcessVarMap(tfCustomFlow);
        }
        Map<String, CustomFlowVarDto> agginessMap = (Map<String, CustomFlowVarDto>) flowProcessVarMap.get(SystemConstant.AGGINESS_MAP);
        List<String> approveUserIds = new ArrayList(Arrays.asList(String.valueOf(approveId)));
        Set<String> set = new LinkedHashSet(approveUserIds);
        ApproveUserResult approveUserResult = sysUserService.findByIds(set.stream().map(x -> SystemConstant.convertIdToLong(x)).collect(Collectors.toList()));
        agginessMap.put(CustomFlowTypeEnum.USER_TASK.getId() + DefaultInstanceConvertToMultiInstance.DEFAULT_USER_TASK, new CustomFlowVarDto(SystemConstant.APPROVE_ID, approveUserIds, approveUserResult.getPendApproveUsers(), null, null, null, null, null, null, tfCustomFlow.getModelType()));
        flowProcessVarMap.put(SystemConstant.AGGINESS_MAP, agginessMap);

        map.computeIfAbsent(SystemConstant.ID, v -> tfCustomFlow.getFlowKey());
        map.put(SystemConstant.FLOW_PROCESS_VAR_MAP, flowProcessVarMap);
        map.put(SystemConstant.FLOW_ENTITY_ID, String.valueOf(tfCustomFlowEntity.getId()));
        map.computeIfAbsent(SystemConstant.CUSTOM_FLOW_ID, v -> tfCustomFlow.getId());
        map.computeIfAbsent(SystemConstant.VERSION, v -> tfCustomFlow.getVersion());
        this.flowStart(map);

        tfCustomFlowEntity.setFlowId(SystemConstant.convertIdToLong((String) map.get(SystemConstant.FLOW_ID)));

        map.remove(SystemConstant.APPROVE_ID);
        map.remove(SystemConstant.PROCESS_DEFINITION_ID);
        map.remove(SystemConstant.FLOW_STATUS);
        map.remove(SystemConstant.OBJECT_DATA);
        map.remove(SystemConstant.FLOW_SUBMIT);
        map.computeIfAbsent(SystemConstant.ACT_FLOW_ID, v -> tfCustomFlow.getActFlowId());
        tfCustomFlowEntity.setFlowProcessVar(JacksonUtil.parseJson(map));
        tfCustomFlow.setUpdateId(sysUser.getId());
        tfCustomFlowEntityService.save(tfCustomFlowEntity);
        tfCustomFlowService.updateById(tfCustomFlow);
        return map;
    }

    /**
     * 获取当前流程节点信息
     *
     * @param taskId
     * @return
     */
    @Override
    public TaskInfoResult getTaskInfo(Long taskId) {
        Task task = taskService.createTaskQuery().taskId(String.valueOf(taskId)).singleResult();
        Optional.ofNullable(task).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程任务为空或该流程已被他人审核，请刷新再试！"));
        Long flowId = SystemConstant.convertIdToLong(task.getProcessInstanceId());
        TFCustomFlowEntity tfCustomFlowEntity = tfCustomFlowEntityService.findByFlowId(flowId);
        Map<String, Object> flowProcessVarMap = this.getFlowProcessVarMap(tfCustomFlowEntity);
        Map<String, List<CustomFlowSequenceDto>> approveRejectMap = (Map<String, List<CustomFlowSequenceDto>>) flowProcessVarMap.get(SystemConstant.APPROVE_REJECT_MAP);
        Optional.ofNullable(approveRejectMap).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程没有驳回数据！"));
        Map<String, FlowTaskResult> setupMap = (Map<String, FlowTaskResult>) flowProcessVarMap.get(SystemConstant.SETUP_MAP);
        Optional.ofNullable(setupMap).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程没有步骤数据！"));

        Gson gson = new Gson();
        FlowTaskResult currFlowTaskResult = gson.fromJson(gson.toJson(setupMap.get(task.getTaskDefinitionKey())), FlowTaskResult.class);

        //获取当前流程节点
        TFFlowApprove tfFlowApprove = tfFlowApproveService.findByFlowId(flowId);

        //获取流程待审批人
        Map<String, CustomFlowVarDto> agginessMap = (Map<String, CustomFlowVarDto>) flowProcessVarMap.get(SystemConstant.AGGINESS_MAP);
        if (Objects.nonNull(tfFlowApprove.getTransferAssignee())) {
            agginessMap = JacksonUtil.readJson(tfFlowApprove.getTransferAssignee(), Map.class);
        }

        TaskInfoResult taskInfoResult = new TaskInfoResult(flowId, task.getName(), task.getTaskDefinitionKey(), currFlowTaskResult.getSetup());
        taskInfoResult.setInfo(currFlowTaskResult.getApproveRoleIds(),
                currFlowTaskResult.getApproveUserType(),
                currFlowTaskResult.getModelType(),
                currFlowTaskResult.getApproveUserCountType(),
                currFlowTaskResult.getApproveUserSelectRange(),
                currFlowTaskResult.getApproveUserSelectRoles());
        CustomFlowVarDto currCustomFlowVarDto = gson.fromJson(gson.toJson(agginessMap.get(currFlowTaskResult.getTaskKey())), CustomFlowVarDto.class);
        taskInfoResult.setApproveUserNames(currCustomFlowVarDto.getApproveUserNames());

        int currSetup = currFlowTaskResult.getSetup().intValue();
        currSetup = currSetup == setupMap.size() - 1 ? 0 : currSetup + 1;
        FlowTaskResult nextFlowTaskResult = this.getNextFlowTaskResult(setupMap, gson, currSetup, null);
        nextFlowTaskResult.setFlowId(flowId);
        CustomFlowVarDto nextCustomFlowVarDto = gson.fromJson(gson.toJson(agginessMap.get(nextFlowTaskResult.getTaskKey())), CustomFlowVarDto.class);
        if (Objects.nonNull(nextCustomFlowVarDto) && !Objects.equals(nextFlowTaskResult.getTaskKey(), CustomFlowTypeEnum.END.getId())) {
            nextFlowTaskResult.setApproveUserNames(nextCustomFlowVarDto.getApproveUserNames());
        }

        List<FlowTaskResult> flowTaskResultList = null;
        if (Objects.nonNull(approveRejectMap.get(task.getTaskDefinitionKey()))) {
            flowTaskResultList = new ArrayList<>();
            List<CustomFlowSequenceDto> customFlowSequenceDtoList = gson.fromJson(gson.toJson(approveRejectMap.get(task.getTaskDefinitionKey())), new TypeToken<List<CustomFlowSequenceDto>>() {
            }.getType());
            for (CustomFlowSequenceDto c : customFlowSequenceDtoList) {
                CustomFlowVarDto customFlowVarDto = gson.fromJson(gson.toJson(agginessMap.get(c.getAfterFlowTaskId())), CustomFlowVarDto.class);
                FlowTaskResult flowTaskResult = gson.fromJson(gson.toJson(setupMap.get(c.getAfterFlowTaskId())), FlowTaskResult.class);
                flowTaskResult.setFlowId(flowId);
                flowTaskResult.setApproveUserNames(customFlowVarDto.getApproveUserNames());
                flowTaskResultList.add(flowTaskResult);
            }
        }
        taskInfoResult.setRejectSetupList(flowTaskResultList);
        taskInfoResult.setNextFlowTaskResult(nextFlowTaskResult);
        return taskInfoResult;
    }

    /**
     * 获取当前流程信息
     *
     * @param flowId
     * @return
     */
    @Override
    public FlowViewResult getFlowView(Long flowId) {
        TFCustomFlowEntity tfCustomFlowEntity = tfCustomFlowEntityService.findByFlowId(flowId);
        Optional.ofNullable(tfCustomFlowEntity).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("自定义流程实体数据为空"));

        //获取流程id
        List<TFFlowJoin> tfFlowJoinList = tfFlowJoinService.findByFlowEntityId(tfCustomFlowEntity.getId());
        Optional.ofNullable(tfFlowJoinList).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程数据为空"));

        //获取当前流程节点
        TFFlowApprove tfFlowApprove = tfFlowApproveService.findByFlowId(flowId);
        Optional.ofNullable(tfFlowApprove).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程审核数据为空"));

        Map<String, Object> flowProcessVarMap = this.getFlowProcessVarMap(tfCustomFlowEntity);
        Map<String, FlowTaskResult> setupMap = (Map<String, FlowTaskResult>) flowProcessVarMap.get(SystemConstant.SETUP_MAP);

        Gson gson = new Gson();
        FlowTaskResult currFlowTaskResult = null;
        for (Map.Entry<String, FlowTaskResult> entry : setupMap.entrySet()) {
            FlowTaskResult flowTaskResult = gson.fromJson(gson.toJson(entry.getValue()), FlowTaskResult.class);
            if (Objects.nonNull(tfFlowApprove.getSetup()) && flowTaskResult.getSetup().intValue() == tfFlowApprove.getSetup().intValue()) {
                currFlowTaskResult = flowTaskResult;
                currFlowTaskResult.setFlowId(flowId);
                break;
            }
        }

        //获取流程待审批人
        Map<String, CustomFlowVarDto> agginessMap = (Map<String, CustomFlowVarDto>) flowProcessVarMap.get(SystemConstant.AGGINESS_MAP);
        if (Objects.nonNull(tfFlowApprove.getTransferAssignee())) {
            agginessMap = JacksonUtil.readJson(tfFlowApprove.getTransferAssignee(), Map.class);
        }

        //获取流程审批历史
        List<TFFlowLogResult> tfFlowLogResultList = tfFlowLogService.findByObjectId(tfFlowJoinList.get(0).getObjectId());
        if (Objects.nonNull(tfFlowLogResultList) && tfFlowLogResultList.size() > 0) {
            List<TFFlowViewLogResult> flowViewTaskResultList = gson.fromJson(gson.toJson(tfFlowLogResultList), new TypeToken<List<TFFlowViewLogResult>>() {
            }.getType());
            if (Objects.nonNull(currFlowTaskResult)) {
                if (currFlowTaskResult.getSetup() <= 0) {
                    return new FlowViewResult(currFlowTaskResult, flowViewTaskResultList);
                } else {
                    CustomFlowVarDto customFlowVarDto = gson.fromJson(gson.toJson(agginessMap.get(currFlowTaskResult.getTaskKey())), CustomFlowVarDto.class);
                    String nextApproveUsers = flowViewTaskResultList.get(flowViewTaskResultList.size() - 1).getPendApproveUserName();
                    if (Objects.nonNull(customFlowVarDto.getMultipleUserApproveType()) && customFlowVarDto.getMultipleUserApproveType() == CustomFlowMultipleUserApproveTypeEnum.ORDER) {
                        String[] strs = nextApproveUsers.split(",");
                        nextApproveUsers = strs[0];
                    }
                    currFlowTaskResult.setApproveUserNames(nextApproveUsers);
                    return new FlowViewResult(customFlowVarDto.getMultipleUserApproveType(), currFlowTaskResult, flowViewTaskResultList);
                }
            }
        }
        return new FlowViewResult(currFlowTaskResult);
    }

    /**
     * 根据流程类型获取流程节点
     *
     * @param type
     * @param flowId
     * @return
     */
    @Override
    public FlowInfoResult getFlowInfoByType(TFCustomTypeEnum type, Long flowId) {
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        TFCustomFlow tfCustomFlow = null;
        TFCustomFlowEntity tfCustomFlowEntity = null;
        List<FlowTaskResult> flowTaskResultList = null;
        Map<String, Object> flowProcessVarMap = null;
        if (Objects.isNull(flowId)) {
            tfCustomFlow = tfCustomFlowService.findMaxVersion(sysUser.getSchoolId(), null, type);
            Optional.ofNullable(tfCustomFlow).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("未找到自定义流程数据"));
            flowTaskResultList = this.getFlowTaskResult(tfCustomFlow);
            flowProcessVarMap = this.getFlowProcessVarMap(tfCustomFlow);
        } else {
            tfCustomFlowEntity = tfCustomFlowEntityService.findByFlowId(flowId);
            Optional.ofNullable(tfCustomFlowEntity).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("未找到自定义流程实体数据"));
            flowTaskResultList = this.getFlowTaskResult(tfCustomFlowEntity);
            flowProcessVarMap = this.getFlowProcessVarMap(tfCustomFlowEntity);
        }
        Optional.ofNullable(flowProcessVarMap).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("未找到自定义流程变量数据"));
        Map<String, FlowTaskResult> flowTaskResultMap = flowTaskResultList.stream().collect(Collectors.toMap(FlowTaskResult::getTaskKey, Function.identity(), (dto1, dto2) -> dto1));
        Map<String, CustomFlowVarDto> agginessMap = (Map<String, CustomFlowVarDto>) flowProcessVarMap.get(SystemConstant.AGGINESS_MAP);

        Gson gson = new Gson();
        SysRoleGroupMemberMatchParams roleGroupMemberMatchParams = null;
        Map<String, SysRoleGroupMemberMatch> flowRoleGroupMemberMatchMap = null;
        for (FlowTaskResult f : flowTaskResultList) {
            CustomFlowVarDto customFlowVarDto = gson.fromJson(gson.toJson(agginessMap.get(f.getTaskKey())), CustomFlowVarDto.class);
            if (Objects.nonNull(customFlowVarDto)) {
                if (Objects.isNull(customFlowVarDto.getApproveUserNames()) && customFlowVarDto.getApproveUserType() == CustomFlowApproveUserTypeEnum.ROLE) {
                    roleGroupMemberMatchParams = Objects.isNull(roleGroupMemberMatchParams) ? new SysRoleGroupMemberMatchParams() : roleGroupMemberMatchParams;
                    if (Objects.isNull(roleGroupMemberMatchParams.getFlowRoleGroupMemberMatchMap()) || roleGroupMemberMatchParams.getFlowRoleGroupMemberMatchMap().size() == 0) {
                        flowRoleGroupMemberMatchMap = new LinkedHashMap<>();
                    } else {
                        flowRoleGroupMemberMatchMap = roleGroupMemberMatchParams.getFlowRoleGroupMemberMatchMap();
                    }
                    if (flowRoleGroupMemberMatchMap.size() == 0) {
                        flowRoleGroupMemberMatchMap.computeIfAbsent(f.getTaskKey(), v -> new SysRoleGroupMemberMatch(customFlowVarDto.getApproveRoleIds().stream().map(s -> SystemConstant.convertIdToLong(s)).collect(Collectors.toList()), sysUser.getId()));
                    } else {
                        flowRoleGroupMemberMatchMap.computeIfAbsent(f.getTaskKey(), v -> new SysRoleGroupMemberMatch(customFlowVarDto.getApproveRoleIds().stream().map(s -> SystemConstant.convertIdToLong(s)).collect(Collectors.toList())));
                    }
                    roleGroupMemberMatchParams.setFlowRoleGroupMemberMatchMap(flowRoleGroupMemberMatchMap);
                } else {
                    f.setApproveUserNames(customFlowVarDto.getApproveUserNames());
                }
            }
        }
        if (Objects.nonNull(roleGroupMemberMatchParams)) {
            Map<String, SysRoleGroupMemberMatchResult> sysRoleGroupMemberMatchResultMap = sysRoleGroupMemberService.matchList(roleGroupMemberMatchParams);
            if (Objects.nonNull(sysRoleGroupMemberMatchResultMap) && sysRoleGroupMemberMatchResultMap.size() > 0) {
                sysRoleGroupMemberMatchResultMap.forEach((k, v) -> {
                    String userTaskId = k.substring(k.length() - 1, k.length());
                    if (Objects.isNull(v)) {
                        throw ExceptionResultEnum.ERROR.exception("流程第" + userTaskId + "个审批节点没有审批人或成员数据已发生改变，请重新选择！");
                    }
                    int count = sysRoleGroupMemberService.findByIdsCount(v.getSysRoleGroupMemberIdList());
                    if (count == 0 || count != v.getSysRoleGroupMemberIdList().size()) {
                        throw ExceptionResultEnum.ERROR.exception("流程第" + userTaskId + "个审批节点成员数据已发生改变，请重新选择！");
                    }
                    List<String> approveUserNamesList = v.getApproveUserResultList().stream().map(s -> s.getRealName() + "(" + s.getOrgName() + ")").collect(Collectors.toList());
                    FlowTaskResult flowTaskResult = flowTaskResultMap.get(k);
                    flowTaskResult.setApproveUserNames(approveUserNamesList.toString().replaceAll("\\[", "").replaceAll("\\]", "").trim());
                });
            }
        }
        if (Objects.nonNull(tfCustomFlow)) {
            return new FlowInfoResult(tfCustomFlow.getId(), tfCustomFlow.getVersion(), flowTaskResultList);
        } else {
            return new FlowInfoResult(tfCustomFlowEntity.gettFCustomFlowId(), null, flowTaskResultList);
        }
    }

    /**
     * 获取流程变量
     *
     * @param o
     * @return
     */
    protected Map<String, Object> getFlowProcessVarMap(Object o) {
        Optional.ofNullable(o).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("未找到自定义流程数据"));
        Map<String, Object> varMap = null;
        if (o instanceof TFCustomFlow) {
            o = (TFCustomFlow) o;
            varMap = JacksonUtil.readJson(((TFCustomFlow) o).getFlowProcessVar(), Map.class);
        } else if (o instanceof TFCustomFlowEntity) {
            o = (TFCustomFlowEntity) o;
            varMap = JacksonUtil.readJson(((TFCustomFlowEntity) o).getFlowProcessVar(), Map.class);
        }
        Optional.ofNullable(varMap).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("自定义流程变量数据为空"));
        Map<String, Object> flowProcessVarMap = (Map<String, Object>) varMap.get(SystemConstant.FLOW_PROCESS_VAR_MAP);
        Optional.ofNullable(flowProcessVarMap).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("自定义流程节点变量数据为空"));
        return flowProcessVarMap;
    }

    /**
     * 开始任务节点
     *
     * @return
     */
    protected StartEvent createStartEvent() {
        StartEvent startEvent = new StartEvent();
        startEvent.setId(CustomFlowTypeEnum.START.getId());
        startEvent.setName(CustomFlowTypeEnum.START.getTitle());
        return startEvent;
    }

    /**
     * 结束任务节点
     *
     * @return
     */
    protected EndEvent createEndEvent() {
        EndEvent endEvent = new EndEvent();
        endEvent.setId(CustomFlowTypeEnum.END.getId());
        endEvent.setName(CustomFlowTypeEnum.END.getTitle());
        return endEvent;
    }

    /**
     * @param id       对应我们画流程图中节点任务id
     * @param name     节点任务名称
     * @param assignee 任务的执行者(这一块自行决定是否添加每一环节的执行者，若是动态分配的话，可以不用传值)
     * @return
     */
    protected UserTask createUserTask(String id, String name, String assignee) {
        UserTask userTask = new UserTask();
        userTask.setName(name);
        userTask.setId(id);
        userTask.setAssignee(assignee);
        return userTask;
    }

    /**
     * @param id                                    对应我们画流程图中节点任务id
     * @param name                                  节点任务名称
     * @param assignees                             任务的执行者(这一块自行决定是否添加每一环节的执行者，若是动态分配的话，可以不用传值)
     * @param customFlowMultipleUserApproveTypeEnum
     * @return
     */
    protected UserTask createUserTask(String id, String
            name, List<String> assignees, CustomFlowMultipleUserApproveTypeEnum customFlowMultipleUserApproveTypeEnum) {
        UserTask userTask = new UserTask();
        userTask.setName(name);
        userTask.setId(id);

        boolean isSequential = false;
        if (customFlowMultipleUserApproveTypeEnum == CustomFlowMultipleUserApproveTypeEnum.ORDER) {
            userTask = multiWorkFlow.createMultiInstanceLoopCharacteristics(userTask, !isSequential);
        } else if (customFlowMultipleUserApproveTypeEnum == CustomFlowMultipleUserApproveTypeEnum.ALL) {
            userTask = multiWorkFlow.createMultiInstanceLoopCharacteristics(userTask, isSequential);
        } else {
            String someId = userTask.getId().substring(userTask.getId().length() - 1, userTask.getId().length());
            userTask.setCandidateUsers(Arrays.asList(new StringJoiner("").add(MessageFormat.format("{0}{1}{2}", DefaultInstanceConvertToMultiInstance.DEFAULT_ASSIGNEE_LIST_EXP, someId, DefaultInstanceConvertToMultiInstance.EXP_SUFFIX)).toString()));
        }
        return userTask;
    }

    /**
     * 排他网关
     *
     * @param id
     * @param name
     * @return
     */
    protected ExclusiveGateway createExclusiveGateway(String id, String name) {
        ExclusiveGateway exclusiveGateway = new ExclusiveGateway();
        exclusiveGateway.setId(id);
        exclusiveGateway.setName(name);
        return exclusiveGateway;
    }

    /**
     * 并行网关
     *
     * @param id
     * @param name
     * @return
     */
    protected ParallelGateway createParallelGateway(String id, String name) {
        ParallelGateway parallelGateway = new ParallelGateway();
        parallelGateway.setId(id);
        parallelGateway.setName(name);
        return parallelGateway;
    }

    /**
     * @param from                连线来源节点
     * @param to                  连线目标节点
     * @param id
     * @param name                连线名称(可不填)
     * @param conditionExpression 网关每一种线路走向的条件表达式
     * @return
     */
    protected SequenceFlow createSequenceFlow(String from, String to, String id, String name, String
            conditionExpression) {
        SequenceFlow flow = new SequenceFlow();
        flow.setSourceRef(from);
        flow.setTargetRef(to);
        flow.setId(id);
        flow.setName(name);
        if (Objects.nonNull(conditionExpression)) {
            flow.setConditionExpression(conditionExpression);
        }
        return flow;
    }
}