提交 0181db9b 编写于 作者: 麦壳饼's avatar 麦壳饼

Merge branch 'master' of https://github.com/IoTSharp/IoTSharp

......@@ -40,10 +40,13 @@ namespace IoTSharp.TaskAction
request.RequestFormat = DataFormat.Json;
request.AddHeader("cache-control", "no-cache");
request.AddHeader("Content-Type", "application/json");
request.AddJsonBody(JsonConvert.DeserializeObject<Alarm>(input.Input, new JsonSerializerSettings
var alarm = JsonConvert.DeserializeObject<Alarm>(input.Input, new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
}) ?? new object());
}) ?? new object();
request.AddJsonBody(alarm);
var response = await restclient.ExecutePostAsync(request);
if (response.StatusCode == HttpStatusCode.OK)
{
......
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,
});
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
});
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' }
];
\ No newline at end of file
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
<div #diagramcontainer style="height: 800px; width: 100%;">
<div #ref class="diagram-container" style="padding: 0.1rem">
<div #ref class="diagram-container" style="padding: 0.1rem">
</div>
<nz-collapse style="position: absolute;
<nz-collapse style="position: absolute;
right: 30px;
top: 200px;
width: 500px;">
<nz-collapse-panel
*ngFor="let panel of panels"
[nzHeader]="panel.name"
[nzActive]="panel.active"
[nzDisabled]="panel.disabled"
>
<form nz-form se-container="1" labelWidth="100" gutter="32">
<se label="Id" error="Id" >
<input
nz-input
placeholder=""
[(ngModel)]="form.id"
readonly="readonly"
[ngModelOptions]="{ standalone: true }"
(ngModelChange)="ngModelChange($event)"
/>
</se>
<se label="对象Id" error="对象Id" *ngIf="false" >
<input
nz-input
placeholder=""
[(ngModel)]="form.flowid"
readonly="readonly"
[ngModelOptions]="{ standalone: true }"
(ngModelChange)="ngModelChange($event)"
/>
</se>
<se label="对象名称" error="对象名称" required>
<input
nz-input
placeholder=""
[(ngModel)]="form.flowname"
readonly="readonly"
[ngModelOptions]="{ standalone: true }"
(ngModelChange)="ngModelChange($event)"
/>
</se>
<se label="备注" error="备注">
<input
nz-input
placeholder=""
[(ngModel)]="form.flowdesc"
name="flowdesc"
[ngModelOptions]="{ standalone: true }"
(ngModelChange)="ngModelChange($event)"
/>
</se>
<!-- <se label="网关处理器" error="网关处理器" *ngIf="form.nodeProcessClassVisable">
<nz-collapse-panel *ngFor="let panel of panels" [nzHeader]="panel.name" [nzActive]="panel.active"
[nzDisabled]="panel.disabled">
<form nz-form se-container="1" labelWidth="100" gutter="32">
<se label="Id" error="Id">
<input nz-input placeholder="" [(ngModel)]="form.id" readonly="readonly"
[ngModelOptions]="{ standalone: true }" (ngModelChange)="ngModelChange($event)" />
</se>
<se label="对象Id" error="对象Id" *ngIf="false">
<input nz-input placeholder="" [(ngModel)]="form.flowid" readonly="readonly"
[ngModelOptions]="{ standalone: true }" (ngModelChange)="ngModelChange($event)" />
</se>
<se label="对象名称" error="对象名称" required>
<input nz-input placeholder="" [(ngModel)]="form.flowname" readonly="readonly"
[ngModelOptions]="{ standalone: true }" (ngModelChange)="ngModelChange($event)" />
</se>
<se label="备注" error="备注">
<input nz-input placeholder="" [(ngModel)]="form.flowdesc" name="flowdesc"
[ngModelOptions]="{ standalone: true }" (ngModelChange)="ngModelChange($event)" />
</se>
<!-- <se label="网关处理器" error="网关处理器" *ngIf="form.nodeProcessClassVisable">
<input
nz-input
[(ngModel)]="form.nodeProcessClass"
......@@ -68,91 +39,62 @@
(ngModelChange)="ngModelChange($event)"
/>
</se> -->
<se label="条件表达式" error="条件表达式" *ngIf="form.conditionexpressionVisable">
<textarea
nz-input
[(ngModel)]="form.conditionexpression"
placeholder="条件表达式"
[ngModelOptions]="{ standalone: true }"
(ngModelChange)="ngModelChange($event)"
></textarea>
</se>
<se label="脚本类型" error="脚本类型" *ngIf="form.flowscripttypeVisable">
<nz-select
[(ngModel)]="form.flowscripttype"
[ngModelOptions]="{ standalone: true }"
(ngModelChange)="flowscripttypeChange($event)"
>
<nz-option nzValue="javascript" nzLabel="javascript"></nz-option>
<nz-option nzValue="executor" nzLabel="executor"></nz-option>
<nz-option nzValue="python" nzLabel="python"></nz-option>
<nz-option nzValue="sql" nzLabel="sql"></nz-option>
<nz-option nzValue="lua" nzLabel="lua"></nz-option>
<nz-option nzValue="csharp" nzLabel="csharp"></nz-option>
</nz-select>
</se>
<se label="执行器" error="请选择执行器" *ngIf="form.nodeProcessClassVisable">
<nz-select
[(ngModel)]="form.nodeProcessClass"
[ngModelOptions]="{ standalone: true }"
(ngModelChange)="ngModelChange($event)"
>
<nz-option *ngFor="let option of executors" [nzLabel]="option.label" [nzValue]="option.value"></nz-option>
<se label="条件表达式" error="条件表达式" *ngIf="form.conditionexpressionVisable">
<textarea nz-input [(ngModel)]="form.conditionexpression" placeholder="条件表达式"
[ngModelOptions]="{ standalone: true }" (ngModelChange)="ngModelChange($event)"></textarea>
</se>
<se label="脚本类型" error="脚本类型" *ngIf="form.flowscripttypeVisable">
<nz-select [(ngModel)]="form.flowscripttype" [ngModelOptions]="{ standalone: true }"
(ngModelChange)="flowscripttypeChange($event)">
<nz-option nzValue="javascript" nzLabel="javascript"></nz-option>
<nz-option nzValue="executor" nzLabel="executor"></nz-option>
<nz-option nzValue="python" nzLabel="python"></nz-option>
<nz-option nzValue="sql" nzLabel="sql"></nz-option>
<nz-option nzValue="lua" nzLabel="lua"></nz-option>
<nz-option nzValue="csharp" nzLabel="csharp"></nz-option>
</nz-select>
</se>
<se label="执行器参数(JSON)" error="请选择执行器" *ngIf="form.nodeProcessClassVisable">
<nz-code-editor
[nzToolkit]="toolkit"
[class.full-screen]="fullScreen"
(ngModelChange)="ngModelChange($event)"
style="width: 100%; height: 500px; padding-top: 1rem"
class="editor"
[(ngModel)]="form.nodeProcessParams"
[ngModelOptions]="{ standalone: true }"
[nzEditorOption]="{ theme: 'vs',language: 'json' }"
></nz-code-editor>
</se>
<se label="脚本" error="脚本" *ngIf="form.flowscriptVisable">
<nz-code-editor
[nzToolkit]="toolkit"
[class.full-screen]="fullScreen"
(ngModelChange)="ngModelChange($event)"
style="width: 100%; height: 500px; padding-top: 1rem"
class="editor"
[(ngModel)]="form.flowscript"
[ngModelOptions]="{ standalone: true }"
[nzEditorOption]="{ theme: 'vs',language: 'csharp' }"
></nz-code-editor>
</se>
</form>
</se>
<se label="执行器" error="请选择执行器" *ngIf="form.nodeProcessClassVisable">
<nz-select [(ngModel)]="form.nodeProcessClass" [ngModelOptions]="{ standalone: true }"
(ngModelChange)="ngModelChange($event)">
<nz-option *ngFor="let option of executors" [nzLabel]="option.label" [nzValue]="option.value"></nz-option>
</nz-select>
</se>
<se label="执行器参数(JSON)" error="请选择执行器" *ngIf="form.nodeProcessClassVisable">
<nz-code-editor [nzToolkit]="toolkit" [class.full-screen]="fullScreen" (ngModelChange)="ngModelChange($event)"
style="width: 100%; height: 500px; padding-top: 1rem" class="editor" [(ngModel)]="form.nodeProcessParams"
[ngModelOptions]="{ standalone: true }" [nzEditorOption]="{ theme: 'vs',language: 'json' }">
</nz-code-editor>
</se>
<se label="脚本" error="脚本" *ngIf="form.flowscriptVisable">
<nz-code-editor [nzToolkit]="toolkit" [class.full-screen]="fullScreen" (ngModelChange)="ngModelChange($event)"
style="width: 100%; height: 500px; padding-top: 1rem" class="editor" [(ngModel)]="form.flowscript"
[ngModelOptions]="{ standalone: true }" [nzEditorOption]="{ theme: 'vs',language: 'csharp' }">
</nz-code-editor>
</se>
</form>
</nz-collapse-panel>
</nz-collapse>
<ng-template #toolkit>
<i
nz-icon
[class.active]="fullScreen"
nz-tooltip
nzTooltipTitle="Toggle Fullscreen"
[nzType]="fullScreen ? 'fullscreen-exit' : 'fullscreen'"
(click)="toggleFullScreen()"
></i>
<i nz-icon [class.active]="fullScreen" nz-tooltip nzTooltipTitle="Toggle Fullscreen"
[nzType]="fullScreen ? 'fullscreen-exit' : 'fullscreen'" (click)="toggleFullScreen()"></i>
</ng-template>
<ng-template #extraTemplate>
<a>More</a>
......@@ -164,4 +106,4 @@
<!-- </nz-collapse-panel>
</nz-collapse> -->
</div>
</div>
\ No newline at end of file
......@@ -31,3 +31,51 @@
}
.panel {
background-color: #fafafa;
border: solid 1px #ccc;
border-radius: 2px;
font-family: 'Arial', sans-serif;
padding: 10px;
}
.djs-label {
font-family: 'Arial', sans-serif;
}
#quality-assurance {
color: #111;
left: 50%;
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
}
#quality-assurance #form input {
border: solid 1px #ccc;
border-radius: 2px;
font-family: 'Arial', sans-serif;
padding: 10px;
}
#quality-assurance #form input[type=text] {
width: 100%;
}
#quality-assurance #form #warning {
background-color: rgba(255, 0, 0, 0.25);
border-radius: 2px;
padding: 10px;
}
#quality-assurance #form input[type=submit] {
background-color: #FAFAFA;
color: #111;
}
#hint {
bottom: 20px;
left: 20px;
position: absolute;
}
\ No newline at end of file
......@@ -13,6 +13,8 @@ import {
Renderer2,
Inject
} from '@angular/core';
import { _HttpClient } from '@delon/theme'; //test
import { delay, mergeMap } from 'rxjs/operators';
import * as BpmnJS from 'bpmn-js/dist/bpmn-modeler.production.min.js';
......@@ -25,21 +27,13 @@ import { NzCodeEditorComponent } from 'ng-zorro-antd/code-editor';
import { DOCUMENT } from '@angular/common';
import { NzTooltipDirective } from 'ng-zorro-antd/tooltip';
// import customModule from './custom/custom';
@Component({
selector: 'app-diagram',
templateUrl: './diagram.component.html',
styleUrls: ['./diagram.component.less']
})
//gfx 属性消失代表元素被删除,不用去遍历整个SVG DOM判断,已知增加的钩子还有以下
// 'element.hover',
//'element.out',
// 'element.click',
// 'element.dblclick',
// 'element.mousedown',
// 'element.mouseup'
// 来自 https://github.com/bpmn-io/bpmn-js-examples/tree/master/interaction
export class DiagramComponent implements AfterContentInit, OnChanges, OnDestroy {
nzEditorOption: { theme: 'vs'; language: 'json' };
paramnzEditorOption: { theme: 'vs'; language: 'json' };
......@@ -132,7 +126,7 @@ export class DiagramComponent implements AfterContentInit, OnChanges, OnDestroy
}
break;
default:
break;
}
......@@ -152,9 +146,9 @@ export class DiagramComponent implements AfterContentInit, OnChanges, OnDestroy
return;
}
var elementRegistry = this.bpmnJS.get('elementRegistry');
var modeling = this.bpmnJS.get('modeling');
// var modeling = this.bpmnJS.get('modeling');
// modeling.updateProperties(x.id, {
// name: 'ssss', //名称设置无效,如需双向绑定仍旧需要直接改Dom
......@@ -180,8 +174,8 @@ export class DiagramComponent implements AfterContentInit, OnChanges, OnDestroy
next => {
this.executors = next.data;
},
error => {},
() => {}
error => { },
() => { }
);
}
......@@ -208,9 +202,17 @@ export class DiagramComponent implements AfterContentInit, OnChanges, OnDestroy
this.activity.startEvents = [];
this.activity.textAnnotations = [];
this.bpmnJS = new BpmnJS({
bpmnRenderer: {
defaultFillColor: '#e6f7ff',
defaultStrokeColor: '#1890ff'
},
// additionalModules: [
// customModule
// ],
moddleExtensions: {
}
});
......@@ -254,7 +256,9 @@ export class DiagramComponent implements AfterContentInit, OnChanges, OnDestroy
task.bizObject.nodeProcessClassVisable = false;
task.bizObject.flowscriptVisable = true;
}
if (event.element.businessObject.profile) {
usertask.bizObject.profile = event.element.businessObject.profile;
}
this.form = task.bizObject;
}
......@@ -535,6 +539,8 @@ export class DiagramComponent implements AfterContentInit, OnChanges, OnDestroy
break;
case 'bpmn:UserTask':
var usertask = this.activity.tasks.find(x => x.id == event.element.id);
if (usertask) {
if (usertask.bizObject == null) {
usertask.bizObject = {
......@@ -556,6 +562,12 @@ export class DiagramComponent implements AfterContentInit, OnChanges, OnDestroy
}
this.form.flowscript = '';
this.form.flowscripttype = '';
if (event.element.businessObject.profile) {
usertask.bizObject.profile = event.element.businessObject.profile;
}
usertask.bizObject.flowscriptVisable = true;
usertask.bizObject.flowscripttypeVisable = true;
usertask.bizObject.nodeProcessClassVisable = false;
......@@ -611,7 +623,9 @@ export class DiagramComponent implements AfterContentInit, OnChanges, OnDestroy
nodeProcessParams: ''
};
}
if (event.element.businessObject.profile) {
usertask.bizObject.profile = event.element.businessObject.profile;
}
servicetask.bizObject.flowscriptVisable = true;
servicetask.bizObject.flowscripttypeVisable = true;
servicetask.bizObject.nodeProcessClassVisable = false;
......@@ -640,7 +654,9 @@ export class DiagramComponent implements AfterContentInit, OnChanges, OnDestroy
nodeProcessParams: ''
};
}
if (event.element.businessObject.profile) {
usertask.bizObject.profile = event.element.businessObject.profile;
}
manualtask.bizObject.flowscriptVisable = true;
manualtask.bizObject.flowscripttypeVisable = true;
manualtask.bizObject.nodeProcessClassVisable = false;
......@@ -669,7 +685,9 @@ export class DiagramComponent implements AfterContentInit, OnChanges, OnDestroy
nodeProcessParams: ''
};
}
if (event.element.businessObject.profile) {
usertask.bizObject.profile = event.element.businessObject.profile;
}
sendtask.bizObject.flowscriptVisable = true;
sendtask.bizObject.flowscripttypeVisable = true;
sendtask.bizObject.nodeProcessClassVisable = false;
......@@ -915,10 +933,6 @@ export class DiagramComponent implements AfterContentInit, OnChanges, OnDestroy
element.style.display = 'none';
}
if (element.getAttribute('data-group') == 'data-store') {
element.style.display = 'none';
}
if (element.getAttribute('data-group') == 'collaboration') {
element.style.display = 'none';
}
......@@ -1048,7 +1062,7 @@ export class DiagramComponent implements AfterContentInit, OnChanges, OnDestroy
baseBpmnObject.bizObject.flowid = e.element.id;
this.activity.baseBpmnObjects = [...this.activity.baseBpmnObjects, baseBpmnObject];
}
console.log('baseBpmnObject');
baseBpmnObject.incoming = [
...baseBpmnObject.incoming,
...e.element.incoming.map(x => {
......@@ -1308,7 +1322,9 @@ export class DiagramComponent implements AfterContentInit, OnChanges, OnDestroy
flowscripttypeVisable: true,
flowscripttype: '',
nodeProcessParams: ''
};
}; if (e.element.businessObject.profile) {
task.bizObject.profile = e.element.businessObject.profile;
}
task.id = e.element.businessObject.id;
task.bizObject.flowname = e.element.businessObject.name;
task.bizObject.flowid = e.element.id;
......@@ -1642,9 +1658,14 @@ export class DiagramComponent implements AfterContentInit, OnChanges, OnDestroy
nodeProcessClassVisable: false,
flowscriptVisable: false,
flowscripttypeVisable: false,
flowscripttype: element.bizObject.flowscripttype ?? ''
};
flowscripttype: element.bizObject.flowscripttype ?? '',
profile: element.bizObject.flowdesc ? JSON.parse(element.bizObject.flowdesc) : {}
};
// 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 });
task.incoming = element.incoming ?? [];
task.outgoing = element.incoming ?? [];
task.id = element.id;
......@@ -1750,7 +1771,7 @@ export class DiagramComponent implements AfterContentInit, OnChanges, OnDestroy
flowscriptVisable: false,
flowscripttypeVisable: false,
flowscripttype: '',
nodeProcessParams: ''
nodeProcessParams: '',
};
container.incoming = element.incoming ?? [];
container.outgoing = element.incoming ?? [];
......@@ -1920,7 +1941,12 @@ export class DiagramComponent implements AfterContentInit, OnChanges, OnDestroy
this.activity.lane.push(lane);
}
}
}
}
export class BasebizObject {
......@@ -1951,7 +1977,8 @@ export class BpmnBaseObject {
flowscriptVisable: false,
flowscripttypeVisable: false,
flowscripttype: '',
nodeProcessParams: ''
nodeProcessParams: '',
profile: {}
};
}
......@@ -2011,7 +2038,7 @@ export class DataInputAssociation extends BpmnBaseObject {
public targetId!: String;
}
export class Collaboration extends BpmnBaseObject {}
export class Collaboration extends BpmnBaseObject { }
export const importDiagram = (bpmnJS: any) => (source: Observable<any>) =>
new Observable<any>(observer => {
......@@ -2020,7 +2047,7 @@ export const importDiagram = (bpmnJS: any) => (source: Observable<any>) =>
// canceling the subscription as we are interested
// in the first diagram to display only
subscription.unsubscribe();
console.log(xml);
bpmnJS.importXML(xml.xml, (err: any, warnings: string | undefined) => {
if (err) {
observer.error(err);
......@@ -2056,4 +2083,5 @@ export interface FormBpmnObject {
flowscripttype: string;
flowscripttypeVisable: boolean;
nodeProcessParams: string;
profile?: any
}
......@@ -12,3 +12,23 @@
opacity: 0.4;
fill: #e6f7ff !important; /* color elements as green */
}
.bpmn-icon-task.red {
color: #f5222d !important;
}
.bpmn-icon-task.yellow {
color: #fadb14 !important;
}
.bpmn-icon-task.green {
color: #a0d911 !important;
}
.bpmn-icon-task.blue {
color: #1890ff !important;
}.bpmn-icon-task.purple {
color: #722ed1 !important;
}.bpmn-icon-task.magenta {
color: #eb2f96 !important;
}.bpmn-icon-task.cyan {
color: #13c2c2 !important;
}
\ No newline at end of file
......@@ -1090,6 +1090,9 @@ namespace IoTSharp.Controllers
_logger.LogInformation($"{_dev.Id}的数据通过规则链{g}进行处理。");
var result = await _flowRuleProcessor.RunFlowRules(g, Newtonsoft.Json.JsonConvert.DeserializeObject(body), _dev.Id, EventType.Normal, null);
// _context.SaveFlowResult(_dev.Id,g, result);
});
return Ok(new ApiResult(ApiCode.Success, "OK"));
}
......
......@@ -144,8 +144,15 @@ namespace IoTSharp.Controllers
{
try
{
rule.RuleStatus = -1;
_context.FlowRules.Update(rule);
_context.FlowOperations.RemoveRange(_context.FlowOperations.Where(c=>c.FlowRule.RuleId==id).ToList());
await _context.SaveChangesAsync();
_context.BaseEvents.RemoveRange(_context.BaseEvents.Where(c=>c.FlowRule.RuleId==id).ToList());
await _context.SaveChangesAsync();
_context.Flows.RemoveRange(_context.Flows.Where(c=>c.FlowRule.RuleId==id).ToList());
await _context.SaveChangesAsync();
_context.DeviceRules.RemoveRange(_context.DeviceRules.Where(c => c.FlowRule.RuleId == id).ToList());
await _context.SaveChangesAsync();
_context.FlowRules.Remove(rule);
await _context.SaveChangesAsync();
return new ApiResult<bool>(ApiCode.Success, "OK", true);
}
......@@ -315,7 +322,7 @@ namespace IoTSharp.Controllers
}
[HttpGet("[action]")]
public async Task<ApiResult<PagedData<Device>>> GetRuleDevices([FromQuery] DeviceParam m)
public async Task<ApiResult<PagedData<DeviceRuleDto>>> GetRuleDevices([FromQuery] DeviceParam m)
{
......@@ -336,9 +343,14 @@ namespace IoTSharp.Controllers
var rows =await _context.DeviceRules.Include(c => c.FlowRule).Include(c => c.Device).Where(condition)
.Select(c => c.Device).Skip(m.offset * m.limit).Take(m.limit).ToListAsync();
.Select(c => new DeviceRuleDto()
{
Id = c.Device.Id, DeviceType = c.Device.DeviceType, EnableTrace = c.EnableTrace, LastActive = c.Device.LastActive, Name = c.Device.Name, Online = c.Device.Online, Status = c.Device.Status, Timeout = c.Device.Timeout
}).Skip(m.offset * m.limit).Take(m.limit).ToListAsync();
var total =await _context.DeviceRules.Include(c => c.FlowRule).Include(c => c.Device).Where(condition).Select(c=>c.Device).CountAsync();
return new ApiResult<PagedData<Device>>(ApiCode.Success, "Ok", new PagedData<Device> { rows=rows,total= total });
return new ApiResult<PagedData<DeviceRuleDto>>(ApiCode.Success, "Ok", new PagedData<DeviceRuleDto> { rows=rows,total= total });
}
[HttpGet("[action]")]
......@@ -470,7 +482,7 @@ namespace IoTSharp.Controllers
Createor = profile.Id,
CreateDate = CreateDate,
Customer = rule.Customer,
Tenant = rule.Tenant
Tenant = rule.Tenant, Flowdesc = JsonConvert.SerializeObject(c.BizObject.profile??new object())
});
_context.Flows.AddRange(fw);
......@@ -1138,43 +1150,7 @@ namespace IoTSharp.Controllers
var testabizId = Guid.NewGuid().ToString(); //根据业务保存起来,用来查询执行事件和步骤
var result = await _flowRuleProcessor.RunFlowRules(ruleid, d, Guid.Empty, EventType.TestPurpose, testabizId);
var flowRule = _context.FlowRules.SingleOrDefault(c => c.RuleId == ruleid);
var flows = _context.Flows.Where(c => c.FlowRule == flowRule).ToList();
if (result.Count > 0)
{
await Task.Run(() =>
{
var operevent =
_context.BaseEvents.SingleOrDefault(
c => c.EventId == result.FirstOrDefault().BaseEvent.EventId);
var list = result.Select(c => new FlowOperation
{
AddDate = c.AddDate,
BizId = c.BizId,
Data = c.Data,
BaseEvent = operevent,
Flow = flows.SingleOrDefault(x => x.FlowId == c.Flow.FlowId
),
FlowRule = flowRule,
NodeStatus = c.NodeStatus,
OperationDesc = c.OperationDesc,
OperationId = new Guid(),
Step = c.Step,
Tag = c.Tag,
bpmnid = c.bpmnid
}).ToArray();
_context.FlowOperations.AddRange(list);
_context.SaveChanges();
});
}
_context.SaveFlowResult(Guid.Empty, ruleid,result);
return new ApiResult<dynamic>(ApiCode.Success, "test complete", result.OrderBy(c => c.Step).
Where(c => c.BaseEvent.Bizid == testabizId).ToList()
.GroupBy(c => c.Step).Select(c => new
......
......@@ -116,9 +116,9 @@ namespace IoTSharp.Dtos
public class AssetDto
{
public Guid Id { get; set; }
public string? Name { get; set; }
public string? Description { get; set; }
public string? AssetType { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string AssetType { get; set; }
}
public class AssetRelationDto
......
using System;
using IoTSharp.Data;
namespace IoTSharp.Dtos
{
public class DeviceRuleDto
{
public Guid Id { get; set; }
/// <summary>
/// 设备名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 设备类型
/// </summary>
public DeviceType DeviceType { get; set; }
/// <summary>
/// 在线
/// </summary>
public bool Online { get; set; }
/// <summary>
/// 最后一次活跃时间
/// </summary>
public DateTime LastActive { get; set; }
/// <summary>
/// 超时时间 秒数
/// </summary>
public int Timeout { get; set; }
public int Status { get; set; }
public int EnableTrace { get; set; }
}
}
......@@ -90,7 +90,7 @@ namespace IoTSharp.Extensions
StartDateTime = DateTime.Now,
};
action?.Invoke(alarm);
var isone = from a in _context.Alarms where a.OriginatorId == alarm.OriginatorId && a.AlarmType == alarm.AlarmType select a;
var isone = from a in _context.Alarms where a.OriginatorId == alarm.OriginatorId && a.AlarmType == alarm.AlarmType && (a.AlarmStatus == AlarmStatus.Cleared_UnAck|| a.AlarmStatus == AlarmStatus.Active_UnAck) select a;
if (isone.Any())
{
var old = isone.First();
......
using IoTSharp.Data;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace IoTSharp.Extensions
{
public static class FlowExtension
{
public static void SaveFlowResult(this ApplicationDbContext _context, Guid DeviceId, Guid RuleId, List<FlowOperation> result)
{
if (_context.DeviceRules.Any(c =>
c.Device.Id == DeviceId && c.FlowRule.RuleId == RuleId && c.EnableTrace == 1))
{
if (result.Count > 0)
{
var flowRule = _context.FlowRules.SingleOrDefault(c => c.RuleId == RuleId);
var flows = _context.Flows.Where(c => c.FlowRule == flowRule).ToList();
var operevent =
_context.BaseEvents.SingleOrDefault(
c => c.EventId == result.FirstOrDefault().BaseEvent.EventId);
var list = result.Select(c => new FlowOperation
{
AddDate = c.AddDate,
BizId = c.BizId,
Data = c.Data,
BaseEvent = operevent,
Flow = flows.SingleOrDefault(x => x.FlowId == c.Flow.FlowId
),
FlowRule = flowRule,
NodeStatus = c.NodeStatus,
OperationDesc = c.OperationDesc,
OperationId = new Guid(),
Step = c.Step,
Tag = c.Tag,
bpmnid = c.bpmnid
}).ToArray();
_context.FlowOperations.AddRange(list);
_context.SaveChanges();
}
}
else
{
if (DeviceId == Guid.Empty)
{
if (result.Count > 0)
{
var flowRule = _context.FlowRules.SingleOrDefault(c => c.RuleId == RuleId);
var flows = _context.Flows.Where(c => c.FlowRule == flowRule).ToList();
var operevent =
_context.BaseEvents.SingleOrDefault(
c => c.EventId == result.FirstOrDefault().BaseEvent.EventId);
var list = result.Select(c => new FlowOperation
{
AddDate = c.AddDate,
BizId = c.BizId,
Data = c.Data,
BaseEvent = operevent,
Flow = flows.SingleOrDefault(x => x.FlowId == c.Flow.FlowId
),
FlowRule = flowRule,
NodeStatus = c.NodeStatus,
OperationDesc = c.OperationDesc,
OperationId = new Guid(),
Step = c.Step,
Tag = c.Tag,
bpmnid = c.bpmnid
}).ToArray();
_context.FlowOperations.AddRange(list);
_context.SaveChanges();
}
}
}
}
}
}
......@@ -3,6 +3,7 @@ using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using DotNetCore.CAP;
using IoTSharp.Data;
using IoTSharp.Dtos;
using IoTSharp.Extensions;
......@@ -18,11 +19,11 @@ namespace IoTSharp.Handlers
public class CustomeAlarmPullExcutor : ITaskAction
{
private ApplicationDbContext _context;
public CustomeAlarmPullExcutor(ApplicationDbContext context)
private readonly ICapPublisher _queue;
private readonly ApplicationDbContext _context;
public CustomeAlarmPullExcutor(ApplicationDbContext context, ICapPublisher queue)
{
this._context = context;
this._context = context; _queue = queue;
}
......@@ -30,7 +31,7 @@ namespace IoTSharp.Handlers
{
try
{
return SendData(input);
return Task.FromResult(SendData(input));
}
catch (Exception ex)
{
......@@ -38,11 +39,10 @@ namespace IoTSharp.Handlers
}
}
private async Task<TaskActionOutput> SendData(TaskActionInput input)
private TaskActionOutput SendData(TaskActionInput input)
{
try
{
JObject o = JsonConvert.DeserializeObject(input.Input) as JObject;
var config = JsonConvert.DeserializeObject<CustomeAlarmPullExcutor.ModelExecutorConfig>(input.ExecutorConfig);
var dd = o.Properties().Select(c => new MessagePullExecutor.ParamObject { keyName = c.Name.ToLower(), value = JPropertyToObject(c) }).ToList();
......@@ -51,63 +51,18 @@ namespace IoTSharp.Handlers
input.DeviceId = config.DeviceId;
}
var alarmdto = new CreateAlarmDto();
alarmdto.OriginatorType = OriginatorType.Device;
alarmdto.OriginatorName = input.DeviceId.ToString();
alarmdto.CreateDateTime = DateTime.Now;
alarmdto.Serverity = (ServerityLevel)config.serverity;
alarmdto.AlarmType = config.alarmType;
alarmdto.AlarmDetail = config.AlarmDetail ?? JsonConvert.SerializeObject(dd) ;
var alarm = await _context.OccurredAlarm(alarmdto);
Alarm body = new Alarm();
body.alarmType = alarm.Data.AlarmType;
body.originatorType = Enum.GetName(typeof(OriginatorType), alarm.Data.OriginatorType);
body.serverity = Enum.GetName(typeof(ServerityLevel), alarm.Data.Serverity);
body.alarmDetail = alarm.Data.AlarmDetail;
body.warnDataId = alarm.Data.Id.ToString();
body.originatorName = alarm.Data.OriginatorId.ToString();
body.createDateTime = alarm.Data.AckDateTime;
var restclient = new RestClient(config.BaseUrl);
restclient.AddDefaultHeader(KnownHeaders.Accept, "*/*");
var request =
new RestRequest(config.Url + (input.DeviceId == Guid.Empty ? "" : "/" + input.DeviceId));
request.AddHeader("X-Access-Token",
config.Token);
request.RequestFormat = DataFormat.Json;
request.AddHeader("cache-control", "no-cache");
request.AddHeader("Content-Type", "application/json");
request.AddJsonBody(body);
var response = await restclient.ExecutePostAsync(request);
if (response.StatusCode == HttpStatusCode.OK)
{
var result = JsonConvert.DeserializeObject<CustomeAlarmPullExcutor.MessagePullResult>(response.Content);
if (result is { success: true })
{
return new TaskActionOutput()
{
ExecutionInfo = response.Content,
ExecutionStatus = result.success,
DynamicOutput = input.DynamicInput
};
}
else
{
return new TaskActionOutput() { ExecutionInfo = response.Content, ExecutionStatus = false };
}
}
else
{
return new TaskActionOutput()
{
ExecutionInfo =
$"StatusCode:{response.StatusCode} StatusDescription:{response.StatusDescription} {response.ErrorMessage}",
ExecutionStatus = false
};
}
return new TaskActionOutput() { ExecutionInfo = JsonConvert.SerializeObject(alarmdto), ExecutionStatus = true, DynamicOutput = alarmdto };
}
catch (Exception ex)
{
return new TaskActionOutput() { ExecutionInfo = ex.Message, ExecutionStatus = false };
;
}
}
......
......@@ -22,7 +22,7 @@ namespace IoTSharp.Handlers
public override Task<TaskActionOutput> ExecuteAsync(TaskActionInput param)
{
var result = new TaskActionOutput() { DynamicOutput = new { code = ApiCode.Success,msg="OK" } };
var result = new TaskActionOutput() { DynamicOutput = param.DynamicInput, ExecutionStatus = true, ExecutionInfo = ""};
try
{
var dto = JsonConvert.DeserializeObject<Dtos.CreateAlarmDto>(param.Input);
......@@ -30,7 +30,7 @@ namespace IoTSharp.Handlers
}
catch (Exception ex)
{
result.DynamicOutput = new { code = ApiCode.Exception, msg = ex.Message };
result.DynamicOutput = new { DynamicOutput = param.DynamicInput, ExecutionStatus = false, ExecutionInfo = ex.Message };
}
return Task.FromResult(result);
}
......
......@@ -822,6 +822,31 @@
客户
</summary>
</member>
<member name="P:IoTSharp.Dtos.DeviceRuleDto.Name">
<summary>
设备名称
</summary>
</member>
<member name="P:IoTSharp.Dtos.DeviceRuleDto.DeviceType">
<summary>
设备类型
</summary>
</member>
<member name="P:IoTSharp.Dtos.DeviceRuleDto.Online">
<summary>
在线
</summary>
</member>
<member name="P:IoTSharp.Dtos.DeviceRuleDto.LastActive">
<summary>
最后一次活跃时间
</summary>
</member>
<member name="P:IoTSharp.Dtos.DeviceRuleDto.Timeout">
<summary>
超时时间 秒数
</summary>
</member>
<member name="P:IoTSharp.Dtos.FlowOperationDto.NodeStatus">
<summary>
节点处理状态,0 创建完
......
......@@ -63,5 +63,32 @@ namespace IoTSharp.Models.Rule
public string NodeProcessParams { get; set; }
public string flowscript { get; set; }
public string flowscripttype { get; set; }
public BpmnObjectProfile profile { get; set; }
}
//from Parts.js
public class BpmnObjectProfile
{
public string title { get; set; }
public string desc { get; set; }
public string @namespace { get; set; }
public string color { get; set; }
public string shape { get; set; }
public dynamic action { get; set; }
public dynamic config { get; set; }
public string classname { get; set; }
public string group { get; set; }
}
}
\ No newline at end of file
......@@ -414,7 +414,8 @@ namespace IoTSharp
services.AddTransient<FlowRuleProcessor>(); services.AddTransient<CustomeAlarmPullExcutor>();
services.AddSingleton<TaskExecutorHelper>();
services.AddTransient<PublishAttributeDataTask>();
services.AddTransient<PublishTelemetryDataTask>();
services.AddTransient<PublishTelemetryDataTask>();
services.AddTransient<PublishAlarmDataTask>();
services.AddTransient<RawDataGateway>();
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册