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">&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的流程设计器已经介绍完毕,要实现工作流机制需要针对自己的系统作表单设计和业务关联,相关的实现文档有很多,这里就不过多介绍了。目前功能还比较粗糙,优化完后我会对这些功能进行开源,感兴趣的可以后续关注。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM