springboot 下 activiti 7会签配置与实现

news2024/10/1 19:37:08

流程图配置

在这里插入图片描述
会签实现须在 userTask 节点下的 multi instance 中配置 collection 及 completion condition;

  • collection 会签人员列表;
  • element variable 当前会签变量名称,类似循环中的 item;
  • completion condition: 完成条件。

${taskExecutionServiceImpl.findProcessUsers(‘applicant’)} : spring 代理下的 activiti 项目可使用
bean 下配置方法。

${countersignComponent.isComplete(taskId)} 会签实现方法,省略监听类。括号中的字符加单引号就是传递字符串,不加引号就是取当前任务中的变量。

在这里插入图片描述
会签配置图中的 user 变量需在此处使用。

实现代码

会签实现代码

@Component
@RequiredArgsConstructor
public class CountersignComponent {

    private final TaskService taskService;

    public boolean isComplete(String taskId) {
        // 1、参数验证
        if(StringUtils.isAnyEmpty(taskId)){
            return false;
        }

        // 2、获取当前任务节点参数及会签判断后重新设置
        // 获取流程参数 var,会签人员完成自己的审批任务时会添加流程参数 var,2 为拒绝,1 为同意
        String variable = BeanUtil.nullOrUndefinedToEmptyStr(taskService.getVariableLocal(taskId, ActivitiCommonConstant.VAR.getValue()));
        // 当值为 2 证明已有人拒绝,返回 true
        if(DefaultConstant.TWO_CODE.getKey().equals(variable)){
            //会签结束,设置参数 execType 为 4 进行下一步操作。
            taskService.setVariableLocal(taskId, ActivitiCommonConstant.EXEC_TYPE.getValue(), DefaultConstant.FIVE_CODE.getKey());
            return true;
        }

        // 当值为 1,判断会签是否结束
        Integer complete = (Integer) taskService.getVariable(taskId, ActivitiCommonConstant.NR_OF_COMPLETED_INSTANCES.getValue());
        if(complete == 0){
            // 会签未结束,后续处理
        }
        return false;
    }

}

用户动态获取代码

    @Override
    public List<String> findProcessUsers(String code) {
        // 1、参数验证
        if(StringUtils.isEmpty(code)){
            throw new BusinessException(ActivitiConstant.PROCESS_USER_NULL);
        }

        // 2、查询对应流程人员(具体取人逻辑,根据个人业务变更)
        ProcessParameterQuery processParameterQuery = new ProcessParameterQuery();
        processParameterQuery.setCode(code);
        GostopResponseVo<ProcessParameterVo> processParameter = dev.findProcessParameter(processParameterQuery);
        ProcessParameterVo processParameterVo = processParameter.getResult();
        if(Objects.isNull(processParameterVo)){
            throw new BusinessException(ActivitiConstant.PROCESS_USER_NULL);
        }
        List<HospitalUserVo> userInfos = processParameterVo.getUserInfos();
        if(CollectionUtils.isEmpty(userInfos)){
            throw new BusinessException(ActivitiConstant.PROCESS_USER_NULL);
        }
        return userInfos.stream().map(HospitalUserVo::getId).distinct().collect(Collectors.toList());
    }

开启流程

    @Override
    public String startProcess(CommonTaskParamVo param) {
        // 1、参数验证
        if(Objects.isNull(param) || StringUtils.isAnyEmpty(param.getProcessKey())){
            throw new BusinessException(ActivitiConstant.EXEC_ERROR_PARAMS_NULL);
        }

        // 2、启动流程定义,返回流程实例
        ProcessInstance pi;
        try {
            CustomParamVo customParamVo = param.getCustomParamVo();
            String paramJson = JSONObject.toJSONString(customParamVo);
            Map paramMap = JSONObject.parseObject(paramJson, Map.class);
            pi = runtimeService
                    .startProcessInstanceByKey(param.getProcessKey(), paramMap);
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new BusinessException(ActivitiConstant.PROCESS_NOT_DEPLOYED);
        }
        return pi.getId();
    }

任务执行

    @Override
    public String complete(CommonTaskParamVo param) {
        // 1、参数验证
        if(Objects.isNull(param) || StringUtils.isAnyEmpty(param.getProcessId(), param.getUserId())){
            throw new BusinessException(ActivitiConstant.EXEC_ERROR_PARAMS_NULL);
        }

        // 2、查询当前人任务信息
        String userId = param.getUserId();
        //与正在执行的任务管理相关的Service
        Task task = taskService
                .createTaskQuery()
                //指定个人任务查询,指定办理人
                .taskCandidateUser(userId)
                //使用流程实例ID查询
                .processInstanceId(param.getProcessId())
                //排序
                .orderByTaskCreateTime().asc()
                //返回列表
                .singleResult();
        if (Objects.isNull(task)) {
            throw new BusinessException(ActivitiConstant.TASK_NULL_ERROR);
        }
        task.setDescription(param.getDescription());
        task.setAssignee(userId);
        taskService.saveTask(task);
        // 2.1 设置执行人信息
        HospitalUserCacheVo userInfo = activitComponent.getUserInfo();
        CustomParamVo customParamVo = param.getCustomParamVo();
        customParamVo.setExecUserId(userInfo.getId());
        customParamVo.setExecUserName(userInfo.getDepartmentName());
        customParamVo.setExecTime(DateUtil.date2String(LocalDateTime.now()));
        customParamVo.setTaskId(task.getId());
        // 2.2 将自定义参数转为 map
        String paramJson = JSONObject.toJSONString(customParamVo);
        Map paramMap = JSONObject.parseObject(paramJson, Map.class);
        taskService.setVariablesLocal(task.getId(), paramMap);
        // 3、执行当前节点信息
        taskService.complete(task.getId());
        return task.getId();
    }

参数接收对象

@Data
public class CommonTaskParamVo {

    /**
     * 用户 ID
     */
    private String userId;
    /***
     * 流程图定义 KEY
     */
    private String processKey;
    /**
     * 流程 ID
     */
    private String processId;
    /**
     * 描述
     */
    private String description;
    /**
     * 自定义参数类
     */
    private CustomParamVo customParamVo;

}
@Data
public class CustomParamVo {

    /**
     * 操作类型 (1 同意, 2 回退, 3 驳回, 4 提交 5 删除)
     */
    private String execType;
    /**
     * 节点类型 (1 申请节点 2 审批节点)
     */
    private String nodeType;
    /**
     * 预留参数
     */
    private String var;
    /**
     * 执行人 ID
     */
    private String execUserId;
    /**
     * 执行人名称
     */
    private String execUserName;
    /**
     * 执行时间
     */
    private String execTime;
    /**
     * 任务 ID
     */
    private String taskId;

}

使用上述参数类及流程配置后,查询任务流水就变得非常简单。

流水查询

@Override
    public List<FlowDataVo> flowQueryProcess(FlowQuery param) {
        // 1、参数验证
        if(Objects.isNull(param) || StringUtils.isAnyEmpty(param.getProcessId())){
            return new ArrayList<>();
        }

        // 2、查询任务执行节点信息
        HistoricTaskInstanceQuery historicTaskInstanceQuery = historyService.createHistoricTaskInstanceQuery();
        List<HistoricTaskInstance> taskInfoArr = historicTaskInstanceQuery.processInstanceId(param.getProcessId()).orderByTaskCreateTime().asc().list();
        if(CollectionUtils.isEmpty(taskInfoArr)){
            return new ArrayList<>();
        }

        // 3、查询任务执行参数信息
        HistoricVariableInstanceQuery historicVariableInstanceQuery = historyService.createHistoricVariableInstanceQuery();
        List<HistoricVariableInstance> variableInstanceList = historicVariableInstanceQuery.processInstanceId(param.getProcessId()).list();

        // 4、构建返回信息对象
        List<FlowDataVo> resultArr = taskInfoArr.stream().map(taskInfo -> {
            FlowDataVo flowDataVo = new FlowDataVo();
            flowDataVo.setNodeName(taskInfo.getName());
            flowDataVo.setDescription(taskInfo.getDescription());
            List<HistoricVariableInstance> variableArr = variableInstanceList.stream().filter(e -> taskInfo.getId().equals(e.getTaskId())).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(variableArr)) {
                flowDataVo.setStatus(DefaultConstant.ONE_CODE.getKey());
                return flowDataVo;
            }
            JSONObject flowDataJson = (JSONObject) JSONObject.toJSON(flowDataVo);
            variableArr.stream().forEach(var -> {
                String variableName = var.getVariableName();
                String value = BeanUtil.nullOrUndefinedToEmptyStr(var.getValue());
                flowDataJson.put(variableName, value);
            });
            String flowDataJsonString = flowDataJson.toJSONString();
            FlowDataVo afterFlowData = JSONObject.parseObject(flowDataJsonString, FlowDataVo.class);
            afterFlowData.setStatus(DefaultConstant.TWO_CODE.getKey());
            return afterFlowData;
        }).collect(Collectors.toList());

        return resultArr;
    }

流水查询使用 bean 对象

@Data
public class FlowQuery {

    /**
     * 流程 ID
     */
    private String processId;
    /**
     * 用户 ID
     */
    private String userId;
}
@Data
public class FlowDataVo {

    /**
     * 操作类型 (1 同意, 2 回退, 3 驳回, 4 提交 5 删除)
     */
    private String execType;
    /**
     * 节点类型 (1 申请节点 2 审批节点)
     */
    private String nodeType;
    /**
     * 预留参数
     */
    private String var;
    /**
     * 节点名称
     */
    private String nodeName;
    /**
     * 执行状态 1 未执行 2 已执行
     */
    private String status;
    /**
     * 执行人 ID
     */
    private String execUserId;
    /**
     * 执行人名称
     */
    private String execUserName;
    /**
     * 执行时间
     */
    private String execTime;
    /***
     * 描述
     */
    private String description;

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/983567.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Credo推出业界首款单片集成CMOS VCSEL驱动器的800G光DSP芯片

针对AOC及短距&#xff08;SR&#xff09;光模块优化的新型Credo DSP&#xff0c;适用于下一代超大规模数据中心/AI应用 加州圣何塞和中国深圳&#xff0c;2023年9月6日——Credo Technology&#xff08;纳斯达克股票代码&#xff1a;CRDO&#xff09;今日发布两款新品&#x…

EasyPhoto:基于 SD WebUI 的艺术照生成插件来啦!

作者 &#xff1a;wuziheng 背景介绍 最近&#xff0c;基于生成式AI技术批量产出真/像/美的个人写真应用非常受欢迎。同时&#xff0c;随着 Stable Diffusion 领域开源社区的快速发展&#xff0c;社区也涌现了类似 FaceChain 的开源项目&#xff0c;帮助开发者开发个性化的真…

14 合并区间

合并区间 题解1 左端点排序后合并&#xff08;可证连续&#xff0c;贪心&#xff09;题解2 双指针&#xff08;优化&#xff09; 以数组 i n t e r v a l s intervals intervals 表示若干个区间的集合&#xff0c;其中单个区间为 i n t e r v a l s [ i ] [ s t a r t i , e n…

计算机视觉-OpenCV入门讲解

&#x1f389;作者简介&#xff1a;在读计算机研究生&#xff0c;目前研二。主要研究方向是人工智能和群智能算法方向。目前熟悉python网页爬虫、机器学习、计算机视觉&#xff08;OpenCV&#xff09;、群智能算法目前正在学习深度学习的相关内容。 &#x1f4c3;个人主页&…

jar包或exe程序设置为windows服务

最近在使用java和python制作客户端时突发奇想&#xff0c;是否能够通过一种方法来讲jar包和exe程序打包成windows服务呢&#xff1f;简单了解了一下是可以的。 首先要用到的是winSW&#xff0c;制作windows服务的过程非常简单&#xff0c;仅需几步制作完成&#xff0c;也不需要…

2023 Google 开发者大会

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

C++(Liunx) 使用cut截 取出Ubuntu用户的家目录,要求:不能使用“:“作为分割.

使用cut截 取出Ubuntu用户的家目录&#xff0c;要求&#xff1a;不能使用":"作为分割

spawnsync pnpm.cmd enoent

解决&#xff1a; 安装pnpm npm install pnpm -g

深入解析JDK 8 HashMap

HashMap 简介 HashMap 主要用来存放键值对&#xff0c;它基于哈希表的 Map 接口实现&#xff0c;是常用的 Java 集合之一&#xff0c;是非线程安全的。 HashMap 可以存储 null 的 key 和 value&#xff0c;但 null 作为键只能有一个&#xff0c;null 作为值可以有多个 JDK1.8…

自从学会了ChatGPT,我就再没加过班

不会吧不会吧&#xff0c;竟然还有程序员没学会ChatGPT&#xff1f;据说早学会ChatGPT的程序员已经开挂了&#xff01; 不仅实现了按时下班的人生理想&#xff0c;还拥有了升职加薪的意外收获&#xff0c;在开挂人生的另一边却仍有人担心自己会被ChatGPT取代&#xff01;因为C…

【高阶数据结构】红黑树 {概念及性质;红黑树的结构;红黑树的实现;红黑树插入操作详细解释;红黑树的验证}

红黑树 一、红黑树的概念 红黑树&#xff08;Red Black Tree&#xff09; 是一种自平衡二叉查找树&#xff0c;在每个结点上增加一个存储位表示结点的颜色&#xff0c;可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制&#xff0c;红黑树确保没有…

A145-FR04HS-60变量柱塞泵控制比例放大器

本比例放大器驱动电比例泵、比例压力阀、比例流量阀、比例减压阀、比例方向阀、比例插装阀、比例溢流阀、比例节流阀、比例换向阀控制。 输入指令、最大、最小电流、上升、下降斜坡时间、颤振频率等可现场设置&#xff1b; 带数码显示&#xff0c;可查看设置参数及故障报警提…

vue-cli中总提示组件没有正确注册

这里写目录标题 一、报错提示二、修改办法 一、报错提示 二、修改办法 <template><div><aside-component style"width: 15%"></aside-component></div> </template><script> import AsideComponent from /components/Asi…

JAVA毕业设计096—基于Java+Springboot+Vue的在线教育系统(源码+数据库+18000字论文)

基于JavaSpringbootVue的在线教育系统(源码数据库18000字论文)096 一、系统介绍 本系统前后端分离 本系统分为管理员、用户两种角色(管理员角色权限可自行分配) 用户功能&#xff1a; 注册、登录、课程预告、在线课程观看、学习资料下载、学习文章预览、个人信息管理、消息…

06-JVM对象内存回收机制深度剖析

上一篇&#xff1a;05-JVM内存分配机制深度剖析 堆中几乎放着所有的对象实例&#xff0c;对堆垃圾回收前的第一步就是要判断哪些对象已经死亡&#xff08;即不能再被任何途径使用的对象&#xff09;。 1.引用计数法 给对象中添加一个引用计数器&#xff0c;每当有一个地方引…

最新暴力破解漏洞技术详解

暴力破解漏洞简介 暴力破解漏洞的产生是由于服务器端没有做限制&#xff0c;导致攻击者可以通过暴力的手段破解所需信息&#xff0c;如用户名、密码、短信验证码等。暴力破解的关键在于字典的大小及字典是否具有针对性&#xff0c;如登录时&#xff0c;需要输入4位数字的短信验…

无涯教程-JavaScript - DEC2BIN函数

描述 DEC2BIN函数将十进制数转换为二进制数。 语法 DEC2BIN (number, [places])争论 Argument描述Required/Optionalnumber 要转换的十进制整数。 如果number为负数,则将忽略有效的位置值,并且DEC2BIN返回10个字符(10位)的二进制数字,其中最高有效位是符号位。其余的9位是幅…

使用多线程或异步技术提高图片抓取效率

导语 图片抓取是爬虫技术中常见的需求&#xff0c;但是图片抓取的效率受到很多因素的影响&#xff0c;比如网速、网站反爬机制、图片数量和大小等。本文将介绍如何使用多线程或异步技术来提高图片抓取的效率&#xff0c;以及如何使用爬虫代理IP来避免被网站封禁。 概述 多线…

【无监督学习之聚类】

聚类 0.简介距离 和 相似度1. K均值聚类(kmeans)模型算法特点 2. 谱聚类(Spectral clustering)算法思想特点谱聚类的具体步骤&#xff1a;算法步骤&#xff1a; 3.小结参考资料 0.简介 聚类&#xff1a;针对给定的样本&#xff0c;依据他们的属性的相似度或距离&#xff0c;将…

spring---第一篇

系列文章目录 文章目录 系列文章目录一、如何实现一个IOC容器二、spring是什么?一、如何实现一个IOC容器 1、配置文件配置包扫描路径 2、递归包扫描获取.class文件 3、反射、确定需要交给IOC管理的类 4、对需要注入的类进行依赖注入 配置文件中指定需要扫描的包路径 定义一些…