package com.yunzhupaas.flowable.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.google.common.collect.ImmutableList;
import com.yunzhupaas.base.Pagination;
import com.yunzhupaas.base.UserInfo;
import com.yunzhupaas.base.entity.DictionaryDataEntity;
import com.yunzhupaas.base.entity.VisualdevEntity;
import com.yunzhupaas.base.model.flow.FlowFormDataModel;
import com.yunzhupaas.base.service.SuperServiceImpl;
import com.yunzhupaas.constant.MsgCode;
import com.yunzhupaas.constant.PermissionConst;
import com.yunzhupaas.exception.WorkFlowException;
import com.yunzhupaas.flowable.entity.*;
import com.yunzhupaas.flowable.enums.*;
import com.yunzhupaas.flowable.mapper.TaskMapper;
import com.yunzhupaas.flowable.model.candidates.*;
import com.yunzhupaas.flowable.model.flowable.FlowAbleUrl;
import com.yunzhupaas.flowable.model.flowable.FlowableNodeModel;
import com.yunzhupaas.flowable.model.flowable.NextOrPrevFo;
import com.yunzhupaas.flowable.model.message.FlowMsgModel;
import com.yunzhupaas.flowable.model.record.NodeRecordModel;
import com.yunzhupaas.flowable.model.task.*;
import com.yunzhupaas.flowable.model.template.BeforeInfoVo;
import com.yunzhupaas.flowable.model.templatejson.TemplateJsonInfoVO;
import com.yunzhupaas.flowable.model.templatenode.ButtonModel;
import com.yunzhupaas.flowable.model.templatenode.TaskNodeModel;
import com.yunzhupaas.flowable.model.templatenode.nodejson.CounterSignConfig;
import com.yunzhupaas.flowable.model.templatenode.nodejson.FileConfig;
import com.yunzhupaas.flowable.model.templatenode.nodejson.NodeModel;
import com.yunzhupaas.flowable.model.util.FlowConstant;
import com.yunzhupaas.flowable.model.util.FlowContextHolder;
import com.yunzhupaas.flowable.model.util.FlowNature;
import com.yunzhupaas.flowable.service.*;
import com.yunzhupaas.flowable.util.*;
import com.yunzhupaas.permission.entity.OrganizeEntity;
import com.yunzhupaas.permission.entity.UserEntity;
import com.yunzhupaas.permission.entity.UserRelationEntity;
import com.yunzhupaas.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 类的描述
 *
 * @author YUNZHUPAASYUNZHUPAAS开发组
 * @version 5.0.x
 * @since 2024/4/17 15:09
 */
@Service
public class TaskServiceImpl extends SuperServiceImpl<TaskMapper, TaskEntity> implements TaskService {
    @Autowired
    private TemplateService templateService;
    @Autowired
    private TemplateJsonService templateJsonService;
    @Autowired
    private TemplateNodeService templateNodeService;
    @Autowired
    private FlowAbleUrl flowAbleUrl;
    @Autowired
    private LaunchUserService launchUserService;
    @Autowired
    private ServiceUtil serviceUtil;
    @Autowired
    private ConditionService conditionService;
    @Autowired
    private CandidatesService candidatesService;
    @Autowired
    private OperatorService operatorService;
    @Autowired
    private RecordUtil recordUtil;
    @Autowired
    private RecordService recordService;
    @Autowired
    private CirculateService circulateService;
    @Autowired
    private NodeUtil nodeUtil;
    @Autowired
    private OperatorUtil operatorUtil;
    @Autowired
    private MsgUtil msgUtil;
    @Autowired
    private CommentService commentService;
    @Autowired
    private RejectDataService rejectDataService;
    @Autowired
    private TaskUtil taskUtil;
    @Autowired
    private ButtonUtil buttonUtil;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private DelegateService delegateService;
    @Autowired
    private NodeRecordService nodeRecordService;
    @Autowired
    private TaskLineService taskLineService;
    @Autowired
    private RevokeService revokeService;
    @Autowired
    private TriggerTaskService triggerTaskService;

    @Override
    public TaskEntity getInfoSubmit(String id, SFunction<TaskEntity, ?>... columns) {
        List<TaskEntity> list = getInfosSubmit(new String[] { id }, columns);
        if (list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    @Override
    public List<TaskEntity> getInfosSubmit(String[] ids, SFunction<TaskEntity, ?>... columns) {
        List<TaskEntity> resultList = Collections.emptyList();
        if (ids == null || ids.length == 0) {
            return resultList;
        }
        LambdaQueryWrapper<TaskEntity> queryWrapper = new LambdaQueryWrapper<>();
        if (ids.length == 1) {
            queryWrapper.select(columns).and(
                    t -> t.eq(TaskEntity::getId, ids[0]));
            resultList = this.list(queryWrapper);
            if (resultList.isEmpty()) {
                queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.select(columns).and(
                        t -> t.eq(TaskEntity::getFlowId, ids[0]));
                resultList = this.list(queryWrapper);
            }
        } else {
            queryWrapper.select(TaskEntity::getId).and(t -> {
                t.in(TaskEntity::getId, ids).or().in(TaskEntity::getId, ids);
            });
            List<String> resultIds = this.listObjs(queryWrapper, Object::toString);
            if (!resultIds.isEmpty()) {
                queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.select(columns).in(TaskEntity::getId, resultIds);
                resultList = this.list(queryWrapper);
            }
        }
        return resultList;
    }

    @Override
    public List<TaskEntity> getList(TaskPagination pagination) {
        String userId = UserProvider.getUser().getUserId();
        List<Integer> templateStatusList = ImmutableList.of(1, 2);
        List<Integer> taskStatusList = ImmutableList.of(0, 1, 5, 8, 9);
        MPJLambdaWrapper<TaskEntity> queryWrapper = JoinWrappers.lambda(TaskEntity.class)
                .selectAll(TaskEntity.class)
                .leftJoin(TemplateEntity.class, TemplateEntity::getId, TaskEntity::getTemplateId)
                .and(e -> e.in(TemplateEntity::getStatus, templateStatusList)
                        .or(t -> t.eq(TemplateEntity::getStatus, 3).notIn(TaskEntity::getStatus, taskStatusList)));

        List<DelegateEntity> delegateList = delegateService.getByToUserId(userId, 0);
        queryWrapper.and(t -> {
            t.eq(TaskEntity::getCreatorUserId, userId);
            for (DelegateEntity delegate : delegateList) {
                if (StringUtil.isNotEmpty(delegate.getFlowId())) {
                    String[] flowIds = delegate.getFlowId().split(",");
                    t.or(tw -> tw.in(TaskEntity::getTemplateId, flowIds)
                            .eq(TaskEntity::getCreatorUserId, delegate.getUserId())
                            .eq(TaskEntity::getDelegateUserId, userId)
                            .between(TaskEntity::getStartTime, delegate.getStartTime(), delegate.getEndTime()));
                } else {
                    t.or().eq(TaskEntity::getCreatorUserId, delegate.getUserId())
                            .eq(TaskEntity::getDelegateUserId, userId)
                            .between(TaskEntity::getStartTime, delegate.getStartTime(), delegate.getEndTime());
                }
            }
        });

        // 关键字（流程名称、流程编码）
        String keyWord = pagination.getKeyword();
        if (ObjectUtil.isNotEmpty(keyWord)) {
            queryWrapper.and(t -> t.like(TaskEntity::getEnCode, keyWord).or().like(TaskEntity::getFullName, keyWord));
        }
        // 日期范围（近7天、近1月、近3月、自定义）
        if (ObjectUtil.isNotEmpty(pagination.getStartTime()) && ObjectUtil.isNotEmpty(pagination.getEndTime())) {
            queryWrapper.between(TaskEntity::getStartTime, new Date(pagination.getStartTime()),
                    new Date(pagination.getEndTime()));
        }
        // 所属流程
        String templateId = pagination.getTemplateId();
        if (ObjectUtil.isNotEmpty(templateId)) {
            queryWrapper.eq(TaskEntity::getTemplateId, templateId);
        }
        // 流程状态
        Integer status = pagination.getStatus();
        if (ObjectUtil.isNotEmpty(status)) {
            if (status.equals(0)) {// 待提交
                List<Integer> list = ImmutableList.of(TaskStatusEnum.TO_BE_SUBMIT.getCode(),
                        TaskStatusEnum.BACKED.getCode(), TaskStatusEnum.RECALL.getCode());
                queryWrapper.in(TaskEntity::getStatus, list);
            } else if (status.equals(1)) { // 进行中
                List<Integer> list = ImmutableList.of(TaskStatusEnum.RUNNING.getCode(),
                        TaskStatusEnum.PAUSED.getCode());
                queryWrapper.in(TaskEntity::getStatus, list);
            } else { // 已完成
                List<Integer> list = ImmutableList.of(TaskStatusEnum.PASSED.getCode(),
                        TaskStatusEnum.REJECTED.getCode(),
                        TaskStatusEnum.CANCEL.getCode(), TaskStatusEnum.REVOKED.getCode());
                queryWrapper.in(TaskEntity::getStatus, list);
            }
        }
        // 紧急程度
        Integer flowUrgent = pagination.getFlowUrgent();
        if (ObjectUtil.isNotEmpty(flowUrgent)) {
            queryWrapper.eq(TaskEntity::getUrgent, flowUrgent);
        }
        // 所属分类
        String flowCategory = pagination.getFlowCategory();
        if (ObjectUtil.isNotEmpty(flowCategory)) {
            queryWrapper.eq(TaskEntity::getFlowCategory, flowCategory);
        }
        // 排序
        queryWrapper.orderByAsc(TaskEntity::getStatus).orderByDesc(TaskEntity::getStartTime);
        Page<TaskEntity> page = new Page<>(pagination.getCurrentPage(), pagination.getPageSize());
        IPage<TaskEntity> taskEntityPage = this.selectJoinListPage(page, TaskEntity.class, queryWrapper);

        return pagination.setData(taskEntityPage.getRecords(), page.getTotal());
    }

    @Override
    public List<TaskEntity> getMonitorList(TaskPagination pagination) {
        // 定义变量判断是否需要使用修改时间倒序
        boolean flag = false;
        UserInfo userInfo = UserProvider.getUser();

        QueryWrapper<TaskEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().select(TaskEntity::getId)
                .isNotNull(TaskEntity::getStartTime)
                .gt(TaskEntity::getStatus, TaskStatusEnum.TO_BE_SUBMIT.getCode());

        if (!userInfo.getIsAdministrator()) {
            List<String> userList = serviceUtil.getOrganizeUserList("select");
            if (userList.isEmpty()) {
                return new ArrayList<>();
            }
            queryWrapper.lambda().in(TaskEntity::getCreatorUserId, userList);
        }
        // 关键字（流程名称、流程编码）
        String keyWord = pagination.getKeyword();
        if (ObjectUtil.isNotEmpty(keyWord)) {
            flag = true;
            queryWrapper.lambda()
                    .and(t -> t.like(TaskEntity::getEnCode, keyWord).or().like(TaskEntity::getFullName, keyWord));
        }
        // 日期范围（近7天、近1月、近3月、自定义）
        if (ObjectUtil.isNotEmpty(pagination.getStartTime()) && ObjectUtil.isNotEmpty(pagination.getEndTime())) {
            queryWrapper.lambda().between(TaskEntity::getStartTime, new Date(pagination.getStartTime()),
                    new Date(pagination.getEndTime()));
        }
        // 所属流程
        String templateId = pagination.getTemplateId();
        if (ObjectUtil.isNotEmpty(templateId)) {
            flag = true;
            queryWrapper.lambda().eq(TaskEntity::getTemplateId, templateId);
        }
        // 流程状态
        Integer status = pagination.getStatus();
        if (ObjectUtil.isNotEmpty(status)) {
            flag = true;
            queryWrapper.lambda().eq(TaskEntity::getStatus, status);
        }
        // 紧急程度
        Integer flowUrgent = pagination.getFlowUrgent();
        if (ObjectUtil.isNotEmpty(flowUrgent)) {
            flag = true;
            queryWrapper.lambda().eq(TaskEntity::getUrgent, flowUrgent);
        }
        // 所属分类
        String flowCategory = pagination.getFlowCategory();
        if (ObjectUtil.isNotEmpty(flowCategory)) {
            flag = true;
            queryWrapper.lambda().eq(TaskEntity::getFlowCategory, flowCategory);
        }
        // 发起人员
        String creatorUserId = pagination.getCreatorUserId();
        if (StringUtil.isNotBlank(creatorUserId)) {
            flag = true;
            queryWrapper.lambda().eq(TaskEntity::getCreatorUserId, creatorUserId);
        }

        queryWrapper.lambda().orderByDesc(TaskEntity::getStartTime);
        if (flag) {
            queryWrapper.lambda().orderByDesc(TaskEntity::getLastModifyTime);
        }

        Page<TaskEntity> page = new Page<>(pagination.getCurrentPage(), pagination.getPageSize());
        Page<TaskEntity> iPage = this.page(page, queryWrapper);
        if (!iPage.getRecords().isEmpty()) {
            List<String> ids = iPage.getRecords().stream().map(TaskEntity::getId).collect(Collectors.toList());
            queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().in(TaskEntity::getId, ids);
            // 排序
            queryWrapper.lambda().orderByDesc(TaskEntity::getStartTime);
            if (flag) {
                queryWrapper.lambda().orderByDesc(TaskEntity::getLastModifyTime);
            }
            iPage.setRecords(this.list(queryWrapper));
        }
        return pagination.setData(iPage.getRecords(), page.getTotal());
    }

    @Override
    public TaskEntity getInfo(String id) throws WorkFlowException {
        QueryWrapper<TaskEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TaskEntity::getId, id == null ? "" : id);
        TaskEntity entity = this.getOne(queryWrapper);
        if (null == entity) {
            throw new WorkFlowException(MsgCode.FA001.get());
        }
        return entity;
    }

    // 发起、审批详情
    @Override
    public BeforeInfoVo getInfo(String id, FlowModel fo) throws WorkFlowException {
        BeforeInfoVo vo = new BeforeInfoVo();
        TemplateJsonInfoVO jsonInfoVO = null;
        TemplateEntity template = null;

        if (!StringUtil.equals("0", id)) {
            TaskEntity taskEntity = this.getById(id);
            if (null != taskEntity) {
                jsonInfoVO = templateJsonService.getInfoVo(taskEntity.getFlowId());
                template = templateService.getInfo(taskEntity.getTemplateId());
            }
            vo.setLineKeyList(taskLineService.getLineKeyList(id));
        }
        if (null == jsonInfoVO) {
            template = null == template ? templateService.getInfo(fo.getFlowId()) : template;
            jsonInfoVO = templateJsonService.getInfoVo(template.getFlowId());
        }
        fo.setTemplateEntity(template);
        vo.setFlowInfo(jsonInfoVO);
        fo.setDeploymentId(jsonInfoVO.getFlowableId());

        // 节点
        List<TemplateNodeEntity> nodeEntities = templateNodeService.getList(jsonInfoVO.getFlowId());

        TemplateNodeEntity nodeEntity = null;
        OperatorEntity operatorEntity = new OperatorEntity();
        RecordEntity recordEntity = new RecordEntity();
        Map<String, Object> map = new HashMap<>();
        Map<String, Object> draft = new HashMap<>();
        String operatorId = ObjectUtil.isNotEmpty(fo.getOperatorId()) ? fo.getOperatorId() : "";
        switch (fo.getOpType()) {
            case "-1":
            case "1": // 待签
            case "2": // 待办
            case "3": // 在办
                OperatorEntity operator = operatorService.getInfo(operatorId);
                if (null != operator) {
                    nodeEntity = nodeEntities.stream()
                            .filter(e -> StringUtil.equals(operator.getNodeCode(), e.getNodeCode())).findFirst()
                            .orElse(null);
                    operatorEntity = operator;
                }
                break;
            case "4": // 已办
                RecordEntity record = recordService.getInfo(operatorId);
                if (null != record) {
                    nodeEntity = nodeEntities.stream()
                            .filter(e -> StringUtil.equals(record.getNodeCode(), e.getNodeCode())).findFirst()
                            .orElse(null);
                    if (StringUtil.isNotBlank(record.getOperatorId())) {
                        OperatorEntity op = operatorService.getById(record.getOperatorId());
                        if (null != op) {
                            operatorEntity = op;
                        }
                    }
                    recordEntity = record;
                }
                break;
            case "5": // 抄送
                CirculateEntity circulateEntity = circulateService.getById(operatorId);
                if (null != circulateEntity) {
                    nodeEntity = nodeEntities.stream()
                            .filter(e -> StringUtil.equals(circulateEntity.getNodeCode(), e.getNodeCode())).findFirst()
                            .orElse(null);
                    circulateEntity.setCirculateRead(1);
                    circulateService.updateById(circulateEntity);
                    if (StringUtil.isNotBlank(circulateEntity.getOperatorId())) {
                        OperatorEntity ope = operatorService.getById(circulateEntity.getOperatorId());
                        if (null != ope) {
                            operatorEntity = ope;
                        }
                    }
                }
                break;
        }
        if (null == nodeEntity) {
            // 默认获取开始节点
            nodeEntity = nodeEntities.stream()
                    .filter(e -> StringUtil.equals(NodeEnum.start.getType(), e.getNodeType())).findFirst().orElse(null);
        }
        if (null == nodeEntity) {
            throw new WorkFlowException(MsgCode.WF076.get());
        }
        if (null != operatorEntity.getDraftData()) {
            Map<String, Object> draftData = JsonUtil.stringToMap(operatorEntity.getDraftData());
            draftData.forEach((k, v) -> {
                if (ObjectUtil.isNotEmpty(v) && !Objects.equals(TableFeildsEnum.VERSION.getField(), k)) {
                    map.put(k, v);
                }
            });
            draft.putAll(draftData);
        }
        String formId = nodeEntity.getFormId();
        NodeModel currentNode = JsonUtil.getJsonToBean(nodeEntity.getNodeJson(), NodeModel.class);
        vo.setFormOperates(currentNode.getFormOperates());
        // 表单数据
        if (!StringUtil.equals("0", id)) {
            Map<String, Object> formData = serviceUtil.infoData(formId, id);
            vo.setFormData(formData);
            fo.setFormData(formData);
            formData.putAll(map);
            draft.putAll(formData);

            String flowTaskID = Objects.nonNull(formData.get(FlowFormConstant.FLOWTASKID))
                    ? formData.get(FlowFormConstant.FLOWTASKID).toString()
                    : "";
            id = StringUtil.isNotBlank(flowTaskID) ? flowTaskID : id;
            TaskEntity taskEntity = this.getById(id);
            if (null != taskEntity) {
                TaskVo taskVo = JsonUtil.getJsonToBean(taskEntity, TaskVo.class);
                taskVo.setFlowUrgent(taskEntity.getUrgent());
                UserEntity user = serviceUtil.getUserInfo(taskEntity.getCreatorUserId());
                taskVo.setCreatorUser(user.getRealName());
                taskVo.setHeadIcon(UploaderUtil.uploaderImg(user.getHeadIcon()));
                String flowCategory = taskEntity.getFlowCategory();
                // 分类名称
                List<String> categoryIds = ImmutableList.of(flowCategory);
                List<DictionaryDataEntity> dictionName = serviceUtil.getDictionName(categoryIds);
                taskVo.setFlowCategory(
                        dictionName.stream().map(DictionaryDataEntity::getFullName).collect(Collectors.joining(",")));

                vo.setTaskInfo(taskVo);
                fo.setTaskEntity(taskEntity);

                // 流转记录
                List<RecordEntity> records = recordService.getList(taskEntity.getId());
                vo.setRecordList(recordUtil.getRecordList(records));

                FlowModel flowModel = new FlowModel();
                flowModel.setFormData(formData);
                flowModel.setDeploymentId(fo.getDeploymentId());
                flowModel.setTaskEntity(taskEntity);
                flowModel.setNodeEntityList(nodeEntities);
                flowModel.setNodeEntity(nodeEntity);
                // 节点
                List<TaskNodeModel> nodeList = nodeUtil.getNodeList(flowModel);
                vo.setNodeList(nodeList);
                fo.setNodeList(nodeList);

                vo.setFlowInfo(jsonInfoVO);
                Map<String, Object> nodeProperties = jsonInfoVO.getFlowNodes().get(nodeEntity.getNodeCode());
                nodeUtil.setFlowFile(currentNode, taskEntity, nodeProperties);
                vo.setNodeProperties(nodeProperties);

                vo.setProgressList(!Objects.equals(fo.getOpType(), "6") ? recordUtil.getProgressList(flowModel)
                        : new ArrayList<>());
            }
        }
        // 判断按钮
        fo.setOperatorEntity(operatorEntity);
        fo.setNodeEntity(nodeEntity);
        fo.setRecordEntity(recordEntity);
        fo.setNodeEntityList(nodeEntities);
        fo.setFlowId(jsonInfoVO.getFlowId());
        ButtonModel model = buttonUtil.handleButton(fo);
        vo.setBtnInfo(model);
        // vo.setDraftData(draft);
        RevokeEntity revokeEntity = revokeService.getRevokeTask(id);
        if (null != revokeEntity) {
            Map<String, Object> revokeMap = JsonUtil.stringToMap(revokeEntity.getFormData());
            vo.setFormData(revokeMap);
            VisualdevEntity formInfo = new VisualdevEntity();
            formInfo.setEnCode(FlowNature.REVOKE_FORM_CODE);
            formInfo.setType(2);
            vo.setFormInfo(formInfo);
            TaskVo taskInfo = vo.getTaskInfo();
            if (null != taskInfo) {
                taskInfo.setIsRevokeTask(true);
            }
        } else {
            vo.setFormData(draft);
            // 获取表单
            if (null != formId) {
                VisualdevEntity formInfo = serviceUtil.getFormInfo(formId);
                vo.setFormInfo(formInfo);
            }
        }
        return vo;
    }

    @Override
    public CandidateCheckVo checkCandidates(String id, CandidateCheckFo fo) throws WorkFlowException {
        CandidateCheckVo vo = new CandidateCheckVo();
        List<CandidateListModel> list = new ArrayList<>();

        String flowId = fo.getFlowId();
        String nodeCode = null;
        Map<String, Object> formData = fo.getFormData();
        String taskId = fo.getId();

        TemplateEntity template;
        TemplateJsonEntity jsonEntity = templateJsonService.getById(flowId);
        if (null == jsonEntity) {
            template = templateService.getInfo(flowId);
            jsonEntity = templateJsonService.getInfo(template.getFlowId());
        } else {
            template = templateService.getInfo(jsonEntity.getTemplateId());
        }
        if (ObjectUtil.equals(id, "0")) {
            if (!ObjectUtil.equals(template.getStatus(), 1)) {
                throw new WorkFlowException(MsgCode.WF140.get());
            }
        } else {
            List<Integer> templateStatus = ImmutableList.of(1, 2);
            if (!templateStatus.contains(template.getStatus())) {
                throw new WorkFlowException(MsgCode.WF140.get());
            }
        }
        if (StringUtil.isNotBlank(fo.getDelegateUser())) {
            List<String> launchPermission = serviceUtil.getLaunchPermission(fo.getDelegateUser());
            if (ObjectUtil.equals(template.getVisibleType(), 2) && !launchPermission.contains(template.getId())) {
                throw new WorkFlowException(MsgCode.WF129.get());
            }
        }

        List<TemplateNodeEntity> nodeEntities = templateNodeService.getList(jsonEntity.getId());

        Map<String, NodeModel> nodes = new HashMap<>();
        for (TemplateNodeEntity nodeEntity : nodeEntities) {
            nodes.put(nodeEntity.getNodeCode(), JsonUtil.getJsonToBean(nodeEntity.getNodeJson(), NodeModel.class));
        }
        NodeModel global = nodes.get(NodeEnum.global.getType());

        TemplateNodeEntity currentNode;
        OperatorEntity operatorEntity = new OperatorEntity();
        // 默认获取开始节点编码
        if (StringUtil.equals(id, "0")) {
            currentNode = nodeEntities.stream()
                    .filter(e -> StringUtil.equals(NodeEnum.start.getType(), e.getNodeType())).findFirst().orElse(null);
        } else {
            operatorEntity = operatorService.getInfo(id);
            if (operatorEntity == null) {
                throw new WorkFlowException(MsgCode.FA001.get());
            }
            // 加签的经办无需选择候选人
            if (!ObjectUtil.equals(operatorEntity.getParentId(), "0")) {
                vo.setList(list);
                return vo;
            }
            String finalNodeCode = operatorEntity.getNodeCode();
            currentNode = nodeEntities.stream().filter(e -> StringUtil.equals(finalNodeCode, e.getNodeCode()))
                    .findFirst().orElse(null);
            taskId = operatorEntity.getTaskId();
        }
        RevokeEntity revokeEntity = revokeService.getRevokeTask(taskId);
        if (null != revokeEntity) {
            vo.setList(list);
            return vo;
        }
        if (null == currentNode) {
            throw new WorkFlowException(MsgCode.WF076.get());
        }
        nodeCode = currentNode.getNodeCode();
        NodeModel currentNodeModel = nodes.get(nodeCode);
        String divideRule = currentNodeModel.getDivideRule();
        boolean branchFlow = ObjectUtil.equals(DivideRuleEnum.CHOOSE.getType(), divideRule);

        UserInfo userInfo = UserProvider.getUser();
        // 判断条件
        TaskEntity taskEntity = this.getById(taskId);
        if (taskEntity == null) {
            FlowModel flowModel = new FlowModel();
            flowModel.setFlowId(flowId);
            flowModel.setFormData(formData);
            flowModel.setDelegateUser(fo.getDelegateUser());
            flowModel.setUserInfo(userInfo);
            flowModel.setJsonEntity(jsonEntity);
            taskEntity = this.createEntity(flowModel, template, nodes);
        }
        if (ObjectUtil.isNotEmpty(taskEntity.getRejectDataId())) {
            return vo;
        }
        taskUtil.getGlobalParam(taskEntity, nodes.get(nodeCode), nodes.get(NodeEnum.global.getType()), formData);
        FlowMethod flowMethod = new FlowMethod();
        flowMethod.setDeploymentId(jsonEntity.getFlowableId());
        flowMethod.setNodeCode(nodeCode);
        flowMethod.setFormData(formData);
        flowMethod.setNodes(nodes);
        flowMethod.setTaskEntity(taskEntity);
        flowMethod.setUserInfo(userInfo);
        Map<String, Boolean> resMap = conditionService.handleCondition(flowMethod);

        CounterSignConfig counterSignConfig = currentNodeModel.getCounterSignConfig();
        boolean delay = ObjectUtil.equals(counterSignConfig.getCalculateType(), 2);
        // 全是false，说明没有分支可走
        if (!branchFlow && !delay) {
            // 拒绝 且 配置拒绝不允许继续流转 直接返回
            if (ObjectUtil.equals(fo.getHandleStatus(), FlowNature.RejectCompletion)
                    && !global.getHasContinueAfterReject()) {
                vo.setList(list);
                return vo;
            }
            conditionService.checkCondition(resMap, nodes);
        } else {
            // 选择分支、且不是最后一个审批人，直接返回
            // 删除原先存在的下一级候选人
            NextOrPrevFo nextOrPrevFo = new NextOrPrevFo();
            nextOrPrevFo.setDeploymentId(jsonEntity.getFlowableId());
            nextOrPrevFo.setTaskKey(currentNode.getNodeCode());
            List<FlowableNodeModel> nextModels = flowAbleUrl.getNext(nextOrPrevFo);
            List<String> nextCodes = nextModels.stream().map(FlowableNodeModel::getId).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(nextCodes)) {
                candidatesService.deleteByCodes(taskId, nextCodes);
            }
            operatorEntity.setHandleStatus(fo.getHandleStatus());
            flowMethod.setOperatorEntity(operatorEntity);
            flowMethod.setNodeModel(currentNodeModel);
            flowMethod.setHandleStatus(fo.getHandleStatus());
            flowMethod.setAuditFlag(true);
            boolean auditRes = operatorUtil.checkAudit(flowMethod);
            if (!auditRes) {
                return vo;
            }
            if (ObjectUtil.equals(flowMethod.getHandleStatus(), FlowNature.RejectCompletion)
                    && !global.getHasContinueAfterReject()) {
                return vo;
            }
        }
        List<String> typeList = ImmutableList.of(NodeEnum.eventTrigger.getType(), NodeEnum.timeTrigger.getType(),
                NodeEnum.noticeTrigger.getType(), NodeEnum.webhookTrigger.getType(), NodeEnum.trigger.getType());
        List<String> connectList = global.getConnectList();
        List<String> flows = flowMethod.getOutgoingFlows();
        // 判断排他
        boolean isExclusive = ObjectUtil.equals(currentNodeModel.getDivideRule(), DivideRuleEnum.EXCLUSIVE.getType());
        boolean exclusive = false;
        // 根据true的分支获取节点
        for (String key : flows) {
            if (!connectList.contains(key)) {
                continue;
            }
            if (!branchFlow) {
                if (!resMap.get(key)) {
                    continue;
                }
                if (exclusive) { // 标识为true，说明排他的第一个条件为true
                    break;
                }
                if (isExclusive) {// 排他网关 变更标识
                    exclusive = true;
                }
            }
            // 获取连接线的目标节点
            List<String> nodeKey = flowAbleUrl.getTaskKeyAfterFlow(jsonEntity.getFlowableId(), key);
            if (CollectionUtil.isEmpty(nodeKey)) {
                continue;
            }
            NodeModel nodeModel = nodes.get(nodeKey.get(0));
            if (null == nodeModel) {
                continue;
            }
            if (typeList.contains(nodeModel.getType())) {
                continue;
            }
            getCandidateListModel(nodeModel, list);
            if (nodeModel.getType().equals(NodeEnum.subFlow.getType())) {
                // 判断子流程，获取审批节点
                FlowMethod jsonToBean = JsonUtil.getJsonToBean(flowMethod, FlowMethod.class);
                jsonToBean.setNodeCode(nodeModel.getNodeId());
                jsonToBean.setNextSubFlow(true);
                List<NodeModel> nextApprover = taskUtil.getNextApprover(jsonToBean);
                for (NodeModel node : nextApprover) {
                    getCandidateListModel(node, list);
                }
            }
        }
        // 获取已选择的候选人
        Integer counterSign = currentNodeModel.getCounterSign();
        if (StringUtil.isNotBlank(taskId) && !ObjectUtil.equals(counterSign, 0)) {
            for (CandidateListModel model : list) {
                List<CandidatesEntity> candidates = candidatesService.getList(taskId, model.getNodeCode());
                String candidateStr = candidates.stream().map(CandidatesEntity::getCandidates)
                        .collect(Collectors.joining(","));
                if (StringUtil.isNotEmpty(candidateStr)) {
                    List<String> selected = new ArrayList<>();
                    List<String> userIds = Arrays.stream(candidateStr.split(",")).distinct()
                            .collect(Collectors.toList());
                    List<UserEntity> userList = serviceUtil.getUserName(userIds);
                    for (UserEntity user : userList) {
                        selected.add(user.getRealName() + "/" + user.getAccount());
                    }
                    model.setSelected(String.join(";", selected));
                }
            }
        }
        if (branchFlow) {
            vo.setType(1);
            list = list.stream().peek(e -> e.setIsBranchFlow(true)).collect(Collectors.toList());
        } else {
            CandidateListModel listModel = list.stream().filter(e -> ObjectUtil.equals(e.getIsCandidates(), true))
                    .findFirst().orElse(null);
            if (null != listModel) {
                vo.setType(2);
            }
        }
        vo.setList(list);
        return vo;
    }

    public void getCandidateListModel(NodeModel nodeModel, List<CandidateListModel> list) {
        CandidateListModel listModel = list.stream()
                .filter(e -> ObjectUtil.equals(nodeModel.getNodeId(), e.getNodeCode())).findFirst().orElse(null);
        if (null != listModel) {
            return;
        }
        CandidateListModel model = new CandidateListModel();
        model.setNodeCode(nodeModel.getNodeId());
        model.setNodeName(nodeModel.getNodeName());
        boolean isCandidate = FlowTaskOperatorEnum.Candidate.getCode().equals(nodeModel.getAssigneeType());
        model.setIsCandidates(isCandidate);
        if (isCandidate) {
            List<String> userIds = serviceUtil.getUserListAll(nodeModel.getApprovers());
            List<UserEntity> users = serviceUtil.getUserName(userIds, true);
            model.setHasCandidates(!users.isEmpty());
        }
        list.add(model);
    }

    @Override
    public List<CandidateUserVo> getCandidateUser(String id, CandidateUserFo fo) throws WorkFlowException {
        TemplateJsonEntity jsonEntity = templateJsonService.getById(fo.getFlowId());
        if (null == jsonEntity) {
            TemplateEntity template = templateService.getInfo(fo.getFlowId());
            jsonEntity = templateJsonService.getInfo(template.getFlowId());
        }
        List<TemplateNodeEntity> nodeEntities = templateNodeService.getList(jsonEntity.getId());

        Map<String, NodeModel> nodes = new HashMap<>();
        for (TemplateNodeEntity nodeEntity : nodeEntities) {
            nodes.put(nodeEntity.getNodeCode(), JsonUtil.getJsonToBean(nodeEntity.getNodeJson(), NodeModel.class));
        }
        NodeModel nodeModel = nodes.get(fo.getNodeCode());
        if (null == nodeModel) {
            throw new WorkFlowException(MsgCode.WF076.get());
        }
        List<CandidateUserVo> vos = new ArrayList<>();
        // 获取候选人
        List<String> approvers = taskUtil.getSub(nodeModel);
        List<String> userIds = serviceUtil.getUserListAll(approvers);
        Pagination pagination = JsonUtil.getJsonToBean(fo, Pagination.class);

        // 候选人范围过滤
        UserInfo userInfo = UserProvider.getUser();
        UserEntity userEntity = serviceUtil.getUserInfo(userInfo.getUserId());
        OperatorEntity operator = operatorService.getById(id);
        if (null != operator) {
            userEntity = serviceUtil.getUserInfo(operator.getHandleId());
        } else {
            if (StringUtil.isNotBlank(fo.getDelegateUser())) {
                userEntity = serviceUtil.getUserInfo(fo.getDelegateUser());
            }
        }
        taskUtil.rule(userIds, userEntity, nodeModel.getExtraRule());

        List<UserEntity> userList = serviceUtil.getUserName(userIds, pagination);
        fo.setTotal(pagination.getTotal());
        List<String> userIdList = userList.stream().map(UserEntity::getId).collect(Collectors.toList());
        Map<String, List<UserRelationEntity>> userMap = serviceUtil.getListByUserIdAll(userIdList).stream()
                .filter(t -> PermissionConst.ORGANIZE.equals(t.getObjectType()))
                .collect(Collectors.groupingBy(UserRelationEntity::getUserId));

        for (UserEntity user : userList) {
            CandidateUserVo vo = JsonUtil.getJsonToBean(user, CandidateUserVo.class);
            vo.setFullName(user.getRealName() + "/" + user.getAccount());
            vo.setHeadIcon(UploaderUtil.uploaderImg(user.getHeadIcon()));
            List<UserRelationEntity> listByUserId = userMap.get(user.getId()) != null ? userMap.get(user.getId())
                    : new ArrayList<>();
            StringJoiner joiner = new StringJoiner(",");
            for (UserRelationEntity relation : listByUserId) {
                List<OrganizeEntity> organizeId = serviceUtil.getOrganizeId(relation.getObjectId());
                if (!organizeId.isEmpty()) {
                    String organizeName = organizeId.stream().map(OrganizeEntity::getFullName)
                            .collect(Collectors.joining("/"));
                    joiner.add(organizeName);
                }
            }
            vo.setOrganize(joiner.toString());
            vos.add(vo);
        }
        return vos;
    }

    // 提交的候选人校验
    public void checkCandidateOfSubmit(Map<String, List<String>> candidateList, String flowId,
            Map<String, Object> formData, String taskId) throws WorkFlowException {
        CandidateCheckFo checkFo = new CandidateCheckFo();
        checkFo.setFlowId(flowId);
        checkFo.setFormData(formData);
        checkFo.setId(taskId);
        CandidateCheckVo candidateCheckVo = checkCandidates("0", checkFo);
        if (null != candidateCheckVo && CollectionUtil.isNotEmpty(candidateCheckVo.getList())) {
            for (CandidateListModel model : candidateCheckVo.getList()) {
                // 候选人选项，但候选人集合为空
                if (model.getIsCandidates() && CollectionUtil.isEmpty(candidateList.get(model.getNodeCode()))) {
                    throw new WorkFlowException(MsgCode.WF121.get());
                }
            }
        }
    }

    @DSTransactional(rollbackFor = Exception.class)
    @Override
    public void batchSaveOrSubmit(FlowModel flowModel) throws Exception {
        UserInfo userInfo = flowModel.getUserInfo();
        if (null == userInfo) {
            userInfo = UserProvider.getUser();
            flowModel.setUserInfo(userInfo);
        }

        String delegateUser = flowModel.getDelegateUser();
        if (StringUtil.isBlank(delegateUser)) {
            this.saveOrSubmit(flowModel);
        } else {
            FlowModel model = JsonUtil.getJsonToBean(flowModel, FlowModel.class);
            model.setDelegateUser(userInfo.getUserId());
            model.setUserId(delegateUser);
            UserEntity userEntity = serviceUtil.getUserInfo(delegateUser);
            if (null != userEntity) {
                UserInfo info = model.getUserInfo();
                info.setUserName(userEntity.getRealName());
                info.setUserAccount(userEntity.getAccount());
                info.setUserId(userEntity.getId());
                model.setUserInfo(info);
            }
            this.saveOrSubmit(model);
            // 赋值给原来的FlowModel
            BeanUtil.copyProperties(model, flowModel);
        }
        // 保存表单数据
        FlowContextHolder.deleteFormOperator();
        Map<String, Map<String, Object>> allData = FlowContextHolder.getAllData();
        Map<String, List<Map<String, Object>>> formOperates = FlowContextHolder.getFormOperates();
        List<String> writeIdList = FlowContextHolder.getWriteIdList();
        for (String idAll : writeIdList) {
            String[] idList = idAll.split("_yunzhupaas_");
            List<Map<String, Object>> operates = formOperates.get(idAll);
            Map<String, Object> formData = allData.get(idAll);
            formData = formData == null ? new HashMap<>() : formData;
            String flowId = (String) formData.get(FlowFormConstant.FLOWID);
            FlowFormDataModel formDataModel = FlowFormDataModel.builder().formId(idList[1]).id(idList[0]).map(formData)
                    .formOperates(operates).flowId(flowId).isTransfer(true).build();
            serviceUtil.saveOrUpdateFormData(formDataModel);
        }
        FlowContextHolder.clearAll();
    }

    // 提交或暂存
    @Override
    public void saveOrSubmit(FlowModel flowModel) throws Exception {
        TemplateEntity templateEntity = null;

        TemplateJsonEntity jsonEntity = templateJsonService.getById(flowModel.getFlowId());
        if (null == jsonEntity) {
            templateEntity = templateService.getInfo(flowModel.getFlowId());
            jsonEntity = templateJsonService.getInfo(templateEntity.getFlowId());
        } else {
            templateEntity = templateService.getInfo(jsonEntity.getTemplateId());
        }

        UserInfo userInfo = flowModel.getUserInfo();
        List<String> branchList = flowModel.getBranchList();
        // taskUtil.checkLaunchPermission(userInfo.getUserId(), templateEntity);

        // 获取节点
        List<TemplateNodeEntity> nodeEntityList = templateNodeService.getList(jsonEntity.getId());
        if (CollectionUtil.isEmpty(nodeEntityList)) {
            throw new WorkFlowException(MsgCode.WF076.get());
        }
        Map<String, NodeModel> nodes = new HashMap<>();
        for (TemplateNodeEntity nodeEntity : nodeEntityList) {
            nodes.put(nodeEntity.getNodeCode(), JsonUtil.getJsonToBean(nodeEntity.getNodeJson(), NodeModel.class));
        }

        flowModel.setJsonEntity(jsonEntity);
        TaskEntity entity = this.createEntity(flowModel, templateEntity, nodes);
        // 开始节点
        TemplateNodeEntity nodeEntity = nodeEntityList.stream()
                .filter(e -> StringUtil.equals(NodeEnum.start.getType(), e.getNodeType())).findFirst().orElse(null);
        if (null == nodeEntity) {
            throw new WorkFlowException(MsgCode.WF076.get());
        }
        String nodeCode = nodeEntity.getNodeCode();
        // 传递部署id、节点集合
        String deploymentId = jsonEntity.getFlowableId();
        flowModel.setDeploymentId(deploymentId);
        flowModel.setNodeEntityList(nodeEntityList);
        flowModel.setNodes(nodes);
        flowModel.setNodeEntity(nodeEntity);

        NodeModel nodeModel = JsonUtil.getJsonToBean(nodeEntity.getNodeJson(), NodeModel.class);
        // 表单主键
        String formId = nodeEntity.getFormId();

        Map<String, Object> data = flowModel.getFormData();
        data.put(FlowFormConstant.FLOWID, jsonEntity.getId());
        FlowMethod flowMethod = new FlowMethod();
        flowMethod.setDeploymentId(deploymentId);
        flowMethod.setNodeCode(nodeCode);
        flowMethod.setFormData(data);
        flowMethod.setNodes(nodes);
        flowMethod.setTaskEntity(entity);
        // flowMethod.setJsonEntity(jsonEntity);

        // 退回到发起
        if (null != entity.getRejectDataId() && ObjectUtil.equals(flowModel.getStatus(), 1)) {
            RejectDataEntity rejectData = rejectDataService.getInfo(entity.getRejectDataId());
            String taskJson = rejectData.getTaskJson();
            String operatorJson = rejectData.getOperatorJson();

            TaskEntity srcTask = JsonUtil.getJsonToBean(taskJson, TaskEntity.class);
            List<OperatorEntity> srcOperatorList = JsonUtil.getJsonToList(operatorJson, OperatorEntity.class);
            for (OperatorEntity operator : srcOperatorList) {
                operator.setCreatorTime(new Date());
            }
            operatorService.updateBatchById(srcOperatorList);

            UpdateWrapper<TaskEntity> updateWrapper = new UpdateWrapper<>();
            updateWrapper.lambda().eq(TaskEntity::getId, srcTask.getId())
                    .set(TaskEntity::getCurrentNodeCode, srcTask.getCurrentNodeCode())
                    .set(TaskEntity::getCurrentNodeName, srcTask.getCurrentNodeName())
                    .set(TaskEntity::getStatus, srcTask.getStatus())
                    .set(TaskEntity::getStartTime, srcTask.getStartTime())
                    .set(TaskEntity::getRejectDataId, null);
            this.update(updateWrapper);

            rejectDataService.removeById(entity.getRejectDataId());

            TaskEntity task = this.getById(srcTask.getId());
            flowModel.setTaskEntity(task);

            // 记录
            flowMethod.setFlowModel(flowModel);
            flowMethod.setType(RecordEnum.submit.getCode());
            OperatorEntity operatorEntity = new OperatorEntity();
            operatorEntity.setNodeCode(nodeEntity.getNodeCode());
            operatorEntity.setNodeName(nodeModel.getNodeName());
            operatorEntity.setTaskId(entity.getId());
            if (StringUtil.isNotBlank(flowModel.getUserId())) {
                flowMethod.setHandId(flowModel.getUserId());
            }
            flowMethod.setOperatorEntity(operatorEntity);
            recordUtil.createRecord(flowMethod);
            return;
        }

        FlowFormDataModel model = new FlowFormDataModel();
        model.setFormId(formId);
        model.setId(entity.getId());
        model.setFormOperates(nodeModel.getFormOperates());
        model.setMap(flowModel.getFormData());
        model.setFlowId(jsonEntity.getId());

        if (ObjectUtil.equals(TaskStatusEnum.TO_BE_SUBMIT.getCode(), flowModel.getStatus())) {
            // 生成任务，保存表单数据
            if (flowModel.getSubFlow()) {
                model.setIsTransfer(true);
            }
            // 菜单入口、编辑
            if (Objects.equals(flowModel.getIsFlow(), 0)) {
                serviceUtil.saveOrUpdateFormData(model);
                entity.setLastModifyTime(new Date());
                entity.setLastModifyUserId(null != userInfo ? userInfo.getUserId() : UserProvider.getLoginUserId());
                this.updateById(entity);
                flowModel.setTaskEntity(entity);
                return;
            }

            if (StringUtil.isEmpty(flowModel.getId())) {
                entity.setStatus(TaskStatusEnum.TO_BE_SUBMIT.getCode());
                if (this.save(entity)) {
                    // 保存表单数据
                    serviceUtil.saveOrUpdateFormData(model);
                }
            } else {
                // 我发起的暂存 直接修改表单数据
                serviceUtil.saveOrUpdateFormData(model);
            }
            flowModel.setTaskEntity(entity);
        } else if (ObjectUtil.equals(TaskStatusEnum.RUNNING.getCode(), flowModel.getStatus())) {
            // 判断条件
            Map<String, Boolean> resMap = new HashMap<>();
            if (branchList.isEmpty()) {
                resMap = conditionService.handleCondition(flowMethod);
                // 全是false，说明没有分支可走
                conditionService.checkCondition(resMap, nodes);
                // 判断候选人
                // checkCandidateOfSubmit(flowModel.getCandidateList(), flowModel.getFlowId(),
                // flowModel.getFormData(), entity.getId());
                // Map<String, List<String>> errorRuleUserList =
                // flowModel.getErrorRuleUserList();
                // if (CollectionUtil.isEmpty(errorRuleUserList)) {
                // List<NodeModel> nextApprover = taskUtil.getNextApprover(flowMethod);
                // flowModel.setTaskEntity(entity);
                // taskUtil.checkNextError(flowModel, nextApprover);
                // }
            } else {
                // 选择分支的处理
                resMap = conditionService.getForBranch(flowMethod, branchList);
            }
            // 引擎启动的变量
            Map<String, Object> variables = new HashMap<>(resMap);
            // 生成引擎实例
            String instanceId = entity.getInstanceId();
            if (entity.getInstanceId() == null) {
                taskLineService.create(entity.getId(), resMap);
                instanceId = flowAbleUrl.startInstance(jsonEntity.getFlowableId(), variables);
                entity.setInstanceId(instanceId);
            }
            entity.setEngineType(1);
            entity.setStatus(TaskStatusEnum.RUNNING.getCode());
            entity.setStartTime(new Date());
            // 生成任务
            try {
                TaskEntity task = this.getById(entity.getId());
                if (null == task) {
                    this.save(entity);
                } else {
                    entity.setStatus(TaskStatusEnum.RUNNING.getCode());
                    this.updateById(entity);
                }
                flowModel.setTaskEntity(entity);
                serviceUtil.saveOrUpdateFormData(model);
                data = serviceUtil.infoData(formId, entity.getId());
                // 表单数据存储
                data.put(FlowFormConstant.FLOWID, jsonEntity.getId());
                FlowContextHolder.addChildData(entity.getId(), nodeEntity.getFormId(), data,
                        nodeModel.getFormOperates(), false);
                flowModel.setFormData(data);
                // 流程参数
                NodeModel global = nodes.get(NodeEnum.global.getType());
                taskUtil.updateGlobalParam(entity, nodeModel, global, flowModel.getFormData());
                // 记录
                flowMethod.setFlowModel(flowModel);
                flowMethod.setType(RecordEnum.submit.getCode());
                OperatorEntity operatorEntity = new OperatorEntity();
                operatorEntity.setNodeCode(nodeEntity.getNodeCode());
                operatorEntity.setNodeName(nodeModel.getNodeName());
                operatorEntity.setTaskId(entity.getId());
                if (StringUtil.isNotBlank(flowModel.getUserId())) {
                    flowMethod.setHandId(flowModel.getUserId());
                }
                operatorEntity.setHandleTime(entity.getStartTime());
                flowMethod.setOperatorEntity(operatorEntity);
                recordUtil.createRecord(flowMethod);
                // 节点记录
                NodeRecordModel nodeRecordModel = new NodeRecordModel();
                nodeRecordModel.setTaskId(entity.getId());
                nodeRecordModel.setNodeCode(nodeEntity.getNodeCode());
                nodeRecordModel.setNodeName(nodeModel.getNodeName());
                nodeRecordModel.setNodeStatus(1);
                nodeRecordService.create(nodeRecordModel);

                // 保存候选人、异常人
                candidatesService.create(flowModel, entity.getId(), nodeEntityList, null);
                // 保存发起用户信息
                launchUserService.createLaunchUser(entity.getId(), entity.getCreatorUserId());

                // 生成经办
                List<OperatorEntity> operatorEntities = operatorService.handleOperator(flowModel);

                // 系统审批
                operatorUtil.systemAudit();
                // 消息
                FlowMsgModel flowMsgModel = new FlowMsgModel();
                flowMsgModel.setNodeList(nodeEntityList);
                flowMsgModel.setTaskEntity(entity);
                flowMsgModel.setFlowModel(flowModel);
                flowMsgModel.setOperatorList(operatorEntities);
                flowMsgModel.setFormData(FlowContextHolder.getAllData());
                msgUtil.message(flowMsgModel);

            } catch (WorkFlowException e) {
                log.error("提交异常", e);
                // 异常，手动删除实例
                flowAbleUrl.deleteInstance(instanceId, "submitException");
                throw e;
            }
        }
    }

    public TaskEntity createEntity(FlowModel fo, TemplateEntity templateEntity, Map<String, NodeModel> nodes)
            throws WorkFlowException {
        UserInfo user = UserProvider.getUser();
        String userName = user.getUserName();
        String userId = user.getUserId();
        UserInfo userInfo = fo.getUserInfo();
        if (null != userInfo) {
            if (StringUtil.isBlank(fo.getUserId())) {
                fo.setUserId(userInfo.getUserId());
            }
            userName = userInfo.getUserName();
            userId = userInfo.getUserId();
        }
        Map<String, Object> data = fo.getFormData() == null ? new HashMap<>() : fo.getFormData();
        data.put(FlowConstant.FLOW_FULL_NAME, templateEntity.getFullName());
        data.put(FlowConstant.FLOW_FULL_CODE, templateEntity.getEnCode());
        data.put(FlowConstant.LAUNCH_USER_NAME, userName);
        data.put(FlowConstant.LAUNCH_TIME, DateUtil.daFormat(new Date()));
        NodeModel global = nodes.get(NodeEnum.global.getType());
        if (StringUtil.isNotEmpty(fo.getId())) {
            TaskEntity taskEntity = this.getById(fo.getId());
            if (null != taskEntity) {
                if (StringUtil.isNotBlank(fo.getDelegateUser())) {
                    taskEntity.setDelegateUserId(fo.getDelegateUser());
                }
                taskEntity.setCreatorUserId(StringUtil.isNotBlank(fo.getUserId()) ? fo.getUserId() : userId);
                // 流程名称
                if (ObjectUtil.equals(TaskStatusEnum.RUNNING.getCode(), fo.getStatus())
                        && ObjectUtil.equals(taskEntity.getStatus(), TaskStatusEnum.TO_BE_SUBMIT.getCode())) {
                    String fullName = userName + "的" + taskEntity.getFullName();
                    if (!FlowNature.TitleType.equals(global.getTitleType())) {
                        fullName = FlowJsonUtil.field(global.getTitleContent(), data, "1");
                    }
                    taskEntity.setFullName(fullName);
                }
                return taskEntity;
            }
        }
        TaskEntity entity = new TaskEntity();

        entity.setType(fo.getIsFlow());
        if (StringUtil.isNotEmpty(fo.getId())) {
            entity.setId(fo.getId());
        } else {
            entity.setId(RandomUtil.uuId());
        }
        entity.setUrgent(fo.getFlowUrgent());
        entity.setSortCode(0L);

        if (StringUtil.isNotBlank(fo.getDelegateUser())) {
            entity.setDelegateUserId(fo.getDelegateUser());
        }

        // 发起人就是创建人
        entity.setCreatorUserId(StringUtil.isNotBlank(fo.getUserId()) ? fo.getUserId() : userId);
        entity.setCreatorTime(new Date());

        FileConfig fileConfig = global.getFileConfig();
        entity.setIsFile(fileConfig.getOn() ? 0 : null);
        // 流程名称
        String fullName = templateEntity.getFullName();
        if (!ObjectUtil.equals(fo.getStatus(), TaskStatusEnum.TO_BE_SUBMIT.getCode())) {
            fullName = userName + "的" + templateEntity.getFullName();
            if (!FlowNature.TitleType.equals(global.getTitleType())) {
                fullName = FlowJsonUtil.field(global.getTitleContent(), data, "1");
            }
        }
        entity.setParentId(fo.getParentId());
        if (!StringUtil.equals("0", fo.getParentId())) {
            fullName += "(子流程)";
            entity.setSubCode(fo.getSubCode());
            entity.setSubParameter(JsonUtil.getObjectToString(fo.getSubParameter()));
            entity.setIsAsync(fo.getIsAsync());
        }
        entity.setFullName(fullName);

        entity.setDelegateUserId(fo.getDelegateUser());
        entity.setFlowCode(templateEntity.getEnCode());
        entity.setFlowName(templateEntity.getFullName());
        entity.setFlowCategory(templateEntity.getCategory());
        TemplateJsonEntity jsonEntity = fo.getJsonEntity();
        if (null != jsonEntity && StringUtil.isNotBlank(jsonEntity.getVersion())) {
            entity.setFlowVersion(jsonEntity.getVersion());
        } else {
            entity.setFlowVersion(templateEntity.getVersion());
        }
        entity.setTemplateId(templateEntity.getId());
        entity.setFlowId(templateEntity.getFlowId());
        // entity.setIsBatch(1);// 0：否，1：是

        if (templateEntity.getType() != null) {
            entity.setFlowType(templateEntity.getType());
        }
        return entity;
    }

    // 发起撤回
    @DSTransactional
    @Override
    public void recall(String id, FlowModel flowModel) throws WorkFlowException {
        taskUtil.setFlowModel(id, flowModel);
        TaskEntity taskEntity = flowModel.getTaskEntity();
        taskUtil.checkTemplateHide(taskEntity.getTemplateId());
        List<TemplateNodeEntity> nodeEntityList = flowModel.getNodeEntityList();
        if (CollectionUtil.isEmpty(nodeEntityList)) {
            throw new WorkFlowException(MsgCode.WF076.get());
        }

        // 开始节点
        TemplateNodeEntity nodeEntity = nodeEntityList.stream()
                .filter(e -> StringUtil.equals(NodeEnum.start.getType(), e.getNodeType())).findFirst().orElse(null);
        if (null == nodeEntity) {
            throw new WorkFlowException(MsgCode.WF076.get());
        }
        NodeModel start = JsonUtil.getJsonToBean(nodeEntity.getNodeJson(), NodeModel.class);

        flowModel.setNodeEntity(nodeEntity);
        flowModel.setIsException(true);
        if (!buttonUtil.checkRecall(flowModel)) {
            throw new WorkFlowException(MsgCode.WF077.get());
        }
        // 删除子流程(判断方法中，存在异步 或 同步子流程已提交 则不允许撤回)
        taskUtil.deleteSubflow(taskEntity.getId(), null);
        // 记录
        FlowMethod flowMethod = new FlowMethod();
        flowMethod.setType(RecordEnum.recall.getCode());
        flowMethod.setFlowModel(flowModel);
        OperatorEntity operatorEntity = new OperatorEntity();
        operatorEntity.setNodeCode(nodeEntity.getNodeCode());
        operatorEntity.setNodeName(start.getNodeName());
        operatorEntity.setTaskId(taskEntity.getId());
        operatorEntity.setHandleId(taskEntity.getCreatorUserId());
        operatorEntity.setHandleTime(new Date());
        flowMethod.setOperatorEntity(operatorEntity);
        recordUtil.createRecord(flowMethod);

        // 节点记录
        NodeRecordModel nodeRecordModel = new NodeRecordModel();
        nodeRecordModel.setTaskId(taskEntity.getId());
        nodeRecordModel.setNodeCode(nodeEntity.getNodeCode());
        nodeRecordModel.setNodeStatus(6);
        nodeRecordService.update(nodeRecordModel);

        // 删除经办
        QueryWrapper<OperatorEntity> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(OperatorEntity::getTaskId, taskEntity.getId());
        operatorService.remove(wrapper);

        // 删除候选人
        candidatesService.deleteByCodes(taskEntity.getId(), null);

        // 删除发起人
        launchUserService.delete(taskEntity.getId());

        // 删除引擎实例
        flowAbleUrl.deleteInstance(taskEntity.getInstanceId(), "retract");

        // 变更任务状态
        UpdateWrapper<TaskEntity> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().eq(TaskEntity::getId, taskEntity.getId())
                .set(TaskEntity::getInstanceId, null)
                .set(TaskEntity::getRejectDataId, null)
                .set(TaskEntity::getCurrentNodeName, FlowNature.START_NAME)
                .set(TaskEntity::getCurrentNodeCode, FlowNature.START_CODE)
                .set(TaskEntity::getStatus, TaskStatusEnum.RECALL.getCode());
        this.update(updateWrapper);
        if (taskEntity.getRejectDataId() != null) {
            rejectDataService.removeById(taskEntity.getRejectDataId());
        }
    }

    // 催办
    @Override
    public boolean press(String id) throws WorkFlowException {
        FlowModel flowModel = new FlowModel();
        taskUtil.setFlowModel(id, flowModel);
        TaskEntity taskEntity = flowModel.getTaskEntity();
        List<TemplateNodeEntity> nodeEntityList = flowModel.getNodeEntityList();

        // 消息
        QueryWrapper<OperatorEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(OperatorEntity::getTaskId, id).eq(OperatorEntity::getCompletion, 0)
                .ne(OperatorEntity::getStatus, OperatorStateEnum.Futility.getCode())
                .isNull(OperatorEntity::getHandleStatus).isNotNull(OperatorEntity::getDuedate);
        List<OperatorEntity> operatorList = operatorService.list(queryWrapper);
        if (operatorList.isEmpty()) {
            return false;
        }
        FlowMsgModel flowMsgModel = new FlowMsgModel();
        flowMsgModel.setNodeList(nodeEntityList);
        flowMsgModel.setFlowModel(flowModel);
        flowMsgModel.setTaskEntity(taskEntity);
        flowMsgModel.setOperatorList(operatorList);
        flowMsgModel.setPress(true);
        msgUtil.message(flowMsgModel);
        return true;
    }

    @DSTransactional
    @Override
    public void revoke(String id, FlowModel flowModel) throws Exception {
        taskUtil.setFlowModel(id, flowModel);
        TaskEntity taskEntity = flowModel.getTaskEntity();
        if (!TaskStatusEnum.PASSED.getCode().equals(taskEntity.getStatus())) {
            throw new WorkFlowException(MsgCode.WF078.get());
        }
        // 处理撤销表单的数据
        taskUtil.submitOfRevoke(flowModel);
    }

    @DSTransactional(rollbackFor = Exception.class)
    @Override
    public List<TaskEntity> delete(String id) throws Exception {
        TaskEntity entity = this.getById(id);
        if (null == entity) {
            throw new WorkFlowException(MsgCode.FA001.get());
        }
        if (TaskStatusEnum.PAUSED.getCode().equals(entity.getStatus())) {
            throw new WorkFlowException(MsgCode.WF114.get());
        }
        ImmutableList<Object> status = ImmutableList.of(TaskStatusEnum.TO_BE_SUBMIT.getCode(),
                TaskStatusEnum.RECALL.getCode());
        if (!status.contains(entity.getStatus())) {
            throw new WorkFlowException(MsgCode.WF063.get());
        }
        if (StringUtil.isNotEmpty(entity.getParentId()) && !FlowNature.ParentId.equals(entity.getParentId())) {
            throw new WorkFlowException(entity.getFullName() + MsgCode.WF021.get());
        }

        List<String> idList = ImmutableList.of(entity.getId());
        this.delete(idList);
        List<TaskEntity> list = ImmutableList.of(entity);
        return list;
    }

    @DSTransactional(rollbackFor = Exception.class)
    @Override
    public void deleteBatch(List<String> ids) throws Exception {
        if (ids.isEmpty()) {
            return;
        }
        List<TaskEntity> taskList = taskUtil.getOrderStaList(ids);

        List<TaskEntity> child = taskList.stream()
                .filter(t -> StringUtil.isNotEmpty(t.getParentId()) && !FlowNature.ParentId.equals(t.getParentId()))
                .collect(Collectors.toList());
        if (!child.isEmpty()) {
            throw new WorkFlowException(child.get(0).getFullName() + MsgCode.WF021.get());
        }

        List<TaskEntity> taskStatusList = new ArrayList<>();
        for (String id : ids) {
            List<String> childAllList = this.getChildAllList(id);
            taskStatusList.addAll(taskUtil.getOrderStaList(childAllList));
        }
        List<TaskEntity> taskStatus = taskStatusList.stream()
                .filter(t -> TaskStatusEnum.PAUSED.getCode().equals(t.getStatus())).collect(Collectors.toList());
        if (!taskStatus.isEmpty()) {
            throw new WorkFlowException(taskStatus.get(0).getFullName() + MsgCode.WF113.get());
        }

        UserInfo userInfo = UserProvider.getUser();
        if (!userInfo.getIsAdministrator()) {
            List<String> organizeUserList = serviceUtil.getOrganizeUserList("delete");
            List<TaskEntity> taskOrganize = taskStatusList.stream()
                    .filter(t -> !organizeUserList.contains(t.getCreatorUserId())).collect(Collectors.toList());
            if (!taskOrganize.isEmpty()) {
                throw new WorkFlowException(taskOrganize.get(0).getFullName() + MsgCode.WF051.get());
            }
        }

        this.delete(ids);
        taskUtil.deleteFormData(taskStatusList);

        List<String> instanceIds = taskStatusList.stream()
                .filter(t -> TaskStatusEnum.RUNNING.getCode().equals(t.getStatus())
                        || TaskStatusEnum.CANCEL.getCode().equals(t.getStatus()))
                .map(TaskEntity::getInstanceId).distinct().collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(instanceIds)) {
            for (String instanceId : instanceIds) {
                flowAbleUrl.deleteInstance(instanceId, "monitor");
            }
        }
    }

    public void delete(List<String> idList) {
        List<String> idAll = new ArrayList<>();
        this.deleTaskAll(idList, idAll);
        List<String> revokeTaskIds = revokeService.getByTaskId(idAll);
        idAll.addAll(revokeTaskIds);
        if (!idAll.isEmpty()) {
            QueryWrapper<TaskEntity> task = new QueryWrapper<>();
            task.lambda().in(TaskEntity::getId, idAll);
            this.setIgnoreLogicDelete().remove(task);
            this.clearIgnoreLogicDelete();
            // 候选人
            QueryWrapper<CandidatesEntity> candidates = new QueryWrapper<>();
            candidates.lambda().in(CandidatesEntity::getTaskId, idAll);
            candidatesService.setIgnoreLogicDelete().remove(candidates);
            candidatesService.clearIgnoreLogicDelete();
            // 发起人
            QueryWrapper<LaunchUserEntity> launchUser = new QueryWrapper<>();
            launchUser.lambda().in(LaunchUserEntity::getTaskId, idAll);
            launchUserService.setIgnoreLogicDelete().remove(launchUser);
            launchUserService.clearIgnoreLogicDelete();
            // 评论
            QueryWrapper<CommentEntity> comment = new QueryWrapper<>();
            comment.lambda().in(CommentEntity::getTaskId, idAll);
            commentService.setIgnoreLogicDelete().remove(comment);
            commentService.clearIgnoreLogicDelete();
            // 经办
            QueryWrapper<OperatorEntity> operator = new QueryWrapper<>();
            operator.lambda().in(OperatorEntity::getTaskId, idAll);
            operatorService.setIgnoreLogicDelete().remove(operator);
            operatorService.clearIgnoreLogicDelete();
            // 记录
            QueryWrapper<RecordEntity> record = new QueryWrapper<>();
            record.lambda().in(RecordEntity::getTaskId, idAll);
            recordService.setIgnoreLogicDelete().remove(record);
            recordService.clearIgnoreLogicDelete();
            // 退回信息
            List<TaskEntity> taskList = this.list(task);
            List<String> rejectDataIds = taskList.stream().map(TaskEntity::getRejectDataId)
                    .collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(rejectDataIds)) {
                QueryWrapper<RejectDataEntity> rejectData = new QueryWrapper<>();
                rejectData.lambda().in(RejectDataEntity::getId, rejectDataIds);
                rejectDataService.setIgnoreLogicDelete().remove(rejectData);
                rejectDataService.clearIgnoreLogicDelete();
            }
            // 抄送
            QueryWrapper<CirculateEntity> circulate = new QueryWrapper<>();
            circulate.lambda().in(CirculateEntity::getTaskId, idAll);
            circulateService.setIgnoreLogicDelete().remove(circulate);
            circulateService.clearIgnoreLogicDelete();
            // 任务条件
            QueryWrapper<TaskLineEntity> taskLine = new QueryWrapper<>();
            taskLine.lambda().in(TaskLineEntity::getTaskId, idAll);
            taskLineService.setIgnoreLogicDelete().remove(taskLine);
            taskLineService.clearIgnoreLogicDelete();
            // 撤销
            QueryWrapper<RevokeEntity> revokeWrapper = new QueryWrapper<>();
            revokeWrapper.lambda().in(RevokeEntity::getRevokeTaskId, idAll);
            revokeService.setIgnoreLogicDelete().remove(revokeWrapper);
            revokeService.clearIgnoreLogicDelete();
            // 任务流程
            triggerTaskService.deleteByTaskId(idAll);
        }
    }

    @Override
    public void deleTaskAll(List<String> idList, List<String> idAll) {
        idAll.addAll(idList);
        for (String id : idList) {
            List<TaskEntity> taskAll = this.getChildList(id, TaskEntity::getId);
            List<String> list = taskAll.stream().map(TaskEntity::getId).collect(Collectors.toList());
            this.deleTaskAll(list, idAll);
        }
    }

    public List<TaskEntity> getChildList(String id, SFunction<TaskEntity, ?>... columns) {
        return getChildList(ImmutableList.of(id), columns);
    }

    public List<TaskEntity> getChildList(List<String> id, SFunction<TaskEntity, ?>... columns) {
        QueryWrapper<TaskEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().select(columns).in(TaskEntity::getParentId, id);
        return this.list(queryWrapper);
    }

    public List<String> getChildAllList(String id) {
        List<String> idAll = new ArrayList<>();
        List<String> idList = ImmutableList.of(id);
        this.deleTaskAll(idList, idAll);
        return idAll;
    }

    public void getChildList(String id, boolean suspend, List<String> list) {
        List<TaskEntity> taskAll = this.getChildList(id, TaskEntity::getId, TaskEntity::getIsAsync);
        if (suspend) {
            taskAll = taskAll.stream().filter(t -> FlowNature.ChildSync.equals(t.getIsAsync()))
                    .collect(Collectors.toList());
        }
        for (TaskEntity entity : taskAll) {
            list.add(entity.getId());
            this.getChildList(entity.getId(), suspend, list);
        }
    }

    // 终止与挂起的区别，就是能否在列表中查询到，撤销中不允许终止等操作
    @DSTransactional
    @Override
    public void cancel(String id, FlowModel flowModel, boolean isCancel) throws WorkFlowException {
        if (isCancel) {
            // 任务流程的终止
            TriggerTaskEntity triggerTask = triggerTaskService.getById(id);
            if (null != triggerTask) {
                triggerTask.setStatus(TaskStatusEnum.CANCEL.getCode());
                triggerTaskService.updateById(triggerTask);
                return;
            }
        }
        taskUtil.setFlowModel(id, flowModel);
        TaskEntity taskEntity = flowModel.getTaskEntity();
        taskUtil.isSuspend(taskEntity);

        // 下架的判断
        if (!isCancel) {
            TemplateEntity template = templateService.getById(taskEntity.getTemplateId());
            if (null != template) {
                if (!ObjectUtil.equals(template.getStatus(), 1)) {
                    throw new WorkFlowException(MsgCode.WF140.get());
                }
            }
        }

        List<String> idList = ImmutableList.of(id);

        List<TaskEntity> taskList = new ArrayList<>();
        // 递归获取子流程
        for (String taskId : idList) {
            List<String> childAllList = this.getChildAllList(taskId);
            taskList.addAll(taskUtil.getOrderStaList(childAllList));
        }

        List<TemplateNodeEntity> nodeEntityList = flowModel.getNodeEntityList();

        for (TaskEntity entity : taskList) {
            taskUtil.isSuspend(entity);
            // 记录
            FlowMethod flowMethod = new FlowMethod();
            flowMethod.setFlowModel(flowModel);
            Integer type = isCancel ? RecordEnum.cancel.getCode() : RecordEnum.activate.getCode();
            flowMethod.setType(type);
            OperatorEntity operatorEntity = new OperatorEntity();
            String code = StringUtil.isNotEmpty(entity.getCurrentNodeCode()) ? entity.getCurrentNodeCode()
                    : FlowNature.START_CODE;
            operatorEntity.setNodeCode(code);
            String name = StringUtil.isNotEmpty(entity.getCurrentNodeName()) ? entity.getCurrentNodeName()
                    : FlowNature.START_NAME;
            operatorEntity.setNodeName(name);
            operatorEntity.setTaskId(entity.getId());
            operatorEntity.setHandleId(UserProvider.getLoginUserId());
            flowMethod.setOperatorEntity(operatorEntity);
            recordUtil.createRecord(flowMethod);

            if (isCancel) {
                // 终止，更新实例
                entity.setHisStatus(entity.getStatus());
                entity.setStatus(TaskStatusEnum.CANCEL.getCode());
                this.updateById(entity);

                // 消息
                FlowMsgModel flowMsgModel = new FlowMsgModel();
                flowMsgModel.setNodeList(nodeEntityList);
                flowMsgModel.setFlowModel(flowModel);
                flowMsgModel.setTaskEntity(entity);
                flowMsgModel.setEnd(true);
                msgUtil.message(flowMsgModel);
            } else {
                // 复活
                entity.setStatus(entity.getHisStatus());
                this.updateById(entity);
                operatorUtil.updateCreateTime(flowModel);
            }
        }
    }

    @Override
    public boolean checkAsync(String id) {
        List<TaskEntity> childList = this.getChildList(id, TaskEntity::getId, TaskEntity::getIsAsync);
        return childList.stream().filter(e -> FlowNature.ChildAsync.equals(e.getIsAsync())).count() > 0;
    }

    // isSuspend: true 挂起、false 恢复
    @DSTransactional
    @Override
    public void pause(String id, FlowModel flowModel, Boolean isSuspend) throws WorkFlowException {
        List<String> idList = new ArrayList<>();
        idList.add(id);

        boolean pause = false;

        // 暂停的选项，0.全部 1：仅主流程，同时暂停同步子流程
        if (isSuspend) {
            pause = flowModel.getPause() == 1;
        } else {
            TaskEntity taskEntity = this.getInfo(id);
            if (ObjectUtil.equals(taskEntity.getIsRestore(), 1)) {
                throw new WorkFlowException("无法恢复");
            }
            List<TaskEntity> childList = this.getChildList(id, TaskEntity::getId, TaskEntity::getIsRestore);
            // 存在 0（能恢复的），就只恢复 1（不能恢复的，即同步的）
            pause = childList.stream().filter(e -> ObjectUtil.equals(e.getIsRestore(), 0)).count() > 0;
        }
        String userId = UserProvider.getLoginUserId();

        this.getChildList(id, pause, idList);

        List<TaskEntity> orderStaList = taskUtil.getOrderStaList(idList);

        this.pause(orderStaList, isSuspend, id);

        for (TaskEntity entity : orderStaList) {
            // 记录
            FlowMethod flowMethod = new FlowMethod();
            flowMethod.setFlowModel(flowModel);
            flowMethod.setType(isSuspend ? RecordEnum.pause.getCode() : RecordEnum.reboot.getCode());
            OperatorEntity operatorEntity = new OperatorEntity();
            operatorEntity.setNodeCode(StringUtil.isNotBlank(entity.getCurrentNodeCode()) ? entity.getCurrentNodeCode()
                    : FlowNature.START_CODE);
            operatorEntity.setNodeName(StringUtil.isNotBlank(entity.getCurrentNodeName()) ? entity.getCurrentNodeName()
                    : FlowNature.START_NAME);
            operatorEntity.setTaskId(entity.getId());
            operatorEntity.setHandleId(userId);
            flowMethod.setOperatorEntity(operatorEntity);
            recordUtil.createRecord(flowMethod);
        }

    }

    public List<OperatorEntity> pause(List<TaskEntity> orderStaList, boolean isSuspend, String id) {
        List<OperatorEntity> operatorList = new ArrayList<>();
        for (TaskEntity taskEntity : orderStaList) {
            if (isSuspend) {
                // 暂停
                if (!ObjectUtil.equals(taskEntity.getStatus(), TaskStatusEnum.PAUSED.getCode())) {
                    taskEntity.setHisStatus(taskEntity.getStatus());
                    taskEntity.setStatus(TaskStatusEnum.PAUSED.getCode());
                }
                taskEntity.setIsRestore(ObjectUtil.equals(taskEntity.getId(), id) ? 0 : 1);
                this.updateById(taskEntity);
            } else {
                // 恢复
                taskEntity.setStatus(taskEntity.getHisStatus());
                taskEntity.setHisStatus(TaskStatusEnum.PAUSED.getCode());
                taskEntity.setIsRestore(0);
                this.updateById(taskEntity);
            }
            // 过滤作废的经办
            List<OperatorEntity> list = operatorUtil.getList(taskEntity.getId()).stream()
                    .filter(e -> !e.getStatus().equals(OperatorStateEnum.Futility.getCode()))
                    .collect(Collectors.toList());
            operatorList.addAll(list);
        }
        return operatorList;
    }

    @DSTransactional
    @Override
    public void assign(String id, FlowModel flowModel) throws WorkFlowException {
        taskUtil.setFlowModel(id, flowModel);
        TaskEntity entity = flowModel.getTaskEntity();
        taskUtil.isSuspend(entity);
        taskUtil.isCancel(entity);

        String handleId = flowModel.getUserInfo() == null ? UserProvider.getLoginUserId()
                : flowModel.getUserInfo().getUserId();

        List<TemplateNodeEntity> nodeEntityList = flowModel.getNodeEntityList();

        // 作废原先的经办、生成指派的经办
        OperatorEntity operator = operatorUtil.handleAssign(flowModel);
        List<OperatorEntity> list = new ArrayList<>();
        list.add(operator);

        String nodeCode = flowModel.getNodeCode();
        NodeModel nodeModel = flowModel.getNodes().get(nodeCode);
        Boolean autoTransfer = flowModel.getAutoTransferFlag();
        boolean isProcessing = ObjectUtil.equals(nodeModel.getType(), NodeEnum.processing.getType());
        if (autoTransfer) {
            flowModel.setHandleOpinion(isProcessing ? "系统转办" : "系统转审");
        }
        // 记录
        FlowMethod flowMethod = new FlowMethod();
        flowMethod.setFlowModel(flowModel);
        Integer transferType = isProcessing ? RecordEnum.transferProcessing.getCode() : RecordEnum.transfer.getCode();
        flowMethod.setType(autoTransfer ? transferType : RecordEnum.assign.getCode());
        OperatorEntity operatorEntity = new OperatorEntity();
        operatorEntity.setId(operator.getId());
        operatorEntity.setNodeCode(nodeCode);
        operatorEntity.setNodeId(operator.getNodeId());
        operatorEntity.setNodeName(nodeModel.getNodeName());
        operatorEntity.setTaskId(entity.getId());
        operatorEntity.setHandleId(autoTransfer ? FlowNature.SYSTEM_CODE : handleId);
        flowMethod.setOperatorEntity(operatorEntity);
        List<String> userIds = ImmutableList.of(flowModel.getHandleIds());
        flowMethod.setUserId(String.join(",", userIds));
        recordUtil.createRecord(flowMethod);

        // 消息
        FlowMsgModel flowMsgModel = new FlowMsgModel();
        flowMsgModel.setNodeList(nodeEntityList);
        flowMsgModel.setFlowModel(flowModel);
        flowMsgModel.setTaskEntity(entity);
        flowMsgModel.setOperatorList(list);
        if (flowModel.getAutoTransferFlag()) {
            flowMsgModel.setTransfer(true);
        } else {
            flowMsgModel.setAssign(true);
        }
        msgUtil.message(flowMsgModel);

        // 超时
        TimeUtil.timeModel(list, flowModel, redisUtil);
    }

    @Override
    public TaskUserListModel getTaskUserList(String taskId) {
        Set<String> userIdSet = new HashSet<>();

        // 发起人
        TaskEntity taskEntity = this.getById(taskId);
        if (null != taskEntity) {
            userIdSet.add(taskEntity.getCreatorUserId());
        }

        // 审批人
        List<OperatorEntity> operatorList = operatorService.getList(taskId);
        if (CollectionUtil.isNotEmpty(operatorList)) {
            userIdSet.addAll(operatorList.stream().map(OperatorEntity::getHandleId).collect(Collectors.toList()));
        }

        // 抄送
        List<CirculateEntity> circulateList = circulateService.getList(taskId);
        if (CollectionUtil.isNotEmpty(circulateList)) {
            userIdSet.addAll(circulateList.stream().map(CirculateEntity::getUserId).collect(Collectors.toList()));
        }

        List<RecordEntity> recordList = recordService.getList(taskId);
        if (CollectionUtil.isNotEmpty(recordList)) {
            userIdSet.addAll(recordList.stream().map(RecordEntity::getHandleId).collect(Collectors.toList()));
        }

        TaskUserListModel model = new TaskUserListModel();
        model.setAllUserIdList(userIdSet.stream().collect(Collectors.toList()));
        model.setFlowTask(taskEntity);
        model.setOperatorList(operatorList);
        model.setCirculateList(circulateList);
        model.setOperatorRecordList(recordList);

        return model;
    }

    @Override
    public List<BeforeInfoVo> subFlowInfo(FlowModel flowModel) throws WorkFlowException {
        String taskId = flowModel.getTaskId();
        String nodeCode = flowModel.getNodeCode();
        List<BeforeInfoVo> list = new ArrayList<>();
        QueryWrapper<TaskEntity> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(TaskEntity::getParentId, taskId).eq(TaskEntity::getSubCode, nodeCode);
        List<TaskEntity> entityList = this.list(wrapper);
        if (CollectionUtil.isNotEmpty(entityList)) {
            for (TaskEntity entity : entityList) {
                FlowModel model = new FlowModel();
                model.setFlowId(entity.getFlowId());
                BeforeInfoVo info = this.getInfo(entity.getId(), model);
                list.add(info);
            }
        }
        return list;
    }

    // 消息跳转流程时，校验以及返回opType
    @Override
    public String checkInfo(String id) throws WorkFlowException {
        CirculateEntity circulate = circulateService.getById(id);
        if (null != circulate) {
            return FlowNature.Circulate;
        }
        OperatorEntity operator = operatorService.getInfo(id);
        if (null == operator) {
            throw new WorkFlowException(MsgCode.FA001.get());
        }
        if (operator.getStatus().equals(OperatorStateEnum.Futility.getCode())) {
            throw new WorkFlowException("该流程无权限查看");
        }

        TaskEntity taskEntity = this.getById(operator.getTaskId());
        if (null == taskEntity) {
            throw new WorkFlowException(MsgCode.FA001.get());
        }
        if (TaskStatusEnum.CANCEL.getCode().equals(taskEntity.getStatus())) {
            throw new WorkFlowException(MsgCode.WF041.get());
        }
        if (TaskStatusEnum.RECALL.getCode().equals(taskEntity.getStatus())) {
            throw new WorkFlowException(MsgCode.WF042.get());
        }
        taskUtil.checkTemplateHide(taskEntity.getTemplateId());

        String handleId = operator.getHandleId();
        String userId = UserProvider.getLoginUserId();
        List<String> delegateList = delegateService.getToUser(handleId, taskEntity.getFlowId());
        delegateList.add(handleId);
        if (!delegateList.contains(userId)) {
            throw new WorkFlowException(MsgCode.FA021.get());
        }

        String opType = FlowNature.LaunchDetail;
        if (null == operator.getSignTime() && null == operator.getStartHandleTime()
                && null == operator.getHandleStatus()) {
            opType = FlowNature.WaitSign;
        }
        if (null != operator.getSignTime() && null == operator.getStartHandleTime()
                && null == operator.getHandleStatus()) {
            opType = FlowNature.Todo;
        }
        if (null != operator.getSignTime() && null != operator.getStartHandleTime()
                && null == operator.getHandleStatus()) {
            opType = FlowNature.Doing;
        }
        if (null != operator.getHandleStatus() || operator.getCompletion().equals(1)) {
            opType = FlowNature.Circulate;
        }
        return opType;
    }

    @Override
    public void updateIsFile(String taskId) throws WorkFlowException {
        TaskEntity taskEntity = this.getInfo(taskId);
        if (null != taskEntity) {
            taskEntity.setIsFile(1);
            this.updateById(taskEntity);
        }
    }

    // 获取发起表单
    @Override
    public ViewFormModel getStartForm(String taskId) throws WorkFlowException {
        ViewFormModel model = new ViewFormModel();
        TaskEntity taskEntity = this.getInfo(taskId);
        List<TemplateNodeEntity> nodeEntityList = templateNodeService.getList(taskEntity.getFlowId());
        TemplateNodeEntity nodeEntity = nodeEntityList.stream()
                .filter(e -> ObjectUtil.equals(e.getNodeType(), NodeEnum.start.getType())).findFirst().orElse(null);
        if (null != nodeEntity) {
            String formId = nodeEntity.getFormId();
            VisualdevEntity formInfo = serviceUtil.getFormInfo(formId);
            model.setFormInfo(formInfo);
            Map<String, Object> map = serviceUtil.infoData(formId, taskId);
            model.setFormData(map);
        }
        return model;
    }
}
