package org.jeecg.modules.flowable.service.impl;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.*;
import org.flowable.common.engine.api.FlowableException;
import org.flowable.common.engine.api.FlowableObjectNotFoundException;
import org.flowable.engine.ProcessEngineConfiguration;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.history.HistoricProcessInstanceQuery;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.task.Comment;
import org.flowable.identitylink.api.IdentityLinkType;
import org.flowable.identitylink.api.history.HistoricIdentityLink;
import org.flowable.image.ProcessDiagramGenerator;
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.variable.api.history.HistoricVariableInstance;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.SpringContextUtils;
import org.jeecg.modules.flowable.apithird.business.entity.FlowForm;
import org.jeecg.modules.flowable.apithird.business.entity.FlowMyBusiness;
import org.jeecg.modules.flowable.apithird.business.service.IFlowFormService;
import org.jeecg.modules.flowable.apithird.business.service.ISysDeployFormService;
import org.jeecg.modules.flowable.apithird.business.service.impl.FlowMyBusinessServiceImpl;
import org.jeecg.modules.flowable.apithird.entity.ActStatus;
import org.jeecg.modules.flowable.apithird.entity.SysUser;
import org.jeecg.modules.flowable.apithird.service.FlowCallBackServiceI;
import org.jeecg.modules.flowable.apithird.service.IFlowThirdService;
import org.jeecg.modules.flowable.common.constant.ProcessConstants;
import org.jeecg.modules.flowable.common.enums.FlowComment;
import org.jeecg.modules.flowable.common.exception.CustomException;
import org.jeecg.modules.flowable.domain.dto.FlowCommentDto;
import org.jeecg.modules.flowable.domain.dto.FlowNextDto;
import org.jeecg.modules.flowable.domain.dto.FlowTaskDto;
import org.jeecg.modules.flowable.domain.dto.FlowViewerDto;
import org.jeecg.modules.flowable.domain.vo.FlowTaskVo;
import org.jeecg.modules.flowable.factory.FlowServiceFactory;
import org.jeecg.modules.flowable.flow.CustomProcessDiagramGenerator;
import org.jeecg.modules.flowable.flow.FindNextNodeUtil;
import org.jeecg.modules.flowable.flow.FlowableUtils;
import org.jeecg.modules.flowable.service.IFlowTaskService;
import org.jeecg.modules.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 **/
@Service
@Slf4j
@Transactional
public class FlowTaskServiceImpl extends FlowServiceFactory implements IFlowTaskService {

    @Autowired
    private IFlowThirdService iFlowThirdService;
    @Autowired
    FlowMyBusinessServiceImpl flowMyBusinessService;
    @Autowired
    private ISysDeployFormService sysInstanceFormService;
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private IFlowFormService flowFormService;
    @Autowired
    private ISysDeployFormService sysDeployFormService;

    /**
     * 完成任务
     *
     * @param taskVo 请求实体参数
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result complete(FlowTaskVo taskVo) {

        Task task = taskService.createTaskQuery().taskId(taskVo.getTaskId()).singleResult();
        if (Objects.isNull(task)) {
            return Result.error("任务不存在");
        }
        if (DelegationState.PENDING.equals(task.getDelegationState())) {
            taskService.addComment(taskVo.getTaskId(), taskVo.getInstanceId(), FlowComment.DELEGATE.getType(), taskVo.getComment());
            taskService.resolveTask(taskVo.getTaskId(), taskVo.getValues());
            //taskService.setAssignee(taskVo.getTaskId(),"e9ca23d68d884d4ebb19d07889727dae");
        } else {
            taskService.addComment(taskVo.getTaskId(), taskVo.getInstanceId(), FlowComment.NORMAL.getType(), taskVo.getComment());
            //Long userId = SecurityUtils.getLoginUser().getUser().getUserId();
            SysUser loginUser = iFlowThirdService.getLoginUser();

            taskService.complete(taskVo.getTaskId(), taskVo.getValues());

            Object userTypeObject = taskVo.getValues().get("approvalType");
            if(userTypeObject!=null) {
                Task nextTask = taskService.createTaskQuery()
                        .processInstanceId(taskVo.getInstanceId())
                        .singleResult();
                if(nextTask!=null){
                    String userType = userTypeObject.toString();
                    String approvalId = taskVo.getValues().get("approval").toString();
                    if(userType.equals("user")) {
                        taskService.setAssignee(nextTask.getId(), approvalId);
                    } else {
                        taskService.addCandidateGroup(nextTask.getId(),approvalId);
                    }
                }

            }
        }

        //判断是否是最后一个节点
        Task endnextTask = taskService.createTaskQuery()
                .processInstanceId(taskVo.getInstanceId())
                .singleResult();
        if(endnextTask==null){

            // 获取流程变量
            Map<String, Object> formValues = getProcessVariables(taskVo.getTaskId());

            String zdmc = Optional.ofNullable(formValues)
                    .map(map -> map.get("dataName"))
                    .map(Object::toString) // 安全转换为String
                    .orElse(null);

            String zdval = Optional.ofNullable(formValues)
                    .map(map -> map.get("dataId"))
                    .map(Object::toString) // 安全转换为String
                    .orElse(null);

            // 通过流程定义ID查询流程定义对象
            ProcessDefinition processDefinition = repositoryService
                    .createProcessDefinitionQuery()
                    .processDefinitionId(task.getProcessDefinitionId()) // 替换为你的流程定义ID
                    .singleResult();

            if (processDefinition != null) {
                // 从流程定义对象中获取部署ID
                String DeployId = processDefinition.getDeploymentId();
                FlowForm flowForm=sysDeployFormService.selectSysDeployFormByDeployId(DeployId);

                if(flowForm!=null){

                    String tabname= flowForm.getFormTableName();
                    if(tabname!=null&&!tabname.equals("")&&zdmc!=null&&!zdmc.equals("")&&zdval!=null&&!zdval.equals("")){
                        String formContent=zdmc+"="+zdval;
                        FlowForm flowFormben=new FlowForm();
                        flowFormben.setFormTableName(tabname);
                        flowFormben.setFormContent(formContent);
                        flowFormben.setFormTp("3");
                        flowFormben.setFormUrl(DeployId);
                        sysDeployFormService.updateBisTabBpmStatus(flowFormben);
                    }
                }


            }


        }


        return Result.OK();

        /**
         Task task = taskService.createTaskQuery().taskId(taskVo.getTaskId()).singleResult();
         if (Objects.isNull(task)){
         return Result.error("任务不存在");
         }
         SysUser loginUser = iFlowThirdService.getLoginUser();
         if (DelegationState.PENDING.equals(task.getDelegationState())) {
         taskService.addComment(taskVo.getTaskId(), taskVo.getInstanceId(), FlowComment.DELEGATE.getType(), taskVo.getComment());
         //taskService.resolveTask(taskVo.getTaskId(), taskVo.getValues());
         } else {
         taskService.addComment(taskVo.getTaskId(), taskVo.getInstanceId(), FlowComment.NORMAL.getType(), taskVo.getComment());
         taskService.setAssignee(taskVo.getTaskId(), loginUser.getUsername());
         //taskService.complete(taskVo.getTaskId(), taskVo.getValues());
         }
         */
        /*======================审批通过  回调以及关键数据保存======================*/
        /**
         //业务数据id
         String dataId = taskVo.getDataId();
         //如果保存数据前未调用必调的FlowCommonService.initActBusiness方法，就会有问题
         FlowMyBusiness business = flowMyBusinessService.getByDataId(dataId);
         //spring容器类名
         String serviceImplName = business.getServiceImplName();
         FlowCallBackServiceI flowCallBackService = (FlowCallBackServiceI) SpringContextUtils.getBean(serviceImplName);
         // 流程变量
         Map<String, Object> flowBeforeParamsValues = flowCallBackService.flowValuesOfTask(business.getTaskNameId(),taskVo.getValues());

         //设置数据
         Map<String, Object> values = taskVo.getValues();
         if (MapUtil.isNotEmpty(flowBeforeParamsValues)){
         //    业务层有设置变量，使用业务层的变量
         values = flowBeforeParamsValues;
         }
         FlowNextDto nextFlowNode = this.getNextFlowNode(task.getId(), values);
         //下一个实例节点
         if (DelegationState.PENDING.equals(task.getDelegationState())) {
         taskService.resolveTask(taskVo.getTaskId(), values);
         } else {
         taskService.complete(taskVo.getTaskId(), values);
         }
         List<Task> task2List = taskService.createTaskQuery().processInstanceId(business.getProcessInstanceId()).active().list();
         Task task2 = null;
         if (CollUtil.isNotEmpty(task2List)){
         task2 = task2List.get(0);
         }

         // 下个节点候选人
         List<String> beforeParamsCandidateUsernames = Lists.newArrayList();
         if(task2!=null){
         beforeParamsCandidateUsernames = flowCallBackService.flowCandidateUsernamesOfTask(task2.getTaskDefinitionKey(),taskVo.getValues());
         }
         List<String> candidateUsers = taskVo.getCandidateUsers();
         if (CollUtil.isNotEmpty(candidateUsers)){
         //    前端传入候选人 覆盖
         beforeParamsCandidateUsernames = candidateUsers;
         }
         String doneUsers = business.getDoneUsers();
         // 处理过流程的人
         JSONArray doneUserList = new JSONArray();
         if (StrUtil.isNotBlank(doneUsers)){
         doneUserList = JSON.parseArray(doneUsers);
         }
         if (!doneUserList.contains(loginUser.getUsername())){
         doneUserList.add(loginUser.getUsername());
         }

         if (task2!=null && task.getTaskDefinitionKey().equals(task2.getTaskDefinitionKey())){
         //    * 当前节点是会签节点，没有走完
         business.setActStatus(ActStatus.doing)
         .setTaskId(task2.getId())
         .setDoneUsers(doneUserList.toJSONString())
         ;
         String todoUsersStr = business.getTodoUsers();
         JSONArray todosArr = JSON.parseArray(todoUsersStr);
         // 删除后重写
         for (Task task2One : task2List) {
         for (Object oldUser : todosArr) {
         taskService.deleteCandidateUser(task2One.getId(),oldUser.toString());
         }
         }
         // 重写
         if (CollUtil.isNotEmpty(beforeParamsCandidateUsernames)){
         beforeParamsCandidateUsernames.remove(loginUser.getUsername());
         // 业务层有指定候选人，覆盖
         for (Task task2One : task2List) {
         for (String newUser : beforeParamsCandidateUsernames) {
         taskService.addCandidateUser(task2One.getId(),newUser);
         }
         }
         business.setTodoUsers(JSON.toJSONString(beforeParamsCandidateUsernames));
         } else {
         todosArr.remove(loginUser.getUsername());
         for (Task task2One : task2List) {
         for (Object oldUser : todosArr) {
         taskService.addCandidateUser(task2One.getId(),oldUser.toString());
         }
         }
         business.setTodoUsers(todosArr.toJSONString());
         }


         } else {
         //    * 下一节点是会签节点 或 普通用户节点，逻辑一致
         if (nextFlowNode!=null){
         //**有下一个节点
         UserTask nextTask = nextFlowNode.getUserTask();
         //能够处理下个节点的候选人
         List<SysUser> nextFlowNodeUserList = nextFlowNode.getUserList();
         List<String> collect_username = nextFlowNodeUserList.stream().map(SysUser::getUsername).collect(Collectors.toList());
         if (CollUtil.isNotEmpty(candidateUsers)){
         //    前端传入候选人
         collect_username = candidateUsers;
         }
         business.setActStatus(ActStatus.doing)
         .setTaskId(task2.getId())
         .setTaskNameId(nextTask.getId())
         .setTaskName(nextTask.getName())
         .setPriority(nextTask.getPriority())
         .setDoneUsers(doneUserList.toJSONString())
         .setTodoUsers(JSON.toJSONString(collect_username))
         ;
         // 删除后重写
         for (Task task2One : task2List) {
         for (String oldUser : collect_username) {
         taskService.deleteCandidateUser(task2One.getId(),oldUser);
         }
         }
         if (CollUtil.isEmpty(candidateUsers)&&CollUtil.isNotEmpty(beforeParamsCandidateUsernames)){
         // 前端没有传入候选人 && 业务层有指定候选人，覆盖
         for (Task task2One : task2List) {
         for (String newUser : beforeParamsCandidateUsernames) {
         taskService.addCandidateUser(task2One.getId(),newUser);
         }
         }
         business.setTodoUsers(JSON.toJSONString(beforeParamsCandidateUsernames));
         } else {
         for (Task task2One : task2List) {
         for (String oldUser : collect_username) {
         taskService.addCandidateUser(task2One.getId(),oldUser);
         }
         }
         }

         } else {
         //    **没有下一个节点，流程已经结束了
         business.setActStatus(ActStatus.pass)
         .setDoneUsers(doneUserList.toJSONString())
         .setTodoUsers("")
         .setTaskId("")
         .setTaskNameId("")
         .setTaskName("")
         ;
         }
         }

         flowMyBusinessService.updateById(business);
         // 流程处理完后，进行回调业务层
         business.setValues(values);
         if (flowCallBackService!=null)flowCallBackService.afterFlowHandle(business);
         return Result.OK();
         */
    }
    @Override
    public Result completeByDateId(FlowTaskVo flowTaskVo){
        //如果保存数据前未调用必调的FlowCommonService.initActBusiness方法，就会有问题
        FlowMyBusiness business = flowMyBusinessService.getByDataId(flowTaskVo.getDataId());
        flowTaskVo.setTaskId(business.getTaskId());
        flowTaskVo.setInstanceId(business.getProcessInstanceId());
        return this.complete(flowTaskVo);
    }
    @Override
    public void taskRejectByDataId(FlowTaskVo flowTaskVo){
        FlowMyBusiness business = flowMyBusinessService.getByDataId(flowTaskVo.getDataId());
        flowTaskVo.setTaskId(business.getTaskId());
        this.taskReject(flowTaskVo);
    }
    /**
     * 驳回任务
     *
     * @param flowTaskVo
     */
    @Override
    public void taskReject(FlowTaskVo flowTaskVo) {

        if (taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult().isSuspended()) {
            throw new CustomException("任务处于挂起状态!");
        }
        // 当前任务 task
        Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult();
        // 获取流程定义信息
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
        // 获取所有节点信息
        Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0);
        // 获取全部节点列表，包含子节点
        Collection<FlowElement> allElements = FlowableUtils.getAllElements(process.getFlowElements(), null);
        // 获取当前任务节点元素
        FlowElement source = null;
        if (allElements != null) {
            for (FlowElement flowElement : allElements) {
                // 类型为用户节点
                if (flowElement.getId().equals(task.getTaskDefinitionKey())) {
                    // 获取节点信息
                    source = flowElement;
                }
            }
        }

        // 目的获取所有跳转到的节点 targetIds
        // 获取当前节点的所有父级用户任务节点
        // 深度优先算法思想：延边迭代深入
        List<UserTask> parentUserTaskList = FlowableUtils.iteratorFindParentUserTasks(source, null, null);
        if (parentUserTaskList == null || parentUserTaskList.size() == 0) {
            throw new CustomException("当前节点为初始任务节点，不能驳回");
        }
        // 获取活动 ID 即节点 Key
        List<String> parentUserTaskKeyList = new ArrayList<>();
        parentUserTaskList.forEach(item -> parentUserTaskKeyList.add(item.getId()));
        // 获取全部历史节点活动实例，即已经走过的节点历史，数据采用开始时间升序
        List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery().processInstanceId(task.getProcessInstanceId()).orderByHistoricTaskInstanceStartTime().asc().list();
        // 数据清洗，将回滚导致的脏数据清洗掉
        List<String> lastHistoricTaskInstanceList = FlowableUtils.historicTaskInstanceClean(allElements, historicTaskInstanceList);
        // 此时历史任务实例为倒序，获取最后走的节点
        List<String> targetIds = new ArrayList<>();
        // 循环结束标识，遇到当前目标节点的次数
        int number = 0;
        StringBuilder parentHistoricTaskKey = new StringBuilder();
        for (String historicTaskInstanceKey : lastHistoricTaskInstanceList) {
            // 当会签时候会出现特殊的，连续都是同一个节点历史数据的情况，这种时候跳过
            if (parentHistoricTaskKey.toString().equals(historicTaskInstanceKey)) {
                continue;
            }
            parentHistoricTaskKey = new StringBuilder(historicTaskInstanceKey);
            if (historicTaskInstanceKey.equals(task.getTaskDefinitionKey())) {
                number++;
            }
            // 在数据清洗后，历史节点就是唯一一条从起始到当前节点的历史记录，理论上每个点只会出现一次
            // 在流程中如果出现循环，那么每次循环中间的点也只会出现一次，再出现就是下次循环
            // number == 1，第一次遇到当前节点
            // number == 2，第二次遇到，代表最后一次的循环范围
            if (number == 2) {
                break;
            }
            // 如果当前历史节点，属于父级的节点，说明最后一次经过了这个点，需要退回这个点
            if (parentUserTaskKeyList.contains(historicTaskInstanceKey)) {
                targetIds.add(historicTaskInstanceKey);
            }
        }


        // 目的获取所有需要被跳转的节点 currentIds
        // 取其中一个父级任务，因为后续要么存在公共网关，要么就是串行公共线路
        UserTask oneUserTask = parentUserTaskList.get(0);
        // 获取所有正常进行的任务节点 Key，这些任务不能直接使用，需要找出其中需要撤回的任务
        List<Task> runTaskList = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list();
        List<String> runTaskKeyList = new ArrayList<>();
        runTaskList.forEach(item -> runTaskKeyList.add(item.getTaskDefinitionKey()));
        // 需驳回任务列表
        List<String> currentIds = new ArrayList<>();
        // 通过父级网关的出口连线，结合 runTaskList 比对，获取需要撤回的任务
        List<UserTask> currentUserTaskList = FlowableUtils.iteratorFindChildUserTasks(oneUserTask, runTaskKeyList, null, null);
        currentUserTaskList.forEach(item -> currentIds.add(item.getId()));


        // 规定：并行网关之前节点必须需存在唯一用户任务节点，如果出现多个任务节点，则并行网关节点默认为结束节点，原因为不考虑多对多情况
        if (targetIds.size() > 1 && currentIds.size() > 1) {
            throw new CustomException("任务出现多对多情况，无法撤回");
        }

        // 循环获取那些需要被撤回的节点的ID，用来设置驳回原因
        List<String> currentTaskIds = new ArrayList<>();
        currentIds.forEach(currentId -> runTaskList.forEach(runTask -> {
            if (currentId.equals(runTask.getTaskDefinitionKey())) {
                currentTaskIds.add(runTask.getId());
            }
        }));
        // 设置驳回意见
        currentTaskIds.forEach(item -> taskService.addComment(item, task.getProcessInstanceId(), FlowComment.REJECT.getType(), flowTaskVo.getComment()));

        try {
            // 如果父级任务多于 1 个，说明当前节点不是并行节点，原因为不考虑多对多情况
            if (targetIds.size() > 1) {
                // 1 对 多任务跳转，currentIds 当前节点(1)，targetIds 跳转到的节点(多)
                runtimeService.createChangeActivityStateBuilder()
                        .processInstanceId(task.getProcessInstanceId()).
                        moveSingleActivityIdToActivityIds(currentIds.get(0), targetIds).changeState();
            }
            // 如果父级任务只有一个，因此当前任务可能为网关中的任务
            if (targetIds.size() == 1) {
                // 1 对 1 或 多 对 1 情况，currentIds 当前要跳转的节点列表(1或多)，targetIds.get(0) 跳转到的节点(1)
                runtimeService.createChangeActivityStateBuilder()
                        .processInstanceId(task.getProcessInstanceId())
                        .moveActivityIdsToSingleActivityId(currentIds, targetIds.get(0)).changeState();
            }
        } catch (FlowableObjectNotFoundException e) {
            throw new CustomException("未找到流程实例，流程可能已发生变化");
        } catch (FlowableException e) {
            throw new CustomException("无法取消或开始活动");
        }

        /**
         if (taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult().isSuspended()) {
         throw new CustomException("任务处于挂起状态");
         }
         // 当前任务 task
         Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult();
         // 获取流程定义信息
         ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
         // 获取所有节点信息
         Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0);
         // 获取全部节点列表，包含子节点
         Collection<FlowElement> allElements = FlowableUtils.getAllElements(process.getFlowElements(), null);
         // 获取当前任务节点元素
         FlowElement source = null;
         if (allElements != null) {
         for (FlowElement flowElement : allElements) {
         // 类型为用户节点
         if (flowElement.getId().equals(task.getTaskDefinitionKey())) {
         // 获取节点信息
         source = flowElement;
         }
         }
         }

         // 目的获取所有跳转到的节点 targetIds
         // 获取当前节点的所有父级用户任务节点
         // 深度优先算法思想：延边迭代深入
         List<UserTask> parentUserTaskList = FlowableUtils.iteratorFindParentUserTasks(source, null, null);
         if (parentUserTaskList == null || parentUserTaskList.size() == 0) {
         throw new CustomException("当前节点为初始任务节点，不能驳回");
         }
         // 获取活动 ID 即节点 Key
         List<String> parentUserTaskKeyList = new ArrayList<>();
         parentUserTaskList.forEach(item -> parentUserTaskKeyList.add(item.getId()));
         // 获取全部历史节点活动实例，即已经走过的节点历史，数据采用开始时间升序
         List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery().processInstanceId(task.getProcessInstanceId()).orderByHistoricTaskInstanceStartTime().asc().list();
         // 数据清洗，将回滚导致的脏数据清洗掉
         List<String> lastHistoricTaskInstanceList = FlowableUtils.historicTaskInstanceClean(allElements, historicTaskInstanceList);
         // 此时历史任务实例为倒序，获取最后走的节点
         List<String> targetIds = new ArrayList<>();
         // 循环结束标识，遇到当前目标节点的次数
         int number = 0;
         StringBuilder parentHistoricTaskKey = new StringBuilder();
         for (String historicTaskInstanceKey : lastHistoricTaskInstanceList) {
         // 当会签时候会出现特殊的，连续都是同一个节点历史数据的情况，这种时候跳过
         if (parentHistoricTaskKey.toString().equals(historicTaskInstanceKey)) {
         continue;
         }
         parentHistoricTaskKey = new StringBuilder(historicTaskInstanceKey);
         if (historicTaskInstanceKey.equals(task.getTaskDefinitionKey())) {
         number++;
         }
         // 在数据清洗后，历史节点就是唯一一条从起始到当前节点的历史记录，理论上每个点只会出现一次
         // 在流程中如果出现循环，那么每次循环中间的点也只会出现一次，再出现就是下次循环
         // number == 1，第一次遇到当前节点
         // number == 2，第二次遇到，代表最后一次的循环范围
         if (number == 2) {
         break;
         }
         // 如果当前历史节点，属于父级的节点，说明最后一次经过了这个点，需要退回这个点
         if (parentUserTaskKeyList.contains(historicTaskInstanceKey)) {
         targetIds.add(historicTaskInstanceKey);
         }
         }


         // 目的获取所有需要被跳转的节点 currentIds
         // 取其中一个父级任务，因为后续要么存在公共网关，要么就是串行公共线路
         UserTask oneUserTask = parentUserTaskList.get(0);
         // 获取所有正常进行的任务节点 Key，这些任务不能直接使用，需要找出其中需要撤回的任务
         List<Task> runTaskList = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list();
         List<String> runTaskKeyList = new ArrayList<>();
         runTaskList.forEach(item -> runTaskKeyList.add(item.getTaskDefinitionKey()));
         // 需驳回任务列表
         List<String> currentIds = new ArrayList<>();
         // 通过父级网关的出口连线，结合 runTaskList 比对，获取需要撤回的任务
         List<UserTask> currentUserTaskList = FlowableUtils.iteratorFindChildUserTasks(oneUserTask, runTaskKeyList, null, null);
         currentUserTaskList.forEach(item -> currentIds.add(item.getId()));


         // 规定：并行网关之前节点必须需存在唯一用户任务节点，如果出现多个任务节点，则并行网关节点默认为结束节点，原因为不考虑多对多情况
         if (targetIds.size() > 1 && currentIds.size() > 1) {
         throw new CustomException("任务出现多对多情况，无法撤回");
         }

         // 循环获取那些需要被撤回的节点的ID，用来设置驳回原因
         List<String> currentTaskIds = new ArrayList<>();
         currentIds.forEach(currentId -> runTaskList.forEach(runTask -> {
         if (currentId.equals(runTask.getTaskDefinitionKey())) {
         currentTaskIds.add(runTask.getId());
         }
         }));
         // 设置驳回意见
         currentTaskIds.forEach(item -> taskService.addComment(item, task.getProcessInstanceId(), FlowComment.REJECT.getType(), flowTaskVo.getComment()));
         SysUser loginUser = iFlowThirdService.getLoginUser();
         try {
         // 设置处理人
         taskService.setAssignee(task.getId(), loginUser.getUsername());
         // 如果父级任务多于 1 个，说明当前节点不是并行节点，原因为不考虑多对多情况
         if (targetIds.size() > 1) {
         // 1 对 多任务跳转，currentIds 当前节点(1)，targetIds 跳转到的节点(多)
         runtimeService.createChangeActivityStateBuilder()
         .processInstanceId(task.getProcessInstanceId()).
         moveSingleActivityIdToActivityIds(currentIds.get(0), targetIds).changeState();
         }
         // 如果父级任务只有一个，因此当前任务可能为网关中的任务
         if (targetIds.size() == 1) {
         // 1 对 1 或 多 对 1 情况，currentIds 当前要跳转的节点列表(1或多)，targetIds.get(0) 跳转到的节点(1)
         runtimeService.createChangeActivityStateBuilder()
         .processInstanceId(task.getProcessInstanceId())
         .moveActivityIdsToSingleActivityId(currentIds, targetIds.get(0)).changeState();
         }
         */
        /*======================驳回  回调以及关键数据保存======================*/
        /**
         //业务数据id
         String dataId = flowTaskVo.getDataId();
         if (dataId==null) return;
         //如果保存数据前未调用必调的FlowCommonService.initActBusiness方法，就会有问题
         FlowMyBusiness business = flowMyBusinessService.getByDataId(dataId);
         // 驳回到了上一个节点等待处理
         List<Task> task2List = taskService.createTaskQuery().processInstanceId(business.getProcessInstanceId()).active().list();
         Task task2 = task2List.get(0);
         //spring容器类名
         String serviceImplName = business.getServiceImplName();
         FlowCallBackServiceI flowCallBackService = (FlowCallBackServiceI) SpringContextUtils.getBean(serviceImplName);
         Map<String, Object> values = flowTaskVo.getValues();
         if (values ==null){
         values = MapUtil.newHashMap();
         values.put("dataId",dataId);
         } else {
         values.put("dataId",dataId);
         }
         List<String> beforeParamsCandidateUsernames = flowCallBackService.flowCandidateUsernamesOfTask(task2.getTaskDefinitionKey(), values);
         //设置数据
         String doneUsers = business.getDoneUsers();
         // 处理过流程的人
         JSONArray doneUserList = new JSONArray();
         if (StrUtil.isNotBlank(doneUsers)){
         doneUserList = JSON.parseArray(doneUsers);
         }
         if (!doneUserList.contains(loginUser.getUsername())){
         doneUserList.add(loginUser.getUsername());
         }
         business.setActStatus(ActStatus.reject)
         .setTaskId(task2.getId())
         .setTaskNameId(task2.getTaskDefinitionKey())
         .setTaskName(task2.getName())
         .setDoneUsers(doneUserList.toJSONString())
         ;
         FlowElement targetElement = null;
         if (allElements != null) {
         for (FlowElement flowElement : allElements) {
         // 类型为用户节点
         if (flowElement.getId().equals(task2.getTaskDefinitionKey())) {
         // 获取节点信息
         targetElement = flowElement;
         }
         }
         }

         if (targetElement!=null){
         UserTask targetTask = (UserTask) targetElement;
         business.setPriority(targetTask.getPriority());

         if (StrUtil.equals(business.getTaskNameId(),ProcessConstants.START_NODE)){
         //    开始节点。设置处理人为申请人
         business.setTodoUsers(JSON.toJSONString(Lists.newArrayList(business.getProposer())));
         taskService.setAssignee(business.getTaskId(),business.getProposer());
         } else {
         List<SysUser> sysUserFromTask = getSysUserFromTask(targetTask);
         List<String> collect_username = sysUserFromTask.stream().map(SysUser::getUsername).collect(Collectors.toList());
         // 前端存入的候选人
         List<String> candidateUsers = flowTaskVo.getCandidateUsers();
         if (CollUtil.isNotEmpty(candidateUsers)){
         collect_username = candidateUsers;
         }
         business.setTodoUsers(JSON.toJSONString(collect_username));
         // 删除后重写
         for (Task task2One : task2List) {
         for (String oldUser : collect_username) {
         taskService.deleteCandidateUser(task2One.getId(),oldUser);
         }
         }
         if (CollUtil.isNotEmpty(beforeParamsCandidateUsernames)){
         if (CollUtil.isNotEmpty(candidateUsers)){
         beforeParamsCandidateUsernames = candidateUsers;
         }
         // 业务层有指定候选人，覆盖
         for (Task task2One : task2List) {
         for (String newUser : beforeParamsCandidateUsernames) {
         taskService.addCandidateUser(task2One.getId(), newUser);
         }
         }
         business.setTodoUsers(JSON.toJSONString(beforeParamsCandidateUsernames));
         } else {
         for (Task task2One : task2List) {
         for (String oldUser : collect_username) {
         taskService.addCandidateUser(task2One.getId(), oldUser);
         }
         }
         }
         }
         }

         flowMyBusinessService.updateById(business);
         // 流程处理完后，进行回调业务层
         business.setValues(values);
         if (flowCallBackService!=null) flowCallBackService.afterFlowHandle(business);
         } catch (FlowableObjectNotFoundException e) {
         throw new CustomException("未找到流程实例，流程可能已发生变化");
         } catch (FlowableException e) {
         throw new CustomException("无法取消或开始活动");
         }
         */

    }
    @Override
    public void taskReturnByDataId(FlowTaskVo flowTaskVo){
        //如果保存数据前未调用必调的FlowCommonService.initActBusiness方法，就会有问题
        FlowMyBusiness business = flowMyBusinessService.getByDataId(flowTaskVo.getDataId());
        flowTaskVo.setTaskId(business.getTaskId());
        taskReturn(flowTaskVo);
    }
    /**
     * 退回任务
     *
     * @param flowTaskVo 请求实体参数
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void taskReturn(FlowTaskVo flowTaskVo) {
        if (taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult().isSuspended()) {
            throw new CustomException("任务处于挂起状态");
        }
        // 当前任务 task
        Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult();
        // 获取流程定义信息
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
        // 获取所有节点信息
        Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0);
        // 获取全部节点列表，包含子节点
        Collection<FlowElement> allElements = FlowableUtils.getAllElements(process.getFlowElements(), null);
        // 获取当前任务节点元素
        FlowElement source = null;
        // 获取跳转的节点元素
        FlowElement target = null;
        if (allElements != null) {
            for (FlowElement flowElement : allElements) {
                // 当前任务节点元素
                if (flowElement.getId().equals(task.getTaskDefinitionKey())) {
                    source = flowElement;
                }
                // 跳转的节点元素
                if (flowElement.getId().equals(flowTaskVo.getTargetKey())) {
                    target = flowElement;
                }
            }
        }

        // 从当前节点向前扫描
        // 如果存在路线上不存在目标节点，说明目标节点是在网关上或非同一路线上，不可跳转
        // 否则目标节点相对于当前节点，属于串行
        Boolean isSequential = FlowableUtils.iteratorCheckSequentialReferTarget(source, flowTaskVo.getTargetKey(), null, null);
        if (!isSequential) {
            throw new CustomException("当前节点相对于目标节点，不属于串行关系，无法回退");
        }


        // 获取所有正常进行的任务节点 Key，这些任务不能直接使用，需要找出其中需要撤回的任务
        List<Task> runTaskList = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list();
        List<String> runTaskKeyList = new ArrayList<>();
        runTaskList.forEach(item -> runTaskKeyList.add(item.getTaskDefinitionKey()));
        // 需退回任务列表
        List<String> currentIds = new ArrayList<>();
        // 通过父级网关的出口连线，结合 runTaskList 比对，获取需要撤回的任务
        List<UserTask> currentUserTaskList = FlowableUtils.iteratorFindChildUserTasks(target, runTaskKeyList, null, null);
        currentUserTaskList.forEach(item -> {
            currentIds.add(item.getId());
        });

        // 循环获取那些需要被撤回的节点的ID，用来设置驳回原因
        List<String> currentTaskIds = new ArrayList<>();
        currentIds.forEach(currentId -> runTaskList.forEach(runTask -> {
            if (currentId.equals(runTask.getTaskDefinitionKey())) {
                currentTaskIds.add(runTask.getId());
            }
        }));
        // 设置回退意见
        for (String currentTaskId : currentTaskIds) {
            taskService.addComment(currentTaskId, task.getProcessInstanceId(), FlowComment.REBACK.getType(), flowTaskVo.getComment());
        }
        SysUser loginUser = iFlowThirdService.getLoginUser();
        try {
            // 设置处理人
            taskService.setAssignee(task.getId(), loginUser.getUsername());
            // 1 对 1 或 多 对 1 情况，currentIds 当前要跳转的节点列表(1或多)，targetKey 跳转到的节点(1)
            runtimeService.createChangeActivityStateBuilder()
                    .processInstanceId(task.getProcessInstanceId())
                    .moveActivityIdsToSingleActivityId(currentIds, flowTaskVo.getTargetKey()).changeState();

            /*======================退回  回调以及关键数据保存======================*/
            //业务数据id
            String dataId = flowTaskVo.getDataId();
            if (dataId==null) return;
            //如果保存数据前未调用必调的FlowCommonService.initActBusiness方法，就会有问题
            FlowMyBusiness business = flowMyBusinessService.getByDataId(dataId);
            //spring容器类名
            String serviceImplName = business.getServiceImplName();
            FlowCallBackServiceI flowCallBackService = (FlowCallBackServiceI) SpringContextUtils.getBean(serviceImplName);
            //设置数据
            String doneUsers = business.getDoneUsers();
            // 处理过流程的人
            JSONArray doneUserList = new JSONArray();
            if (StrUtil.isNotBlank(doneUsers)){
                doneUserList = JSON.parseArray(doneUsers);
            }

            if (!doneUserList.contains(loginUser.getUsername())){
                doneUserList.add(loginUser.getUsername());
            }
            //**跳转到目标节点
            List<Task> task2List = taskService.createTaskQuery().processInstanceId(business.getProcessInstanceId()).active().list();
            Task targetTask = task2List.get(0);
            business.setActStatus(ActStatus.reject)
                    .setTaskId(targetTask.getId())
                    .setTaskNameId(targetTask.getTaskDefinitionKey())
                    .setTaskName(targetTask.getName())
                    .setPriority(targetTask.getPriority()+"")
                    .setDoneUsers(doneUserList.toJSONString())
            ;
            if (target!=null){
                UserTask target2 = (UserTask) target;
                business.setPriority(target2.getPriority());
                if (StrUtil.equals(business.getTaskNameId(),ProcessConstants.START_NODE)){
                    //    开始节点。设置处理人为申请人
                    business.setTodoUsers(JSON.toJSONString(Lists.newArrayList(business.getProposer())));
                    taskService.setAssignee(business.getTaskId(),business.getProposer());
                } else {
                    List<SysUser> sysUserFromTask = getSysUserFromTask(target2);
                    List<String> collect_username = sysUserFromTask.stream().map(SysUser::getUsername).collect(Collectors.toList());
                    List<String> candidateUsers = flowTaskVo.getCandidateUsers();
                    if (CollUtil.isNotEmpty(candidateUsers)){
                        collect_username = candidateUsers;
                    }
                    business.setTodoUsers(JSON.toJSONString(collect_username));
                    // 删除后重写
                    for (Task task2One : task2List) {
                        for (String oldUser : collect_username) {
                            taskService.deleteCandidateUser(task2One.getId(),oldUser);
                        }
                    }
                    Map<String, Object> values = flowTaskVo.getValues();
                    if (values==null){
                        values = MapUtil.newHashMap();
                        values.put("dataId",dataId);
                    } else {
                        values.put("dataId",dataId);
                    }
                    List<String> beforeParamsCandidateUsernames = flowCallBackService.flowCandidateUsernamesOfTask(targetTask.getTaskDefinitionKey(), values);
                    if (CollUtil.isNotEmpty(beforeParamsCandidateUsernames)){
                        if (CollUtil.isNotEmpty(candidateUsers)){
                            beforeParamsCandidateUsernames = candidateUsers;
                        }
                        // 业务层有指定候选人，覆盖
                        for (Task task2One : task2List) {
                            for (String newUser : beforeParamsCandidateUsernames) {
                                taskService.addCandidateUser(task2One.getId(),newUser);
                            }
                        }
                        business.setTodoUsers(JSON.toJSONString(beforeParamsCandidateUsernames));
                    } else {
                        for (Task task2One : task2List) {
                            for (String oldUser : collect_username) {
                                taskService.addCandidateUser(task2One.getId(), oldUser);
                            }
                        }
                    }
                }
            }
            flowMyBusinessService.updateById(business);
            // 流程处理完后，进行回调业务层
            business.setValues(flowTaskVo.getValues());
            if (flowCallBackService!=null) flowCallBackService.afterFlowHandle(business);
        } catch (FlowableObjectNotFoundException e) {
            throw new CustomException("未找到流程实例，流程可能已发生变化");
        } catch (FlowableException e) {
            throw new CustomException("无法取消或开始活动");
        }
    }

    @Override
    public Result findReturnTaskListByDataId(FlowTaskVo flowTaskVo) {
        FlowMyBusiness business = flowMyBusinessService.getByDataId(flowTaskVo.getDataId());
        flowTaskVo.setTaskId(business.getTaskId());
        return findReturnTaskList(flowTaskVo);
    }
    /**
     * 获取所有可回退的节点
     *
     * @param flowTaskVo
     * @return
     */
    @Override
    public Result findReturnTaskList(FlowTaskVo flowTaskVo) {
        // 当前任务 task
        Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult();
        // 获取流程定义信息
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
        // 获取所有节点信息，暂不考虑子流程情况
        Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0);
        Collection<FlowElement> flowElements = process.getFlowElements();
        // 获取当前任务节点元素
        UserTask source = null;
        if (flowElements != null) {
            for (FlowElement flowElement : flowElements) {
                // 类型为用户节点
                if (flowElement.getId().equals(task.getTaskDefinitionKey())) {
                    source = (UserTask) flowElement;
                }
            }
        }
        // 获取节点的所有路线
        List<List<UserTask>> roads = FlowableUtils.findRoad(source, null, null, null);
        // 可回退的节点列表
        List<UserTask> userTaskList = new ArrayList<>();
        for (List<UserTask> road : roads) {
            if (userTaskList.size() == 0) {
                // 还没有可回退节点直接添加
                userTaskList = road;
            } else {
                // 如果已有回退节点，则比对取交集部分
                userTaskList.retainAll(road);
            }
        }
        return Result.OK(userTaskList);
    }

    /**
     * 删除任务
     *
     * @param flowTaskVo 请求实体参数
     */
    @Override
    public void deleteTask(FlowTaskVo flowTaskVo) {
        // todo 待确认删除任务是物理删除任务 还是逻辑删除，让这个任务直接通过？
        taskService.deleteTask(flowTaskVo.getTaskId(),flowTaskVo.getComment());
    }

    /**
     * 认领/签收任务
     *
     * @param flowTaskVo 请求实体参数
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void claim(FlowTaskVo flowTaskVo) {
        taskService.claim(flowTaskVo.getTaskId(), flowTaskVo.getUserId());
    }

    /**
     * 取消认领/签收任务
     *
     * @param flowTaskVo 请求实体参数
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void unClaim(FlowTaskVo flowTaskVo) {
        taskService.unclaim(flowTaskVo.getTaskId());
    }

    /**
     * 委派任务
     *
     * @param flowTaskVo 请求实体参数
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delegateTask(FlowTaskVo flowTaskVo) {
        taskService.delegateTask(flowTaskVo.getTaskId(), flowTaskVo.getAssignee());
    }


    /**
     * 转办任务
     *
     * @param flowTaskVo 请求实体参数
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void assignTask(FlowTaskVo flowTaskVo) {
        taskService.setAssignee(flowTaskVo.getTaskId(),flowTaskVo.getComment());
    }

    /**
     * 我发起的流程
     *
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Override
    public Result myProcess(Integer pageNum, Integer pageSize) {
        Page<FlowTaskDto> page = new Page<>();
        String username = iFlowThirdService.getLoginUser().getUsername();
        HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery()
                .startedBy(username)
                .orderByProcessInstanceStartTime()
                .desc();
        List<HistoricProcessInstance> historicProcessInstances = historicProcessInstanceQuery.listPage((pageNum - 1)*pageSize, pageSize);
        page.setTotal(historicProcessInstanceQuery.count());
        List<FlowTaskDto> flowList = new ArrayList<>();
        for (HistoricProcessInstance hisIns : historicProcessInstances) {
            FlowTaskDto flowTask = new FlowTaskDto();
            flowTask.setCreateTime(hisIns.getStartTime());
            flowTask.setFinishTime(hisIns.getEndTime());
            flowTask.setProcInsId(hisIns.getId());

            // 计算耗时
            if (Objects.nonNull(hisIns.getEndTime())) {
                long time = hisIns.getEndTime().getTime() - hisIns.getStartTime().getTime();
                flowTask.setDuration(getDate(time));
            } else {
                long time = System.currentTimeMillis() - hisIns.getStartTime().getTime();
                flowTask.setDuration(getDate(time));
            }
            // 流程定义信息
            ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
                    .processDefinitionId(hisIns.getProcessDefinitionId())
                    .singleResult();
            flowTask.setDeployId(pd.getDeploymentId());
            flowTask.setProcDefName(pd.getName());
            flowTask.setProcDefVersion(pd.getVersion());
            flowTask.setCategory(pd.getCategory());
            flowTask.setProcDefVersion(pd.getVersion());
            // 当前所处流程 todo: 本地启动放开以下注释
            List<Task> taskList = taskService.createTaskQuery().processInstanceId(hisIns.getId()).list();
            if (CollectionUtils.isNotEmpty(taskList)) {
                flowTask.setTaskId(taskList.get(0).getId());
            } else {
                List<HistoricTaskInstance> historicTaskInstance = historyService.createHistoricTaskInstanceQuery().processInstanceId(hisIns.getId()).orderByHistoricTaskInstanceEndTime().desc().list();
                flowTask.setTaskId(historicTaskInstance.get(0).getId());
            }
            flowList.add(flowTask);
        }
        page.setRecords(flowList);
        return Result.OK(page);
    }

    /**
     * 取消申请
     *
     * @param flowTaskVo
     * @return
     */
    @Override
    public Result stopProcess(FlowTaskVo flowTaskVo) {
        List<Task> task = taskService.createTaskQuery().processInstanceId(flowTaskVo.getInstanceId()).list();
        if (CollectionUtils.isEmpty(task)) {
            throw new CustomException("流程未启动或已执行完成，取消申请失败");
        }
        //业务系统退回到原始状态
        setBusinessBpmStatus(flowTaskVo.getInstanceId(),"");

        SysUser loginUser = iFlowThirdService.getLoginUser();
        ProcessInstance processInstance =
                runtimeService.createProcessInstanceQuery().processInstanceId(flowTaskVo.getInstanceId()).singleResult();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
        if (Objects.nonNull(bpmnModel)) {
            Process process = bpmnModel.getMainProcess();
            List<EndEvent> endNodes = process.findFlowElementsOfType(EndEvent.class, false);
            if (CollectionUtils.isNotEmpty(endNodes)) {
                // TODO 取消流程为什么要设置流程发起人?
                /**
                 Authentication.setAuthenticatedUserId(loginUser.getUsername());
                 taskService.addComment(task.get(0).getId(), processInstance.getProcessInstanceId(), FlowComment.STOP.getType(),
                 StringUtils.isBlank(flowTaskVo.getComment()) ? "取消申请" : flowTaskVo.getComment());
                 */
                String endId = endNodes.get(0).getId();
                List<Execution> executions =
                        runtimeService.createExecutionQuery().parentId(processInstance.getProcessInstanceId()).list();
                List<String> executionIds = new ArrayList<>();
                executions.forEach(execution -> executionIds.add(execution.getId()));
                runtimeService.createChangeActivityStateBuilder().moveExecutionsToSingleActivityId(executionIds,
                        endId).changeState();
            }
        }

        return Result.OK();
    }

    /**
     * 撤回流程  todo 目前存在错误
     *
     * @param flowTaskVo
     * @return
     */
    @Override
    public Result revokeProcess(FlowTaskVo flowTaskVo) {
        Task task = taskService.createTaskQuery().processInstanceId(flowTaskVo.getInstanceId()).singleResult();
        if (task == null) {
            throw new CustomException("流程未启动或已执行完成，无法撤回");
        }

        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        List<HistoricTaskInstance> htiList = historyService.createHistoricTaskInstanceQuery()
                .processInstanceId(task.getProcessInstanceId())
                .orderByTaskCreateTime()
                .asc()
                .list();
        String myTaskId = null;
        HistoricTaskInstance myTask = null;
        for (HistoricTaskInstance hti : htiList) {
            if (loginUser.getUsername().toString().equals(hti.getAssignee())) {
                myTaskId = hti.getId();
                myTask = hti;
                break;
            }
        }
        if (null == myTaskId) {
            throw new CustomException("该任务非当前用户提交，无法撤回");
        }

        String processDefinitionId = myTask.getProcessDefinitionId();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);

        //变量
//      Map<String, VariableInstance> variables = runtimeService.getVariableInstances(currentTask.getExecutionId());
        String myActivityId = null;
        List<HistoricActivityInstance> haiList = historyService.createHistoricActivityInstanceQuery()
                .executionId(myTask.getExecutionId()).finished().list();
        for (HistoricActivityInstance hai : haiList) {
            if (myTaskId.equals(hai.getTaskId())) {
                myActivityId = hai.getActivityId();
                break;
            }
        }
        FlowNode myFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(myActivityId);

        Execution execution = runtimeService.createExecutionQuery().executionId(task.getExecutionId()).singleResult();
        String activityId = execution.getActivityId();
        FlowNode flowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(activityId);

        //记录原活动方向
        List<SequenceFlow> oriSequenceFlows = new ArrayList<>(flowNode.getOutgoingFlows());


        return Result.OK();
    }

    /**
     * 代办任务列表
     *
     * @param pageNum  当前页码
     * @param pageSize 每页条数
     * @return
     */
    @Override
    public Result todoList(Integer pageNum, Integer pageSize) {
        Page<FlowTaskDto> page = new Page<>();
        String userId = iFlowThirdService.getLoginUser().getId();
        String userName = iFlowThirdService.getLoginUser().getUsername();

        // 获取用户所属的角色Ids
        List<String> userRoleIds = iFlowThirdService.getUserRoleIdsByUserId(userName);

        // 方法1：使用任务候选用户查询（如果系统支持）
        TaskQuery taskQuery = taskService.createTaskQuery()
                .active()
                .includeProcessVariables()
                .or()
                .taskAssignee(userId)
                .taskCandidateUser(userId)
                .taskCandidateGroupIn(userRoleIds)
                .endOr()
                .orderByTaskCreateTime().desc();

        page.setTotal(taskQuery.count());

        List<Task> taskList = taskQuery.listPage((pageNum - 1) * pageSize, pageSize);

        List<FlowTaskDto> flowList = new ArrayList<>();
        for (Task task : taskList) {
            FlowTaskDto flowTask = new FlowTaskDto();
            // 当前流程信息
            flowTask.setTaskId(task.getId());
            flowTask.setTaskDefKey(task.getTaskDefinitionKey());
            flowTask.setCreateTime(task.getCreateTime());
            flowTask.setProcDefId(task.getProcessDefinitionId());
            flowTask.setTaskName(task.getName());

            // 设置任务类型
            if (task.getAssignee() != null && task.getAssignee().equals(userId)) {
                flowTask.setTaskType("assignee"); // 个人任务
            } else {
                flowTask.setTaskType("candidate"); // 候选任务
            }

            // 流程定义信息
            ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
                    .processDefinitionId(task.getProcessDefinitionId())
                    .singleResult();
            flowTask.setDeployId(pd.getDeploymentId());
            flowTask.setProcDefName(pd.getName());
            flowTask.setProcDefVersion(pd.getVersion());
            flowTask.setProcInsId(task.getProcessInstanceId());
            flowTask.setCategory(pd.getCategory());



            // 流程发起人信息
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                    .processInstanceId(task.getProcessInstanceId())
                    .singleResult();
            //SysUser startUser = iFlowThirdService.getUserByUsername(historicProcessInstance.getStartUserId());
            SysUser startUser = iFlowThirdService.getUserByUserid(historicProcessInstance.getStartUserId());
            if(startUser==null){
                startUser = iFlowThirdService.getUserByUsername(historicProcessInstance.getStartUserId());
            }
            List<String> departNamesByUsername = iFlowThirdService.getDepartNamesByUsername(historicProcessInstance.getStartUserId());
            if(departNamesByUsername==null||(departNamesByUsername!=null&&departNamesByUsername.size()==0)){
                departNamesByUsername = iFlowThirdService.getDepartNamesByUserId(historicProcessInstance.getStartUserId());
            }

            flowTask.setStartUserId(startUser.getUsername());
            flowTask.setStartUserName(startUser.getRealname());
            flowTask.setStartDeptName(CollUtil.join(departNamesByUsername, "，"));
            //why add 2025-11-25 得到 dataId
            // 1. 获取单个变量
            String executionId = task.getExecutionId();
            Object variableValue = runtimeService.getVariable(executionId, "dataId");
            if(variableValue!=null){
                Object variableValueName = runtimeService.getVariable(executionId, "dataName");
                flowTask.setDataId(variableValue.toString());
                flowTask.setDataName(variableValueName.toString());
            }
            FlowNextDto flowtDto=getFlowNodeType(task.getId());
            if(flowtDto!=null){

                flowTask.setNodeisApprove(flowtDto.isNodeisApprove());
            }


            flowList.add(flowTask);
        }

        page.setRecords(flowList);
        return Result.OK(page);
    }

    /**
     * 已办任务列表
     *
     * @param pageNum  当前页码
     * @param pageSize 每页条数
     * @return
     */
    @Override
    public Result finishedList(Integer pageNum, Integer pageSize) {
        Page<FlowTaskDto> page = new Page<>();
        String userId = iFlowThirdService.getLoginUser().getId();
        HistoricTaskInstanceQuery taskInstanceQuery = historyService.createHistoricTaskInstanceQuery()
                .includeProcessVariables()
                .finished()
                .taskAssignee(userId)
                .orderByHistoricTaskInstanceEndTime()
                .desc();
        List<HistoricTaskInstance> historicTaskInstanceList = taskInstanceQuery.listPage((pageNum - 1)*pageSize, pageSize);
        List<FlowTaskDto> hisTaskList = Lists.newArrayList();
        for (HistoricTaskInstance histTask : historicTaskInstanceList) {
            FlowTaskDto flowTask = new FlowTaskDto();
            // 当前流程信息
            flowTask.setTaskId(histTask.getId());
            // 审批人员信息
            flowTask.setCreateTime(histTask.getCreateTime());
            flowTask.setFinishTime(histTask.getEndTime());
            flowTask.setDuration(getDate(histTask.getDurationInMillis()));
            flowTask.setProcDefId(histTask.getProcessDefinitionId());
            flowTask.setTaskDefKey(histTask.getTaskDefinitionKey());
            flowTask.setTaskName(histTask.getName());

            // 流程定义信息
            ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
                    .processDefinitionId(histTask.getProcessDefinitionId())
                    .singleResult();
            flowTask.setDeployId(pd.getDeploymentId());
            flowTask.setProcDefName(pd.getName());
            flowTask.setProcDefVersion(pd.getVersion());
            flowTask.setProcInsId(histTask.getProcessInstanceId());
            flowTask.setHisProcInsId(histTask.getProcessInstanceId());

            // 流程发起人信息
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                    .processInstanceId(histTask.getProcessInstanceId())
                    .singleResult();
            SysUser startUser = iFlowThirdService.getUserByUsername(historicProcessInstance.getStartUserId());
            flowTask.setStartUserId(startUser.getUsername());
            flowTask.setStartUserName(startUser.getRealname());
            List<String> departNamesByUsername = iFlowThirdService.getDepartNamesByUsername(historicProcessInstance.getStartUserId());
            flowTask.setStartDeptName(CollUtil.join(departNamesByUsername,"，"));
            hisTaskList.add(flowTask);
        }
        page.setTotal(hisTaskList.size());
        page.setRecords(hisTaskList);
//        Map<String, Object> result = new HashMap<>();
//        result.put("result",page);
//        result.put("finished",true);
        return Result.OK(page);
    }

    private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
        Set<Object> seen = ConcurrentHashMap.newKeySet();
        return t -> seen.add(keyExtractor.apply(t));
    }

    /**
     * 流程历史流转记录
     *
     * @param dataId 流程数据Id
     * @return
     */
    @Override
    public Result flowRecord(String dataId) {
        FlowMyBusiness business = flowMyBusinessService.getByDataId(dataId);
        String procInsId = business.getProcessInstanceId();
        Map<String, Object> map = new HashMap<String, Object>();
        if (StringUtils.isNotBlank(procInsId)) {
            List<HistoricActivityInstance> list = historyService
                    .createHistoricActivityInstanceQuery()
                    .processInstanceId(procInsId)
                    .orderByHistoricActivityInstanceStartTime()
                    .desc().list();
            List<FlowTaskDto> hisFlowList = new ArrayList<>();
            for (HistoricActivityInstance histIns : list) {
                if (StringUtils.isNotBlank(histIns.getTaskId())) {
                    FlowTaskDto flowTask = new FlowTaskDto();
                    flowTask.setTaskId(histIns.getTaskId());
                    flowTask.setTaskName(histIns.getActivityName());
                    flowTask.setTaskDefKey(histIns.getActivityId());
                    flowTask.setCreateTime(histIns.getStartTime());
                    flowTask.setFinishTime(histIns.getEndTime());
                    if (StringUtils.isNotBlank(histIns.getAssignee())) {
                        SysUser sysUser = iFlowThirdService.getUserByUsername(histIns.getAssignee());
                        flowTask.setAssigneeId(sysUser.getUsername());
                        flowTask.setAssigneeName(sysUser.getRealname());
                        List<String> departNamesByUsername = iFlowThirdService.getDepartNamesByUsername(histIns.getAssignee());
                        flowTask.setDeptName(CollUtil.join(departNamesByUsername,"，"));
                        if (StrUtil.equals(histIns.getActivityId(),ProcessConstants.START_NODE)){
                            //    开始节点，把候选人设置为发起人，这个值已被其他地方设置过，与实际办理人一致即可
                            flowTask.setCandidate(sysUser.getRealname());
                        }
                    }
                    // 展示审批人员
                    List<HistoricIdentityLink> linksForTask = historyService.getHistoricIdentityLinksForTask(histIns.getTaskId());
                    StringBuilder stringBuilder = new StringBuilder();
                    for (HistoricIdentityLink identityLink : linksForTask) {
                        if (IdentityLinkType.CANDIDATE.equals(identityLink.getType())) {
                            if (StringUtils.isNotBlank(identityLink.getUserId())) {
                                SysUser sysUser = iFlowThirdService.getUserByUsername(identityLink.getUserId());
                                stringBuilder.append(sysUser.getRealname()).append(",");
                            }
                            /*已经全部设置到 CANDIDATE 了，不拿组了*/
                            /*if (StringUtils.isNotBlank(identityLink.getGroupId())) {
                                List<SysRole> allRole = iFlowThirdService.getAllRole();
                                SysRole sysRole = allRole.stream().filter(o -> StringUtils.equals(identityLink.getGroupId(), o.getId())).findAny().orElse(new SysRole());
                                stringBuilder.append(sysRole.getRoleName()).append(",");
                            }*/
                        }
                    }
                    if (StringUtils.isNotBlank(stringBuilder)) {
                        flowTask.setCandidate(stringBuilder.substring(0, stringBuilder.length() - 1));
                    }

                    flowTask.setDuration(histIns.getDurationInMillis() == null || histIns.getDurationInMillis() == 0 ? null : getDate(histIns.getDurationInMillis()));
                    // 获取意见评论内容
                    List<Comment> commentList = taskService.getProcessInstanceComments(histIns.getProcessInstanceId());
                    commentList.forEach(comment -> {
                        if (histIns.getTaskId().equals(comment.getTaskId())) {
                            flowTask.setComment(FlowCommentDto.builder().type(comment.getType()).comment(comment.getFullMessage()).build());
                        }
                    });
                    hisFlowList.add(flowTask);
                }
            }
            map.put("flowList", hisFlowList);
        }
        // 获取初始化表单
        String serviceImplName = business.getServiceImplName();
        FlowCallBackServiceI flowCallBackService = (FlowCallBackServiceI) SpringContextUtils.getBean(serviceImplName);
        // 流程处理完后，进行回调业务层
        if (flowCallBackService!=null){
            Object businessDataById = flowCallBackService.getBusinessDataById(dataId);
            map.put("formData",businessDataById);
        }
        return Result.OK(map);
    }

    /**
     * 根据任务ID查询挂载的表单信息
     *
     * @param taskId 任务Id
     * @return
     */
    @Override
    public Task getTaskForm(String taskId) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        return task;
    }

    /**
     * 获取流程过程图
     *
     * @param processId
     * @return
     */
    @Override
    public InputStream diagram(String processId) {
        String processDefinitionId;
        // 获取当前的流程实例
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();
        // 如果流程已经结束，则得到结束节点
        if (Objects.isNull(processInstance)) {
            HistoricProcessInstance pi = historyService.createHistoricProcessInstanceQuery().processInstanceId(processId).singleResult();

            processDefinitionId = pi.getProcessDefinitionId();
        } else {// 如果流程没有结束，则取当前活动节点
            // 根据流程实例ID获得当前处于活动状态的ActivityId合集
            ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();
            processDefinitionId = pi.getProcessDefinitionId();
        }

        // 获得活动的节点
        List<HistoricActivityInstance> highLightedFlowList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processId).orderByHistoricActivityInstanceStartTime().asc().list();

        List<String> highLightedFlows = new ArrayList<>();
        List<String> highLightedNodes = new ArrayList<>();
        //高亮线
        for (HistoricActivityInstance tempActivity : highLightedFlowList) {
            if ("sequenceFlow".equals(tempActivity.getActivityType())) {
                //高亮线
                highLightedFlows.add(tempActivity.getActivityId());
            } else {
                //高亮节点
                highLightedNodes.add(tempActivity.getActivityId());
            }
        }

        //获取流程图
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        ProcessEngineConfiguration configuration = processEngine.getProcessEngineConfiguration();
        //获取自定义图片生成器
        ProcessDiagramGenerator diagramGenerator = new CustomProcessDiagramGenerator();
        InputStream in = diagramGenerator.generateDiagram(bpmnModel, "png", highLightedNodes, highLightedFlows, configuration.getActivityFontName(),
                configuration.getLabelFontName(), configuration.getAnnotationFontName(), configuration.getClassLoader(), 1.0, true);
        return in;

    }

    /**
     * 获取流程执行过程
     *
     * @param procInsId
     * @return
     */
    @Override
    public List<FlowViewerDto> getFlowViewer(String procInsId) {
        List<FlowViewerDto> flowViewerList = new ArrayList<>();
        FlowViewerDto flowViewerDto;
        // 获得活动的节点
        List<HistoricActivityInstance> hisActIns = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(procInsId)
                .orderByHistoricActivityInstanceStartTime()
                .asc().list();
        for (HistoricActivityInstance activityInstance : hisActIns) {
            if (!"sequenceFlow".equals(activityInstance.getActivityType())) {
                flowViewerDto = new FlowViewerDto();
                flowViewerDto.setKey(activityInstance.getActivityId());
                flowViewerDto.setCompleted(!Objects.isNull(activityInstance.getEndTime()));

                for (FlowViewerDto viewerDto : flowViewerList) {
                    String key = viewerDto.getKey();
                    if (key.equals(flowViewerDto.getKey())){
                        //    重复删除后面更新
                        flowViewerList.remove(viewerDto);
                        break;
                    }
                }
                flowViewerList.add(flowViewerDto);
            }
        }

        return flowViewerList;
    }

    @Override
    public List<FlowViewerDto> getFlowViewerByDataId(String dataId) {
        LambdaQueryWrapper<FlowMyBusiness> flowMyBusinessLambdaQueryWrapper = new LambdaQueryWrapper<>();
        flowMyBusinessLambdaQueryWrapper.eq(FlowMyBusiness::getDataId,dataId)
        ;
        //如果保存数据前未调用必调的FlowCommonService.initActBusiness方法，就会有问题
        FlowMyBusiness business = flowMyBusinessService.getOne(flowMyBusinessLambdaQueryWrapper);
        // 1.执行过的步骤
        List<FlowViewerDto> flowViewers = this.getFlowViewer(business.getProcessInstanceId());
        // 2.获取所有节点信息，根据所有节点 按顺序  和执行过的比较，驳回的节点就被跳过
        Process process = repositoryService.getBpmnModel(business.getProcessDefinitionId()).getProcesses().get(0);
        List<FlowElement> flowElements = Lists.newArrayList(process.getFlowElements());
        // 获取当前任务节点元素
        List<FlowViewerDto> reflowViewers = Lists.newArrayList();
        // *顺序的Key
        List<String> orderKeys = Lists.newArrayList();
        if (flowElements != null) {
            for (FlowElement flowElement : flowElements) {
                try {
                    // 开始节点
                    StartEvent stev = (StartEvent) flowElement;
                    //第一个key节点，
                    String firstKey = stev.getId();
                    orderKeys.add(firstKey);
                    //顺序获取节点
                    this.appendKeys(orderKeys, firstKey,flowElements);
                } catch (Exception e) {
                    break;
                }

            }

            for (String key : orderKeys) {
                Optional<FlowViewerDto> any = flowViewers.stream().filter(o -> StrUtil.equals(o.getKey(), key)).findAny();
                if(any.isPresent()){
                    FlowViewerDto viewerDto = any.get();
                    reflowViewers.add(viewerDto);
                    if (!viewerDto.isCompleted()){
                        //    已到正在等待执行的节点，后面的不要了
                        break;
                    }
                }
            }
        }
        for (FlowViewerDto flowViewer : flowViewers) {
            boolean present = reflowViewers.stream().filter(o -> StrUtil.equals(o.getKey(), flowViewer.getKey())).findAny().isPresent();
            flowViewer.setBack(!present);
        }
        //return reflowViewers;
        return flowViewers;
    }

    /**
     * 顺序抽取节点
     * @param orderKeys 容器
     * @param sourceKey 源
     * @param flowElements 所有的节点对象
     */
    private void appendKeys(List<String> orderKeys, String sourceKey, List<FlowElement> flowElements) {
        for (FlowElement flowElement : flowElements) {
            try {
                SequenceFlow sf = (SequenceFlow) flowElement;
                String sourceRef = sf.getSourceRef();
                String targetRef = sf.getTargetRef();
                if (sourceKey.equals(sourceRef)&&targetRef!=null){
                    orderKeys.add(targetRef);
                    this.appendKeys(orderKeys,targetRef,flowElements);
                }
            } catch (Exception e) {
                continue;
            }

        }
    }

    /**
     * 获取流程变量
     *
     * @param taskId
     * @return
     */
    @Override
    public Result processVariables(String taskId) {
        // 流程变量
        HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().includeProcessVariables().finished().taskId(taskId).singleResult();
        if (Objects.nonNull(historicTaskInstance)) {
            return Result.OK(historicTaskInstance.getProcessVariables());
        } else {
            Map<String, Object> variables = taskService.getVariables(taskId);
            return Result.OK(variables);
        }
    }

    /**
     * 获取下一节点
     *
     * @param flowTaskVo 任务
     * @return
     */
    @Override
    public Result getNextFlowNode(FlowTaskVo flowTaskVo) {
        /** 1个节点 逻辑
        // todo 似乎逻辑未写完，待检查
        FlowNextDto flowNextDto = this.getNextFlowNode(flowTaskVo.getTaskId(), flowTaskVo.getValues());
//        if (flowNextDto==null) {
//            return Result.OK("流程已完结", null);
//        }
        return Result.OK(flowNextDto);
        */

        List<FlowNextDto> flowNextDto = this.getNextFlowNodeList(flowTaskVo.getTaskId(), flowTaskVo.getValues());
        return Result.OK(flowNextDto);
    }

    /**
     * 获取下一个节点信息,流程定义上的节点信息
     * @param taskId 当前节点id
     * @param values 流程变量
     * @return 如果返回null，表示没有下一个节点，流程结束
     */
    public FlowNextDto getNextFlowNode(String taskId, Map<String, Object> values) {
        //当前节点
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (Objects.nonNull(task)) {
            // 下个任务节点
            List<UserTask> nextUserTask = FindNextNodeUtil.getNextUserTasks(repositoryService, task, values);
            if (CollectionUtils.isNotEmpty(nextUserTask)) {
                FlowNextDto flowNextDto = new FlowNextDto();
                for (UserTask userTask : nextUserTask) {
                    flowNextDto.setUserTask(userTask);
                    //待办人员
                    List<SysUser> sysUserFromTask = this.getSysUserFromTask(userTask);
                    flowNextDto.setUserList(sysUserFromTask);

                    MultiInstanceLoopCharacteristics   multiInstance =  userTask.getLoopCharacteristics();
                    if (Objects.nonNull(multiInstance)) {
                        //    会签  多实例
                        String collectionString = multiInstance.getInputDataItem();
                        Object colObj = values.get(collectionString);
                        List<String> userNameList = null;
                        if(colObj!=null){
                            userNameList = (List) colObj;
                        }
                        if (CollUtil.isNotEmpty(userNameList)){
                            // 待办人员从变量中获取  否则就是节点中配置的用户 sysUserFromTask
                            List<SysUser> userList = Lists.newArrayList();
                            for (String username : userNameList) {
                                SysUser userByUsername = iFlowThirdService.getUserByUsername(username);
                                if (userByUsername==null){
                                    throw new CustomException(username + " 用户名未找到");
                                } else {
                                    userList.add(userByUsername);
                                }
                            }
                            flowNextDto.setUserList(userList);
                        } else {
                            // 变量中没有传入，写入节点中配置的用户
                            List<String> collect_username = sysUserFromTask.stream().map(SysUser::getUsername).collect(Collectors.toList());
                            values.put(collectionString,collect_username);
                        }
                    } else {
                        // todo 读取自定义节点属性做些啥？
                        //String dataType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_DATA_TYPE);
                        String dataType="fixed";
                        String userType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_USER_TYPE);

                        flowNextDto.setType(userType);
                        if(userType.equals("user")&&(userTask.getAssignee()==null||(userTask.getAssignee()!=null&&userTask.getAssignee().equals("")))){
                            dataType="dynamic";
                        }
                        if(userType.equals("role")&&(userTask.getCandidateGroups()==null||(userTask.getCandidateGroups()!=null&&userTask.getCandidateGroups().size()==0))){
                            dataType="dynamic";
                        }
                        if(userType.equals("role")&&(userTask.getCandidateGroups()!=null&&userTask.getCandidateGroups().size()>0)){
                            dataType="fixed";
                        }
                        flowNextDto.setDataType(dataType);

                    }

                    boolean issApprove=this.getNextFlowNodeIsApprove(taskId);
                    flowNextDto.setNodeisApprove(issApprove);

                }

                //why工作流修改
                if(nextUserTask!=null&&nextUserTask.size()>0){
                    flowNextDto.setUserTaskList(nextUserTask);
                }

                return flowNextDto;

            }
        }
        return null;

    }

    /**
     * 获取下一个节点信息,流程定义上的节点信息
     * @param taskId 当前节点id
     * @param values 流程变量
     * @return 如果返回null，表示没有下一个节点，流程结束
     */
    public List<FlowNextDto> getNextFlowNodeList(String taskId, Map<String, Object> values) {
        List<FlowNextDto> FlowNextDtoList=new ArrayList<>();
        //当前节点
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (Objects.nonNull(task)) {
            // 下个任务节点
            List<UserTask> nextUserTask = FindNextNodeUtil.getNextUserTasks(repositoryService, task, values);
            if (CollectionUtils.isNotEmpty(nextUserTask)) {

                for (UserTask userTask : nextUserTask) {
                    FlowNextDto flowNextDto = new FlowNextDto();
                    flowNextDto.setUserTask(userTask);
                    //待办人员
                    List<SysUser> sysUserFromTask = this.getSysUserFromTask(userTask);
                    flowNextDto.setUserList(sysUserFromTask);

                    MultiInstanceLoopCharacteristics   multiInstance =  userTask.getLoopCharacteristics();
                    if (Objects.nonNull(multiInstance)) {
                        //    会签  多实例
                        String collectionString = multiInstance.getInputDataItem();
                        Object colObj = values.get(collectionString);
                        List<String> userNameList = null;
                        if(colObj!=null){
                            userNameList = (List) colObj;
                        }
                        if (CollUtil.isNotEmpty(userNameList)){
                            // 待办人员从变量中获取  否则就是节点中配置的用户 sysUserFromTask
                            List<SysUser> userList = Lists.newArrayList();
                            for (String username : userNameList) {
                                SysUser userByUsername = iFlowThirdService.getUserByUsername(username);
                                if (userByUsername==null){
                                    throw new CustomException(username + " 用户名未找到");
                                } else {
                                    userList.add(userByUsername);
                                }
                            }
                            flowNextDto.setUserList(userList);
                        } else {
                            // 变量中没有传入，写入节点中配置的用户
                            List<String> collect_username = sysUserFromTask.stream().map(SysUser::getUsername).collect(Collectors.toList());
                            values.put(collectionString,collect_username);
                        }
                    } else {
                        // todo 读取自定义节点属性做些啥？
                        //String dataType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_DATA_TYPE);
                        String dataType="fixed";
                        String userType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_USER_TYPE);

                        flowNextDto.setType(userType);
                        if(userType.equals("user")&&(userTask.getAssignee()==null||(userTask.getAssignee()!=null&&userTask.getAssignee().equals("")))){
                            dataType="dynamic";
                        }
                        if(userType.equals("role")&&(userTask.getCandidateGroups()==null||(userTask.getCandidateGroups()!=null&&userTask.getCandidateGroups().size()==0))){
                            dataType="dynamic";
                        }
                        if(userType.equals("role")&&(userTask.getCandidateGroups()!=null&&userTask.getCandidateGroups().size()>0)){
                            dataType="fixed";
                        }
                        flowNextDto.setDataType(dataType);

                    }

                    boolean issApprove=this.getNextFlowNodeIsApprove(taskId);
                    flowNextDto.setNodeisApprove(issApprove);
                    FlowNextDtoList.add(flowNextDto);
                }



                return FlowNextDtoList;

            }
        }
        return null;

    }

    public List<SysUser> getSysUserFromTask(UserTask userTask) {
        String assignee = userTask.getAssignee();
        if (StrUtil.isNotBlank(assignee)){
            // 指定单人
            SysUser userByUsername = iFlowThirdService.getUserByUsername(assignee);
            return Lists.newArrayList(userByUsername);
        }
        List<String> candidateUsers = userTask.getCandidateUsers();
        if (CollUtil.isNotEmpty(candidateUsers)){
            // 指定多人
            List<SysUser> list = iFlowThirdService.getAllUser();
            return list.stream().filter(o->candidateUsers.contains(o.getUsername())).collect(Collectors.toList());
        }
        List<String> candidateGroups = userTask.getCandidateGroups();
        if (CollUtil.isNotEmpty(candidateGroups)){
            //    指定多组
            List<SysUser> userList = Lists.newArrayList();
            for (String candidateGroup : candidateGroups) {
                List<SysUser> usersByRoleId = iFlowThirdService.getUsersByRoleId(candidateGroup);
                userList.addAll(usersByRoleId);
            }
            return userList;
        }
        return Lists.newArrayList();
    }
    /**
     * 流程完成时间处理
     *
     * @param ms
     * @return
     */
    private String getDate(long ms) {

        long day = ms / (24 * 60 * 60 * 1000);
        long hour = (ms / (60 * 60 * 1000) - day * 24);
        long minute = ((ms / (60 * 1000)) - day * 24 * 60 - hour * 60);
        long second = (ms / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60);

        if (day > 0) {
            return day + "天" + hour + "小时" + minute + "分钟";
        }
        if (hour > 0) {
            return hour + "小时" + minute + "分钟";
        }
        if (minute > 0) {
            return minute + "分钟";
        }
        if (second > 0) {
            return second + "秒";
        } else {
            return 0 + "秒";
        }
    }


    /**
     * 流程节点信息
     *
     * @param procInsId
     * @return
     */
    @Override
    public Result flowXmlAndNode(String procInsId, String deployId) {
        try {
            List<FlowViewerDto> flowViewerList = new ArrayList<>();
            // 获取已经完成的节点
            List<HistoricActivityInstance> listFinished = historyService.createHistoricActivityInstanceQuery()
                    .processInstanceId(procInsId)
                    .finished()
                    .list();

            // 保存已经完成的流程节点编号
            listFinished.forEach(s -> {
                FlowViewerDto flowViewerDto = new FlowViewerDto();
                flowViewerDto.setKey(s.getActivityId());
                flowViewerDto.setCompleted(true);
                // 退回节点不进行展示
                if (StringUtils.isBlank(s.getDeleteReason())) {
                    flowViewerList.add(flowViewerDto);
                }
            });

            // 获取代办节点
            List<HistoricActivityInstance> listUnFinished = historyService.createHistoricActivityInstanceQuery()
                    .processInstanceId(procInsId)
                    .unfinished()
                    .list();

            // 保存需要代办的节点编号
            listUnFinished.forEach(s -> {
                // 删除已退回节点
                flowViewerList.removeIf(task -> task.getKey().equals(s.getActivityId()));
                FlowViewerDto flowViewerDto = new FlowViewerDto();
                flowViewerDto.setKey(s.getActivityId());
                flowViewerDto.setCompleted(false);
                flowViewerList.add(flowViewerDto);
            });
            Map<String, Object> result = new HashMap();
            // xmlData 数据
            ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(deployId).singleResult();
            InputStream inputStream = repositoryService.getResourceAsStream(definition.getDeploymentId(), definition.getResourceName());
            String xmlData = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
            result.put("nodeData", flowViewerList);
            result.put("xmlData", xmlData);
            return Result.OK(result);
        } catch (Exception e) {
            return Result.error("高亮历史任务失败");
        }
    }

    /**
     * 流程初始化表单
     *
     * @param deployId
     * @return
     */
    @Override
    public Result flowFormData(String deployId) {
        // 第一次申请获取初始化表单
        if (StringUtils.isNotBlank(deployId)) {
            FlowForm sysForm = sysInstanceFormService.selectSysDeployFormByDeployId(deployId);
            if (Objects.isNull(sysForm)) {
                return Result.error("请先配置流程表单!");
            }
            return Result.OK(JSONObject.parseObject(sysForm.getFormContent()));
        } else {
            return Result.error("参数错误!");
        }
    }


    @Override
    public Result flowFormAllData(String deployId) {
        // 第一次申请获取初始化表单
        if (StringUtils.isNotBlank(deployId)) {
            FlowForm sysForm = sysInstanceFormService.selectSysFormByDeployId(deployId);
            if (Objects.isNull(sysForm)) {
                return Result.error("请先配置流程表单!");
            }
            return Result.OK(sysForm);
        } else {
            return Result.error("参数错误!");
        }
    }

    /**
     * 发起流程获取下一节点
     *
     * @param flowTaskVo 任务
     * @return
     */
    @Override
    public Result getNextFlowNodeByStart(FlowTaskVo flowTaskVo) {
        // Step 1. 查找流程定义信息
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(flowTaskVo.getDeploymentId()).singleResult();
        if (Objects.isNull(processDefinition)) {
            return Result.error("流程信息不存在!");
        }
        // Step 2. 获取下一任务节点(网关节点时需要校验表达式)
        List<UserTask> nextUserTask = FindNextNodeUtil.getNextUserTasksByStart(repositoryService, processDefinition, flowTaskVo.getValues());
        if (CollectionUtils.isEmpty(nextUserTask)) {
            return Result.error("暂未查找到下一任务,请检查流程设计是否正确!");
        }
        return getFlowAttribute(nextUserTask);
    }

    /**
     * 获取任务节点属性,包含自定义属性等
     *
     * @param nextUserTask
     */
    private Result getFlowAttribute(List<UserTask> nextUserTask) {
        FlowNextDto flowNextDto = new FlowNextDto();
        for (UserTask userTask : nextUserTask) {
            MultiInstanceLoopCharacteristics multiInstance = userTask.getLoopCharacteristics();
            // 会签节点
            if (Objects.nonNull(multiInstance)) {
                flowNextDto.setVars(multiInstance.getInputDataItem());
                flowNextDto.setType(ProcessConstants.PROCESS_MULTI_INSTANCE);
                flowNextDto.setDataType(ProcessConstants.DYNAMIC);
            } else {
                // 读取自定义节点属性 判断是否是否需要动态指定任务接收人员、组
                String dataType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_DATA_TYPE);
                String userType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_USER_TYPE);
                flowNextDto.setVars(ProcessConstants.PROCESS_APPROVAL);
                if(dataType==null){
                    dataType="fixed";
                }
                if ("user".equals(userType)) {
                    dataType = StringUtils.isBlank(userTask.getAssignee()) ? "dynamic" : "fixed";
                } else if ("role".equals(userType)) {
                    dataType = CollectionUtils.isEmpty(userTask.getCandidateGroups()) ? "dynamic" : "fixed";
                }

                flowNextDto.setType(userType);
                flowNextDto.setDataType(dataType);
            }
        }
        return Result.OK(flowNextDto);
    }

    /**
     * 流程节点表单
     *
     * @param taskId 流程任务编号
     * @return
     */
    @Override
    public Result flowTaskForm(String taskId) throws Exception {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        // 流程变量
        Map<String, Object> parameters = new HashMap<>();
        HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().includeProcessVariables().finished().taskId(taskId).singleResult();
        if (Objects.nonNull(historicTaskInstance)) {
            parameters = historicTaskInstance.getProcessVariables();
        } else {
            parameters = taskService.getVariables(taskId);
        }
//        JSONObject oldVariables = JSONObject.parseObject(JSON.toJSONString(parameters.get("formJson")));
//        List<JSONObject> oldFields = JSON.parseObject(JSON.toJSONString(oldVariables.get("widgetList")), new TypeReference<List<JSONObject>>() {
//        });
        // 设置已填写的表单为禁用状态
//        for (JSONObject oldField : oldFields) {
//            JSONObject options = oldField.getJSONObject("options");
//            options.put("disabled", true);
//        }

        //TODO 暂时只处理用户任务上的表单

//        if (StringUtils.isNotBlank(task.getFormKey())) {
//            SysForm sysForm = flowFormService.(Long.parseLong(task.getFormKey()));
//            JSONObject data = JSONObject.parseObject(sysForm.getFormContent());
//            List<JSONObject> newFields = JSON.parseObject(JSON.toJSONString(data.get("widgetList")), new TypeReference<List<JSONObject>>() {
//            });
//            // 表单回显时 加入子表单信息到流程变量中
//            for (JSONObject newField : newFields) {
//                String key = newField.getString("id");
//                // 处理图片上传组件回显问题
//                if ("picture-upload".equals(newField.getString("type"))) {
//                    parameters.put(key, new ArrayList<>());
//                } else {
//                    parameters.put(key, null);
//                }
//            }
//            oldFields.addAll(newFields);
//        }

//        oldVariables.put("widgetList", oldFields);
//        parameters.put("formJson", oldVariables);


        return Result.OK(parameters);
    }



    /**
     * 流程历史流转记录
     *
     * @param procInsId 流程实例Id
     * @return
     */
    @Override
    public Result flowRecord(String procInsId, String deployId) {
        {

            List<HistoricTaskInstance> tasks = historyService
                    .createHistoricTaskInstanceQuery()
                    .processInstanceId(procInsId)
                    .orderByHistoricTaskInstanceStartTime().asc()
                    .list();
            String urlquerystr="";
            // 1. 获取历史活动实例
            List<HistoricActivityInstance> activities = historyService
                    .createHistoricActivityInstanceQuery()
                    .processInstanceId(procInsId)
                    .activityType("userTask")  // 只查询用户任务类型
                    .orderByHistoricActivityInstanceStartTime().asc()
                    .list();

            // 2. 获取BPMN模型
            HistoricProcessInstance historicProcessInstance = historyService
                    .createHistoricProcessInstanceQuery()
                    .processInstanceId(procInsId)
                    .singleResult();

            BpmnModel bpmnModel = repositoryService
                    .getBpmnModel(historicProcessInstance.getProcessDefinitionId());

            // 3. 构建详细信息
            for (HistoricActivityInstance activity : activities) {
                FlowElement flowElement = bpmnModel
                        .getFlowElement(activity.getActivityId());

                if (flowElement instanceof UserTask) {
                    UserTask userTask = (UserTask) flowElement;





                    // 获取任务实例信息（如果有）
                    if (activity.getTaskId() != null) {
                        HistoricTaskInstance task = historyService
                                .createHistoricTaskInstanceQuery()
                                .taskId(activity.getTaskId())
                                .singleResult();

                        if (task != null) {

                            // 获取流程变量
                            Map<String, Object> formValues = getProcessVariables(task.getId());
                            if(formValues!=null){
                                // 获取流程变量
                                String   formUrlparval="";
                                String   formUrlpar="";
                                if(formValues.get("dataId")==null){
                                    if(formValues.get("_value")!=null){
                                        Map zdv=(Map)formValues.get("_value");
                                        formUrlpar=(String)zdv.get("dataName");
                                        formUrlparval=zdv.get("dataId").toString();
                                    }


                                }else{
                                    formUrlparval=formValues.get("dataId").toString();
                                    formUrlpar=formValues.get("dataName").toString();
                                }


                                urlquerystr=formUrlpar+"="+formUrlparval;
                            break;
                            }

                        }
                    }


                }
            }




            //Object formData = runtimeService.getVariable(procInsId, "formJson");

            Map<String, Object> map = new HashMap<String, Object>();
            if (StringUtils.isNotBlank(procInsId)) {
                List<HistoricActivityInstance> list = historyService
                        .createHistoricActivityInstanceQuery()
                        .processInstanceId(procInsId)
                        .orderByHistoricActivityInstanceStartTime()
                        .desc().list();
                List<FlowTaskDto> hisFlowList = new ArrayList<>();
                for (HistoricActivityInstance histIns : list) {
                    // 展示开始节点
//                if ("startEvent".equals(histIns.getActivityType())) {
//                    FlowTaskDto flowTask = new FlowTaskDto();
//                    // 流程发起人信息
//                    HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
//                            .processInstanceId(histIns.getProcessInstanceId())
//                            .singleResult();
//                    SysUser startUser = sysUserService.selectUserById(Long.parseLong(historicProcessInstance.getStartUserId()));
//                    flowTask.setTaskName(startUser.getNickName() + "(" + startUser.getDept().getDeptName() + ")发起申请");
//                    flowTask.setFinishTime(histIns.getEndTime());
//                    hisFlowList.add(flowTask);
//                } else if ("endEvent".equals(histIns.getActivityType())) {
//                    FlowTaskDto flowTask = new FlowTaskDto();
//                    flowTask.setTaskName(StringUtils.isNotBlank(histIns.getActivityName()) ? histIns.getActivityName() : "结束");
//                    flowTask.setFinishTime(histIns.getEndTime());
//                    hisFlowList.add(flowTask);
//                } else
                    if (StringUtils.isNotBlank(histIns.getTaskId())) {
                        FlowTaskDto flowTask = new FlowTaskDto();
                        flowTask.setTaskId(histIns.getTaskId());
                        flowTask.setTaskName(histIns.getActivityName());
                        flowTask.setCreateTime(histIns.getStartTime());
                        flowTask.setFinishTime(histIns.getEndTime());
                        if (StringUtils.isNotBlank(histIns.getAssignee())) {
                            //SysUser sysUser = sysUserService.getById(Long.parseLong(histIns.getAssignee()));
                            if(histIns.getAssignee()!=null) {


                                org.jeecg.modules.system.entity.SysUser sysUser = sysUserService.getById(histIns.getAssignee());
                                if (sysUser!= null) {
                                    flowTask.setAssigneeId(sysUser.getId());
                                    flowTask.setAssigneeName(sysUser.getRealname());
                                    flowTask.setDeptName(Objects.nonNull(sysUser.getDepartIds()) ? sysUser.getDepartIds() : "");

                                }

                            }
                        }
                        // 展示审批人员
                        List<HistoricIdentityLink> linksForTask = historyService.getHistoricIdentityLinksForTask(histIns.getTaskId());
                        StringBuilder stringBuilder = new StringBuilder();
                        for (HistoricIdentityLink identityLink : linksForTask) {
                            // 获选人,候选组/角色(多个)
                            if ("candidate".equals(identityLink.getType())) {
                                if (StringUtils.isNotBlank(identityLink.getUserId())) {
                                    //SysUser sysUser = sysUserService.selectUserById(Long.parseLong(identityLink.getUserId()));
                                    org.jeecg.modules.system.entity.SysUser sysUser = sysUserService.getById(identityLink.getUserId());
                                    stringBuilder.append(sysUser.getRealname()).append(",");
                                }
                                if (StringUtils.isNotBlank(identityLink.getGroupId())) {
                                    //why mod 2025 11 12
                                    // SysRole sysRole = sysRoleService.selectRoleById(Long.parseLong(identityLink.getGroupId()));
                                    //  stringBuilder.append(sysRole.getRoleName()).append(",");
                                }
                            }
                        }
                        if (StringUtils.isNotBlank(stringBuilder)) {
                            flowTask.setCandidate(stringBuilder.substring(0, stringBuilder.length() - 1));
                        }

                        flowTask.setDuration(histIns.getDurationInMillis() == null || histIns.getDurationInMillis() == 0 ? null : getDate(histIns.getDurationInMillis()));
                        // 获取意见评论内容
                        List<Comment> commentList = taskService.getProcessInstanceComments(histIns.getProcessInstanceId());
                        commentList.forEach(comment -> {
                            if (histIns.getTaskId().equals(comment.getTaskId())) {
                                flowTask.setComment(FlowCommentDto.builder().type(comment.getType()).comment(comment.getFullMessage()).build());
                            }
                        });

                        //why 2025-12-5  获得节点的表单 histIns.getTaskId()
                        // 获取任务表单定义
                        //TaskFormData taskFormData = formService.getTaskFormData(histIns.getTaskId());
                        // 如果是用户任务，获取任务详情
                        if ("userTask".equals(histIns.getActivityType())) {
                            HistoricTaskInstance task = historyService
                                    .createHistoricTaskInstanceQuery()
                                    .taskId(histIns.getTaskId())
                                    .singleResult();

                            if (task != null) {

                                // 获取任务变量
                                List<HistoricVariableInstance> variables = historyService
                                        .createHistoricVariableInstanceQuery()
                                        .taskId(task.getId())
                                        .list();


                                if(task.getFormKey()!=null) {
                                    flowTask.setFormKey(task.getFormKey());
                                    Integer formId = Integer.parseInt(task.getFormKey());
                                    FlowForm flowForm = flowFormService.getById(formId);
                                    if(flowForm!=null){
                                        flowTask.setFormTp(flowForm.getFormTp());
                                        if(flowForm.getFormTp()!=null&&flowForm.getFormTp().equals("1")){
                                            // flowTask.setFormContent();
                                            //flowTask.setFormContent((String)formData);
                                            flowTask.setFormContent(flowForm);

                                        }else{
                                            //urlquerystr
                                            String url=flowForm.getFormUrl();
                                            url=url+"?"+urlquerystr;
                                            flowTask.setFormUrl(url);
                                        }
                                    }

                                }


                            }
                        }



                        hisFlowList.add(flowTask);
                    }
                }
                map.put("flowList", hisFlowList);
            }
            // 第一次申请获取初始化表单
            if (StringUtils.isNotBlank(deployId)) {
                FlowForm sysForm = sysInstanceFormService.selectSysDeployFormByDeployId(deployId);

                if (Objects.isNull(sysForm)) {
                    return Result.error("请先配置流程表单");
                }
                map.put("formData", JSONObject.parseObject(sysForm.getFormContent()));
            }
            return Result.OK(map);
        }
    }



    /**
     * 获取流程节点类型
     *
     * @param taskId
     * @return
     */
    @Override
    public Result getNextFlowNodeType(String taskId) {
        boolean resulttype=false;
        //当前节点
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();

        if (Objects.nonNull(task)) {

            List<UserTask> nextUserTask = FindNextNodeUtil.getNextUserTasks(repositoryService, task, null);
            if (CollectionUtils.isNotEmpty(nextUserTask)) {
                FlowNextDto flowNextDto = new FlowNextDto();
                for (UserTask userTask : nextUserTask) {
                    if(userTask==null){
                        continue;
                    }
                    Map<String, List<ExtensionElement>> extensionElements = userTask.getExtensionElements();

                    // 7. 查找名为"properties"的扩展元素
                    List<ExtensionElement> properties = extensionElements.get("properties");
                    if (properties != null) {
                        for (ExtensionElement propertyElement : properties) {
                            // 8. 获取"property"子元素
                            Map<String, List<ExtensionElement>> childElements = propertyElement.getChildElements();
                            List<ExtensionElement> propertyList = childElements.get("property");

                            if (propertyList != null) {
                                for (ExtensionElement prop : propertyList) {
                                    // 9. 读取属性名和值
                                    String name = prop.getAttributeValue(null, "name");
                                    String sxvalue = prop.getAttributeValue(null, "value");

                                    // 10. 如果找到isApprove属性，输出其值
                                    if (ProcessConstants.PROCESS_ISAPPROVE.equals(name)) {
                                        if(sxvalue!=null&&(sxvalue.equals("是")||sxvalue.equals("true")||sxvalue.equals("t")||sxvalue.equals("T"))){
                                            resulttype=true;
                                            // 这里可以返回或使用这个值
                                        }else {
                                            resulttype=false;
                                        }
                                    }
                                }
                            }
                        }
                    } else {
                    }
                }
            }
        }

        return Result.OK(null,resulttype);



    }

    public boolean getNextFlowNodeIsApprove(String taskId) {
        boolean resulttype=false;
        //当前节点
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (Objects.nonNull(task)) {
            // 下个任务节点
            List<UserTask> nextUserTask = FindNextNodeUtil.getNextUserTasks(repositoryService, task, null);
            if (CollectionUtils.isNotEmpty(nextUserTask)) {
                FlowNextDto flowNextDto = new FlowNextDto();
                for (UserTask userTask : nextUserTask) {
                    if(userTask==null){
                        continue;
                    }


                    // 6. 获取扩展元素
                    Map<String, List<ExtensionElement>> extensionElements = userTask.getExtensionElements();

                    // 7. 查找名为"properties"的扩展元素
                    List<ExtensionElement> properties = extensionElements.get("properties");
                    if (properties != null) {
                        for (ExtensionElement propertyElement : properties) {
                            // 8. 获取"property"子元素
                            Map<String, List<ExtensionElement>> childElements = propertyElement.getChildElements();
                            List<ExtensionElement> propertyList = childElements.get("property");

                            if (propertyList != null) {
                                for (ExtensionElement prop : propertyList) {
                                    // 9. 读取属性名和值
                                    String name = prop.getAttributeValue(null, "name");
                                    String sxvalue = prop.getAttributeValue(null, "value");

                                    // 10. 如果找到isApprove属性，输出其值
                                    if (ProcessConstants.PROCESS_ISAPPROVE.equals(name)) {
                                        if(sxvalue!=null&&(sxvalue.equals("是")||sxvalue.equals("true")||sxvalue.equals("t")||sxvalue.equals("T")||sxvalue.equals("1"))){
                                            resulttype=true;
                                            // 这里可以返回或使用这个值
                                        }else {
                                            resulttype=false;
                                        }
                                    }
                                }
                            }
                        }
                    } else {
                    }
                }
            }
        }

        return resulttype;

    }


    /**
     * 获取流程节点类型
     *
     * @param taskId
     * @return
     */
    @Override
    public FlowNextDto getFlowNodeType(String taskId) {
        FlowNextDto nodeInfo = new FlowNextDto();
        // 1. 获取任务实例以取得关键信息
        // 对于运行中任务
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        // 对于历史任务，使用：historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();

        if (task == null) {
            // throw new RuntimeException("未找到任务，ID: " + taskId);
            return  nodeInfo;
        }

        // 2. 获取关键桥梁信息：流程定义ID 和 任务定义Key
        String processDefinitionId = task.getProcessDefinitionId();
        String taskDefinitionKey = task.getTaskDefinitionKey(); // 这是节点在流程图中的唯一标识

        // 3. 获取BPMN模型并定位节点[citation:4]
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        FlowElement flowElement = bpmnModel.getFlowElement(taskDefinitionKey);


        if (flowElement instanceof UserTask) {
            UserTask userTask = (UserTask) flowElement;

            // 6. 获取扩展元素
            Map<String, List<ExtensionElement>> extensionElements = userTask.getExtensionElements();

            // 7. 查找名为"properties"的扩展元素
            List<ExtensionElement> properties = extensionElements.get("properties");
            if (properties != null) {
                for (ExtensionElement propertyElement : properties) {
                    // 8. 获取"property"子元素
                    Map<String, List<ExtensionElement>> childElements = propertyElement.getChildElements();
                    List<ExtensionElement> propertyList = childElements.get("property");

                    if (propertyList != null) {
                        for (ExtensionElement prop : propertyList) {
                            // 9. 读取属性名和值
                            String name = prop.getAttributeValue(null, "name");
                            String sxvalue = prop.getAttributeValue(null, "value");

                            // 10. 如果找到isApprove属性，输出其值
                            if (ProcessConstants.PROCESS_ISAPPROVE.equals(name)) {
                                if(sxvalue!=null&&(sxvalue.equals("是")||sxvalue.equals("true")||sxvalue.equals("t")||sxvalue.equals("T")||sxvalue.equals("1"))){

                                    // 这里可以返回或使用这个值
                                    nodeInfo.setNodeisApprove(true);
                                }else {
                                    nodeInfo.setNodeisApprove(false);
                                }
                            }
                        }
                    }
                }
            } else {
            }




        }
        return  nodeInfo;



    }

    /**
     * 获取流程变量
     */
    private Map<String, Object> getProcessVariables(String taskId) {
        // 先查询历史任务实例（已完成的任务）
        HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery()
                .includeProcessVariables()
                .finished()
                .taskId(taskId)
                .singleResult();

        if (historicTaskInstance != null) {
            return historicTaskInstance.getProcessVariables();
        } else {
            // 如果是当前任务，获取当前变量
            return taskService.getVariables(taskId);
        }
    }

    public void setBusinessBpmStatus(String instanceId,String bpmStatus){
        // 查询该流程实例下所有的历史任务（包括已完成和未完成的）
        List<HistoricTaskInstance> historicTasks = historyService.createHistoricTaskInstanceQuery()
                .processInstanceId(instanceId)
                .list();

        for (HistoricTaskInstance historicTask : historicTasks) {
            String taskId = historicTask.getId();
            // 先查询历史任务实例（已完成的任务）
            HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery()
                    .includeProcessVariables()
                    .taskId(taskId)
                    .singleResult();
            // 获取流程变量
            Map<String, Object> formValues = historicTaskInstance.getProcessVariables();

            String zdmc = Optional.ofNullable(formValues)
                    .map(map -> map.get("dataName"))
                    .filter(String.class::isInstance)
                    .map(String.class::cast)
                    .orElse(null);

            String zdval = Optional.ofNullable(formValues)
                    .map(map -> map.get("dataId"))
                    .map(Object::toString)
                    .orElse(null);

            // 通过流程定义ID查询流程定义对象
            ProcessDefinition processDefinition = repositoryService
                    .createProcessDefinitionQuery()
                    .processDefinitionId(historicTask.getProcessDefinitionId()) // 替换为你的流程定义ID
                    .singleResult();

            if (processDefinition != null) {
                // 从流程定义对象中获取部署ID
                String DeployId = processDefinition.getDeploymentId();
                FlowForm flowForm=sysDeployFormService.selectSysDeployFormByDeployId(DeployId);

                if(flowForm!=null){


                    String tabname= flowForm.getFormTableName();
                    if(tabname!=null&&!tabname.equals("")&&zdmc!=null&&!zdmc.equals("")&&zdval!=null&&!zdval.equals("")){
                        String formContent=zdmc+"="+zdval;
                        FlowForm flowFormben=new FlowForm();
                        flowFormben.setFormTableName(tabname);
                        flowFormben.setFormContent(formContent);
                        flowFormben.setFormTp(bpmStatus);
                        flowFormben.setFormUrl(DeployId);
                        sysDeployFormService.updateBisTabBpmStatus(flowFormben);
                    }
                }


            }

            break;

        }



    }

    @Override
    public Result flowFormAllData(String deployId,String taskId) {
        String formUrlparval= "";
        String formUrlpar= "";
        try {
            // 参数校验
            if (StringUtils.isBlank(taskId)) {
                return Result.error("任务ID不能为空");
            }
            // 查询任务信息
            Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
            if (task == null) {

            }
            // 获取流程变量
            Map<String, Object> formValues = getProcessVariables(taskId);
            formUrlparval=formValues.get("dataId").toString();
            formUrlpar=formValues.get("dataName").toString();


        } catch (Exception e) {

        }

        // 第一次申请获取初始化表单
        if (StringUtils.isNotBlank(deployId)) {
            FlowForm sysForm = sysInstanceFormService.selectSysFormByDeployId(deployId);
            if (Objects.isNull(sysForm)) {
                return Result.error("请先配置流程表单!");
            }
           String url= sysForm.getFormUrl();
            url=url+"?"+formUrlpar+"="+formUrlparval;
            sysForm.setFormUrl(url);
            return Result.OK(sysForm);
        } else {
            return Result.error("参数错误!");
        }
    }



}
