简单的springboot整合activiti5-serviceImpl部分(1)

简单的springboot整合activiti5.22.0-serviceImpl部分(1)

原来的流程serviceImpl部分代码过多,所以此处单独记录一下,此处记录的是serviceImpl第一部分代码

package cn.git.workflow.service.impl;

import cn.git.cache.api.BaseCacheApi;
import cn.git.cache.entity.CacheTcSysCodes;
import cn.git.common.exception.ServiceException;
import cn.git.common.page.PageBean;
import cn.git.common.page.PaginationContext;
import cn.git.common.util.OracleInQueryUtil;
import cn.git.common.util.WebUtil;
import cn.git.loan.dto.LoanWorkFlowDTO;
import cn.git.manage.api.UserApi;
import cn.git.manage.dto.*;
import cn.git.query.dto.WorkFlowJumpDTO;
import cn.git.workflow.constant.WorkFlowConstant;
import cn.git.workflow.constant.WorkFlowServerConstant;
import cn.git.workflow.dto.*;
import cn.git.workflow.dto.activiti.WorkFlowActHisActInstListDTO;
import cn.git.workflow.dto.activiti.WorkFlowActHisProcessListDTO;
import cn.git.workflow.dto.activiti.WorkFlowLoadTemplateDTO;
import cn.git.workflow.entity.*;
import cn.git.workflow.entity.activiti.WorkFlowLoadTemplate;
import cn.git.workflow.feign.*;
import cn.git.workflow.mapper.*;
import cn.git.workflow.mapstruct.ActivitiConvert;
import cn.git.workflow.mapstruct.WorkFlowConvert;
import cn.git.workflow.page.PageUtil;
import cn.git.workflow.page.WorkFlowPage;
import cn.git.workflow.service.WorkFlowService;
import cn.git.workflow.util.*;
import cn.git.workflow.vo.WorkFlowTraceVO;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.*;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricActivityInstanceQuery;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricProcessInstanceQuery;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmActivity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.task.TaskDefinition;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.Model;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.activiti.image.ProcessDiagramGenerator;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.DatatypeConverter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.*;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 流程server 通用serviceImpl
 *
 * @program: bank-credit-sy
 * @author: lixuchun
 * @create: 2021-06-08
 */
@Service
@Slf4j
public class WorkFlowServiceImpl implements WorkFlowService {

    /**
     * todo: 流程模块nacos配置,上线时间 yyyy-MM-dd 格式 暂时设定为2022-08-29,后期修改为上线时间
     * 主要在流程历史意见信息查看部分使用
     */
    @Value("${workflow.upper.date}")
    private String nacosUpperDate;

    @Autowired
    private BaseCacheApi baseCacheApi;

    @Autowired
    private LoanWorkFlowApiClient loanWorkFlowApiClient;

    @Autowired
    private WorkFlowFactory workFlowFactory;

    @Autowired
    private TbConVoteMapper tbConVoteMapper;

    @Autowired
    private TbSysFlowPositionMapper tbSysFlowPositionMapper;

    @Autowired
    private TbSysFlowPositionDetailMapper tbSysFlowPositionDetailMapper;

    @Autowired
    private WfmidAppProcessInstanceMapper wfmidAppProcessInstanceMapper;

    @Autowired
    private WfmidAppProcessInstanceHisMapper wfmidAppProcessInstanceHisMapper;

    @Autowired
    private WfmidAppTaskInstanceMapper wfmidAppTaskInstanceMapper;

    @Autowired
    private WfmidAppTaskInstanceHisMapper wfmidAppTaskInstanceHisMapper;

    @Autowired
    private WfmidProcessInstanceMapper wfmidProcessInstanceMapper;

    @Autowired
    private WfmidProcessInstanceHisMapper wfmidProcessInstanceHisMapper;

    @Autowired
    private WfmidTaskInstanceMapper wfmidTaskInstanceMapper;

    @Autowired
    private WfmidTaskInstanceHisMapper wfmidTaskInstanceHisMapper;

    @Autowired
    private TbSysUnfinishedFlowMapper tbSysUnfinishedFlowMapper;

    @Autowired
    private TbSysBackPositionInfoMapper tbSysBackPositionInfoMapper;

    @Autowired
    private WorkFlowUtil workFlowUtil;

    @Autowired
    private WorkFlowConvert workFlowConvert;

    @Autowired
    private PageUtil pageUtil;

    @Autowired
    private WebUtil webUtil;

    @Autowired
    private OrganizationApiFeignClient organizationApiFeignClient;

    @Autowired
    private LoanApiFeignClient loanApiFeignClient;

    @Autowired
    private ManagementApiClient managementApiClient;

    @Autowired
    private AccountApiClient accountApiClient;

    @Autowired
    private OracleInQueryUtil oracleInQueryUtil;

    @Autowired
    private UserApi userApi;

    @Autowired
    private AfterLoanClient afterLoanClient;

    @Autowired
    private QueryWorkFlowApiFeignClient queryWorkFlowApiFeignClient;

    @Autowired
    private ManageForWorkflowApiClient manageForWorkflowApiClient;

    @Autowired
    private ActHiTaskinstBackMapper actHiTaskinstBackMapper;

    @Autowired
    private ActHiActinstBackMapper actHiActinstBackMapper;

    @Autowired
    private ActHiCommentBackMapper actHiCommentBackMapper;

    @Autowired
    private ActHiProcinstBackMapper actHiProcinstBackMapper;

    @Autowired
    private ActHiProcinstMapper actHiProcinstMapper;

    @Autowired
    private TbSysBackPositionInfoHisMapper tbSysBackPositionInfoHisMapper;

    @Autowired
    private TbSysUnfinishedFlowHisMapper tbSysUnfinishedFlowHisMapper;

    @Autowired
    private ActHiVarinstBackMapper actHiVarinstBackMapper;

    @Autowired
    private ActivitiConvert activitiConvert;

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private ProcessEngine processEngine;

    @Autowired
    private HistoryService historyService;

    @Autowired
    private IdentityService identityService;

    @Autowired
    private ActivitiUtil activitiUtil;

    @Autowired
    private TbSysWorkflowJumpMapper tbSysWorkflowJumpMapper;

    @Autowired
    private HttpServletResponse response;

    /**
     * 代办未分类列表信息count查询
     *
     * @param userCd 柜员号
     * @param orgCd  机构号
     * @return WorkFlowPage 分页信息
     */
    @Override
    public WorkFlowPage<List<Map<String, Object>>> findWorkCountFlowList(String userCd, String orgCd) {
        // 最终返回数据格式
        Map<String, Integer> countMap = new HashMap<>(WorkFlowServerConstant.DEFAULT_MAP_SIZE);

        // 设置查询参数userId为orgCd:userCd
        String userId = StrUtil.format(WorkFlowServerConstant.USER_ID_APPEND_TEMPLATE, userCd, orgCd);
        // 分页查询初始化任务列表信息,processVariableValueEquals可以对参数进行过滤,此处用不到
        TaskQuery taskQuery = taskService.createTaskQuery()
                // 当前处理人
                .taskAssignee(userId)
                // 活动流程任务
                .active()
                // 查询包含参数信息,可以过滤使用
                .includeProcessVariables()
                // 创建时间排序
                .orderByTaskCreateTime()
                // 倒序排序
                .desc();

        // 进行数据查询,此处无需分页处理,直接查询全部
        List<Task> taskList = taskQuery.list();

        // 非空判断
        if (ObjectUtil.isNotEmpty(taskList)) {
            taskList.forEach(task -> {
                // 获取任务参数信息
                Map<String, Object> paramMap = task.getProcessVariables();
                String bizType = StrUtil.emptyToDefault(
                        (String) paramMap.get(WorkFlowServerConstant.BIZ_TYPE_FLAG), StrUtil.EMPTY);
                String processKey = StrUtil.emptyToDefault(
                        (String) paramMap.get(WorkFlowServerConstant.PROCESS_KEY_FLAG), StrUtil.EMPTY);
                if (StrUtil.isNotBlank(bizType)
                        && !processKey.startsWith(WorkFlowServerConstant.STORE_PREFIX)
                        && !processKey.toLowerCase().startsWith(WorkFlowServerConstant.RSK_PREFIX)) {
                    workFlowUtil.countWorkFlow(countMap, bizType);
                }
            });
        }

        // 设置最终返回结果集 List<Map<String, Object>> Map-> bizType,bizName,count
        List<Map<String, Object>> workMapList = new ArrayList<>();
        countMap.forEach((key, value) -> {
            Map<String, Object> workMap = new HashMap<>(3);
            workMap.put(WorkFlowServerConstant.BIZ_TYPE_FLAG, key);
            workMap.put(WorkFlowServerConstant.COUNT_FLAG, value);
            // 通过缓存平台获取缓存平台对应业务种类名称
            WorkFlowProductEnum productEnum = workFlowUtil.getProductEnumByBizType(key);
            if (ObjectUtil.isNotNull(productEnum)) {
                workMap.put(WorkFlowServerConstant.BIZ_NAME_FLAG, productEnum.getBizTypeName());
            } else {
                log.info("流程初始化获取WorkFlowProductEnum失败,对应key为[{}]!", key);
            }
            workMapList.add(workMap);
        });

        return pageUtil.setFlowListPage(workMapList, PaginationContext.getPageNum(), PaginationContext.getPageSize());
    }

    /**
     * 代办未分类列表信息count查询,新增系统标识参数
     *
     * @param userCd     柜员号
     * @param orgCd      机构号
     * @param systemFlag 系统标识
     * @return WorkFlowPage 分页信息
     * @throws cn.git.workflow.webservice.query.BpmException_Exception 流程异常
     */
    @Override
    public WorkFlowPage<List<Map<String, Object>>> findSysWorkCountFlowList(String userCd,
                                                                            String orgCd,
                                                                            String systemFlag) {
        // 最终返回数据格式
        Map<String, Integer> countMap = new HashMap<>(WorkFlowServerConstant.DEFAULT_MAP_SIZE);

        // 设置查询参数userId为orgCd:userCd
        String userId = StrUtil.format(WorkFlowServerConstant.USER_ID_APPEND_TEMPLATE, userCd, orgCd);
        // 分页查询初始化任务列表信息,processVariableValueEquals可以对参数进行过滤,此处用不到
        TaskQuery taskQuery = taskService.createTaskQuery()
                // 当前处理人
                .taskAssignee(userId)
                // 活动流程任务
                .active()
                // 查询包含参数信息,可以过滤使用
                .includeProcessVariables()
                // 创建时间排序
                .orderByTaskCreateTime()
                // 倒序排序
                .desc();

        // 进行数据查询,此处无需分页处理,直接查询全部
        List<Task> taskList = taskQuery.list();

        // 空值判定
        if (ObjectUtil.isNotEmpty(taskList)) {
            taskList.forEach(task -> {
                // 获取参数信息,获取bizType以及流程定义key
                Map<String, Object> paramMap = task.getProcessVariables();
                String bizType = StrUtil.emptyToDefault(
                        (String) paramMap.get(WorkFlowServerConstant.BIZ_TYPE_FLAG), StrUtil.EMPTY);
                String processKey = StrUtil.emptyToDefault(
                        (String) paramMap.get(WorkFlowServerConstant.PROCESS_KEY_FLAG), StrUtil.EMPTY);
                if (StrUtil.isBlank(systemFlag) || WorkFlowServerConstant.FLOW_TYPE_0.equals(systemFlag)) {
                    // 信贷系统
                    if (StrUtil.isNotBlank(bizType)
                            && !processKey.startsWith(WorkFlowServerConstant.STORE_PREFIX)
                            && !processKey.toLowerCase().startsWith(WorkFlowServerConstant.RSK_PREFIX)) {
                        workFlowUtil.countWorkFlow(countMap, bizType);
                    }
                } else if (WorkFlowServerConstant.STRING_NUM_1.equals(systemFlag)) {
                    // 风险系统
                    if (StrUtil.isNotBlank(bizType)
                            && processKey.toLowerCase().startsWith(WorkFlowServerConstant.RSK_PREFIX)) {
                        workFlowUtil.countWorkFlow(countMap, bizType);
                    }
                } else if (WorkFlowServerConstant.STRING_NUM_2.equals(systemFlag)) {
                    // 储备系统
                    if (StrUtil.isNotBlank(bizType)
                            && processKey.toLowerCase().startsWith(WorkFlowServerConstant.STORE_PREFIX)) {
                        workFlowUtil.countWorkFlow(countMap, bizType);
                    }
                }
            });
        }

        // 设置最终返回结果集 List<Map<String, Object>> Map-> bizType,bizName,count
        List<Map<String, Object>> workMapList = new ArrayList<>();
        countMap.forEach((key, value) -> {
            Map<String, Object> workMap = new HashMap<>(3);
            workMap.put(WorkFlowServerConstant.BIZ_TYPE_FLAG, key);
            workMap.put(WorkFlowServerConstant.COUNT_FLAG, value);
            // 通过缓存平台获取缓存平台对应业务种类名称
            WorkFlowProductEnum productEnum = workFlowUtil.getProductEnumByBizType(key);
            if (ObjectUtil.isNotNull(productEnum)) {
                workMap.put(WorkFlowServerConstant.BIZ_NAME_FLAG, productEnum.getBizTypeName());
            } else {
                log.info("流程初始化获取WorkFlowProductEnum失败,对应key为[{}]!", key);
            }
            workMapList.add(workMap);
        });

        return pageUtil.setFlowListPage(workMapList, PaginationContext.getPageNum(), PaginationContext.getPageSize());
    }

    /**
     * 具体业务代办任务详情列表查询
     *
     * @param workFlowUndoTaskDTO undoDto
     * @return WorkFlowPage 代办详情列表信息
     */
    @Override
    public WorkFlowPage<WorkFlowUndoTask> findUndoWorkTaskDetailList(WorkFlowUndoTaskDTO workFlowUndoTaskDTO) {
        log.info("具体代办业务查询参数[{}]", workFlowUndoTaskDTO.toString());
        // 获取业务信息
        WorkFlowProductEnum workFlowProductEnum = workFlowUtil.getProductEnumByBizType(workFlowUndoTaskDTO.getBizType());
        if (ObjectUtil.isNull(workFlowProductEnum)) {
            throw new ServiceException(StrUtil.format("通过流程bizType[{}]获取流程模板信息为空!",
                    workFlowUndoTaskDTO.getBizType()));
        }

        // 设置查询参数userId为orgCd:userCd
        String userId = StrUtil.format(WorkFlowServerConstant.USER_ID_APPEND_TEMPLATE,
                workFlowUndoTaskDTO.getUserCd(),
                workFlowUndoTaskDTO.getOrgCd());

        // 分页查询初始化任务列表信息,processVariableValueEquals可以对参数进行过滤,此处用不到
        TaskQuery taskQuery = taskService.createTaskQuery()
                // 当前处理人
                .taskAssignee(userId)
                // 活动流程任务
                .active()
                // 查询包含参数信息,可以过滤使用
                .includeProcessVariables()
                // 创建时间排序
                .orderByTaskCreateTime()
                // 倒序排序
                .desc();

        // 进行数据查询,此处无需分页处理,直接查询全部
        List<Task> taskList = taskQuery.list();

        // 响应数据信息
        List<WorkFlowUndoTask> workFlowDtoList = new ArrayList<>();

        // 非空判定
        if (ObjectUtil.isNotEmpty(taskList)) {
            // 获取缓存参数信息,获取bizType对应的中文转义字段名称
            List<String> codeTypeCdList = new ArrayList<>();
            codeTypeCdList.add("ProcessTypeCd");
            Map<String, String> codeInfoMap = baseCacheApi.getTypeCdValueKeyMap(codeTypeCdList);
            // 获取柜员名称以及机构信息
            List<String> userInfoList =taskList.stream().map(task -> {
                Map<String, Object> processVariableMap = task.getProcessVariables();
                if (workFlowProductEnum.getBizType()
                        .equals(StrUtil.toString(processVariableMap.get(WorkFlowServerConstant.BIZ_TYPE_FLAG)))) {
                    return StrUtil.toString(processVariableMap.get(WorkFlowServerConstant.CREATOR_FLAG));
                } else {
                    return null;
                }
            }).collect(Collectors.toList()).stream()
                    .distinct()
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());

            // 获取用户信息列表
            List<String> userCdList = userInfoList.stream().map(userInfo -> {
                String[] creatorInfo = userInfo.split(WorkFlowServerConstant.SPLIT_FLAG);
                return creatorInfo[0];
            }).collect(Collectors.toList());
            // 判断为空
            if (ObjectUtil.isEmpty(userCdList)) {
                return pageUtil.setFlowListPage(workFlowDtoList, PaginationContext.getPageNum(),
                        PaginationContext.getPageSize());
            }
            List<ManageUserDTO> userDTOList = managementApiClient.listUserInfoByUserCd(userCdList);
            Map<String, String> userInfoMap = userDTOList.stream().collect(
                    Collectors.toMap(ManageUserDTO::getUserCd, ManageUserDTO::getUserName, (k1, k2) -> k2)
            );

            // 获取机构信息列表
            List<String> orgList = userInfoList.stream().map(userInfo -> {
                String[] creatorInfo = userInfo.split(WorkFlowServerConstant.SPLIT_FLAG);
                return creatorInfo[1];
            }).collect(Collectors.toList());
            ManageOrganizationListDTO orgDTO = organizationApiFeignClient.listInfoByOrgCdList(orgList);
            List<ManageOrganizationDTO> organizationInfoList = orgDTO.getOrganizationInfoList();
            Map<String, String> orgInfoMap = organizationInfoList.stream().collect(
                    Collectors.toMap(ManageOrganizationDTO::getOrgCd,
                            ManageOrganizationDTO::getOrgName, (k1, k2) -> k2)
            );

            List<WorkFlowUndoTask> finalWorkFlowDtoList = workFlowDtoList;
            taskList.forEach(task -> {
                // 获取参数信息
                Map<String, Object> processVariableMap = task.getProcessVariables();

                // 类型判定
                if (workFlowProductEnum.getBizType()
                        .equals(StrUtil.toString(processVariableMap.get(WorkFlowServerConstant.BIZ_TYPE_FLAG)))) {
                    WorkFlowUndoTask undoTask = new WorkFlowUndoTask();
                    undoTask.setBizNo(StrUtil.toString(processVariableMap.get(WorkFlowServerConstant.BIZ_ID_FLAG)));
                    undoTask.setCustomerName(
                            StrUtil.toString(processVariableMap.get(WorkFlowServerConstant.CUSTOMER_NAME_FLAG)));
                    // 缓存信息获取码值中文名称
                    String codeName = codeInfoMap.get("ProcessTypeCd".concat(StrUtil.UNDERLINE)
                            .concat(workFlowUndoTaskDTO.getBizType()));
                    undoTask.setBizType(workFlowUndoTaskDTO.getBizType());
                    undoTask.setProcessTypeName(codeName);
                    WorkFlowProductEnum productEnum = workFlowUtil
                            .getProductEnumByBizType(workFlowUndoTaskDTO.getBizType());
                    // 设置业务名称
                    undoTask.setBizName(productEnum.getBizTypeName());
                    // 创建柜员
                    String[] creatorInfo = StrUtil.toString(processVariableMap.get(WorkFlowServerConstant.CREATOR_FLAG))
                            .split(WorkFlowServerConstant.SPLIT_FLAG);
                    undoTask.setProcessCreator(creatorInfo[0]);
                    undoTask.setProcessCreatorName(userInfoMap.get(creatorInfo[0]));
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    // 机构信息
                    undoTask.setOrgCd(creatorInfo[1]);
                    undoTask.setOrgName(orgInfoMap.get(creatorInfo[1]));
                    // 执行ID processVariableMap.get(WorkFlowServerConstant.EXECUTION_ID_FLAG).toString() 修改为task获取
                    undoTask.setExecutionId(task.getExecutionId());
                    // 创建时间字符串
                    undoTask.setProcessCreateTimeStr(sdf.format(task.getCreateTime()));
                    undoTask.setProcessCreateTime(task.getCreateTime());
                    // 岗位id
                    undoTask.setActivityId(task.getName());
                    // 任务id
                    undoTask.setTaskId(task.getId());

                    // 客户名称校验
                    if (StrUtil.isNotBlank(workFlowUndoTaskDTO.getCustomerName())) {
                        String undoCustomerName = StrUtil.toString(processVariableMap.get(WorkFlowServerConstant.CUSTOMER_NAME_FLAG));
                        if (StrUtil.isNotBlank(undoCustomerName)
                                && undoCustomerName.contains(workFlowUndoTaskDTO.getCustomerName())) {
                            finalWorkFlowDtoList.add(undoTask);
                        }
                    } else {
                        finalWorkFlowDtoList.add(undoTask);
                    }
                }
            });
        }

        return pageUtil.setFlowListPage(workFlowDtoList, PaginationContext.getPageNum(),
                PaginationContext.getPageSize());
    }

    /**
     * 代办任务点击,贷审会审批结果校验,任务详情页面跳转
     *
     * @param taskId 任务编号
     * @param userCd 用户柜员号
     * @param orgCd  机构号
     * @return WorkFlowUndoTaskDetailDTO taskInfo详情
     */
    @Override
    public WorkFlowUndoTaskDetailDTO findTaskDetailInfo(String taskId, String userCd, String orgCd) {

        log.info("代办任务点击,贷审会审批结果校验,任务详情页面跳转参数taskId[{}], userCd[{}], orgCd[{}]",
                taskId, userCd, orgCd);

        // 最终返回dto
        WorkFlowUndoTaskDetailDTO undoTaskDetailDto = new WorkFlowUndoTaskDetailDTO();
        undoTaskDetailDto.setTaskId(taskId);
        undoTaskDetailDto.setOrgCd(orgCd);

        // 通过taskId获取任务信息
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        // 非空判定
        if (ObjectUtil.isNotNull(task)) {
            // 获取节点名称eg: usertask01以及流程实例id
            String activityId = task.getName();
            String processInstanceId = task.getProcessInstanceId();
            undoTaskDetailDto.setProcessId(processInstanceId);

            // 通过流程id获取流程实例信息,设置返回路径以及流程模板等信息
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                    .processInstanceId(processInstanceId)
                    .includeProcessVariables()
                    .singleResult();

            // 业务编号
            String bizNo = null;
            // 非空判定
            if (ObjectUtil.isNotNull(processInstance)) {
                // 获取业务编号以及流程名称
                bizNo = processInstance.getBusinessKey();
                String templateNum = processInstance.getProcessDefinitionName();
                List<Map<String, String>> urlNameMapList = tbSysFlowPositionDetailMapper.listSysFlowUrlName(templateNum,
                        activityId);
                if (ObjectUtil.isNotEmpty(urlNameMapList)) {
                    // 返回url
                    undoTaskDetailDto.setUri(urlNameMapList.get(0).get(WorkFlowServerConstant.URL_NAME_FLAG));
                    // 返回当前登录岗位对应流程模板中节点id
                    undoTaskDetailDto.setCurrentActivityId(urlNameMapList.get(0)
                            .get(WorkFlowServerConstant.ACTIVITI_ID_FLAG));
                }
                // 获取参数信息
                Map<String, Object> processVariables = processInstance.getProcessVariables();
                processVariables.put(WorkFlowServerConstant.ACTIVITY_NAME_FLAG, activityId);
                undoTaskDetailDto.setBizNo(bizNo);
                undoTaskDetailDto.setVariableMap(processVariables);
            }

            // 判断只有“贷审会秘书录结果岗”,“有权签批岗”,“最高签批岗”进行获取贷审会信息。
            if (WorkFlowServerConstant.LOAN_MEET_SECRETARY_RESULT.equals(activityId.substring(WorkFlowServerConstant.INT_NUM_2))
                    || activityId.contains(WorkFlowServerConstant.MEETING_RESULT_POSITION)
                    || WorkFlowServerConstant.HAVE_SIGN_APPROVE.equals(activityId.substring(WorkFlowServerConstant.INT_NUM_2))
                    || WorkFlowServerConstant.MOST_SIGN_APPROVE.equals(activityId.substring(WorkFlowServerConstant.INT_NUM_2))
                    || WorkFlowServerConstant.PROVINCE_REVIEW_APPROVE.equals(activityId)
                    || WorkFlowServerConstant.PROVINCE_CHECK_APPROVE.equals(activityId)) {
                // 代办任务点击贷审会校验,最终会返回check结果
                QueryWrapper<TbConVote> queryWrapper = new QueryWrapper<>();
                queryWrapper.lambda().eq(TbConVote::getBizNum, bizNo)
                        .eq(TbConVote::getStatus, WorkFlowServerConstant.VOTE_STATUS_ACTIVE)
                        .orderByDesc(TbConVote::getVoteNum);
                List<TbConVote> voteList = tbConVoteMapper.selectList(queryWrapper);
                if (ObjectUtil.isNotEmpty(voteList)) {
                    VoteCheckDTO voteDto = workFlowUtil.checkVoteMeetingResult(voteList, orgCd);
                    if (StrUtil.isNotBlank(voteDto.getErrorMessage())) {
                        undoTaskDetailDto.setErrorMessage(voteDto.getErrorMessage());
                        return undoTaskDetailDto;
                    }
                    undoTaskDetailDto.setVoteCheckDTO(voteDto);
                    // 0 没有发起会议 1发起了会议
                    undoTaskDetailDto.setVoteMessage("1");
                } else {
                    // 0 没有发起会议 1发起了会议
                    undoTaskDetailDto.setVoteMessage("0");
                }
            }
        }

        return undoTaskDetailDto;
    }

    /**
     * 获取流程图
     *
     * @param processId
     * @return
     */
    @Override
    public String findProcessPic(String processId) throws IOException {
        // 获取流程实例信息
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(processId)
                .singleResult();

        // 通过流程定义id获取流程定义信息
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionId(processInstance.getProcessDefinitionId())
                .singleResult();

        // 获取流程引擎配置信息
        ProcessEngineConfiguration processEngineConfiguration = processEngine.getProcessEngineConfiguration();
        Context.setProcessEngineConfiguration((ProcessEngineConfigurationImpl) processEngineConfiguration);

        // 获取流程图生成器
        ProcessDiagramGenerator diagramGenerator = processEngineConfiguration.getProcessDiagramGenerator();
        ProcessDefinitionEntity definitionEntity = (ProcessDefinitionEntity)repositoryService
                .getProcessDefinition(processDefinition.getId());

        // 历史信息获取
        List<HistoricActivityInstance> highLightedActivitList = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(processId)
                .list();

        // 高亮环节id集合
        List<String> highLightedActivitis = new ArrayList<>();
        // 高亮线路id集合
        List<String> highLightedFlows = getHighLightedFlows(definitionEntity,highLightedActivitList);

        highLightedActivitList.forEach(tempActivity -> {
            String activityId = tempActivity.getActivityId();
            highLightedActivitis.add(activityId);
        });

        //中文显示的是口口口,设置字体就好了
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
        InputStream inputStream = diagramGenerator.generateDiagram(bpmnModel,
                "png",
                highLightedActivitis,
                highLightedFlows,
                "宋体",
                "宋体",
                "宋体",
                null,
                1.0);

        // 获取图片的二进制数据
        byte[] picByte = IOUtils.toByteArray(inputStream);
        return DatatypeConverter.printBase64Binary(picByte);
    }

    /**
     * 获取高亮线
     *
     * @param processDefinitionEntity
     * @param historicActivityInstances
     * @return
     */
    public List<String> getHighLightedFlows(ProcessDefinitionEntity processDefinitionEntity,
                                            List<HistoricActivityInstance> historicActivityInstances) {
        // 用以保存高亮的线flowId
        List<String> highFlows = new ArrayList<>();
        // 对历史流程节点进行遍历
        for (int i = 0; i < historicActivityInstances.size() - 1; i++) {
            ActivityImpl activityImpl = processDefinitionEntity.findActivity(historicActivityInstances.get(i)
                            // 得到节点定义的详细信息
                            .getActivityId());
            // 用以保存后需开始时间相同的节点
            List<ActivityImpl> sameStartTimeNodes = new ArrayList<>();
            ActivityImpl sameActivityImpl1 = processDefinitionEntity.findActivity(historicActivityInstances.get(i + 1)
                            .getActivityId());
            // 将后面第一个节点放在时间相同节点的集合里
            sameStartTimeNodes.add(sameActivityImpl1);

            // 取出节点的所有出去的线
            for (int j = i + 1; j < historicActivityInstances.size() - 1; j++) {
                // 后续第一个节点
                HistoricActivityInstance activityImpl1 = historicActivityInstances.get(j);
                // 后续第二个节点
                HistoricActivityInstance activityImpl2 = historicActivityInstances.get(j + 1);
                if (activityImpl1.getStartTime().equals(activityImpl2.getStartTime())) {
                    // 如果第一个节点和第二个节点开始时间相同保存
                    ActivityImpl sameActivityImpl2 = processDefinitionEntity.findActivity(activityImpl2.getActivityId());
                    sameStartTimeNodes.add(sameActivityImpl2);
                } else {
                    // 有不相同跳出循环
                    break;
                }
            }
            // 取出节点的所有出去的线
            List<PvmTransition> pvmTransitions = activityImpl.getOutgoingTransitions();
            for (PvmTransition pvmTransition : pvmTransitions) {
                // 对所有的线进行遍历
                ActivityImpl pvmActivityImpl = (ActivityImpl) pvmTransition.getDestination();
                // 如果取出的线的目标节点存在时间相同的节点里,保存该线的id,进行高亮显示
                if (sameStartTimeNodes.contains(pvmActivityImpl)) {
                    highFlows.add(pvmTransition.getId());
                }
            }
        }
        return highFlows;
    }

    /**
     * 开始一个新流程
     *
     * @param startProcessDTO 流程参数
     * @return Map<String, Object> 流程发起参数信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> startProcess(WorkFlowStartProcessDTO startProcessDTO) {
        log.info("开始一个新流程参数信息startProcessDTO[{}]", startProcessDTO.toString());

        // 拼装流程发起参数
        String userId = StrUtil.format(WorkFlowServerConstant.USER_ID_APPEND_TEMPLATE, startProcessDTO.getUserCd(),
                startProcessDTO.getOrgCd());
        Map<String, Object> variableMap = startProcessDTO.getVariableMap();
        // 流程发起用户id
        variableMap.put(WorkFlowServerConstant.BIZ_TYPE_FLAG, startProcessDTO.getWorkFlowProductEnum().getBizType());
        // 流程业务名称
        variableMap.put(WorkFlowServerConstant.PRODUCT_TYPE_FLAG, startProcessDTO.getWorkFlowProductEnum().getBizTypeName());
        // 流程发起人
        variableMap.put(WorkFlowServerConstant.CREATOR_FLAG, userId);
        // 客户类型 固定 “2” 法人
        variableMap.put(WorkFlowServerConstant.CUSTOMER_TYPE_FLAG, WorkFlowServerConstant.STRING_NUM_2);
        // 客户名称
        variableMap.put(WorkFlowServerConstant.CUSTOMER_NAME_FLAG, startProcessDTO.getCustomerName());
        // 客户编号
        variableMap.put(WorkFlowServerConstant.CUSTOMER_NUM_FLAG, startProcessDTO.getCustomerNum());
        // 业务编号
        variableMap.put(WorkFlowServerConstant.BIZ_ID_FLAG, startProcessDTO.getBizId());
        log.info(String.format("开始一个新流程发送参数: %s", JSONObject.toJSONString(variableMap)));
        // 工作流引擎会基于这个设置的用户ID来检查用户是否有权限执行特定的操作,比如任务分配给自己或者其他人
        identityService.setAuthenticatedUserId(userId);
        // 发起流程
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(
                startProcessDTO.getWorkFlowProductEnum().getTemplateId(),
                startProcessDTO.getBizId(),
                variableMap);

        // 获取当前任务列表,刚刚发起业务,应该只有一个值
        List<Task> list = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).list();
        Map<String, Object> returnVariableMap = new HashMap<>();
        if (ObjectUtil.isNotEmpty(list)) {
            Task currentTask = list.get(0);
            returnVariableMap.put(WorkFlowServerConstant.TASK_ID_FLAG, currentTask.getId());
            returnVariableMap.put(WorkFlowServerConstant.ACTIVITY_NAME_FLAG, currentTask.getName());
            returnVariableMap.put(WorkFlowServerConstant.TASK_DEF_KEY, currentTask.getTaskDefinitionKey());
            returnVariableMap.put(WorkFlowServerConstant.PROCESS_ID_FLAG, processInstance.getProcessInstanceId());
        }

        // 新增业务插入到在途业务表中
        TbSysUnfinishedFlow tbSysUnfinishedFlow = new TbSysUnfinishedFlow();
        tbSysUnfinishedFlow.setId(IdUtil.simpleUUID());
        tbSysUnfinishedFlow.setCustomerNum(startProcessDTO.getCustomerNum());
        tbSysUnfinishedFlow.setCustomerName(startProcessDTO.getCustomerName());
        tbSysUnfinishedFlow.setBizNo(startProcessDTO.getBizId());
        tbSysUnfinishedFlow.setProcessId(processInstance.getProcessInstanceId());
        tbSysUnfinishedFlow.setBizName(startProcessDTO.getWorkFlowProductEnum().getBizTypeName());
        if (ObjectUtil.isNotNull(startProcessDTO.getWorkFlowSysEnum())) {
            tbSysUnfinishedFlow.setSystemFlag(startProcessDTO.getWorkFlowSysEnum().getSystemFlag());
        } else {
            tbSysUnfinishedFlow.setSystemFlag(WorkFlowSysEnum.DICS.getSystemFlag());
        }
        tbSysUnfinishedFlowMapper.insert(tbSysUnfinishedFlow);

        // 开始插入退回上调查复核岗对应所需信息,包含流程模板编号,以及processId,柜员编号机构号等
        TbSysBackPositionInfo tbSysBackPositionInfo = new TbSysBackPositionInfo();
        tbSysBackPositionInfo.setId(IdUtil.simpleUUID());
        tbSysBackPositionInfo.setProcessId(
                StrUtil.toString(returnVariableMap.get(WorkFlowServerConstant.PROCESS_ID_FLAG)));
        tbSysBackPositionInfo.setWorkFlowTemplateId(startProcessDTO.getWorkFlowProductEnum().getTemplateId());
        tbSysBackPositionInfo.setOptionUserCd(startProcessDTO.getUserCd());
        tbSysBackPositionInfo.setOptionOrgCd(startProcessDTO.getOrgCd());
        tbSysBackPositionInfo.setActivitiId(WorkFlowServerConstant.USER_TASK_FLAG_START);
        tbSysBackPositionInfo.setSubmitTime(new Date());
        tbSysBackPositionInfo.setBizNo(startProcessDTO.getBizId());
        tbSysBackPositionInfo.setIsDel(WorkFlowServerConstant.FLOW_TYPE_1);
        tbSysBackPositionInfoMapper.insert(tbSysBackPositionInfo);
        return returnVariableMap;
    }

    /**
     * 撤销流程
     *
     * @param workFlowCancelDTO 流程撤销dto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelProcessByProcessId(WorkFlowCancelDTO workFlowCancelDTO) {
        log.info("开始调用撤销流程方法,撤销参数信息[{}]", JSONObject.toJSONString(workFlowCancelDTO));

        // 拼装流程撤销参数
        String userId = StrUtil.format(WorkFlowServerConstant.USER_ID_APPEND_TEMPLATE,
                workFlowCancelDTO.getUserCd(),
                workFlowCancelDTO.getOrgCd());

        // 删除在途业务
        QueryWrapper<TbSysUnfinishedFlow> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TbSysUnfinishedFlow::getBizNo, workFlowCancelDTO.getBizId());
        tbSysUnfinishedFlowMapper.delete(queryWrapper);

        // 删除退出上一岗位信息内容
        UpdateWrapper<TbSysBackPositionInfo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().eq(TbSysBackPositionInfo::getProcessId, workFlowCancelDTO.getProcessId());
        tbSysBackPositionInfoMapper.delete(updateWrapper);

        // 权限认证
        identityService.setAuthenticatedUserId(userId);

        // 开始进行业务撤销
        runtimeService.deleteProcessInstance(workFlowCancelDTO.getProcessId(),
                WorkFlowServerConstant.DEFAULT_CANCEL_REASON);
    }

    /**
     * 回退流程到发起岗位
     *
     * @param workFlowTaskBackDTO 回退流程到发起岗位dto
     * @return Map<String, Object> 撤销返回参数
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> submitTaskBack(WorkFlowTaskBackDTO workFlowTaskBackDTO) {
        // 获取任务信息
        Task currentTask = taskService.createTaskQuery()
                .taskId(workFlowTaskBackDTO.getTaskId())
                .singleResult();

        // 设置意见信息
        if (ObjectUtil.isNotNull(workFlowTaskBackDTO.getComment())) {
            //只保留一条批注记录
            List<Comment> commentList = taskService.getTaskComments(currentTask.getId());
            if(ObjectUtil.isNotEmpty(commentList)){
                commentList.forEach(common -> {
                    taskService.deleteComment(common.getId());
                });
            }
            // 添加新的批注信息
            taskService.addComment(currentTask.getId(), currentTask.getProcessInstanceId(),
                    workFlowTaskBackDTO.getComment());
        }

        // 获取流程发起对应柜员信息
        String processId = workFlowTaskBackDTO.getProcessId();
        if (StrUtil.isBlank(processId)) {
            processId = currentTask.getProcessInstanceId();
            workFlowTaskBackDTO.setProcessId(processId);
        }
        TbSysBackPositionInfo backPositionInfo = tbSysBackPositionInfoMapper
                .getBackPositionInfoByProcessId(processId);
        if (ObjectUtil.isNull(backPositionInfo)) {
            throw new ServiceException("通过processId[{}]获取流程发起柜员机构信息为空,流程退回到发起岗失败!");
        }

        // 拼装流程回退参数
        String userId = StrUtil.format(WorkFlowServerConstant.USER_ID_APPEND_TEMPLATE, backPositionInfo.getOptionUserCd(),
                backPositionInfo.getOptionOrgCd());

        // 获取当前操作柜员信息,并且保存退回上一处理人信息
        String optionUserCd = webUtil.getCurrentUserCd();
        String optionOrgCd = webUtil.getCurrentOrgCd();
        TbSysBackPositionInfo tbSysBackPositionInfo = new TbSysBackPositionInfo();
        tbSysBackPositionInfo.setId(IdUtil.simpleUUID());
        tbSysBackPositionInfo.setActivitiId(workFlowTaskBackDTO.getCurrentActivityId());
        tbSysBackPositionInfo.setProcessId(workFlowTaskBackDTO.getProcessId());
        tbSysBackPositionInfo.setOptionOrgCd(optionOrgCd);
        tbSysBackPositionInfo.setOptionUserCd(optionUserCd);
        tbSysBackPositionInfo.setWorkFlowTemplateId(backPositionInfo.getWorkFlowTemplateId());
        tbSysBackPositionInfo.setBizNo(backPositionInfo.getBizNo());
        tbSysBackPositionInfo.setSubmitTime(new Date());
        tbSysBackPositionInfo.setIsDel(WorkFlowServerConstant.STRING_NUM_1);
        // 设置流程意见信息
        tbSysBackPositionInfo.setFlowComment(workFlowTaskBackDTO.getComment());
        log.info("回退流程到发起岗位保存信息[{}]", JSONObject.toJSONString(tbSysBackPositionInfo));
        tbSysBackPositionInfoMapper.insert(tbSysBackPositionInfo);

        // 回退参数Map
        Map<String, Object> backMap = new HashMap<>(WorkFlowServerConstant.DEFAULT_MAP_SIZE);
        backMap.put(WorkFlowServerConstant.USER_ID_FLAG, userId);

        // 删除退出上一岗位信息内容
        if (StrUtil.isNotBlank(workFlowTaskBackDTO.getProcessId())) {
            UpdateWrapper<TbSysBackPositionInfo> updateWrapper = new UpdateWrapper<>();
            updateWrapper.lambda().eq(TbSysBackPositionInfo::getProcessId, workFlowTaskBackDTO.getProcessId());
            log.info("回退流程到发起岗位,删除退回上一岗信息,参数processId[{}]", workFlowTaskBackDTO.getProcessId());
            tbSysBackPositionInfoMapper.delete(updateWrapper);
        }

        // 设置权限信息
        identityService.setAuthenticatedUserId(userId);

        // 获取当前任务参数信息
        Map<String, Object> processVariables = currentTask.getProcessVariables();
        processVariables.put(WorkFlowServerConstant.COMMENT_FLAG, workFlowTaskBackDTO.getComment());
        processVariables.put(WorkFlowServerConstant.OPINION_FLAG, workFlowTaskBackDTO.getComment());

        // 对历史任务进行正序排序,获取最早的任务节点
        List<HistoricActivityInstance> activityInstanceList = historyService.createHistoricActivityInstanceQuery()
                // 流程执行id
                .executionId(currentTask.getProcessInstanceId())
                // 按照时间排序
                .orderByHistoricActivityInstanceStartTime()
                .asc()
                .list();

        // 找到第一个userTask类型的任务节点,既为发起节点
        HistoricActivityInstance firstActivityInstance = activityInstanceList.stream().filter(activityInstance ->
                WorkFlowServerConstant.USER_TASK_FLAG.equalsIgnoreCase(activityInstance.getActivityType())
        ).findFirst().orElse(null);
        // 空值判定
        if (ObjectUtil.isNull(firstActivityInstance)) {
            throw new ServiceException("未找到流程发起节点信息,退回到发起节点异常!");
        }

        // 获取实际发起节点的流程定义信息
        ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
                .getDeployedProcessDefinition(firstActivityInstance.getProcessDefinitionId());

        // 获取发起节点定义信息
        ActivityImpl startActivity = processDefinition.findActivity(firstActivityInstance.getActivityId());

        // 获取当前节点定义信息
        ActivityImpl currentTaskActivity = processDefinition.findActivity(currentTask.getTaskDefinitionKey());

        // 退回首节点校验,首节点不能再次退回首节点
        if(startActivity.getId().equals(currentTask.getTaskDefinitionKey())){
            throw new ServiceException("当前节点为首节点,无法退回");
        }

        // 通过流程实例id以及任务定义key获取同级别任务列表信息,既需要退回的任务
        List<Task> backTaskList = taskService.createTaskQuery()
                .processInstanceId(workFlowTaskBackDTO.getProcessId())
                .taskDefinitionKey(currentTask.getTaskDefinitionKey())
                .list();
        backTaskList.forEach(task -> {
            // 进行任务跳转
            activitiUtil.turnTransitionForUTask(task.getId(),
                    currentTaskActivity,
                    startActivity,
                    processVariables);
        });

        // 通过processId获取最新的一个task任务信息
        List<Task> nextTaskList = taskService.createTaskQuery()
                // 流程实例id
                .processInstanceId(processId)
                // 存活状态
                .active()
                // 按照日期排序,最新的一个
                .orderByTaskCreateTime()
                .desc()
                .list();

        // 空值判定
        Map<String, Object> returnVariableMap = null;
        if (ObjectUtil.isNotEmpty(nextTaskList)) {
            // 获取当下生效的taskId
            String activeTaskId = nextTaskList.get(0).getId();
            // 进行处理人强制转换,修改流程处理人信息
            Task nextTask = taskService.createTaskQuery()
                    .taskId(activeTaskId)
                    .singleResult();
            nextTask.setAssignee(userId);
            taskService.saveTask(nextTask);
            taskService.claim(nextTask.getId(), userId);

            // 设置响应参数
            returnVariableMap = new HashMap<>();
            returnVariableMap.put("nextTaskId", nextTask.getId());
            returnVariableMap.put("taskName", nextTask.getName());
            returnVariableMap.put("taskDefKey", nextTask.getTaskDefinitionKey());
            returnVariableMap.put("creator", nextTask.getAssignee());
        }
        return returnVariableMap;
    }

    /**
     * 提交任务到下一岗位
     *
     * @param workFlowSubmitTaskDTO dto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> submitNormalTask(WorkFlowSubmitTaskDTO workFlowSubmitTaskDTO) {

        // 参数校验
        if (StrUtil.isBlank(workFlowSubmitTaskDTO.getCurrentActivityId())) {
            throw new ServiceException("提交下一岗位回退上一处理人[currentActivityId]信息为空!");
        }
        if (StrUtil.isBlank(workFlowSubmitTaskDTO.getProcessId())) {
            throw new ServiceException("提交下一岗位当前流程[processId]信息为空!");
        }
        // 当前岗位信息不能为usertask0,usertask0为开始流程默认岗位编号
        if (WorkFlowServerConstant.USER_TASK_FLAG_START.equals(workFlowSubmitTaskDTO.getCurrentActivityId())) {
            throw new ServiceException("传入当前岗位信息不能为usertask0!");
        }
        // 下一处理人格式校验
        if (StrUtil.isBlank(workFlowSubmitTaskDTO.getWfusers())
                || !workFlowSubmitTaskDTO.getWfusers().contains(StrUtil.COLON)) {
            throw new ServiceException("下一处理人格式为 userCd:orgCd,请确认!");
        }

        // 通过流程processId获取bizNo信息,以及流程模板编号信息
        TbSysBackPositionInfo startPositionInfo = tbSysBackPositionInfoMapper
                .getBackPositionInfoByProcessId(workFlowSubmitTaskDTO.getProcessId());
        // 获取当前操作柜员信息,并且保存退回上一处理人信息
        String optionUserCd = webUtil.getCurrentUserCd();
        String optionOrgCd = webUtil.getCurrentOrgCd();
        TbSysBackPositionInfo tbSysBackPositionInfo = new TbSysBackPositionInfo();
        tbSysBackPositionInfo.setId(IdUtil.simpleUUID());
        tbSysBackPositionInfo.setActivitiId(workFlowSubmitTaskDTO.getCurrentActivityId());
        tbSysBackPositionInfo.setProcessId(workFlowSubmitTaskDTO.getProcessId());
        tbSysBackPositionInfo.setOptionOrgCd(optionOrgCd);
        tbSysBackPositionInfo.setOptionUserCd(optionUserCd);
        if (ObjectUtil.isNotNull(startPositionInfo)) {
            tbSysBackPositionInfo.setWorkFlowTemplateId(startPositionInfo.getWorkFlowTemplateId());
            tbSysBackPositionInfo.setBizNo(startPositionInfo.getBizNo());
        }
        tbSysBackPositionInfo.setSubmitTime(new Date());
        // 设置流程意见信息
        tbSysBackPositionInfo.setFlowComment(workFlowSubmitTaskDTO.getComment());
        log.info("正常提交方法,保存退回上一处理人信息[{}]", JSONObject.toJSONString(tbSysBackPositionInfo));
        tbSysBackPositionInfoMapper.insert(tbSysBackPositionInfo);

        // 设置提交流程参数信息
        Map<String, Object> paramMap = workFlowSubmitTaskDTO.getVariableMap();
        if (ObjectUtil.isEmpty(paramMap)) {
            paramMap = new HashMap<>(WorkFlowServerConstant.DEFAULT_MAP_SIZE);
        }
        // 下一处理人
        paramMap.put(WorkFlowServerConstant.WORKFLOW_USERS_FLAG, workFlowSubmitTaskDTO.getWfusers());
        // 审批信息
        paramMap.put(WorkFlowServerConstant.COMMENT_FLAG, workFlowSubmitTaskDTO.getComment());
        // 审批信息
        paramMap.put(WorkFlowServerConstant.OPINION_FLAG, workFlowSubmitTaskDTO.getComment());

        // 开始提交到下一审批人
        log.info("正常提交方法,提交参数[{}]", JSONObject.toJSONString(paramMap));

        // 设置权限信息
        identityService.setAuthenticatedUserId(workFlowSubmitTaskDTO.getWfusers());

        // 获取当前任务信息
        Task task = taskService.createTaskQuery()
                .taskId(workFlowSubmitTaskDTO.getTaskId())
                .singleResult();

        // 获取执行id
        String executionId = task.getExecutionId();

        // 设置留言信息,只留一条批注信息
        List<Comment> commentList = taskService.getTaskComments(task.getId());
        if(ObjectUtil.isNotEmpty(commentList)){
            for(Comment comment : commentList){
                // 删除原有批注信息
                taskService.deleteComment(comment.getId());
            }
        }

        // 添加批注信息
        taskService.addComment(task.getId(), task.getProcessInstanceId(), workFlowSubmitTaskDTO.getComment());

        // 设置参数信息
        runtimeService.setVariables(executionId, paramMap);

        // 开始提交任务
        taskService.complete(task.getId(), paramMap);

        // 进行用户认领操作
        List<Task> taskList = taskService.createTaskQuery()
                // 执行id
                .executionId(executionId)
                .list();
        // 进行认领操作
        Map<String, Object> returnMap = new HashMap<>();
        if (ObjectUtil.isNotEmpty(taskList)) {
            // 进行处理人强制转换
            Task nextTask = taskService.createTaskQuery()
                    .taskId(taskList.get(0).getId())
                    .singleResult();
            nextTask.setAssignee(workFlowSubmitTaskDTO.getWfusers());
            taskService.saveTask(nextTask);
            taskService.claim(nextTask.getId(), workFlowSubmitTaskDTO.getWfusers());

            // 设置响应信息
            returnMap.put(WorkFlowServerConstant.NEXT_TASK_ID, nextTask.getId());
            returnMap.put(WorkFlowServerConstant.TASK_DEF_KEY, nextTask.getTaskDefinitionKey());
            returnMap.put(WorkFlowServerConstant.TASK_NAME_FLAG,  nextTask.getName());
        }

        return returnMap;
    }

    /**
     * 回退流程到上一岗位
     *
     * @param workFlowBackPreviousDTO 流程实例退回上一岗位dto
     * @return String 撤销信息
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String submitBackPrevious(WorkFlowBackPreviousDTO workFlowBackPreviousDTO) {
        log.info("回退流程到上一岗位参数信息workFlowBackPreviousDTO[{}]", workFlowBackPreviousDTO.toString());

        // 最终返回信息,非空则有问题
        String errorMessage;

        // 获取上一岗位信息
        String processId = workFlowBackPreviousDTO.getProcessId();
        QueryWrapper<TbSysBackPositionInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TbSysBackPositionInfo::getProcessId, processId)
                .eq(TbSysBackPositionInfo::getIsDel, WorkFlowConstant.STRING_NUM_0)
                .orderBy(true, false, TbSysBackPositionInfo::getSubmitTime);
        List<TbSysBackPositionInfo> backPositionInfoList = tbSysBackPositionInfoMapper.selectList(queryWrapper);
        if (ObjectUtil.isEmpty(backPositionInfoList)) {
            errorMessage = StrUtil.format("通过流程实例id[{}]没有找到上一岗位信息!",
                    workFlowBackPreviousDTO.getProcessId());
            log.error(errorMessage);
            return errorMessage;
        }
        TbSysBackPositionInfo previousInfo = backPositionInfoList.get(0);

        // 判断当前岗位为贷审会秘书岗时撤回业务,需要校验发起的会议是否已经都投票完成
        if (StrUtil.isNotBlank(workFlowBackPreviousDTO.getPositionName())
                && workFlowBackPreviousDTO.getPositionName().contains(WorkFlowServerConstant.LOAN_MEET_SECRETARY)) {
            // 校验委员是否全部投票完成
            QueryWrapper<TbConVote> voteQueryWrapper = new QueryWrapper<>();
            voteQueryWrapper.lambda().eq(TbConVote::getBizNum, previousInfo.getBizNo())
                    .eq(TbConVote::getStatus, WorkFlowServerConstant.VOTE_STATUS_ACTIVE)
                    .isNull(TbConVote::getVote)
                    .orderByDesc(TbConVote::getVoteNum);
            List<TbConVote> voteList = tbConVoteMapper.selectList(voteQueryWrapper);
            if (ObjectUtil.isNotEmpty(voteList) && voteList.size() > WorkFlowServerConstant.SIZE_0) {
                // 未进行投票的柜员编号
                List<String> unVoteUserCdList = voteList.stream().map(TbConVote::getUserNum).collect(Collectors.toList());
                // 获取userCd对应用户名称
                String undoVoteUserNames = userApi.listUserInfoByUserCd(unVoteUserCdList).stream().map(nameInfoDTO -> {
                    String appendNameCd = StrUtil.format(WorkFlowServerConstant.APPEND_TEMPLATE,
                            nameInfoDTO.getUserCd(),
                            nameInfoDTO.getUserName());
                    return appendNameCd;
                }).collect(Collectors.joining(WorkFlowServerConstant.SPLIT_COMMA_FLAG));

                errorMessage = StrUtil.format(
                        WorkFlowServerConstant.APPEND_TEMPLATE_VOTE_CHECK,
                        WorkFlowServerConstant.UN_VOTE_CHECK_MESSAGE_FRONT,
                        undoVoteUserNames,
                        WorkFlowServerConstant.UN_VOTE_CHECK_RECALL);
                return errorMessage;
            }
        }

        // 如果未传currentActivityId,需要计算当前业务currentActivityId信息
        Task currentTask = taskService.createTaskQuery()
                .taskId(workFlowBackPreviousDTO.getTaskId())
                .singleResult();
        if (StrUtil.isBlank(workFlowBackPreviousDTO.getCurrentActivityId())) {
            if (ObjectUtil.isNotNull(currentTask)) {
                log.info("通过getCurrentActivityId获取activitiId信息为[{}]", currentTask.getTaskDefinitionKey());
                workFlowBackPreviousDTO.setCurrentActivityId(currentTask.getTaskDefinitionKey());
            }
        }

        // 设置意见信息
        if (ObjectUtil.isNotNull(workFlowBackPreviousDTO.getOpinion())) {
            //只保留一条批注记录
            List<Comment> commentList = taskService.getTaskComments(currentTask.getId());
            if(ObjectUtil.isNotEmpty(commentList)){
                commentList.forEach(common -> {
                    taskService.deleteComment(common.getId());
                });
            }
            // 添加新的批注信息
            taskService.addComment(currentTask.getId(), currentTask.getProcessInstanceId(), workFlowBackPreviousDTO.getOpinion());
        }

        // 获取当前操作柜员信息,并且保存退回上一处理人信息
        String optionUserCd = webUtil.getCurrentUserCd();
        String optionOrgCd = webUtil.getCurrentOrgCd();
        TbSysBackPositionInfo tbSysBackPositionInfo = new TbSysBackPositionInfo();
        tbSysBackPositionInfo.setId(IdUtil.simpleUUID());
        tbSysBackPositionInfo.setActivitiId(workFlowBackPreviousDTO.getCurrentActivityId());
        tbSysBackPositionInfo.setProcessId(workFlowBackPreviousDTO.getProcessId());
        tbSysBackPositionInfo.setOptionOrgCd(optionOrgCd);
        tbSysBackPositionInfo.setOptionUserCd(optionUserCd);
        tbSysBackPositionInfo.setWorkFlowTemplateId(previousInfo.getWorkFlowTemplateId());
        tbSysBackPositionInfo.setBizNo(previousInfo.getBizNo());
        tbSysBackPositionInfo.setSubmitTime(new Date());
        tbSysBackPositionInfo.setIsDel(WorkFlowServerConstant.STRING_NUM_1);
        // 设置流程意见信息
        tbSysBackPositionInfo.setFlowComment(workFlowBackPreviousDTO.getOpinion());
        log.info("回退流程到上一岗位保存信息[{}]", JSONObject.toJSONString(tbSysBackPositionInfo));
        tbSysBackPositionInfoMapper.insert(tbSysBackPositionInfo);

        // 如果流程节点是usertask1,证明提交到第二个岗位,直接调用回退到发起岗位方法
        if (WorkFlowServerConstant.FIRST_ACTIVITI_ID.equals(previousInfo.getActivitiId())) {
            // 任务回退到发起岗位,设置信息字段
            WorkFlowTaskBackDTO workFlowTaskBackDTO = new WorkFlowTaskBackDTO();
            workFlowTaskBackDTO.setProcessId(workFlowBackPreviousDTO.getProcessId());
            workFlowTaskBackDTO.setTaskId(workFlowBackPreviousDTO.getTaskId());
            workFlowTaskBackDTO.setUserCd(previousInfo.getOptionUserCd());
            workFlowTaskBackDTO.setOrgCd(previousInfo.getOptionOrgCd());
            submitTaskBack(workFlowTaskBackDTO);
            return null;
        }

        // 权限设定
        String nextUserId = StrUtil.format(WorkFlowServerConstant.USER_ID_APPEND_TEMPLATE,
                previousInfo.getOptionUserCd(),
                previousInfo.getOptionOrgCd());
        identityService.setAuthenticatedUserId(nextUserId);

        // 获取实际发起节点的流程定义信息
        ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
                .getDeployedProcessDefinition(currentTask.getProcessDefinitionId());
        // 获取目标节点定义
        ActivityImpl definitionActivity = processDefinition.findActivity(previousInfo.getActivitiId());

        // 获取当前节点定义信息
        ActivityImpl currentTaskActivity = processDefinition.findActivity(currentTask.getTaskDefinitionKey());

        // 退回首节点校验,首节点不能再次退回首节点
        if(definitionActivity.getId().equals(currentTask.getTaskDefinitionKey())){
            throw new ServiceException("当前节点为首节点,无法退回");
        }

        // 设置参数信息
        Map<String, Object> processVariables = currentTask.getProcessVariables();
        processVariables.put(WorkFlowServerConstant.COMMENT_FLAG, workFlowBackPreviousDTO.getOpinion());
        processVariables.put(WorkFlowServerConstant.OPINION_FLAG, workFlowBackPreviousDTO.getOpinion());

        // 通过流程实例id以及任务定义key获取同级别任务列表信息,既需要退回的任务
        List<Task> backTaskList = taskService.createTaskQuery()
                .processInstanceId(workFlowBackPreviousDTO.getProcessId())
                .taskDefinitionKey(currentTask.getTaskDefinitionKey())
                .list();
        backTaskList.forEach(task -> {
            // 进行任务跳转
            activitiUtil.turnTransitionForUTask(task.getId(),
                    currentTaskActivity,
                    definitionActivity,
                    processVariables);
        });

        // 通过processId获取最新的一个task任务信息
        Task nextTask = taskService.createTaskQuery()
                // 流程实例id
                .processInstanceId(workFlowBackPreviousDTO.getProcessId())
                // 存活状态
                .active()
                // 按照日期排序,最新的一个
                .orderByTaskCreateTime()
                .desc()
                .singleResult();

        // 进行处理人强制转换,修改流程处理人信息
        nextTask.setAssignee(nextUserId);
        taskService.saveTask(nextTask);
        taskService.claim(nextTask.getId(), nextUserId);

        // 删除回退信息
        tbSysBackPositionInfoMapper.deleteById(previousInfo);
        return null;
    }

    /**
     * 结束流程
     *
     * @param workFlowEndProcessDTO dto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void endProcess(WorkFlowEndProcessDTO workFlowEndProcessDTO) {
        log.info("调用流程结束任务,结束参数信息为[{}]", JSONObject.toJSONString(workFlowEndProcessDTO));
        // 流程结束参数信息
        String userId = StrUtil.format(WorkFlowServerConstant.USER_ID_APPEND_TEMPLATE, workFlowEndProcessDTO.getUserCd(),
                workFlowEndProcessDTO.getOrgCd());
        Map<String, Object> paramMap = new HashMap<>(WorkFlowServerConstant.DEFAULT_MAP_SIZE);
        paramMap.put(WorkFlowServerConstant.OPINION_FLAG, workFlowEndProcessDTO.getOpinion());

        // 设置权限信息
        identityService.setAuthenticatedUserId(userId);

        // 获取当前task任务信息
        Task currentTask = taskService.createTaskQuery()
                .taskId(workFlowEndProcessDTO.getTaskId())
                .singleResult();

        // 设置意见信息
        if (ObjectUtil.isNotNull(workFlowEndProcessDTO.getOpinion())) {
            //只保留一条批注记录
            List<Comment> commentList = taskService.getTaskComments(currentTask.getId());
            if(ObjectUtil.isNotEmpty(commentList)){
                commentList.forEach(common -> {
                    taskService.deleteComment(common.getId());
                });
            }
            // 添加新的批注信息
            taskService.addComment(currentTask.getId(), currentTask.getProcessInstanceId(), workFlowEndProcessDTO.getOpinion());
        }

        // 当前任务节点定义信息
        String currentActivityId = null;
        if (ObjectUtil.isNotNull(currentTask)) {
            // 流程任务定义key
            currentActivityId = currentTask.getTaskDefinitionKey();
            UpdateWrapper<TbSysBackPositionInfo> updateWrapper = new UpdateWrapper<>();
            updateWrapper.lambda().eq(TbSysBackPositionInfo::getProcessId, currentTask.getProcessInstanceId());
            tbSysBackPositionInfoMapper.delete(updateWrapper);
        }

        // 通过流程processId获取bizNo信息,以及流程模板编号信息
        List<TbSysBackPositionInfo> startPositionList = tbSysBackPositionInfoMapper
                .getBackPositionInfoByBizNo(workFlowEndProcessDTO.getBizId());

        // 存入返回上一岗位必要信息
        String optionUserCd = webUtil.getCurrentUserCd();
        String optionOrgCd = webUtil.getCurrentOrgCd();
        TbSysBackPositionInfo tbSysBackPositionInfo = new TbSysBackPositionInfo();
        tbSysBackPositionInfo.setId(IdUtil.simpleUUID());
        if (StrUtil.isNotBlank(currentActivityId)) {
            tbSysBackPositionInfo.setActivitiId(currentActivityId);
        } else {
            tbSysBackPositionInfo.setActivitiId(WorkFlowServerConstant.WORKFLOW_TASK_END);
        }
        if (ObjectUtil.isNotEmpty(startPositionList)) {
            tbSysBackPositionInfo.setProcessId(startPositionList.get(WorkFlowServerConstant.INT_NUM_0)
                    .getProcessId());
            tbSysBackPositionInfo.setWorkFlowTemplateId(startPositionList.get(WorkFlowServerConstant.INT_NUM_0)
                    .getWorkFlowTemplateId());
        }
        tbSysBackPositionInfo.setBizNo(workFlowEndProcessDTO.getBizId());
        tbSysBackPositionInfo.setOptionOrgCd(optionOrgCd);
        tbSysBackPositionInfo.setOptionUserCd(optionUserCd);
        tbSysBackPositionInfo.setSubmitTime(new Date());
        tbSysBackPositionInfo.setFlowComment(workFlowEndProcessDTO.getOpinion());
        tbSysBackPositionInfo.setIsDel(WorkFlowServerConstant.FLOW_TYPE_1);
        log.info("结束流程方法,存入退回上一岗位必要信息[{}]", JSONObject.toJSONString(tbSysBackPositionInfo));
        tbSysBackPositionInfoMapper.insert(tbSysBackPositionInfo);

        // 通过业务编号删除在途业务
        QueryWrapper<TbSysUnfinishedFlow> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TbSysUnfinishedFlow::getBizNo, workFlowEndProcessDTO.getBizId());
        tbSysUnfinishedFlowMapper.delete(queryWrapper);

        // 获取流程定义信息
        ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
                .getDeployedProcessDefinition(currentTask.getProcessDefinitionId());

        // 获取流程定义节点详情信息
        List<ActivityImpl> allActivityList = processDefinition.getActivities();

        // 过滤出end节点信息
        ActivityImpl endActivity = allActivityList.stream().filter(activity -> {
            return ObjectUtil.isEmpty(activity.getOutgoingTransitions());
        }).findAny().orElse(null);
        if (ObjectUtil.isEmpty(endActivity)) {
            throw new ServiceException("获取流程end节点信息为空,请确认流程图有end节点信息配置正确!");
        }

        // 获取当前节点定义信息
        ActivityImpl currentTaskActivity = processDefinition.findActivity(currentTask.getTaskDefinitionKey());
        // 进行任务跳转,既结束任务
        activitiUtil.turnTransitionForUTask(currentTask.getId(),
                currentTaskActivity,
                endActivity,
                paramMap);
    }

    /**
     * 跟踪列表查询
     *
     * @param workFlowTraceListDTO dto
     */
    @Override
    public WorkFlowTraceListDTO findTraceList(WorkFlowTraceListDTO workFlowTraceListDTO) {
        // 最终返回跟踪列表
        List<WorkFlowTrace> finalTraceList;

        // 新流程获取
        List<WorkFlowTrace> newTraceList;
        if (WorkFlowServerConstant.STRING_NUM_1.equals(workFlowTraceListDTO.getIfThreeMonthsAgo())) {
            // 新流程三个月之前信息,从本地workflow备份库中获取列表信息
            finalTraceList = getNewFlowHistoryTraceList(workFlowTraceListDTO);
        } else {
            // 首先获取新流程近三个月信息
            finalTraceList = getNewFlowTraceList(workFlowTraceListDTO);
        }

        // 获取分页信息
        List<WorkFlowTrace> workFlowTraceList = null;
        WorkFlowPage page = null;
        if (ObjectUtil.isNotEmpty(finalTraceList)) {
            page = pageUtil.setFlowListPage(finalTraceList, PaginationContext.getPageNum(),
                    PaginationContext.getPageSize());
            workFlowTraceList = page.getResult();
        }
        // 设置成分页对象格式
        if (ObjectUtil.isNotEmpty(workFlowTraceList)) {
            // 产品码值信息
            List<String> codeTypeCdList = new ArrayList<>();
            // 机构信息列表
            List<String> orgCdList = new ArrayList<>();
            // 柜员信息
            List<String> userCdList = new ArrayList<>();
            codeTypeCdList.add("ProcessTypeCd");
            Map<String, String> codeInfoMap = baseCacheApi.getTypeCdValueKeyMap(codeTypeCdList);
            for (WorkFlowTrace trace : workFlowTraceList) {
                orgCdList.add(trace.getOrgCd());
                userCdList.add(trace.getCreator());
                String codeName = codeInfoMap.get("ProcessTypeCd".concat(StrUtil.UNDERLINE).concat(trace.getBizType()));
                trace.setBizType(codeName);
            }

            // 获取机构柜员名称信息
            ManageOrgUserInfoDTO manageOrgUserInfoDTO = new ManageOrgUserInfoDTO();
            // 机构编号以及柜员编号去重去空
            orgCdList.removeIf(StrUtil::isBlank);
            orgCdList = orgCdList.stream().distinct().collect(Collectors.toList());
            userCdList.removeIf(StrUtil::isBlank);
            userCdList = userCdList.stream().distinct().collect(Collectors.toList());

            // 封装请求参数
            manageOrgUserInfoDTO.setOrgCdList(orgCdList);
            manageOrgUserInfoDTO.setUserCdList(userCdList);
            manageOrgUserInfoDTO = manageForWorkflowApiClient.getOrgUserInfo(manageOrgUserInfoDTO);
            ManageOrgUserInfoDTO finalManageOrgUserInfoDTO = manageOrgUserInfoDTO;
            workFlowTraceList.forEach(trace -> {
                // 设置机构信息
                if (ObjectUtil.isNotEmpty(finalManageOrgUserInfoDTO.getOrgInfoMap())) {
                    trace.setOrgName(finalManageOrgUserInfoDTO.getOrgInfoMap().get(trace.getOrgCd()));
                }

                // 设置机构信息
                if (ObjectUtil.isNotEmpty(finalManageOrgUserInfoDTO.getUserInfoMap())) {
                    trace.setCreatorName(finalManageOrgUserInfoDTO.getUserInfoMap().get(trace.getCreator()));
                }
            });
            workFlowTraceListDTO.setWorkFlowPage(page);
        }

        return workFlowTraceListDTO;
    }

    /**
     * 跟踪列表查询
     *
     * @param workFlowTraceListDTO dto
     * @return WorkFlowTraceListDTO dto
     */
    @Override
    public WorkFlowTraceListDTO findOldTraceList(WorkFlowTraceListDTO workFlowTraceListDTO) {
        // 最终返回跟踪列表
        List<WorkFlowTraceVO> oldTraceList = null;
        if (StrUtil.isBlank(workFlowTraceListDTO.getSystemFlag())
                || WorkFlowServerConstant.FLOW_TYPE_0.equals(workFlowTraceListDTO.getSystemFlag())) {
            oldTraceList = getOldFlowTraceList(workFlowTraceListDTO);
        }

        // 设置成分页对象格式
        if (ObjectUtil.isNotEmpty(oldTraceList)) {
            // 产品码值信息
            List<String> codeTypeCdList = new ArrayList<>();
            // 机构信息列表
            List<String> orgCdList = new ArrayList<>();
            // 柜员信息
            List<String> userCdList = new ArrayList<>();
            codeTypeCdList.add("ProcessTypeCd");
            Map<String, String> codeInfoMap = baseCacheApi.getTypeCdValueKeyMap(codeTypeCdList);
            for (WorkFlowTrace trace : oldTraceList) {
                orgCdList.add(trace.getOrgCd());
                userCdList.add(trace.getCreator());
                String codeName = codeInfoMap.get("ProcessTypeCd".concat(StrUtil.UNDERLINE).concat(trace.getBizType()));
                trace.setBizType(codeName);
            }

            // 获取机构柜员名称信息
            ManageOrgUserInfoDTO manageOrgUserInfoDTO = new ManageOrgUserInfoDTO();
            // 机构编号以及柜员编号去重去空
            orgCdList.removeIf(StrUtil::isBlank);
            orgCdList = orgCdList.stream().distinct().collect(Collectors.toList());
            userCdList.removeIf(StrUtil::isBlank);
            userCdList = userCdList.stream().distinct().collect(Collectors.toList());

            // 封装请求参数
            manageOrgUserInfoDTO.setOrgCdList(orgCdList);
            manageOrgUserInfoDTO.setUserCdList(userCdList);
            manageOrgUserInfoDTO = manageForWorkflowApiClient.getOrgUserInfo(manageOrgUserInfoDTO);
            ManageOrgUserInfoDTO finalManageOrgUserInfoDTO = manageOrgUserInfoDTO;
            oldTraceList.forEach(trace -> {
                // 设置机构信息
                if (ObjectUtil.isNotEmpty(finalManageOrgUserInfoDTO.getOrgInfoMap())) {
                    trace.setOrgName(finalManageOrgUserInfoDTO.getOrgInfoMap().get(trace.getOrgCd()));
                }

                // 设置机构信息
                if (ObjectUtil.isNotEmpty(finalManageOrgUserInfoDTO.getUserInfoMap())) {
                    trace.setCreatorName(finalManageOrgUserInfoDTO.getUserInfoMap().get(trace.getCreator()));
                }
            });
            // 设置查询分页信息
            if (ObjectUtil.isNotEmpty(oldTraceList)) {
                WorkFlowPage page = new WorkFlowPage();
                page.setPageNum(workFlowTraceListDTO.getPageNum());
                page.setPageSize(workFlowTraceListDTO.getPageSize());
                page.setResult(oldTraceList);
                workFlowTraceListDTO.setWorkFlowPage(page);
            }
        }

        return workFlowTraceListDTO;
    }

    /**
     * 风险新流程三个月前跟踪列表查询
     *
     * @param workFlowRiskTraceDTO dto
     * @return WorkFlowTraceListDTO dto
     */
    @Override
    public WorkFlowRiskTraceDTO findRiskTraceList(WorkFlowRiskTraceDTO workFlowRiskTraceDTO) {
        // 获取参数信息
        WorkFlowTraceListDTO workFlowTraceListDTO = workFlowConvert.riskParamDtoTOTraceListDto(workFlowRiskTraceDTO);
        workFlowTraceListDTO.setSystemFlag(WorkFlowServerConstant.STRING_NUM_1);
        // 新流程三个月之前信息,从本地workflow备份库中获取列表信息
        List<WorkFlowTrace> newTraceList = getNewFlowHistoryTraceList(workFlowTraceListDTO);
        if (ObjectUtil.isNotEmpty(newTraceList)) {
            List<WorkFlowRiskTraceDTO.WorkFlowRiskTrace> workFlowRiskTraceList = newTraceList.stream().map(trace ->
                    workFlowConvert.workflowTraceToInnerRiskTrace(trace)
            ).collect(Collectors.toList());
            workFlowRiskTraceDTO.setWorkFlowRiskTraceList(workFlowRiskTraceList);
        }
        return workFlowRiskTraceDTO;
    }

    /**
     * 获取老流程信息,其中包含finish信息以及未完成信息
     * @param workFlowTraceListDTO
     * @return
     */
    public List<WorkFlowTraceVO> getOldFlowTraceList(WorkFlowTraceListDTO workFlowTraceListDTO) {
        // 任务列表信息分頁信息
        workFlowTraceListDTO.setPageNum(PaginationContext.getPageNum());
        workFlowTraceListDTO.setPageSize(PaginationContext.getPageSize());
        workFlowTraceListDTO.setOffSet((PaginationContext.getPageNum() - 1) * PaginationContext.getPageSize());

        // 查询分支,三个月之前流程跟踪列表信息
        List<WorkFlowTraceVO> traceVoList = null;
        if (WorkFlowServerConstant.WORKFLOW_STATUS_FINISHED.equals(workFlowTraceListDTO.getStatus())) {
            if (WorkFlowServerConstant.STRING_NUM_1.equals(workFlowTraceListDTO.getIfThreeMonthsAgo())) {
                // 老流程三个月之前业务信息查询,默认查询为finished业务
                workFlowTraceListDTO.setTraceType(WorkFlowServerConstant.STRING_NUM_6);
                traceVoList = wfmidAppProcessInstanceMapper.findOldHistoryTraceList(workFlowTraceListDTO);
            } else {
                // 老流程服务近三个月流程信息 暂时注释 暂定老流程近三个月全部迁移到历史三个月之前信息表中
                workFlowTraceListDTO.setTraceType(WorkFlowServerConstant.STRING_NUM_5);
                traceVoList = wfmidAppProcessInstanceMapper.findOldTraceList(workFlowTraceListDTO);
            }
        }

        // 设置跟踪列表来源标识字段信息
        if (ObjectUtil.isNotEmpty(traceVoList)) {
            traceVoList.forEach(trace -> {
                if (ObjectUtil.isNotNull(trace.getCreateDate())) {
                    trace.setCreateDateStr(DateUtil.format(trace.getCreateDate(), DatePattern.NORM_DATETIME_PATTERN));
                }
                trace.setTraceType(workFlowTraceListDTO.getTraceType());
            });
            return traceVoList;
        }
        return null;
    }

    /**
     * 新流程获取三个月内历史信息
     * @param workFlowTraceListDTO 参数dto
     * @return 任务列表
     */
    public List<WorkFlowTrace> getNewFlowTraceList(WorkFlowTraceListDTO workFlowTraceListDTO) {
        // 任务列表信息
        List<WorkFlowTrace> traceList = new ArrayList<>();

        // 拼装流程发起参数
        String userId = StrUtil.format(WorkFlowServerConstant.USER_ID_APPEND_TEMPLATE,
                workFlowTraceListDTO.getUserCd(),
                workFlowTraceListDTO.getOrgCd());

        // 开始调用流程server获取服务,新流程三月内处理
        if (WorkFlowServerConstant.WORKFLOW_STATUS_FINISHED.equals(workFlowTraceListDTO.getStatus())) {
            workFlowTraceListDTO.setTraceType(WorkFlowServerConstant.STRING_NUM_1);
        } else {
            workFlowTraceListDTO.setTraceType(WorkFlowServerConstant.STRING_NUM_2);
        }
        // 获取历史信息
        List<WorkFlowActHisProcessListDTO> actHisProcessListDTOList = queryStatusHisList(userId,
                workFlowTraceListDTO.getStatus());

        // 空值判定
        if (ObjectUtil.isNotEmpty(actHisProcessListDTOList)) {
            // 合同编号列表
            List<String> contractNumList = new ArrayList<>();
            actHisProcessListDTOList.forEach(processInfo -> {
                // 获取流程模板信息
                String processDefinitionKey = processInfo.getProcessDefinitionKey();
                if (StrUtil.isBlank(workFlowTraceListDTO.getSystemFlag())
                        || WorkFlowServerConstant.FLOW_TYPE_0.equals(workFlowTraceListDTO.getSystemFlag())) {
                    // 信贷系统
                    if (!processDefinitionKey.toLowerCase().startsWith(WorkFlowServerConstant.RSK_PREFIX)
                            && !processDefinitionKey.toLowerCase().startsWith(WorkFlowServerConstant.STORE_PREFIX)) {
                        // 通过业务名称获取客户号,客户名称
                        contractNumList.add(processInfo.getBusinessKey());
                    }
                } else if (WorkFlowServerConstant.STRING_NUM_1.equals(workFlowTraceListDTO.getSystemFlag())) {
                    // 风险系统
                    if (processDefinitionKey.toLowerCase().startsWith(WorkFlowServerConstant.RSK_PREFIX)) {
                        contractNumList.add(processInfo.getBusinessKey());
                    }
                } else if (WorkFlowServerConstant.STRING_NUM_2.equals(workFlowTraceListDTO.getSystemFlag())) {
                    // 储备系统
                    if (processDefinitionKey.toLowerCase().startsWith(WorkFlowServerConstant.STORE_PREFIX)) {
                        contractNumList.add(processInfo.getBusinessKey());
                    }
                }
            });
            // 设置查询参数,根据合同号批量查询客户信息
            LoanWorkFlowDTO loanWorkFlowDTO = LoanWorkFlowDTO
                    .builder()
                    .contractNumList(contractNumList)
                    .build();
            // 原来使用 loanWorkFlowApiClient.getContractInfo(loanWorkFlowDTO);,获取逻辑信息,现在使用本地代办任务表获取
            if (ObjectUtil.isNotEmpty(contractNumList)) {
                List<WorkFlowContractInfoDTO> workFlowContractInfoDTOList = tbSysUnfinishedFlowMapper
                        .getContractInfoList(contractNumList);
                List<LoanWorkFlowDTO.ContractInfo> convertConInfoList = workFlowConvert
                        .workFlowConDtoToConInfo(workFlowContractInfoDTOList);
                loanWorkFlowDTO.setContractInfoList(convertConInfoList);
            }
            if (ObjectUtil.isNotEmpty(loanWorkFlowDTO.getContractInfoList())) {
                // 过滤满足客户名称数据,参数客户名称为空则直接返回查询数据
                List<LoanWorkFlowDTO.ContractInfo> contractInfoList = loanWorkFlowDTO.getContractInfoList()
                        .stream().filter(contractInfo -> {
                            // 客户名字为空,定义为非法数据过滤 todo: 后续可能修改
                            if (ObjectUtil.isNull(contractInfo.getCustomerName())
                                    || ObjectUtil.isNull(contractInfo.getCustomerNum())) {
                                return false;
                            }
                            boolean checkCustomerName = StrUtil.isBlank(workFlowTraceListDTO.getProcessCustomerName())
                                    || (StrUtil.isNotBlank(workFlowTraceListDTO.getProcessCustomerName())
                                    && contractInfo.getCustomerName().contains(workFlowTraceListDTO.getProcessCustomerName()));
                            return checkCustomerName;
                        }).collect(Collectors.toList());
                loanWorkFlowDTO.setContractInfoList(contractInfoList);

                // 合同信息map
                Map<String, LoanWorkFlowDTO.ContractInfo> customerMap = loanWorkFlowDTO.getContractInfoList()
                        .stream().collect(Collectors.toMap(
                                LoanWorkFlowDTO.ContractInfo::getContractNum, Function.identity(), (k1, k2) -> k1)
                        );

                actHisProcessListDTOList.forEach(processInfo -> {
                    // 创建人
                    String startUserId = processInfo.getStartUserId();
                    // 通过业务名称获取客户号,客户名称
                    if (ObjectUtil.isNotEmpty(startUserId)) {
                        // 将processInfo转关为processMap
                        Map<String, Object> processMap = JSON.parseObject(JSONObject.toJSONString(processInfo));
                        String contractNum = processInfo.getBusinessKey();
                        LoanWorkFlowDTO.ContractInfo contractInfo = customerMap.get(contractNum);
                        if (ObjectUtil.isNotEmpty(contractInfo)) {
                            // workFlowTrace返回信息拼装
                            buildWorkFlowTraceInfo(workFlowTraceListDTO, traceList,
                                    processMap,
                                    contractInfo.getCustomerName(),
                                    contractInfo.getCustomerNum());
                        }
                    }
                });
                // 设置跟踪列表来源标识字段信息
                if (ObjectUtil.isNotEmpty(traceList)) {
                    traceList.forEach(trace -> {
                        trace.setTraceType(workFlowTraceListDTO.getTraceType());
                    });
                }
            }
        }
        return traceList;
    }

    /**
     * 获取新流程已经结束的历史信息
     *
     * @param userId 用户id
     * @param finishStatus 流程状态 finished,running
     * @return 任务列表
     */
    public List<WorkFlowActHisProcessListDTO> queryStatusHisList(String userId, String finishStatus) {
        // 参数校验
        if (StrUtil.isBlank(userId)) {
            throw new ServiceException("历史信息查询时候,用户id为空,请确认");
        }

        // 设置查询条件
        HistoricProcessInstanceQuery instanceQuery = historyService.createHistoricProcessInstanceQuery()
                // 参与用户id
                .involvedUser(userId)
                // 按照时间倒序排序
                .orderByProcessInstanceStartTime()
                .desc();
        // 是否结束条件判定 0否1是
        if (WorkFlowServerConstant.WORKFLOW_STATUS_FINISHED.equals(finishStatus)) {
            instanceQuery.finished();
        } else {
            // 解决空值情况下,默认查询历史为running状态
            finishStatus = WorkFlowServerConstant.WORKFLOW_STATUS_RUNNING;
            instanceQuery.unfinished();
        }

        // 获取查询结果集合
        List<HistoricProcessInstance> historicProcessInstanceList = instanceQuery.list();

        // 查询信息进行转换
        List<WorkFlowActHisProcessListDTO> actHisProcessListDTOList = historicProcessInstanceList
                .stream().map(historyInstance ->
                        activitiConvert.hisProcessInstanceCovertToDTO(historyInstance)
                ).collect(Collectors.toList());

        // 跟踪列表查询数据不正确 优化处理
        List<ActHiProcinst> historyInstanceList = actHiProcinstMapper.listHistoryInstance(finishStatus, userId);

        // 非空判定
        if (ObjectUtil.isNotEmpty(historyInstanceList)) {
            Map<String, String> instanceMap = new HashMap<>();
            for (ActHiProcinst actHiProcinst : historyInstanceList) {
                String businessKey = actHiProcinst.getBusinessKey();
                instanceMap.put(businessKey, businessKey);
            }
            // 去除不正确处理人
            List<WorkFlowActHisProcessListDTO> removeList = new ArrayList<>();
            for (WorkFlowActHisProcessListDTO dto : actHisProcessListDTOList) {
                if (ObjectUtil.isNull(instanceMap.get(dto.getBusinessKey()))) {
                    removeList.add(dto);
                }
            }
            // 删除错误信息
            if (removeList.size() > 0) {
                actHisProcessListDTOList.removeAll(removeList);
            }
        } else {
            // 如果正确查询没有信息,则全部去除即可
            actHisProcessListDTOList = new ArrayList<>();
        }
        return actHisProcessListDTOList;
    }

    /**
     * 新流程获取三个月外历史信息
     * @param workFlowTraceListDTO 参数dto
     * @return 任务列表
     */
    public List<WorkFlowTrace> getNewFlowHistoryTraceList(WorkFlowTraceListDTO workFlowTraceListDTO) {
        // 任务列表信息
        List<WorkFlowTrace> traceList = new ArrayList<>();
        // 三个月前信息查询
        if (WorkFlowServerConstant.WORKFLOW_STATUS_FINISHED.equals(workFlowTraceListDTO.getStatus())) {
            workFlowTraceListDTO.setTraceType(WorkFlowServerConstant.STRING_NUM_3);
            // 拼装流程发起参数
            String userId = StrUtil.format(WorkFlowServerConstant.USER_ID_APPEND_TEMPLATE,
                    workFlowTraceListDTO.getUserCd(),
                    workFlowTraceListDTO.getOrgCd());
            // 查询本地备份表信息进行数据查询
            List<ActProcessTrace> processTraceList = actHiTaskinstBackMapper.getActProcessTraceHisList(userId);
            if (ObjectUtil.isNotEmpty(processTraceList)) {
                // 根据系统标识选择自己系统的跟踪列表信息
                if (StrUtil.isBlank(workFlowTraceListDTO.getSystemFlag())
                        || WorkFlowServerConstant.FLOW_TYPE_0.equals(workFlowTraceListDTO.getSystemFlag())) {
                    // 信贷系统
                    processTraceList.removeIf(processInfo -> {
                        String tractTemplateId = processInfo.getProcDefKey();
                        return StrUtil.isBlank(tractTemplateId)
                                || tractTemplateId.toLowerCase().startsWith(WorkFlowServerConstant.RSK_PREFIX)
                                || tractTemplateId.toLowerCase().startsWith(WorkFlowServerConstant.STORE_PREFIX);
                    });
                } else if (WorkFlowServerConstant.STRING_NUM_1.equals(workFlowTraceListDTO.getSystemFlag())) {
                    // 风险系统
                    processTraceList.removeIf(processInfo -> {
                        String tractTemplateId = processInfo.getProcDefKey();
                        return StrUtil.isBlank(tractTemplateId)
                                || !tractTemplateId.toLowerCase().startsWith(WorkFlowServerConstant.RSK_PREFIX);
                    });
                } else if (WorkFlowServerConstant.STRING_NUM_2.equals(workFlowTraceListDTO.getSystemFlag())) {
                    // 储备子系统
                    processTraceList.removeIf(processInfo -> {
                        String tractTemplateId = processInfo.getProcDefKey();
                        return StrUtil.isBlank(tractTemplateId)
                                || !tractTemplateId.toLowerCase().startsWith(WorkFlowServerConstant.STORE_PREFIX);
                    });
                }
                // 整合processIdList信息
                List<String> processIdList = processTraceList.stream().map(
                        ActProcessTrace::getProcInstId
                ).collect(Collectors.toList());

                // 根据流程参数信息获取合同客户信息列表
                QueryWrapper<ActHiVarinstBack> actHiVarinstQueryWrapper = new QueryWrapper<>();
                if (processIdList.size() < OracleInQueryUtil.DEFAULT_SPLIT_SIZE) {
                    actHiVarinstQueryWrapper.lambda().in(ActHiVarinstBack::getProcInstId, processIdList);
                } else {
                    oracleInQueryUtil.queryWrapperIn(actHiVarinstQueryWrapper,
                            "PROC_INST_ID_",
                            processIdList,
                            OracleInQueryUtil.DEFAULT_SPLIT_SIZE);
                }
                List<ActHiVarinstBack> varinstList = actHiVarinstBackMapper.selectList(actHiVarinstQueryWrapper);

                // 将查询信息转换为map信息
                Map<String, Map<String, Object>> paramsMap = new HashMap<>(WorkFlowServerConstant.DEFAULT_MAP_SIZE);
                varinstList.forEach(varinst -> {
                    Map<String, Object> paramMap = paramsMap.get(varinst.getProcInstId());
                    if (ObjectUtil.isNull(paramMap)) {
                        paramMap = new HashMap<>(WorkFlowServerConstant.DEFAULT_MAP_SIZE);
                    }
                    if (WorkFlowServerConstant.BIZ_ID_FLAG.equals(varinst.getName())) {
                        paramMap.put(WorkFlowServerConstant.BUSINESS_KEY_FLAG, varinst.getText());
                    } else if (WorkFlowServerConstant.CUSTOMER_NAME_FLAG.equals(varinst.getName())) {
                        paramMap.put(WorkFlowServerConstant.CUSTOMER_NAME_FLAG, varinst.getText());
                    } else if (WorkFlowServerConstant.CUSTOMER_NUM_FLAG.equals(varinst.getName())) {
                        paramMap.put(WorkFlowServerConstant.CUSTOMER_NUM_FLAG, varinst.getText());
                    } else if (WorkFlowServerConstant.PROCESS_KEY_FLAG.equals(varinst.getName())) {
                        paramMap.put(WorkFlowServerConstant.PROCESS_DEFINITION_ID, varinst.getText());
                        paramMap.put(WorkFlowServerConstant.PROCESS_DEFINITION_KEY, varinst.getText());
                    } else if (WorkFlowServerConstant.CREATOR_FLAG.equals(varinst.getName())) {
                        paramMap.put(WorkFlowServerConstant.START_USER_ID_FLAG, varinst.getText());
                    }

                    // 设置processId
                    paramMap.put(WorkFlowServerConstant.ID_FLAG, varinst.getProcInstId());
                    paramsMap.put(varinst.getProcInstId(), paramMap);
                });

                // map信息转换为合同dto列表信息,一个循环中只可以使用一次iterator.next
                Iterator<Map.Entry<String, Map<String, Object>>> iterator = paramsMap.entrySet().iterator();
                while (iterator.hasNext()) {
                    Map.Entry<String, Map<String, Object>> mapEntry = iterator.next();
                    Map<String, Object> value = mapEntry.getValue();
                    // 获取合同客户信息
                    Object bizNoObj = value.get(WorkFlowServerConstant.BUSINESS_KEY_FLAG);
                    Object customerNumObj = value.get(WorkFlowServerConstant.CUSTOMER_NUM_FLAG);
                    Object customerNameObj = value.get(WorkFlowServerConstant.CUSTOMER_NAME_FLAG);
                    // 空值校验
                    boolean paramCheck = ObjectUtil.isNotNull(bizNoObj)
                            && ObjectUtil.isNotNull(customerNumObj)
                            && ObjectUtil.isNotNull(customerNameObj);
                    if (paramCheck) {
                        // 选填客户名称信息校验
                        boolean checkCustomerName = StrUtil.isBlank(workFlowTraceListDTO.getProcessCustomerName())
                                || (StrUtil.isNotBlank(workFlowTraceListDTO.getProcessCustomerName())
                                && customerNameObj.toString().contains(workFlowTraceListDTO.getProcessCustomerName()));
                        if (!checkCustomerName) {
                            iterator.remove();
                        }
                    } else {
                        iterator.remove();
                    }
                }
                if (ObjectUtil.isNotEmpty(paramsMap)) {
                    processTraceList.forEach(processInfo -> {
                        // 通过业务名称获取客户号,客户名称
                        if (ObjectUtil.isNotEmpty(processInfo.getStartUserId())) {
                            if (ObjectUtil.isNotEmpty(paramsMap.get(processInfo.getProcInstId()))) {
                                Map<String, Object> processMap = paramsMap.get(processInfo.getProcInstId());
                                // 设置start时间为Long类型,下面方法中map获取写死,用于设定开始结束时间
                                Date startTime = processInfo.getStartTime();
                                Date endTime = processInfo.getEndTime();
                                if (ObjectUtil.isNotNull(startTime)) {
                                    processMap.put(WorkFlowServerConstant.START_TIME_FLAG, startTime.getTime());
                                }
                                if (ObjectUtil.isNotNull(endTime)) {
                                    processMap.put(WorkFlowServerConstant.END_TIME_FLAG, startTime.getTime());
                                }

                                // workFlowTrace返回信息拼装
                                buildWorkFlowTraceInfo(workFlowTraceListDTO, traceList,
                                        processMap,
                                        processMap.get(WorkFlowServerConstant.CUSTOMER_NAME_FLAG).toString(),
                                        processMap.get(WorkFlowServerConstant.CUSTOMER_NUM_FLAG).toString());
                            }
                        }
                    });
                    // 设置跟踪列表来源标识字段信息
                    if (ObjectUtil.isNotEmpty(traceList)) {
                        traceList.forEach(trace -> {
                            trace.setTraceType(workFlowTraceListDTO.getTraceType());
                        });
                    }
                }
            }
        }

        // 设置跟踪列表来源标识字段信息
        if (ObjectUtil.isNotEmpty(traceList)) {
            traceList.forEach(trace -> {
                trace.setTraceType(workFlowTraceListDTO.getTraceType());
            });
        }
        return traceList;
    }

    /**
     * workFlowTrace返回信息拼装
     *
     * @param workFlowTraceListDTO
     * @param traceList
     * @param processMap
     * @param customerName
     * @param customerNum
     */
    private void buildWorkFlowTraceInfo(WorkFlowTraceListDTO workFlowTraceListDTO,
                                        List<WorkFlowTrace> traceList,
                                        Map<String, Object> processMap,
                                        String customerName,
                                        String customerNum) {
        // 新增最终返回trace跟踪信息
        WorkFlowTraceVO workFlowTrace = new WorkFlowTraceVO();
        workFlowTrace.setCustomerNum(customerNum);
        workFlowTrace.setCustomerName(customerName);
        workFlowTrace.setStatus(workFlowTraceListDTO.getStatus());
        workFlowTrace.setBizNo(StrUtil.toString(processMap.get(WorkFlowServerConstant.BUSINESS_KEY_FLAG)));

        // 获取循环trace信息模板id与bizType模板进行判断是否赋值
        String tractTemplateId = StrUtil.toString(processMap.get(WorkFlowServerConstant.PROCESS_DEFINITION_KEY));
        if (ObjectUtil.isNotEmpty(workFlowTraceListDTO.getBizTypeTrace())) {
            // 获取产品类型枚举信息
            WorkFlowProductEnum workFlowProductEnum =
                    workFlowUtil.getProductEnumByBizType(workFlowTraceListDTO.getBizTypeTrace());
            // 将tract列表按照bizType 进行过滤,去除非查询type数据
            if (ObjectUtil.isNotNull(workFlowProductEnum)
                    && tractTemplateId.equals(workFlowProductEnum.getTemplateId())) {
                workFlowTrace.setBizType(workFlowProductEnum.getBizType());
                workFlowTrace.setProductType(workFlowProductEnum.getBizTypeName());
                workFlowUtil.addTraceInfoList(traceList, workFlowTrace, processMap);
            }
        } else {
            WorkFlowProductEnum workFlowProductEnum = workFlowUtil.getProductEnumByTemplateId(tractTemplateId);
            // 枚举类型空值判断
            if (ObjectUtil.isNotNull(workFlowProductEnum)) {
                workFlowTrace.setBizType(workFlowProductEnum.getBizType());
                workFlowTrace.setProductType(workFlowProductEnum.getBizTypeName());
                workFlowUtil.addTraceInfoList(traceList, workFlowTrace, processMap);
            }
        }
    }

    /**
     * 查询跟踪列表单条历史数据
     *
     * @param traceHistoryListDTO dto
     * @return WorkFlowTraceHistoryListDTO dto
     */
    @Override
    public WorkFlowTraceHistoryListDTO findTraceHistoryList(WorkFlowTraceHistoryListDTO traceHistoryListDTO) {

        // 通过traceType信息获取不同时间以及新老流程单条历史提交记录信息
        String traceType = traceHistoryListDTO.getTraceType();

        // 如果来源信息为空,默认走近三个月,其中结束流程无退回处理,在途任务有退回处理
        if (StrUtil.isBlank(traceType)
                || WorkFlowServerConstant.STRING_NUM_1.equals(traceType)
                || WorkFlowServerConstant.STRING_NUM_2.equals(traceType)) {
            // 三个月之内activiti(新流程)信息获取,包含完成以及未完成的信息,有回退处理
            traceHistoryListDTO = getNewFlowCommentInThreeMonth(traceHistoryListDTO);
        } else if (WorkFlowServerConstant.STRING_NUM_3.equals(traceType)) {
            // activiti(新流程)三月外,已结束信息
            traceHistoryListDTO = getNewFlowCommentOutThreeMonth(traceHistoryListDTO);
        } else if (WorkFlowServerConstant.STRING_NUM_5.equals(traceType) || WorkFlowServerConstant.STRING_NUM_6.equals(traceType)) {
            // 老流程历史意见信息获取
            traceHistoryListDTO = getOldFlowCommon(traceHistoryListDTO);
        }

        return traceHistoryListDTO;
    }

    /**
     * 获取老流程意见信息
     * @param traceHistoryListDTO 参数dto
     * @return 列表信息
     */
    public WorkFlowTraceHistoryListDTO getOldFlowCommon(WorkFlowTraceHistoryListDTO traceHistoryListDTO) {
        // 意见信息列表
        List<WorkFlowTaskCommon> commonList;
        if (WorkFlowServerConstant.STRING_NUM_5.equals(traceHistoryListDTO.getTraceType())) {
            // 老流程三月内信息
            commonList = wfmidAppProcessInstanceMapper.findTaskInfoList(traceHistoryListDTO.getProcessId());
        } else {
            // 老流程三月外信息
            commonList = wfmidAppProcessInstanceMapper.findHisTaskInfoList(traceHistoryListDTO.getProcessId());
        }
        if (ObjectUtil.isNotEmpty(commonList)) {
            // 返回意见信息列表信息
            List<WorkFlowTraceHistory> workFlowTraceHistoryList = new ArrayList<>();
            commonList.forEach(common -> {
                WorkFlowTraceHistory workFlowTraceHistory = new WorkFlowTraceHistory();
                if (ObjectUtil.isNotNull(common.getTaskFinishTime())) {
                    workFlowTraceHistory.setFinishDate(common.getTaskFinishTime());
                    workFlowTraceHistory.setFinishDateStr(DateUtil.format(common.getTaskFinishTime(), DatePattern.NORM_DATETIME_PATTERN));
                    workFlowTraceHistory.setProcessId(traceHistoryListDTO.getProcessId());
                    workFlowTraceHistory.setOpinion(common.getProcessComment());
                    workFlowTraceHistory.setTaskId(common.getTaskId());
                    workFlowTraceHistory.setPositionName(common.getActivityId());
                    workFlowTraceHistory.setOrgCd(common.getTaskOrgCd());
                    workFlowTraceHistory.setUserCd(common.getOwner());
                    // 获取柜员名称
                    ManageUserDTO param = new ManageUserDTO();
                    param.setUserCd(common.getOwner());
                    ManageUserDTO userDTO = managementApiClient.findUserNameByUserCd(param);
                    workFlowTraceHistory.setUserName(userDTO.getUserName());
                    // 获取机构名称
                    if (StrUtil.isNotBlank(common.getTaskOrgCd())) {
                        List<String> params = new ArrayList<>();
                        params.add(common.getTaskOrgCd());
                        ManageOrganizationListDTO orgDTO = organizationApiFeignClient.listInfoByOrgCdList(params);
                        if (ObjectUtil.isNotEmpty(orgDTO.getOrganizationInfoList())) {
                            workFlowTraceHistory.setOrgName(orgDTO.getOrganizationInfoList()
                                    .get(WorkFlowServerConstant.INT_NUM_0).getOrgName());
                        }
                    } else {
                        workFlowTraceHistory.setOrgName(WorkFlowServerConstant.ORG_LOSE_FLAG);
                    }
                    // 获取业务客户信息
                    if (StrUtil.isBlank(traceHistoryListDTO.getCustomerName())) {
                        traceHistoryListDTO.setCustomerName(common.getCustomerName());
                    }
                    if (StrUtil.isBlank(traceHistoryListDTO.getCustomerNum())) {
                        traceHistoryListDTO.setCustomerNum(common.getCustomerNum());
                    }
                    workFlowTraceHistoryList.add(workFlowTraceHistory);
                }
            });

            if (ObjectUtil.isNotEmpty(workFlowTraceHistoryList)) {
                // 设置查询分页信息
                WorkFlowPage page = pageUtil.setFlowListPage(workFlowTraceHistoryList, PaginationContext.getPageNum(),
                        workFlowTraceHistoryList.size());
                traceHistoryListDTO.setPage(page);
            }
            traceHistoryListDTO.setContractStatusInfo(WorkFlowServerConstant.CONTRACT_STATUS_AGREE);

        }
        return traceHistoryListDTO;
    }

    /**
     * 三个月之前activiti(新流程)意见信息获取,只有完成任务的信息,且无退回相关信息
     * @param traceHistoryListDTO 参数dto
     * @return 列表信息
     */
    public WorkFlowTraceHistoryListDTO getNewFlowCommentOutThreeMonth(WorkFlowTraceHistoryListDTO traceHistoryListDTO) {
        // 意见列表信息
        List<WorkFlowTraceHistory> historyList = new ArrayList<>();

        // 获取所有过程意见信息
        QueryWrapper<ActHiActinstBack> actHiActinstQueryWrapper = new QueryWrapper<>();
        actHiActinstQueryWrapper.lambda().eq(ActHiActinstBack::getProcInstId, traceHistoryListDTO.getProcessId());
        List<ActHiActinstBack> actHiActinstBackList = actHiActinstBackMapper.selectList(actHiActinstQueryWrapper);
        if (ObjectUtil.isNotEmpty(actHiActinstBackList)) {
            actHiActinstBackList.forEach(actHiActinstBack -> {
                // 去除开始以及结束节点信息
                if (WorkFlowServerConstant.START_FLAG.equals(actHiActinstBack.getActName())
                        || WorkFlowServerConstant.END_FLAG.equals(actHiActinstBack.getActName())) {
                    return;
                }
                // 判断节点是否为task节点
                boolean ifTask = WorkFlowServerConstant.EXCLUSIVE_GATEWAY.equals(actHiActinstBack.getActId())
                        || WorkFlowServerConstant.PARALLEL_GATEWAY.equals(actHiActinstBack.getActId())
                        || WorkFlowServerConstant.INCLUSIVE_GATEWAY.equals(actHiActinstBack.getActId())
                        || WorkFlowServerConstant.EVENT_GATEWAY.equals(actHiActinstBack.getActId());
                if (!ifTask && StrUtil.isNotBlank(actHiActinstBack.getTaskId())) {
                    QueryWrapper<ActHiCommentBack> commentQueryWrapper = new QueryWrapper<>();
                    commentQueryWrapper.lambda().eq(ActHiCommentBack::getTaskId, actHiActinstBack.getTaskId())
                            .eq(ActHiCommentBack::getType, WorkFlowServerConstant.COMMENT_FLAG);
                    ActHiCommentBack actHiCommentBack = actHiCommentBackMapper.selectOne(commentQueryWrapper);
                    WorkFlowTraceHistory traceHistory = new WorkFlowTraceHistory();
                    // 结束时间
                    if (ObjectUtil.isNotNull(actHiActinstBack.getEndTime())) {
                        traceHistory.setFinishDate(actHiActinstBack.getEndTime());
                        traceHistory.setFinishDateStr(DateUtil.format(actHiActinstBack.getEndTime(), DatePattern.NORM_DATETIME_PATTERN));
                    }
                    // processId
                    traceHistory.setProcessId(actHiActinstBack.getProcInstId());
                    // 岗位名称
                    traceHistory.setPositionName(actHiActinstBack.getActName());
                    // 评论信息
                    if (ObjectUtil.isNotNull(actHiCommentBack)) {
                        traceHistory.setOpinion(actHiCommentBack.getMessage());
                    }
                    // 任务办理人信息
                    if (StrUtil.isNotBlank(actHiActinstBack.getAssignee())) {
                        String[] handingInfo = StrUtil.toString(actHiActinstBack.getAssignee())
                                .split(WorkFlowServerConstant.SPLIT_FLAG);
                        traceHistory.setUserCd(handingInfo[0]);
                        if (ObjectUtil.isNotNull(handingInfo[0])
                                && !WorkFlowServerConstant.NULL_STR.equalsIgnoreCase(handingInfo[0])) {
                            ManageUserDTO param = new ManageUserDTO();
                            param.setUserCd(handingInfo[0]);
                            ManageUserDTO userNameByUserCd = managementApiClient.findUserNameByUserCd(param);
                            traceHistory.setUserName(userNameByUserCd.getUserName());
                        }
                        if (handingInfo.length > 1) {
                            traceHistory.setOrgCd(handingInfo[1]);
                            List<String> params = new ArrayList<>();
                            params.add(handingInfo[1]);
                            ManageOrganizationListDTO manageOrganizationListDTO = organizationApiFeignClient.listInfoByOrgCdList(params);
                            if (manageOrganizationListDTO.getOrganizationInfoList() != null && manageOrganizationListDTO.getOrganizationInfoList().size() == 1) {
                                traceHistory.setOrgName(manageOrganizationListDTO.getOrganizationInfoList().get(0).getOrgName());
                            }
                        }
                    }
                    // 任务id
                    traceHistory.setTaskId(actHiActinstBack.getTaskId());
                    // 去除发起头以及结尾信息
                    if (!WorkFlowServerConstant.START_FLAG.equals(actHiActinstBack.getActName())
                            && !WorkFlowServerConstant.END_FLAG.equals(actHiActinstBack.getActName())) {
                        historyList.add(traceHistory);
                    }
                }
            });

            historyList.sort((history, history2) -> {
                if (ObjectUtil.isNull(history.getFinishDate()) && ObjectUtil.isNotNull(history2.getFinishDate())) {
                    return -1;
                } else if (ObjectUtil.isNull(history2.getFinishDate()) && ObjectUtil.isNotNull(history.getFinishDate())) {
                    return 1;
                } else if (history.getFinishDate().compareTo(history2.getFinishDate()) > 0) {
                    return -1;
                } else if (history.getFinishDate().compareTo(history2.getFinishDate()) < 0) {
                    return 1;
                } else {
                    return 0;
                }
            });

            if (ObjectUtil.isNotEmpty(historyList)) {
                // 设置查询分页信息
                WorkFlowPage page = pageUtil.setFlowListPage(historyList, PaginationContext.getPageNum(),
                        historyList.size());
                traceHistoryListDTO.setPage(page);
            }
        }

        // 意见信息
        String contractStatus = WorkFlowServerConstant.CONTRACT_STATUS_AGREE;
        traceHistoryListDTO.setContractStatusInfo(contractStatus);

        // 获取业务客户信息
        List<TbSysUnfinishedFlowHis> unfinishedFlowList = tbSysUnfinishedFlowHisMapper
                .getUnFinishedFlowList(traceHistoryListDTO.getBizNo());
        if (ObjectUtil.isNotEmpty(unfinishedFlowList)) {
            // 获取业务客户信息
            if (ObjectUtil.isNotEmpty(unfinishedFlowList)) {
                traceHistoryListDTO.setCustomerName(
                        unfinishedFlowList.get(WorkFlowServerConstant.PAGE_INDEX).getCustomerName());
                traceHistoryListDTO.setCustomerNum(
                        unfinishedFlowList.get(WorkFlowServerConstant.PAGE_INDEX).getCustomerNum());
            }
        } else {
            // 为老流程三个月前信息,需要从 ACT_HI_VARINST_BACK 中获取客户信息
            QueryWrapper<ActHiVarinstBack> actHiVarinstQueryWrapper = new QueryWrapper<>();
            actHiVarinstQueryWrapper.lambda().eq(ActHiVarinstBack::getProcInstId, traceHistoryListDTO.getProcessId());
            List<ActHiVarinstBack> varinstList = actHiVarinstBackMapper.selectList(actHiVarinstQueryWrapper);
            if (ObjectUtil.isNotEmpty(varinstList)) {
                for (ActHiVarinstBack varinst: varinstList) {
                    if (WorkFlowServerConstant.CUSTOMER_NUM_FLAG.equals(varinst.getName())
                            && StrUtil.isBlank(traceHistoryListDTO.getCustomerNum())) {
                        traceHistoryListDTO.setCustomerNum(varinst.getText());
                    }
                    if (WorkFlowServerConstant.CUSTOMER_NAME_FLAG.equals(varinst.getName())
                            && StrUtil.isBlank(traceHistoryListDTO.getCustomerName())) {
                        traceHistoryListDTO.setCustomerName(varinst.getText());
                    }
                }
            }
        }

        return traceHistoryListDTO;
    }

    /**
     * 三个月之内activiti(新流程)意见信息获取,包含完成以及未完成的信息
     * @param traceHistoryListDTO 参数dto
     * @return 意见信息列表
     */
    public WorkFlowTraceHistoryListDTO getNewFlowCommentInThreeMonth(WorkFlowTraceHistoryListDTO traceHistoryListDTO) {
        // 获取当前登录柜员编号以及机构号
        String currentOrgCd = webUtil.getCurrentOrgCd();
        String currentUserCd = webUtil.getCurrentUserCd();

        // 获取列表
        List<WorkFlowTraceHistory> historyList = findHistoryList(traceHistoryListDTO.getUserCd(),
                traceHistoryListDTO.getOrgCd(),
                traceHistoryListDTO.getProcessId());

        // 所有列表信息
        List<TbSysBackPositionInfo> allBackPositionInfoList = null;

        // 空值校验
        if (ObjectUtil.isNotEmpty(historyList)) {
            // 获取结束时间为空的任务信息
            WorkFlowTraceHistory makTaskHistory = historyList.stream().filter(task ->
                    ObjectUtil.isNull(task.getFinishDate())
            ).findAny().orElse(null);

            // 获取当前processId全部历史意见信息
            allBackPositionInfoList = tbSysBackPositionInfoMapper.getAllBackPositionInfoList(traceHistoryListDTO.getProcessId());

            // 去除删除数据
            List<TbSysBackPositionInfo> tbSysBackPositionInfoList = null;
            if (ObjectUtil.isNotNull(allBackPositionInfoList)) {
                tbSysBackPositionInfoList = allBackPositionInfoList.stream().filter(backPosition ->
                        WorkFlowServerConstant.FLOW_TYPE_0.equals(backPosition.getIsDel())
                ).collect(Collectors.toList());
            }

            // 判断是否需要撤销操作
            if (ObjectUtil.isNotEmpty(tbSysBackPositionInfoList)
                    && StrUtil.isNotBlank(tbSysBackPositionInfoList.get(WorkFlowServerConstant.INT_NUM_0)
                    .getWorkFlowTemplateId())) {
                // 获取上一岗位对应信息
                TbSysBackPositionInfo backPositionInfo = tbSysBackPositionInfoList.get(WorkFlowServerConstant.INT_NUM_0);
                // 获取岗位cd名称对应关系
                QueryWrapper<TbSysFlowPosition> positionQueryWrapper = new QueryWrapper<>();
                positionQueryWrapper.lambda().eq(TbSysFlowPosition::getFlowTempletNum, backPositionInfo.getWorkFlowTemplateId());
                TbSysFlowPosition flowPosition = tbSysFlowPositionMapper.selectOne(positionQueryWrapper);
                if (ObjectUtil.isNotNull(flowPosition)) {
                    QueryWrapper<TbSysFlowPositionDetail> detailQueryWrapper = new QueryWrapper<>();
                    detailQueryWrapper.lambda().eq(TbSysFlowPositionDetail::getFlowId, flowPosition.getFlowId());
                    List<TbSysFlowPositionDetail> detailList = tbSysFlowPositionDetailMapper.selectList(detailQueryWrapper);
                    // 将岗位信息变更为map,方便使用获取
                    Map<String, String> positionMap = detailList.stream().collect(Collectors.toMap(
                            TbSysFlowPositionDetail::getActivitiId, TbSysFlowPositionDetail::getPositionName, (k1, k2) -> k1
                    ));

                    // 通过activitiId获取positionName
                    String positionName = positionMap.get(backPositionInfo.getActivitiId());
                    // 如果岗位为调查岗确认 则业务不允许上一岗位撤回,撤回按钮不显示
                    if (ObjectUtil.isNotNull(makTaskHistory)
                            && !WorkFlowServerConstant.POSITION_CONFIRM.equals(makTaskHistory.getPositionName())) {
                        for (WorkFlowTraceHistory history : historyList) {
                            if (history.getPositionName().equals(positionName)
                                    && currentOrgCd.equals(history.getOrgCd())
                                    && currentUserCd.equals(history.getUserCd())) {
                                history.setCancelFlag(WorkFlowServerConstant.STRING_NUM_1);
                                break;
                            }
                        }
                    }
                    // 如果没有结束时间未填的任务节点
                    if (ObjectUtil.isNotNull(makTaskHistory)) {
                        traceHistoryListDTO.setSubmitBackPrefixTaskId(makTaskHistory.getTaskId());
                    }
                }
            }
        }

        if (ObjectUtil.isNotEmpty(historyList)) {
            historyList.sort(new Comparator<WorkFlowTraceHistory>() {
                @Override
                public int compare(WorkFlowTraceHistory history, WorkFlowTraceHistory history2) {
                    if (ObjectUtil.isNull(history.getFinishDate()) && ObjectUtil.isNotNull(history2.getFinishDate())) {
                        return -1;
                    } else if (ObjectUtil.isNull(history2.getFinishDate()) && ObjectUtil.isNotNull(history.getFinishDate())) {
                        return 1;
                    } else if (history.getFinishDate().compareTo(history2.getFinishDate()) > 0) {
                        return -1;
                    } else if (history.getFinishDate().compareTo(history2.getFinishDate()) < 0) {
                        return 1;
                    } else {
                        return 0;
                    }
                }
            });

            // 判断如果本地记录信息和activiti查询列表信息条数相同,并且activiti无意见信息,则替换本地意见信息
            if (ObjectUtil.isNotNull(allBackPositionInfoList)
                    && ObjectUtil.isNotEmpty(historyList)
                    && allBackPositionInfoList.size() + 1 == historyList.size()) {
                for (int index = 1; index < historyList.size(); index++) {
                    WorkFlowTraceHistory traceHistory = historyList.get(index);
                    if (ObjectUtil.isNotNull(traceHistory) && StrUtil.isBlank(traceHistory.getOpinion())) {
                        // 替换本地意见信息
                        traceHistory.setOpinion(allBackPositionInfoList.get(index - 1).getFlowComment());
                    }
                }
            }

            // 设置查询分页信息
            WorkFlowPage page = pageUtil.setFlowListPage(historyList, PaginationContext.getPageNum(),
                    historyList.size());
            traceHistoryListDTO.setPage(page);
        }

        // 获取业务客户信息
        List<TbSysUnfinishedFlow> unfinishedFlowList = tbSysUnfinishedFlowMapper
                .getUnFinishedFlowList(traceHistoryListDTO.getBizNo());
        // 意见信息
        String contractStatus = WorkFlowServerConstant.CONTRACT_STATUS_AGREE;
        // 获取业务客户信息
        if (ObjectUtil.isNotEmpty(unfinishedFlowList)) {
            traceHistoryListDTO.setCustomerName(
                    unfinishedFlowList.get(WorkFlowServerConstant.PAGE_INDEX).getCustomerName());
            traceHistoryListDTO.setCustomerNum(
                    unfinishedFlowList.get(WorkFlowServerConstant.PAGE_INDEX).getCustomerNum());
        }
        traceHistoryListDTO.setContractStatusInfo(contractStatus);
        return traceHistoryListDTO;
    }

    /**
     * 查询跟踪列表历史任务通用方法
     *
     * @param userCd    柜员号
     * @param orgCd     机构cd
     * @param processId 流程实例id
     */
    public List<WorkFlowTraceHistory> findHistoryList(String userCd, String orgCd, String processId) {
        // 拼装流程发起参数
        String userId = StrUtil.format(WorkFlowServerConstant.USER_ID_APPEND_TEMPLATE, userCd, orgCd);

        // 设置权限信息
        identityService.setAuthenticatedUserId(userId);

        // 格式化时间格式
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DatePattern.NORM_DATETIME_PATTERN);

        // 查询并且解析查询结果信息
        List<WorkFlowTraceHistory> historyList = new ArrayList<>();
        List<WorkFlowActHisActInstListDTO> hisActInstListDTOList = queryHisTaskList(processId);
        // 传输对象转换为 Map 对象
        if (ObjectUtil.isNotEmpty(hisActInstListDTOList)) {
            hisActInstListDTOList.forEach(hisActInst -> {
                // 最终返回对象
                WorkFlowTraceHistory traceHistory = new WorkFlowTraceHistory();
                // 结束时间
                if (ObjectUtil.isNotEmpty(hisActInst.getEndTime())) {
                    traceHistory.setFinishDate(hisActInst.getEndTime());
                    traceHistory.setFinishDateStr(simpleDateFormat.format(traceHistory.getFinishDate()));
                }
                // processId
                traceHistory.setProcessId(hisActInst.getProcessInstanceId());
                // 岗位名称
                traceHistory.setPositionName(hisActInst.getActivityName());
                // 评论信息
                traceHistory.setOpinion(hisActInst.getOpinion());
                // 任务办理人信息
                if (StrUtil.isNotBlank(hisActInst.getAssignee())) {
                    String[] handingInfo = StrUtil.toString(hisActInst.getAssignee())
                            .split(WorkFlowServerConstant.SPLIT_FLAG);
                    traceHistory.setUserCd(handingInfo[0]);
                    if (handingInfo[0] != null && !WorkFlowServerConstant.NULL_STR.equalsIgnoreCase(handingInfo[0])) {
                        ManageUserDTO param = new ManageUserDTO();
                        param.setUserCd(handingInfo[0]);
                        ManageUserDTO userNameByUserCd = managementApiClient.findUserNameByUserCd(param);
                        traceHistory.setUserName(userNameByUserCd.getUserName());
                    }
                    if (handingInfo.length > 1) {
                        traceHistory.setOrgCd(handingInfo[1]);
                        List<String> params = new ArrayList<>();
                        params.add(handingInfo[1]);
                        ManageOrganizationListDTO manageOrganizationListDTO = organizationApiFeignClient.listInfoByOrgCdList(params);
                        if (manageOrganizationListDTO.getOrganizationInfoList() != null && manageOrganizationListDTO.getOrganizationInfoList().size() == 1) {
                            traceHistory.setOrgName(manageOrganizationListDTO.getOrganizationInfoList().get(0).getOrgName());
                        }
                    }
                }
                // 任务id
                traceHistory.setTaskId(hisActInst.getTaskId());
                // 去除发起头以及结尾信息
                if (!WorkFlowServerConstant.START_FLAG.equals(hisActInst.getActivityName())
                        && !WorkFlowServerConstant.END_FLAG.equals(hisActInst.getActivityName())) {
                    historyList.add(traceHistory);
                }
            });
        }
        return historyList;
    }

    /**
     * 根据历史流程实例id查询历史任务实例
     *
     * @param processId 流程实例id
     */
    public List<WorkFlowActHisActInstListDTO> queryHisTaskList(String processId) {
        // 获取历史活动实例
        HistoricActivityInstanceQuery activityInstanceQuery = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(processId)
                .orderByHistoricActivityInstanceId()
                .desc();
        // 获取历史活动实例列表
        List<HistoricActivityInstance> activityInstanceList = activityInstanceQuery.list();

        // 类型信息转换
        List<WorkFlowActHisActInstListDTO> actHisActInstListDTOList = activityInstanceList.stream().map(instance ->
                activitiConvert.hisInstanceToActList(instance)
        ).collect(Collectors.toList());

        // 进行非task节点信息判定,排除无用节点
        actHisActInstListDTOList = actHisActInstListDTOList.stream().filter(actInst -> {
            boolean ifRightType = actInst.getActivityType().equals(WorkFlowServerConstant.EXCLUSIVE_GATEWAY)
                    || actInst.getActivityType().equals(WorkFlowServerConstant.PARALLEL_GATEWAY)
                    || actInst.getActivityType().equals(WorkFlowServerConstant.INCLUSIVE_GATEWAY)
                    || actInst.getActivityType().equals(WorkFlowServerConstant.EVENT_GATEWAY);
            return !ifRightType;
        }).collect(Collectors.toList());

        // 设置common评论信息
        actHisActInstListDTOList.forEach(actInst -> {
            // 获取common信息
            List<Comment> commentList = taskService.getTaskComments(actInst.getTaskId());
            if (ObjectUtil.isNotEmpty(commentList)) {
                // 设置评论信息
                actInst.setOpinion(commentList.get(0).getFullMessage());
            }
        });

        return actHisActInstListDTOList;
    }

    /**
     * 获取下一处理环节
     *
     * @param workFlowNextPositionDTO dto
     * @return WorkFlowNextPositionDTO dto
     */
    @Override
    public WorkFlowNextPositionDTO findNextPositionList(WorkFlowNextPositionDTO workFlowNextPositionDTO) {
        // 参数校验
        if (StrUtil.isBlank(workFlowNextPositionDTO.getTaskId())) {
            throw new ServiceException("传入用户taskId信息为空!");
        }
        if (StrUtil.isBlank(workFlowNextPositionDTO.getCurrentActivityId())) {
            throw new ServiceException("传入用户当前activitiId信息为空!");
        }

        // 获取task信息
        Task task = taskService.createTaskQuery()
                .taskId(workFlowNextPositionDTO.getTaskId())
                .singleResult();

        // 获取全部流程自定义变量信息
        Map<String, Object> taskVariables = runtimeService.getVariables(task.getExecutionId());

        // 如果模板信息没有传递,则通过参数获取
        if (StrUtil.isBlank(workFlowNextPositionDTO.getProcessName())
                && ObjectUtil.isNotNull(taskVariables.get(WorkFlowServerConstant.BIZ_TYPE_FLAG))) {
            // 通过bizType获取流程产品枚举类型
            String bizType = taskVariables.get(WorkFlowServerConstant.BIZ_TYPE_FLAG).toString();
            WorkFlowProductEnum productEnum = workFlowUtil.getProductEnumByBizType(bizType);
            if (ObjectUtil.isNotNull(productEnum)) {
                workFlowNextPositionDTO.setProcessName(productEnum.getTemplateId());
            }
        }

        // 任务进行跳节点,获取实际发起节点的流程定义信息
        ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
                .getDeployedProcessDefinition(task.getProcessDefinitionId());

        // 获取当前节点信息,可以获取outgoingSequenceFlows,结合自定义变量信息,可以获取下一节点信息
        ActivityImpl currentActivity = processDefinition.findActivity(task.getTaskDefinitionKey());

        // 获取当前节点对外指向,并且对指向进行分析
        List<PvmTransition> transitionList = currentActivity.getOutgoingTransitions();
        if (ObjectUtil.isEmpty(transitionList)) {
            return workFlowNextPositionDTO;
        }

        // 最终获取全部下一处理岗位定义节点
        List<PvmActivity> finalActivityList = new ArrayList<>();

        // 循环获取目标节点信息,当前行内服务,只使用排他网关,所以后续分支只支持单一条件满足,下一节点为单一分支
        for (PvmTransition transition : transitionList) {
            // 获取目标节点
            PvmActivity destinationActivity = transition.getDestination();
            // 获取目标节点nodeType类型
            String activityNodeType = StrUtil.toString(destinationActivity.getProperty(WorkFlowServerConstant.NODE_TYPE));
            // 目标节点不同类型进行不同处理,
            if (WorkFlowServerConstant.EXCLUSIVE_GATEWAY.equals(activityNodeType) || WorkFlowServerConstant.INCLUSIVE_GATEWAY.equals(activityNodeType)) {
                // 注意此处为 节点->排他网关/包含网关->节点 形式,更复杂形式需要针对业务进行调整
                List<PvmActivity> exclusiveGateActivityList = activitiUtil.getNextPositionByExclusiveGateway(destinationActivity, taskVariables);
                finalActivityList.addAll(exclusiveGateActivityList);
            } else if (WorkFlowServerConstant.PARALLEL_GATEWAY.equals(activityNodeType)) {
                // 并行网关 节点->并行网关->节点
                List<PvmActivity> parallelGateActivityList = activitiUtil.getNextPositionByParallelGateway(destinationActivity);
                finalActivityList.addAll(parallelGateActivityList);
            } else if (WorkFlowServerConstant.USER_TASK_FLAG.equalsIgnoreCase(activityNodeType)) {
                // 普通用户任务 节点->节点
                finalActivityList.add(destinationActivity);
            } else {
                throw new ServiceException(StrUtil.format("当前获取下一岗位信息暂时activityNodeType[{}]暂时不支持!", activityNodeType));
            }
        }

        // 获取下一岗位信息非空判定
        if (ObjectUtil.isEmpty(finalActivityList)) {
            throw new ServiceException(StrUtil.format("当前taskId[{}]对应节点[{}]获取下一岗位信息为空!",
                    workFlowNextPositionDTO.getTaskId(), task.getTaskDefinitionKey()));
        }

        // 获取下一岗位名称id信息
        ActivityImpl nextActivity = (ActivityImpl)finalActivityList.get(0);
        String nextActivityName = nextActivity.getProperty(WorkFlowServerConstant.NAME_FLAG).toString();
        // 下一岗位id
        TaskDefinition taskDefinition = (TaskDefinition)nextActivity.getProperty(WorkFlowServerConstant.TASK_DEFINITION);
        String nextActivityId = taskDefinition.getKey();

        // 构建页面下拉选择框 "-1" / "请选择"以及其他下拉列表信息
        List<WorkFlowNextPosition> nextPositionList = new ArrayList<>();
        Map<String, String> itemMap = new HashMap<>(WorkFlowServerConstant.DEFAULT_MAP_SIZE);
        itemMap.put(WorkFlowServerConstant.DEFAULT_ITEM_KEY, WorkFlowServerConstant.DEFAULT_ITEM_VALUE);
        nextPositionList.add(new WorkFlowNextPosition(WorkFlowServerConstant.DEFAULT_ITEM_KEY,
                WorkFlowServerConstant.DEFAULT_ITEM_VALUE));
        // 查询岗位信息拼接串,当前岗位信息
        List<Map<String, String>> currentPositionList = null;
        if (StrUtil.isNotBlank(workFlowNextPositionDTO.getCurrentActivityId())) {
            currentPositionList = tbSysFlowPositionDetailMapper.listPositionInfo(
                    workFlowNextPositionDTO.getProcessName(), workFlowNextPositionDTO.getCurrentActivityId());
        }

        // 如果返回 nextActivityName 为 end 则不查询下一处理人 证明当前岗位为最后一岗
        if (ObjectUtil.isNotEmpty(currentPositionList)
                && !StrUtil.equalsIgnoreCase(nextActivityName, WorkFlowServerConstant.END_FLAG)) {
            // 获取流程实例id
            String processId = task.getProcessInstanceId();

            if (StrUtil.isBlank(processId)) {
                throw new ServiceException(StrUtil.format("通过taskId[]获取流程实例信息失败!",
                        workFlowNextPositionDTO.getTaskId()));
            }

            // 获取当前业务发起机构
            TbSysBackPositionInfo tbSysBackPositionInfo = tbSysBackPositionInfoMapper
                    .getBackPositionInfoByProcessId(processId);
            if (ObjectUtil.isNull(tbSysBackPositionInfo)) {
                throw new ServiceException(StrUtil.format("通过process[{}]获取发起机构信息失败!", processId));
            }

            // 获取当前岗位信息对应跳岗信息,此处传入机构编号,从发起业务机构向上查询,
            WorkFlowJumpDTO workFlowJumpDTO = new WorkFlowJumpDTO();
            workFlowJumpDTO.setOrgCd(tbSysBackPositionInfo.getOptionOrgCd());
            workFlowJumpDTO.setPositionName(workFlowNextPositionDTO.getCurrentActivityId());
            workFlowJumpDTO.setTemplateNum(workFlowNextPositionDTO.getProcessName());
            workFlowJumpDTO = queryWorkFlowApiFeignClient.queryJumpWorkFlow(workFlowJumpDTO);

            log.info("流程processId[{}],下一岗位信息为[{}],获取跳岗信息为[{}],是否有权为[{}]",
                    processId,
                    nextActivityName,
                    JSONObject.toJSONString(workFlowJumpDTO.getNextPositionArray()),
                    workFlowNextPositionDTO.getRuleResult());

            // 跳岗下一岗位不为空,则正常显示跳岗信息,正常下一岗位不显示
            // 2022-11-09 新增有权字段 如果为有权 则正常提交下一岗位
            if (StrUtil.isNotBlank(workFlowJumpDTO.getNextPositionArray())
                    && !WorkFlowConstant.STRING_NUM_1.equals(workFlowNextPositionDTO.getRuleResult())
                    && !WorkFlowConstant.STRING_NUM_2.equals(workFlowNextPositionDTO.getRuleResult())) {
                // 跳岗位岗位名称
                String activityIds = workFlowJumpDTO.getNextPositionArray();
                List<String> positionNameList = Arrays
                        .asList(activityIds.split(WorkFlowServerConstant.SPLIT_COMMA_FLAG));
                // 跳岗返回key格式: activitiId{usertask10},调查岗{positionName},1{positionLevelCd},NPD0001{positionCd}
                List<Map<String, String>> dropPositionDetailList = tbSysFlowPositionDetailMapper.listDropPositionList(
                        workFlowNextPositionDTO.getProcessName(), positionNameList);
                dropPositionDetailList.forEach(positionInfo -> {
                    String dropPositionInfo = StrUtil.format(WorkFlowServerConstant.POSITION_TEMPLATE_ACTIVITY_ID,
                            positionInfo.get(WorkFlowServerConstant.ACTIVITI_ID_FLAG),
                            positionInfo.get(WorkFlowServerConstant.POSITION_NAME_FLAG),
                            positionInfo.get(WorkFlowServerConstant.POSITION_LEVEL_CD_FLAG),
                            positionInfo.get(WorkFlowServerConstant.POSITION_CD_FLAG));
                    itemMap.put(dropPositionInfo, positionInfo.get(WorkFlowServerConstant.POSITION_NAME_FLAG));
                    nextPositionList.add(new WorkFlowNextPosition(dropPositionInfo,
                            positionInfo.get(WorkFlowServerConstant.POSITION_NAME_FLAG)));
                });
            } else {
                // 获取正常下一岗位信息,返回key格式: 调查岗{positionName},1{positionLevelCd},NPD0001{positionCd}
                List<Map<String, String>> nextPositionMapList = tbSysFlowPositionDetailMapper.listPositionInfo(
                        workFlowNextPositionDTO.getProcessName(), nextActivityId);
                if (ObjectUtil.isNotEmpty(nextPositionMapList)) {
                    Map<String, String> nextPositionMap = nextPositionMapList.get(0);
                    String positionStrInfo = StrUtil.format(WorkFlowServerConstant.POSITION_INFO_APPEND_TEMPLATE,
                            nextActivityName,
                            nextPositionMap.get(WorkFlowServerConstant.POSITION_LEVEL_CD_FLAG),
                            nextPositionMap.get(WorkFlowServerConstant.POSITION_CD_FLAG));
                    itemMap.put(positionStrInfo, nextActivityName);
                    nextPositionList.add(new WorkFlowNextPosition(positionStrInfo, nextActivityName));
                }
            }
        }
        workFlowNextPositionDTO.setNextPositionMap(itemMap);
        workFlowNextPositionDTO.setNextPositionList(nextPositionList);
        return workFlowNextPositionDTO;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值