cuikaidong
2025-05-27 504333e56f249d16e71e8ac2a435cf2212040c23
Merge remote-tracking branch 'origin/master'
已修改12个文件
735 ■■■■ 文件已修改
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 257 ●●●● 补丁 | 查看 | 原始文档 | 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 112 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lxzn-module-flowable/src/main/java/org/jeecg/modules/flowable/service/impl/FlowTaskServiceImpl.java 266 ●●●● 补丁 | 查看 | 原始文档 | 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,12 +276,15 @@
        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())) {
@@ -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 {
@@ -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
     *
@@ -244,6 +246,7 @@
        Result result = startProcessInstanceById(processDefinition.getId(),variables);
        return result;
    }
    /**
     * 根据流程定义ID启动流程实例
     *
@@ -283,13 +286,11 @@
        //如果保存数据前未调用必调的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();
@@ -300,9 +301,25 @@
            doneUserList.add(sysUser.getUsername());
        }
        if (nextFlowNode!=null){
            //**有下一个节点
        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();
@@ -310,7 +327,7 @@
            //spring容器类名
            String serviceImplName = business.getServiceImplName();
            FlowCallBackServiceI flowCallBackService = (FlowCallBackServiceI) SpringContextUtils.getBean(serviceImplName);
            List<String> beforeParamsCandidateUsernames = flowCallBackService.flowCandidateUsernamesOfTask(task2.getTaskDefinitionKey(), variables);
                List<String> beforeParamsCandidateUsernames = flowCallBackService.flowCandidateUsernamesOfTask(task2.getTaskDefinitionId(), variables);
            business.setProcessDefinitionId(procDefId)
                    .setProcessInstanceId(processInstance.getProcessInstanceId())
////                    .setActStatus(ActStatus.start)
@@ -322,8 +339,53 @@
                    .setDoneUsers(doneUserList.toJSONString());
            if (CollUtil.isNotEmpty(beforeParamsCandidateUsernames)){
                // 删除后重写
                for (Task task2One : task2List) {
                    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);
                    }
                }
@@ -333,27 +395,37 @@
                        taskService.addCandidateUser(task2One.getId(),newUser);
                    }
                }
                business.setTodoUsers(JSON.toJSONString(beforeParamsCandidateUsernames));
                        newBusiness.setTodoUsers(JSON.toJSONString(beforeParamsCandidateUsernames));
            }else {
                // 业务层没有指定候选人,直接覆盖
                business.setTodoUsers(JSON.toJSONString(collect_username));
                        newBusiness.setTodoUsers(JSON.toJSONString(collect_username));
                        // 删除后重写
                        for (Task task2One : task2List) {
                            for (String oldUser : collect_username) {
                                taskService.deleteCandidateUser(task2One.getId(), oldUser);
            }
        } else {
        //    **没有下一个节点,流程已经结束了
            business.setProcessDefinitionId(procDefId)
                    .setProcessInstanceId(processInstance.getProcessInstanceId())
//                    .setActStatus(ActStatus.pass)
                    .setProposer(sysUser.getUsername())
                    .setDoneUsers(doneUserList.toJSONString())
            ;
        }
        flowMyBusinessService.updateById(business);
                        // 业务层有指定候选人,覆盖
                        for (Task task2One : task2List) {
                            for (String newUser : collect_username) {
                                taskService.addCandidateUser(task2One.getId(), newUser);
                            }
                        }
                    }
                    flowMyBusinessService.save(newBusiness);
                }
            }
            //删除原有的业务数据
            flowMyBusinessService.removeById(business.getId());
        }
        //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("流程启动成功");
    }
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;
    /**
     * 完成任务
     *
@@ -111,7 +114,7 @@
        //业务数据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);
@@ -124,7 +127,9 @@
        //    业务层有设置变量,使用业务层的变量
            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,21 +137,6 @@
            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();
@@ -157,7 +147,33 @@
            doneUserList.add(loginUser.getUsername());
        }
        if (task2!=null && task.getTaskDefinitionKey().equals(task2.getTaskDefinitionKey())){
        if (CollectionUtils.isEmpty(nextFlowNodeList)) {
            //    **没有下一个节点,流程已经结束了
            business
                    .setDoneUsers(doneUserList.toJSONString())
                    .setTodoUsers("")
                    .setTaskId("")
                    .setTaskNameId("")
                    .setTaskName("")
            ;
            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 (task.getTaskDefinitionKey().equals(task2.getTaskDefinitionKey())) {
                    //多实例 会签 TODO
        //    * 当前节点是会签节点,没有走完
            business.setTaskId(task2.getId())
//                    .setActStatus(ActStatus.doing)
@@ -166,37 +182,26 @@
            String todoUsersStr = business.getTodoUsers();
            JSONArray todosArr = JSON.parseArray(todoUsersStr);
            // 删除后重写
            for (Task task2One : task2List) {
                for (Object oldUser : todosArr) {
                    taskService.deleteCandidateUser(task2One.getId(),oldUser.toString());
                }
                        taskService.deleteCandidateUser(task2.getId(), oldUser.toString());
            }
            // 重写
            if (CollUtil.isNotEmpty(beforeParamsCandidateUsernames)){
                beforeParamsCandidateUsernames.remove(loginUser.getUsername());
                // 业务层有指定候选人,覆盖
                for (Task task2One : task2List) {
                    for (String newUser : beforeParamsCandidateUsernames) {
                        taskService.addCandidateUser(task2One.getId(),newUser);
                    }
                            taskService.addCandidateUser(task2.getId(), newUser);
                }
                business.setTodoUsers(JSON.toJSONString(beforeParamsCandidateUsernames));
            } else {
                todosArr.remove(loginUser.getUsername());
                for (Task task2One : task2List) {
                    for (Object oldUser : todosArr) {
                        taskService.addCandidateUser(task2One.getId(),oldUser.toString());
                    }
                            taskService.addCandidateUser(task2.getId(), oldUser.toString());
                }
                business.setTodoUsers(todosArr.toJSONString());
            }
        } else {
        //    * 下一节点是会签节点 或 普通用户节点,逻辑一致
            if (nextFlowNode!=null){
                //**有下一个节点
                UserTask nextTask = nextFlowNode.getUserTask();
                //能够处理下个节点的候选人
                List<SysUser> nextFlowNodeUserList = nextFlowNode.getUserList();
                List<String> collect_username = nextFlowNodeUserList.stream().map(SysUser::getUsername).collect(Collectors.toList());
@@ -214,43 +219,120 @@
                        .setTodoUsers(JSON.toJSONString(collect_username))
                ;
                // 删除后重写
                for (Task task2One : task2List) {
                    for (String oldUser : collect_username) {
                        taskService.deleteCandidateUser(task2One.getId(),oldUser);
                        taskService.deleteCandidateUser(task2.getId(), oldUser);
                    }
                }
                if (CollUtil.isEmpty(candidateUsers)&&CollUtil.isNotEmpty(beforeParamsCandidateUsernames)){
                    if (CollUtil.isNotEmpty(beforeParamsCandidateUsernames)) {
                    // 前端没有传入候选人 && 业务层有指定候选人,覆盖
                    for (Task task2One : task2List) {
                        for (String newUser : beforeParamsCandidateUsernames) {
                            taskService.addCandidateUser(task2One.getId(),newUser);
                        }
                            taskService.addCandidateUser(task2.getId(), newUser);
                    }
                    business.setTodoUsers(JSON.toJSONString(beforeParamsCandidateUsernames));
                } else {
                    for (Task task2One : task2List) {
                        for (String oldUser : collect_username) {
                            taskService.addCandidateUser(task2One.getId(),oldUser);
                            taskService.addCandidateUser(task2.getId(), oldUser);
                        }
                        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<String> beforeParamsCandidateUsernames = flowCallBackService.flowCandidateUsernamesOfTask(task2.getTaskDefinitionKey(), taskVo.getValues());
                    List<String> candidateUsers = taskVo.getCandidateUsers();
                    if (CollUtil.isNotEmpty(candidateUsers)) {
                        //    前端传入候选人 覆盖
                        beforeParamsCandidateUsernames = candidateUsers;
                    }
                    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());
                        }
                        // 重写
                        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("")
                ;
                        //能够处理下个节点的候选人
                        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();
    }
@@ -266,6 +348,7 @@
        flowTaskVo.setTaskId(business.getTaskId());
        this.taskReject(flowTaskVo);
    }
    /**
     * 驳回任务
     *
@@ -487,6 +570,7 @@
        }
    }
    @Override
    public void taskReturnByDataId(FlowTaskVo flowTaskVo){
        //如果保存数据前未调用必调的FlowCommonService.initActBusiness方法,就会有问题
@@ -494,6 +578,7 @@
        flowTaskVo.setTaskId(business.getTaskId());
        taskReturn(flowTaskVo);
    }
    /**
     * 退回任务
     *
@@ -671,6 +756,7 @@
    /**
     * 结束流程
     *
     * @param processInstanceId 流程实例 ID
     * @param deleteReason 定义删除原因
     */
@@ -942,6 +1028,7 @@
    /**
     * 判断多个任务是否处于同一流程节点
     *
     * @param taskIds 逗号分隔的任务ID字符串
     * @return 统一结果封装
     */
@@ -1327,6 +1414,7 @@
    /**
     * 顺序抽取节点
     *
     * @param orderKeys 容器
     * @param sourceKey 源
     * @param flowElements 所有的节点对象
@@ -1373,45 +1461,75 @@
     * @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)){
                    //多任务并行
                    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) {
@@ -1426,20 +1544,17 @@
                        } else {
                            // 变量中没有传入,写入节点中配置的用户
                            List<String> collect_username = sysUserFromTask.stream().map(SysUser::getUsername).collect(Collectors.toList());
                            values.put(collectionString,collect_username);
                        values.put(userTask.getId(), collect_username);
                        }
                    } else {
                        // todo 读取自定义节点属性做些啥?
                        //String dataType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_DATA_TYPE);
                        String userType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_USER_TYPE);
                    nextDtoList.add(flowNextDto);
                    }
                }
                return flowNextDto;
                return nextDtoList;
            }
        }
        return null;
    }
    public List<SysUser> getSysUserFromTask(UserTask userTask) {
        String assignee = userTask.getAssignee();
        if (StrUtil.isNotBlank(assignee)){
@@ -1465,6 +1580,7 @@
        }
        return Lists.newArrayList();
    }
    /**
     * 流程完成时间处理
     *