提交 6b6d9a85 编写于 作者: W wq1234wq

工具栏修改

上级 c4088098
<nz-row class="customrow">
<nz-code-editor (ngModelChange)="ngModelChange($event)"
style="width: 100%; height: 500px; padding-top: 1rem" class="editor" [(ngModel)]="Json"
[ngModelOptions]="{ standalone: true }" [nzEditorOption]="{ theme: 'vs',language: 'json' }">
</nz-code-editor>
</nz-row>
<nz-row class="customrow">
<nz-tree-view [nzTreeControl]="treeControl" [nzDataSource]="dataSource" [trackBy]="trackBy">
<nz-tree-node *nzTreeNodeDef="let node; when: hasChild" nzTreeNodeIndentLine>
<nz-tree-node-toggle>
<i nz-icon nzType="caret-down" nzTreeNodeToggleRotateIcon></i>
</nz-tree-node-toggle>
<nz-select [(ngModel)]="node.field">
<nz-option *ngFor="let option of columns" [nzLabel]="option.label" [nzValue]="option.value"></nz-option>
</nz-select>
<nz-select [(ngModel)]="node.operator">
<nz-option nzLabel="等于" nzValue="="></nz-option>
<nz-option nzLabel="大于" nzValue=">"></nz-option>
<nz-option nzLabel="小于" nzValue="<"></nz-option>
<!-- <nz-option nzLabel="小于等于" nzValue="=<"></nz-option>
<nz-option nzLabel="大于等于" nzValue=">="></nz-option> -->
</nz-select>
<input nz-input placeholder="值" [(ngModel)]="node.text" />
<nz-select [(ngModel)]="node.connector">
<nz-option nzLabel="AND" nzValue="&&"></nz-option>
<nz-option nzLabel="OR" nzValue="||"></nz-option>
</nz-select>
<button nz-button nzType="text" nzSize="small" (click)="addNewNode(node)">
<i nz-icon nzType="plus" nzTheme="outline"></i>
</button>
<button nz-button nzType="text" nzSize="small" (click)="delete(node)">
<i nz-icon nzType="minus" ></i>
</button>
</nz-tree-node>
</nz-tree-view>
</nz-row>
<nz-row class="customrow">
<textarea nz-input placeholder="test expression" [(ngModel)]="expression" [nzAutosize]="{ minRows: 3, maxRows: 5 }"></textarea>
<ng-template #suffixTemplateInfo>
<i nz-icon nz-tooltip nzTooltipTitle="" nzType="info-circle" ></i>
</ng-template>
</nz-row>
<nz-row class="customrow">
<button nz-button nzType="primary" nzShape="round" (click)="create()"><i nz-icon nzType="download"></i>生成</button>
<button nz-button nzType="primary" nzShape="round" (click)="close()"><i nz-icon nzType="download"></i>关闭</button></nz-row>
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ConditionbuilderComponent } from './conditionbuilder.component';
describe('ConditionbuilderComponent', () => {
let component: ConditionbuilderComponent;
let fixture: ComponentFixture<ConditionbuilderComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ ConditionbuilderComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ConditionbuilderComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
import { NzTreeFlatDataSource, NzTreeFlattener } from 'ng-zorro-antd/tree-view';
import { SelectionModel } from '@angular/cdk/collections';
import { FlatTreeControl } from '@angular/cdk/tree';
import { NzDrawerRef } from 'ng-zorro-antd/drawer';
@Component({
selector: 'app-conditionbuilder',
templateUrl: './conditionbuilder.component.html',
styleUrls: ['./conditionbuilder.component.less']
})
export class ConditionbuilderComponent implements OnInit {
treeData: TreeNode[] = [
{
name: '1',
key: '1',
children: []
}
];
columns = [
];
private transformer = (node: TreeNode, level: number): FlatNode => {
const existingNode = this.nestedNodeMap.get(node);
const flatNode =
existingNode && existingNode.key === node.key
? existingNode
: {
expandable: true,
name: node.name,
level,
key: node.key
};
flatNode.name = node.name;
this.flatNodeMap.set(flatNode, node);
this.nestedNodeMap.set(node, flatNode);
return flatNode;
};
flatNodeMap = new Map<FlatNode, TreeNode>();
nestedNodeMap = new Map<TreeNode, FlatNode>();
selectListSelection = new SelectionModel<FlatNode>(true);
treeControl = new FlatTreeControl<FlatNode>(
node => node.level,
node => node.expandable
);
treeFlattener = new NzTreeFlattener(
this.transformer,
node => node.level,
node => node.expandable,
node => node.children
);
dataSource = new NzTreeFlatDataSource(this.treeControl, this.treeFlattener);
constructor(private drawerRef: NzDrawerRef<string>) {
this.dataSource.setData(this.treeData);
this.treeControl.expandAll();
}
Json = '{"a":1,"b":2,"c":3}';
ngModelChange($event) {
var data = JSON.parse($event);
this.columns = [];
for (let key in data) {
this.columns.push({ label: key, value: key });
}
}
ngOnInit(): void {
var data = JSON.parse(this.Json);
this.columns = [];
for (let key in data) {
this.columns.push({ label: key, value: key });
}
}
hasChild = (_: number, node: FlatNode): boolean => true;
hasNoContent = (_: number, node: FlatNode): boolean => node.name === '';
trackBy = (_: number, node: FlatNode): string => `${node.key}-${node.name}`;
close(){
this.drawerRef.close({expression:this.expression,orgin:this.treeData})
}
delete(node: FlatNode): void {
const originNode = this.flatNodeMap.get(node);
const dfsParentNode = (): TreeNode | null => {
const stack = [...this.treeData];
while (stack.length > 0) {
const n = stack.pop()!;
if (n.children) {
if (n.children.find(e => e === originNode)) {
return n;
}
for (let i = n.children.length - 1; i >= 0; i--) {
stack.push(n.children[i]);
}
}
}
return null;
};
const parentNode = dfsParentNode();
if (parentNode && parentNode.children) {
parentNode.children = parentNode.children.filter(e => e !== originNode);
}
this.dataSource.setData(this.treeData);
}
addNewNode(node: FlatNode): void {
const parentNode = this.flatNodeMap.get(node);
if (parentNode) {
parentNode.children = parentNode.children || [];
parentNode.children.push({
name: node.field,
key: `${parentNode.key}-${parentNode.children.length}`,
children: []
});
this.dataSource.setData(this.treeData);
this.treeControl.expand(node);
}
}
saveNode(node: FlatNode, value: string): void {
const nestedNode = this.flatNodeMap.get(node);
if (nestedNode) {
nestedNode.name = value;
this.dataSource.setData(this.treeData);
}
}
create() {
this.expression = this.rebuildtree(this.treeData);
}
expression: string = '';
rebuildtree(nodes: TreeNode[]) {
var expression = '';
for (var i = 0; i < nodes.length; i++) {
if (i == nodes.length - 1) {
var node = nodes[i];
if (node.children && node.children?.length > 0) {
var flatNode = this.nestedNodeMap.get(node);
node.connector = flatNode.connector;
node.field = flatNode.field;
node.text = flatNode.text;
node.operator = flatNode.operator;
node.name = flatNode.name;
if (node.children && node.children?.length > 0) {
this.rebuildtree(node.children);
expression += node.field + ' ' + node.operator + '' + node.text + node.connector + '(' + this.rebuildtree(node.children) + ')';
} else {
expression += node.field + ' ' + node.operator + '' + node.text + node.connector;
}
} else {
var node = nodes[i];
var flatNode = this.nestedNodeMap.get(node);
node.connector = flatNode.connector;
node.field = flatNode.field;
node.text = flatNode.text;
node.operator = flatNode.operator;
node.name = flatNode.name;
expression += node.field + ' ' + node.operator + '' + node.text;
}
} else {
var node = nodes[i];
var flatNode = this.nestedNodeMap.get(node);
node.connector = flatNode.connector;
node.field = flatNode.field;
node.text = flatNode.text;
node.operator = flatNode.operator;
node.name = flatNode.name;
if (node.children && node.children?.length > 0) {
expression += node.field + ' ' + node.operator + '' + node.text + node.connector + '(' + this.rebuildtree(node.children) + ')';
} else {
expression += node.field + ' ' + node.operator + '' + node.text + node.connector;
}
}
}
return expression;
}
}
interface TreeNode {
name: string;
key: string;
children?: TreeNode[];
level?: number;
operator?: string;
field?: string;
text?: string;
connector?: string;
}
interface FlatNode {
expandable: boolean;
name: string;
key: string;
level: number;
operator?: string;
field?: string;
text?: string;
connector?: string;
}
......@@ -20,7 +20,7 @@
[ngModelOptions]="{ standalone: true }" (ngModelChange)="ngModelChange($event)" />
</se>
<se label="对象名称" error="对象名称" required>
<se label="对象名称" error="对象名称" *ngIf="false">
<input nz-input placeholder="" [(ngModel)]="form.flowname" readonly="readonly"
[ngModelOptions]="{ standalone: true }" (ngModelChange)="ngModelChange($event)" />
</se>
......@@ -30,19 +30,17 @@
[ngModelOptions]="{ standalone: true }" (ngModelChange)="ngModelChange($event)" />
</se>
<!-- <se label="网关处理器" error="网关处理器" *ngIf="form.nodeProcessClassVisable">
<input
nz-input
[(ngModel)]="form.nodeProcessClass"
placeholder="网关处理器"
[ngModelOptions]="{ standalone: true }"
(ngModelChange)="ngModelChange($event)"
/>
</se> -->
<se label="条件表达式" error="条件表达式" *ngIf="form.conditionexpressionVisable">
<se label="条件表达式" error="条件表达式" *ngIf="form.conditionexpressionVisable">
<nz-input-group [nzSuffix]="suffixTemplateInfo" class="exgroup" >
<textarea nz-input [(ngModel)]="form.conditionexpression" placeholder="条件表达式"
[ngModelOptions]="{ standalone: true }" (ngModelChange)="ngModelChange($event)"></textarea>
</nz-input-group>
<ng-template #suffixTemplateInfo>
<i nz-icon nz-tooltip nzTooltipTitle="" nzType="info-circle" (click)="showce()" ></i>
</ng-template>
</se>
<se label="脚本类型" error="脚本类型" *ngIf="form.flowscripttypeVisable">
......@@ -106,4 +104,4 @@
<!-- </nz-collapse-panel>
</nz-collapse> -->
</div>
\ No newline at end of file
</div>
......@@ -29,4 +29,7 @@
}
nz-select{
width: 100%;
}
.exgroup{
width: 100%;
}
\ No newline at end of file
......@@ -14,7 +14,7 @@ import {
Inject,
OnInit
} from '@angular/core';
import { _HttpClient } from '@delon/theme'; //test
import { SettingsService, _HttpClient } from '@delon/theme'; //test
import { delay, mergeMap } from 'rxjs/operators';
import * as BpmnJS from 'bpmn-js/dist/bpmn-modeler.production.min.js';
......@@ -28,6 +28,11 @@ import { NzTooltipDirective } from 'ng-zorro-antd/tooltip';
import { appmessage } from 'src/app/models/appmessage';
import { FormBpmnObject, Activity, TextAnnotation, SequenceFlow, Task, BpmnBaseObject, DesignerResult, DataOutputAssociation, GateWay } from 'src/app/models/rules/basebizobject';
import { NzDrawerService } from 'ng-zorro-antd/drawer';
import { ConditionbuilderComponent } from '../conditionbuilder/conditionbuilder.component';
// import customModule from 'src/assets/custom/gh/custom.js';// 导入自定义渲染
@Component({
selector: 'app-diagram',
templateUrl: './diagram.component.html',
......@@ -165,6 +170,29 @@ export class DiagramComponent implements AfterContentInit, OnChanges, OnDestroy
.subscribe();
}
showce(){
var { nzMaskClosable, width } = this.settingService.getData('drawerconfig');
var title = '条件生成' ;
const drawerRef = this.drawerService.create<ConditionbuilderComponent, { id: string }, string>({
nzTitle: title,
nzContent: ConditionbuilderComponent,
nzWidth: width < 1280 ? 1280 : width,
nzMaskClosable: nzMaskClosable,
nzContentParams: {
}
});
drawerRef.afterOpen.subscribe(() => { });
drawerRef.afterClose.subscribe(data => {
this.form.conditionexpression=data['expression'];
var orgin=data['orgin']; //用于服务端条件解析的原始JSON对象
});
}
getexcutors() {
this.http.get('api/rules/getexecutors').subscribe(
next => {
......@@ -183,7 +211,9 @@ export class DiagramComponent implements AfterContentInit, OnChanges, OnDestroy
private nzConfigService: NzConfigService,
private element: ElementRef,
@Inject(DOCUMENT) document: any,
private renderer: Renderer2
private renderer: Renderer2,
private drawerService: NzDrawerService,
private settingService: SettingsService
) {
this.document = document;
this.activity = new Activity();
......@@ -203,7 +233,7 @@ export class DiagramComponent implements AfterContentInit, OnChanges, OnDestroy
defaultStrokeColor: '#1890ff'
},
// additionalModules: [
// customModule
// customModule
// ],
moddleExtensions: {}
});
......@@ -1658,8 +1688,8 @@ export class DiagramComponent implements AfterContentInit, OnChanges, OnDestroy
// var elementRegistry = this.bpmnJS.get('elementRegistry');
// var modeling = this.bpmnJS.get('modeling');
// var node = elementRegistry.get(element.id);
// node.businessObject['profile'] = task.bizObject.profile
// modeling.updateProperties(node, { profile: task.bizObject.profile });
// node.businessObject['profile'] = task.bizObject.profile //附加自定义图形内置数据属性
// modeling.updateProperties(node, { profile: task.bizObject.profile }); //触发任意一次change事件,通知事件总线发起一次重绘
task.incoming = element.incoming ?? [];
task.outgoing = element.incoming ?? [];
task.id = element.id;
......
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { ConditionbuilderComponent } from './conditionbuilder/conditionbuilder.component';
import { DesignerComponent } from './designer/designer.component';
import { FloweventsComponent } from './flowevents/flowevents.component';
import { FlowlistComponent } from './flowlist/flowlist.component';
......@@ -9,7 +10,10 @@ const routes: Routes = [
{ path: 'flowlist', component: FlowlistComponent },
{ path: 'flowevents', component: FloweventsComponent },
{ path: 'designer', component: DesignerComponent },
{ path: 'ruledevice', component: RuledeviceComponent }
{ path: 'ruledevice', component: RuledeviceComponent },
{ path: 'c', component: ConditionbuilderComponent } //test
];
@NgModule({
......
......@@ -3,6 +3,7 @@ import { SharedModule } from '@shared';
import { NgxEchartsModule } from 'ngx-echarts';
import { CommonDialogSevice } from '../util/commonDialogSevice';
import { WidgetsModule } from '../widgets/widgets.module';
import { ConditionbuilderComponent } from './conditionbuilder/conditionbuilder.component';
import { DesignerComponent } from './designer/designer.component';
import { DiagramComponent } from './diagram/diagram.component';
import { FloweventsComponent } from './flowevents/flowevents.component';
......@@ -25,7 +26,7 @@ const COMPONENTS = [
ForkdialogComponent,
SequenceflowtesterComponent,
TasktesterComponent,
RuledeviceComponent,
RuledeviceComponent,ConditionbuilderComponent
];
......
import CustomContextPad from './customContextPad';
import CustomPalette from './customPalette';
import CustomRenderer from './customRenderer';
export default {
__init__: [ 'customContextPad', 'customPalette', 'customRenderer' ],
customContextPad: [ 'type', CustomContextPad ],
customPalette: [ 'type', CustomPalette ],
customRenderer: [ 'type', CustomRenderer ]
};
\ No newline at end of file
import {
TASKS,
} from './parts'
export default class CustomContextPad {
constructor(bpmnFactory, config, contextPad, create, elementFactory, injector, translate) {
this.bpmnFactory = bpmnFactory;
this.create = create;
this.elementFactory = elementFactory;
this.translate = translate;
if (config.autoPlace !== false) {
this.autoPlace = injector.get('autoPlace', false);
}
contextPad.registerProvider(this);
}
getContextPadEntries(element) {
const {
autoPlace,
bpmnFactory,
create,
elementFactory,
} = this;
function appendBuiltinShape(task) {
return function (event, element) {
if (autoPlace) {
const businessObject = bpmnFactory.create(task.shape);
businessObject.suitable = task.title;
businessObject.profile = task;
const shape = elementFactory.createShape({
type: task.shape,
businessObject: businessObject,
});
autoPlace.append(element, shape);
} else {
appendBuiltinShapeStart(event, element);
}
};
}
function appendBuiltinShapeStart(task) {
return function (event) {
const businessObject = bpmnFactory.create(task.shape);
businessObject.suitable = task.title;
businessObject.profile = task;
const shape = elementFactory.createShape({
type: task.shape,
businessObject: businessObject,
});
console.log(shape)
create.start(event, shape, element);
};
}
var tasks = {}
for (var o of TASKS) {
tasks[o.namespace] = {
group: o.group,
className: o.classname,
title: o.desc,
action: {
click: appendBuiltinShape(o),
dragstart: appendBuiltinShapeStart(o)
}
}
}
return tasks;
}
}
CustomContextPad.$inject = [
'bpmnFactory',
'config',
'contextPad',
'create',
'elementFactory',
'injector',
'translate'
];
\ No newline at end of file
import {
TASKS,
} from './parts'
export default class CustomPalette {
constructor(bpmnFactory, create, elementFactory, palette, translate) {
this.bpmnFactory = bpmnFactory;
this.create = create;
this.elementFactory = elementFactory;
this.translate = translate;
palette.registerProvider(this);
}
getPaletteEntries(element) {
const {
bpmnFactory,
create,
elementFactory,
} = this;
function createbuiltinshape(task) {
return function (event) {
const businessObject = bpmnFactory.create(task.shape);
businessObject.suitable = task.title;
businessObject.profile = task;
const shape = elementFactory.createShape({
type: task.shape,
businessObject: businessObject
});
console.log(shape)
create.start(event, shape);
};
}
var tasks = {
'excutors-separator': {
group: 'excutors',
separator: true
},
};
for (var o of TASKS) {
tasks[o.namespace] = {
group: o.group,
className: o.classname,
title: o.desc,
action: {
dragstart: createbuiltinshape(o),
click: createbuiltinshape(o)
}
}
}
return tasks;
}
}
CustomPalette.$inject = [
'bpmnFactory',
'create',
'elementFactory',
'palette',
'translate'
];
\ No newline at end of file
import BaseRenderer from 'diagram-js/lib/draw/BaseRenderer';
import {
append as svgAppend,
attr as svgAttr,
classes as svgClasses,
create as svgCreate
} from 'tiny-svg';
import {
getRoundRectPath
} from 'bpmn-js/lib/draw/BpmnRenderUtil';
import {
is,
getBusinessObject
} from 'bpmn-js/lib/util/ModelUtil';
import { isNil } from 'min-dash';
const HIGH_PRIORITY = 1500,
TASK_BORDER_RADIUS = 3
export default class CustomRenderer extends BaseRenderer {
constructor(eventBus, bpmnRenderer) {
super(eventBus, HIGH_PRIORITY);
this.bpmnRenderer = bpmnRenderer;
}
canRender(element) {
return !element.labelTarget;
}
drawShape(parentNode, element) {
const shape = this.bpmnRenderer.drawShape(parentNode, element);
const profile = this.getSuitabilityProfile(element);
if (!isNil(profile)) {
const color = profile.color;
const rect = drawRect(parentNode, 120, 20, TASK_BORDER_RADIUS, color);
svgAttr(rect, {
transform: 'translate(0, -25)'
});
var text = svgCreate('text');
svgAttr(text, {
fill: '#fff',
transform: 'translate(0, -10)'
});
svgClasses(text).add('djs-label');
svgAppend(text, document.createTextNode(profile.title));
svgAppend(parentNode, text);
}
return shape;
}
getShapePath(shape) {
return getRoundRectPath(shape, TASK_BORDER_RADIUS);
}
getSuitabilityProfile(element) {
const businessObject = getBusinessObject(element);
const { suitable ,profile} = businessObject;
return profile;
}
}
function drawRect(parentNode, width, height, borderRadius, color) {
const rect = svgCreate('rect');
svgAttr(rect, {
width: width,
height: height,
rx: borderRadius,
ry: borderRadius,
stroke: color,
strokeWidth: 1,
fill: color
});
svgAppend(parentNode, rect);
return rect;
}
\ No newline at end of file
export const
TASKS = [
{ title: '告警发布器', desc: '告警发布器', namespace: 'PublishAlarmDataTask', color: '#f5222d', shape: 'bpmn:UserTask', action: null, config: {}, classname: 'bpmn-icon-task red', group: 'excutors' },
{ title: '属性发布器', desc: '属性发布器', namespace: 'PublishAttributeDataTask', color: '#fadb14', shape: 'bpmn:ServiceTask', action: null, config: {}, classname: 'bpmn-icon-task yellow', group: 'excutors' },
{ title: '遥测数据发布器', desc: '遥测数据发布器', namespace: 'PublishTelemetryDataTask', color: '#a0d911', shape: 'bpmn:ManualTask', action: null, config: {}, classname: 'bpmn-icon-task green', group: 'excutors' },
{ title: '告警生成器', desc: '自定义的告警生成器', namespace: 'CustomeAlarmPullExcutor', color: '#1890ff', shape: 'bpmn:SendTask', action: null, config: {}, classname: 'bpmn-icon-task blue', group: 'excutors' },
{ title: '告警推送器', desc: '用于告警推送的执行器', namespace: 'AlarmPullExcutor ', color: '#722ed1', shape: 'bpmn:ReceiveTask', action: null, config: {}, classname: 'bpmn-icon-task purple', group: 'excutors' },
{ title: '消息推送器', desc: '用于消息推送的执行器', namespace: 'MessagePullExecutor', color: '#eb2f96', shape: 'bpmn:BusinessRuleTask', action: null, config: {}, classname: 'bpmn-icon-task magenta', group: 'excutors' },
{ title: '遥测数组推器', desc: '用于遥测数组推送的执行器', namespace: 'TelemetryArrayPullExcutor', color: '#13c2c2', shape: 'bpmn:ScriptTask', action: {}, config: null, classname: 'bpmn-icon-task cyan', group: 'excutors' }
];
......@@ -51,7 +51,7 @@ import {
TrophyOutline,
UsbOutline,
UserOutline,
WeiboCircleOutline, WarningTwoTone
WeiboCircleOutline, WarningTwoTone,MinusOutline
} from '@ant-design/icons-angular/icons';
export const ICONS_AUTO = [
......@@ -102,5 +102,5 @@ export const ICONS_AUTO = [
TrophyOutline,
UsbOutline,
UserOutline,
WeiboCircleOutline, WarningTwoTone
WeiboCircleOutline, WarningTwoTone,MinusOutline
];
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册