diff --git a/IoTSharp.TaskAction/DeviceActionExcutor.cs b/IoTSharp.TaskAction/DeviceActionExcutor.cs index c181927626196e7368dd354d1285b1947fb13c0a..94ba141d35b4b3de6a268f74a300d28457065803 100644 --- a/IoTSharp.TaskAction/DeviceActionExcutor.cs +++ b/IoTSharp.TaskAction/DeviceActionExcutor.cs @@ -32,7 +32,7 @@ namespace IoTSharp.TaskAction request.RequestFormat = DataFormat.Json; request.AddHeader("Content-Type", contentType); request.AddHeader("cache-control", "no-cache"); - request.AddJsonBody(JsonConvert.SerializeObject(new{ sosType="1", sosContent= input.Input, usingUserId= "" })); + request.AddJsonBody(new{ sosType="1", sosContent= input.Input, usingUserId= "" }); var response = await restclient.ExecutePostAsync(request); if (response.StatusCode == HttpStatusCode.OK) { diff --git a/IoTSharp/ClientApp/angular.json b/IoTSharp/ClientApp/angular.json index 18b4296122aab25fdab3aede1b07e08cfe3f2dd9..23253dd1d75f194d178df89a91d46b03c0942ee9 100644 --- a/IoTSharp/ClientApp/angular.json +++ b/IoTSharp/ClientApp/angular.json @@ -37,12 +37,12 @@ "output": "/assets/vs/" }], "styles": [ - "node_modules/grapesjs/dist/css/grapes.min.css", + "node_modules/bpmn-js/dist/assets/diagram-js.css", "node_modules/bpmn-js/dist/assets/bpmn-font/css/bpmn.css", "src/styles.less"], - "scripts": ["node_modules/grapesjs/dist/grapes.min.js"], - "allowedCommonJsDependencies": ["@antv/g2", "file-saver", "ajv", "ajv-formats", "date-fns", "jquery", "mousetrap","grapesjs-blocks-basic"] + "scripts": [], + "allowedCommonJsDependencies": ["@antv/g2", "file-saver", "ajv", "ajv-formats", "date-fns", "jquery", "mousetrap"] }, "configurations": { "production": { diff --git a/IoTSharp/ClientApp/package.json b/IoTSharp/ClientApp/package.json index 6333c78fd19cf1c9a959f39a9d5bac661d990ca8..b9471ea9699f20cdfb81e49e598f692a45851ed1 100644 --- a/IoTSharp/ClientApp/package.json +++ b/IoTSharp/ClientApp/package.json @@ -65,16 +65,15 @@ "angular-baidu-maps": "^12.0.0", "angular-draggable-droppable": "^5.0.0", "bpmn-js": "^8.1.0", + "echarts": "^5.3.1", "file-saver": "^2.0.5", - "grapesjs": "^0.17.29", - "grapesjs-blocks-basic": "^0.1.8", - "grapesjs-plugin-forms": "^2.0.1", "guid-typescript": "^1.0.9", "monaco-editor": "^0.30.1", "ng-zorro-antd": "^12.0.1", "ngw-json-view": "^3.0.6", "ngx-clipboard": "^14.0.2", "ngx-countdown": "^12.0.1", + "ngx-echarts": "^7.1.0", "ngx-tinymce": "^12.0.0", "ngx-ueditor": "^12.0.0", "rxjs": "~6.6.0", diff --git a/IoTSharp/ClientApp/src/app/routes/flow/flowevents/flowevents.component.ts b/IoTSharp/ClientApp/src/app/routes/flow/flowevents/flowevents.component.ts index 4f734d0320fcfa58b4d326e9784a4af8d494f5bd..bdd2b517d0a84c8e23b08c0a616fdb2b9a5c4bc6 100644 --- a/IoTSharp/ClientApp/src/app/routes/flow/flowevents/flowevents.component.ts +++ b/IoTSharp/ClientApp/src/app/routes/flow/flowevents/flowevents.component.ts @@ -95,7 +95,7 @@ export class FloweventsComponent implements OnInit { const drawerRef = this.drawerService.create({ nzTitle: title, nzContent: FloweventviewComponent, - nzWidth: width, + nzWidth: 1080, nzMaskClosable: nzMaskClosable, nzContentParams: { event: event, diff --git a/IoTSharp/ClientApp/src/app/routes/flow/floweventview/floweventview.component.html b/IoTSharp/ClientApp/src/app/routes/flow/floweventview/floweventview.component.html index a9a60e1f47528dae7a6fefba03bf23f8976b0b2a..0b0710ea703f0725c27c6f9fb4b9190b4ac95a9a 100644 --- a/IoTSharp/ClientApp/src/app/routes/flow/floweventview/floweventview.component.html +++ b/IoTSharp/ClientApp/src/app/routes/flow/floweventview/floweventview.component.html @@ -1,13 +1,11 @@ -
+
-
-
- - + + - - -
+ + +
+
+ +
\ No newline at end of file diff --git a/IoTSharp/ClientApp/src/app/routes/flow/floweventview/floweventview.component.ts b/IoTSharp/ClientApp/src/app/routes/flow/floweventview/floweventview.component.ts index 5ed18a0ec3dfea8dcb1b8112b597af7e7bee060b..093436f497b31306561781943aa593bd7459181f 100644 --- a/IoTSharp/ClientApp/src/app/routes/flow/floweventview/floweventview.component.ts +++ b/IoTSharp/ClientApp/src/app/routes/flow/floweventview/floweventview.component.ts @@ -1,5 +1,6 @@ import { Component, Input, OnDestroy, OnInit, ViewChild } from '@angular/core'; import { _HttpClient } from '@delon/theme'; +import { EChartsOption } from 'echarts'; import { interval, Subscription } from 'rxjs'; import { concat, } from 'rxjs'; import { map } from 'rxjs/operators'; import { appmessage } from '../../common/AppMessage'; @@ -22,6 +23,7 @@ export class FloweventviewComponent implements OnInit, OnDestroy { @ViewChild('flowview', { static: true }) flowview: FlowviewerComponent; current: 0; + option: EChartsOption; constructor(private http: _HttpClient,) { } ngOnDestroy(): void { @@ -39,8 +41,31 @@ export class FloweventviewComponent implements OnInit, OnDestroy { ), this.http.get('api/rules/GetFlowOperations?eventId=' + this.event.eventId).pipe( map((x) => { - if(x.data.length>0){ - this.nodes = x.data; + if(x.data&&x.data.steps.length>0){ + this.nodes = x.data.steps; + this.option = { + // title: { + // text: '' + // }, + tooltip: { + trigger: 'item', + triggerOn: 'mousemove' + }, + series: [ + { + type: 'sankey', + data: x.data.charts.sankey.nodes, + links: x.data.charts.sankey.links, + emphasis: { + focus: 'adjacency' + }, + lineStyle: { + color: 'gradient', + curveness: 0.5 + } + } + ] + }; this.play(); } @@ -53,7 +78,7 @@ export class FloweventviewComponent implements OnInit, OnDestroy { if (this.obs) { this.obs.unsubscribe(); } - this.obs = interval(1000).subscribe(async (x) => { + this.obs = interval(1500).subscribe(async (x) => { var index = x % this.nodes.length; if (index == 0) { await this.flowview.redraw(); diff --git a/IoTSharp/ClientApp/src/app/routes/routes.module.ts b/IoTSharp/ClientApp/src/app/routes/routes.module.ts index 8ddccfb1a6bb9e8da2efd2c10d924b289d8366e7..6c1f24d94e27d70f8732752d840289d19e54f755 100644 --- a/IoTSharp/ClientApp/src/app/routes/routes.module.ts +++ b/IoTSharp/ClientApp/src/app/routes/routes.module.ts @@ -75,16 +75,14 @@ import { DevivceshapeComponent } from './device/devicegraph/panels/devivceshape/ import { GatewayshapeComponent } from './device/devicegraph/panels/gatewayshape/gatewayshape.component'; import { PortshapeComponent } from './device/devicegraph/panels/portshape/portshape.component'; import { toolpaneldirective } from './device/devicegraph/panels/toolpaneldirective'; - - +import { NgxEchartsModule } from 'ngx-echarts'; const COMPONENTS: Array> = []; -const Directive: Type[] = [ - fielddirective, - controldirective, - toolpaneldirective]; +const Directive: Type[] = [fielddirective, controldirective, toolpaneldirective]; @NgModule({ - imports: [SharedModule, RouteRoutingModule, G2BarModule, G2GaugeModule, NzIconModule, WidgetsModule, ClipboardModule ], + imports: [SharedModule, RouteRoutingModule, G2BarModule, G2GaugeModule, NzIconModule, WidgetsModule, ClipboardModule, NgxEchartsModule.forRoot({ + echarts: () => import('echarts'), + }),], declarations: [ ...COMPONENTS, @@ -153,8 +151,7 @@ const Directive: Type[] = [ ConnectionedgeComponent, DevivceshapeComponent, GatewayshapeComponent, - PortshapeComponent, - + PortshapeComponent ] }) export class RoutesModule {} diff --git a/IoTSharp/ClientApp/src/app/routes/util/dynamicform/dynamicformdesigner/dynamicformdesigner.component.ts b/IoTSharp/ClientApp/src/app/routes/util/dynamicform/dynamicformdesigner/dynamicformdesigner.component.ts index 82d42569dff6caa8cf33fd31352310722cbd9065..7abc65d66435c1d54085671b5dbcea07a02ca016 100644 --- a/IoTSharp/ClientApp/src/app/routes/util/dynamicform/dynamicformdesigner/dynamicformdesigner.component.ts +++ b/IoTSharp/ClientApp/src/app/routes/util/dynamicform/dynamicformdesigner/dynamicformdesigner.component.ts @@ -1,6 +1,5 @@ import { Component, Injector, OnInit } from '@angular/core'; -import pluginForms from 'grapesjs-plugin-forms'; -import pluginBlocks from 'grapesjs-blocks-basic'; + import { createCustomElement } from '@angular/elements'; import { NzSelectComponent } from 'ng-zorro-antd/select'; import { TextBoxComponent } from '../cps/text-box/text-box.component'; @@ -15,61 +14,11 @@ export class DynamicformdesignerComponent implements OnInit { constructor(private injector: Injector) { } editor; ngOnInit(): void { - this.editor = grapesjs.init({ - container: '#gjs', - showOffsets: 1, - storageManager: false, - plugins: ['form'], - pluginsOpts: { - 'form': {}, - }, - // ... - - }); - //导入布局栏 - pluginBlocks(this.editor, {}); - //导入Form栏 - pluginForms(this.editor, {}); - - - - console.log(customElements.get('nz-select')) - //导入ng-zorro组件 需要安装@angular/elements支持 - if (!customElements.get('nz-select')) { - customElements.define('nz-select', createCustomElement(NzSelectComponent, { injector: this.injector })); - } - - // Input没有专门的Component,再包装一下就行了,AutoComplate也是一样,把属性和事件暴露出来,然后就跟普通Component一样用,difine和add中的名字和你定义的selector一定要保持一致 - if (!customElements.get('app-text-box')) { - customElements.define('app-text-box', createCustomElement(TextBoxComponent, { injector: this.injector })); - } - - - //样式丢了,结构没有问题 - this._initBlock(); + + + } - _initBlock() { - - + - this.editor.BlockManager.add('nz-select', { - label: 'nz-select', - content: ` - - - - - `, - }); - - - this.editor.BlockManager.add('app-text-box', { - label: 'nz-textbox', - content: ` - - - `, - }); - } } diff --git a/IoTSharp/ClientApp/src/typings.d.ts b/IoTSharp/ClientApp/src/typings.d.ts index 32e6e26ef8cea2c7d6cab39dda63ddd166606e06..e5e544490ea66233372393bdf1c68dc0f5013218 100644 --- a/IoTSharp/ClientApp/src/typings.d.ts +++ b/IoTSharp/ClientApp/src/typings.d.ts @@ -1,4 +1,4 @@ // # 3rd Party Library // If the library doesn't have typings available at `@types/`, // you can still use it by manually adding typings for it -declare var grapesjs: any; + diff --git a/IoTSharp/Controllers/RulesController.cs b/IoTSharp/Controllers/RulesController.cs index 80e6b114d955752f1432b30427447827a0ed72cd..8a16882321fbbb80b54b0dc15ad9c9a3c6b0ae9f 100644 --- a/IoTSharp/Controllers/RulesController.cs +++ b/IoTSharp/Controllers/RulesController.cs @@ -1235,13 +1235,50 @@ namespace IoTSharp.Controllers public ApiResult GetFlowOperations(Guid eventId) { var profile = this.GetUserProfile(); - return new ApiResult(ApiCode.Success, "OK", _context.FlowOperations.Where(c => c.BaseEvent.EventId == eventId).ToList().OrderBy(c => c.Step). - ToList() + var _event = _context.BaseEvents.Include(c=>c.FlowRule).SingleOrDefault(c => c.EventId == eventId); + var _operations = _context.FlowOperations.Include(c=>c.Flow).Where(c => c.BaseEvent == _event).ToList(); + + + + var flows = _context.Flows.Where(c => c.FlowRule.RuleId == _event.FlowRule.RuleId); + var sf = flows.Where(c => c.FlowType == "bpmn:SequenceFlow").ToArray(); + var links = new List(); + var nodes = new List(); + foreach (var item in sf) + { + var target = _operations.FirstOrDefault(c => c.Flow.bpmnid == item.TargetId); + var source = _operations.FirstOrDefault(c => c.Flow.bpmnid == item.SourceId); + if (target != null && source != null) + { + + links.Add(new {source= source.Flow.Flowname?? source.bpmnid, target=target.Flow.Flowname ?? target.bpmnid, value= (target.AddDate - source.AddDate).Value.TotalMilliseconds }); + var _sourcename = source.Flow.Flowname ?? source.bpmnid; + var _targetname = target.Flow.Flowname ?? target.bpmnid; + if (nodes.All(c => c != _sourcename)) + { + nodes.Add(_sourcename); + } + if (nodes.All(c => c != _targetname)) + { + nodes.Add(_targetname); + } + } + } + var steps = _operations.OrderBy(c => c.Step). + ToList() .GroupBy(c => c.Step).Select(c => new { Step = c.Key, Nodes = c - }).ToList()); + }).ToList(); + return new ApiResult(ApiCode.Success, "OK", new + { + steps, + charts=new + { + sankey=new { links, nodes= nodes.Select(c=>new { name=c}).ToList() } + } + }); } [HttpGet("[action]")] diff --git a/IoTSharp/FlowRuleEngine/FlowRuleProcessor.cs b/IoTSharp/FlowRuleEngine/FlowRuleProcessor.cs index b1a460fe260fbd19acdbf654e0153f6ddb1fa4ac..28cbd777e7e8b07f5e397fc731927903c2c7501a 100644 --- a/IoTSharp/FlowRuleEngine/FlowRuleProcessor.cs +++ b/IoTSharp/FlowRuleEngine/FlowRuleProcessor.cs @@ -180,7 +180,7 @@ namespace IoTSharp.FlowRuleEngine return; } - var flow = _allFlows.FirstOrDefault(c => c.bpmnid == peroperation.Flow.TargetId); + var flow = _allFlows.FirstOrDefault(c => c.bpmnid == peroperation.Flow.TargetId && c.FlowType != "label"); switch (flow.FlowType) { case "bpmn:SequenceFlow": @@ -456,25 +456,8 @@ namespace IoTSharp.FlowRuleEngine case "bpmn:EndEvent": - var end = _allflowoperation.FirstOrDefault(c => c.bpmnid == flow.bpmnid); - - if (end != null) - { - end.BuildFlowOperation(peroperation, flow); - end.bpmnid = flow.bpmnid; - end.AddDate = DateTime.Now; - end.FlowRule = peroperation.BaseEvent.FlowRule; - end.Flow = flow; - - end.Data = JsonConvert.SerializeObject(data); - end.NodeStatus = 1; - end.OperationDesc = "处理完成"; - end.Step = 1 + _allflowoperation.Max(c => c.Step); - end.BaseEvent = peroperation.BaseEvent; - } - else - { - end = new FlowOperation(); + + var end = new FlowOperation(); end.BuildFlowOperation(peroperation, flow); end.OperationId = Guid.NewGuid(); end.bpmnid = flow.bpmnid; @@ -487,7 +470,7 @@ namespace IoTSharp.FlowRuleEngine end.Step = 1 + _allflowoperation.Max(c => c.Step); end.BaseEvent = peroperation.BaseEvent; _allflowoperation.Add(end); - } + _logger.Log(LogLevel.Warning, "规则链执行完成"); break;