百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程文章 > 正文

Github 标星35k 的 SpringBoot整合acvtiviti开源分享,看完献上膝盖

qiyuwang 2025-03-10 20:00 4 浏览 0 评论

前言

activiti是目前比较流行的工作流框架,但是activiti学起来还是费劲,还是有点难度的,如何整合在线编辑器,如何和业务表单绑定,如何和系统权限绑定,这些问题都是要考虑到的,不是说纯粹的把activiti整合到系统中就完事了。如今国内比较流行的是前后端分离模式,之前都是前后端放一个工程里面,接口风格很乱,并且不好维护,前后端开发不是很方便。目前前端都做成了工程化的形式,比如国产的Vue,国外的React等等。为了顺应潮流,我就做了一套springboot-vue-activiti的快速开发小脚手架,对于大型项目来说还是不太适合,毕竟来说,一个人的开发能力有限,但是对于中小微型项目,并且带有审批业务的项目来说,那简直就是一个福音了。

一、效果展示

1.模型设计器

2.流程节点设置

审批人员可以根据角色、部门、部门负责人、直接选择人员等。

3.审批进度查询

二、操作过程

1.引入activiti依赖


    
        org.activiti
        activiti-spring-boot-starter-basic
        ${activiti.version}
        
            
                org.mybatis
                mybatis
            
        
    
    
    
        org.activiti
        activiti-diagram-rest
        ${activiti.version}
    
    
    
        org.activiti
        activiti-modeler
        ${activiti.version}
    

2.编辑器代码及汉化

3.application.yml配置

activiti:
    check-process-definitions: false
    #启用作业执行器
    async-executor-activate: false
    #启用异步执行器
    job-executor-activate: false    

4.数据库表

三、业务表单和系统权限绑定

1.思路

1.新建一张流程定义扩展表(用来存储流程部署的基本信息、关联业务表名、前端路由信息、业务表单类型等),流程部署完后往流程定义扩展表插入部署基本信息,然后编辑已发布的流程,往扩展表中插入本流程的分类,关联表单信息。
2.关于自定义节点设置,主要是用来定义每个节点由哪个角色,或者具体哪个人来审批。建立一张节点扩展表(存储节点流转信息,指定人ID、角色ID,等)。

2.部分代码

// 获取模型
        Model modelData = repositoryService.getModel(id);
        byte[] bytes = repositoryService.getModelEditorSource(modelData.getId());
        if (bytes == null) {
            return Result.error("模型数据为空,请先成功设计流程并保存");
        }
        try {
            JsonNode modelNode = new ObjectMapper().readTree(bytes);
            BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode);
            if(model.getProcesses().size()==0){
                return Result.error("模型不符要求,请至少设计一条主线流程");
            }
            byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(model);
            // 部署发布模型流程
            String processName = modelData.getName() + ".bpmn20.xml";
            Deployment deployment = repositoryService.createDeployment()
                    .name(modelData.getName())
                    .addString(processName, new String(bpmnBytes, "UTF-8"))
                    .deploy();
            String metaInfo = modelData.getMetaInfo();
            JSONObject metaInfoMap = JSON.parseObject(metaInfo);
            // 设置流程分类,保存扩展流程至数据库
            List list = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).list();
            for (ProcessDefinition pd : list) {
                ActZprocess actZprocess = new ActZprocess();
                actZprocess.setId(pd.getId());
                actZprocess.setName(modelData.getName());
                actZprocess.setProcessKey(modelData.getKey());
                actZprocess.setDeploymentId(deployment.getId());
                actZprocess.setDescription(metaInfoMap.getString(ModelDataJsonConstants.MODEL_DESCRIPTION));
                actZprocess.setVersion(pd.getVersion());
                actZprocess.setDiagramName(pd.getDiagramResourceName());
                actZprocessService.setAllOldByProcessKey(modelData.getKey());
                actZprocess.setLatest(true);
                actZprocessService.save(actZprocess);
            }
        }catch (Exception e){
            String err = e.toString();
            log.error(e.getMessage(),e);
            if (err.indexOf("NCName")>-1){
                return Result.error("部署失败:流程设计中的流程名称不能为空,不能为数字以及特殊字符开头!");
            }
            if (err.indexOf("PRIMARY")>-1){
                return Result.error("部署失败:该模型已发布,key唯一!");
            }
            return Result.error("部署失败!");
        }
        return Result.ok("部署成功");
/*获取高亮实时流程图*/
    @RequestMapping(value = "/getHighlightImg/{id}", method = RequestMethod.GET)
    public void getHighlightImg(@PathVariable String id, HttpServletResponse response){
        InputStream inputStream = null;
        ProcessInstance pi = null;
        String picName = "";
        // 查询历史
        HistoricProcessInstance hpi = historyService.createHistoricProcessInstanceQuery().processInstanceId(id).singleResult();
        if (hpi.getEndTime() != null) {
            // 已经结束流程获取原图
            ProcessDefinition pd = repositoryService.createProcessDefinitionQuery().processDefinitionId(hpi.getProcessDefinitionId()).singleResult();
            picName = pd.getDiagramResourceName();
            inputStream = repositoryService.getResourceAsStream(pd.getDeploymentId(), pd.getDiagramResourceName());
        } else {
            pi = runtimeService.createProcessInstanceQuery().processInstanceId(id).singleResult();
            BpmnModel bpmnModel = repositoryService.getBpmnModel(pi.getProcessDefinitionId());

            List highLightedActivities = new ArrayList();
            // 高亮任务节点
            List tasks = taskService.createTaskQuery().processInstanceId(id).list();
            for (Task task : tasks) {
                highLightedActivities.add(task.getTaskDefinitionKey());
            }
            List highLightedFlows = new ArrayList();
            ProcessDiagramGenerator diagramGenerator = processEngineConfiguration.getProcessDiagramGenerator();
            //"宋体"
            inputStream = diagramGenerator.generateDiagram(bpmnModel, "png", highLightedActivities, highLightedFlows,
                    "宋体", "宋体", "宋体",null, 1.0);
            picName = pi.getName()+".png";
        }
        try {
            response.setContentType("application/octet-stream;charset=UTF-8");
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(picName, "UTF-8"));
            byte[] b = new byte[1024];
            int len = -1;
            while ((len = inputStream.read(b, 0, 1024)) != -1) {
                response.getOutputStream().write(b, 0, len);
            }
            response.flushBuffer();
        } catch (IOException e) {
            log.error(e.toString());
            throw new JeecgBootException("读取流程图片失败");
        }
    }

总结

上面只是展示了部分代码和部分效果图,对于一个正常的审批流转业务来说,提交审批,申请人撤销,重新申请,审批人驳回,委托他人审批,会签,流程挂起,流程实时跟踪,并行网关,排他网关,监听,待办,已办消息通知等都是必须要的,我这就不一一展现了。

更多资料,私信回复【666】......

相关推荐

在Word中分栏设置页码一页两个页码的技巧!

施老师:在正常情况下,Word文档中一页只会出现一个页码。但在某种情况下,比如说:用了分栏后,我们希望一页中出现两个页码,那应该如何实现呢?今天,就由宁双学好网施老师来为大家讲一下,利用域来实现一页两...

如何在关键时刻向上自荐(如何在关键时刻做出正确选择)

抓住机会,挺身而出有种时刻叫“关键时刻”,关键时刻,作为一个认为自己有能力的、训练有素的人,应该考虑挺身而出,甚至应该不考虑就挺身而出。...

WPS Word:跨页的文档表格,快速调整为一页。#Excel

如何快速将跨页的文档表格调整为一页?需要根据两种情况分别处理。如果表格所有行的行高相同,调整为一页的方法有两种。第一种方法是将光标移动到表格内,然后将鼠标移动到表格右下角的方框处,按住鼠标左键向上拖动...

word文档插入下一页分节符(word下一页分页符)

在word文档中,对文档页面进行分页是特别常见的操作,其中的下一页分节符也是用得比较多的,但是一些人不太清楚在哪里设置,也不知道它具体能实现的功能是什么。接下来看看如何在word文档中插入下一页分节符...

word文档如何设置某一页纸张的方向

word文档页面方向有横向和纵向,纵向是默认的纸张方向,有时我们需要将页面设置为横向,或只设置其中某一页方向,应该怎么操作呢?一起来看看下面的详细介绍第一步:...

word怎么单独设置一页为横向(word2019怎样设置单独一页为横向)

word里面其中一页可以改为横向的吗?经过实际操作发现是完全可以的。...

Word如何设置分栏,如何一页内容同时显示一栏和两栏

我们使用Word文档,有时需要用到两栏的排版,甚至一页内容同时包含一栏和两栏的排版,这种格式怎么设置呢?具体步骤如下:首先是两栏排版的设置,直接点击Word文件上方工具栏【布局】,选择【分栏】下面的【...

Word怎么分页?这三个方法可以帮到你

我们不仅可以利用Word编辑文档,还可以编辑文集呢。但是有时候会出现两个部分的文章长短不一,我们需要对文档进行分页处理。这样可以方便我们对文档进行其他操作。那么Word怎么分页呢?大家可以采用下面这...

Word内容稍超一页,如何优化至单页打印?

如何将两页纸的内容,缩到一页打印呢?有时候一页纸多一点内容,我们完全可以缩一下,放到一页来打印。...

[word] word 表格如何跨行显示表头、标题

word表格如何跨行显示表头、标题在Word中的表格如果过长的话,会跨行显示在另一页,如果想要在其它页面上也显示表头,更直观的查看数据。难道要一个个复制表头吗?当然不是,教你简单的方法操作设置Wo...

Word表格跨页如何续上表?(word如何让表格跨页不断掉)

长文档的表格跨页时,你会发现页末空白太多了,这时要怎么调整?选中整张表格,右击【表格属性】,点击【行】选项,之后勾选【允许跨页断行】,点击确定即可解决空白问题。...

Word怎么连续自动生成页码,操作步骤来了!

Word怎么连续自动生成页码,操作步骤来了!...

word文档怎么把两页合并成一页内容?教你4种方法

word怎么把两页合并成一页?word怎么把两页合并成一页?用四种方法演示一下。·方法一:把这一个文档合并成一页,按ctrl加a全选文档,然后右键点击段落,弹出的界面行距改成固定值,磅值可以改小一点,...

如何将Word中的一页的纸张方向设置为横向?这里提供详细步骤

默认情况下,MicrosoftWord将页面定向为纵向视图。虽然这在大多数情况下都很好,但你可能拥有在横向视图中看起来更好的页面或页面组。以下是实现这一目标的两种方法。无论使用哪种方法,请注意,如果...

Word横竖混排你会玩吗?(word横排竖排混合)

我们在用Word排版的时候,一般都是竖版格式,但偶尔会需要到一些特殊的版式要求,比如文档中插入的一个表格,横向的内容比较多,这时就需要用到横版,否则表格显示不全。这种横竖版混排的要求,在Word20...

取消回复欢迎 发表评论: