springboot+activiti根据模型id,查询节点列表

在奋斗的大道      2022-05-17     399

关键词:

本文基于:Activiti 模型管理

Model 模型管理需求:

在模型管理功能基础上添加动态配置外置表单,注意不是内置表单。

温馨提示:不管是内置表单还是外置表单,都是配置在指定模型的节点之上所有我们就必须更新模型Id查询指定模型涉及的节点列表信息。

Model 模型管理之新增表单配置功能:

选择转正流程模型,查看节点列表:

 温馨提示:这里还欠缺将自定义表单绑定值指定节点上。这个功能会在后期 实现。

SpringBoot 之Activiti Model 模型管理后台

SpringBoot 添加流程模型节点查找控制器(NodeController

package com.zzg.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.zzg.common.activiti.entity.NodeEntity;
import com.zzg.common.activiti.enums.NodeTypeEnum;
import com.zzg.common.vo.Resp;
import org.activiti.bpmn.model.*;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Model;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.w3c.dom.Node;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 节点控制层
 */
@RequestMapping("/node")
@RestController
public class NodeController 
    private static Logger logger= LoggerFactory.getLogger(NodeController.class);

    @Autowired
    private HistoryService historyService;

    @Autowired
    private RepositoryService repositoryService;
    /**
     * 查找指定流程模型Id关联开始节点和用户任务节点
     * @param modelId
     */
    @PostMapping(value = "/findModelAssociationNode/modelId")
    public Resp<List<NodeEntity>> findModelAssociationNode(@PathVariable("modelId") String modelId) throws IOException 
        List<NodeEntity> list = new ArrayList<>();
        // 获取模型XML文件
        ObjectNode objectNode = (ObjectNode) new ObjectMapper().readTree(repositoryService.getModelEditorSource(modelId));
        BpmnModel bpmnModel = new BpmnJsonConverter().convertToBpmnModel(objectNode);
        //获得流程模型的所有节点
        Collection<FlowElement> flowElements = bpmnModel.getMainProcess().getFlowElements();
        // 过滤序列流
        List<FlowElement> filterFlowElements = flowElements.stream().filter(item -> 
            if(item instanceof  SequenceFlow)
                return false;
            
            return true;
        ).collect(Collectors.toList());

        for(FlowElement e : filterFlowElements) 
            NodeEntity entity = new NodeEntity();
            String id = null;
            String name = null;
            String formKey = null;
            List<FormProperty> formProperties = null;
            // 判断节点类型-- 用户任务节点
            if (e instanceof UserTask) 
                entity.setNodeTypeEnum(NodeTypeEnum.UserTask);
                // 节点Id
                id =((UserTask)e).getId();
                // 节点名称
                name = ((UserTask)e).getName();
                // 配置表单(外置表单)
                formKey = ((UserTask)e).getFormKey();
                // 配置表单(内置表单)
                formProperties = ((UserTask)e).getFormProperties();
            
            // 判断节点类型 -- 开始任务
            if(e instanceof  StartEvent) 
                entity.setNodeTypeEnum(NodeTypeEnum.StartEvent);
                // 节点Id
                id =((StartEvent)e).getId();
                // 节点名称
                name = ((StartEvent)e).getName();
                // 配置表单(外置表单)
                formKey = ((StartEvent)e).getFormKey();
                // 配置表单(内置表单)
                formProperties = ((StartEvent)e).getFormProperties();
            
            // 判断节点类型 -- 结束任务
            if(e instanceof  EndEvent) 
                entity.setNodeTypeEnum(NodeTypeEnum.EndEvent);
                // 节点Id
                id =((EndEvent)e).getId();
                // 节点名称
                name = ((EndEvent)e).getName();
            
             entity.setId(id);
             entity.setName(name);
             entity.setFormKey(formKey);
             entity.setFormPropertys(formProperties);
             list.add(entity);
        
        return Resp.OK(list);
    

package com.zzg.common.activiti.entity;

import com.zzg.common.activiti.enums.NodeTypeEnum;
import org.activiti.bpmn.model.FormProperty;

import java.util.List;

/**
 * activiti 节点对象封装
 */
public class NodeEntity implements java.io.Serializable

    private String id;

    private String name;

    /**
     * 外置表单
     */
    private String formKey;

    /**
     * 内置表单
     */
    private List<FormProperty> formPropertys;

    private NodeTypeEnum nodeTypeEnum;

    public NodeTypeEnum getNodeTypeEnum() 
        return nodeTypeEnum;
    

    public void setNodeTypeEnum(NodeTypeEnum nodeTypeEnum) 
        this.nodeTypeEnum = nodeTypeEnum;
    

    public String getId() 
        return id;
    

    public void setId(String id) 
        this.id = id;
    

    public String getName() 
        return name;
    

    public void setName(String name) 
        this.name = name;
    

    public String getFormKey() 
        return formKey;
    

    public void setFormKey(String formKey) 
        this.formKey = formKey;
    

    public List<FormProperty> getFormPropertys() 
        return formPropertys;
    

    public void setFormPropertys(List<FormProperty> formPropertys) 
        this.formPropertys = formPropertys;
    

 

package com.zzg.common.activiti.enums;

/**
 * Activiti 节点枚举类型定义
 */
public enum NodeTypeEnum 
    StartEvent("开始节点", "start_event"), UserTask("用户任务", "user_task"), EndEvent("结束节点", "end_event");

    private String name;

    private String type;

    NodeTypeEnum(String name, String type) 
        this.name = name;
        this.type = type;
    

    public String getName() 
        return name;
    

    public void setName(String name) 
        this.name = name;
    

    public String getType() 
        return type;
    

    public void setType(String type) 
        this.type = type;
    

Model.html 页面添加表单配置前端代码:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport"
          content="width=device-width, initial-scale=1, maximum-scale=1">
    <title>**系统 - Layui</title>
    <link rel="stylesheet" href="layui/css/layui.css">
</head>
<body class="layui-layout-body">
<div class="layui-layout layui-layout-admin">
    <div class="layui-header">
        <div class="layui-logo">** 系统</div>
        <ul class="layui-nav layui-layout-right">
            <li class="layui-nav-item"><a href="javascript:;"> 超级管理员 </a>
                <dl class="layui-nav-child">
                    <dd>
                        <a href="">基本资料</a>
                    </dd>
                    <dd>
                        <a href="">安全设置</a>
                    </dd>
                </dl></li>
            <li class="layui-nav-item"><a href="">退了</a></li>
        </ul>
    </div>

    <div class="layui-side layui-bg-black">
        <div class="layui-side-scroll">
            <!-- 左侧导航区域(可配合layui已有的垂直导航) -->
            <ul class="layui-nav layui-nav-tree" lay-filter="test">
                <li class="layui-nav-item layui-nav-itemed"><a class=""
                                                               href="javascript:;">流程管理</a>
                    <dl class="layui-nav-child">
                        <dd>
                            <a href="javascript:;">流程定义</a>
                        </dd>
                        <dd>
                            <a href="javascript:;">表单定义</a>
                        </dd>

                    </dl></li>
                <li class="layui-nav-item"><a href="javascript:;">用户管理</a>
                    <dl class="layui-nav-child">
                        <dd>
                            <a href="javascript:;">查询用户</a>
                        </dd>
                        <dd>
                            <a href="javascript:;">新增用户</a>
                        </dd>
                    </dl></li>
                <li class="layui-nav-item"><a href="javascript:;">借阅信息</a>
                    <dl class="layui-nav-child">
                        <dd>
                            <a href="javascript:;">所有记录</a>
                        </dd>
                        <dd>
                            <a href="javascript:;">个人记录</a>
                        </dd>
                    </dl></li>
                <li class="layui-nav-item"><a href="">帮助</a></li>
            </ul>
        </div>
    </div>

    <div class="layui-body">
        <!-- 内容主体区域 -->
        <div style="padding: 15px;">

            <div class="demoTable">
                流程名称:
                <div class="layui-inline">
                    <input class="layui-input" name="id" id="demoReload" autocomplete="off">
                </div>
                <button class="layui-btn" data-type="reload">搜索</button>
                <button class="layui-btn" data-type="add">新增</button>

            </div>


            <table id="tb-book" lay-filter="tb-book"></table>

            <script type="text/html" id="barDemo">
                <a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
                <a class="layui-btn layui-btn-xs" lay-event="deploy">部署</a>
                <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a>
                <a class="layui-btn layui-btn-warm layui-btn-xs" lay-event="export">导出</a>
                <a class="layui-btn layui-btn-warm layui-btn-xs" lay-event="form">表单配置</a>
            </script>
            <!-- 编辑节点弹出层-->
            <script type="text/html" id="nodeDemo">
                <a class="layui-btn layui-btn-xs" lay-event="setting">配置</a>
            </script>
            <script type="text/html" id="node_table">
                <div class="layui-col-md12" style="margin-left: 5px;">
                    <table id="tb-node" lay-filter="tb-node"></table>
                </div>

            </script>

            <!--    编辑弹出层-->
            <script type="text/html" id="edit_form">
                <div class="layui-col-md10" style="margin-left: 35px;margin-top: 20px">
                    <form class="layui-form layui-form-pane" lay-filter="edit_form" action="">
                        <div class="layui-form-item">
                            <label class="layui-form-label">流程Key</label>
                            <div class="layui-input-block">
                                <input type="text" name="processKey" required  lay-verify="required" placeholder="请输入流程Key"
                                       autocomplete="off" class="layui-input">
                            </div>
                        </div>
                        <div class="layui-form-item">
                            <label class="layui-form-label">流程名称</label>
                            <div class="layui-input-block">
                                <input type="text" name="processName" required  lay-verify="required" placeholder="请输入流程Key"
                                       autocomplete="off" class="layui-input">
                            </div>
                        </div>
                        <div class="layui-form-item">
                            <label class="layui-form-label">流程描述</label>
                            <div class="layui-input-block">
                                <input type="text" name="processDesc" required  lay-verify="required" placeholder="请输入流程Key"
                                       autocomplete="off" class="layui-input">
                            </div>
                        </div>
                        <div class="layui-form-item" style="margin-top: 20px">
                            <div class="layui-input-block">
                                <button class="layui-btn" lay-submit lay-filter="formDemo">立即提交</button>
                                <button type="reset" class="layui-btn layui-btn-primary">重置</button>
                            </div>
                        </div>

                    </form>

                </div>
            </script>

        </div>
    </div>

    <div class="layui-footer">
        <!-- 底部固定区域 -->
        © layui.com - **系统
    </div>


</div>
<script src="layui/layui.js"></script>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>


<script>
	layui.use(['element','table', 'form'], function()
  	  	element = layui.element;
  	  	table = layui.table;
  	  	form = layui.form;

  	  	//第一个实例
  table.render(
    elem: '#tb-book'
    ,height: 312
    ,url: 'http://localhost:8080/model/page'
    ,where: page: '1', size: '10'
    ,page: true //开启分页
    ,cols: [[ //表头
      field: 'id', title: 'ID', sort: true, fixed: 'left'
      ,field: 'name', title: '流程名称', 
      ,field: 'key', title: '流程Key', 
      ,field: 'category', title: '流程分类', 
      ,field: 'createTime', title: '创建时间', 
      ,fixed: 'right', title:'操作', toolbar: '#barDemo', width:320
    ]]
    ,parseData: function (res)  //将原始数据解析成 table 组件所规定的数据
        console.log(res)
                return 
                    "code": 0, //解析接口状态
                    "count": res.totalData, //解析数据长度
                    "data": res.list //解析数据列表
                ;
     
  );

     // 表格数据重载
    var $ = layui.$, active = 
    reload: function()
      var demoReload = $('#demoReload');
      console.log('----'+ demoReload.val())
      //执行重载
      table.reload('tb-book', 
        page: 
          curr: 1 //重新从第 1 页开始
        
        ,where: 
            name: demoReload.val()
        
      );
    ,
    add: function()
         layer.open(
                type: 1,
                title: '新增流程',
                area: ['420px', '330px'],
                content: $('#edit_form').html()
            );

             form.on('submit(formDemo)',function(messge)
                 console.log(messge);
                 var str=
                                "processDesc":messge.field.processDesc,
                                "processKey":messge.field.processKey,
                                "processName":messge.field.processName
                          ;
                    $.ajax(
                            url:"http://localhost:8080/model/insert",
                            type:"POST",
                            contentType: "application/json; charset=utf-8",
                            dataType: "json",
                            data: JSON.stringify(str),
                            success:function (msg) 
                                console.log("成功消息:" + msg);
                                if (msg.code === 200) 
                                    layer.msg("新增成功", icon: 6);
                                  	layer.closeAll();
                                    // 跳转至流程设计界面
                                     window.location.href ="http://localhost:8080/modeler.html?modelId=" + msg.data
                                 else 
                                    layer.msg("新增失败", icon: 5);
                                
                            
                        )
                        return false;//阻止表单跳转,网页url不显示提交的参数。
                    )

    
  ;

  $('.demoTable .layui-btn').on('click', function()
    var type = $(this).data('type');
    active[type] ? active[type].call(this) : '';
  );


  //监听工具条
  table.on('tool(tb-book)', function(obj)
    console.log(obj);
    var data = obj.data;
    if(obj.event === 'deploy') 

                    $.ajax(
                            url:"http://localhost:8080/model/deploy/" + data.id,
                            type:"POST",
                            success:function (msg) 
                                console.log(msg);
                                // var returnCode = msg.returnValue//取得返回数据(Sting类型的字符串)的信息进行取值判断
                                if (msg.code === 200) 
                                    //layer.closeAll('loading');
                                    //layer.load(2);
                                    layer.msg("模型部署成功:" + msg.data, icon: 6);
                                  	layer.closeAll();
                                    // 加载层 - 风格
                                 else 
                                    layer.msg("模型部署失败", icon: 5);
                                
                            
                        )


     else if(obj.event === 'del')
      layer.confirm('真的删除行么', function(index)
        obj.del();
        layer.close(index);
        console.log('id is:', data.id)
         $.ajax(
                            url:"http://localhost:8080/model/delete?processId="+data.id,
                            success:function (msg) 
                                console.log(msg);
                                // var returnCode = msg.returnValue//取得返回数据(Sting类型的字符串)的信息进行取值判断
                                if (msg) 
                                    //layer.closeAll('loading');
                                    //layer.load(2);
                                    layer.msg("修改成功", icon: 6);
                                  	layer.closeAll();
                                    // 加载层 - 风格
                                 else 
                                    layer.msg("新增失败", icon: 5);
                                
                            
                        )

      );
     else if(obj.event === 'edit')
      console.log("点击编辑")
      window.location.href ="http://localhost:8080/modeler.html?modelId=" + data.id

     else if(obj.event ==='export')
      console.log("点击导出")
      window.location.href ="http://localhost:8080/model/export/" + data.id
     else if(obj.event ==='form')
      console.log("点击表单配置")
      layer.open(
                type: 1,
                title: '流程节点表单设置',
                area: ['520px', '420px'],
                content: $('#node_table').html()
            );
      table.render(
    elem: '#tb-node'
    ,url: 'http://localhost:8080/node/findModelAssociationNode/' + data.id
    ,method: 'post'
    ,cols: [[ //表头
      field: 'id', title: 'ID', sort: true, fixed: 'left'
      ,field: 'name', title: '流程节点名称', 
      ,field: 'formKey', title: '流程外置表单Key', 
      ,field: 'nodeTypeEnum', title: '节点类型', 
      ,fixed: 'right', title:'操作', toolbar: '#nodeDemo'
    ]]
    ,parseData: function (res)  //将原始数据解析成 table 组件所规定的数据
        console.log("节点数据返回:" +res.data)
                return 
                    "code": 0, //解析接口状态
                    "data": res.data //解析数据列表
                ;
     
  );

    


  );

	);
</script>
</body>
</html>

springboot~工作流activiti的搭建

概念工作流产品使用activiti的算是比较多了,自带了一套UI界面,可以直接使用,用来设计流程,下面简单总结一下它的步骤:1设计模型2发布为流程,一个模型可以发布多个版本的流程3建立一个流程的实例和实例任务,一个流... 查看详情

activiti7工作流引擎:进阶篇springboot整合工作流activiti7(代码片段)

...房结婚生子,孩子经常回家陪伴父母,一家人其乐融融。SpringBoot整合Activiti7需要与SpringSecurity整合。SpringBoot整合Activiti7之后的所有数据库Id值都使用了类似于UUID样的值。一:与SpringSecurity整合方式1.pom.xml< 查看详情

activiti查询

一 1.根据当前任务id获得当前任务对象  Tasktask=processEngine.getTaskService().createTaskQuery().taskId(taskId).singleResult();2.根据流程id获得流程实例ProcessInstancepi=processEngine.getRuntimeService().createProcessInstanceQuery().processInstanceId(task.getProc... 查看详情

activity根据流程实例id删除流程实例删除流程部署

--删除流程实例(一定要以下表顺序,否则会报键约束错误)deletefromact_hi_attachmenttwheret.proc_inst_id_=‘7626‘;deletefromact_hi_commenttwheret.proc_inst_id_=‘7626‘;deletefromact_hi_actinsttwheret.proc_inst_id_=‘7626‘;deletefrom 查看详情

URL 中的 Rails slugs - 使用 Active Record 模型帖子的 Title 属性而不是 ID

】URL中的Railsslugs-使用ActiveRecord模型帖子的Title属性而不是ID【英文标题】:RailsslugsinURL-usingActiveRecordModelPost\'sTitleattributeinsteadofID【发布时间】:2010-11-1803:49:48【问题描述】:我一直在尝试让我的Rails创建URL来显示记录,方法是使... 查看详情

springboot2+activiti7整合用流程设计器设计一个流程

我们已常用的请假来设计一个流程。流程设计器参见springboot2+activiti7整合(二)IDEA安装Activiti工作流设计器,通过在项目中右键找到ExternalTools->camunda-modeler开始流程设计。   相同的业务流程,流程定义的 id ... 查看详情

根据模型属性获取django对象id

】根据模型属性获取django对象id【英文标题】:Getdjangoobjectidbasedonmodelattribute【发布时间】:2011-06-0706:12:24【问题描述】:我有一个名为“Places”的基本模型,它有这个视图:defview_index(request,place_name):用户将使用如下URL访问该视... 查看详情

springboot根据不同环境加载对应的配置

 java-jarspringboot.jar-Dspring.profiles.active=dev  查看详情

如何使用 Spatie/Activitylog 根据 id 获取模型属性名称?

】如何使用Spatie/Activitylog根据id获取模型属性名称?【英文标题】:HowtogetmodelattributenamebasedonidusingSpatie/Activitylog?【发布时间】:2019-08-1906:54:31【问题描述】:我正在尝试使用Spatie/Activitylogactivity_log表的属性属性基于Task模型的empl... 查看详情

activiti流程发起人控制

...须重新设置流程发起人,因为通过流程定义不能获取流程模型id,虽然很不合理,但是确实获取不到流程模型id,最后问了同事,可以通过process的key、以及defination的key来进行控制,流程定义的key很好获取,可以通过processDef.getKey( 查看详情

springboot项目在idea根据不同的开发人员读取不同的配置文件

IDEA启动项目打开项目的配置文件,修改Programargument为--spring.profiles.active=developerName启动项目,即可  命令行方式启动项目java-jarxxx.jar--spring.profiles.active=xxxx   查看详情

如何根据Django中相同模型的其他字段ID过滤字段值

】如何根据Django中相同模型的其他字段ID过滤字段值【英文标题】:howtofilterfieldvaluesbasedonotherfieldidofsamemodelinDjango【发布时间】:2021-11-0315:23:48【问题描述】:这里我要过滤每个组的所有项目让我们将我的模型视为classItemsList(mode... 查看详情

Django Rest Framework如何根据ID保存具有相关字段的模型

】DjangoRestFramework如何根据ID保存具有相关字段的模型【英文标题】:DjangoRestFrameworkhowtosaveamodelwithRelatedFieldbasedonID【发布时间】:2015-01-1716:17:31【问题描述】:我对DRF有点陌生。我的Record模型看起来像这样:classRecords(models.Model):o... 查看详情

如何根据数据透视表中两列(两个外键)中的 ID 返回相关模型?

】如何根据数据透视表中两列(两个外键)中的ID返回相关模型?【英文标题】:HowdoIreturnrelatedmodelsbasedonIDsintwocolumnsinpivottable(twoforeignkeys)?【发布时间】:2014-11-2015:50:56【问题描述】:我有一个包含以下列的数据透视表:table-con... 查看详情

elasticsearch序列-springboot整合es:根据指定的ids查询(代码片段)

文章目录1.ElasticSearch根据ids查询文档2.SpringBoot整合ES实现ids查询1.ElasticSearch根据ids查询文档①索引文档,构造数据PUT/my_index/_doc/1"price":10PUT/my_index/_doc/2"price":20PUT/my_index/_doc/3"price":30②查询文档id为1或者2的文... 查看详情

springboot整合工作流activiti7(代码片段)

SpringBoot整合Activiti7需要与SpringSecurity整合。SpringBoot整合Activiti7之后的所有数据库Id值都使用了类似于UUID样的值。SpringBoot又封装了一套API来操作Activiti。1.pom.xml<dependency> <groupId>org.activiti</groupId> <artifactId>activiti-sp... 查看详情

activiti挂起任务能查到吗

参考技术A1、首先是根据流程ID获取当前任务:Listlt;Task;tasks=taskService.createTaskQuery().processInstanceId(procInstanceId).list();2、然后根据当前任务获取当前流程的流程定义,然后根据流程定义获得所有的节点:ProcessDefinitionEntitydef=(ProcessDef... 查看详情

如何从activity页面跳转到fragment页面

...中获得这个id,例如intid=intert.getIntegerExtra("fragid",-1);然后根据这个id跳转即可if(id>0)if(id==目标id)myfragment.setvisible(true);用类似方法即可打字不易,如满意,望采纳。参考技术A你可以在你startactivity的地方,对intent加入一个参数... 查看详情