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

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

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

java 复制代码
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;

    /**
     * 获取待投票列表信息
     *
     * @param customerNum 客户号
     * @return page
     */
    @Override
    public PageBean<PageTbConVote> pageVoteMeetingList(String customerNum) {
        Page page = new Page(PaginationContext.getPageNum(), PaginationContext.getPageSize());
        QueryWrapper<TbConVote> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TbConVote::getCustomerNum, customerNum);
        IPage<PageTbConVote> iPage = tbConVoteMapper.findTbConVoteList(page, customerNum);
        PageBean<PageTbConVote> pageBean = new PageBean<>(iPage);
        iPage.getRecords().forEach(pageVote -> {
            pageVote.setApplyTypeName(workFlowUtil.getProductEnumByBizType(pageVote.getApplyType()).getBizTypeName());
        });
        return pageBean;
    }

    /**
     * 获取待投票列表信息
     *
     * @param userCd 柜员编号  orgCd 机构编号
     * @return List<TbConVote> 投票列表信息
     */
    @Override
    public List<TbConVote> findVoteMeetingList(String userCd, String orgCd) {
        QueryWrapper<TbConVote> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TbConVote::getUserNum, userCd);
        queryWrapper.lambda().eq(TbConVote::getOrgCd, orgCd);
        queryWrapper.lambda().eq(TbConVote::getStatus, WorkFlowServerConstant.VOTE_ACTIVE_STATUS);
        queryWrapper.lambda().isNull(TbConVote::getVote);
        queryWrapper.and(qr -> qr.like("BIZ_NUM", "GZJC%").or().like("BIZ_NUM", "MEET%"));
        List<TbConVote> voteList = tbConVoteMapper.selectList(queryWrapper);
        return voteList;
    }

    /**
     * 获取待投票列表信息
     *
     * @param userCd 柜员编号  orgCd 机构编号
     * @return List<TbConVote> 投票列表信息
     */
    @Override
    public List<TbConVote> findVoteMeetingList1(String userCd, String orgCd) {
        QueryWrapper<TbConVote> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TbConVote::getUserNum, userCd);
        queryWrapper.lambda().eq(TbConVote::getOrgCd, orgCd);
        queryWrapper.lambda().eq(TbConVote::getStatus, WorkFlowServerConstant.VOTE_ACTIVE_STATUS);
        queryWrapper.lambda().isNull(TbConVote::getVote);
        queryWrapper.lambda().notLike(TbConVote::getBizNum, "GZJC%");
        queryWrapper.lambda().notLike(TbConVote::getBizNum, "MEET%");
        List<TbConVote> voteList = tbConVoteMapper.selectList(queryWrapper);
        if(voteList.size() > WorkFlowServerConstant.SIZE_0){
            List<TbConVote> bizList = tbConVoteMapper.findVoteBizList(userCd,orgCd);
            for (TbConVote vote:bizList) {
                if(!WorkFlowServerConstant.VOTE_ACTIVE_STATUS_TWO.equals(vote.getStatus())){
                    // 会议次数
                    BigDecimal voteNum = new BigDecimal(vote.getVoteNum()).subtract(WorkFlowServerConstant.BIG_DECIMAL_1);
                    QueryWrapper<TbConVote> fyQueryWrapper = new QueryWrapper<>();
                    fyQueryWrapper.lambda().eq(TbConVote::getBizNum,vote.getBizNum());
                    fyQueryWrapper.lambda().eq(TbConVote::getVoteNum,voteNum.toString());
                    fyQueryWrapper.lambda().eq(TbConVote::getUserNum, userCd);
                    fyQueryWrapper.lambda().eq(TbConVote::getOrgCd, orgCd);
                    fyQueryWrapper.lambda().eq(TbConVote::getStatus, WorkFlowServerConstant.VOTE_ACTIVE_STATUS_TWO);
                    List<TbConVote> fyVoteList = tbConVoteMapper.selectList(fyQueryWrapper);
                    if(fyVoteList.size() > WorkFlowServerConstant.SIZE_0){
                        // 如果存在复议,将当前生效状态改为复议
                        voteList.stream().forEach(vo->vo.setStatus(WorkFlowServerConstant.VOTE_ACTIVE_STATUS_TWO));
                    }
                }

            }
        }
        return voteList;
    }

    /**
     * 更新贷审会投票结果与意见信息(1 同意 2 否决 3 复议)
     *
     * @param workFlowUpdateVoteStatusDTO dto
     */
    @Override
    public WorkFlowUpdateVoteStatusDTO updateVoteStatus(WorkFlowUpdateVoteStatusDTO workFlowUpdateVoteStatusDTO) {
        UpdateWrapper<TbConVote> updateWrapper = new UpdateWrapper<>();
        if (StrUtil.isNotBlank(workFlowUpdateVoteStatusDTO.getStatus())
                && StrUtil.isNotBlank(workFlowUpdateVoteStatusDTO.getBizNum())) {
            // 更新会议状态为二次复议
            updateWrapper.lambda().eq(TbConVote::getBizNum, workFlowUpdateVoteStatusDTO.getBizNum());
            updateWrapper.lambda().set(TbConVote::getStatus, workFlowUpdateVoteStatusDTO.getStatus());
            updateWrapper.lambda().set(TbConVote::getMtime, new Date());
        } else {
            // 更新会议投票结果
            updateWrapper.lambda().eq(TbConVote::getVoteId, workFlowUpdateVoteStatusDTO.getVoteId());
            updateWrapper.lambda().set(TbConVote::getVote, workFlowUpdateVoteStatusDTO.getVote())
                    .set(TbConVote::getVoteIdea, workFlowUpdateVoteStatusDTO.getVoteIdea())
                    .set(TbConVote::getMtime, new Date());
        }
        int flag = tbConVoteMapper.update(null, updateWrapper);
        if (flag == WorkFlowServerConstant.SIZE_0) {
            workFlowUpdateVoteStatusDTO.setErrorMessage(WorkFlowServerConstant.UPDATE_ERROR);
        }

        return workFlowUpdateVoteStatusDTO;
    }

    /**
     * 发起会议代办人插入信息
     *
     * @param workFlowVoteUserAddDTO dto
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public WorkFlowReturnDTO addConVoteInfoList(WorkFlowVoteUserAddDTO workFlowVoteUserAddDTO) {
        WorkFlowReturnDTO workFlowReturnDTO = new WorkFlowReturnDTO();
        if (ObjectUtil.isNotEmpty(workFlowVoteUserAddDTO.getUserCdList())) {
            // 获取当前业务最大voteNum
            String maxVoteNum = tbConVoteMapper.findMaxBizVoteNumByBizNo(workFlowVoteUserAddDTO.getBizNo());
            // 2022.10.08 upd by zhangwei for 业务要求二期增加
            // 贷审会会议不能超过两次,超过则不能提交
            /*if (Integer.parseInt(maxVoteNum) > 1) {
                workFlowReturnDTO.setErrorMessage("贷审会会议超过两次不允许再次启动会议");
                return workFlowReturnDTO;
            }*/
            if (StrUtil.isBlank(maxVoteNum)) {
                maxVoteNum = "0";
            }
            // 当前业务值为
            int finalVoteNum = Integer.valueOf(maxVoteNum) + 1;
            workFlowVoteUserAddDTO.getUserCdList().forEach(userCd -> {
                TbConVote tbConVote = new TbConVote();
                // 主键
                tbConVote.setVoteId(IdUtil.simpleUUID());
                // 业务编号
                tbConVote.setBizNum(workFlowVoteUserAddDTO.getBizNo());
                // orgCd
                tbConVote.setOrgCd(workFlowVoteUserAddDTO.getOrgCd());
                // 委员编号
                tbConVote.setUserNum(userCd);
                // 客户名称
                tbConVote.setCustomerName(workFlowVoteUserAddDTO.getCustomerName());
                // 客户编号
                tbConVote.setCustomerNum(workFlowVoteUserAddDTO.getCustomerNum());
                // 业务类型编码
                tbConVote.setApplyType(workFlowVoteUserAddDTO.getBizType());
                // 创建时间
                tbConVote.setCreateTime(workFlowVoteUserAddDTO.getCreateDate());
                // 投票次数
                tbConVote.setVoteNum(StrUtil.toString(finalVoteNum));
                // 生效
                tbConVote.setStatus(WorkFlowServerConstant.VOTE_ACTIVE_STATUS);
                tbConVoteMapper.insert(tbConVote);
            });
        }
        return workFlowReturnDTO;
    }

    /**
     * 获取任务过程意见信息
     *
     * @param paramDTO dto
     * @return WorkFlowHistoryCommonListDTO dto
     */
    @Override
    public WorkFlowHistoryCommonListDTO findWorkFlowHistoryCommonList(WorkFlowHistoryCommonListParamDTO paramDTO)
            throws cn.git.workflow.webservice.query.BpmException_Exception {
        // 最终返回参数,以及意见列表信息
        WorkFlowHistoryCommonListDTO workFlowHistoryCommonListDTO = new WorkFlowHistoryCommonListDTO();
        List<WorkFlowHistoryCommonListDTO.WorkFlowTaskCommon> commonList = new ArrayList<>();
        workFlowHistoryCommonListDTO.setCustomerName(paramDTO.getCustomerName());
        workFlowHistoryCommonListDTO.setCustomerNum(paramDTO.getCustomerNum());
        workFlowHistoryCommonListDTO.setBizNo(paramDTO.getBizNo());

        // 获取系统上线时间,与业务编号获取时间进行比对,如果在上线时间之后则直接通过新模板获取流程信息
        Date upperLineDate = null;
        if (StrUtil.isBlank(nacosUpperDate)) {
            throw new ServiceException("流程模块nacos注册中心未配置上线时间!");
        } else {
            upperLineDate = DateUtil.parseDate(nacosUpperDate);
        }

        // 如果没有传递流程状态,从代办任务中获取
        if (StrUtil.isBlank(paramDTO.getWorkflowStatus())) {
            // 通过bizNo获取确定任务是否在途,默认查询is_del = 0 在途业务
            QueryWrapper<TbSysUnfinishedFlow> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(TbSysUnfinishedFlow::getBizNo, paramDTO.getBizNo());
            TbSysUnfinishedFlow unfinishedFlow = tbSysUnfinishedFlowMapper.selectOne(queryWrapper);
            if (ObjectUtil.isNull(unfinishedFlow)) {
                // 空值,设定查询为结束流程
                paramDTO.setWorkflowStatus(WorkFlowServerConstant.WORKFLOW_STATUS_FINISHED);
            }
        }

        // 通过业务编号获取业务生成具体时间
        Matcher matcher = Pattern.compile(WorkFlowServerConstant.STR_INDEX_PATTEN).matcher(paramDTO.getBizNo());
        Date bizOccurDate = null;
        if (matcher.find()) {
            String bizSuffixStr = paramDTO.getBizNo().substring(matcher.start());
            if (StrUtil.length(bizSuffixStr) > WorkFlowServerConstant.INT_NUM_8) {
                String suffixDateStr = bizSuffixStr.substring(WorkFlowServerConstant.INT_NUM_0, WorkFlowServerConstant.INT_NUM_8);
                try {
                    bizOccurDate = DateUtil.parse(suffixDateStr);
                } catch (Exception e) {
                    log.error("通过bizNo[{}]获取业务发生时间失败!", paramDTO.getBizNo());
                    e.printStackTrace();
                }
            }
        }

        // 业务时间判定,判定业务在新流程上线之前
        boolean ifOldBusinessFlag = (ObjectUtil.isNotNull(bizOccurDate) && upperLineDate.compareTo(bizOccurDate)
                > WorkFlowServerConstant.INT_NUM_0)
                || (ObjectUtil.isNull(bizOccurDate));
        // 上线前发生业务
        if (ifOldBusinessFlag) {
            // 老流程意见信息查看(包含三月内以及三月前信息),在老流程中获取processId
            String processId = getProcessId(paramDTO);
            // 流程实例id不为空,则查询老流程中的信息
            if (StrUtil.isNotBlank(processId)) {
                queryProcessInfo(paramDTO, workFlowHistoryCommonListDTO, processId);
            } else {
                /**
                 * todo: 暂时注释,所有原activiti流程上线前数据,无论是否三个月外都迁移到三个月外历史记录表中
                 * 上线前新流程三个月内流程意见信息获取,直接activiti信息表种获取
                 * setBefUpperLineInThreeMonthCommon(paramDTO, commonList, workFlowHistoryCommonListDTO);
                 */
                // 新流程上线前,三个月之前业务流程意见信息获取(备份数据)
                setBefUpperLineThreeMonthAgoCommon(paramDTO, commonList, workFlowHistoryCommonListDTO);
            }
        } else if (ObjectUtil.isNotNull(bizOccurDate) && upperLineDate.compareTo(bizOccurDate)
                <= WorkFlowServerConstant.INT_NUM_0) {
            // 上线后发生的业务,全部为新流程业务
            // 先判断业务是否存在于三个月内信息表中
            List<TbSysUnfinishedFlow> unfinishedFlowList = tbSysUnfinishedFlowMapper.getUnFinishedFlowList(paramDTO.getBizNo());
            if (ObjectUtil.isNotEmpty(unfinishedFlowList)) {
                // 新系统上线,并且业务发生时间,与当前时间相差小于三个月
                setAftUpperLineInThreeMonthCommon(paramDTO, commonList, workFlowHistoryCommonListDTO);
            } else {
                // 新系统上线后,并且业务备份到三个月前历史信息表中
                setAftUpperLineThreeMonthAgoCommon(paramDTO, commonList, workFlowHistoryCommonListDTO);
            }
        }

        return workFlowHistoryCommonListDTO;
    }

    /**
     * 新流程上线前3个月内,流程意见信息获取
     * @param paramDTO 参数dto
     * @param workFlowHistoryCommonListDTO 返回dto
     * @param commonList 意见信息列表
     */
    public void setBefUpperLineInThreeMonthCommon(WorkFlowHistoryCommonListParamDTO paramDTO,
                                                  List<WorkFlowHistoryCommonListDTO.WorkFlowTaskCommon> commonList,
                                                  WorkFlowHistoryCommonListDTO workFlowHistoryCommonListDTO) {

        // 拼装流程发起参数
        String userId = StrUtil.format(WorkFlowServerConstant.USER_ID_APPEND_TEMPLATE, paramDTO.getUserCd(),
                paramDTO.getOrgCd());
        Map<String, Object> paramMap = new HashMap<>(WorkFlowServerConstant.DEFAULT_MAP_SIZE);
        paramMap.put(WorkFlowServerConstant.PAGE_INDEX_FLAG, WorkFlowServerConstant.PAGE_INDEX);
        paramMap.put(WorkFlowServerConstant.PAGE_SIZE_FLAG, WorkFlowServerConstant.PAGE_SIZE);
        paramMap.put(WorkFlowServerConstant.USER_ID_FLAG, userId);

        // 获取历史信息
        List<WorkFlowActHisProcessListDTO> actHisProcessListDTOList = queryStatusHisList(userId,
                paramDTO.getWorkflowStatus());
        if (ObjectUtil.isNotEmpty(actHisProcessListDTOList)) {
            // 获取业务编号以及流程实例id
            String newWorkFlowProcessId = "";
            for (WorkFlowActHisProcessListDTO historyProcess : actHisProcessListDTOList) {
                String hisBizKey = historyProcess.getBusinessKey();
                if (paramDTO.getBizNo().equals(hisBizKey)) {
                    newWorkFlowProcessId = historyProcess.getId();
                    break;
                }
            }

            // 新流程获取processId不为空则通过流程实例id查询任务历史信息
            if (StrUtil.isNotBlank(newWorkFlowProcessId)) {
                getTaskHisInfoByProcessId(userId, paramMap, commonList, newWorkFlowProcessId);
            }

            // 设置返回参数信息
            if (ObjectUtil.isNotEmpty(commonList)) {
                workFlowHistoryCommonListDTO.setWorkFlowTaskCommonList(commonList);
            }
        }
    }


    /**
     * 新流程上线前3个月前,流程意见信息获取
     * @param paramDTO 参数dto
     * @param workFlowHistoryCommonListDTO 返回dto
     * @param commonList 意见信息列表
     */
    public void setBefUpperLineThreeMonthAgoCommon(WorkFlowHistoryCommonListParamDTO paramDTO,
                                                   List<WorkFlowHistoryCommonListDTO.WorkFlowTaskCommon> commonList,
                                                   WorkFlowHistoryCommonListDTO workFlowHistoryCommonListDTO) {
        // 新流程三个月之前流程意见信息获取
        QueryWrapper<ActHiProcinstBack> instQueryWrapper = new QueryWrapper<>();
        instQueryWrapper.lambda().eq(ActHiProcinstBack::getBusinessKey, paramDTO.getBizNo());
        ActHiProcinstBack actHiProcinstBack = actHiProcinstBackMapper.selectOne(instQueryWrapper);
        if (ObjectUtil.isNotNull(actHiProcinstBack)) {
            QueryWrapper<ActHiActinstBack> actHiActinstQueryWrapper = new QueryWrapper<>();
            actHiActinstQueryWrapper.lambda().eq(ActHiActinstBack::getProcInstId, actHiProcinstBack.getProcInstId());
            List<ActHiActinstBack> actHiActinstBackList = actHiActinstBackMapper.selectList(actHiActinstQueryWrapper);
            if (ObjectUtil.isNotEmpty(actHiActinstBackList)) {
                for (ActHiActinstBack actHiActinstBack : actHiActinstBackList) {
                    // 判断节点是否为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);
                        // 意见信息封装
                        WorkFlowHistoryCommonListDTO.WorkFlowTaskCommon workFlowTaskCommon =
                                new WorkFlowHistoryCommonListDTO.WorkFlowTaskCommon();

                        // 结束时间
                        if (ObjectUtil.isNotNull(actHiActinstBack.getEndTime())) {
                            workFlowTaskCommon.setTaskFinishTime(actHiActinstBack.getEndTime());
                        }
                        // processId
                        workFlowTaskCommon.setProcessId(actHiActinstBack.getProcInstId());
                        // 岗位名称
                        workFlowTaskCommon.setActivityId(actHiActinstBack.getActName());
                        // 评论信息
                        if (ObjectUtil.isNotNull(actHiCommentBack)) {
                            workFlowTaskCommon.setProcessComment(actHiCommentBack.getMessage());
                        }
                        // 任务办理人信息
                        if (StrUtil.isNotBlank(actHiActinstBack.getAssignee())) {
                            String[] handingInfo = StrUtil.toString(actHiActinstBack.getAssignee())
                                    .split(WorkFlowServerConstant.SPLIT_FLAG);
                            if (ObjectUtil.isNotNull(handingInfo[0])
                                    && !WorkFlowServerConstant.NULL_STR.equalsIgnoreCase(handingInfo[0])) {
                                ManageUserDTO param = new ManageUserDTO();
                                param.setUserCd(handingInfo[0]);
                                ManageUserDTO userNameByUserCd = managementApiClient.findUserNameByUserCd(param);
                                workFlowTaskCommon.setOwner(userNameByUserCd.getUserName());
                            }
                            if (handingInfo.length > 1) {
                                workFlowTaskCommon.setOrgCd(handingInfo[1]);
                            }
                        }
                        // 任务id
                        workFlowTaskCommon.setTaskId(actHiActinstBack.getTaskId());
                        // 去除发起头以及结尾信息
                        if (!WorkFlowServerConstant.START_FLAG.equals(actHiActinstBack.getActName())
                                && !WorkFlowServerConstant.END_FLAG.equals(actHiActinstBack.getActName())) {
                            commonList.add(workFlowTaskCommon);
                        }
                    }
                }
                // 设置返回参数信息
                if (ObjectUtil.isNotEmpty(commonList)) {
                    workFlowHistoryCommonListDTO.setWorkFlowTaskCommonList(commonList);
                }
            }
        }
    }

    /**
     * 新流程上线后,3个月前,流程意见信息获取
     * @param paramDTO 参数dto
     * @param workFlowHistoryCommonListDTO 返回dto
     * @param commonList 意见信息列表
     */
    public void setAftUpperLineThreeMonthAgoCommon(WorkFlowHistoryCommonListParamDTO paramDTO,
                                                   List<WorkFlowHistoryCommonListDTO.WorkFlowTaskCommon> commonList,
                                                   WorkFlowHistoryCommonListDTO workFlowHistoryCommonListDTO) {
        List<TbSysBackPositionInfoHis> backPositionInfoList = tbSysBackPositionInfoHisMapper
                .getBackPositionInfoListByBizNo(paramDTO.getBizNo());

        if (ObjectUtil.isEmpty(backPositionInfoList)) {
            return;
        }

        // 筛选非最新processId信息
        Optional<TbSysBackPositionInfoHis> maxProcessPositionInfo = backPositionInfoList.stream().max(
                Comparator.comparing(TbSysBackPositionInfoHis::getProcessId)
        );
        String maxProcessId = maxProcessPositionInfo.get().getProcessId();
        backPositionInfoList = backPositionInfoList.stream().filter(position ->
                position.getProcessId().equals(maxProcessId)
        ).collect(Collectors.toList());

        // 获取流程模板id
        String workFlowTemplateId = backPositionInfoList.get(WorkFlowServerConstant.INT_NUM_0)
                .getWorkFlowTemplateId();
        if (StrUtil.isNotBlank(workFlowTemplateId)) {
            // 通过流程模板id获取各个岗位详情信息
            QueryWrapper<TbSysFlowPosition> positionQueryWrapper = new QueryWrapper<>();
            positionQueryWrapper.lambda().eq(TbSysFlowPosition::getFlowTempletNum, workFlowTemplateId);
            TbSysFlowPosition tbSysFlowPosition = tbSysFlowPositionMapper.selectOne(positionQueryWrapper);
            if (ObjectUtil.isNull(tbSysFlowPosition)) {
                return;
            }
            QueryWrapper<TbSysFlowPositionDetail> detailQueryWrapper = new QueryWrapper<>();
            detailQueryWrapper.lambda().eq(TbSysFlowPositionDetail::getFlowId, tbSysFlowPosition.getFlowId());
            List<TbSysFlowPositionDetail> detailList = tbSysFlowPositionDetailMapper.selectList(detailQueryWrapper);
            if (ObjectUtil.isEmpty(detailList)) {
                return;
            }
            // 获取岗位activitiId,岗位名称的map
            Map<String, String> positionMap = detailList.stream().collect(Collectors.toMap(
                    TbSysFlowPositionDetail::getActivitiId, TbSysFlowPositionDetail::getPositionName, (k1, k2) -> k1)
            );
            // 封装意见列表信息
            commonList = backPositionInfoList.stream().map(info -> {
                WorkFlowHistoryCommonListDTO.WorkFlowTaskCommon common = new WorkFlowHistoryCommonListDTO.WorkFlowTaskCommon();
                common.setBizNo(paramDTO.getBizNo());
                common.setTaskFinishTime(info.getSubmitTime());
                common.setCustomerNum(info.getOptionUserCd());
                common.setOwner(info.getOptionUserCd());
                common.setActivityId(positionMap.get(info.getActivitiId()));
                common.setOrgCd(info.getOptionOrgCd());
                common.setProcessComment(info.getFlowComment());
                return common;
            }).collect(Collectors.toList());
        }
        // 设置返回参数信息
        if (ObjectUtil.isNotEmpty(commonList)) {
            workFlowHistoryCommonListDTO.setWorkFlowTaskCommonList(commonList);
        }
    }

    /**
     * 新流程上线后,3个月内,流程意见信息获取
     * @param paramDTO 参数dto
     * @param commonList 意见信息列表
     */
    public void setAftUpperLineInThreeMonthCommon(WorkFlowHistoryCommonListParamDTO paramDTO,
                                                  List<WorkFlowHistoryCommonListDTO.WorkFlowTaskCommon> commonList,
                                                  WorkFlowHistoryCommonListDTO workFlowHistoryCommonListDTO) {
        // 获取processId信息
        List<TbSysUnfinishedFlow> unfinishedFlowList = null;
        if (StrUtil.isNotBlank(paramDTO.getBizType())) {
            unfinishedFlowList = tbSysUnfinishedFlowMapper.getUnFinishedFlowListByBizType(paramDTO.getBizNo(), paramDTO.getBizType());
        }

        // 判定业务在上线之后,一律使用新的意见信息获取流程(三个月之内)
        List<TbSysBackPositionInfo> backPositionInfoList = null;
        if (ObjectUtil.isEmpty(unfinishedFlowList)) {
            backPositionInfoList = tbSysBackPositionInfoMapper.getBackPositionInfoListByBizNo(paramDTO.getBizNo());
        } else {
            // 本地信息不为空
            TbSysUnfinishedFlow unfinishedFlow = unfinishedFlowList.get(WorkFlowServerConstant.INT_NUM_0);
            if (ObjectUtil.isNotNull(unfinishedFlow) && StrUtil.isNotBlank(unfinishedFlow.getProcessId())) {
                backPositionInfoList = tbSysBackPositionInfoMapper.getBackPositionInfoListByProcessId(unfinishedFlow.getProcessId());
            }
        }
        if (ObjectUtil.isEmpty(backPositionInfoList)) {
            return;
        }

        // 筛选非最新processId信息
        Optional<TbSysBackPositionInfo> maxProcessPositionInfo = backPositionInfoList.stream().max(
                Comparator.comparing(TbSysBackPositionInfo::getProcessId)
        );
        String maxProcessId = maxProcessPositionInfo.get().getProcessId();
        backPositionInfoList = backPositionInfoList.stream().filter(position ->
                position.getProcessId().equals(maxProcessId)
        ).collect(Collectors.toList());

        // 获取流程模板id
        String workFlowTemplateId = backPositionInfoList.get(WorkFlowServerConstant.INT_NUM_0)
                .getWorkFlowTemplateId();
        if (StrUtil.isNotBlank(workFlowTemplateId)) {
            // 通过流程模板id获取各个岗位详情信息
            QueryWrapper<TbSysFlowPosition> positionQueryWrapper = new QueryWrapper<>();
            positionQueryWrapper.lambda().eq(TbSysFlowPosition::getFlowTempletNum, workFlowTemplateId);
            TbSysFlowPosition tbSysFlowPosition = tbSysFlowPositionMapper.selectOne(positionQueryWrapper);
            if (ObjectUtil.isNull(tbSysFlowPosition)) {
                return;
            }
            QueryWrapper<TbSysFlowPositionDetail> detailQueryWrapper = new QueryWrapper<>();
            detailQueryWrapper.lambda().eq(TbSysFlowPositionDetail::getFlowId, tbSysFlowPosition.getFlowId());
            List<TbSysFlowPositionDetail> detailList = tbSysFlowPositionDetailMapper.selectList(detailQueryWrapper);
            if (ObjectUtil.isEmpty(detailList)) {
                return;
            }
            // 获取岗位activitiId,岗位名称的map
            Map<String, String> positionMap = detailList.stream().collect(Collectors.toMap(
                    TbSysFlowPositionDetail::getActivitiId, TbSysFlowPositionDetail::getPositionName, (k1, k2) -> k1)
            );
            // 封装意见列表信息
            commonList = backPositionInfoList.stream().map(info -> {
                WorkFlowHistoryCommonListDTO.WorkFlowTaskCommon common = new WorkFlowHistoryCommonListDTO.WorkFlowTaskCommon();
                common.setBizNo(paramDTO.getBizNo());
                common.setTaskFinishTime(info.getSubmitTime());
                common.setCustomerNum(info.getOptionUserCd());
                common.setOwner(info.getOptionUserCd());
                common.setActivityId(positionMap.get(info.getActivitiId()));
                common.setOrgCd(info.getOptionOrgCd());
                common.setProcessComment(info.getFlowComment());
                return common;
            }).collect(Collectors.toList());
        }
        // 设置返回参数信息
        if (ObjectUtil.isNotEmpty(commonList)) {
            workFlowHistoryCommonListDTO.setWorkFlowTaskCommonList(commonList);
        }
    }

    /**
     * 通过流程实例id查询任务历史信息
     *
     * @param userId 用户id
     * @param paramMap 参数map
     * @param commonList 意见列表
     * @param newWorkFlowProcessId 新流程实例id
     */
    private void getTaskHisInfoByProcessId(String userId,
                                           Map<String, Object> paramMap,
                                           List<WorkFlowHistoryCommonListDTO.WorkFlowTaskCommon> commonList,
                                           String newWorkFlowProcessId) {
        // 获取历史信息
        List<WorkFlowActHisActInstListDTO> actHisActInstListDTOList = queryHisTaskList(newWorkFlowProcessId);
        // 解析查询回来信息
        if (ObjectUtil.isNotEmpty(actHisActInstListDTOList)) {
            actHisActInstListDTOList.forEach(taskInfo -> {
                // 返回common类型对象
                WorkFlowHistoryCommonListDTO.WorkFlowTaskCommon workFlowTaskCommon =
                        new WorkFlowHistoryCommonListDTO.WorkFlowTaskCommon();
                // 结束时间
                if (ObjectUtil.isNotEmpty(taskInfo.getEndTime())) {
                    workFlowTaskCommon.setTaskFinishTime(taskInfo.getEndTime());
                }
                // processId
                workFlowTaskCommon.setProcessId(taskInfo.getProcessInstanceId());
                // 岗位名称
                workFlowTaskCommon.setActivityId(taskInfo.getActivityName());
                // 评论信息
                workFlowTaskCommon.setProcessComment(taskInfo.getOpinion());
                // 任务办理人信息
                if (StrUtil.isNotBlank(taskInfo.getAssignee())) {
                    // 字符串分割 userCd + : + orgCd
                    String[] handingInfo = StrUtil.toString(taskInfo.getAssignee())
                            .split(WorkFlowServerConstant.SPLIT_FLAG);
                    workFlowTaskCommon.setOwner(handingInfo[0]);
                    if (handingInfo.length > 1) {
                        workFlowTaskCommon.setOrgCd(handingInfo[1]);
                    }
                }
                // 任务id
                workFlowTaskCommon.setTaskId(taskInfo.getTaskId());
                // 去除发起头以及结尾信息
                if (!WorkFlowServerConstant.START_FLAG.equals(taskInfo.getActivityName())
                        && !WorkFlowServerConstant.END_FLAG.equals(taskInfo.getActivityName())) {
                    commonList.add(workFlowTaskCommon);
                }
            });
        }
    }

    /**
     * 查询老流程中的信息,其中包含三月内以及三月外部分,都进行查询
     *
     * @param paramDTO 参数dto
     * @param workFlowHistoryCommonListDTO 参数dto
     * @param processId 流程processId
     */
    private void queryProcessInfo(WorkFlowHistoryCommonListParamDTO paramDTO,
                                  WorkFlowHistoryCommonListDTO workFlowHistoryCommonListDTO,
                                  String processId) {
        // 查看流程是否在途
        QueryWrapper<WfmidProcessInstance> instanceQueryWrapper = new QueryWrapper<>();
        instanceQueryWrapper.lambda().eq(WfmidProcessInstance::getProcessId, processId);
        WfmidProcessInstance instance = wfmidProcessInstanceMapper.selectOne(instanceQueryWrapper);
        // 历史信息记录
        List<WorkFlowTaskCommon> workFlowTaskCommonList;
        if (ObjectUtil.isNotEmpty(instance)) {
            // 查询流程信息
            workFlowTaskCommonList = wfmidAppProcessInstanceMapper.findTaskInfoList(processId);
        } else {
            workFlowTaskCommonList = wfmidAppProcessInstanceHisMapper.findHistoryTaskInfoList(processId);
        }

        // 返回结果list集合
        List<WorkFlowHistoryCommonListDTO.WorkFlowTaskCommon> commonList = workFlowTaskCommonList.stream()
                .map(common ->
                        workFlowConvert.taskCommonServerConvertWorkFlowTaskApi(common)
                ).collect(Collectors.toList());

        if (ObjectUtil.isNotEmpty(commonList)) {
            workFlowHistoryCommonListDTO.setWorkFlowTaskCommonList(commonList);
            workFlowHistoryCommonListDTO.setBizNo(paramDTO.getBizNo());
            workFlowHistoryCommonListDTO.setBizTypeCd(commonList.get(0).getBizType());
            workFlowHistoryCommonListDTO.setTaskOrgCd(commonList.get(0).getTaskOrgCd());
            workFlowHistoryCommonListDTO.setCustomerName(paramDTO.getCustomerName());
            workFlowHistoryCommonListDTO.setCustomerNum(paramDTO.getCustomerNum());
        }
    }

    /**
     * 在老流程中获取processId
     *
     * @param paramDTO
     * @return
     */
    private String getProcessId(WorkFlowHistoryCommonListParamDTO paramDTO) {
        QueryWrapper<WfmidAppProcessInstance> appInstanceQueryWrapper = new QueryWrapper<>();
        appInstanceQueryWrapper.lambda().eq(WfmidAppProcessInstance::getBizNo, paramDTO.getBizNo());
        List<WfmidAppProcessInstance> processInstance = wfmidAppProcessInstanceMapper.selectList(appInstanceQueryWrapper);
        // 流程实例id
        String processId = null;
        if (ObjectUtil.isNotEmpty(processInstance)) {
            processId = processInstance.get(0).getId();
        } else {
            QueryWrapper<WfmidAppProcessInstanceHis> hisQueryWrapper = new QueryWrapper<>();
            hisQueryWrapper.lambda().eq(WfmidAppProcessInstanceHis::getBizNo, paramDTO.getBizNo());
            WfmidAppProcessInstanceHis instanceHis = wfmidAppProcessInstanceHisMapper.selectOne(hisQueryWrapper);
            if (ObjectUtil.isNotEmpty(instanceHis)) {
                processId = instanceHis.getId();
            }
        }
        return processId;
    }

    /**
     * 任务跳跃节点
     *
     * @param workFlowGotoTaskDTO 当前任务id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void gotoTask(WorkFlowGotoTaskDTO workFlowGotoTaskDTO) {
        // 跳岗当前岗位信息taskId是否传入校验
        if (StrUtil.isBlank(workFlowGotoTaskDTO.getCurrentActivityId())) {
            throw new ServiceException("提交下一岗位回退上一处理人[currentActivityId]信息为空!");
        }

        // 权限设定
        String nextUserId = StrUtil.format(WorkFlowServerConstant.USER_ID_APPEND_TEMPLATE,
                workFlowGotoTaskDTO.getNextUserCd(),
                workFlowGotoTaskDTO.getNextOrgCd());
        identityService.setAuthenticatedUserId(nextUserId);

        // 获取当前task信息
        Task task = taskService.createTaskQuery()
                .taskId(workFlowGotoTaskDTO.getTaskId())
                .singleResult();
        if (ObjectUtil.isNotNull(task)) {
            // 保存参数
            Map<String, Object> saveParamMap = new HashMap<>(WorkFlowServerConstant.DEFAULT_MAP_SIZE);
            saveParamMap.put(WorkFlowServerConstant.WORKFLOW_USERS_FLAG, nextUserId);
            if (ObjectUtil.isNotEmpty(workFlowGotoTaskDTO.getSaveMap())) {
                saveParamMap.putAll(workFlowGotoTaskDTO.getSaveMap());
            }

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

            // 修改参数信息
            taskService.setVariables(task.getId(), saveParamMap);

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

            // 获取当前节点定义信息以及目标节点的节点信息
            ActivityImpl currentTaskActivity = processDefinition.findActivity(task.getTaskDefinitionKey());
            ActivityImpl destinationTaskActivity = processDefinition.findActivity(workFlowGotoTaskDTO.getDesTaskDefinitionKey());

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

            // 通过流程实例,获取当前有效的任务列表
            List<Task> activeTaskList = taskService.createTaskQuery()
                    .processInstanceId(task.getProcessInstanceId())
                    .orderByTaskCreateTime()
                    .desc()
                    .list();
            if (ObjectUtil.isEmpty(activeTaskList)) {
                throw new ServiceException("流程任务跳转之后通过processId未获取到正确的生效任务task!");
            }
            String activeTaskId = activeTaskList.get(0).getId();

            // 通过流程processId获取bizNo信息,以及流程模板编号信息
            TbSysBackPositionInfo startPositionInfo = tbSysBackPositionInfoMapper
                    .getBackPositionInfoByProcessId(task.getProcessInstanceId());
            // 存入返回上一岗位必要信息
            String optionUserCd = webUtil.getCurrentUserCd();
            String optionOrgCd = webUtil.getCurrentOrgCd();
            TbSysBackPositionInfo tbSysBackPositionInfo = new TbSysBackPositionInfo();
            tbSysBackPositionInfo.setId(IdUtil.simpleUUID());
            tbSysBackPositionInfo.setActivitiId(workFlowGotoTaskDTO.getCurrentActivityId());
            tbSysBackPositionInfo.setProcessId(task.getProcessInstanceId());
            if (ObjectUtil.isNotNull(startPositionInfo)) {
                tbSysBackPositionInfo.setBizNo(startPositionInfo.getBizNo());
                tbSysBackPositionInfo.setWorkFlowTemplateId(startPositionInfo.getWorkFlowTemplateId());
            }
            tbSysBackPositionInfo.setOptionOrgCd(optionOrgCd);
            tbSysBackPositionInfo.setOptionUserCd(optionUserCd);
            tbSysBackPositionInfo.setSubmitTime(new Date());
            if (ObjectUtil.isNotNull(saveParamMap.get(WorkFlowServerConstant.COMMENT_FLAG))) {
                // 设置流程意见信息
                tbSysBackPositionInfo.setFlowComment(
                        StrUtil.toString(saveParamMap.get(WorkFlowServerConstant.COMMENT_FLAG)));
            }
            log.info("跳岗方法,存入退回上一岗位必要信息[{}]", JSONObject.toJSONString(tbSysBackPositionInfo));
            tbSysBackPositionInfoMapper.insert(tbSysBackPositionInfo);

            // 开始强制修改处理人信息
            Task nextTask = taskService.createTaskQuery()
                    .taskId(activeTaskId)
                    .singleResult();
            nextTask.setAssignee(nextUserId);

            // 任务转移到nextUserId上
            taskService.saveTask(nextTask);
            taskService.claim(activeTaskId, nextUserId);
        } else {
            throw new ServiceException("任务跳节点查询任务信息失败!");
        }
    }

    /**
     * 任务信息修改
     *
     * @param workFlowTaskUpdateDTO 任务修改dto
     */
    @Override
    public void saveTask(WorkFlowTaskUpdateDTO workFlowTaskUpdateDTO) {
        // 请求参数
        Map<String, Object> paramMap = new HashMap<>(WorkFlowServerConstant.DEFAULT_MAP_SIZE);
        if (ObjectUtil.isNotEmpty(workFlowTaskUpdateDTO.getParamMap())) {
            paramMap.putAll(workFlowTaskUpdateDTO.getParamMap());
        }

        // 下一审批人
        String userId = StrUtil.format(WorkFlowServerConstant.USER_ID_APPEND_TEMPLATE, workFlowTaskUpdateDTO.getUserCd(),
                workFlowTaskUpdateDTO.getOrgCd());
        paramMap.put(WorkFlowServerConstant.WORKFLOW_USERS_FLAG, userId);

        // 获取任务service
        Task task = taskService.createTaskQuery()
                .taskId(workFlowTaskUpdateDTO.getTaskId())
                .singleResult();

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

        // 保存参数
        taskService.setVariables(task.getId(), paramMap);
    }

    /**
     * 任务代理人变更
     *
     * @param taskId 任务编号
     * @param orgCd  机构号
     * @param userCd 柜员号
     */
    @Override
    public void delegateTask(String taskId, String orgCd, String userCd) {
        // 新代理人
        String userId = StrUtil.format(WorkFlowServerConstant.USER_ID_APPEND_TEMPLATE, userCd, orgCd);
        Task task = taskService.createTaskQuery()
                .taskId(taskId)
                .singleResult();

        // 设置当前代理人
        task.setAssignee(userId);
        taskService.saveTask(task);
    }

    /**
     * 查看当前用户是否有在途任务
     *
     * @param customerNum 客户号
     * @return 在途业务信息
     */
    @Override
    public String findUndoTask(String customerNum, String bizName) {
        // 返回信息
        String returnMsg = null;
        // 查询在途信息
        QueryWrapper<TbSysUnfinishedFlow> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TbSysUnfinishedFlow::getCustomerNum, customerNum);
        if (StrUtil.isNotBlank(bizName)) {
            queryWrapper.lambda().eq(TbSysUnfinishedFlow::getBizName, bizName);
        }
        List<TbSysUnfinishedFlow> flowList = tbSysUnfinishedFlowMapper.selectList(queryWrapper);
        if (ObjectUtil.isNotEmpty(flowList)) {
            returnMsg = flowList.stream().map(finishFlow ->
                    StrUtil.format(WorkFlowServerConstant.APPEND_TEMPLATE_WORK_FLOW_THREE,
                            finishFlow.getBizName(),
                            finishFlow.getBizNo(),
                            WorkFlowServerConstant.WORK_FLOW_IS_EXIST))
                    .collect(Collectors.joining(WorkFlowServerConstant.SPLIT_COMMA_FLAG));
        }
        return returnMsg;
    }

    /**
     * 更新制定业务待审核审批状态
     *
     * @param bizNum
     * @return 成功失败信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateVote(String bizNum, String voteState) {
        QueryWrapper<TbConVote> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(TbConVote::getBizNum, bizNum);
        List<TbConVote> voteList = tbConVoteMapper.selectList(wrapper);
        if (ObjectUtil.isNotEmpty(voteList)) {
            voteList.forEach(vote -> {
                TbConVote tbConVote = new TbConVote();
                tbConVote.setVoteId(vote.getVoteId());
                tbConVote.setStatus(voteState);
                tbConVote.setCtime(new Date());
                tbConVoteMapper.updateById(tbConVote);
            });
        }
    }

    /**
     * 修改贷审会信息状态为失效
     *
     * @param bizNum 流程编号
     */
    @Override
    public void updateConVoteStatus(String bizNum) {
        UpdateWrapper<TbConVote> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().eq(TbConVote::getBizNum, bizNum);
        updateWrapper.lambda().set(TbConVote::getStatus, WorkFlowServerConstant.VOTE_STATUS_EXPIRE)
                .set(TbConVote::getMtime,new Date());
        tbConVoteMapper.update(null, updateWrapper);
    }

    /**
     * 查看当前用户的在途任务
     *
     * @param customerNum 客户号
     * @return 在途业务信息
     */
    @Override
    public String findUndoTaskForPLMS(String customerNum, String bizNo) {
        // 查询在途信息
        String message = null;
        QueryWrapper<TbSysUnfinishedFlow> queryWrapper = new QueryWrapper<>();
        if (StrUtil.isNotBlank(bizNo)) {
            queryWrapper.lambda().eq(TbSysUnfinishedFlow::getCustomerNum, customerNum)
                    .eq(TbSysUnfinishedFlow::getBizNo, bizNo);
        } else {
            // 2022-10-20 经过跟谭智鹏沟通需要加入老评级和老授信验证在途
            queryWrapper.lambda().eq(TbSysUnfinishedFlow::getCustomerNum, customerNum)
                    .in(TbSysUnfinishedFlow::getBizName, "法人贷款申请",
                            "法人贷款放款核准流程",
                            "新授信申请",
                            "授信申请",
                            "法人评级申请流程",
                            "法人重新评级申请流程");
        }
        List<TbSysUnfinishedFlow> flowList = tbSysUnfinishedFlowMapper.selectList(queryWrapper);
        if (ObjectUtil.isNotEmpty(flowList)) {
            TbSysUnfinishedFlow tbSysUnfinishedFlow = flowList.get(WorkFlowServerConstant.PAGE_INDEX);
            message = tbSysUnfinishedFlow.getBizNo();
        }
        return message;
    }

    /**
     * 跳转到调查复核岗
     *
     * @param processId
     * @return 错误信息
     */
    @Override
    public String gotoPositionCheck(String processId, String taskId, String positionCd, String activityId) {
        // 通过process获取流程模板id
        QueryWrapper<TbSysBackPositionInfo> positionInfoQueryWrapper = new QueryWrapper<>();
        positionInfoQueryWrapper.lambda().eq(TbSysBackPositionInfo::getProcessId, processId)
                .isNotNull(TbSysBackPositionInfo::getWorkFlowTemplateId)
                .orderByDesc(TbSysBackPositionInfo::getSubmitTime);
        List<TbSysBackPositionInfo> backList = tbSysBackPositionInfoMapper.selectList(positionInfoQueryWrapper);
        if (ObjectUtil.isEmpty(backList)) {
            return StrUtil.format("通过processId[{}]查询流程模板id为空!", processId);
        }
        String templateId = backList.get(0).getWorkFlowTemplateId();

        // 获取流程模板对应流程调查复核岗岗位activitiId信息,首先获取flowId
        QueryWrapper<TbSysFlowPosition> flowPositionQueryWrapper = new QueryWrapper<>();
        flowPositionQueryWrapper.lambda().eq(TbSysFlowPosition::getFlowTempletNum, templateId);
        TbSysFlowPosition tbSysFlowPosition = tbSysFlowPositionMapper.selectOne(flowPositionQueryWrapper);
        if (ObjectUtil.isNull(tbSysFlowPosition)) {
            return StrUtil.format("通过templateId[{}]查询流程流程岗位定义信息为空!", templateId);
        }
        String flowId = tbSysFlowPosition.getFlowId();

        // 通过flowId获取岗位信息
        QueryWrapper<TbSysFlowPositionDetail> detailQueryWrapper = new QueryWrapper<>();
        detailQueryWrapper.lambda().eq(TbSysFlowPositionDetail::getFlowId, flowId)
                .eq(TbSysFlowPositionDetail::getPositionCd, positionCd)
                .orderByAsc(TbSysFlowPositionDetail::getPositionName);
        List<TbSysFlowPositionDetail> positionDetailList = tbSysFlowPositionDetailMapper.selectList(detailQueryWrapper);
        if(positionDetailList.size() > 1){
            detailQueryWrapper.lambda().eq(TbSysFlowPositionDetail::getPositionLevelCd, webUtil.getCurrentOrgLevel());
            positionDetailList = tbSysFlowPositionDetailMapper.selectList(detailQueryWrapper);
        }
        if (ObjectUtil.isNull(positionDetailList) || positionDetailList.size() == 0) {
            return StrUtil.format("获取当前processId对应业务模板[{}]没有调查复核岗位信息或者对应activitiId信息为空!",
                    tbSysFlowPosition.getFlowTempletName());
        }
        TbSysFlowPositionDetail positionDetail = positionDetailList.get(0);
        String activitiId = positionDetail.getActivitiId();

        // 通过activiti获取调查复核岗提交人信息
        positionInfoQueryWrapper.clear();
        positionInfoQueryWrapper.lambda().eq(TbSysBackPositionInfo::getProcessId, processId)
                .eq(TbSysBackPositionInfo::getActivitiId, activitiId);
        backList = tbSysBackPositionInfoMapper.selectList(positionInfoQueryWrapper);
        if (ObjectUtil.isNull(backList)) {
            return StrUtil.format("通过processId[{}]以及activitiId[{}]查询跳岗信息调查复核岗信息为空!",
                    processId, activitiId);
        }

        // 组织跳岗信息,开始进行跳转到调查复核岗
        String nextUserCd = backList.get(0).getOptionUserCd();
        String nextOrgCd = backList.get(0).getOptionOrgCd();

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

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

        // 获取当前节点定义信息以及目标节点的节点信息
        ActivityImpl currentTaskActivity = processDefinition.findActivity(task.getTaskDefinitionKey());
        ActivityImpl destinationTaskActivity = processDefinition.findActivity(activitiId);

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

        // 通过流程实例,获取当前有效的任务列表
        List<Task> activeTaskList = taskService.createTaskQuery()
                .processInstanceId(task.getProcessInstanceId())
                .orderByTaskCreateTime()
                .desc()
                .list();
        if (ObjectUtil.isEmpty(activeTaskList)) {
            throw new ServiceException("流程任务跳转之后通过processId未获取到正确的生效任务task!");
        }
        String activeTaskId = activeTaskList.get(0).getId();

        // 修改任务处理人信息,转换为下一岗位机构处理人信息
        String nextUserId = StrUtil.format(WorkFlowServerConstant.USER_ID_APPEND_TEMPLATE, nextUserCd, nextOrgCd);
        Task nextTask = taskService.createTaskQuery()
                .taskId(activeTaskId)
                .singleResult();
        nextTask.setAssignee(nextUserId);

        // 任务转移到nextUserId上
        taskService.saveTask(nextTask);
        taskService.claim(activeTaskId, nextUserId);
        return null;
    }

    /**
     * 设置任务参数信息
     *
     * @param workFlowCusParamDTO 设置参数信息dto
     */
    @Override
    public void saveWorkflowParams(WorkFlowCusParamDTO workFlowCusParamDTO) {
        // 获取任务task详细信息
        String taskId = workFlowCusParamDTO.getTaskId();
        Task task = taskService.createTaskQuery()
                .taskId(taskId)
                .singleResult();

        // 设置意见信息
        Map<String, Object> saveParamMap = workFlowCusParamDTO.getParamMap();
        if (ObjectUtil.isNotNull(saveParamMap.get("opinion"))) {
            //只保留一条批注记录
            List<Comment> commentList = taskService.getTaskComments(taskId);
            if(ObjectUtil.isNotEmpty(commentList)){
                commentList.forEach(common -> {
                    taskService.deleteComment(common.getId());
                });
            }
            // 添加新的批注信息
            taskService.addComment(taskId, task.getProcessInstanceId(), saveParamMap.get("opinion").toString());
        }

        // 修改参数信息
        taskService.setVariables(taskId, saveParamMap);
    }

    /**
     * 通过bizNo以及流程模板id列表获取意见信息列表
     *
     * @param workFlowCommentDTO 意见列表获取参数信息
     * @return 流程意见信息
     */
    @Override
    public WorkFlowCommentDTO getComment(WorkFlowCommentDTO workFlowCommentDTO) {
        // 空信息判断
        if (ObjectUtil.isEmpty(workFlowCommentDTO.getBizNoList())) {
            return workFlowCommentDTO;
        }

        // 获取意见列表参数信息以
        List<String> bizNoList = workFlowCommentDTO.getBizNoList();

        // 设置返回意见map信息
        Map<String, List<WorkFlowCommentDTO.WorkFlowSimpleCommon>> commonMap = new HashMap<>();

        bizNoList.forEach(bizNo -> {
            WorkFlowHistoryCommonListParamDTO paramDTO = new WorkFlowHistoryCommonListParamDTO();
            paramDTO.setBizNo(bizNo);
            // 在老流程中获取processId
            String processId = this.getProcessId(paramDTO);
            // 流程实例id不为空,则查询老流程中的信息
            if (StrUtil.isNotBlank(processId)) {
                WorkFlowHistoryCommonListDTO workFlowHistoryCommonListDTO = new WorkFlowHistoryCommonListDTO();
                this.queryProcessInfo(paramDTO, workFlowHistoryCommonListDTO, processId);
                // 判断查询列表信息不为空
                if (ObjectUtil.isNotEmpty(workFlowHistoryCommonListDTO.getWorkFlowTaskCommonList())) {
                    // 设置列表信息 todo: 老流程信息查询结果集不满足当前业务,后续优化
                    List<WorkFlowCommentDTO.WorkFlowSimpleCommon> commonList = new ArrayList<>();
                    workFlowHistoryCommonListDTO.getWorkFlowTaskCommonList().forEach(common -> {
                        WorkFlowCommentDTO.WorkFlowSimpleCommon simpleCommon = new WorkFlowCommentDTO.WorkFlowSimpleCommon();
                        simpleCommon.setFlowComment(common.getProcessComment());
                        simpleCommon.setOptionOrgCd(common.getOrgCd());
                        simpleCommon.setPositionCd(common.getActivityId());
                        simpleCommon.setOptionUserName(common.getCustomerName());
                        commonList.add(simpleCommon);
                    });
                    commonMap.put(bizNo, commonList);
                }
            } else {
                // 获取template流程信息以及processId
                QueryWrapper<TbSysBackPositionInfo> queryWrapper = new QueryWrapper<>();
                queryWrapper.lambda().eq(TbSysBackPositionInfo::getBizNo, bizNo)
                        .in(TbSysBackPositionInfo::getIsDel,
                                Arrays.asList(WorkFlowConstant.STRING_NUM_0, WorkFlowConstant.STRING_NUM_1));
                TbSysBackPositionInfo tbSysBackPositionInfo = tbSysBackPositionInfoMapper.selectOne(queryWrapper);
                // 查询流程意见信息以及岗位信息
                List<PageFlowComment> workFlowCommentList = null;
                if (ObjectUtil.isNotNull(tbSysBackPositionInfo)) {
                    workFlowCommentList = tbSysBackPositionInfoMapper.getFlowCommentList(tbSysBackPositionInfo.getProcessId());
                    if (ObjectUtil.isNotEmpty(workFlowCommentList)) {
                        // 转义查询岗位分页信息
                        List<WorkFlowCommentDTO.WorkFlowSimpleCommon> commonList = workFlowCommentList.stream().map(pageCommon ->
                                workFlowConvert.pageCommonDtoToCommon(pageCommon)
                        ).collect(Collectors.toList());
                        commonMap.put(bizNo, commonList);
                    }
                }
            }
        });

        // 如果map信息非空设置map信息
        if (ObjectUtil.isNotEmpty(commonMap)) {
            workFlowCommentDTO.setCommonMap(commonMap);
        }

        return workFlowCommentDTO;
    }

    /**
     * 通过bizType以及岗位中文名称获取岗位cd
     *
     * @param workFlowTransferDTO 参数dto
     * @return 岗位信息
     */
    @Override
    public WorkFlowTransferDTO getPositionCd(WorkFlowTransferDTO workFlowTransferDTO) {
        // 通过bizType获取流程模板id
        WorkFlowProductEnum productEnum = workFlowUtil.getProductEnumByBizType(workFlowTransferDTO.getBizType());
        if (ObjectUtil.isNull(productEnum) || StrUtil.isBlank(productEnum.getTemplateId())) {
            throw new ServiceException(StrUtil.format("通过流程bizType[{}]获取流程枚举类型失败!",
                    workFlowTransferDTO.getBizType()));
        }
        String templateId = productEnum.getTemplateId();

        // 通过模板id以及岗位名称获取positionCd信息
        QueryWrapper<TbSysFlowPosition> flowPositionQueryWrapper = new QueryWrapper<>();
        flowPositionQueryWrapper.lambda().eq(TbSysFlowPosition::getFlowTempletNum, templateId);
        List<TbSysFlowPosition> positionList = tbSysFlowPositionMapper.selectList(flowPositionQueryWrapper);
        if (ObjectUtil.isEmpty(positionList)) {
            throw new ServiceException(StrUtil.format("通过流程模板编号[{}]获取流程配置信息失败!", templateId));
        }
        String flowId = positionList.get(WorkFlowServerConstant.INT_NUM_0).getFlowId();
        QueryWrapper<TbSysFlowPositionDetail> detailQueryWrapper = new QueryWrapper<>();
        detailQueryWrapper.lambda().eq(TbSysFlowPositionDetail::getFlowId, flowId)
                .eq(TbSysFlowPositionDetail::getPositionName, workFlowTransferDTO.getPositionName());
        TbSysFlowPositionDetail detail = tbSysFlowPositionDetailMapper.selectOne(detailQueryWrapper);
        if (ObjectUtil.isNull(detail) || StrUtil.isBlank(detail.getPositionCd())) {
            throw new ServiceException("获取流程岗位cd详情信息失败!");
        }
        workFlowTransferDTO.setPositionCd(detail.getPositionCd());

        return workFlowTransferDTO;
    }

    /**
     * 获取外围系统代办业务列表信息
     *
     * @param workFlowUndoListDTO 参数dto
     * @return 参数dto
     */
    @Override
    public WorkFlowUndoListDTO getUndoListDetailList(WorkFlowUndoListDTO workFlowUndoListDTO) {
        // 处理人id
        String userId = StrUtil.format(WorkFlowServerConstant.USER_ID_APPEND_TEMPLATE, workFlowUndoListDTO.getUserCd(),
                workFlowUndoListDTO.getOrgCd());

        // 循环拼装信息
        List<WorkFlowUndoListDTO.OtherSystemUndoWork> otherSystemUndoWorkList = new ArrayList<>();
        for (WorkFlowProductEnum workFlowProductEnum : workFlowUndoListDTO.getWorkFlowProductEnumList()) {
            // 分页查询初始化任务列表信息
            TaskQuery taskQuery = taskService.createTaskQuery()
                    // 处理人
                    .taskAssignee(userId)
                    // 生效的
                    .active()
                    // 带有参数信息
                    .includeProcessVariables()
                    // 创建时间倒序
                    .orderByTaskCreateTime()
                    .desc();
            // 获取任务列表信息
            List<Task> taskList = taskQuery.list();

            // 待封装待办任务信息列表
            List<WorkFlowUndoListDTO.WorkFlowUndoTask> workFlowDtoList = new ArrayList<>();

            // 任务列表非空判定
            if (ObjectUtil.isNotEmpty(taskList)) {
                // 获取柜员名称以及机构信息
                List<String> userInfoList = taskList.stream().map(taskInfo -> {
                    // 获取流程变量信息
                    Map<String, Object> processVariables = taskInfo.getProcessVariables();
                    if (workFlowProductEnum.getBizType()
                            .equals(StrUtil.toString(processVariables.get(WorkFlowServerConstant.BIZ_TYPE_FLAG)))) {
                        return StrUtil.toString(processVariables.get(WorkFlowServerConstant.CREATOR_FLAG));
                    } else {
                        return null;
                    }
                }).collect(Collectors.toList()).stream().distinct().filter(Objects::nonNull).collect(Collectors.toList());
                // 当前业务没有数据
                if (ObjectUtil.isEmpty(userInfoList)) {
                    continue;
                }
                // 获取用户信息列表
                List<String> userCdList = userInfoList.stream().map(userInfo -> {
                    String[] creatorInfo = userInfo.split(WorkFlowServerConstant.SPLIT_FLAG);
                    return creatorInfo[0];
                }).collect(Collectors.toList());
                List<ManageUserDTO> userDTOList = managementApiClient.listUserInfoByUserCd(userCdList);
                Map<String, String> userInfoMap = userDTOList.stream().collect(
                        Collectors.toMap(ManageUserDTO::getUserCd, ManageUserDTO::getUserName)
                );
                // 获取机构信息列表
                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)
                );

                // 其他系统未办业务
                WorkFlowUndoListDTO.OtherSystemUndoWork otherSystemUndoWork = new WorkFlowUndoListDTO.OtherSystemUndoWork();
                List<WorkFlowUndoListDTO.WorkFlowUndoTask> finalWorkFlowDtoList = workFlowDtoList;
                taskList.forEach(taskInfo -> {
                    // 获取参数信息
                    Map<String, Object> processVariables = taskInfo.getProcessVariables();
                    if (workFlowProductEnum.getBizType()
                            .equals(StrUtil.toString(processVariables.get(WorkFlowServerConstant.BIZ_TYPE_FLAG)))) {
                        WorkFlowUndoListDTO.WorkFlowUndoTask undoTask = new WorkFlowUndoListDTO.WorkFlowUndoTask();
                        // 业务编号
                        undoTask.setBizNo(StrUtil.toString(processVariables.get(WorkFlowServerConstant.BIZ_ID_FLAG)));
                        // 客户名称
                        undoTask.setCustomerName(
                                StrUtil.toString(processVariables.get(WorkFlowServerConstant.CUSTOMER_NAME_FLAG)));
                        // 设置业务种类信息
                        undoTask.setBizType(workFlowProductEnum.getBizType());
                        WorkFlowProductEnum productEnum = workFlowUtil
                                .getProductEnumByBizType(workFlowProductEnum.getBizType());
                        // 业务名称
                        undoTask.setBizName(productEnum.getBizTypeName());
                        // 设置创建人信息
                        String[] creatorInfo = StrUtil.toString(processVariables.get(WorkFlowServerConstant.CREATOR_FLAG))
                                .split(WorkFlowServerConstant.SPLIT_FLAG);
                        // 创建人
                        undoTask.setProcessCreator(creatorInfo[0]);
                        // 创建人名称
                        undoTask.setProcessCreatorName(userInfoMap.get(creatorInfo[0]));
                        // 机构cd
                        undoTask.setOrgCd(creatorInfo[1]);
                        // 机构名称
                        undoTask.setOrgName(orgInfoMap.get(creatorInfo[1]));
                        // 流程实例id
                        undoTask.setProcessId(taskInfo.getProcessInstanceId());
                        // 创建时间
                        String createTime = DateUtil.format(taskInfo.getCreateTime(), DatePattern.NORM_DATETIME_PATTERN);
                        undoTask.setProcessCreateTime(createTime);
                        // 当前岗位中文名称
                        undoTask.setActivityId(taskInfo.getName());
                        // 任务id
                        undoTask.setTaskId(taskInfo.getId());

                        // 客户名称非空校验
                        if (StrUtil.isNotBlank(workFlowUndoListDTO.getCustomerName())) {
                            // 客户名称
                            String undoCustomerName = StrUtil
                                    .toString(processVariables.get(WorkFlowServerConstant.CUSTOMER_NAME_FLAG));
                            if (StrUtil.isNotBlank(undoCustomerName)
                                    && undoCustomerName.contains(workFlowUndoListDTO.getCustomerName())) {
                                finalWorkFlowDtoList.add(undoTask);
                            }
                        } else {
                            finalWorkFlowDtoList.add(undoTask);
                        }
                    }
                });
                if (ObjectUtil.isNotEmpty(finalWorkFlowDtoList)) {
                    // 过滤非外围系统标识数据
                    List<String> bizNumList = finalWorkFlowDtoList.stream().map(
                            WorkFlowUndoListDTO.WorkFlowUndoTask::getBizNo
                    ).collect(Collectors.toList());

                    // 获取列表信息
                    QueryWrapper<TbSysUnfinishedFlow> queryWrapper = new QueryWrapper<>();
                    queryWrapper.lambda().eq(TbSysUnfinishedFlow::getSystemFlag,
                            workFlowUndoListDTO.getWorkFlowSysEnum().getSystemFlag());
                    if (bizNumList.size() < OracleInQueryUtil.DEFAULT_SPLIT_SIZE) {
                        // 系统标识
                        queryWrapper.lambda().in(TbSysUnfinishedFlow::getBizNo, bizNumList);
                    } else {
                        oracleInQueryUtil.queryWrapperIn(queryWrapper,
                                WorkFlowConstant.BIZ_NO_FLAG,
                                bizNumList,
                                OracleInQueryUtil.DEFAULT_SPLIT_SIZE);
                    }
                    // 获取未完成代办列表信息
                    List<TbSysUnfinishedFlow> unfinishedFlowList = tbSysUnfinishedFlowMapper.selectList(queryWrapper);
                    if (ObjectUtil.isNotEmpty(unfinishedFlowList)) {
                        Map<String, String> bizNumMap = unfinishedFlowList.stream().collect(Collectors.toMap(
                                TbSysUnfinishedFlow::getBizNo, TbSysUnfinishedFlow::getBizNo, (k1, k2) -> k1)
                        );
                        // 过滤非当前系统业务信息
                        finalWorkFlowDtoList.removeIf(undoTask ->
                                StrUtil.isBlank(bizNumMap.get(undoTask.getBizNo()))
                        );
                        otherSystemUndoWork.setFinalWorkFlowDtoList(finalWorkFlowDtoList);
                        otherSystemUndoWork.setBizType(workFlowProductEnum.getBizType());
                        otherSystemUndoWork.setBizCount(StrUtil.toString(finalWorkFlowDtoList.size()));
                        otherSystemUndoWorkList.add(otherSystemUndoWork);
                    }
                }
            }
            if (ObjectUtil.isNotEmpty(otherSystemUndoWorkList)) {
                workFlowUndoListDTO.setOtherSystemUndoWorkList(otherSystemUndoWorkList);
            }
        }
        // 去除无用信息
        workFlowUndoListDTO.setWorkFlowSysEnum(null);
        workFlowUndoListDTO.setWorkFlowProductEnumList(null);
        workFlowUndoListDTO.setCustomerName(null);
        workFlowUndoListDTO.setUserCd(null);
        workFlowUndoListDTO.setOrgCd(null);
        return workFlowUndoListDTO;
    }

    /**
     * 获取外围系统跟踪列表信息
     *
     * @param workFLowOtherTraceListDTO 参数dto
     * @return 列表信息
     */
    @Override
    public WorkFlowOtherTraceListDTO getOtherSysTraceListInfo(WorkFlowOtherTraceListDTO workFLowOtherTraceListDTO) {
        // 设置查询用户id
        String userId = StrUtil.format(WorkFlowServerConstant.USER_ID_APPEND_TEMPLATE,
                workFLowOtherTraceListDTO.getUserCd(),
                workFLowOtherTraceListDTO.getOrgCd());

        // 获取历史信息
        List<WorkFlowActHisProcessListDTO> actHisProcessListDTOList = queryStatusHisList(userId,
                workFLowOtherTraceListDTO.getStatus());

        // 通过系统编号获取所有外围系统发起业务
        List<TbSysUnfinishedFlow> unfinishedFlowList = tbSysUnfinishedFlowMapper.getOtherSysUnfinishedFlowList(
                workFLowOtherTraceListDTO.getWorkFlowSysEnum().getSystemFlag());
        if (ObjectUtil.isEmpty(unfinishedFlowList)) {
            // 当前系统没有发生业务
            return new WorkFlowOtherTraceListDTO();
        }

        // 设置map信息,方便校验业务是否为当前系统标识
        Map<String, String> otherBizMap = unfinishedFlowList.stream().collect(Collectors.toMap(
                TbSysUnfinishedFlow::getBizNo, TbSysUnfinishedFlow::getBizNo, (k1, k2) -> k2)
        );

        // 查询历史信息非空判定
        if (ObjectUtil.isNotEmpty(actHisProcessListDTOList)) {
            // 最终转换跟踪列表信息
            List<WorkFlowTrace> traceList = new ArrayList<>();
            // 合同编号列表
            List<String> contractNumList = new ArrayList<>();

            actHisProcessListDTOList.forEach(processInfo -> {
                // 获取流程模板信息,并且过滤风险部分数据
                String tractTemplateId = processInfo.getProcessDefinitionKey();
                if (!tractTemplateId.contains(WorkFlowServerConstant.RSK_PREFIX)) {
                    // 通过业务名称获取客户号,客户名称
                    String contractNum = processInfo.getBusinessKey();
                    contractNumList.add(contractNum);
                }
            });
            // 设置查询参数,根据合同号批量查询客户信息
            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(workFLowOtherTraceListDTO.getProcessCustomerName())
                                    || (StrUtil.isNotBlank(workFLowOtherTraceListDTO.getProcessCustomerName())
                                    && contractInfo.getCustomerName().contains(workFLowOtherTraceListDTO.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 -> {
                    // 开始操作柜员非空判定
                    if (StrUtil.isNotBlank(processInfo.getStartUserId())) {
                        // 获取合同编号
                        String contractNum = processInfo.getBusinessKey();
                        LoanWorkFlowDTO.ContractInfo contractInfo = customerMap.get(contractNum);
                        // 通过bizNum业务编号判断当前业务是否为外围系统发起业务
                        if (ObjectUtil.isNotEmpty(contractInfo) && StrUtil.isNotBlank(otherBizMap.get(contractNum))) {
                            // 将processInfo转关为processMap
                            Map<String, Object> processMap = JSON.parseObject(JSONObject.toJSONString(processInfo));

                            // 设置产品类型请以及流程状态参数信息
                            WorkFlowTraceListDTO workFlowTraceListDTO = new WorkFlowTraceListDTO();
                            workFlowTraceListDTO.setBizTypeTrace(workFLowOtherTraceListDTO
                                    .getWorkFlowProductEnum().getBizType());
                            workFlowTraceListDTO.setStatus(workFLowOtherTraceListDTO.getStatus());
                            // workFlowTrace返回信息拼装
                            buildWorkFlowTraceInfo(workFlowTraceListDTO, traceList,
                                    processMap,
                                    contractInfo.getCustomerName(),
                                    contractInfo.getCustomerNum());
                        }
                    }
                });
            }
            // 设置返回信息
            List<WorkFlowOtherTraceListDTO.WorkFlowOtherTraceInfo> otherTraceInfoList = new ArrayList<>();
            if (ObjectUtil.isNotEmpty(traceList)) {
                traceList.forEach(trace -> {
                    trace.setBizType(workFLowOtherTraceListDTO.getWorkFlowProductEnum().getBizTypeName());
                    WorkFlowOtherTraceListDTO.WorkFlowOtherTraceInfo otherTraceInfo =
                            workFlowConvert.traceConvertOtherTrace(trace);
                    if (ObjectUtil.isNotNull(trace.getCreateDate())) {
                        otherTraceInfo.setCreateDate(DateUtil.format(trace.getCreateDate(), DatePattern.NORM_DATETIME_PATTERN));
                    }
                    otherTraceInfoList.add(otherTraceInfo);
                });
                workFLowOtherTraceListDTO.setTraceInfoList(otherTraceInfoList);
            }
        }
        // 删除无用数据
        workFLowOtherTraceListDTO.setWorkFlowSysEnum(null);
        workFLowOtherTraceListDTO.setStatus(null);
        workFLowOtherTraceListDTO.setUserCd(null);
        workFLowOtherTraceListDTO.setOrgCd(null);
        workFLowOtherTraceListDTO.setProcessCustomerName(null);
        workFLowOtherTraceListDTO.setWorkFlowProductEnum(null);
        return workFLowOtherTraceListDTO;
    }

    /**
     * app通过业务类型获取业务count信息
     *
     * @param workFlowAppUndoCountDTO 参数dto
     * @return 列表信息
     */
    @Override
    public WorkFlowAppUndoCountDTO getAppUndoCountInfoList(WorkFlowAppUndoCountDTO workFlowAppUndoCountDTO) {
        // 任务类型列表信息
        List<WorkFlowProductEnum> workFlowProductEnumList = workFlowAppUndoCountDTO.getBizTypeList();
        Map<String, WorkFlowProductEnum> productEnumMap = workFlowProductEnumList.stream().collect(
                Collectors.toMap(WorkFlowProductEnum::getBizType, Function.identity(), (k1, k2) -> k1)
        );

        // 获取柜员机构信息
        String userCd = webUtil.getCurrentUserCd();
        String orgCd = webUtil.getCurrentOrgCd();
        Map<String, Integer> countMap = new HashMap<>(8);
        // 分页查询初始化任务列表信息
        String userId = StrUtil.format(WorkFlowServerConstant.USER_ID_APPEND_TEMPLATE, userCd, orgCd);

        // 通过assignee处理人查询任务列表,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> processVariableMap = task.getProcessVariables();
                String bizType = StrUtil.emptyToDefault(
                        (String) processVariableMap.get(WorkFlowServerConstant.BIZ_TYPE_FLAG), StrUtil.EMPTY);
                if (StrUtil.isNotBlank(bizType) && ObjectUtil.isNotNull(productEnumMap.get(bizType))) {
                    workFlowUtil.countWorkFlow(countMap, bizType);
                }
            });
        }

        // 代办任务各子业务count信息列表拼装
        List<WorkFlowAppUndoCountDTO.WorkFlowBizCount> workFlowBizCountList = new ArrayList<>();
        AtomicReference<Integer> totalCount = new AtomicReference<>(WorkFlowServerConstant.INT_NUM_0);
        productEnumMap.forEach((enumKey, productEnum) -> {
            WorkFlowAppUndoCountDTO.WorkFlowBizCount workFlowBizCount = new WorkFlowAppUndoCountDTO.WorkFlowBizCount();
            if (ObjectUtil.isNotNull(countMap.get(enumKey))) {
                workFlowBizCount.setBizCount(countMap.get(enumKey));
                workFlowBizCount.setBizType(enumKey);
                workFlowBizCountList.add(workFlowBizCount);
                totalCount.set(totalCount.get() + countMap.get(enumKey));
            } else {
                workFlowBizCount.setBizCount(WorkFlowServerConstant.INT_NUM_0);
                workFlowBizCount.setBizType(enumKey);
                workFlowBizCountList.add(workFlowBizCount);
            }
            workFlowBizCountList.add(workFlowBizCount);
        });

        if (ObjectUtil.isNotEmpty(workFlowBizCountList)) {
            workFlowAppUndoCountDTO.setWorkFlowBizCountList(workFlowBizCountList);
        }
        workFlowAppUndoCountDTO.setTotalCount(totalCount.get());
        return workFlowAppUndoCountDTO;
    }

    /**
     * app通过业务类型获取跟踪列表业务count信息
     *
     * @param workFlowAppTraceCountDTO 参数dto
     * @return 列表信息
     */
    @Override
    public WorkFlowAppTraceCountDTO getAppTraceCountInfoList(WorkFlowAppTraceCountDTO workFlowAppTraceCountDTO) {

        // 任务类型列表信息
        List<WorkFlowProductEnum> workFlowProductEnumList = workFlowAppTraceCountDTO.getBizTypeList();
        Map<String, WorkFlowProductEnum> productEnumMap = workFlowProductEnumList.stream().collect(
                Collectors.toMap(WorkFlowProductEnum::getBizType, Function.identity(), (k1, k2) -> k1)
        );

        // 拼装流程发起参数
        String userId = StrUtil.format(WorkFlowServerConstant.USER_ID_APPEND_TEMPLATE,
                webUtil.getCurrentUserCd(),
                webUtil.getCurrentOrgCd());
        Map<String, Object> paramMap = new HashMap<>(WorkFlowServerConstant.DEFAULT_MAP_SIZE);
        paramMap.put(WorkFlowServerConstant.PAGE_INDEX_FLAG, WorkFlowServerConstant.PAGE_INDEX);
        paramMap.put(WorkFlowServerConstant.CURRENT_PAGE_FLAG, WorkFlowServerConstant.CURRENT_PAGE);
        paramMap.put(WorkFlowServerConstant.PAGE_SIZE_FLAG, WorkFlowServerConstant.PAGE_SIZE);
        paramMap.put(WorkFlowServerConstant.USER_ID_FLAG, userId);

        // 跟踪列表信息,由完成任务以及未完成任务组成
        List<WorkFlowTrace> traceList = new ArrayList<>();

        // 获取未完成的任务信息
        List<WorkFlowActHisProcessListDTO> hisProcessList = queryStatusHisList(userId,
                WorkFlowServerConstant.WORKFLOW_STATUS_RUNNING);

        // 获取任务列表非空校验
        if (ObjectUtil.isNotEmpty(hisProcessList)) {
            // 合同编号列表
            List<String> contractNumList = new ArrayList<>();
            hisProcessList.forEach(processInfo -> {
                // 获取流程模板信息,并且过滤风险部分数据
                String tractTemplateId = processInfo.getProcessDefinitionKey();
                if (!tractTemplateId.contains(WorkFlowServerConstant.RSK_PREFIX)) {
                    // 通过业务名称获取客户号,客户名称
                    String contractNum = processInfo.getBusinessKey();
                    contractNumList.add(contractNum);
                }
            });
            // 设置查询参数,根据合同号批量查询客户信息
            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: 后续可能修改
                            return !ObjectUtil.isNull(contractInfo.getCustomerName())
                                    && !ObjectUtil.isNull(contractInfo.getCustomerNum());
                        }).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)
                        );

                hisProcessList.forEach(processInfo -> {
                    // 获取模板信息
                    String tractTemplateId = processInfo.getProcessDefinitionKey();
                    WorkFlowProductEnum workFlowProductEnum = workFlowUtil.getProductEnumByTemplateId(tractTemplateId);

                    // app排除非app业务信息
                    if (ObjectUtil.isNotNull(workFlowProductEnum)
                            && ObjectUtil.isNotNull(productEnumMap.get(workFlowProductEnum.getBizType()))) {
                        // 通过业务名称获取客户号,客户名称
                        if (StrUtil.isNotBlank(processInfo.getStartUserId())) {
                            String contractNum = processInfo.getBusinessKey();
                            LoanWorkFlowDTO.ContractInfo contractInfo = customerMap.get(contractNum);
                            if (ObjectUtil.isNotEmpty(contractInfo)) {
                                WorkFlowTraceVO workFlowTrace = new WorkFlowTraceVO();
                                workFlowTrace.setBizNo(contractNum);
                                workFlowTrace.setBizType(workFlowProductEnum.getBizType());
                                traceList.add(workFlowTrace);
                            }
                        }
                    }
                });
            }
        }
        // 组装app跟踪列表count信息
        if (ObjectUtil.isNotEmpty(traceList)) {
            Map<String, Integer> countMap = new HashMap<>(8);
            traceList.forEach(trace -> {
                String bizType = trace.getBizType();
                if (StrUtil.isNotBlank(bizType) && ObjectUtil.isNotNull(productEnumMap.get(bizType))) {
                    workFlowUtil.countWorkFlow(countMap, bizType);
                }
            });

            if (ObjectUtil.isNotEmpty(countMap)) {
                // 代办任务各子业务count信息列表拼装
                List<WorkFlowAppTraceCountDTO.WorkFlowBizCount> workFlowBizCountList = new ArrayList<>();
                AtomicReference<Integer> totalCount = new AtomicReference<>(WorkFlowServerConstant.INT_NUM_0);
                productEnumMap.forEach((enumKey, productEnum) -> {
                    WorkFlowAppTraceCountDTO.WorkFlowBizCount workFlowBizCount = new WorkFlowAppTraceCountDTO.WorkFlowBizCount();
                    if (ObjectUtil.isNotNull(countMap.get(enumKey))) {
                        workFlowBizCount.setBizCount(countMap.get(enumKey));
                        workFlowBizCount.setBizType(enumKey);
                        workFlowBizCountList.add(workFlowBizCount);
                        totalCount.set(totalCount.get() + countMap.get(enumKey));
                    } else {
                        workFlowBizCount.setBizCount(WorkFlowServerConstant.INT_NUM_0);
                        workFlowBizCount.setBizType(enumKey);
                        workFlowBizCountList.add(workFlowBizCount);
                    }
                    workFlowBizCountList.add(workFlowBizCount);
                });
                if (ObjectUtil.isNotEmpty(workFlowBizCountList)) {
                    workFlowAppTraceCountDTO.setWorkFlowBizCountList(workFlowBizCountList);
                }
                workFlowAppTraceCountDTO.setTotalCount(totalCount.get());
            }
        }
        return workFlowAppTraceCountDTO;
    }

    /**
     * 三个月前获取参数列表信息
     *
     * @param workFlowRiskActHiVarDTO 参数dto
     * @return 参数
     */
    @Override
    public WorkFlowRiskActHiVarDTO getActHiVarinst(WorkFlowRiskActHiVarDTO workFlowRiskActHiVarDTO) {
        // 根据流程参数信息获取合同客户信息列表
        List<String> processIdList = workFlowRiskActHiVarDTO.getProcessIdList();
        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);
        if (ObjectUtil.isNotEmpty(varinstList)) {
            List<WorkFlowRiskActHiVarDTO.ActHiVarinst> innerActHiVarinstList = varinstList.stream().map(varinst ->
                    workFlowConvert.workActToInnerActHiVar(varinst)
            ).collect(Collectors.toList());
            workFlowRiskActHiVarDTO.setActHiVarinstList(innerActHiVarinstList);
        }
        return workFlowRiskActHiVarDTO;
    }

    /**
     * 获取风险任务实例历史信息
     *
     * @param workFlowActProcessTraceDTO 参数dto
     * @return
     */
    @Override
    public WorkFlowActProcessTraceDTO getActProcessTraceList(WorkFlowActProcessTraceDTO workFlowActProcessTraceDTO) {
        // 拼装流程发起参数
        String userId = StrUtil.format(WorkFlowServerConstant.USER_ID_APPEND_TEMPLATE,
                workFlowActProcessTraceDTO.getUserCd(),
                workFlowActProcessTraceDTO.getOrgCd());
        // 查询本地备份表信息进行数据查询
        List<ActProcessTrace> processTraceList = actHiTaskinstBackMapper.getActProcessTraceHisList(userId);
        if (ObjectUtil.isNotEmpty(processTraceList)) {
            List<WorkFlowActProcessTraceDTO.ActProcessTrace> traceList = processTraceList.stream().map(trace -> {
                return workFlowConvert.workActProTraceToInnerTrace(trace);
            }).collect(Collectors.toList());
            workFlowActProcessTraceDTO.setActProcessTraceList(traceList);
        }
        return workFlowActProcessTraceDTO;
    }

    /**
     * 获取风险三个月前流程意见信息
     *
     * @param traceHistoryListDTO 参数dto
     * @return
     */
    @Override
    public WorkFlowRiskCommonDTO getRiskCommonInfo(WorkFlowTraceHistoryListDTO traceHistoryListDTO) {
        WorkFlowTraceHistoryListDTO workFlowTraceHistoryListDTO = getNewFlowCommentOutThreeMonth(traceHistoryListDTO);
        return workFlowConvert.traceListToRiskCommon(workFlowTraceHistoryListDTO);
    }

    /**
     * 查看当前用户的在途任务-贷审会抽取委员
     *
     * @param bizNo 流程编号
     * @return 在途业务信息
     */
    @Override
    public String findUndoTaskForDSH(String bizNo) {
        // 查询在途信息
        String message = null;
        QueryWrapper<TbSysUnfinishedFlow> queryWrapper = new QueryWrapper<>();
        if (StrUtil.isNotBlank(bizNo) && !bizNo.equals(WorkFlowServerConstant.STRING_NUM_1)) {
            queryWrapper.lambda().eq(TbSysUnfinishedFlow::getBizNo, bizNo);
        } else {
            queryWrapper.lambda().in(TbSysUnfinishedFlow::getBizName, "贷审会专家委员抽取");
        }
        List<TbSysUnfinishedFlow> flowList = tbSysUnfinishedFlowMapper.selectList(queryWrapper);
        if (ObjectUtil.isNotEmpty(flowList)) {
            TbSysUnfinishedFlow tbSysUnfinishedFlow = flowList.get(WorkFlowServerConstant.PAGE_INDEX);
            message = tbSysUnfinishedFlow.getCustomerNum();
        }
        return message;
    }

    /**
     * 直接通过文件部署新流程图
     *
     * @param multipartFile
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String deployProcess(MultipartFile multipartFile) throws IOException, ParserConfigurationException, SAXException {
        // 文件校验,校验文件是否为空以及是否为bpmn文件
        if (ObjectUtil.isEmpty(multipartFile)) {
            throw new ServiceException("部署新流程,流程文件为空!");
        }
        if (StrUtil.isBlank(multipartFile.getOriginalFilename())
                || !multipartFile.getOriginalFilename().endsWith(WorkFlowServerConstant.BPMN_FILE_SUFFIX)) {
            throw new ServiceException("部署新流程文件格式错误,请上传bpmn格式流程文件!");
        }

        // 获取部署文件名称,eg : aftLoanFirstCheckNew.bpmn
        String deployFileName = multipartFile.getOriginalFilename();

        // 校验部署文件在enum中是否已经正确配置,如果没有则抛出异常
        String deployFileKey = StrUtil.subBefore(deployFileName, WorkFlowServerConstant.BPMN_FILE_SUFFIX, true);
        WorkFlowProductEnum templateEnum = workFlowUtil.getProductEnumByTemplateId(deployFileKey);

        // 风险系统部署流程不需要进行enum枚举类校验
        if (ObjectUtil.isNull(templateEnum) && !deployFileName.startsWith(WorkFlowServerConstant.RSK_PREFIX)) {
            throw new ServiceException(StrUtil
                    .format("流程[{}]未在流程枚举类WorkFlowProductEnum中正确配置,请确认!", deployFileName));
        }

        // 校验文件节点是否进行过跳岗节点配置
        StringBuilder xmlContent = new StringBuilder();
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(multipartFile.getInputStream()))) {
            String line;
            while ((line = reader.readLine()) != null) {
                xmlContent.append(line);
            }
        }

        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        InputSource is = new InputSource(new StringReader(xmlContent.toString()));
        Document doc = builder.parse(is);

        // 获取文件中的所有userTask节点
        NodeList nodeList = doc.getElementsByTagName(WorkFlowServerConstant.BIG_USER_TASK_FLAG);

        // 获取文件中所有 process节点,正常只有一个
        NodeList processNodeList = doc.getElementsByTagName(WorkFlowServerConstant.PROCESS);
        if (ObjectUtil.isEmpty(processNodeList) || processNodeList.getLength() != 1) {
            throw new ServiceException("流程中[process]节点必须只能有一个,部署流程失败!");
        }
        Node processNode = processNodeList.item(0);
        NamedNodeMap processNodeAttributes = processNode.getAttributes();
        // 判定参数是否为空
        if (ObjectUtil.isNotEmpty(processNodeAttributes)) {
            // 存储信息
            if (ObjectUtil.isNull(processNodeAttributes.getNamedItem("name")) || ObjectUtil.isNull(processNodeAttributes.getNamedItem("id"))) {
                throw new ServiceException("当前部署流程图,部分userTask节点没有正确配置name以及id属性,请确认!");
            }

            // 分别获取userTask节点中的name以及id属性
            Node nameNode = processNodeAttributes.getNamedItem(WorkFlowServerConstant.NAME_FLAG);
            Node idNode = processNodeAttributes.getNamedItem(WorkFlowServerConstant.ID_FLAG);
            String name = nameNode.getNodeValue();
            String id = idNode.getNodeValue();

            // 中文名称判定
            if (!name.equals(id) || !deployFileName.contains(name)) {
                throw new ServiceException("流程文件中的[process]节点要求name与id必须相同,并且需要与流程文件名称相同,请确认!");
            }
        }

        // 获取流程中文名称
        NodeList textAnnotationNodeList = doc.getElementsByTagName(WorkFlowServerConstant.TEXT_ANNOTATION);
        if (textAnnotationNodeList.getLength() > WorkFlowServerConstant.INT_NUM_1 || ObjectUtil.isEmpty(textAnnotationNodeList)) {
            throw new ServiceException("流程中[textAnnotationNode]节点必须只能有一个,部署流程失败!");
        }
        // 获取部署流程的中文名称
        String deployChineseName = null;
        for (int i = 0; i < textAnnotationNodeList.getLength(); i++) {
            Node textAnnotationNode = textAnnotationNodeList.item(i);
            // 查找textAnnotation下的text节点
            Node textNode = textAnnotationNode.getFirstChild();
            while (textNode != null) {
                if (textNode.getNodeType() == Node.ELEMENT_NODE
                        && WorkFlowServerConstant.TEXT.equals(textNode.getNodeName())) {
                    // 获取text节点的文本内容
                    deployChineseName = textNode.getTextContent();
                    // textAnnotation下只有一个text节点,找到后即可退出循环
                    break;
                }
                textNode = textNode.getNextSibling();
            }
        }

        // 名称校验,风险系统不需要进行名称校验
        if (!deployFileName.startsWith(WorkFlowServerConstant.RSK_PREFIX)
                && !templateEnum.getBizTypeName().equals(deployChineseName)) {
            throw new ServiceException(StrUtil
                    .format("流程[{}],对应WorkFlowProductEnum枚举类中配置的中文名称[{}]与流程文件中配置的名称[{}]不符,部署失败!",
                            deployFileKey, templateEnum.getBizTypeName(), deployChineseName));
        }

        // 进行position以及positionDetail数据插入,校验原有跳岗信息新部署节点是否包含,如果不包含则抛出异常
        if (!deployFileName.startsWith(WorkFlowServerConstant.RSK_PREFIX)) {
            Map<String, String> positionDetailMap = new HashMap<>();
            for (int i = 0; i < nodeList.getLength(); i++) {
                Node node = nodeList.item(i);
                NamedNodeMap attributes = node.getAttributes();
                // 判定参数是否为空
                if (ObjectUtil.isNotEmpty(attributes)) {
                    // 存储信息
                    if (ObjectUtil.isNull(attributes.getNamedItem("name")) || ObjectUtil.isNull(attributes.getNamedItem("id"))) {
                        throw new ServiceException("当前部署流程图,部分userTask节点没有正确配置name以及id属性,请确认!");
                    }

                    // 分别获取userTask节点中的name以及id属性
                    Node nameNode = attributes.getNamedItem(WorkFlowServerConstant.NAME_FLAG);
                    Node idNode = attributes.getNamedItem(WorkFlowServerConstant.ID_FLAG);
                    // 岗位中文名称
                    String name = nameNode.getNodeValue();
                    // eg: usertask12
                    String id = idNode.getNodeValue();

                    // 设置map信息
                    positionDetailMap.put(name, id);
                }
            }

            // 开始获取跳岗信息,包含两部分信息,分别为配置跳岗节点,以及跳岗目标array节点信息
            List<String> jumpDefineNameList = new ArrayList<>();
            List<WorkFlowJumpPointDTO> jumpInfoList = tbSysWorkflowJumpMapper.getDeployJumpInfoList(deployFileKey);
            if (ObjectUtil.isNotEmpty(jumpInfoList)) {
                // 配置跳岗节点
                List<String> taskDefinitionNameList = jumpInfoList.stream().map(
                        WorkFlowJumpPointDTO::getTaskDefinitionName
                ).collect(Collectors.toList());

                // 将jumpList中的TbSysWorkflowJump对象中的positionArray进行按照逗号分割,分割后进行去重过滤,然后再次组装成list
                List<String> positionArrayList = jumpInfoList.stream()
                        .map(WorkFlowJumpPointDTO::getPositionArray)
                        .map(positionArray -> StrUtil.split(positionArray, StrUtil.COMMA))
                        .flatMap(Arrays::stream)
                        .distinct()
                        .collect(Collectors.toList());
                jumpDefineNameList.addAll(taskDefinitionNameList);
                jumpDefineNameList.addAll(positionArrayList);
                jumpDefineNameList = jumpDefineNameList.stream().distinct().collect(Collectors.toList());
            }
            // 进行流程跳岗配置岗位是否存在校验
            if (ObjectUtil.isNotEmpty(jumpDefineNameList)) {
                String differPositionInfo = jumpDefineNameList.stream().filter(jumpDefineName ->
                        StrUtil.isBlank(positionDetailMap.get(jumpDefineName))
                ).collect(Collectors.joining(StrUtil.COMMA));

                if (StrUtil.isNotBlank(differPositionInfo)) {
                    throw new ServiceException(StrUtil
                            .format("当前部署流程[{}]未包含原有跳岗岗位[{}],如需部署请先删除原有跳岗信息再进行部署!",
                                    deployFileKey, differPositionInfo));
                }
            }

            // 只有新部署的流程才进行流程部署节点自动插入
            QueryWrapper<TbSysFlowPosition> positionQueryWrapper = new QueryWrapper<>();
            positionQueryWrapper.lambda().eq(TbSysFlowPosition::getFlowTempletNum, deployFileKey);
            TbSysFlowPosition position = tbSysFlowPositionMapper.selectOne(positionQueryWrapper);
            if (ObjectUtil.isNull(position)) {
                // 新增缓存码值信息,注意此信息需要重启码值
                CacheTcSysCodes codes = new CacheTcSysCodes();
                codes.setCodeId(IdUtil.simpleUUID());
                codes.setCodeCd(templateEnum.getBizType());
                codes.setCodeName(templateEnum.getTemplateId());
                codes.setCodeLevelCd("1");
                codes.setCodeKey("S".concat(templateEnum.getBizType()));
                codes.setCodeTypeCd("ProcessTypeCd");
                codes.setOrderNo(templateEnum.getBizType());
                tbSysFlowPositionMapper.addTcSysCodes(codes);

                // 新增缓存码值信息
                baseCacheApi.addTcSysCodes("ProcessTypeCd", codes);

                // 新增流程定义信息
                position = new TbSysFlowPosition();
                String flowId = IdUtil.simpleUUID();
                position.setFlowId(flowId);
                position.setFlowTempletName(deployChineseName);
                position.setFlowTempletNum(deployFileKey);
                position.setCtime(new Date());
                position.setVersion(WorkFlowServerConstant.FLOW_TYPE_1);
                position.setHandlingOrgCd(webUtil.getCurrentOrgCd());
                position.setHandlingUserCd(webUtil.getCurrentUserCd());
                tbSysFlowPositionMapper.insert(position);

                // 将positionDetailMap对应的key转换为list类型 todo: 因为TbSysFlowPosition表中存在垃圾数据过多,一个岗位中文名称对应多个positionCd,暂时注释
                /**
                 Set<String> keySet = positionDetailMap.keySet();
                 List<String> positionNameList = new ArrayList<>(keySet);

                 // 获取岗位cd信息
                 List<Map<String, String>> positionInfoList = tbSysFlowPositionDetailMapper.listPositionCd(positionNameList);
                 Map<String, TbSysFlowPositionDetail> positionCdMap = positionInfoList.stream().collect(Collectors.toMap(
                 positionInfo -> positionInfo.get(WorkFlowServerConstant.POSITION_NAME_FLAG),
                 positionInfo -> {
                 TbSysFlowPositionDetail positionDetail = new TbSysFlowPositionDetail();
                 positionDetail.setPositionCd(positionInfo.get("positionCd"));
                 positionDetail.setPositionName(positionInfo.get("positionName"));
                 return positionDetail;
                 }
                 ));
                 **/

                // 循环加入userTask信息到岗位detail表中
                positionDetailMap.forEach((key, value) -> {
                    TbSysFlowPositionDetail positionDetail = new TbSysFlowPositionDetail();
                    positionDetail.setFlowDetailId(IdUtil.simpleUUID());
                    positionDetail.setFlowId(flowId);

                    // 设置岗位cd以及岗位名称,cd暂时需要手工设置
                    positionDetail.setPositionName(key);
                    // 设置流程userTask定义节点信息
                    positionDetail.setActivitiId(value);
                    positionDetail.setJumpDisplayFlag(WorkFlowServerConstant.FLOW_TYPE_0);
                    positionDetail.setCtime(new Date());
                    positionDetail.setMtime(new Date());
                    tbSysFlowPositionDetailMapper.insert(positionDetail);
                });
            }
        }

        // 开始进行部署操作
        Deployment deployment = repositoryService.createDeployment()
                .addInputStream(multipartFile.getOriginalFilename(), multipartFile.getInputStream())
                .name(deployFileKey)
                .deploy();

        String deploymentId = deployment.getId();
        List<ProcessDefinition> definitionList = repositoryService.createProcessDefinitionQuery()
                .deploymentId(deploymentId)
                .list();

        // 通过流程定义信息获取流程定义key
        if (ObjectUtil.isNotEmpty(definitionList)) {
            // 首次部署,取第一个定义信息即可
            ProcessDefinition processDefinition = definitionList.get(0);
            return processDefinition.getKey();
        } else {
            throw new ServiceException(StrUtil.format("流程已经部署,通过部署deploymentId[{}]获取流程定义信息为空!",
                    deploymentId));
        }
    }

    /**
     * 获取已经部署流程模板列表信息
     *
     * @param workFlowLoadTemplateDTO 参数dto
     * @return
     */
    @Override
    public WorkFlowPage<WorkFlowLoadTemplate> getLoadTemplatePage(WorkFlowLoadTemplateDTO workFlowLoadTemplateDTO) {
        // 定义查询类
        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
        // 流程定义条件查询,分别是定义key,以及流程定义名称还有版本号
        if (StrUtil.isNotBlank(workFlowLoadTemplateDTO.getTemplateKey())) {
            processDefinitionQuery.processDefinitionKeyLike(workFlowLoadTemplateDTO.getTemplateKey());
        }
        // 版本编号如果为空,则默认设置为最终版本
        if (ObjectUtil.isNotNull(workFlowLoadTemplateDTO.getVersion())) {
            processDefinitionQuery.processDefinitionVersion(workFlowLoadTemplateDTO.getVersion());
        } else {
            processDefinitionQuery.latestVersion();
        }

        // 获取总数量用于分表使用
        long totalCount = processDefinitionQuery.count();

        // 开始查询列表信息
        int firstResultNum = pageUtil.getStartSizeNum(PaginationContext.getPageNum(), PaginationContext.getPageSize());
        List<ProcessDefinition> definitionList = processDefinitionQuery
                .orderByProcessDefinitionKey()
                .asc()
                .listPage(firstResultNum, PaginationContext.getPageSize());

        // 封装返回分页信息
        List<WorkFlowLoadTemplate> loadTemplateList = new ArrayList<>();
        if (ObjectUtil.isNotEmpty(definitionList)) {
            loadTemplateList = definitionList.stream().map(definition -> {
                WorkFlowLoadTemplate camundaLoadTemplate = new WorkFlowLoadTemplate();
                camundaLoadTemplate.setId(definition.getDeploymentId());
                camundaLoadTemplate.setTemplateKey(definition.getKey());
                // 通过key获取流程定义名称
                WorkFlowProductEnum productEnum = workFlowUtil.getProductEnumByTemplateId(definition.getKey());
                if (ObjectUtil.isNotNull(productEnum)) {
                    camundaLoadTemplate.setTemplateName(productEnum.getBizTypeName());
                } else {
                    camundaLoadTemplate.setTemplateName(definition.getName());
                }
                camundaLoadTemplate.setVersion(definition.getVersion());
                // 通过deploymentId获取deployment部署时间信息
                String deploymentId = definition.getDeploymentId();
                Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId)
                        .singleResult();
                if (ObjectUtil.isNotNull(deployment)) {
                    camundaLoadTemplate.setCreateTime(DateUtil.format(deployment.getDeploymentTime(),
                            DatePattern.NORM_DATETIME_PATTERN));
                }
                return camundaLoadTemplate;
            }).collect(Collectors.toList());
        }

        // 进行分页设置
        return pageUtil.setCountFlowListPage(loadTemplateList,
                PaginationContext.getPageNum(),
                PaginationContext.getPageSize(),
                (int) totalCount);
    }

    /**
     * 获取流程模板XML
     *
     * @param workFlowLoadTemplateDTO 参数dto
     * @return
     */
    @Override
    public void getLoadTemplateXML(WorkFlowLoadTemplateDTO workFlowLoadTemplateDTO) throws IOException {
        // 获取流程定义查询query
        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey(workFlowLoadTemplateDTO.getTemplateKey());
        if (ObjectUtil.isNotNull(workFlowLoadTemplateDTO.getVersion())) {
            processDefinitionQuery.processDefinitionVersion(workFlowLoadTemplateDTO.getVersion());
        } else {
            processDefinitionQuery.latestVersion();
        }

        // 获取流程定义信息
        ProcessDefinition processDefinition = processDefinitionQuery.singleResult();

        // 通过流程定义信息获取流程XML信息
        if (ObjectUtil.isNotNull(processDefinition)) {
            String deploymentId = processDefinition.getDeploymentId();
            String resourceName = processDefinition.getResourceName();
            // 获取流程定义信息
            Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId)
                    .singleResult();
            if (ObjectUtil.isNotNull(deployment)) {
                // 获取流程定义信息
                InputStream inputStream = repositoryService.getResourceAsStream(deploymentId, resourceName);

                // 开始开始进行下载
                response.setContentType(WorkFlowServerConstant.APPLICATION_XML);
                response.setHeader(WorkFlowServerConstant.CONTENT_DISPOSITION, "attachment;filename=\"" + workFlowLoadTemplateDTO.getTemplateKey() + "\"");
                try {
                    IOUtils.copy(inputStream, response.getOutputStream());
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    IOUtils.closeQuietly(inputStream);
                    response.flushBuffer();
                }
            }
        }
    }

    /**
     * 获取流程模板XML字符串
     *
     * @param workFlowLoadTemplateDTO 参数dto
     * @return
     */
    @Override
    public String getLoadTemplateXMLStr(WorkFlowLoadTemplateDTO workFlowLoadTemplateDTO) throws IOException {
        // 获取流程定义查询query
        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey(workFlowLoadTemplateDTO.getTemplateKey());
        if (ObjectUtil.isNotNull(workFlowLoadTemplateDTO.getVersion())) {
            processDefinitionQuery.processDefinitionVersion(workFlowLoadTemplateDTO.getVersion());
        } else {
            processDefinitionQuery.latestVersion();
        }

        // 获取流程定义信息
        ProcessDefinition processDefinition = processDefinitionQuery.singleResult();

        // 通过流程定义信息获取流程XML信息
        if (ObjectUtil.isNotNull(processDefinition)) {
            String deploymentId = processDefinition.getDeploymentId();
            String resourceName = processDefinition.getResourceName();
            // 获取流程定义信息
            Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId)
                    .singleResult();
            if (ObjectUtil.isNotNull(deployment)) {
                // 获取流程定义信息
                InputStream inputStream = repositoryService.getResourceAsStream(deploymentId, resourceName);
                // 通过inputStream获取流程模板的xml字符串信息进行返回
                StringBuilder stringBuilder = new StringBuilder();
                try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream,
                        StandardCharsets.UTF_8))) {
                    String line;
                    while ((line = reader.readLine()) != null) {
                        // 注意:\n用于保持换行,根据需要可调整
                        stringBuilder.append(line).append("\n");
                    }
                }
                return stringBuilder.toString();
            }
        }
        return null;
    }

    /**
     * 获取流程模板图片
     *
     * @param workFlowLoadTemplateDTO 参数dto
     * @return
     */
    @Override
    public void getLoadTemplatePIC(WorkFlowLoadTemplateDTO workFlowLoadTemplateDTO) throws IOException {
        // 获取流程model列表信息
        List<Model> modelList = repositoryService.createModelQuery()
                .modelKey(workFlowLoadTemplateDTO.getTemplateKey())
                .orderByCreateTime()
                .desc()
                .latestVersion()
                .list();

        // 空值判断
        if (ObjectUtil.isNotEmpty(modelList)) {
            // 获取第一个model信息
            Model model = modelList.get(0);
            // 获取二进制流信息
            byte[] modelEditorSourceExtra = repositoryService.getModelEditorSourceExtra(model.getId());
            if (ObjectUtil.isNotNull(modelEditorSourceExtra)) {
                // 开始开始进行下载
                response.setCharacterEncoding(StandardCharsets.ISO_8859_1.displayName());
                response.setContentType(WorkFlowServerConstant.IMAGE_PNG);
                response.setHeader(WorkFlowServerConstant.CONTENT_DISPOSITION, "attachment;filename=\"" + workFlowLoadTemplateDTO.getTemplateKey() + "\"");
                try {
                    IOUtils.copy(new ByteArrayInputStream(modelEditorSourceExtra), response.getOutputStream());
                } catch(IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
相关推荐
张某布响丸辣4 分钟前
SQL中的时间类型:深入解析与应用
java·数据库·sql·mysql·oracle
喜欢打篮球的普通人9 分钟前
rust模式和匹配
java·算法·rust
java小吕布23 分钟前
Java中的排序算法:探索与比较
java·后端·算法·排序算法
慢生活的人。28 分钟前
SpringSecurity+jwt+captcha登录认证授权总结
java·认证·rbac·权限·验证
向阳12181 小时前
LeetCode40:组合总和II
java·算法·leetcode
云空1 小时前
《InsCode AI IDE:编程新时代的引领者》
java·javascript·c++·ide·人工智能·python·php
慧都小妮子1 小时前
Spire.PDF for .NET【页面设置】演示:复制 PDF 文档中的页面
java·pdf·.net
Dr_eamboat1 小时前
【Java】枚举类映射
java·开发语言·python
李少兄1 小时前
解决 Spring Boot 中 `Ambiguous mapping. Cannot map ‘xxxController‘ method` 错误
java·spring boot·后端
matrixlzp1 小时前
Java 责任链模式 减少 if else 实战案例
java·设计模式