angular流程引擎集成
工作流在oa和erp中十分常见,现有成熟的工作流通常是在客户端实现的,web实现工作流的案例十分稀少。要实现web工作流必须要有强大的流程设计器,这里为大家介绍一款基于angular的流程控件,其功能十分强大,可直接开发在线流程设计工具。
流程设计效果如下:

该流程工具使用的是syncfusion旗下的angular组件开发,需要先安装组件: @syncfusion/ej2-angular-diagrams
angular项目中添加demo-flow组件,在demo-flow目录中添加script文件夹,script中粘贴diagram-common.js
准备就绪后开始布局流程页面,布局代码如下:
<script src="script/diagram-common.ts"></script>
<div class="m-portlet m-portlet--mobile">
<div class="m-portlet__head">
<div class="m-portlet__head-caption">
<div class="m-portlet__head-title">
<h3 class="m-portlet__head-text">
流程设计测试
</h3>
</div>
</div>
</div>
<div class="diagram-serialization" style="width: 100%;height: 10%">
<ejs-toolbar width="100%" (clicked)="onClicked($event)">
<e-items>
<e-item text='New' tooltipText='New' prefixIcon='e-ddb-icons e-new'></e-item>
<e-item type='Separator'></e-item>
<e-item text='Save' tooltipText='Save' prefixIcon='e-ddb-icons e-save'></e-item>
<e-item type='Separator'></e-item>
<e-item text='Load' tooltipText='Load' prefixIcon='e-ddb-icons e-open'></e-item>
<e-item type='Separator'></e-item>
</e-items>
</ejs-toolbar>
</div>
<div style="width:100%;height: 80%">
<div id="palette-space" class="sb-mobile-palette">
<ejs-symbolpalette id="symbolpalette" [enableAnimation]='enableAnimation' [expandMode]='expandMode'
[palettes]='palettes' (created)='create($event)' width="100%" height="700px" [symbolHeight]=60
[symbolWidth]=60 [symbolMargin]='symbolMargin' [getSymbolInfo]='getSymbolInfo'
[getNodeDefaults]='getSymbolDefaults'>
</ejs-symbolpalette>
</div> <div id="diagram-space" class="sb-mobile-diagram">
<div class="content-wrapper">
<ejs-diagram #diagram id="diagram" width="100%" height="700px" [snapSettings]='snapSettings'
[getConnectorDefaults]='getConnectorDefaults' (doubleClick)="doubleClick($event)">
<e-nodes>
<e-node id='Start' [height]=50 [width]=100 [shape]='terminator' [offsetX]=250 [offsetY]=80
[style]='terminatorStyle'>
<e-node-annotations>
<e-node-annotation content='Start'>
</e-node-annotation>
</e-node-annotations>
</e-node>
<e-node id='Alarm' [height]=50 [width]=100 [shape]='process' [offsetX]=250 [offsetY]=160
[style]='processStyle'>
<e-node-annotations>
<e-node-annotation content='Alarm Rings'>
</e-node-annotation>
</e-node-annotations>
</e-node>
<e-node id='Ready' [height]=50 [width]=100 [shape]='decision' [offsetX]=250 [offsetY]=240
[style]='decisionStyle'>
<e-node-annotations>
<e-node-annotation content='Ready to Get Up?'>
</e-node-annotation>
</e-node-annotations>
</e-node>
<e-node id='Climb' [height]=50 [width]=100 [shape]='process' [offsetX]=250 [offsetY]=330
[style]='processStyle'>
<e-node-annotations>
<e-node-annotation content='Climb Out of Bed'>
</e-node-annotation>
</e-node-annotations>
</e-node>
<e-node id='End' [height]=50 [width]=100 [shape]='terminator' [offsetX]=250 [offsetY]=430
[style]='terminatorStyle'>
<e-node-annotations>
<e-node-annotation content='End'>
</e-node-annotation>
</e-node-annotations>
</e-node>
<e-node id='Relay' [height]=50 [width]=100 [shape]='delay' [offsetX]=450 [offsetY]=160
[style]='delayStyle'>
<e-node-annotations>
<e-node-annotation content='Relay'>
</e-node-annotation>
</e-node-annotations>
</e-node>
<e-node id='Hit' [height]=50 [width]=100 [shape]='process' [offsetX]=450 [offsetY]=240
[style]='processStyle'>
<e-node-annotations>
<e-node-annotation content='Hit Snooze Button'>
</e-node-annotation>
</e-node-annotations>
</e-node>
</e-nodes>
<e-connectors>
<e-connector id='connector1' sourceID='Start' targetID='Alarm'>
</e-connector>
<e-connector id='connector2' sourceID='Alarm' targetID='Ready'>
</e-connector>
<e-connector id='connector3' sourceID='Ready' targetID='Climb'>
<e-connector-annotations>
<e-connector-annotation content='Yes' [style]='connectorTextStyle'>
</e-connector-annotation>
</e-connector-annotations>
</e-connector>
<e-connector id='connector4' sourceID='Climb' targetID='End'>
</e-connector>
<e-connector id='connector5' sourceID='Ready' targetID='Hit'>
<e-connector-annotations>
<e-connector-annotation content='No' [style]='connectorTextStyle'>
</e-connector-annotation>
</e-connector-annotations>
</e-connector>
<e-connector id='connector6' sourceID='Hit' targetID='Relay'>
</e-connector>
<e-connector id='connector7' sourceID='Relay' targetID='Alarm'>
</e-connector>
</e-connectors>
</ejs-diagram>
</div>
<ejs-uploader #defaultupload id='fileupload' (success)='onUploadSuccess($event)'
[asyncSettings]='asyncSettings'></ejs-uploader>
</div>
</div> <div bsModal #createOrEditModal="bs-modal" class="modal fade" tabindex="-1" role="dialog"
aria-labelledby="createOrEditModal" aria-hidden="true" [config]="{backdrop:'static'}">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">
<span>修改节点</span>
</h4>
<button type="button" class="close" (click)="close()" attr.aria-label="关闭">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<label>Id</label>
<input type="text" class="form-control" [(ngModel)]="selectItem.id" readonly>
</div>
<div class="form-group" [hidden]="selectItem.type!='node'">
<label>名称*</label>
<input type="text" class="form-control" [(ngModel)]="selectItem.name">
</div>
<div class="form-group" [hidden]="selectItem.type!='node'">
<label>执行权限</label>
<select class="form-control" [formControl]="selectedState">
<option value="">选择执行权限</option>
<option value="1">所有人</option>
<option value="2">指定角色</option>
</select>
</div>
<div class="form-group" [hidden]="selectItem.type!='node' || selectedState.value!='2'">
<label class="m-checkbox">
<input type="checkbox">
部门主管
<span></span>
</label>
<label class="m-checkbox">
<input type="checkbox">
部门经理
<span></span>
</label>
</div>
<div class="form-group" [hidden]="selectItem.type!='connector'">
<label>执行条件</label><br>
<p-radioButton name="radGroup" value="yes" label="通过" [(ngModel)]="condition"></p-radioButton>
<p-radioButton name="radGroup" value="no" label="不通过" [(ngModel)]="condition"></p-radioButton>
<p-radioButton name="radGroup" value="scope" label="执行范围" [(ngModel)]="condition"></p-radioButton>
</div>
<div class="form-row" [hidden]="selectItem.type!='connector' || condition!='scope'">
<div class="form-group col-md-4">
<label>运算符</label>
<select class="form-control" [formControl]="operator">
<option value="">选择运算符</option>
<option value="大于">大于</option>
<option value="小于">小于</option>
<option value="等于">等于</option>
</select>
</div>
<div class="form-group col-md-4">
<label class="">值</label>
<div class="">
<input type="number" [(ngModel)]="scopeValue" class="form-control" placeholder="值">
</div>
</div>
<div class="form-group col-md-4">
<label>单位</label>
<select class="form-control" [formControl]="unit">
<option value="">选择单位</option>
<option value="天">天</option>
<option value="小时">小时</option>
<option value="元">元</option>
</select>
</div>
</div> </div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" (click)="close()">关闭</button>
<button type="button" class="btn btn-primary" (click)="save()">
<i class="fa fa-save"></i><span>保存</span>
</button>
</div>
</div> </div>
</div>
</div>
流程页面模板中加入了双击节点和连接器的事件,如果要开发工作流必须要对事件作处理,仅开发流程设计器则需要取消双击事件以免影响使用。
事件处理如下:
public doubleClick(args: IDoubleClickEventArgs): void {
var node = this.diagram.selectedItems.nodes[0];
var connector = this.diagram.selectedItems.connectors[0];
if (node) {
this.selectItem.id = node.id;
this.selectItem.name = node.annotations[0].content;
this.selectItem.type = 'node';
this.modal.show();
}
if (connector) {
this.selectItem.id = connector.id;
this.selectItem.name = connector.annotations[0].content;
this.selectItem.type = 'connector';
this.modal.show();
}
}
save(): void {
if (this.diagram.selectedItems.nodes[0]) {
this.diagram.selectedItems.nodes[0].annotations[0].content = this.selectItem.name;
this.close();
}
if (this.diagram.selectedItems.connectors[0]) {
if(this.condition=='yes'){
this.diagram.selectedItems.connectors[0].annotations[0].content="通过";
}
if(this.condition=='no'){
this.diagram.selectedItems.connectors[0].annotations[0].content="不通过";
}
if(this.condition=='scope'){
this.diagram.selectedItems.connectors[0].annotations[0].content=this.operator.value+' '+this.scopeValue+' '+this.unit.value;
}
this.close();
}
}
close(): void {
this.modal.hide();
}
流程器显示和双击功能如下:



到这里angular的流程设计器已经介绍完毕,要实现工作流机制需要针对自己的系统作表单设计和业务关联,相关的实现文档有很多,这里就不过多介绍了。目前功能还比较粗糙,优化完后我会对这些功能进行开源,感兴趣的可以后续关注。
angular流程引擎集成的更多相关文章
- .NET 开源工作流: Slickflow流程引擎高级开发(七)--消息队列(RabbitMQ)的集成使用
前言:工作流流程过程中,除了正常的人工审批类型的节点外,事件类型的节点处理也尤为重要.比如比较常见的事件类型的节点有:Timer/Message/Signal等.本文重点阐述消息类型的节点处理,以及实 ...
- 基于开源流程引擎开发BPM或OA有哪些难点
前言 如何基于开源流程引擎开发OA系统?开源流程引擎哪个好?把它整合到自己的产品里难不难,有没有啥风险?这是大家经常遇到的问题.笔者从2006年开始参与流程引擎开发,经历了三代流程引擎研发,支 ...
- .NET 开源工作流: Slickflow流程引擎高级开发(十) -- BpmnJS流程设计器集成
前言: 在Slickflow产品开发过程中,前端流程设计器经历了几个不同的版本(jsPlumb, mxGraph等),目的是为了在设计流程时的用户体验更加良好,得到客户的好评和认可.BpmnJS流程设 ...
- Fixflow引擎解析(一)(介绍) - Fixflow开源流程引擎介绍
Fixflow引擎解析(四)(模型) - 通过EMF扩展BPMN2.0元素 Fixflow引擎解析(三)(模型) - 创建EMF模型来读写XML文件 Fixflow引擎解析(二)(模型) - BPMN ...
- 从零开始学习和改造activiti流程引擎的13天,自己记录一下
day#1(11.13) 尝试通过spring boot 集成最新版activiti 7,但是苦于官方的文档基本为空,无法完成spring boot的配置,最终按照activiti 6的文档,手工初始 ...
- 关于广州xx公司对驰骋BPM, 流程引擎表单引擎 常见问题解答
关于广州xx公司对驰骋BPM, 流程引擎表单引擎 常见问题解答 @驰骋工作流,ccflow周朋 周总早, ccflow 功能很强大,在体验过程中,以下几个问题需沟通下: 先使用.net 再使用java ...
- 低代码平台--基于surging开发微服务编排流程引擎构思
前言 微服务对于各位并不陌生,在互联网浪潮下不是在学习微服务的路上,就是在使用改造的路上,每个人对于微服务都有自己理解,有用k8s 就说自己是微服务,有用一些第三方框架spring cloud, du ...
- 项目实践之工作流引擎基本文档!Activiti工作流框架中流程引擎API和服务详解
流程引擎的API和服务 流程引擎API(ProcessEngine API)是与Activiti打交道的最常用方式 Activiti从ProcessEngine开始.在ProcessEngine中,可 ...
- 开源流程引擎osworkflow、jbpm、activiti、flowable、camunda哪个好?
市场上比较有名的开源流程引擎有osworkflow.jbpm.activiti.flowable.camunda.其中:Jbpm4.Activiti.Flowable.camunda四个框架同宗同源, ...
随机推荐
- Linux学习—yum命令(转载)
yum简介 yum( Yellow dog Updater, Modified)是一个在Fedora和RedHat以及SUSE中的Shell前端软件包管理器. 基於RPM包管理,能够从指定的服务器自动 ...
- vue项目在(windowServer)nginx上的部署
(一) 本地部署. 1.下载phpStudy (http://phpstudy.php.cn/) 2.安装到自己指定盘根目录的文件夹目录,安装完后会用到. 3.运行phpStusy可能报错,需要下载安 ...
- 四、VSCode调试vue项目
1.先决条件设置 你必须安装好 Chrome 和 VS Code.同时请确保自己在 VS Code 中安装了 Debugger for Chrome 扩展的最新版本. 在可以从 VS Code 调试你 ...
- HTML基础知识自学教程
HTML 是用来描述网页的一套标记标签,是我们在web前端开发中的基础.下面PHP程序员雷雪松主要结合自己的经验给大家分享下HTML的基础知识,以及在自学过程中一些比较常用的和重要的HTML知识点. ...
- uni-app 手指左右滑动实现翻页效果
首先给页面添加 touch 事件 <view class="text-area" @touchstart="start" @touchend=" ...
- vue如何监听键盘事件中的按键?
原文地址 背景 在一些搜索框中,我们往往需要监听键盘的按下(onkeydown)或抬起(onkeyup)事件以进行一些操作.在原生js或者jQuery中,我们需要判断e.keyCode的值来获取用户所 ...
- 【计算机视觉】基于样本一致性的背景减除运动目标检测算法(SACON)
SACON(SAmple CONsensus)算法是基于样本一致性的运动目标检测算法.该算法通过对每个像素进行样本一致性判断来判定像素是否为背景. 算法框架图 由上图可知,该算法主要分为四个主要部分, ...
- [转帖]nginx1.17.2版本源码安装
nginx1.17.2版本源码安装 原创: 沧海书生 Ansible爱好者 昨天 公众号里面的内容 这里简单测试了下 在x86的虚拟机里面编译安装 nginx 仅make make install n ...
- HDU1285(拓扑排序裸题
..被多组测试坑了一波 #include<iostream> #include<vector> #include<queue> using namespace st ...
- 二维数组(解引用、指针数组、数组的指针)——C语言
二维数组 在说二维数组前先来说下一维数组中的指针数组和和数组的指针 一.一维数组中指针数组和数组指针的区别 指针数组: ]; []的优先级比*高,首先它是一个数组,它的大小是5,它里面存放的数据类型是 ...