/**
 * Copyright &copy; 2021-2026 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
 */
package com.jeeplus.flowable.service;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.jeeplus.common.TokenProvider;
import com.jeeplus.common.utils.Collections3;
import com.jeeplus.flowable.common.cmd.BackUserTaskCmd;
import com.jeeplus.flowable.constant.FlowableConstant;
import com.jeeplus.flowable.mapper.FlowMapper;
import com.jeeplus.flowable.model.ActRuTaskInfo;
import com.jeeplus.flowable.model.CwWorkClientBaseDtoTest;
import com.jeeplus.flowable.model.Flow;
import com.jeeplus.flowable.model.TaskComment;
import com.jeeplus.flowable.service.converter.json.FlowModelService;
import com.jeeplus.flowable.utils.FlowableUtils;
import com.jeeplus.flowable.utils.ProcessDefCache;
import com.jeeplus.flowable.vo.*;
import com.jeeplus.sys.feign.ITenantApi;
import com.jeeplus.sys.feign.IUserApi;
import com.jeeplus.sys.service.dto.UserDTO;
import liquibase.pro.packaged.S;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.constants.BpmnXMLConstants;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.FlowNode;
import org.flowable.bpmn.model.Process;
import org.flowable.editor.language.json.converter.util.CollectionUtils;
import org.flowable.engine.*;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.history.HistoricProcessInstanceQuery;
import org.flowable.engine.runtime.ActivityInstance;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.DelegationState;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.task.api.history.HistoricTaskInstanceQuery;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.flowable.task.service.impl.persistence.entity.TaskEntityImpl;
import org.flowable.variable.api.history.HistoricVariableInstanceQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 流程定义相关Service
 *
 * @author jeeplus
 * @version 2021-09-03
 */
@Slf4j
@Service
@Transactional
public class FlowTaskService {

    @Autowired
    private FlowMapper flowMapper;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private FormService formService;
    @Autowired
    private HistoryService historyService;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private IdentityService identityService;
    @Autowired
    private FlowModelService flowModelService;
    @Autowired
    private ManagementService managementService;
    @Autowired
    private FlowProcessService flowProcessService;
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private IUserApi userApi;
    @Autowired
    private ITenantApi tenantApi;

    /**
     * 获取流转历史任务列表
     *
     * @param procInsId 流程实例
     */
    public Map historicTaskList2(String procInsId) throws Exception {
        List<Flow> actList = Lists.newArrayList ();
        List<HistoricActivityInstance> list = Lists.newArrayList ();
        List<HistoricActivityInstance> historicActivityInstances2 = historyService.createHistoricActivityInstanceQuery ().processInstanceId (procInsId)
                .orderByHistoricActivityInstanceStartTime ().asc ().orderByHistoricActivityInstanceEndTime ().asc ().list ();
        for (HistoricActivityInstance historicActivityInstance : historicActivityInstances2) {
            if (historicActivityInstance.getEndTime () != null) {
                list.add (historicActivityInstance);
            }
        }

        for (HistoricActivityInstance historicActivityInstance : historicActivityInstances2) {
            if (historicActivityInstance.getEndTime () == null) {
                list.add (historicActivityInstance);
            }
        }

        for (int i = 0; i < list.size (); i++) {
            HistoricActivityInstance histIns = list.get (i);
            // 只显示开始节点和结束节点，并且执行人不为空的任务
            if (StrUtil.isNotBlank (histIns.getAssignee ())
                    && historyService.createHistoricTaskInstanceQuery ().taskId (histIns.getTaskId ()).count () != 0
                    || BpmnXMLConstants.ELEMENT_TASK_USER.equals (histIns.getActivityType ()) && histIns.getEndTime () == null
                    || BpmnXMLConstants.ELEMENT_EVENT_START.equals (histIns.getActivityType ())
                    || BpmnXMLConstants.ELEMENT_EVENT_END.equals (histIns.getActivityType ())) {
                // 获取流程发起人名称
                Flow e = queryTaskState (histIns);

                actList.add (e);
            }
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
        Map data = new HashMap();
        for (Flow flow : actList) {
            HistoricActivityInstance histIns = flow.getHistIns();
            if(StringUtils.isNotBlank(histIns.getActivityName())){

                switch (histIns.getActivityName()){
                    case "开始":
                        if(StringUtils.isNotBlank(flow.getAssigneeName())){
                            data.put("firstAuditName",flow.getAssigneeName());
                            data.put("giveName",flow.getAssigneeName());
                        }else{
                            data.put("firstAuditName","");
                        }
                        if(null != histIns.getEndTime()){
                            data.put("firstAuditDate",sdf.format(histIns.getEndTime()));
                        }else{
                            data.put("firstAuditDate","    年  月  日");
                        }
                        break;
                    case "二级复核":
                        if(null != flow.getComment() && "success".equals(flow.getComment().getLevel())){
                            if(StringUtils.isNotBlank(flow.getAssigneeName())){
                                data.put("secondAuditName",flow.getAssigneeName());
                            }else{
                                data.put("secondAuditName","");
                            }
                            if(null != histIns.getEndTime()){
                                data.put("secondAuditDate",sdf.format(histIns.getEndTime()));
                            }else{
                                data.put("secondAuditDate","    年  月  日");
                            }
                        }
                        break;
                    case "三级复核":
                        if(null != flow.getComment() && "success".equals(flow.getComment().getLevel())){
                            if(StringUtils.isNotBlank(flow.getAssigneeName())){
                                UserDTO userDTO = SpringUtil.getBean ( IUserApi.class ).getByLoginNameNotTenantId("潘中");
                                if(null != userDTO && StringUtils.isNotBlank(userDTO.getName())){
                                    data.put("thirdlyAuditName",userDTO.getName());
                                }else{
                                    data.put("thirdlyAuditName","");
                                }
                            }else{
                                data.put("thirdlyAuditName","");
                            }
                            if(null != histIns.getEndTime()){
                                data.put("thirdlyAuditDate",sdf.format(histIns.getEndTime()));
                            }else{
                                data.put("thirdlyAuditDate","    年  月  日");
                            }
                        }
                        break;
                }
            }
        }

        return data;
    }

    /**
     * 获取流转历史任务列表
     *
     * @param procInsId 流程实例
     */
    public Map historicTaskList3(String procInsId) throws Exception {
        List<Flow> actList = Lists.newArrayList ();
        List<HistoricActivityInstance> list = Lists.newArrayList ();
        List<HistoricActivityInstance> historicActivityInstances2 = historyService.createHistoricActivityInstanceQuery ().processInstanceId (procInsId)
                .orderByHistoricActivityInstanceStartTime ().asc ().orderByHistoricActivityInstanceEndTime ().asc ().list ();
        for (HistoricActivityInstance historicActivityInstance : historicActivityInstances2) {
            if (historicActivityInstance.getEndTime () != null) {
                list.add (historicActivityInstance);
            }
        }

        for (HistoricActivityInstance historicActivityInstance : historicActivityInstances2) {
            if (historicActivityInstance.getEndTime () == null) {
                list.add (historicActivityInstance);
            }
        }

        for (int i = 0; i < list.size (); i++) {
            HistoricActivityInstance histIns = list.get (i);
            // 只显示开始节点和结束节点，并且执行人不为空的任务
            if (StrUtil.isNotBlank (histIns.getAssignee ())
                    && historyService.createHistoricTaskInstanceQuery ().taskId (histIns.getTaskId ()).count () != 0
                    || BpmnXMLConstants.ELEMENT_TASK_USER.equals (histIns.getActivityType ()) && histIns.getEndTime () == null
                    || BpmnXMLConstants.ELEMENT_EVENT_START.equals (histIns.getActivityType ())
                    || BpmnXMLConstants.ELEMENT_EVENT_END.equals (histIns.getActivityType ())) {
                // 获取流程发起人名称
                Flow e = queryTaskState (histIns);

                actList.add (e);
            }
        }
        Map data = new HashMap();

        for (Flow flow : actList) {
            HistoricActivityInstance histIns = flow.getHistIns();
            if(StringUtils.isNotBlank(histIns.getActivityName())){

                switch (histIns.getActivityName()){
                    case "归档员审核":
                        if(null != flow.getComment() && "success".equals(flow.getComment().getLevel())){
                            if(StringUtils.isNotBlank(flow.getAssigneeName())){
                                data.put("archiveName",flow.getAssigneeName());
                            }else{
                                data.put("archiveName","");
                            }
                        }
                        break;
                }
            }
        }

        return data;
    }

    public String taskDispose(String data,String currentToken) {
        List<CwWorkClientBaseDtoTest> list = JSON.parseObject(data, new TypeReference<List<CwWorkClientBaseDtoTest>>() {});
//        String currentToken = TokenProvider.getCurrentToken();
        String userId = SpringUtil.getBean ( IUserApi.class ).getByToken (currentToken).getId ();
        // =============== 已经签收或者等待签收的任务  ===============
        TaskQuery todoTaskQuery = taskService.createTaskQuery ().taskCandidateOrAssigned (userId).active ()
                .includeProcessVariables ().orderByTaskCreateTime ().desc ();

        List <Task> todoList = todoTaskQuery.list ( );

        Method procInsIdMethod = null;
        Method processDefinitionIdMethod = null;
        Method statusMethod = null;
        for (CwWorkClientBaseDtoTest info : list ) {
            Class<? extends Object> tClass = info.getClass();
            //得到所有属性
            Field[] fields = tClass.getDeclaredFields();
            Class<? extends Object> superClass = tClass.getSuperclass();
            //得到所有属性
            Field[] superField = superClass.getDeclaredFields();
            Field[] field = concat(fields,superField);

            for (Task taskInfo : todoList) {
                Integer taskIdInteger = null;
                try {
                    for (Integer i=0; i<field.length; i++ ){
                        //获取属性的名字
                        String name = field[i].getName();
                        //将属性名字的首字母大写
                        name = name.replaceFirst(name.substring(0, 1), name.substring(0, 1).toUpperCase());

                        if("ProcInsId".equals(name)){
                            field[i].setAccessible(true);
                            //整合出 getId() 属性这个方法
                            procInsIdMethod = tClass.getMethod("get"+name);

                        }else if("ProcessDefinitionId".equals(name)){
                            field[i].setAccessible(true);
                            //整合出 getId() 属性这个方法
                            processDefinitionIdMethod = tClass.getMethod("get"+name);

                        }else if("Status".equals(name)){
                            field[i].setAccessible(true);
                            //整合出 getId() 属性这个方法
                            statusMethod = tClass.getMethod("get"+name);

                        }else if("TaskId".equals(name)){
                            field[i].setAccessible(true);
                            //整合出 getId() 属性这个方法
                            taskIdInteger = i;

                        }
                    }

                    //调用这个整合出来的get方法，强转成自己需要的类型
                    String procInsId = (String)procInsIdMethod.invoke(info);
                    String processDefinitionId = (String)processDefinitionIdMethod.invoke(info);
                    String status = (String)statusMethod.invoke(info);

                    if(procInsId.equals(taskInfo.getProcessInstanceId()) && processDefinitionId.equals(taskInfo.getProcessDefinitionId()) && "4".equals(status)){
                        field[taskIdInteger].set(info,taskInfo.getId());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return JSON.toJSONString(list);
    }

    /**
     * 数据整合方法
     * @param a
     * @param b
     * @return
     */
    static Field[] concat(Field[] a, Field[] b) {

        Field[] c= new Field[a.length+b.length];
        System.arraycopy(a, 0, c, 0, a.length);
        System.arraycopy(b, 0, c, a.length, b.length);
        return c;
    }

    public String getTaskIdByprocInstId(String procInsId){
        return flowMapper.getTaskIdByprocInstId(procInsId);
    }

    /**
     * 获取待办任务列表
     *
     * @return
     */
    public Page <ProcessVo> todoList(Page <ProcessVo> page, Flow flow) {
        List <HashMap <String, String>> result = new ArrayList <HashMap <String, String>> ( );
        String userId = userApi.getByToken ( TokenProvider.getCurrentToken ( ) ).getId ( );//ObjectUtils.toString(UserUtils.getUser().getId());
        // =============== 已经签收或者等待签收的任务  ===============
        TaskQuery todoTaskQuery = taskService.createTaskQuery ( ).taskCandidateOrAssigned ( userId ).active ( )
                .includeProcessVariables ( ).orderByTaskCreateTime ( ).desc ( );

        // 设置查询条件
        if ( StrUtil.isNotBlank ( flow.getProcDefKey ( ) ) ) {
            todoTaskQuery.processDefinitionKey ( flow.getProcDefKey ( ) );
        }
        if ( flow.getBeginDate ( ) != null ) {
            todoTaskQuery.taskCreatedAfter ( flow.getBeginDate ( ) );
        }
        if ( flow.getEndDate ( ) != null ) {
            todoTaskQuery.taskCreatedBefore ( flow.getEndDate ( ) );
        }
        if (StrUtil.isNotBlank (flow.getTitle ())) {
            todoTaskQuery.processVariableValueLike ( FlowableConstant.TITLE, "%" + flow.getTitle () + "%");
        }
        if (StringUtils.isNotEmpty(flow.getAssigneeId())) {
            todoTaskQuery.processVariableValueLike ( FlowableConstant.USERNAME,"%"+ flow.getAssigneeId()+"%");
        }


        long total = todoTaskQuery.count ( );
        page.setTotal ( total );

        List <Task> todoList;
        // 查询列表
        if ( page.getSize ( ) == -1 ) {//不分页
            todoList = todoTaskQuery.list ( );
        } else {
            int start = (int) ((page.getCurrent ( ) - 1) * page.getSize ( ));
            int size = (int) (page.getSize ( ));
            todoList = todoTaskQuery.listPage ( start, size );
        }
        List records = Lists.newArrayList ( );
        for (Task task : todoList) {
            Process process = SpringUtil.getBean ( RepositoryService.class ).getBpmnModel ( task.getProcessDefinitionId ( ) ).getMainProcess ( );
            ProcessVo processVo = new ProcessVo ( );
            TaskVo taskVo = new TaskVo ( task );
            taskVo.setProcessDefKey ( process.getId ( ) );
            processVo.setTask ( taskVo );
            processVo.setVars ( task.getProcessVariables ( ) );
            processVo.setProcessDefinitionName ( ProcessDefCache.get ( task.getProcessDefinitionId ( ) ).getName ( ) );
            processVo.setVersion ( ProcessDefCache.get ( task.getProcessDefinitionId ( ) ).getVersion ( ) );
            processVo.setStatus ( "todo" );
            records.add ( processVo );
        }
        page.setRecords ( records );
        return page;
    }

    /**
     * 获取已办任务列表
     *
     * @param page
     * @return
     */
    public Page <HisTaskVo> historicList(Page <HisTaskVo> page, Flow act) {
        String userId = userApi.getByToken ( TokenProvider.getCurrentToken ( ) ).getId ( );

        HistoricTaskInstanceQuery histTaskQuery = historyService.createHistoricTaskInstanceQuery ( ).taskAssignee ( userId ).finished ( )
                .includeProcessVariables ( ).orderByHistoricTaskInstanceEndTime ( ).desc ( );

        // 设置查询条件
        if ( StrUtil.isNotBlank ( act.getProcDefKey ( ) ) ) {
            histTaskQuery.processDefinitionKey ( act.getProcDefKey ( ) );
        }
        if ( act.getBeginDate ( ) != null ) {
            histTaskQuery.taskCompletedAfter ( act.getBeginDate ( ) );
        }
        if ( act.getEndDate ( ) != null ) {
            histTaskQuery.taskCompletedBefore ( act.getEndDate ( ) );
        }
        if ( act.getTitle ( ) != null ) {
            histTaskQuery.processVariableValueLike ( FlowableConstant.TITLE, "%" + act.getTitle ( ) + "%" );
        }
        if (StringUtils.isNotEmpty(act.getAssigneeId())) {
            histTaskQuery.processVariableValueLike (FlowableConstant.USERNAME,"%"+ act.getAssigneeId()+"%");
        }
        // 查询总数
        page.setTotal ( histTaskQuery.count ( ) );
        // 查询列表
        List <HistoricTaskInstance> histList;
        if ( page.getSize ( ) == -1 ) {
            histList = histTaskQuery.list ( );
        } else {
            int start = (int) ((page.getCurrent ( ) - 1) * page.getSize ( ));
            int size = (int) (page.getSize ( ));
            histList = histTaskQuery.listPage ( start, size );
        }

        List records = Lists.newArrayList ( );
        for (HistoricTaskInstance histTask : histList) {
            HisTaskVo hisTaskVo = new HisTaskVo ( histTask );
            hisTaskVo.setProcessDefinitionName ( ProcessDefCache.get ( histTask.getProcessDefinitionId ( ) ).getName ( ) );
            hisTaskVo.setBack ( isBack ( histTask ) );
            List <Task> currentTaskList = taskService.createTaskQuery ( ).processInstanceId ( histTask.getProcessInstanceId ( ) ).list ( );
            if ( ((List) currentTaskList).size ( ) > 0 ) {
                TaskVo currentTaskVo = new TaskVo ( currentTaskList.get ( 0 ) );
                hisTaskVo.setCurrentTask ( currentTaskVo );
            }


            // 获取意见评论内容

            List <TaskComment> commentList = this.getTaskComments ( histTask.getId ( ) );
            if ( commentList.size ( ) > 0 ) {
                TaskComment comment = commentList.get ( commentList.size ( ) - 1 );
                hisTaskVo.setComment ( comment.getMessage ( ) );
                hisTaskVo.setLevel ( comment.getLevel ( ) );
                hisTaskVo.setType ( comment.getType ( ) );
                hisTaskVo.setStatus ( comment.getStatus ( ) );

            }
            records.add ( hisTaskVo );
        }
        page.setRecords ( records );
        return page;
    }

    /**
     * 获取流转历史任务列表
     *
     * @param procInsId 流程实例
     */
    public List <Flow> historicTaskList(String procInsId) throws Exception {
        List <Flow> actList = Lists.newArrayList ( );
        List <HistoricActivityInstance> list = Lists.newArrayList ( );
        List <HistoricActivityInstance> historicActivityInstances2 = historyService.createHistoricActivityInstanceQuery ( ).processInstanceId ( procInsId )
                .orderByHistoricActivityInstanceStartTime ( ).asc ( ).orderByHistoricActivityInstanceEndTime ( ).asc ( ).list ( );
        for (HistoricActivityInstance historicActivityInstance : historicActivityInstances2) {
            if ( historicActivityInstance.getEndTime ( ) != null ) {
                list.add ( historicActivityInstance );
            }
        }

        for (HistoricActivityInstance historicActivityInstance : historicActivityInstances2) {
            if ( historicActivityInstance.getEndTime ( ) == null ) {
                list.add ( historicActivityInstance );
            }
        }

        for (int i = 0; i < list.size ( ); i++) {
            HistoricActivityInstance histIns = list.get ( i );
            // 只显示开始节点和结束节点，并且执行人不为空的任务
            if ( StrUtil.isNotBlank ( histIns.getAssignee ( ) )
                    && historyService.createHistoricTaskInstanceQuery ( ).taskId ( histIns.getTaskId ( ) ).count ( ) != 0
                    || BpmnXMLConstants.ELEMENT_TASK_USER.equals ( histIns.getActivityType ( ) ) && histIns.getEndTime ( ) == null
                    || BpmnXMLConstants.ELEMENT_EVENT_START.equals ( histIns.getActivityType ( ) )
                    || BpmnXMLConstants.ELEMENT_EVENT_END.equals ( histIns.getActivityType ( ) ) ) {
                // 获取流程发起人名称
                Flow e = queryTaskState ( histIns );

                actList.add ( e );
            }
        }
        return actList;
    }

    /**
     * 获取流程表单（首先获取任务节点表单KEY，如果没有则取流程开始节点表单KEY）
     *
     * @return
     */
    public String getFormKey(String procDefId, String taskDefKey) {
        String formKey = "";
        if ( StrUtil.isNotBlank ( procDefId ) ) {
            if ( StrUtil.isNotBlank ( taskDefKey ) ) {
                try {
                    formKey = formService.getTaskFormKey ( procDefId, taskDefKey );
                } catch (Exception e) {
                    formKey = "";
                }
            }
            if ( StrUtil.isBlank ( formKey ) ) {
                formKey = formService.getStartFormKey ( procDefId );
            }
            if ( StrUtil.isBlank ( formKey ) ) {
                formKey = "/404";
            }
        }
        log.debug ( "getFormKey: {}", formKey );
        return formKey;
    }

    /**
     * 获取正在运行的流程实例对象
     *
     * @param procInsId
     * @return
     */
    public ProcessInstance getProcIns(String procInsId) {
        return runtimeService.createProcessInstanceQuery ( ).processInstanceId ( procInsId ).singleResult ( );
    }

    /**
     * 获取已经结束流程实例对象
     *
     * @param procInsId
     * @return
     */
    public HistoricProcessInstance getFinishedProcIns(String procInsId) {
        return historyService.createHistoricProcessInstanceQuery ( ).processInstanceId ( procInsId ).singleResult ( );
    }


    /**
     * 获取我发起的流程申请列表
     *
     * @param user
     * @return
     */
    public Page <ProcessVo> getMyStartedProcIns(UserDTO user, Page <ProcessVo> page, Flow flow) throws Exception {
        HistoricProcessInstanceQuery query = historyService.createHistoricProcessInstanceQuery ( ).startedBy ( user.getId ( ) ).includeProcessVariables ( ).orderByProcessInstanceStartTime ( ).desc ( );
        if ( flow.getBeginDate ( ) != null ) {
            query.startedAfter ( flow.getBeginDate ( ) );
        }
        if ( flow.getEndDate ( ) != null ) {
            query.startedBefore ( flow.getEndDate ( ) );
        }
        if ( StrUtil.isNotBlank ( flow.getTitle ( ) ) ) {
            query.variableValueLike ( FlowableConstant.TITLE, "%" + flow.getTitle ( ) + "%" );
        }

        page.setTotal ( query.count ( ) );
        List <HistoricProcessInstance> histList;
        if ( page.getSize ( ) == -1 ) {//不分页
            histList = query.list ( );
        } else {
            int start = (int) ((page.getCurrent ( ) - 1) * page.getSize ( ));
            int size = (int) (page.getSize ( ));
            histList = query.involvedUser ( user.getId ( ) ).listPage ( start, size );
        }
        List records = Lists.newArrayList ( );
        for (HistoricProcessInstance historicProcessInstance : histList) {
            ProcessVo processVo = flowProcessService.queryProcessState ( historicProcessInstance.getProcessDefinitionId ( ), historicProcessInstance.getId ( ) );
            processVo.setEndTime ( historicProcessInstance.getEndTime ( ) );
            processVo.setStartTime ( historicProcessInstance.getStartTime ( ) );
            processVo.setProcessDefinitionId ( historicProcessInstance.getProcessDefinitionId ( ) );
            processVo.setProcessInstanceId ( historicProcessInstance.getId ( ) );
            processVo.setVars ( historicProcessInstance.getProcessVariables ( ) );
            processVo.setProcessDefinitionName ( historicProcessInstance.getProcessDefinitionName ( ) );
            processVo.setVersion ( historicProcessInstance.getProcessDefinitionVersion ( ) );
            records.add ( processVo );
        }
        page.setRecords ( records );

        return page;
    }


    /**
     * 启动流程
     *
     * @param procDefKey    流程定义KEY
     * @param businessTable 业务表表名
     * @param businessId    业务表编号
     * @param title         流程标题，显示在待办任务标题
     * @param recordType    项目类型
     * @return 流程实例ID
     */
    public String startProcess(String procDefKey, String businessTable, String businessId, String title,String recordType, String procDefId) {
        Map <String, Object> vars = Maps.newHashMap ( );
        return startProcess ( procDefKey, businessTable, businessId, title,  vars ,recordType, procDefId);
    }

    /**
     * 启动流程
     *
     * @param procDefKey    流程定义KEY
     * @param businessTable 业务表表名
     * @param businessId    业务表编号
     * @param title         流程标题，显示在待办任务标题
     * @param vars          流程变量
     * @return 流程实例ID
     */
    @SuppressWarnings("unused")
    public String startProcess(String procDefKey, String businessTable, String businessId, String title, Map <String, Object> vars,String recordType,  String procDefId) {
        //String userId = UserUtils.getUser().getLoginName();//ObjectUtils.toString(UserUtils.getUser().getId())
        // 设置流程变量
        if ( vars == null ) {
            vars = Maps.newHashMap ( );
        }

        String userId = (String) vars.get ( FlowableConstant.INITIATOR );
        if ( userId == null ) {
            userId = userApi.getByToken ( TokenProvider.getCurrentToken ( ) ).getId ( );
        }
        String userName = userApi.getById ( userId ).getName ( );
        vars.put ( FlowableConstant.USERNAME, userName );

        // 用来设置启动流程的人员ID，引擎会自动把用户ID保存到activiti:initiator中
        identityService.setAuthenticatedUserId ( userId );

        // 设置流程标题
        if ( StrUtil.isNotBlank ( title ) ) {
            vars.put ( FlowableConstant.TITLE, title );
        }
        //设置项目类型
        if (StrUtil.isNotBlank(recordType)){
            vars.put(FlowableConstant.RECORDTYPE,recordType);
        }


        // 启动流程
        ProcessInstance procIns = runtimeService.startProcessInstanceByKeyAndTenantId ( procDefKey, businessTable + ":" + businessId, vars, /*tenantApi.getCurrentTenantId ( )*/ flowMapper.getTenantIdByProcDefKey(procDefKey) );

        // 更新业务表流程实例ID
        Flow act = new Flow ( );
        act.setBusinessTable ( businessTable );// 业务表名
        act.setBusinessId ( businessId );  // 业务表ID
        act.setProcInsId ( procIns.getId ( ) );
        act.setProcDefId(procDefId);
        act.setVars ( vars );
        flowMapper.updateProcInsIdByBusinessId ( act );
        return act.getProcInsId ( );
    }


    /**
     * 删除任务
     *
     * @param taskId       任务ID
     * @param deleteReason 删除原因
     */
    public void deleteTask(String taskId, String deleteReason) {
        taskService.deleteTask ( taskId, deleteReason );
    }

    /**
     * 签收任务
     *
     * @param taskId 任务ID
     * @param userId 签收用户ID（用户登录名）
     */
    public void claim(String taskId, String userId) {
        taskService.claim ( taskId, userId );
    }


    /**
     * 提交任务, 并保存意见
     *
     * @param vars 任务变量
     */
    public void complete(Flow flow, Map <String, Object> vars) {
        // 添加意见
        if ( StrUtil.isNotBlank ( flow.getProcInsId ( ) ) ) {
            taskService.addComment ( flow.getTaskId ( ), flow.getProcInsId ( ), flow.getComment ( ).getCommentType ( ), flow.getComment ( ).getFullMessage ( ) );
        }

        // 设置流程变量
        if ( vars == null ) {
            vars = Maps.newHashMap ( );
        }

        // 设置流程标题
        if ( StrUtil.isNotBlank ( flow.getTitle ( ) ) ) {
            vars.put ( FlowableConstant.TITLE, flow.getTitle ( ) );
        }


        Task task = taskService.createTaskQuery ( ).taskId ( flow.getTaskId ( ) ).singleResult ( );

        Object agree = vars.get("agree");
        Boolean flagAgree = null;
        if(null != agree && StringUtils.isNotBlank(String.valueOf(agree))){
            flagAgree = (Boolean) agree;
        }
        if(null != flagAgree){
            if(flagAgree){
                flowProcessService.rejectProcessInstanceById (task.getProcessInstanceId (), ProcessStatus.AGREE, flow.getComment ().getMessage ());
            }else{
                flowProcessService.rejectProcessInstanceById (task.getProcessInstanceId (), ProcessStatus.REJECT, flow.getComment ().getMessage ());
            }
        }

        // owner不为空说明可能存在委托任务
        if ( StrUtil.isNotBlank ( task.getOwner ( ) ) ) {
            DelegationState delegationState = task.getDelegationState ( );
            switch (delegationState) {
                case PENDING:
                    taskService.resolveTask ( flow.getTaskId ( ) );
                    taskService.complete ( flow.getTaskId ( ), vars );
                    break;

                case RESOLVED:
                    // 委托任务已经完成
                    break;

                default:
                    // 不是委托任务
                    taskService.complete ( flow.getTaskId ( ), vars );
                    break;
            }
        } else if ( StrUtil.isBlank ( task.getAssignee ( ) ) ) { // 未签收任务
            // 签收任务
            taskService.claim ( flow.getTaskId ( ), userApi.getByToken ( TokenProvider.getCurrentToken ( ) ).getId ( ) );
            // 提交任务
            taskService.complete ( flow.getTaskId ( ), vars );
        } else {
            // 提交任务
            taskService.complete ( flow.getTaskId ( ), vars );
        }
    }


    /**
     * 查询任务节点的状态
     */
    public Flow queryTaskState(HistoricActivityInstance histIns) {
        Flow e = new Flow ( );
        e.setHistIns ( histIns );
        // 获取流程发起人名称
        if ( BpmnXMLConstants.ELEMENT_EVENT_START.equals ( histIns.getActivityType ( ) ) ) {
            List <HistoricProcessInstance> il = historyService.createHistoricProcessInstanceQuery ( ).processInstanceId ( histIns.getProcessInstanceId ( ) ).orderByProcessInstanceStartTime ( ).asc ( ).list ( );
            if ( il.size ( ) > 0 ) {
                if ( StrUtil.isNotBlank ( il.get ( 0 ).getStartUserId ( ) ) ) {
                    UserDTO user = userApi.getById ( il.get ( 0 ).getStartUserId ( ) );
                    if ( user != null ) {
                        e.setAssignee ( histIns.getAssignee ( ) );
                        e.setAssigneeName ( user.getName ( ) );
                        e.setAssigneeId ( user.getId ( ) );
                    }
                }
            }
            TaskComment taskComment = new TaskComment ( );
            taskComment.setStatus ( FlowableConstant.START_EVENT_LABEL );
            taskComment.setMessage ( FlowableConstant.START_EVENT_COMMENT );
            e.setComment ( taskComment );
            return e;
        }
        if ( BpmnXMLConstants.ELEMENT_EVENT_END.equals ( histIns.getActivityType ( ) ) ) {
            TaskComment taskComment = new TaskComment ( );
            taskComment.setStatus ( FlowableConstant.END_EVENT_LABEL );
            taskComment.setMessage ( FlowableConstant.END_EVENT_COMMENT );
            e.setAssigneeName ( FlowableConstant.SYSTEM_EVENT_COMMENT );
            e.setComment ( taskComment );
            return e;
        }
        // 获取任务执行人名称
        if ( StrUtil.isNotEmpty ( histIns.getAssignee ( ) ) ) {
            UserDTO user = userApi.getFlowAbleById ( histIns.getAssignee ( ) );
            if ( user != null ) {
                e.setAssignee ( histIns.getAssignee ( ) );
                e.setAssigneeName ( user.getName ( ) );
                e.setAssigneeId ( user.getId ( ) );
            }
        }
        // 获取意见评论内容
        if ( StrUtil.isNotBlank ( histIns.getTaskId ( ) ) ) {
            List <TaskComment> commentList = this.getTaskComments ( histIns.getTaskId ( ) );
            HistoricVariableInstanceQuery action = historyService.createHistoricVariableInstanceQuery ( ).processInstanceId ( histIns.getProcessInstanceId ( ) ).taskId ( histIns.getTaskId ( ) ).variableName ( "_flow_button_name" );
            if ( commentList.size ( ) > 0 ) {
                TaskComment comment = commentList.get ( commentList.size ( ) - 1 );
                e.setComment ( comment );
            } else {
                e.setComment ( new TaskComment ( ) );
            }
        }
        //等待执行的任务
        if ( histIns.getEndTime ( ) == null ) {
            List assignList = Lists.newArrayList ( );
            taskService.getIdentityLinksForTask ( histIns.getTaskId ( ) ).forEach ( identityLink -> {
                assignList.add ( userApi.getById ( identityLink.getUserId ( ) ) );
            } );
            String assignName = Collections3.extractToString ( assignList, "name", "," );
            TaskComment taskComment = new TaskComment ( );
            taskComment.setStatus ( ActionType.WAITING.getStatus ( ) );
//            taskComment.setMessage (FlowableConstant.WAITING_EVENT_COMMENT);
            e.setComment ( taskComment );
            e.setAssigneeName ( assignName );
        }
        return e;
    }


    public List <TaskComment> getTaskComments(String taskId) {
        return jdbcTemplate.query ( "select * from ACT_HI_COMMENT where TYPE_ like '" + TaskComment.prefix + "%' and TASK_ID_ = '" + taskId + "' order by TIME_ desc", new RowMapper <TaskComment> ( ) {
            @Override
            public TaskComment mapRow(ResultSet rs, int rowNum) throws SQLException {
                TaskComment taskComment = new TaskComment ( );
                taskComment.setCommentType ( rs.getString ( "TYPE_" ) );
                taskComment.setFullMessage ( new String ( rs.getBytes ( "FULL_MSG_" ) ) );
                return taskComment;
            }
        } );
    }


    public Map getDiagram(String processId) {
        Map m = new HashMap ( );
        try {
            String processDefId = "";
            ProcessInstance pi = runtimeService.createProcessInstanceQuery ( ).processInstanceId ( processId ).singleResult ( );
            //流程走完的不显示图
            if ( pi == null ) {
                processDefId = historyService.createHistoricProcessInstanceQuery ( ).processInstanceId ( processId ).singleResult ( ).getProcessDefinitionId ( );
            } else {
                processDefId = pi.getProcessDefinitionId ( );
            }
            BpmnModel bpmnModel = repositoryService.getBpmnModel ( processDefId );
            List <HistoricActivityInstance> historyProcess = getHistoryProcess ( processId );
            Set <String> activityIds = new LinkedHashSet <> ( );
            List <String> flows = new ArrayList <> ( );
            for (HistoricActivityInstance hi : historyProcess) {
                String activityType = hi.getActivityType ( );
                if ( activityType.equals ( BpmnXMLConstants.ELEMENT_SEQUENCE_FLOW ) || activityType.equals ( BpmnXMLConstants.ELEMENT_GATEWAY_EXCLUSIVE ) ) {
                    flows.add ( hi.getActivityId ( ) );
                } else if ( StrUtil.isNotBlank ( hi.getAssignee ( ) )
                        && historyService.createHistoricTaskInstanceQuery ( ).taskId ( hi.getTaskId ( ) ).count ( ) != 0
                        || BpmnXMLConstants.ELEMENT_TASK_USER.equals ( hi.getActivityType ( ) ) && hi.getEndTime ( ) == null
                        || BpmnXMLConstants.ELEMENT_EVENT_START.equals ( hi.getActivityType ( ) )
                        || BpmnXMLConstants.ELEMENT_EVENT_END.equals ( hi.getActivityType ( ) ) ) {
                    activityIds.add ( hi.getActivityId ( ) );
                }
            }
            List <Task> tasks = taskService.createTaskQuery ( ).processInstanceId ( processId ).list ( );
            for (Task task : tasks) {
                activityIds.remove ( task.getTaskDefinitionKey ( ) );
                activityIds.add ( task.getTaskDefinitionKey ( ) );
            }
            byte[] bpmnBytes = flowModelService.getBpmnXML ( bpmnModel );
            m.put ( "bpmnXml", new String ( bpmnBytes ) );
            m.put ( "flows", flows );
            m.put ( "activityIds", activityIds );
            return m;
        } catch (Exception e) {
            e.printStackTrace ( );
        }
        return null;
    }


    /**
     * 任务历史
     *
     * @param processId 部署id
     */
    public List <HistoricActivityInstance> getHistoryProcess(String processId) {
        List <HistoricActivityInstance> list = historyService // 历史相关Service
                .createHistoricActivityInstanceQuery ( ) // 创建历史活动实例查询
                .processInstanceId ( processId ) // 执行流程实例id
                .finished ( ).orderByHistoricActivityInstanceEndTime ( ).asc ( )
                .list ( );
        return list;
    }


    /**
     * 保存审核意见
     *
     * @param flow
     */
    public void auditSave(Flow flow, Map vars) {
        complete ( flow, vars );

    }


    /**
     * 是否可以取回任务
     */
    public boolean isBack(HistoricTaskInstance hisTask) {
        ProcessInstance pi = runtimeService.createProcessInstanceQuery ( )
                .processInstanceId ( hisTask.getProcessInstanceId ( ) ).singleResult ( );
        if ( pi != null ) {
            if ( pi.isSuspended ( ) ) {
                return false;
            } else {
                Task currentTask = taskService.createTaskQuery ( ).processInstanceId ( hisTask.getProcessInstanceId ( ) ).list ( ).get ( 0 );
                HistoricTaskInstance lastHisTask = historyService.createHistoricTaskInstanceQuery ( ).processInstanceId ( hisTask.getProcessInstanceId ( ) ).finished ( )
                        .includeProcessVariables ( ).orderByHistoricTaskInstanceEndTime ( ).desc ( ).list ( ).get ( 0 );

                if ( currentTask.getClaimTime ( ) != null ) {//用户已签收
                    return false;
                }
                if ( hisTask.getId ( ).equals ( lastHisTask.getId ( ) ) ) {
                    return true;
                }
                return false;
            }

        } else {
            return false;
        }
    }

    /*
     * 驳回任务
     */
    public String backTask(String backTaskDefKey, String taskId, TaskComment comment) {
        Task task = taskService.createTaskQuery ( ).taskId ( taskId ).singleResult ( );
        if ( StrUtil.isBlank ( task.getAssignee ( ) ) ) {
            taskService.claim ( taskId, userApi.getByToken ( TokenProvider.getCurrentToken ( ) ).getId ( ) );
        }

        // 退回发起者处理,退回到发起者,默认设置任务执行人为发起者
        ActivityInstance targetRealActivityInstance = runtimeService.createActivityInstanceQuery ( ).processInstanceId ( task.getProcessInstanceId ( ) ).activityId ( backTaskDefKey ).list ( ).get ( 0 );
        if ( targetRealActivityInstance.getActivityType ( ).equals ( BpmnXMLConstants.ELEMENT_EVENT_START ) ) {
            flowProcessService.stopProcessInstanceById ( task.getProcessInstanceId ( ), ProcessStatus.REJECT, comment.getMessage ( ) );
        } else {
            taskService.addComment ( taskId, task.getProcessInstanceId ( ), comment.getCommentType ( ), comment.getFullMessage ( ) );
            managementService.executeCommand ( new BackUserTaskCmd ( runtimeService,
                    taskId, backTaskDefKey ) );
        }

        return task.getProcessInstanceId ( );
    }


    /**
     * 获取可驳回节点
     *
     * @param taskId
     * @return
     */
    public List <Flow> getBackNodes(String taskId) {
        Task taskEntity = taskService.createTaskQuery ( ).taskId ( taskId ).singleResult ( );
        String processInstanceId = taskEntity.getProcessInstanceId ( );
        String currActId = taskEntity.getTaskDefinitionKey ( );
        String processDefinitionId = taskEntity.getProcessDefinitionId ( );
        Process process = repositoryService.getBpmnModel ( processDefinitionId ).getMainProcess ( );
        FlowNode currentFlowElement = (FlowNode) process.getFlowElement ( currActId, true );
        List <ActivityInstance> activitys =
                runtimeService.createActivityInstanceQuery ( ).processInstanceId ( processInstanceId ).finished ( ).orderByActivityInstanceStartTime ( ).asc ( ).list ( );
        List <String> activityIds =
                activitys.stream ( ).filter ( activity -> activity.getActivityType ( ).equals ( BpmnXMLConstants.ELEMENT_TASK_USER ) || activity.getActivityType ( ).equals ( BpmnXMLConstants.ELEMENT_EVENT_START ) ).filter ( activity -> !activity.getActivityId ( ).equals ( currActId ) ).map ( ActivityInstance::getActivityId ).distinct ( ).collect ( Collectors.toList ( ) );
        List <Flow> result = new ArrayList <> ( );
        for (String activityId : activityIds) {
            FlowNode toBackFlowElement = (FlowNode) process.getFlowElement ( activityId, true );
            if ( FlowableUtils.isReachable ( process, toBackFlowElement, currentFlowElement ) ) {
                Flow vo = new Flow ( );
                vo.setTaskDefKey ( activityId );
                vo.setTaskName ( toBackFlowElement.getName ( ) );
                vo.setTaskId ( activityId );
                result.add ( vo );
            }
        }
        return result;
    }

    public void addSignTask(String taskId, List <String> userIds, String comment, Boolean flag) throws Exception {
        TaskEntityImpl taskEntity = (TaskEntityImpl) taskService.createTaskQuery ( ).taskId ( taskId ).singleResult ( );
        //1.把当前的节点设置为空
        if ( taskEntity != null ) {
            //如果是加签再加签
            String parentTaskId = taskEntity.getParentTaskId ( );
            if ( org.apache.commons.lang.StringUtils.isBlank ( parentTaskId ) ) {
                taskEntity.setOwner ( userApi.getByToken ( TokenProvider.getCurrentToken ( ) ).getId ( ) );
                taskEntity.setAssignee ( null );
                taskEntity.setCountEnabled ( true );
                if ( flag ) {
                    taskEntity.setScopeType ( FlowableConstant.AFTER_ADDSIGN );
                } else {
                    taskEntity.setScopeType ( FlowableConstant.BEFORE_ADDSIGN );
                }
                //1.2 设置任务为空执行者
                taskService.saveTask ( taskEntity );
            }
            //2.添加加签数据
            this.createSignSubTasks ( userIds, taskEntity );
            //3.添加审批意见
            String type = flag ? ActionType.ADD_AFTER_MULTI_INSTANCE.toString ( ) : ActionType.ADD_BEFORE_MULTI_INSTANCE.toString ( );
            taskService.addComment ( taskId, taskEntity.getProcessInstanceId ( ), type, comment );
        } else {
            throw new Exception ( "不存在任务实例，请确认!" );
        }
    }

    /**
     * 创建加签子任务
     *
     * @param userIds    加签参数
     * @param taskEntity 父任务
     */
    private void createSignSubTasks(List <String> userIds, TaskEntity taskEntity) {
        if ( CollectionUtils.isNotEmpty ( userIds ) ) {
            String parentTaskId = taskEntity.getParentTaskId ( );
            if ( org.apache.commons.lang.StringUtils.isBlank ( parentTaskId ) ) {
                parentTaskId = taskEntity.getId ( );
            }
            String finalParentTaskId = parentTaskId;
            //1.创建被加签人的任务列表
            userIds.forEach ( userCode -> {
                if ( StrUtil.isNotBlank ( userCode ) ) {
                    this.createSubTask ( taskEntity, finalParentTaskId, userCode );
                }
            } );
            String taskId = taskEntity.getId ( );
            if ( org.apache.commons.lang.StringUtils.isBlank ( taskEntity.getParentTaskId ( ) ) ) {
                //2.创建加签人的任务并执行完毕
                Task task = this.createSubTask ( taskEntity, finalParentTaskId, userApi.getByToken ( TokenProvider.getCurrentToken ( ) ).getId ( ) );
                taskId = task.getId ( );
            }
            Task taskInfo = taskService.createTaskQuery ( ).taskId ( taskId ).singleResult ( );
            if ( null != taskInfo ) {
                taskService.complete ( taskId );
            }
            //如果是候选人，需要删除运行时候选表种的数据。
            long candidateCount = taskService.createTaskQuery ( ).taskId ( parentTaskId ).taskCandidateUser ( userApi.getByToken ( TokenProvider.getCurrentToken ( ) ).getId ( ) ).count ( );
            if ( candidateCount > 0 ) {
                taskService.deleteCandidateUser ( parentTaskId, userApi.getByToken ( TokenProvider.getCurrentToken ( ) ).getId ( ) );
            }
        }
    }

    /**
     * 创建子任务
     *
     * @param ptask    创建子任务
     * @param assignee 子任务的执行人
     * @return
     */
    protected TaskEntity createSubTask(TaskEntity ptask, String ptaskId, String assignee) {
        TaskEntity task = null;
        if ( ptask != null ) {
            //1.生成子任务
            task = (TaskEntity) taskService.newTask ( UUID.randomUUID ( ).toString ( ) );
            task.setCategory ( ptask.getCategory ( ) );
            task.setDescription ( ptask.getDescription ( ) );
            task.setTenantId ( ptask.getTenantId ( ) );
            task.setAssignee ( assignee );
            task.setName ( ptask.getName ( ) );
            task.setParentTaskId ( ptaskId );
            task.setProcessDefinitionId ( ptask.getProcessDefinitionId ( ) );
            task.setProcessInstanceId ( ptask.getProcessInstanceId ( ) );
            task.setTaskDefinitionKey ( ptask.getTaskDefinitionKey ( ) );
            task.setTaskDefinitionId ( ptask.getTaskDefinitionId ( ) );
            task.setPriority ( ptask.getPriority ( ) );
            task.setCreateTime ( new Date ( ) );
            taskService.saveTask ( task );
        }
        return task;
    }

    /**
     * 获取当前节点审核人id信息集合
     * @param taskId
     * @return
     */
    public List<String> getTaskAuditUsers(String taskId) {
        List<String> assignList = Lists.newArrayList ();
        //获取当前节点审核人id信息集合
        taskService.getIdentityLinksForTask ( taskId ).forEach ( identityLink -> {
            assignList.add ( identityLink.getUserId () );
        } );
        return assignList;
    }

    /**
     * 获取当前节点信息
     * @param processInstanceId
     * @return
     */
    public FlowNode getCurrentTask(String processInstanceId){
        //当前任务信息
        Task task =taskService.createTaskQuery().processInstanceId(processInstanceId).active().singleResult();

        if(task!=null) {
            //获取流程发布Id信息
            String definitionId = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult().getProcessDefinitionId();
            //获取bpm对象
            BpmnModel bpmnModel = SpringUtil.getBean (RepositoryService.class).getBpmnModel(definitionId);
            //传节点定义key 获取当前节点
            FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(task.getTaskDefinitionKey());
            return flowNode;
        }else{
            return null;
        }

    }

    /**
     * 获取当前节点名称
     * @param processInstanceId
     * @return
     */
    public String getCurrentTaskName(String processInstanceId){
        FlowNode currentTask = getCurrentTask(processInstanceId);
        if (Objects.nonNull(currentTask)) {
            return currentTask.getName();
        }
        return "";
    }

    /**
     * 审核通过或驳回
     * @param procInsId
     * @param flag “yes”通过  “no”驳回
     * @param assignee 设置下一步处理人
     * @param comm 审核意见
     */
    public void auditByProcInsIdAndFlag(String procInsId,String flag,String assignee,String comm) throws Exception {
        // 获取审核操作需要的参数
        List<Flow> flows = this.historicTaskList(procInsId);
        Flow flow = flows.get(flows.size() - 1);
        Flow saveParam = new Flow();
        HistoricActivityInstance histIns = flow.getHistIns();
        saveParam.setTaskId(histIns.getTaskId());
        saveParam.setTaskDefKey(histIns.getActivityId());
        saveParam.setProcInsId(histIns.getProcessInstanceId());
        saveParam.setProcDefId(histIns.getProcessDefinitionId());
        Map<String, Object> vars = Maps.newHashMap();
        TaskComment comment = new TaskComment();
        comment.setMessage(comm);
        if ("yes".equals(flag)) {
            vars.put("agree", true); // 审核通过
            comment.setType(ActionType.AGREE.getType());
            comment.setStatus(ActionType.AGREE.getStatus());
        } else {
            vars.put("agree", false); // 审核驳回
            comment.setType(ActionType.REJECT.getType());
            comment.setStatus(ActionType.REJECT.getStatus());
        }
        saveParam.setComment(comment);
        this.auditSave(saveParam, vars); // 流程审核操作
        //指定下一步处理人
        if(StringUtils.isNotBlank(assignee)){
            Task task = taskService.createTaskQuery().processInstanceId(procInsId).active().singleResult();
            if(task != null){
                taskService.setAssignee(task.getId(), assignee);
            }
        }
    }

    /**
     * 检查是否为最后一个审核节点
     * @param processInstanceId
     * @return
     */
    public boolean checkIsLastTask(String processInstanceId) {
        Task task = taskService.createTaskQuery().processInstanceId(processInstanceId).active().singleResult();
        // task为null则审核节点为最后一个审核节点
        if (Objects.nonNull(task)) {
            return false;
        } else {
            // 当前审核节点为最后节点
            return true;
        }
    }

    /**
     * 根据taskId查询流程信息
     * @param taskId
     * @return
     */
    public ActRuTaskInfo getTaskInfoByTaskId(String taskId){
        return flowMapper.getTaskInfoByTaskId(taskId);
    }

    public String getActNameByDefId(String procDefId) {
        return flowMapper.getActNameByDefId(procDefId);
    }
}
