郭卫东 发表于 2023-4-20 21:22:16

boot-admin整合flowable官方editor-app进行BPMN2.0建模

正所谓百家争鸣、见仁见智、众说纷纭、各有千秋!在工作流bpmn2.0可视化建模工具实现的细分领域,网上扑面而来的是 bpmn.js 这个渲染工具包和web建模器,而笔者却认为使用flowable官方开源 editor-app 才是王道。
Flowable 开源版本中的 web 版流程设计器editor-app,展示风格和功能基本跟 activiti-modeler 一样,集成简单,开发工作量小,界面美观大方,功能强大,用户体验友好。
通过以下两张Gif动图来个PK,您的直观感受如何呢?
bpmn.js运行效果图(gif动图取自互联网)
https://img2023.cnblogs.com/blog/3173544/202304/3173544-20230420210544438-747915579.gif
Flowable editor-app运行效果:
https://img2023.cnblogs.com/blog/3173544/202304/3173544-20230420210559990-920566339.gif
boot-admin 是一款采用前后端分离模式、基于SpringCloud微服务架构的SaaS后台管理框架。系统内置基础管理、权限管理、运行管理、定义管理、代码生成器和办公管理6个功能模块,集成分布式事务Seata、工作流引擎Flowable、业务规则引擎Drools、后台作业调度框架Quartz等,技术栈包括Mybatis-plus、Redis、Nacos、Seata、Flowable、Drools、Quartz、SpringCloud、Springboot Admin Gateway、Liquibase、jwt、Openfeign、I18n等。
gitee源码地址
github源码地址
下面介绍 boot-admin 对flowable官方bpmn2.0可视化建模工具 editor-app 的集成改造步骤:
获取前端源码


[*]下载官方数据包flowable-6.4.1.zip
[*]从压缩包中解压出flowable-6.4.1\wars下面的flowable-modeler.war
[*]从flowable-modeler.war中解压出 WEB-INF\classes\static\editor-app 文件夹
[*]将数据包中 editor-app 文件夹复制到 boot-admin项目 前端工程的 public 文件夹下面
[*]在 boot-admin项目 前端工程 public 文件夹下面创建 modeler.html 作为编辑器入口
modeler.html内容:
<!doctype html>




<html >
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Activiti Editor</title>
    <meta name="description" content="">
    <meta name="viewport"
          content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, width=device-width">
   
    <link rel="Stylesheet" media="screen" href="/editor-app/libs/ng-grid-2.0.7.min.css" type="text/css"/>
    <link rel="stylesheet" href="/editor-app/libs/bootstrap_3.1.1/css/bootstrap.min.css"/>
    <link rel="Stylesheet" media="screen" href="/editor-app/editor/css/editor.css" type="text/css"/>
    <link rel="stylesheet" href="/editor-app/css/style.css" type="text/css"/>
    <link rel="stylesheet" href="/editor-app/css/style-common.css">
    <link rel="stylesheet" href="/editor-app/css/style-editor.css">
</head>
<body>



       

       
          
                <i
                   ng-></i>
                {{alerts.current.message}}

                 0">
                    {{alerts.queue.length + 1}}
                
          
       

       
       

       

       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
       
</body>
</html>整合改造前端源码


[*]修改 ACTIVITI.CONFIG ,设置网关 URL
var ACTIVITI = ACTIVITI || {};
ACTIVITI.CONFIG = {
        'contextRoot' : 'http://网关IP:网关端口号/api/workflow/auth/activiti',
};
[*]修改 configuration\url-config.js,设置各具体访问点URL
var KISBPM = KISBPM || {};

KISBPM.URL = {
//通过modelId,获取已保存模型的json数据
getModel: function(modelId) {
    return ACTIVITI.CONFIG.contextRoot + '/model/json?modelId=' + modelId;
},
//获取汉化资源json数据
getStencilSet: function() {
    return ACTIVITI.CONFIG.contextRoot + '/editor/stencilset?version=' + Date.now();
},
//保存模型数据
putModel: function(modelId) {
    return ACTIVITI.CONFIG.contextRoot + '/model/save?modelId=' + modelId;
},
//从cookie中读取令牌
getToken: function() {
    var cookies = document.cookie;
    var list = cookies.split("; "); // 解析出名/值对列表

    for (var i = 0; i < list.length; i++) {
      var arr = list.split("="); // 解析出名和值
      if (arr == "Admin-Token") {
      var cookieVal = decodeURIComponent(arr); // 对cookie值解码
      break;
      }
    }
    return 'Bearer' + cookieVal;
}
};
[*]修改 /public/editor-app/stencil-controller.js 中获取汉化包的方法,由源码中自由访问修改为携带令牌访问后台资源
            $http({method: 'GET',
            headers: {
                  'X-Token': KISBPM.URL.getToken()
            },
            url: KISBPM.URL.getStencilSet()})
            .success(function (data, status, headers, config) {

                    var quickMenuDefinition = ['UserTask', 'EndNoneEvent', 'ExclusiveGateway',
                                               'CatchTimerEvent', 'ThrowNoneEvent', 'TextAnnotation',
                                               'SequenceFlow', 'Association'];
                    var ignoreForPaletteDefinition = ['SequenceFlow', 'MessageFlow', 'Association', 'DataAssociation', 'DataStore', 'SendTask'];
                    var quickMenuItems = [];

                    var morphRoles = [];
                for (var i = 0; i < data.rules.morphingRules.length; i++)
                {
                  var role = data.rules.morphingRules.role;
                  var roleItem = {'role': role, 'morphOptions': []};
                  morphRoles.push(roleItem);
                }

                // Check all received items
                for (var stencilIndex = 0; stencilIndex < data.stencils.length; stencilIndex++)
                {
                        // Check if the root group is the 'diagram' group. If so, this item should not be shown.
                  var currentGroupName = data.stencils.groups;
                  if (currentGroupName === 'Diagram' || currentGroupName === 'Form') {
                        continue;// go to next item
                  }

                  var removed = false;
                  if (data.stencils.removed) {
                        removed = true;
                  }

                  var currentGroup = undefined;
                  if (!removed) {
                        // Check if this group already exists. If not, we create a new one

                        if (currentGroupName !== null && currentGroupName !== undefined && currentGroupName.length > 0) {

                            currentGroup = findGroup(currentGroupName, stencilItemGroups); // Find group in root groups array
                            if (currentGroup === null) {
<template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template>currentGroup = addGroup(currentGroupName, stencilItemGroups);
                            }

                            // Add all child groups (if any)
                            for (var groupIndex = 1; groupIndex < data.stencils.groups.length; groupIndex++) {
<template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template>var childGroupName = data.stencils.groups;
<template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template>var childGroup = findGroup(childGroupName, currentGroup.groups);
<template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template>if (childGroup === null) {
<template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template>    childGroup = addGroup(childGroupName, currentGroup.groups);
<template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template>}

<template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template>// The current group variable holds the parent of the next group (if any),
<template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template>// and is basically the last element in the array of groups defined in the stencil item
<template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template>currentGroup = childGroup;

                            }

                        }
                  }

                  // Construct the stencil item
                  var stencilItem = {'id': data.stencils.id,
                        'name': data.stencils.title,
                        'description': data.stencils.description,
                        'icon': data.stencils.icon,
                        'type': data.stencils.type,
                        'roles': data.stencils.roles,
                        'removed': removed,
                        'customIcon': false,
                        'canConnect': false,
                        'canConnectTo': false,
                        'canConnectAssociation': false};

                  if (data.stencils.customIconId && data.stencils.customIconId > 0) {
                        stencilItem.customIcon = true;
                        stencilItem.icon = data.stencils.customIconId;
                  }

                  if (!removed) {
                        if (quickMenuDefinition.indexOf(stencilItem.id) >= 0) {
                                quickMenuItems = stencilItem;
                        }
                  }

                  if (stencilItem.id === 'TextAnnotation' || stencilItem.id === 'BoundaryCompensationEvent') {
                          stencilItem.canConnectAssociation = true;
                  }

                  for (var i = 0; i < data.stencils.roles.length; i++) {
                          var stencilRole = data.stencils.roles;
                          if (stencilRole === 'sequence_start') {
                                  stencilItem.canConnect = true;
                          } else if (stencilRole === 'sequence_end') {
                                  stencilItem.canConnectTo = true;
                          }

                          for (var j = 0; j < morphRoles.length; j++) {
                                  if (stencilRole === morphRoles.role) {
                                    if (!removed) {
                                               morphRoles.morphOptions.push(stencilItem);
                                          }
                                          stencilItem.morphRole = morphRoles.role;
                                          break;
                                  }
                          }
                  }

                  if (currentGroup) {
                            // Add the stencil item to the correct group
                            currentGroup.items.push(stencilItem);
                            if (ignoreForPaletteDefinition.indexOf(stencilItem.id) < 0) {
                                    currentGroup.paletteItems.push(stencilItem);
                            }

                  } else {
                        // It's a root stencil element
                        if (!removed) {
                            stencilItemGroups.push(stencilItem);
                        }
                  }
                }

                for (var i = 0; i < stencilItemGroups.length; i++)
                {
                        if (stencilItemGroups.paletteItems && stencilItemGroups.paletteItems.length == 0)
                        {
                                stencilItemGroups.visible = false;
                        }
                }

                $scope.stencilItemGroups = stencilItemGroups;

                var containmentRules = [];
                for (var i = 0; i < data.rules.containmentRules.length; i++)
                {
                  var rule = data.rules.containmentRules;
                  containmentRules.push(rule);
                }
                $scope.containmentRules = containmentRules;

                // remove quick menu items which are not available anymore due to custom pallette
                var availableQuickMenuItems = [];
                for (var i = 0; i < quickMenuItems.length; i++)
                {
                  if (quickMenuItems) {
                        availableQuickMenuItems = quickMenuItems;
                  }
                }

                $scope.quickMenuItems = availableQuickMenuItems;
                $scope.morphRoles = morphRoles;
            }).

            error(function (data, status, headers, config) {
                console.log('Something went wrong when fetching stencil items:' + JSON.stringify(data));
            });
[*]修改 /public/editor-app/app.js 中获取模型数据的方法,由源码中自由访问修改为携带令牌访问后台资源
            function fetchModel(modelId) {
                var modelUrl = KISBPM.URL.getModel(modelId);
                $http({method: 'GET',
                headers: {'X-Token': KISBPM.URL.getToken()},
                url: modelUrl}).
                  success(function (data, status, headers, config) {
                        $rootScope.editor = new ORYX.Editor(data);
                        $rootScope.modelData = angular.fromJson(data);
                        $rootScope.editorFactory.resolve();
                  }).
                  error(function (data, status, headers, config) {
                      console.log('Error loading model with id ' + modelId + ' ' + data);
                  });
            }
[*]修改 /public/editor-app/configuration/toolbar-default-actions.js 中保存模型的方法,由源码中自由访问修改为携带令牌访问后台资源
      $http({    method: 'PUT',
            data: params,
            ignoreErrors: true,
            headers: {'Accept': 'application/json',
                      'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
                      'X-Token': KISBPM.URL.getToken()},
            transformRequest: function (obj) {
                var str = [];
                for (var p in obj) {
                  str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj));
                }
                return str.join("&");
            },
            url: KISBPM.URL.putModel(modelMetaData.modelId)})

            .success(function (data, status, headers, config) {
                $scope.editor.handleEvents({
                  type: ORYX.CONFIG.EVENT_SAVED
                });
                $scope.modelData.name = $scope.saveDialog.name;
                $scope.modelData.lastUpdated = data.lastUpdated;

                $scope.status.loading = false;
                $scope.$hide();

                // Fire event to all who is listening
                var saveEvent = {
                  type: KISBPM.eventBus.EVENT_TYPE_MODEL_SAVED,
                  model: params,
                  modelId: modelMetaData.modelId,
                            eventType: 'update-model'
                };
                KISBPM.eventBus.dispatch(KISBPM.eventBus.EVENT_TYPE_MODEL_SAVED, saveEvent);

                // Reset state
                $scope.error = undefined;
                $scope.status.loading = false;

                // Execute any callback
                if (successCallback) {
                  successCallback();
                }

            })
            .error(function (data, status, headers, config) {
                $scope.error = {};
                console.log('Something went wrong when updating the process model:' + JSON.stringify(data));
                $scope.status.loading = false;
            });
[*]创建 Modeler.vue 组件,以 iframe 形式将 editor-app 嵌入 vue-element-ui的弹窗 el-dialog 中
<template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template>
[*]模型管理VUE文件
<template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template><template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template><template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template><template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template><template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template><template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template><template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template><template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template><template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template>                      查询            重置                        关闭<template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template><template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template>刷新                        新建                        查询<template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template><template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template><template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template>{{ props.row.id }}<template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template>            {{ props.row.key }}<template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template>            {{ props.row.name }}<template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template>            {{ props.row.version }}<template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template>            {{ $commonUtils.dateTimeFormat(props.row.createTime) }}<template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template>            {{ $commonUtils.dateTimeFormat(props.row.lastUpdateTime) }}<template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template><template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template><template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template><template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template>                  修改            删除            部署            XML<template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template><template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template><template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template><template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template><template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template>                      关闭                        创建                        重置<template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template>                  关闭                        生成文件<template>

    <el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" width="80%" height="100%" title="模型编辑器" @close="closeDialog">
      
      <iframe ref="Modeler" id="map" scrolling="auto" v-bind:src="contents"
          frameborder="0" ></iframe>
      
    </el-dialog>

</template>workflow-model.js
import request from '@/utils/request'

//分页获取模型数据
export function fetchModelPage(data) {
return request({
    url: '/api/workflow/auth/activiti/model/page',
    method: 'post',
    data
})
}

//保存模型
export function saveNewModel(data) {
return request({
    url: '/api/workflow/auth/activiti/model/add',
    method: 'post',
    data
})
}

//删除模型数据
export function delModel(data) {
return request({
    url: '/api/workflow/auth/activiti/model/del',
    method: 'post',
    data
})
}

//部署模型
export function deployModel(data) {
return request({
    url: '/api/workflow/auth/activiti/model/deploy',
    method: 'post',
    data
})
}

//获取模型XML
export function fetchXml(data) {
return request({
    url: '/api/workflow/auth/activiti/model/xml',
    method: 'post',
    data
})
}后端功能实现

对应前端需求,后端主要实现使用flowable引擎,获取汉化资源、读取模型数据、保存模型数据三个功能。
具体内容参见下一篇博文
项目源码仓库github
项目源码仓库gitee

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: boot-admin整合flowable官方editor-app进行BPMN2.0建模