cuikaidong
2025-05-27 504333e56f249d16e71e8ac2a435cf2212040c23
Merge remote-tracking branch 'origin/master'
已修改12个文件
1135 ■■■■■ 文件已修改
lxzn-module-eam-common/src/main/java/org/jeecg/modules/eam/constant/BusinessCodeConst.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-eam/src/main/java/org/jeecg/modules/eam/controller/EamThirdMaintenanceOrderController.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-eam/src/main/java/org/jeecg/modules/eam/request/EamThirdMaintenanceRequest.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-eam/src/main/java/org/jeecg/modules/eam/service/IEamThirdMaintenanceOrderService.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-eam/src/main/java/org/jeecg/modules/eam/service/impl/EamThirdMaintenanceOrderServiceImpl.java 259 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-eam/src/main/java/org/jeecg/modules/eam/service/impl/EamWeekMaintenanceOrderServiceImpl.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/apithird/business/service/IFlowMyBusinessService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/apithird/business/service/impl/FlowMyBusinessServiceImpl.java 27 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/controller/FlowTaskController.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/service/IFlowTaskService.java 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/service/impl/FlowDefinitionServiceImpl.java 240 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/service/impl/FlowTaskServiceImpl.java 536 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-eam-common/src/main/java/org/jeecg/modules/eam/constant/BusinessCodeConst.java
@@ -49,5 +49,7 @@
    String PCR0004 = "PCR0004";
    //设备能源部
    String PCR0005 = "PCR0005";
    //机动办管理员
    String PCR0006 = "PCR0006";
}
lxzn-module-eam/src/main/java/org/jeecg/modules/eam/controller/EamThirdMaintenanceOrderController.java
@@ -1,6 +1,7 @@
package org.jeecg.modules.eam.controller;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
@@ -211,4 +212,27 @@
        });
        return Result.OK("批量领取成功 " + i.get() + " 条工单!");
    }
    /**
     * 我的待办,审批动作
     *
     * @param request
     * @return
     */
    @ApiOperation(value = "三保工单-执行操作", notes = "三保工单-执行操作")
    @PutMapping(value = "/approval")
    public Result<?> approval(@RequestBody EamThirdMaintenanceRequest request) {
        if (request == null) {
            return Result.error("审批的对象不能为空!");
        }
        // 检查请求参数
        if (StrUtil.isBlank(request.getTaskId()) || StrUtil.isBlank(request.getDataId()) || StrUtil.isBlank(request.getInstanceId())) {
            return Result.error("审批任务错误或不存在!");
        }
        EamThirdMaintenanceOrder entity = eamThirdMaintenanceOrderService.approval(request);
        if (entity == null) {
            return Result.error("操作失败!");
        }
        return Result.ok("操作成功!");
    }
}
lxzn-module-eam/src/main/java/org/jeecg/modules/eam/request/EamThirdMaintenanceRequest.java
@@ -75,4 +75,7 @@
    private String confirmComment;
    @ApiModelProperty(value = "确认类型")
    private String confirmDealType;
    /**领导确认意见*/
    @ApiModelProperty(value = "领导确认意见")
    private String leaderConfirmComment;
}
lxzn-module-eam/src/main/java/org/jeecg/modules/eam/service/IEamThirdMaintenanceOrderService.java
@@ -43,4 +43,11 @@
     * @return
     */
    boolean collect(String id);
    /**
     * 审批流程
     * @param request
     * @return
     */
    EamThirdMaintenanceOrder approval(EamThirdMaintenanceRequest request);
}
lxzn-module-eam/src/main/java/org/jeecg/modules/eam/service/impl/EamThirdMaintenanceOrderServiceImpl.java
@@ -7,19 +7,23 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.flowable.engine.TaskService;
import org.flowable.task.api.Task;
import org.jeecg.common.api.vo.FileUploadResult;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.DataBaseConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.eam.aspect.annotation.EquipmentHistoryLog;
import org.jeecg.modules.eam.constant.BusinessCodeConst;
import org.jeecg.modules.eam.constant.EquipmentMaintenanceStatus;
import org.jeecg.modules.eam.constant.SecondMaintenanceStatusEnum;
import org.jeecg.modules.eam.constant.EquipmentOperationTagEnum;
import org.jeecg.modules.eam.constant.ThirdMaintenanceStatusEnum;
import org.jeecg.modules.eam.entity.EamEquipment;
import org.jeecg.modules.eam.entity.EamThirdMaintenanceOrder;
@@ -35,6 +39,7 @@
import org.jeecg.modules.flowable.service.IFlowDefinitionService;
import org.jeecg.modules.flowable.service.IFlowTaskService;
import org.jeecg.modules.system.service.ISysUserService;
import org.jeecg.modules.system.vo.UserSelector;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -166,32 +171,28 @@
        }
        //判断是否存在保养人 如果存在则启动流程
        if (StringUtils.isNotBlank(order.getOperator())) {
            //启动流程 TODO
//            flowCommonService.initActBusiness("工单号:" + order.getOrderNum() + ";设备编号: " + equipment.getEquipmentCode() + ";进行设备二保",
//                    order.getId(), "IEamWeekMaintenanceOrderService", "week_maintenance_process", null);
//            Map<String, Object> variables = new HashMap<>();
//            variables.put("dataId", order.getId());
//            if (StrUtil.isEmpty(order.getRemark())) {
//                variables.put("organization", "新增周保工单默认启动流程");
//                variables.put("comment", "新增周保工单默认启动流程");
//            } else {
//                variables.put("organization", order.getRemark());
//                variables.put("comment", order.getRemark());
//            }
//            variables.put("proofreading", true);
//            List<String> usernames = new ArrayList<>();
//            usernames.add(order.getOperator());
//            variables.put("NextAssignee", usernames);
//            Result result = flowDefinitionService.startProcessInstanceByKey("week_maintenance_process", variables);
//            if (result != null) {
//                //更新周保状态
//                order.setMaintenanceStatus(WeekMaintenanceStatusEnum.UNDER_MAINTENANCE.name());
//                order.setActualStartTime(new Date());
//                eamWeekMaintenanceOrderMapper.updateById(order);
//                //更新设备保养状态
//                eamEquipmentExtendService.updateEquipmentMaintenanceStatus(order.getEquipmentId(), EquipmentMaintenanceStatus.UNDER_MAINTENANCE.name());
//                return result.isSuccess();
//            }
            //启动流程
            flowCommonService.initActBusiness("工单号:" + order.getOrderNum() + ";设备编号: " + equipment.getEquipmentCode() + ";进行设备三保",
                    order.getId(), "IEamThirdMaintenanceOrderService", "third_maintenance_process", null);
            Map<String, Object> variables = new HashMap<>();
            variables.put("dataId", order.getId());
            if (StrUtil.isEmpty(order.getRemark())) {
                variables.put("organization", "新增三保工单默认启动流程");
                variables.put("comment", "新增三保工单默认启动流程");
            } else {
                variables.put("organization", order.getRemark());
                variables.put("comment", order.getRemark());
            }
            variables.put("proofreading", true);
            //并行任务会签
            variables.put("maintenance_execution", Collections.singletonList(request.getOperator()));
            variables.put("precision_check", Collections.singletonList(equipment.getEquipmentManager()));
            Result result = flowDefinitionService.startProcessInstanceByKey("third_maintenance_process", variables);
            if (result != null) {
                //更新设备保养状态
                eamEquipmentExtendService.updateEquipmentMaintenanceStatus(order.getEquipmentId(), EquipmentMaintenanceStatus.UNDER_THIRD_MAINTENANCE.name());
                return result.isSuccess();
            }
        }
        return true;
@@ -241,32 +242,28 @@
        }
        //判断是否存在保养人 如果存在则启动流程
        if (StringUtils.isNotBlank(entity.getOperator())) {
            //启动流程 TODO
//            flowCommonService.initActBusiness("工单号:" + entity.getOrderNum() + ";设备编号: " + equipment.getEquipmentCode() + ";进行设备周保",
//                    entity.getId(), "IEamWeekMaintenanceOrderService", "week_maintenance_process", null);
//            Map<String, Object> variables = new HashMap<>();
//            variables.put("dataId", entity.getId());
//            if (StrUtil.isEmpty(entity.getRemark())) {
//                variables.put("organization", "新增周保工单默认启动流程");
//                variables.put("comment", "新增周保工单默认启动流程");
//            } else {
//                variables.put("organization", entity.getRemark());
//                variables.put("comment", entity.getRemark());
//            }
//            variables.put("proofreading", true);
//            List<String> usernames = new ArrayList<>();
//            usernames.add(entity.getOperator());
//            variables.put("NextAssignee", usernames);
//            Result result = flowDefinitionService.startProcessInstanceByKey("week_maintenance_process", variables);
//            if (result != null) {
//                //更新周保状态
//                entity.setMaintenanceStatus(WeekMaintenanceStatusEnum.UNDER_MAINTENANCE.name());
//                entity.setActualStartTime(new Date());
//                eamWeekMaintenanceOrderMapper.updateById(entity);
//                //更新设备保养状态
//                eamEquipmentExtendService.updateEquipmentMaintenanceStatus(entity.getEquipmentId(), EquipmentMaintenanceStatus.UNDER_MAINTENANCE.name());
//                return result.isSuccess();
//            }
            //启动流程
            flowCommonService.initActBusiness("工单号:" + entity.getOrderNum() + ";设备编号: " + equipment.getEquipmentCode() + ";进行设备三保",
                    entity.getId(), "IEamThirdMaintenanceOrderService", "third_maintenance_process", null);
            Map<String, Object> variables = new HashMap<>();
            variables.put("dataId", entity.getId());
            if (StrUtil.isEmpty(entity.getRemark())) {
                variables.put("organization", "新增三保工单默认启动流程");
                variables.put("comment", "新增三保工单默认启动流程");
            } else {
                variables.put("organization", entity.getRemark());
                variables.put("comment", entity.getRemark());
            }
            variables.put("proofreading", true);
            //并行任务会签
            variables.put("maintenance_execution", Collections.singletonList(request.getOperator()));
            variables.put("precision_check", Collections.singletonList(equipment.getEquipmentManager()));
            Result result = flowDefinitionService.startProcessInstanceByKey("third_maintenance_process", variables);
            if (result != null) {
                //更新设备保养状态
                eamEquipmentExtendService.updateEquipmentMaintenanceStatus(entity.getEquipmentId(), EquipmentMaintenanceStatus.UNDER_THIRD_MAINTENANCE.name());
                return result.isSuccess();
            }
        }
        return true;
@@ -279,15 +276,18 @@
        if (entity == null) {
            throw new JeecgBootException("要领取的工单不存在,请刷新重试!");
        }
        if (!SecondMaintenanceStatusEnum.WAIT_MAINTENANCE.name().equals(entity.getMaintenanceStatus())) {
        if (!ThirdMaintenanceStatusEnum.WAIT_MAINTENANCE.name().equals(entity.getMaintenanceStatus())) {
            throw new JeecgBootException("该工单已进行过领取!");
        }
        EamEquipment equipment = eamEquipmentService.getById(entity.getEquipmentId());
        if (equipment == null) {
            throw new JeecgBootException("设备不存在,添加失败!");
        }
        if (StringUtils.isBlank(equipment.getEquipmentManager())) {
            throw new JeecgBootException("设备未分配设备管理员,无法进入下级审批!");
        }
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        if(sysUser == null || !BusinessCodeConst.PCR0001.equals(sysUser.getPost())) {
        if (sysUser == null || !BusinessCodeConst.PCR0001.equals(sysUser.getPost())) {
            throw new JeecgBootException("不是操作工,无法领取此工单!");
        }
        entity.setOperator(sysUser.getUsername());
@@ -310,9 +310,9 @@
            variables.put("comment", entity.getRemark());
        }
        variables.put("proofreading", true);
        List<String> usernames = new ArrayList<>();
        usernames.add(entity.getOperator());
        variables.put("NextAssignee", usernames);
        //并行任务会签
        variables.put("maintenance_execution", Collections.singletonList(sysUser.getUsername()));
        variables.put("precision_check", Collections.singletonList(equipment.getEquipmentManager()));
        Result result = flowDefinitionService.startProcessInstanceByKey("third_maintenance_process", variables);
        if (result != null) {
            //更新设备保养状态
@@ -322,6 +322,149 @@
        return true;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    @EquipmentHistoryLog(operationTag = EquipmentOperationTagEnum.THIRD_MAINTENANCE, businessTable = "eam_third_maintenance_order")
    public EamThirdMaintenanceOrder approval(EamThirdMaintenanceRequest request) {
        EamThirdMaintenanceOrder entity = eamThirdMaintenanceOrderMapper.selectById(request.getId());
        if (entity == null) {
            throw new JeecgBootException("审批的数据已删除,请刷新重试!");
        }
        // 获取当前登录用户
        LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        if (user == null || StrUtil.isBlank(user.getId())) {
            throw new JeecgBootException("未获取到登录用户,请重新登录后再试!");
        }
        request.setAssignee(user.getUsername());
        // 获取流程业务记录
        FlowMyBusiness flowMyBusiness = flowMyBusinessService.getFlowMyBusiness(request.getInstanceId(), request.getTaskId());
        if (flowMyBusiness == null) {
            throw new JeecgBootException("流程实例不存在,请刷新后重试!");
        }
        boolean userAuthorized = isUserAuthorized(flowMyBusiness, user);
        if (!userAuthorized) {
            throw new JeecgBootException("用户无权操作此任务,请刷新后重试!");
        }
        // 认领任务
        if (!claimTask(flowMyBusiness.getTaskId(), user)) {
            throw new JeecgBootException("任务不存在、已完成或已被他人认领!");
        }
        EamEquipment equipment = eamEquipmentService.getById(entity.getEquipmentId());
        if (equipment == null) {
            throw new JeecgBootException("设备不存在,请检查!");
        }
        ThirdMaintenanceStatusEnum status = ThirdMaintenanceStatusEnum.getInstance(entity.getMaintenanceStatus());
        if (status == null) {
            return null;
        }
        //流程变量
        Map<String, Object> values = new HashMap<>();
        List<String> userApprovalList;
        List<UserSelector> userSelectors;
        switch (status) {
            case UNDER_MAINTENANCE:
                boolean parallelCompletion = flowTaskService.checkParallelCompletion(flowMyBusiness.getTaskId());
                //执行完成
                userSelectors = sysUserService.selectOperatorList(equipment.getEquipmentCode(), equipment.getOrgId(), BusinessCodeConst.PCR0006);
                if (CollectionUtil.isEmpty(userSelectors)) {
                    throw new JeecgBootException("设备未分配给车间班组长,无法进入下级审批!");
                }
                userApprovalList = userSelectors.stream().map(UserSelector::getUsername).collect(Collectors.toList());
                values.put("dataId", entity.getId());
                values.put("organization", "三保执行结束");
                values.put("comment", "三保执行结束");
                if (parallelCompletion) {
                    values.put("NextAssignee", userApprovalList);
                }
                request.setComment("三保执行结束");
                //设置entity
                if (parallelCompletion) {
                    entity.setMaintenanceStatus(ThirdMaintenanceStatusEnum.WAIT_CONFIRM.name());
                    entity.setActualEndTime(new Date());
                }
                if ("maintenance_execution".equals(flowMyBusiness.getTaskNameId())) {
                    //执行保养
                    //处理附件
                    if (CollectionUtil.isNotEmpty(request.getImageFilesResult())) {
                        List<FileUploadResult> fileUploadResultList = request.getImageFilesResult();
                        ObjectMapper mapper = new ObjectMapper();
                        try {
                            String referenceFile = mapper.writeValueAsString(fileUploadResultList);
                            entity.setImageFiles(referenceFile);
                        } catch (JsonProcessingException e) {
                            log.error("JSON转换失败:" + e.getMessage(), e);
                        }
                    }
                    //处理详情
                    if (CollectionUtil.isNotEmpty(request.getTableDetailList())) {
                        thirdMaintenanceOrderDetailService.updateBatchById(request.getTableDetailList());
                    }
                } else if ("precision_check".equals(flowMyBusiness.getTaskNameId())) {
                    entity.setPrecisionChecker(user.getUsername());
                    entity.setPrecisionCheckTime(new Date());
                    //处理精度检验
                    if (CollectionUtil.isNotEmpty(request.getPrecisionDetailList())) {
                        precisionCheckDetailService.updateBatchById(request.getPrecisionDetailList());
                    }
                }
                if (parallelCompletion) {
                    //更新设备保养状态
                    eamEquipmentExtendService.updateEquipmentMaintenanceStatus(entity.getEquipmentId(), EquipmentMaintenanceStatus.THIRD_MAINTENANCE_WAIT_CONFIRM.name());
                }
                break;
            case WAIT_CONFIRM:
                userSelectors = sysUserService.selectOperatorList(equipment.getEquipmentCode(), equipment.getOrgId(), BusinessCodeConst.PCR0003);
                if (CollectionUtil.isEmpty(userSelectors)) {
                    throw new JeecgBootException("设备未分配给车间班组长,无法进入下级审批!");
                }
                //班组长确认
                userApprovalList = userSelectors.stream().map(UserSelector::getUsername).collect(Collectors.toList());
                values.put("dataId", entity.getId());
                values.put("organization", request.getConfirmComment());
                values.put("comment", request.getConfirmComment());
                values.put("NextAssignee", userApprovalList);
                values.put("confirmation", request.getConfirmDealType());
                request.setComment(request.getConfirmComment());
                //设置entity
                entity.setMaintenanceStatus(ThirdMaintenanceStatusEnum.WAIT_LEADER_CONFIRM.name());
                entity.setConfirmUser(user.getUsername());
                entity.setConfirmComment(request.getConfirmComment());
                entity.setConfirmTime(new Date());
                //处理报修
                List<EamThirdMaintenanceOrderDetail> collect = request.getTableDetailList().stream().filter((detail) -> CommonConstant.DEFAULT_1.equals(detail.getReportFlag())).collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(collect)) {
                    eamReportRepairService.reportRepairFromThirdMaintenance(equipment.getId(), entity.getOperator(), collect);
                }
                break;
            case WAIT_LEADER_CONFIRM:
                values.put("dataId", entity.getId());
                values.put("organization", request.getLeaderConfirmComment());
                values.put("comment", request.getLeaderConfirmComment());
                request.setComment(request.getLeaderConfirmComment());
                //设置entity
                entity.setMaintenanceStatus(ThirdMaintenanceStatusEnum.COMPLETE.name());
                entity.setConfirmLeader(user.getUsername());
                entity.setLeaderConfirmComment(request.getLeaderConfirmComment());
                entity.setLeaderConfirmTime(new Date());
                //更新设备保养状态
                eamEquipmentExtendService.updateEquipmentMaintenanceStatus(entity.getEquipmentId(), EquipmentMaintenanceStatus.NORMAL.name());
                break;
        }
        request.setValues(values);
        // 完成流程任务
        Result result = flowTaskService.complete(request);
        if (!result.isSuccess()) {
            throw new JeecgBootException("审批失败,请刷新查看!");
        }
        //保存工单
        eamThirdMaintenanceOrderMapper.updateById(entity);
        return entity;
    }
    private boolean isUserAuthorized(FlowMyBusiness flowMyBusiness, LoginUser user) {
        List<String> todoUsers = JSON.parseArray(flowMyBusiness.getTodoUsers(), String.class);
        return todoUsers != null && todoUsers.contains(user.getUsername());
lxzn-module-eam/src/main/java/org/jeecg/modules/eam/service/impl/EamWeekMaintenanceOrderServiceImpl.java
@@ -356,14 +356,16 @@
        }
        //流程变量
        Map<String, Object> values = new HashMap<>();
        List<UserSelector> userSelectors;
        List<String> userApprovalList;
        switch (status) {
            case UNDER_MAINTENANCE:
                //执行完成
                List<UserSelector> userSelectors = sysUserService.selectOperatorList(equipment.getEquipmentCode(), equipment.getOrgId(), BusinessCodeConst.PCR0003);
                userSelectors = sysUserService.selectOperatorList(equipment.getEquipmentCode(), equipment.getOrgId(), BusinessCodeConst.PCR0003);
                if (CollectionUtil.isEmpty(userSelectors)) {
                    throw new JeecgBootException("设备未分配给班组长,无法进入下级审批!");
                }
                List<String> userApprovalList = userSelectors.stream().map(UserSelector::getUsername).collect(Collectors.toList());
                userApprovalList = userSelectors.stream().map(UserSelector::getUsername).collect(Collectors.toList());
                values.put("dataId", entity.getId());
                values.put("organization", "周保执行结束");
                values.put("comment", "周保执行结束");
lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/apithird/business/service/IFlowMyBusinessService.java
@@ -2,6 +2,8 @@
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.modules.flowable.apithird.business.entity.FlowMyBusiness;
import java.util.List;
/**
 * @Description: 流程业务扩展表
 * @Author: jeecg-boot
@@ -17,9 +19,23 @@
    FlowMyBusiness getFlowMyBusiness(String instanceId);
    /**
     * 根据流程实例id 获取 流程实例
     * @param instanceId 流程实例id
     * @return
     */
    FlowMyBusiness getFlowMyBusiness(String instanceId, String taskId);
    /**
     * 获取流程实例
     * @param dataId 业务Id
     * @return
     */
    FlowMyBusiness selectByDataId(String dataId);
    /**
     * 获取流程实例 多实例并行,存在多条记录
     * @param dataId
     * @return
     */
    List<FlowMyBusiness> selectListByDataId(String dataId);
}
lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/apithird/business/service/impl/FlowMyBusinessServiceImpl.java
@@ -5,6 +5,7 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.collections4.CollectionUtils;
import org.flowable.engine.HistoryService;
import org.flowable.engine.history.HistoricActivityInstance;
import org.jeecg.modules.flowable.apithird.business.dto.FlowMyBusinessDto;
@@ -18,6 +19,7 @@
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.Date;
import java.util.List;
@@ -37,14 +39,14 @@
    public HistoricActivityInstance getPreviousNode(String taskId) {
        // 获取当前任务的执行实例 ID
        String executionId = historyService.createHistoricTaskInstanceQuery()
        String processInstanceId = historyService.createHistoricTaskInstanceQuery()
                .taskId(taskId)
                .singleResult()
                .getExecutionId();
                .getProcessInstanceId();
        // 查询历史活动实例
        List<HistoricActivityInstance> historicActivityInstances = historyService.createHistoricActivityInstanceQuery()
                .executionId(executionId)
                .processInstanceId(processInstanceId)
                .activityType("userTask")
                .finished()
                .orderByHistoricActivityInstanceEndTime()
@@ -135,9 +137,28 @@
    }
    @Override
    public FlowMyBusiness getFlowMyBusiness(String instanceId, String taskId) {
        List<FlowMyBusiness> businessList = super.list(
                new QueryWrapper<FlowMyBusiness>().eq("process_instance_id", instanceId).eq("task_id", taskId));
        return businessList.isEmpty() ? null : businessList.get(0);
    }
    @Override
    public FlowMyBusiness selectByDataId(String dataId) {
        List<FlowMyBusiness> businessList = super.list(
                new QueryWrapper<FlowMyBusiness>().eq("data_id", dataId));
        return businessList.isEmpty() ? null : businessList.get(0);
    }
    @Override
    public List<FlowMyBusiness> selectListByDataId(String dataId) {
        //如果保存数据前未调用必调的FlowCommonService.initActBusiness方法,就会有问题
        LambdaQueryWrapper<FlowMyBusiness> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(FlowMyBusiness::getDataId, dataId);
        List<FlowMyBusiness> list = flowMyBusinessMapper.selectList(queryWrapper);
        if(CollectionUtils.isEmpty(list)){
            return Collections.emptyList();
        }
        return list;
    }
}
lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/controller/FlowTaskController.java
@@ -5,6 +5,7 @@
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.modules.flowable.domain.dto.FlowNextDto;
import org.jeecg.modules.flowable.domain.dto.FlowTaskDto;
import org.jeecg.modules.flowable.domain.vo.FlowTaskVo;
import org.jeecg.modules.flowable.service.IFlowTaskService;
@@ -17,6 +18,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
/**
 * <p>工作流任务管理<p>
@@ -154,7 +156,7 @@
    @ApiOperation(value = "获取下一节点")
    @PostMapping(value = "/nextFlowNode")
    public Result getNextFlowNode(@RequestBody FlowTaskVo flowTaskVo) {
    public Result<List<FlowNextDto>> getNextFlowNode(@RequestBody FlowTaskVo flowTaskVo) {
        return flowTaskService.getNextFlowNode(flowTaskVo);
    }
lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/service/IFlowTaskService.java
@@ -3,6 +3,7 @@
import org.flowable.task.api.Task;
import org.jeecg.common.api.vo.Result;
import org.jeecg.modules.flowable.apithird.business.dto.FlowMyBusinessDto;
import org.jeecg.modules.flowable.domain.dto.FlowNextDto;
import org.jeecg.modules.flowable.domain.dto.FlowViewerDto;
import org.jeecg.modules.flowable.domain.vo.FlowTaskVo;
@@ -180,9 +181,13 @@
     * @param flowTaskVo 任务
     * @return
     */
    Result getNextFlowNode(FlowTaskVo flowTaskVo);
    Result<List<FlowNextDto>> getNextFlowNode(FlowTaskVo flowTaskVo);
    /**
     * 检查 并行任务节点是否都已完成
     * @param currentTaskId
     * @return
     */
    boolean checkParallelCompletion(String currentTaskId);
}
lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/service/impl/FlowDefinitionServiceImpl.java
@@ -1,6 +1,8 @@
package org.jeecg.modules.flowable.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
@@ -44,7 +46,6 @@
/**
 * 流程定义
 *
 */
@Service
public class FlowDefinitionServiceImpl extends FlowServiceFactory implements IFlowDefinitionService {
@@ -69,8 +70,8 @@
    /**
     * 流程定义列表
     *
     * @param pageNum  当前页码
     * @param pageSize 每页条数
     * @param pageNum        当前页码
     * @param pageSize       每页条数
     * @param flowProcDefDto
     * @return 流程定义分页列表数据
     */
@@ -83,19 +84,19 @@
                //.processDefinitionId("cs:5:15e953ed-4d09-11ec-85b8-e884a5deddfc")
                .orderByProcessDefinitionKey().asc().orderByProcessDefinitionVersion().desc();
        /*=====参数=====*/
        if (StrUtil.isNotBlank(flowProcDefDto.getName())){
            processDefinitionQuery.processDefinitionNameLike("%"+flowProcDefDto.getName()+"%");
        if (StrUtil.isNotBlank(flowProcDefDto.getName())) {
            processDefinitionQuery.processDefinitionNameLike("%" + flowProcDefDto.getName() + "%");
        }
        if (StrUtil.isNotBlank(flowProcDefDto.getCategory())){
        if (StrUtil.isNotBlank(flowProcDefDto.getCategory())) {
            processDefinitionQuery.processDefinitionCategory(flowProcDefDto.getCategory());
        }
        if (flowProcDefDto.getSuspensionState() == 1){
        if (flowProcDefDto.getSuspensionState() == 1) {
            processDefinitionQuery.active();
        }
        if (StrUtil.isNotBlank(flowProcDefDto.getKey())){
        if (StrUtil.isNotBlank(flowProcDefDto.getKey())) {
            processDefinitionQuery.processDefinitionKey(flowProcDefDto.getKey());
        }
        if (flowProcDefDto.getIsLastVersion() == 1){
        if (flowProcDefDto.getIsLastVersion() == 1) {
            processDefinitionQuery.latestVersion();
        }
        /*============*/
@@ -149,7 +150,7 @@
    @Override
    public Result readXmlByDataId(String dataId) throws IOException {
        LambdaQueryWrapper<FlowMyBusiness> flowMyBusinessLambdaQueryWrapper = new LambdaQueryWrapper<>();
        flowMyBusinessLambdaQueryWrapper.eq(FlowMyBusiness::getDataId,dataId)
        flowMyBusinessLambdaQueryWrapper.eq(FlowMyBusiness::getDataId, dataId)
        ;
        //如果保存数据前未调用必调的FlowCommonService.initActBusiness方法,就会有问题
        FlowMyBusiness business = flowMyBusinessService.getOne(flowMyBusinessLambdaQueryWrapper);
@@ -201,6 +202,7 @@
        InputStream in = processDiagramGenerator.generateDiagram(bpmnModel, "png", activityIds, flows, engConf.getActivityFontName(), engConf.getLabelFontName(), engConf.getAnnotationFontName(), engConf.getClassLoader(), 1.0, true);
        return in;
    }
    /**
     * 读取xml
     *
@@ -232,7 +234,7 @@
     * 根据流程定义ID启动流程实例
     *
     * @param procDefKey 流程定义Id
     * @param variables 流程变量
     * @param variables  流程变量
     * @return
     */
    @Override
@@ -241,9 +243,10 @@
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey(procDefKey)
                .latestVersion().singleResult();
        Result result = startProcessInstanceById(processDefinition.getId(),variables);
        Result result = startProcessInstanceById(processDefinition.getId(), variables);
        return result;
    }
    /**
     * 根据流程定义ID启动流程实例
     *
@@ -254,28 +257,28 @@
    @Override
    @Transactional
    public Result<?> startProcessInstanceById(String procDefId, Map<String, Object> variables) {
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                    .processDefinitionId(procDefId)
                    .singleResult();
            if (Objects.nonNull(processDefinition) && processDefinition.isSuspended()) {
                return Result.error("流程已被挂起,请先激活流程");
            }
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionId(procDefId)
                .singleResult();
        if (Objects.nonNull(processDefinition) && processDefinition.isSuspended()) {
            return Result.error("流程已被挂起,请先激活流程");
        }
//           variables.put("skip", true);
//           variables.put(ProcessConstants.FLOWABLE_SKIP_EXPRESSION_ENABLED, true);
            // 设置流程发起人Id到流程中
            SysUser sysUser = iFlowThirdService.getLoginUser();
            identityService.setAuthenticatedUserId(sysUser.getUsername());
            variables.put(ProcessConstants.PROCESS_INITIATOR, sysUser.getUsername());
            ProcessInstance processInstance = runtimeService.startProcessInstanceById(procDefId, variables);
            // 给第一步申请人节点设置任务执行人和意见
            Task task = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).active().singleResult();
            if (Objects.nonNull(task)) {
                taskService.addComment(task.getId(), processInstance.getProcessInstanceId(), FlowComment.NORMAL.getType(), variables.get("organization").toString());
                taskService.setAssignee(task.getId(), sysUser.getUsername());
                task.setDescription(variables.get("organization").toString());
                //taskService.complete(task.getId(), variables);
            }
            //设置所有申请人
        // 设置流程发起人Id到流程中
        SysUser sysUser = iFlowThirdService.getLoginUser();
        identityService.setAuthenticatedUserId(sysUser.getUsername());
        variables.put(ProcessConstants.PROCESS_INITIATOR, sysUser.getUsername());
        ProcessInstance processInstance = runtimeService.startProcessInstanceById(procDefId, variables);
        // 给第一步申请人节点设置任务执行人和意见
        Task task = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).active().singleResult();
        if (Objects.nonNull(task)) {
            taskService.addComment(task.getId(), processInstance.getProcessInstanceId(), FlowComment.NORMAL.getType(), variables.get("organization").toString());
            taskService.setAssignee(task.getId(), sysUser.getUsername());
            task.setDescription(variables.get("organization").toString());
            //taskService.complete(task.getId(), variables);
        }
        //设置所有申请人
        /*======================todo 启动之后  回调以及关键数据保存======================*/
        //业务数据id
@@ -283,77 +286,146 @@
        //如果保存数据前未调用必调的FlowCommonService.initActBusiness方法,就会有问题
        FlowMyBusiness business = flowMyBusinessService.getByDataId(dataId);
        //设置数据
        FlowNextDto nextFlowNode = flowTaskService.getNextFlowNode(task.getId(), variables);
        List<FlowNextDto> nextFlowNodeList = flowTaskService.getNextFlowNode(task.getId(), variables);
        taskService.complete(task.getId(), variables);
        //下一个实例节点  多实例会是一个list,随意取一个即可  数组中定义Key是一致的
        //Task task2 = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).active().singleResult();
        List<Task> task2List = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).active().list();
        Task task2 = null;
        if(task2List.size()>0) task2 = task2List.get(0);
        String doneUsers = business.getDoneUsers();
        // 处理过流程的人
        JSONArray doneUserList = new JSONArray();
        if (StrUtil.isNotBlank(doneUsers)){
        if (StrUtil.isNotBlank(doneUsers)) {
            doneUserList = JSON.parseArray(doneUsers);
        }
        if (!doneUserList.contains(sysUser.getUsername())){
        if (!doneUserList.contains(sysUser.getUsername())) {
            doneUserList.add(sysUser.getUsername());
        }
        if (nextFlowNode!=null){
            //**有下一个节点
            UserTask nextTask = nextFlowNode.getUserTask();
            //能够处理下个节点的候选人
            List<SysUser> nextFlowNodeUserList = nextFlowNode.getUserList();
            List<String> collect_username = nextFlowNodeUserList.stream().map(SysUser::getUsername).collect(Collectors.toList());
            //spring容器类名
            String serviceImplName = business.getServiceImplName();
            FlowCallBackServiceI flowCallBackService = (FlowCallBackServiceI) SpringContextUtils.getBean(serviceImplName);
            List<String> beforeParamsCandidateUsernames = flowCallBackService.flowCandidateUsernamesOfTask(task2.getTaskDefinitionKey(), variables);
            business.setProcessDefinitionId(procDefId)
                    .setProcessInstanceId(processInstance.getProcessInstanceId())
////                    .setActStatus(ActStatus.start)
                    .setProposer(sysUser.getUsername())
                    .setTaskId(task2.getId())
                    .setTaskName(nextTask.getName())
                    .setTaskNameId(nextTask.getId())
                    .setPriority(nextTask.getPriority())
                    .setDoneUsers(doneUserList.toJSONString());
            if (CollUtil.isNotEmpty(beforeParamsCandidateUsernames)){
                // 删除后重写
                for (Task task2One : task2List) {
                    for (String oldUser : collect_username) {
                        taskService.deleteCandidateUser(task2One.getId(),oldUser);
                    }
                }
                // 业务层有指定候选人,覆盖
                for (Task task2One : task2List) {
                    for (String newUser : beforeParamsCandidateUsernames) {
                        taskService.addCandidateUser(task2One.getId(),newUser);
                    }
                }
                business.setTodoUsers(JSON.toJSONString(beforeParamsCandidateUsernames));
            }else {
                // 业务层没有指定候选人,直接覆盖
                business.setTodoUsers(JSON.toJSONString(collect_username));
            }
        } else {
        //    **没有下一个节点,流程已经结束了
        if (CollectionUtil.isEmpty(nextFlowNodeList)) {
            //    **没有下一个节点,流程已经结束了
            business.setProcessDefinitionId(procDefId)
                    .setProcessInstanceId(processInstance.getProcessInstanceId())
//                    .setActStatus(ActStatus.pass)
                    .setProposer(sysUser.getUsername())
                    .setDoneUsers(doneUserList.toJSONString())
            ;
            flowMyBusinessService.updateById(business);
        } else if (nextFlowNodeList.size() == 1) {
            //下个节点只有一个
            FlowNextDto nextFlowNode = nextFlowNodeList.get(0);
            UserTask nextTask = nextFlowNode.getUserTask();
            Task task2 = null;
            Optional<Task> first = task2List.stream().filter(t -> t.getTaskDefinitionKey().equals(nextTask.getId())).findFirst();
            if (first.isPresent()) {
                task2 = first.get();
            }
            if (task2 != null) {
                //能够处理下个节点的候选人
                List<SysUser> nextFlowNodeUserList = nextFlowNode.getUserList();
                List<String> collect_username = nextFlowNodeUserList.stream().map(SysUser::getUsername).collect(Collectors.toList());
                //spring容器类名
                String serviceImplName = business.getServiceImplName();
                FlowCallBackServiceI flowCallBackService = (FlowCallBackServiceI) SpringContextUtils.getBean(serviceImplName);
                List<String> beforeParamsCandidateUsernames = flowCallBackService.flowCandidateUsernamesOfTask(task2.getTaskDefinitionId(), variables);
                business.setProcessDefinitionId(procDefId)
                        .setProcessInstanceId(processInstance.getProcessInstanceId())
////                    .setActStatus(ActStatus.start)
                        .setProposer(sysUser.getUsername())
                        .setTaskId(task2.getId())
                        .setTaskName(nextTask.getName())
                        .setTaskNameId(nextTask.getId())
                        .setPriority(nextTask.getPriority())
                        .setDoneUsers(doneUserList.toJSONString());
                if (CollUtil.isNotEmpty(beforeParamsCandidateUsernames)) {
                    // 删除后重写
                    for (String oldUser : collect_username) {
                        taskService.deleteCandidateUser(task2.getId(), oldUser);
                    }
                    // 业务层有指定候选人,覆盖
                    for (String newUser : beforeParamsCandidateUsernames) {
                        taskService.addCandidateUser(task2.getId(), newUser);
                    }
                    business.setTodoUsers(JSON.toJSONString(beforeParamsCandidateUsernames));
                } else {
                    // 业务层没有指定候选人,直接覆盖
                    business.setTodoUsers(JSON.toJSONString(collect_username));
                }
                flowMyBusinessService.updateById(business);
            }
        } else {
            for (FlowNextDto nextFlowNode : nextFlowNodeList) {
                //**有下一个节点
                UserTask nextTask = nextFlowNode.getUserTask();
                Task task2 = null;
                Optional<Task> first = task2List.stream().filter(t -> t.getTaskDefinitionKey().equals(nextTask.getId())).findFirst();
                if (first.isPresent()) {
                    task2 = first.get();
                }
                if (task2 != null) {
                    //新的业务流程节点
                    FlowMyBusiness newBusiness =  BeanUtil.copyProperties(business, FlowMyBusiness.class, "id");
                    //能够处理下个节点的候选人
                    List<SysUser> nextFlowNodeUserList = nextFlowNode.getUserList();
                    List<String> collect_username = nextFlowNodeUserList.stream().map(SysUser::getUsername).collect(Collectors.toList());
                    //spring容器类名
                    String serviceImplName = newBusiness.getServiceImplName();
                    FlowCallBackServiceI flowCallBackService = (FlowCallBackServiceI) SpringContextUtils.getBean(serviceImplName);
                    List<String> beforeParamsCandidateUsernames = flowCallBackService.flowCandidateUsernamesOfTask(task2.getTaskDefinitionId(), variables);
                    newBusiness.setProcessDefinitionId(procDefId)
                            .setProcessInstanceId(processInstance.getProcessInstanceId())
////                    .setActStatus(ActStatus.start)
                            .setProposer(sysUser.getUsername())
                            .setTaskId(task2.getId())
                            .setTaskName(nextTask.getName())
                            .setTaskNameId(nextTask.getId())
                            .setPriority(nextTask.getPriority())
                            .setDoneUsers(doneUserList.toJSONString());
                    if (CollUtil.isNotEmpty(beforeParamsCandidateUsernames)) {
                        // 删除后重写
                        for (Task task2One : task2List) {
                            for (String oldUser : beforeParamsCandidateUsernames) {
                                taskService.deleteCandidateUser(task2One.getId(), oldUser);
                            }
                        }
                        // 业务层有指定候选人,覆盖
                        for (Task task2One : task2List) {
                            for (String newUser : beforeParamsCandidateUsernames) {
                                taskService.addCandidateUser(task2One.getId(), newUser);
                            }
                        }
                        newBusiness.setTodoUsers(JSON.toJSONString(beforeParamsCandidateUsernames));
                    } else {
                        // 业务层没有指定候选人,直接覆盖
                        newBusiness.setTodoUsers(JSON.toJSONString(collect_username));
                        // 删除后重写
                        for (Task task2One : task2List) {
                            for (String oldUser : collect_username) {
                                taskService.deleteCandidateUser(task2One.getId(), oldUser);
                            }
                        }
                        // 业务层有指定候选人,覆盖
                        for (Task task2One : task2List) {
                            for (String newUser : collect_username) {
                                taskService.addCandidateUser(task2One.getId(), newUser);
                            }
                        }
                    }
                    flowMyBusinessService.save(newBusiness);
                }
            }
            //删除原有的业务数据
            flowMyBusinessService.removeById(business.getId());
        }
        flowMyBusinessService.updateById(business);
        //spring容器类名
        String serviceImplName = business.getServiceImplName();
        FlowCallBackServiceI flowCallBackService = (FlowCallBackServiceI) SpringContextUtils.getBean(serviceImplName);
        // 流程处理完后,进行回调业务层
        business.setValues(variables);
        if (flowCallBackService!=null)flowCallBackService.afterFlowHandle(business);
        if (flowCallBackService != null) {
            flowCallBackService.afterFlowHandle(business);
        }
        return Result.OK("流程启动成功");
    }
@@ -363,13 +435,13 @@
        flowMyBusinessLambdaQueryWrapper.eq(FlowMyBusiness::getDataId, dataId)
        ;
        FlowMyBusiness business = flowMyBusinessService.getOne(flowMyBusinessLambdaQueryWrapper);
        if (business==null){
            return Result.error("未找到dataId:"+dataId);
        if (business == null) {
            return Result.error("未找到dataId:" + dataId);
        }
        if (StrUtil.isNotBlank(business.getProcessDefinitionId())){
            return this.startProcessInstanceById(business.getProcessDefinitionId(),variables);
        if (StrUtil.isNotBlank(business.getProcessDefinitionId())) {
            return this.startProcessInstanceById(business.getProcessDefinitionId(), variables);
        }
        return this.startProcessInstanceByKey(business.getProcessDefinitionKey(),variables);
        return this.startProcessInstanceByKey(business.getProcessDefinitionKey(), variables);
    }
lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/service/impl/FlowTaskServiceImpl.java
@@ -1,5 +1,6 @@
package org.jeecg.modules.flowable.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
@@ -68,6 +69,7 @@
import java.util.stream.Collectors;
/**
 *
 **/
@Service
@Slf4j
@@ -78,6 +80,7 @@
    private IFlowThirdService iFlowThirdService;
    @Autowired
    FlowMyBusinessServiceImpl flowMyBusinessService;
    /**
     * 完成任务
     *
@@ -87,23 +90,23 @@
    @Override
    public Result complete(FlowTaskVo taskVo) {
        Task task = taskService.createTaskQuery().taskId(taskVo.getTaskId()).singleResult();
        if (Objects.isNull(task)){
        if (Objects.isNull(task)) {
            return Result.error("任务不存在");
        }
        if(StringUtils.isNotEmpty(taskVo.getComment())){
        if (StringUtils.isNotEmpty(taskVo.getComment())) {
            task.setDescription(taskVo.getComment());
            taskService.saveTask(task);
        }
        SysUser loginUser = iFlowThirdService.getLoginUser();
        //判断用户是否有权限
        if (!task.getAssignee().equals(loginUser.getUsername())){
        if (!task.getAssignee().equals(loginUser.getUsername())) {
            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());
        } else {
            System.out.println("taskVo.getTaskId()--->taskVo.getInstanceId()--->FlowComment.NORMAL.getType()--->taskVo.getComment()"+taskVo.getTaskId() + "---" + taskVo.getInstanceId() + "---" + FlowComment.NORMAL.getType() + "---"+taskVo.getComment() );
            System.out.println("taskVo.getTaskId()--->taskVo.getInstanceId()--->FlowComment.NORMAL.getType()--->taskVo.getComment()" + taskVo.getTaskId() + "---" + taskVo.getInstanceId() + "---" + FlowComment.NORMAL.getType() + "---" + taskVo.getComment());
            taskService.addComment(taskVo.getTaskId(), taskVo.getInstanceId(), FlowComment.NORMAL.getType(), taskVo.getComment());
            taskService.setAssignee(taskVo.getTaskId(), loginUser.getUsername());
        }
@@ -111,20 +114,22 @@
        //业务数据id
        String dataId = taskVo.getDataId();
        //如果保存数据前未调用必调的FlowCommonService.initActBusiness方法,就会有问题
        FlowMyBusiness business = flowMyBusinessService.getByDataId(dataId);
        FlowMyBusiness business = flowMyBusinessService.getFlowMyBusiness(taskVo.getInstanceId(), taskVo.getTaskId());
        //spring容器类名
        String serviceImplName = business.getServiceImplName();
        FlowCallBackServiceI flowCallBackService = (FlowCallBackServiceI) SpringContextUtils.getBean(serviceImplName);
        // 流程变量
        Map<String, Object> flowBeforeParamsValues = flowCallBackService.flowValuesOfTask(business.getTaskNameId(),taskVo.getValues());
        Map<String, Object> flowBeforeParamsValues = flowCallBackService.flowValuesOfTask(business.getTaskNameId(), taskVo.getValues());
        //设置数据
        Map<String, Object> values = taskVo.getValues();
        if (MapUtil.isNotEmpty(flowBeforeParamsValues)){
        //    业务层有设置变量,使用业务层的变量
        if (MapUtil.isNotEmpty(flowBeforeParamsValues)) {
            //    业务层有设置变量,使用业务层的变量
            values = flowBeforeParamsValues;
        }
        FlowNextDto nextFlowNode = this.getNextFlowNode(task.getId(), values);
        //并行网关 多任务
        List<FlowNextDto> nextFlowNodeList = this.getNextFlowNode(task.getId(), values);
        //下一个实例节点
        if (DelegationState.PENDING.equals(task.getDelegationState())) {
            taskService.resolveTask(taskVo.getTaskId(), values);
@@ -132,140 +137,218 @@
            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)){
        if (StrUtil.isNotBlank(doneUsers)) {
            doneUserList = JSON.parseArray(doneUsers);
        }
        if (!doneUserList.contains(loginUser.getUsername())){
        if (!doneUserList.contains(loginUser.getUsername())) {
            doneUserList.add(loginUser.getUsername());
        }
        if (task2!=null && task.getTaskDefinitionKey().equals(task2.getTaskDefinitionKey())){
        //    * 当前节点是会签节点,没有走完
            business.setTaskId(task2.getId())
//                    .setActStatus(ActStatus.doing)
        if (CollectionUtils.isEmpty(nextFlowNodeList)) {
            //    **没有下一个节点,流程已经结束了
            business
                    .setDoneUsers(doneUserList.toJSONString())
                    .setTodoUsers("")
                    .setTaskId("")
                    .setTaskNameId("")
                    .setTaskName("")
            ;
            String todoUsersStr = business.getTodoUsers();
            JSONArray todosArr = JSON.parseArray(todoUsersStr);
            // 删除后重写
            for (Task task2One : task2List) {
                for (Object oldUser : todosArr) {
                    taskService.deleteCandidateUser(task2One.getId(),oldUser.toString());
            flowMyBusinessService.updateById(business);
        }
        else if (nextFlowNodeList.size() == 1) {
            FlowNextDto nextFlowNode = nextFlowNodeList.get(0);
            UserTask nextTask = nextFlowNode.getUserTask();
            Task task2 = null;
            Optional<Task> first = task2List.stream().filter(t -> t.getTaskDefinitionKey().equals(nextTask.getId())).findFirst();
            task2 = first.orElseGet(() -> task2List.get(0));
            if (task2 != null) {
                // 下个节点候选人
                List<String> beforeParamsCandidateUsernames = flowCallBackService.flowCandidateUsernamesOfTask(task2.getTaskDefinitionKey(), taskVo.getValues());
                List<String> candidateUsers = taskVo.getCandidateUsers();
                if (CollUtil.isNotEmpty(candidateUsers)) {
                    //    前端传入候选人 覆盖
                    beforeParamsCandidateUsernames = candidateUsers;
                }
            }
            // 重写
            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) {
                if (task.getTaskDefinitionKey().equals(task2.getTaskDefinitionKey())) {
                    //多实例 会签 TODO
                    //    * 当前节点是会签节点,没有走完
                    business.setTaskId(task2.getId())
//                    .setActStatus(ActStatus.doing)
                            .setDoneUsers(doneUserList.toJSONString())
                    ;
                    String todoUsersStr = business.getTodoUsers();
                    JSONArray todosArr = JSON.parseArray(todoUsersStr);
                    // 删除后重写
                    for (Object oldUser : todosArr) {
                        taskService.addCandidateUser(task2One.getId(),oldUser.toString());
                        taskService.deleteCandidateUser(task2.getId(), oldUser.toString());
                    }
                    // 重写
                    if (CollUtil.isNotEmpty(beforeParamsCandidateUsernames)) {
                        beforeParamsCandidateUsernames.remove(loginUser.getUsername());
                        // 业务层有指定候选人,覆盖
                        for (String newUser : beforeParamsCandidateUsernames) {
                            taskService.addCandidateUser(task2.getId(), newUser);
                        }
                        business.setTodoUsers(JSON.toJSONString(beforeParamsCandidateUsernames));
                    } else {
                        todosArr.remove(loginUser.getUsername());
                        for (Object oldUser : todosArr) {
                            taskService.addCandidateUser(task2.getId(), oldUser.toString());
                        }
                        business.setTodoUsers(todosArr.toJSONString());
                    }
                } else {
                    //能够处理下个节点的候选人
                    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
                            .setTaskId(task2.getId())
//                        .setActStatus(ActStatus.doing)
                            .setTaskNameId(nextTask.getId())
                            .setTaskName(nextTask.getName())
                            .setPriority(nextTask.getPriority())
                            .setDoneUsers(doneUserList.toJSONString())
                            .setTodoUsers(JSON.toJSONString(collect_username))
                    ;
                    // 删除后重写
                    for (String oldUser : collect_username) {
                        taskService.deleteCandidateUser(task2.getId(), oldUser);
                    }
                    if (CollUtil.isNotEmpty(beforeParamsCandidateUsernames)) {
                        // 前端没有传入候选人 && 业务层有指定候选人,覆盖
                        for (String newUser : beforeParamsCandidateUsernames) {
                            taskService.addCandidateUser(task2.getId(), newUser);
                        }
                        business.setTodoUsers(JSON.toJSONString(beforeParamsCandidateUsernames));
                    } else {
                        for (String oldUser : collect_username) {
                            taskService.addCandidateUser(task2.getId(), oldUser);
                        }
                        business.setTodoUsers(JSON.toJSONString(collect_username));
                    }
                }
                business.setTodoUsers(todosArr.toJSONString());
            }
        } else {
        //    * 下一节点是会签节点 或 普通用户节点,逻辑一致
            if (nextFlowNode!=null){
            flowMyBusinessService.updateById(business);
        }
        else {
            for(FlowNextDto nextFlowNode : nextFlowNodeList) {
                //**有下一个节点
                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;
                Task task2 = null;
                Optional<Task> first = task2List.stream().filter(t -> t.getTaskDefinitionKey().equals(nextTask.getId())).findFirst();
                if (first.isPresent()) {
                    task2 = first.get();
                }
                business
                        .setTaskId(task2.getId())
//                        .setActStatus(ActStatus.doing)
                        .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 (task2 != null) {
                    //新的业务流程节点
                    FlowMyBusiness newBusiness =  BeanUtil.copyProperties(business, FlowMyBusiness.class, "id");
                    // 下个节点候选人
                    List<String> beforeParamsCandidateUsernames = flowCallBackService.flowCandidateUsernamesOfTask(task2.getTaskDefinitionKey(), taskVo.getValues());
                    List<String> candidateUsers = taskVo.getCandidateUsers();
                    if (CollUtil.isNotEmpty(candidateUsers)) {
                        //    前端传入候选人 覆盖
                        beforeParamsCandidateUsernames = candidateUsers;
                    }
                }
                if (CollUtil.isEmpty(candidateUsers)&&CollUtil.isNotEmpty(beforeParamsCandidateUsernames)){
                    // 前端没有传入候选人 && 业务层有指定候选人,覆盖
                    for (Task task2One : task2List) {
                        for (String newUser : beforeParamsCandidateUsernames) {
                            taskService.addCandidateUser(task2One.getId(),newUser);
                    if (task.getTaskDefinitionKey().equals(task2.getTaskDefinitionKey())) {
                        //多实例 会签 TODO
                        //    * 当前节点是会签节点,没有走完
                        newBusiness.setTaskId(task2.getId())
//                    .setActStatus(ActStatus.doing)
                                .setDoneUsers(doneUserList.toJSONString())
                        ;
                        String todoUsersStr = business.getTodoUsers();
                        JSONArray todosArr = JSON.parseArray(todoUsersStr);
                        // 删除后重写
                        for (Object oldUser : todosArr) {
                            taskService.deleteCandidateUser(task2.getId(), oldUser.toString());
                        }
                    }
                    business.setTodoUsers(JSON.toJSONString(beforeParamsCandidateUsernames));
                } else {
                    for (Task task2One : task2List) {
                        for (String oldUser : collect_username) {
                            taskService.addCandidateUser(task2One.getId(),oldUser);
                        // 重写
                        if (CollUtil.isNotEmpty(beforeParamsCandidateUsernames)) {
                            beforeParamsCandidateUsernames.remove(loginUser.getUsername());
                            // 业务层有指定候选人,覆盖
                            for (String newUser : beforeParamsCandidateUsernames) {
                                taskService.addCandidateUser(task2.getId(), newUser);
                            }
                            newBusiness.setTodoUsers(JSON.toJSONString(beforeParamsCandidateUsernames));
                        } else {
                            todosArr.remove(loginUser.getUsername());
                            for (Object oldUser : todosArr) {
                                taskService.addCandidateUser(task2.getId(), oldUser.toString());
                            }
                            newBusiness.setTodoUsers(todosArr.toJSONString());
                        }
                    }
                }
            } else {
                //    **没有下一个节点,流程已经结束了
                business
                        .setDoneUsers(doneUserList.toJSONString())
                        .setTodoUsers("")
                        .setTaskId("")
                        .setTaskNameId("")
                        .setTaskName("")
                ;
                    } else {
                        //能够处理下个节点的候选人
                        List<SysUser> nextFlowNodeUserList = nextFlowNode.getUserList();
                        List<String> collect_username = nextFlowNodeUserList.stream().map(SysUser::getUsername).collect(Collectors.toList());
                        if (CollUtil.isNotEmpty(candidateUsers)) {
                            //    前端传入候选人
                            collect_username = candidateUsers;
                        }
                        newBusiness
                                .setTaskId(task2.getId())
//                        .setActStatus(ActStatus.doing)
                                .setTaskNameId(nextTask.getId())
                                .setTaskName(nextTask.getName())
                                .setPriority(nextTask.getPriority())
                                .setDoneUsers(doneUserList.toJSONString())
                                .setTodoUsers(JSON.toJSONString(collect_username))
                        ;
                        // 删除后重写
                        for (String oldUser : collect_username) {
                            taskService.deleteCandidateUser(task2.getId(), oldUser);
                        }
                        if (CollUtil.isNotEmpty(beforeParamsCandidateUsernames)) {
                            // 前端没有传入候选人 && 业务层有指定候选人,覆盖
                            for (String newUser : beforeParamsCandidateUsernames) {
                                taskService.addCandidateUser(task2.getId(), newUser);
                            }
                            newBusiness.setTodoUsers(JSON.toJSONString(beforeParamsCandidateUsernames));
                        } else {
                            for (String oldUser : collect_username) {
                                taskService.addCandidateUser(task2.getId(), oldUser);
                            }
                            newBusiness.setTodoUsers(JSON.toJSONString(collect_username));
                        }
                    }
                    flowMyBusinessService.save(newBusiness);
                }
                flowMyBusinessService.updateById(business);
            }
            //删除原有的业务数据
            flowMyBusinessService.removeById(business.getId());
        }
        flowMyBusinessService.updateById(business);
        // 流程处理完后,进行回调业务层
        business.setValues(values);
        if (flowCallBackService!=null)flowCallBackService.afterFlowHandle(business);
        if (flowCallBackService != null) {
            flowCallBackService.afterFlowHandle(business);
        }
        return Result.OK();
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result completeByDateId(FlowTaskVo flowTaskVo){
    public Result completeByDateId(FlowTaskVo flowTaskVo) {
        return this.complete(flowTaskVo);
    }
    @Override
    public void taskRejectByDataId(FlowTaskVo flowTaskVo){
    public void taskRejectByDataId(FlowTaskVo flowTaskVo) {
        FlowMyBusiness business = flowMyBusinessService.getByDataId(flowTaskVo.getDataId());
        flowTaskVo.setTaskId(business.getTaskId());
        this.taskReject(flowTaskVo);
    }
    /**
     * 驳回任务
     *
@@ -387,7 +470,7 @@
            /*======================驳回  回调以及关键数据保存======================*/
            //业务数据id
            String dataId = flowTaskVo.getDataId();
            if (dataId==null) return;
            if (dataId == null) return;
            //如果保存数据前未调用必调的FlowCommonService.initActBusiness方法,就会有问题
            FlowMyBusiness business = flowMyBusinessService.getByDataId(dataId);
            // 驳回到了上一个节点等待处理
@@ -397,21 +480,21 @@
            String serviceImplName = business.getServiceImplName();
            FlowCallBackServiceI flowCallBackService = (FlowCallBackServiceI) SpringContextUtils.getBean(serviceImplName);
            Map<String, Object> values = flowTaskVo.getValues();
            if (values ==null){
            if (values == null) {
                values = MapUtil.newHashMap();
                values.put("dataId",dataId);
                values.put("dataId", dataId);
            } else {
                values.put("dataId",dataId);
                values.put("dataId", dataId);
            }
            List<String> beforeParamsCandidateUsernames = flowCallBackService.flowCandidateUsernamesOfTask(task2.getTaskDefinitionKey(), values);
            //设置数据
            String doneUsers = business.getDoneUsers();
            // 处理过流程的人
            JSONArray doneUserList = new JSONArray();
            if (StrUtil.isNotBlank(doneUsers)){
            if (StrUtil.isNotBlank(doneUsers)) {
                doneUserList = JSON.parseArray(doneUsers);
            }
            if (!doneUserList.contains(loginUser.getUsername())){
            if (!doneUserList.contains(loginUser.getUsername())) {
                doneUserList.add(loginUser.getUsername());
            }
            business
@@ -432,31 +515,31 @@
                }
            }
            if (targetElement!=null){
            if (targetElement != null) {
                UserTask targetTask = (UserTask) targetElement;
                business.setPriority(targetTask.getPriority());
                if (StrUtil.equals(business.getTaskNameId(),ProcessConstants.START_NODE)){
                if (StrUtil.equals(business.getTaskNameId(), ProcessConstants.START_NODE)) {
                    //    开始节点。设置处理人为申请人
                    business.setTodoUsers(JSON.toJSONString(Lists.newArrayList(business.getProposer())));
                    taskService.setAssignee(business.getTaskId(),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)){
                    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);
                            taskService.deleteCandidateUser(task2One.getId(), oldUser);
                        }
                    }
                    if (CollUtil.isNotEmpty(beforeParamsCandidateUsernames)){
                        if (CollUtil.isNotEmpty(candidateUsers)){
                    if (CollUtil.isNotEmpty(beforeParamsCandidateUsernames)) {
                        if (CollUtil.isNotEmpty(candidateUsers)) {
                            beforeParamsCandidateUsernames = candidateUsers;
                        }
                        // 业务层有指定候选人,覆盖
@@ -477,9 +560,9 @@
            }
            flowMyBusinessService.updateById(business);
           // 流程处理完后,进行回调业务层
            // 流程处理完后,进行回调业务层
            business.setValues(values);
            if (flowCallBackService!=null) flowCallBackService.afterFlowHandle(business);
            if (flowCallBackService != null) flowCallBackService.afterFlowHandle(business);
        } catch (FlowableObjectNotFoundException e) {
            throw new CustomException("未找到流程实例,流程可能已发生变化");
        } catch (FlowableException e) {
@@ -487,13 +570,15 @@
        }
    }
    @Override
    public void taskReturnByDataId(FlowTaskVo flowTaskVo){
    public void taskReturnByDataId(FlowTaskVo flowTaskVo) {
        //如果保存数据前未调用必调的FlowCommonService.initActBusiness方法,就会有问题
        FlowMyBusiness business = flowMyBusinessService.getByDataId(flowTaskVo.getDataId());
        flowTaskVo.setTaskId(business.getTaskId());
        taskReturn(flowTaskVo);
    }
    /**
     * 退回任务
     *
@@ -574,7 +659,7 @@
            /*======================退回  回调以及关键数据保存======================*/
            //业务数据id
            String dataId = flowTaskVo.getDataId();
            if (dataId==null) return;
            if (dataId == null) return;
            //如果保存数据前未调用必调的FlowCommonService.initActBusiness方法,就会有问题
            FlowMyBusiness business = flowMyBusinessService.getByDataId(dataId);
            //spring容器类名
@@ -584,61 +669,61 @@
            String doneUsers = business.getDoneUsers();
            // 处理过流程的人
            JSONArray doneUserList = new JSONArray();
            if (StrUtil.isNotBlank(doneUsers)){
            if (StrUtil.isNotBlank(doneUsers)) {
                doneUserList = JSON.parseArray(doneUsers);
            }
            if (!doneUserList.contains(loginUser.getUsername())){
            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
                        .setTaskId(targetTask.getId())
            business
                    .setTaskId(targetTask.getId())
//                        .setActStatus(ActStatus.reject)
                        .setTaskNameId(targetTask.getTaskDefinitionKey())
                        .setTaskName(targetTask.getName())
                        .setPriority(targetTask.getPriority()+"")
                        .setDoneUsers(doneUserList.toJSONString())
                ;
            if (target!=null){
                    .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)){
                //    开始节点。设置处理人为申请人
                if (StrUtil.equals(business.getTaskNameId(), ProcessConstants.START_NODE)) {
                    //    开始节点。设置处理人为申请人
                    business.setTodoUsers(JSON.toJSONString(Lists.newArrayList(business.getProposer())));
                    taskService.setAssignee(business.getTaskId(),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)){
                    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);
                            taskService.deleteCandidateUser(task2One.getId(), oldUser);
                        }
                    }
                    Map<String, Object> values = flowTaskVo.getValues();
                    if (values==null){
                    if (values == null) {
                        values = MapUtil.newHashMap();
                        values.put("dataId",dataId);
                        values.put("dataId", dataId);
                    } else {
                        values.put("dataId",dataId);
                        values.put("dataId", dataId);
                    }
                    List<String> beforeParamsCandidateUsernames = flowCallBackService.flowCandidateUsernamesOfTask(targetTask.getTaskDefinitionKey(), values);
                    if (CollUtil.isNotEmpty(beforeParamsCandidateUsernames)){
                        if (CollUtil.isNotEmpty(candidateUsers)){
                    if (CollUtil.isNotEmpty(beforeParamsCandidateUsernames)) {
                        if (CollUtil.isNotEmpty(candidateUsers)) {
                            beforeParamsCandidateUsernames = candidateUsers;
                        }
                        // 业务层有指定候选人,覆盖
                        for (Task task2One : task2List) {
                            for (String newUser : beforeParamsCandidateUsernames) {
                                taskService.addCandidateUser(task2One.getId(),newUser);
                                taskService.addCandidateUser(task2One.getId(), newUser);
                            }
                        }
                        business.setTodoUsers(JSON.toJSONString(beforeParamsCandidateUsernames));
@@ -654,7 +739,7 @@
            flowMyBusinessService.updateById(business);
            // 流程处理完后,进行回调业务层
            business.setValues(flowTaskVo.getValues());
            if (flowCallBackService!=null) flowCallBackService.afterFlowHandle(business);
            if (flowCallBackService != null) flowCallBackService.afterFlowHandle(business);
        } catch (FlowableObjectNotFoundException e) {
            throw new CustomException("未找到流程实例,流程可能已发生变化");
        } catch (FlowableException e) {
@@ -671,15 +756,16 @@
    /**
     * 结束流程
     *
     * @param processInstanceId 流程实例 ID
     * @param deleteReason 定义删除原因
     * @param deleteReason      定义删除原因
     */
    public Result<?> end(String processInstanceId, String deleteReason) {
        try {
            // 强制结束流程实例
            runtimeService.deleteProcessInstance(processInstanceId, deleteReason);
            // 删除关联流程的业务
            FlowMyBusiness flowMyBusiness=flowMyBusinessService.getFlowMyBusiness(processInstanceId);
            FlowMyBusiness flowMyBusiness = flowMyBusinessService.getFlowMyBusiness(processInstanceId);
            flowMyBusinessService.removeById(flowMyBusiness.getId());
            System.out.println("Process instance with ID " + processInstanceId + " has been forcefully ended.");
        } catch (Exception e) {
@@ -740,7 +826,7 @@
    @Override
    public void deleteTask(FlowTaskVo flowTaskVo) {
        // todo 待确认删除任务是物理删除任务 还是逻辑删除,让这个任务直接通过?
        taskService.deleteTask(flowTaskVo.getTaskId(),flowTaskVo.getComment());
        taskService.deleteTask(flowTaskVo.getTaskId(), flowTaskVo.getComment());
    }
    /**
@@ -785,7 +871,7 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void assignTask(FlowTaskVo flowTaskVo) {
        taskService.setAssignee(flowTaskVo.getTaskId(),flowTaskVo.getAssignee());
        taskService.setAssignee(flowTaskVo.getTaskId(), flowTaskVo.getAssignee());
    }
    /**
@@ -803,7 +889,7 @@
                .startedBy(username)
                .orderByProcessInstanceStartTime()
                .desc();
        List<HistoricProcessInstance> historicProcessInstances = historicProcessInstanceQuery.listPage((pageNum - 1)*pageSize, pageSize);
        List<HistoricProcessInstance> historicProcessInstances = historicProcessInstanceQuery.listPage((pageNum - 1) * pageSize, pageSize);
        page.setTotal(historicProcessInstanceQuery.count());
        List<FlowTaskDto> flowList = new ArrayList<>();
        for (HistoricProcessInstance hisIns : historicProcessInstances) {
@@ -942,6 +1028,7 @@
    /**
     * 判断多个任务是否处于同一流程节点
     *
     * @param taskIds 逗号分隔的任务ID字符串
     * @return 统一结果封装
     */
@@ -1013,7 +1100,7 @@
                .taskAssignee(username)
                .orderByTaskCreateTime().desc();
        page.setTotal(taskQuery.count());
        List<Task> taskList = taskQuery.listPage((pageNum - 1)*pageSize, pageSize);
        List<Task> taskList = taskQuery.listPage((pageNum - 1) * pageSize, pageSize);
        List<FlowTaskDto> flowList = new ArrayList<>();
        for (Task task : taskList) {
            FlowTaskDto flowTask = new FlowTaskDto();
@@ -1040,7 +1127,7 @@
            List<String> departNamesByUsername = iFlowThirdService.getDepartNamesByUsername(historicProcessInstance.getStartUserId());
            flowTask.setStartUserId(startUser.getUsername());
            flowTask.setStartUserName(startUser.getRealname());
            flowTask.setStartDeptName(CollUtil.join(departNamesByUsername,","));
            flowTask.setStartDeptName(CollUtil.join(departNamesByUsername, ","));
            flowList.add(flowTask);
        }
@@ -1069,15 +1156,15 @@
                    .processInstanceId(flowTaskDto.getProcInsId())
                    .singleResult();
            SysUser startUser = iFlowThirdService.getUserByUsername(historicProcessInstance.getStartUserId());
            if (startUser!=null){
            if (startUser != null) {
                flowTaskDto.setStartUserId(startUser.getUsername());
                flowTaskDto.setStartUserName(startUser.getRealname());
            }
            List<String> departNamesByUsername = iFlowThirdService.getDepartNamesByUsername(historicProcessInstance.getStartUserId());
            flowTaskDto.setStartDeptName(CollUtil.join(departNamesByUsername,","));
            if (flowTaskDto.getTodoUsers() == null){
            flowTaskDto.setStartDeptName(CollUtil.join(departNamesByUsername, ","));
            if (flowTaskDto.getTodoUsers() == null) {
                flowTaskDto.setTodoUsers("");
            }else {
            } else {
                //去除[]
                flowTaskDto.setTodoUsers(flowTaskDto.getTodoUsers().replaceAll("\\[", "").replaceAll("\\]", ""));
                flowTaskDto.setTodoUsers(flowTaskDto.getTodoUsers().replaceAll("\"", ""));
@@ -1125,9 +1212,9 @@
                        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.setDeptName(CollUtil.join(departNamesByUsername, ","));
                        if (StrUtil.equals(histIns.getActivityId(), ProcessConstants.START_NODE)) {
                            //    开始节点,把候选人设置为发起人,这个值已被其他地方设置过,与实际办理人一致即可
                            flowTask.setCandidate(sysUser.getRealname());
                        }
                    }
@@ -1169,9 +1256,9 @@
        String serviceImplName = business.getServiceImplName();
        FlowCallBackServiceI flowCallBackService = (FlowCallBackServiceI) SpringContextUtils.getBean(serviceImplName);
        // 流程处理完后,进行回调业务层
        if (flowCallBackService!=null){
        if (flowCallBackService != null) {
            Object businessDataById = flowCallBackService.getBusinessDataById(dataId);
            map.put("formData",businessDataById);
            map.put("formData", businessDataById);
        }
        return Result.OK(map);
    }
@@ -1260,8 +1347,8 @@
                for (FlowViewerDto viewerDto : flowViewerList) {
                    String key = viewerDto.getKey();
                    if (key.equals(flowViewerDto.getKey())){
                    //    重复删除后面更新
                    if (key.equals(flowViewerDto.getKey())) {
                        //    重复删除后面更新
                        flowViewerList.remove(viewerDto);
                        break;
                    }
@@ -1276,7 +1363,7 @@
    @Override
    public List<FlowViewerDto> getFlowViewerByDataId(String dataId) {
        LambdaQueryWrapper<FlowMyBusiness> flowMyBusinessLambdaQueryWrapper = new LambdaQueryWrapper<>();
        flowMyBusinessLambdaQueryWrapper.eq(FlowMyBusiness::getDataId,dataId)
        flowMyBusinessLambdaQueryWrapper.eq(FlowMyBusiness::getDataId, dataId)
        ;
        //如果保存数据前未调用必调的FlowCommonService.initActBusiness方法,就会有问题
        FlowMyBusiness business = flowMyBusinessService.getOne(flowMyBusinessLambdaQueryWrapper);
@@ -1298,7 +1385,7 @@
                    String firstKey = stev.getId();
                    orderKeys.add(firstKey);
                    //顺序获取节点
                    this.appendKeys(orderKeys, firstKey,flowElements);
                    this.appendKeys(orderKeys, firstKey, flowElements);
                } catch (Exception e) {
                    break;
                }
@@ -1307,11 +1394,11 @@
            for (String key : orderKeys) {
                Optional<FlowViewerDto> any = flowViewers.stream().filter(o -> StrUtil.equals(o.getKey(), key)).findAny();
                if(any.isPresent()){
                if (any.isPresent()) {
                    FlowViewerDto viewerDto = any.get();
                    reflowViewers.add(viewerDto);
                    if (!viewerDto.isCompleted()){
                    //    已到正在等待执行的节点,后面的不要了
                    if (!viewerDto.isCompleted()) {
                        //    已到正在等待执行的节点,后面的不要了
                        break;
                    }
                }
@@ -1327,8 +1414,9 @@
    /**
     * 顺序抽取节点
     * @param orderKeys 容器
     * @param sourceKey 源
     *
     * @param orderKeys    容器
     * @param sourceKey    源
     * @param flowElements 所有的节点对象
     */
    private void appendKeys(List<String> orderKeys, String sourceKey, List<FlowElement> flowElements) {
@@ -1337,9 +1425,9 @@
                SequenceFlow sf = (SequenceFlow) flowElement;
                String sourceRef = sf.getSourceRef();
                String targetRef = sf.getTargetRef();
                if (sourceKey.equals(sourceRef)&&targetRef!=null){
                if (sourceKey.equals(sourceRef) && targetRef != null) {
                    orderKeys.add(targetRef);
                    this.appendKeys(orderKeys,targetRef,flowElements);
                    this.appendKeys(orderKeys, targetRef, flowElements);
                }
            } catch (Exception e) {
                continue;
@@ -1373,89 +1461,116 @@
     * @return
     */
    @Override
    public Result getNextFlowNode(FlowTaskVo flowTaskVo) {
    public Result<List<FlowNextDto>> getNextFlowNode(FlowTaskVo flowTaskVo) {
        // todo 似乎逻辑未写完,待检查
        FlowNextDto flowNextDto = this.getNextFlowNode(flowTaskVo.getTaskId(), flowTaskVo.getValues());
        if (flowNextDto==null) {
        List<FlowNextDto> nextDtoList = this.getNextFlowNode(flowTaskVo.getTaskId(), flowTaskVo.getValues());
        if (CollectionUtils.isEmpty(nextDtoList)) {
            return Result.OK("流程已完结", null);
        }
        return Result.OK(flowNextDto);
        return Result.OK(nextDtoList);
    }
    @Override
    public boolean checkParallelCompletion(String currentTaskId) {
        //获取当前任务
        Task currentTask = taskService.createTaskQuery().taskId(currentTaskId).singleResult();
        if (currentTask == null) {
            return false;
        }
        //获取当前执行
        Execution execution = runtimeService.createExecutionQuery().executionId(currentTask.getExecutionId()).singleResult();
        if (execution == null) {
            return false;
        }
        String parentId = execution.getParentId();
        if (StringUtils.isBlank(parentId)) {
            //没有父节点 代表没有并行任务
            return true;
        }
        // 获取所有兄弟执行
        List<Execution> siblingExecutions = runtimeService.createExecutionQuery()
                .parentId(parentId)
                .list();
        for (Execution siblingExecution : siblingExecutions) {
            if (!siblingExecution.getId().equals(execution.getId())) {
                //非自身的兄弟节点
                long count = runtimeService.createActivityInstanceQuery().executionId(siblingExecution.getId()).unfinished().count();
                if (count > 0) {
                    return false;
                }
            }
        }
        return true;
    }
    /**
     * 获取下一个节点信息,流程定义上的节点信息
     *
     * @param taskId 当前节点id
     * @param values 流程变量
     * @return 如果返回null,表示没有下一个节点,流程结束
     */
    public FlowNextDto getNextFlowNode(String taskId, Map<String, Object> values) {
    public List<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();
                List<FlowNextDto> nextDtoList = Lists.newArrayList();
                FlowNextDto flowNextDto;
                for (UserTask userTask : nextUserTask) {
                    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);
                                }
                    //多任务并行
                    Object colObj = values.get(userTask.getId());
                    if (Objects.nonNull(colObj)) {
                        List<String> userNameList = (List) colObj;
                        // 待办人员从变量中获取  否则就是节点中配置的用户 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);
                        }
                        flowNextDto.setUserList(userList);
                    } else {
                        // todo 读取自定义节点属性做些啥?
                        //String dataType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_DATA_TYPE);
                        String userType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_USER_TYPE);
                        // 变量中没有传入,写入节点中配置的用户
                        List<String> collect_username = sysUserFromTask.stream().map(SysUser::getUsername).collect(Collectors.toList());
                        values.put(userTask.getId(), collect_username);
                    }
                    nextDtoList.add(flowNextDto);
                }
                return flowNextDto;
                return nextDtoList;
            }
        }
        return null;
    }
    public List<SysUser> getSysUserFromTask(UserTask userTask) {
        String assignee = userTask.getAssignee();
        if (StrUtil.isNotBlank(assignee)){
        if (StrUtil.isNotBlank(assignee)) {
            // 指定单人
            SysUser userByUsername = iFlowThirdService.getUserByUsername(assignee);
            return Lists.newArrayList(userByUsername);
        }
        List<String> candidateUsers = userTask.getCandidateUsers();
        if (CollUtil.isNotEmpty(candidateUsers)){
        if (CollUtil.isNotEmpty(candidateUsers)) {
            // 指定多人
            List<SysUser> list = iFlowThirdService.getAllUser();
            return list.stream().filter(o->candidateUsers.contains(o.getUsername())).collect(Collectors.toList());
            return list.stream().filter(o -> candidateUsers.contains(o.getUsername())).collect(Collectors.toList());
        }
        List<String> candidateGroups = userTask.getCandidateGroups();
        if (CollUtil.isNotEmpty(candidateGroups)){
        //    指定多组
        if (CollUtil.isNotEmpty(candidateGroups)) {
            //    指定多组
            List<SysUser> userList = Lists.newArrayList();
            for (String candidateGroup : candidateGroups) {
                List<SysUser> usersByRoleId = iFlowThirdService.getUsersByRoleId(candidateGroup);
@@ -1465,6 +1580,7 @@
        }
        return Lists.newArrayList();
    }
    /**
     * 流程完成时间处理
     *