工作流在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">&times;</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>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<label class="m-checkbox">
<input type="checkbox">
部门经理
<span></span>
</label>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</div>
<div class="form-group" [hidden]="selectItem.type!='connector'">
<label>执行条件</label><br>
<p-radioButton name="radGroup" value="yes" label="通过" [(ngModel)]="condition"></p-radioButton>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<p-radioButton name="radGroup" value="no" label="不通过" [(ngModel)]="condition"></p-radioButton>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<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流程引擎集成的更多相关文章

  1. .NET 开源工作流: Slickflow流程引擎高级开发(七)--消息队列(RabbitMQ)的集成使用

    前言:工作流流程过程中,除了正常的人工审批类型的节点外,事件类型的节点处理也尤为重要.比如比较常见的事件类型的节点有:Timer/Message/Signal等.本文重点阐述消息类型的节点处理,以及实 ...

  2. 基于开源流程引擎开发BPM或OA有哪些难点

    前言     如何基于开源流程引擎开发OA系统?开源流程引擎哪个好?把它整合到自己的产品里难不难,有没有啥风险?这是大家经常遇到的问题.笔者从2006年开始参与流程引擎开发,经历了三代流程引擎研发,支 ...

  3. .NET 开源工作流: Slickflow流程引擎高级开发(十) -- BpmnJS流程设计器集成

    前言: 在Slickflow产品开发过程中,前端流程设计器经历了几个不同的版本(jsPlumb, mxGraph等),目的是为了在设计流程时的用户体验更加良好,得到客户的好评和认可.BpmnJS流程设 ...

  4. Fixflow引擎解析(一)(介绍) - Fixflow开源流程引擎介绍

    Fixflow引擎解析(四)(模型) - 通过EMF扩展BPMN2.0元素 Fixflow引擎解析(三)(模型) - 创建EMF模型来读写XML文件 Fixflow引擎解析(二)(模型) - BPMN ...

  5. 从零开始学习和改造activiti流程引擎的13天,自己记录一下

    day#1(11.13) 尝试通过spring boot 集成最新版activiti 7,但是苦于官方的文档基本为空,无法完成spring boot的配置,最终按照activiti 6的文档,手工初始 ...

  6. 关于广州xx公司对驰骋BPM, 流程引擎表单引擎 常见问题解答

    关于广州xx公司对驰骋BPM, 流程引擎表单引擎 常见问题解答 @驰骋工作流,ccflow周朋 周总早, ccflow 功能很强大,在体验过程中,以下几个问题需沟通下: 先使用.net 再使用java ...

  7. 低代码平台--基于surging开发微服务编排流程引擎构思

    前言 微服务对于各位并不陌生,在互联网浪潮下不是在学习微服务的路上,就是在使用改造的路上,每个人对于微服务都有自己理解,有用k8s 就说自己是微服务,有用一些第三方框架spring cloud, du ...

  8. 项目实践之工作流引擎基本文档!Activiti工作流框架中流程引擎API和服务详解

    流程引擎的API和服务 流程引擎API(ProcessEngine API)是与Activiti打交道的最常用方式 Activiti从ProcessEngine开始.在ProcessEngine中,可 ...

  9. 开源流程引擎osworkflow、jbpm、activiti、flowable、camunda哪个好?

    市场上比较有名的开源流程引擎有osworkflow.jbpm.activiti.flowable.camunda.其中:Jbpm4.Activiti.Flowable.camunda四个框架同宗同源, ...

随机推荐

  1. 用Python操作Excel,实现班级成绩的统计

    本次是在原来有一定格式的Excel文档中补充成绩. 安装的模块:xlwt . xlrd .xlutils xlrd的模块是只用读取xls文件,不能写文件,同理xlwt,只(新建写)不读已有的xls, ...

  2. Cocos2d-x_初探_第一次配置与HelloWorld

    此前多久,忘了,反正就是打通关泡泡龙以后.YY君向我推荐了这个(如题).一查资料,诶.还挺有意思的,那我就去下一个玩玩吧. 资料下载清单: 1.Android-ndk 2.Android-sdk 3. ...

  3. 零零散散的python笔记 2

    python2和python3的兼容性方面 工具 2to3 python3中自带的工具,可以检查python2升级到python3的diff: 2to3 x.py 2to3 -w x.py     # ...

  4. Linux安装git (git-2.11.0)

      本文旨在讲述如何在linux上安装最新版的git.   1.查看当前git版本:git --version 查看最新版git:访问https://www.kernel.org/pub/softwa ...

  5. luogu P4513 小白逛公园 (区间合并)

    链接:https://www.luogu.org/problemnew/show/P4513 思路: 很基础的区间合并,开四个数组: num: 区间数字的和 lsum:从左端点起最大连续字段和 rsu ...

  6. 【转帖】安卓的Bionic 简介

    https://blog.csdn.net/yongyu_it/article/details/52574797 google 自己实现了一套libc 的库函数 比glibc 要小一些 占用内存也小. ...

  7. The import javax.websocket cannot be resolved的解决问题

    在eclipse中导入项目的时候出现了这个问题,废了我半天劲,才搞明白,把问题记录下来,方便大家以后遇到这问题好处理.提供参考. 出现的问题截图: 因为我用的是tomcat8, 大体步骤:项目上点右键 ...

  8. win10下访问vm虚拟机Linux服务

    一.环境 win10操作系统 centos6.5 VMware® Workstation 14 Pro虚拟机 二.互相访问设置步骤 1.查看如下图所示 2.记住上面的IP和网关,进行如下图操作 点击应 ...

  9. redis哨兵sentinel.conf文件

    关闭保护模式 //17行 protected-mode no 端口号 //21 port 26379 后台启动 //26 daemonize yes //84行 主机的ip加端口号 2 为票数 sen ...

  10. 用CTime类得到当前日期 时间

    (1)定义一个CTime类的对象CTime time: (2)得到当前时间time = CTime::GetCurrentTime(); (3)Get Year(),GetMonth(),GetDay ...