提交 86c95dcc 编写于 作者: W wq1234wq

事件,规则链模拟,增加代码编辑器以及属性数据代码编辑器动态部件

上级 52dbbf04
......@@ -48,25 +48,28 @@ export class StartupService {
this.translate.setDefaultLang(this.i18n.defaultLang);
}),
),
this.httpClient.get('api/Account/MyInfo').pipe(
this.httpClient.get('api/Menu/GetProfile').pipe(
map((appData) => {
const res = appData as NzSafeAny;
this.settingService.setApp({ name: 'IotSharp', description: 'IotSharp' });
this.settingService.setData('drawerconfig', { width: 720, nzMaskClosable: false });
this.settingService.setUser(res.data.customer);
this.settingService.setUser({
name: res.result.username,
avatar: '',
email: res.result.email,
});
var ACL = [];
if (!res.data.funcs) {
if (!res.result.funcs) {
for (var i = 0; i < 500; i++) {
ACL = [...ACL, i];
}
} else {
this.aclService.setAbility(res.data.funcs);
this.aclService.setAbility(res.result.funcs);
}
this.aclService.setAbility(ACL);
this.aclService.setFull(false); //开启ACL
console.log(this.aclService.data);
var menu = [
{
text: '主导航1',
......@@ -131,11 +134,7 @@ export class StartupService {
link: '/iot/device/devicescene',
// i18n: 'menu.device.devicelist',
},
{
text: '流程',
link: '/iot/flow/designer',
// i18n: 'menu.device.devicelist',
},
{
text: '规则',
link: '/iot/flow/flowlist',
......@@ -175,12 +174,12 @@ export class StartupService {
],
},
];
if (!res.data.menu) {
if (!res.result.menu) {
res.data.menu = menu;
}
this.menuService.add(res.data.menu);
this.menuService.add(res.result.menu);
this.titleService.default = '';
this.titleService.suffix = res.data.tenant.name;
this.titleService.suffix = res.result.appName;
}),
),
).toPromise();
......
import { ChangeDetectorRef } from '@angular/core';
import { Input, ViewChild } from '@angular/core';
import { Component, OnInit } from '@angular/core';
import { SFComponent, SFSchema } from '@delon/form';
import { SFComponent, SFNumberWidgetSchema, SFSchema, SFTextareaWidgetSchema } from '@delon/form';
import { _HttpClient } from '@delon/theme';
import { switchMap } from 'rxjs/operators';
......@@ -33,22 +33,122 @@ export class PropformComponent implements OnInit {
(next) => {
var properties: any = {};
for (var item of next) {
// switch (item.uielement) {
// case 'uielement':
properties[item.keyName] = {
type: 'string',
title: item.keyName,
// maxLength: item.maxLength,
// pattern: item.pattern,
// ui: {
// addOnAfter: item.ui.addOnAfter,
// placeholder: item.ui.placeholder,
// },
default: item.value,
};
// };
// break;
// }
switch (item.keyType) {
case 'XML':
properties[item.keyName] = {
type: 'string',
title: item.keyName,
// maxLength: item.maxLength,
// pattern: item.pattern,
ui: {
widget: 'codefield',
loadingTip: 'loading...',
config: { theme: 'vs-dark', language: 'xml' },
value: item.value,
},
default: item.value,
};
break;
case 'Boolean':
properties[item.keyName] = {
type: 'boolean',
title: item.keyName,
// maxLength: item.maxLength,
// pattern: item.pattern,
ui: {
checkedChildren: 'True',
unCheckedChildren: 'False',
},
default: item.value,
};
break;
case 'String':
properties[item.keyName] = {
type: 'string',
title: item.keyName,
// maxLength: item.maxLength,
// pattern: item.pattern,
default: item.value,
};
break;
case 'Long':
properties[item.keyName] = {
type: 'number',
title: item.keyName,
// maxLength: item.maxLength,
// pattern: item.pattern,
ui: {
hideStep: true,
} as SFNumberWidgetSchema,
default: item.value,
};
break;
case 'Double':
properties[item.keyName] = {
type: 'number',
title: item.keyName,
// maxLength: item.maxLength,
// pattern: item.pattern,
ui: {
hideStep: true,
} as SFNumberWidgetSchema,
default: item.value,
};
break;
case 'Json':
properties[item.keyName] = {
type: 'string',
title: item.keyName,
// maxLength: item.maxLength,
// pattern: item.pattern,
ui: {
widget: 'codefield',
loadingTip: 'loading...',
config: { theme: 'vs-dark', language: 'json' },
value: item.value,
},
default: item.value,
};
break;
case 'Binary':
properties[item.keyName] = {
type: 'string',
title: item.keyName,
// maxLength: item.maxLength,
// pattern: item.pattern,
ui: {
widget: 'textarea',
autosize: { minRows: 2, maxRows: 10 },
} as SFTextareaWidgetSchema,
default: item.value,
};
break;
case 'DateTime':
properties[item.keyName] = {
type: 'string',
title: item.keyName,
format: 'date-time',
displayFormat: 'yyyy-MM-dd HH:mm:ss',
ui: {},
default: item.value,
};
break;
}
}
this.schema.properties = properties;
......@@ -87,4 +187,5 @@ export interface deviceattributeitem {
dataSide: any;
dateTime: string;
value: string;
keyType: string;
}
<div #diagramcontainer style="float: left; width: 100%; height: 800px">
<div #ref class="diagram-container"></div>
<div
style="position: absolute; top: 15rem; right: 30px; z-index: 999; width: 420px; background-color: white; border: solid 1px #ccc"
ng-drag="true"
cdkDrag
>
<!-- <nz-collapse>
<nz-collapse-panel [nzHeader]="nzHeader" nzExpandIconPosition="right" nzActive="false"> -->
<div #diagramcontainer style="height: 800px" nz-row>
<div nz-col #ref class="diagram-container" nzLg="18" nzMd="18" nzSm="18" style="padding: 0.1rem"></div>
<div nz-col nzSm="6" style="padding: 0.1rem">
<nz-card nzTitle="对象属性">
<form nz-form se-container="1" labelWidth="100" gutter="32">
<se label="对象Id" error="对象Id" required>
......@@ -62,13 +55,42 @@
(ngModelChange)="ngModelChange($event)"
/>
</se>
<se label="脚本类型" error="脚本类型" *ngIf="form.flowscripttypeVisable">
<nz-select
[(ngModel)]="form.flowscripttype"
[ngModelOptions]="{ standalone: true }"
(ngModelChange)="flowscripttypeChange($event)"
>
<nz-option nzValue="csharp" nzLabel="csharp"></nz-option>
<nz-option nzValue="json" nzLabel="json"></nz-option>
<nz-option nzValue="bat" nzLabel="bat"></nz-option>
<nz-option nzValue="xml" nzLabel="xml"></nz-option>
<nz-option nzValue="sql" nzLabel="sql"></nz-option>
<nz-option nzValue="python" nzLabel="python"></nz-option>
</nz-select>
</se>
<se label="脚本" error="类型" *ngIf="form.flowscriptVisable">
<nz-code-editor
(ngModelChange)="ngModelChange($event)"
style="width: 100%; height: 500px; padding-top: 1rem"
class="editor"
[(ngModel)]="form.flowscript"
[ngModelOptions]="{ standalone: true }"
[nzEditorOption]="{ theme: 'vs-dark', language: 'csharp' }"
></nz-code-editor>
</se>
</form>
</nz-card>
<!-- </nz-collapse-panel>
</nz-collapse> -->
<ng-template #extraTemplate>
<a>More</a>
</ng-template>
</div>
<ng-template #extraTemplate>
<a>More</a>
</ng-template>
<!-- <nz-collapse>
<nz-collapse-panel [nzHeader]="nzHeader" nzExpandIconPosition="right" nzActive="false"> -->
<!-- </nz-collapse-panel>
</nz-collapse> -->
</div>
.diagram-container {
width: 100%;
height: 100%;
background-color: rgb(181, 245, 185);
}
.highlight:not(.djs-connection) .djs-visual > :nth-child(1) {
fill: green !important; /* color elements as green */
......
......@@ -107,7 +107,7 @@ export class FlowlistComponent implements OnInit {
},
{
text: '设计',
acl: 104,
// acl: 104,
click: (item: ruleflow) => {
this._router.navigate(['/iot/flow/designer'], {
queryParams: {
......@@ -119,7 +119,7 @@ export class FlowlistComponent implements OnInit {
},
{
text: '测试',
acl: 104,
// acl: 104,
click: (item: ruleflow) => {
this.testthisflow(item);
......@@ -202,7 +202,18 @@ export class FlowlistComponent implements OnInit {
this.st.req = this.req;
this.st.load(this.st.pi);
}
reset() {
this.q ==
{
pi: 0,
ps: 10,
Name: '',
Creator: '',
CreatTime: [],
sorter: '',
status: null,
};
}
setstatus(number: number, status: number) {}
}
......
......@@ -42,8 +42,15 @@
</nz-input-group>
</nz-col>
<nz-col [nzSpan]="8">
<button type="button" nz-button nzSize="large" (click)="getCaptcha()" [disabled]="count >= 0" nzBlock
[nzLoading]="http.loading">
<button
type="button"
nz-button
nzSize="large"
(click)="getCaptcha()"
[disabled]="count >= 0"
nzBlock
[nzLoading]="http.loading"
>
{{ count ? count + 's' : ('app.register.get-verification-code' | translate) }}
</button>
</nz-col>
......@@ -57,7 +64,7 @@
<label nz-checkbox formControlName="remember">{{ 'app.login.remember-me' | translate }}</label>
</nz-col>
<nz-col [nzSpan]="12" class="text-right">
<a class="forgot" (click)="msg.error('请找欧阳锋')">{{ 'app.login.forgot-password' | translate }}</a>
<a class="forgot" (click)="msg.error('can\'t help you')">{{ 'app.login.forgot-password' | translate }}</a>
</nz-col>
</nz-form-item>
<nz-form-item>
......@@ -68,10 +75,8 @@
</form>
<div class="other">
{{ 'app.login.sign-in-with' | translate }}
<i nz-tooltip nzTooltipTitle="in fact Auth0 via window" (click)="open('auth0', 'window')" nz-icon
nzType="alipay-circle" class="icon"></i>
<i nz-tooltip nzTooltipTitle="in fact Github via redirect" (click)="open('github')" nz-icon nzType="taobao-circle"
class="icon"></i>
<i nz-tooltip nzTooltipTitle="in fact Auth0 via window" (click)="open('auth0', 'window')" nz-icon nzType="alipay-circle" class="icon"></i>
<i nz-tooltip nzTooltipTitle="in fact Github via redirect" (click)="open('github')" nz-icon nzType="taobao-circle" class="icon"></i>
<i (click)="open('weibo', 'window')" nz-icon nzType="weibo-circle" class="icon"></i>
<a class="register" routerLink="/passport/register">{{ 'app.login.signup' | translate }}</a>
</div>
\ No newline at end of file
</div>
......@@ -38,11 +38,14 @@ import { DynamicformresultviewComponent } from './util/dynamicform/dynamicformre
import { DynamicformviewComponent } from './util/dynamicform/dynamicformview/dynamicformview.component';
import { WidgetsModule } from './widgets/widgets.module';
import { CodeviewComponent } from './util/code/codeview/codeview.component';
import { DelonFormModule, WidgetRegistry } from '@delon/form';
import { CodefieldComponent } from './util/codefield/codefield.component';
const COMPONENTS: Type<null>[] = [];
const Directive: Type<void>[] = [fielddirective];
@NgModule({
imports: [SharedModule, RouteRoutingModule, WidgetsModule],
imports: [SharedModule, RouteRoutingModule, WidgetsModule, DelonFormModule.forRoot()],
declarations: [
...COMPONENTS,
...Directive,
......@@ -77,6 +80,11 @@ const Directive: Type<void>[] = [fielddirective];
DynamicformresultviewComponent,
DynamicformviewComponent,
CodeviewComponent,
CodefieldComponent,
],
})
export class RoutesModule {}
export class RoutesModule {
constructor(widgetRegistry: WidgetRegistry) {
widgetRegistry.register(CodefieldComponent.KEY, CodefieldComponent);
}
}
......@@ -74,7 +74,7 @@ export class TenantlistComponent implements OnInit {
{
// acl: 10,
text: '户管理',
text: '户管理',
click: (item: any) => {
this._router.navigateByUrl('iot/customer/customerlist?id=' + item.id);
},
......
<sf-item-wrap [id]="id" [schema]="schema" [ui]="ui" [showError]="showError" [error]="error" [showTitle]="schema.title">
<nz-code-editor
class="editor"
[ngModel]="value"
[nzEditorOption]="config"
nzEditorMode="normal"
style="width: 100%; height: 200px"
></nz-code-editor>
</sf-item-wrap>
<!-- <nz-code-editor
class="editor"
[ngModel]="code"
[nzEditorOption]="config"
nzEditorMode="normal"
style="width: 300px; height: 100px"
></nz-code-editor> -->
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { CodefieldComponent } from './codefield.component';
describe('CodefieldComponent', () => {
let component: CodefieldComponent;
let fixture: ComponentFixture<CodefieldComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ CodefieldComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(CodefieldComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, OnInit } from '@angular/core';
import { ControlWidget } from '@delon/form';
@Component({
selector: 'app-codefield',
templateUrl: './codefield.component.html',
styleUrls: ['./codefield.component.less'],
})
export class CodefieldComponent extends ControlWidget implements OnInit {
static readonly KEY = 'codefield';
config: { theme: 'vs-dark'; language: 'csharp' };
loadingTip: string;
ngOnInit(): void {
this.loadingTip = this.ui.loadingTip || '加载中……';
this.config = this.ui.config || { theme: 'vs-dark', language: 'csharp' };
console.log(this.value);
this.setValue(this.ui.value);
console.log(this.value);
this.detectChanges();
//this.config = { theme: 'vs-dark', language: 'csharp' };
}
reset(value: string) {
// this.setValue('');
}
change(value: string) {
this.setValue(value);
if (this.ui.change) this.ui.change(value);
}
}
......@@ -47,8 +47,6 @@ export class DynamicformfieldeditorComponent implements OnInit {
this.AllSuportType = x.result.rows.map((x) => {
return { label: x.dictionaryName, value: x.dictionaryValue };
});
console.log(this.AllSuportType);
}),
),
this.http.post('api/dictionary/index', { DictionaryGroupId: 2, pi: 0, ps: 20, limit: 20, offset: 0 }).pipe(
......@@ -56,7 +54,6 @@ export class DynamicformfieldeditorComponent implements OnInit {
this.AllControlType = x.result.rows.map((x) => {
return { label: x.dictionaryName, value: x.dictionaryValue };
});
console.log(this.AllControlType);
}),
),
this.http.get('api/dynamicforminfo/getParams?id=' + this.id).pipe(
......
......@@ -24,13 +24,21 @@ import { map } from 'rxjs/operators';
})
export class DynamicformviewComponent implements OnInit {
@ViewChild('sf', { static: false }) sf: SFComponent;
@Input() id: Number = -1;
@Input() _id: Number = -1;
@Output() onsubmit = new EventEmitter();
options: {};
AllControlType: any = [];
AllSuportType: any = [];
SuportType: any = [];
get id() {
return this._id;
}
set id(val) {
this._id = val;
this.CreatForm(val);
}
constructor(
private _router: ActivatedRoute,
private router: Router,
......@@ -42,7 +50,7 @@ export class DynamicformviewComponent implements OnInit {
private cd: ChangeDetectorRef,
) {}
ngOnInit(): void {
private CreatForm(id) {
this._httpClient.get('api/DynamicFormInfo/GetFormFieldValue?FormId=' + this.id + '&BizId=0').subscribe(
(x) => {
var properties = {};
......@@ -546,6 +554,8 @@ export class DynamicformviewComponent implements OnInit {
() => {},
);
}
ngOnInit(): void {}
schema: SFSchema = {
properties: {},
};
......
<div nz-row>
<div nz-row style="height: 480px">
<div nz-col nzSpan="24">
<nz-card nzTitle="FLows" [nzBordered]="false"> <app-flowviewer #flowview></app-flowviewer></nz-card>
</div>
......@@ -7,13 +7,25 @@
<div nz-row>
<div nz-col nzSpan="12">
<nz-card nzTitle="Test Data" [nzBordered]="false">
<form nz-form #f="ngForm" se-container="1" style="margin: 1rem">
<se label="测试参数模板">
<nz-select [ngModel]="thisisyourtestdataformid" (ngModelChange)="formIdChange($event)" [ngModelOptions]="{ standalone: true }">
<nz-option *ngFor="let option of listOfOption" [nzLabel]="option.label" [nzValue]="option.value"></nz-option>
</nz-select>
</se>
</form>
<app-dynamicformview (onsubmit)="onsubmit($event)" #dynamicformview> </app-dynamicformview
></nz-card>
</div>
<div nz-col nzSpan="12">
<nz-card [nzBordered]="false" class="mb-0" nzTitle="Time Line">
<nz-steps [nzCurrent]="current">
<nz-step></nz-step>
<nz-steps [nzCurrent]="current" nzDirection="vertical">
<nz-step
*ngFor="let step of this.steps"
[nzStatus]="step.nzStatus"
[nzTitle]="step.addDate"
[nzDescription]="step.operationDesc"
></nz-step>
</nz-steps>
</nz-card>
</div>
......
import { Component, OnInit, ViewChild, Input, ChangeDetectorRef, TemplateRef } from '@angular/core';
import { Component, OnInit, ViewChild, Input, ChangeDetectorRef, TemplateRef, OnDestroy } from '@angular/core';
import { _HttpClient } from '@delon/theme';
import { NzTimelineComponent, NzTimelineItemComponent, TimelineService } from 'ng-zorro-antd/timeline';
import { Observable } from 'rxjs';
import { concat, interval, Observable, Subject, Subscription } from 'rxjs';
import { map } from 'rxjs/operators';
import { appmessage } from 'src/app/routes/common/AppMessage';
import { ruleflow } from 'src/app/routes/flow/flowlist/flowlist.component';
import { FlowviewerComponent } from 'src/app/routes/widgets/flowviewer/flowviewer.component';
......@@ -13,9 +14,11 @@ import { DynamicformviewComponent } from '../../dynamicform/dynamicformview/dyna
templateUrl: './flowsimulator.component.html',
styleUrls: ['./flowsimulator.component.less'],
})
export class FlowsimulatorComponent implements OnInit {
export class FlowsimulatorComponent implements OnInit, OnDestroy {
@Input()
id: Number;
listOfOption = [];
obs: Subscription;
// @ViewChild('flowtimeline', { static: true })
// flowtimeline: NzTimelineComponent;
@ViewChild('flowview', { static: true })
......@@ -23,26 +26,50 @@ export class FlowsimulatorComponent implements OnInit {
@ViewChild('dynamicformview', { static: true })
dynamicformview: DynamicformviewComponent;
constructor(
private httpClient: _HttpClient,
private http: _HttpClient,
private cdr: ChangeDetectorRef, // private timelineservice: TimelineService
) {}
ngOnDestroy(): void {
if (this.obs) {
this.obs.unsubscribe();
}
}
// @ViewChild('TimeLineItemTemplate', { read: TemplateRef }) TimeLineItemTemplate: TemplateRef<any>;
thisisyourtestdataformid: number = 1;
steps: [];
thisisyourtestdataformid: Number = 1;
steps: any = [];
nodes = [];
current: 0;
ngOnInit(): void {
this.httpClient.get<appmessage<ruleflow>>('api/rules/get?id=' + this.id).subscribe(
(next) => {
this.flowview.diagramdata = next.result;
concat(
this.http.post('api/dynamicforminfo/index', { DictionaryGroupId: 1, pi: 0, ps: 20, limit: 20, offset: 0 }).pipe(
map((x) => {
this.listOfOption = x.result.rows.map((x) => {
return { label: x.formName, value: x.formId };
});
this.flowview.loadXml();
},
(error) => {},
() => {},
);
this.dynamicformview.id = this.thisisyourtestdataformid;
this.dynamicformview.id = this.listOfOption[0]?.value;
console.log(this.dynamicformview.id);
}),
),
this.http.get<appmessage<ruleflow>>('api/rules/get?id=' + this.id).pipe(
map((x) => {
this.flowview.diagramdata = x.result;
this.flowview.loadXml();
}),
),
).subscribe();
// this.http.get<appmessage<ruleflow>>('api/rules/get?id=' + this.id).subscribe(
// (next) => {
// this.flowview.diagramdata = next.result;
//it's deadend
// this.flowview.loadXml();
// },
// (error) => {},
// () => {},
// );
//it's deadend,nothing you can get
// let item = new NzTimelineItemComponent(this.cdr, this.timelineservice);
// item.borderColor = '#eeeeff';
// item.template = this.TimeLineItemTemplate;
......@@ -56,9 +83,11 @@ export class FlowsimulatorComponent implements OnInit {
// console.log(this.flowtimeline.timelineItems);
}
formIdChange(iamnottheformidyouwantit): void {
this.dynamicformview.id = this.thisisyourtestdataformid;
}
onsubmit(formdata) {
this.httpClient
this.http
.post('api/rules/active', {
form: formdata,
extradata: {
......@@ -67,9 +96,37 @@ export class FlowsimulatorComponent implements OnInit {
},
})
.subscribe(
(next) => {},
(next) => {
this.nodes = next.result; //
this.play();
},
(error) => {},
() => {},
);
}
play() {
if (this.obs) {
this.obs.unsubscribe();
}
this.obs = interval(1000).subscribe(async (x) => {
var index = x % this.nodes.length;
if (index == 0) {
await this.flowview.redraw();
this.steps = [];
}
for (var element of this.steps) {
element.nzStatus = 'finish';
}
for (const node of this.nodes[index].nodes) {
this.flowview.sethighlight(node.bpmnid);
this.steps = [...this.steps, { addDate: node.addDate, operationDesc: node.operationDesc, nzStatus: 'process' }];
}
// if (this.nodes.length + 3 == x) {
// this.obs.unsubscribe();
// }
});
}
}
<div #viewer class="diagram-container" style="width: 100%"></div>
<div #viewer class="diagram-container" style="width: 100%; height: 460px"></div>
......@@ -18,7 +18,6 @@ import { interval } from 'rxjs';
styleUrls: ['./flowviewer.component.less'],
})
export class FlowviewerComponent implements AfterContentInit, OnChanges, OnDestroy {
nodes = ['Event_1ugcz6g', 'Flow_1d2x8ry', 'Activity_1fl2v8i', 'Flow_09ib71g', 'Activity_1pl6xim', 'Flow_1nmme3b', 'Event_1e0aci8'];
@ViewChild('viewer', { static: true })
private viewer: ElementRef;
@Input()
......@@ -43,9 +42,8 @@ export class FlowviewerComponent implements AfterContentInit, OnChanges, OnDestr
this.bpmnViewer.attachTo(this.viewer.nativeElement);
}
async loadXml() {
console.log(this.diagramdata);
await this.bpmnViewer.importXML(this.diagramdata.definitionsXml);
this.bpmnViewer.get('canvas').zoom('fit-viewport');
var elementRegistry = this.bpmnViewer.get('elementRegistry');
var shape = elementRegistry.get('Activity_1pl6xim');
var overlays = this.bpmnViewer.get('overlays');
......@@ -64,19 +62,17 @@ export class FlowviewerComponent implements AfterContentInit, OnChanges, OnDestr
// });
// console.log(overlays);
// overlays.remove(id);
var canvas = this.bpmnViewer.get('canvas');
//只是修改了属性
const souce = interval(1000).subscribe(async (x) => {
var index = x % this.nodes.length;
//只是修改了属性
}
if (index == 0) {
await this.bpmnViewer.importXML(this.diagramdata.definitionsXml);
}
if (index < this.nodes.length) {
canvas.addMarker(this.nodes[index], 'flowviewhighlight');
}
});
async redraw() {
await this.bpmnViewer.importXML(this.diagramdata.definitionsXml);
}
sethighlight(bpmnid) {
var canvas = this.bpmnViewer.get('canvas');
//只能添加一次,再次添加只能重绘后添加了
canvas.addMarker(bpmnid, 'flowviewhighlight');
}
ngOnChanges(changes: SimpleChanges): void {}
......
import { NgModule, Type } from '@angular/core';
import { G2MiniAreaModule } from '@delon/chart/mini-area';
import { G2MiniBarModule } from '@delon/chart/mini-bar';
import { DelonFormModule, WidgetRegistry } from '@delon/form';
import { SharedModule } from '@shared';
import { NzCarouselModule } from 'ng-zorro-antd/carousel';
import { FlowviewerComponent } from './flowviewer/flowviewer.component';
import { WidgetsRoutingModule } from './widgets-routing.module';
......@@ -12,7 +14,7 @@ import { WidgetsComponent } from './widgets/widgets.component';
const COMPONENTS: Type<void>[] = [WidgetsComponent, FlowviewerComponent];
@NgModule({
imports: [SharedModule, WidgetsRoutingModule, NzCarouselModule, G2MiniBarModule, G2MiniAreaModule],
imports: [SharedModule, WidgetsRoutingModule, NzCarouselModule, G2MiniBarModule, G2MiniAreaModule, DelonFormModule],
declarations: COMPONENTS,
exports: COMPONENTS,
})
......
......@@ -16,8 +16,9 @@ import { NgxJsonViewModule } from 'ngw-json-view';
// #region third libs
// import { NgxTinymceModule } from 'ngx-tinymce';
import { UEditorModule } from 'ngx-ueditor';
import { NzCodeEditorModule } from 'ng-zorro-antd/code-editor';
const THIRDMODULES: Type<any>[] = [DragDropModule, DragAndDropModule, NgxJsonViewModule];
const THIRDMODULES: Type<any>[] = [DragDropModule, DragAndDropModule, NgxJsonViewModule, NzCodeEditorModule];
// #endregion
// #region your componets & directives
......
/* You can add global styles to this file, and also import other style files */
@import 'node_modules/ng-zorro-antd/code-editor/style/entry.less';
/* 测试,测完该放哪里放哪里 */
.flowviewhighlight .djs-visual > :nth-child(1) {
border-color: green !important;
opacity: 0.4;
fill: green !important; /* color elements as green */
border-color: rgb(223, 126, 16) !important;
opacity: 0.8;
stroke: rgb(223, 126, 16) !important;
}
.flowview:not(.djs-connection) .djs-visual > :nth-child(1) {
border-color: #e6f7ff !important;
......
using Microsoft.EntityFrameworkCore.Migrations;
namespace IoTSharp.Migrations
{
public partial class addflowoperationfield1 : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "bpmnid",
table: "FlowOperations",
type: "text",
nullable: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "bpmnid",
table: "FlowOperations");
}
}
}
using Microsoft.EntityFrameworkCore.Migrations;
namespace IoTSharp.Migrations
{
public partial class addfolwscriptfield : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "NodeProcessScriptType",
table: "Flows",
type: "text",
nullable: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "NodeProcessScriptType",
table: "Flows");
}
}
}
using Microsoft.EntityFrameworkCore.Migrations;
namespace IoTSharp.Migrations
{
public partial class addformfield : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "FormLayout",
table: "DynamicFormInfos",
type: "text",
nullable: true);
migrationBuilder.AddColumn<bool>(
name: "IsCompact",
table: "DynamicFormInfos",
type: "boolean",
nullable: false,
defaultValue: false);
migrationBuilder.AddColumn<long>(
name: "RuleId",
table: "BaseEvents",
type: "bigint",
nullable: false,
defaultValue: 0L);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "FormLayout",
table: "DynamicFormInfos");
migrationBuilder.DropColumn(
name: "IsCompact",
table: "DynamicFormInfos");
migrationBuilder.DropColumn(
name: "RuleId",
table: "BaseEvents");
}
}
}
using Microsoft.EntityFrameworkCore.Migrations;
namespace IoTSharp.Migrations
{
public partial class addeventfield : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<long>(
name: "EventId",
table: "FlowOperations",
type: "bigint",
nullable: false,
defaultValue: 0L);
migrationBuilder.AddColumn<string>(
name: "Bizid",
table: "BaseEvents",
type: "text",
nullable: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "EventId",
table: "FlowOperations");
migrationBuilder.DropColumn(
name: "Bizid",
table: "BaseEvents");
}
}
}
......@@ -182,6 +182,9 @@ namespace IoTSharp.Migrations
.HasColumnType("bigint")
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
b.Property<string>("Bizid")
.HasColumnType("text");
b.Property<DateTime>("CreaterDateTime")
.HasColumnType("timestamp without time zone");
......@@ -200,6 +203,9 @@ namespace IoTSharp.Migrations
b.Property<string>("MataData")
.HasColumnType("text");
b.Property<long>("RuleId")
.HasColumnType("bigint");
b.Property<int>("Type")
.HasColumnType("integer");
......@@ -639,6 +645,9 @@ namespace IoTSharp.Migrations
b.Property<string>("FormDesc")
.HasColumnType("text");
b.Property<string>("FormLayout")
.HasColumnType("text");
b.Property<string>("FormName")
.HasColumnType("text");
......@@ -651,6 +660,9 @@ namespace IoTSharp.Migrations
b.Property<DateTime?>("FromCreateDate")
.HasColumnType("timestamp without time zone");
b.Property<bool>("IsCompact")
.HasColumnType("boolean");
b.Property<string>("ModelClass")
.HasColumnType("text");
......@@ -696,6 +708,9 @@ namespace IoTSharp.Migrations
b.Property<string>("NodeProcessScript")
.HasColumnType("text");
b.Property<string>("NodeProcessScriptType")
.HasColumnType("text");
b.Property<string>("NodeProcessType")
.HasColumnType("text");
......@@ -738,6 +753,9 @@ namespace IoTSharp.Migrations
b.Property<string>("Data")
.HasColumnType("text");
b.Property<long>("EventId")
.HasColumnType("bigint");
b.Property<long>("FlowId")
.HasColumnType("bigint");
......@@ -756,6 +774,9 @@ namespace IoTSharp.Migrations
b.Property<string>("Tag")
.HasColumnType("text");
b.Property<string>("bpmnid")
.HasColumnType("text");
b.HasKey("OperationId");
b.ToTable("FlowOperations");
......
......@@ -18,9 +18,12 @@ namespace IoTSharp.Data
public string EventName { get; set; }
public string EventDesc { get; set; }
public int EventStaus { get; set; }
public int Type { get; set; }
public EventType Type { get; set; }
public string MataData { get; set; }
public long RuleId { get; set; }
public Guid Creator { get; set; }
public string Bizid { get; set; }
public DateTime CreaterDateTime { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IoTSharp.Data
{
public class BaseFunction
{[Key]
public long FunctionId { get; set; }
public string FunctionName { get; set; }
public string FunctionController { get; set; }
public string FunctionAction { get; set; }
public string FunctionDesc { get; set; }
public string FunctionRoute { get; set; }
public int FunctionType{ get; set; }
public long FunctionParent { get; set; }
public int FunctionStatus { get; set; }
}
}
......@@ -24,5 +24,8 @@ namespace IoTSharp.Data
public string Url { get; set; }
public Guid Creator { get; set; }
public DateTime? FromCreateDate { get; set; }
public string FormLayout { get; set; } //horizontal vertical inline
public bool IsCompact { get; set; }
}
}
......@@ -125,4 +125,15 @@ namespace IoTSharp.Data
RuleNode,
RuleSwitcher
}
[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))]
[JsonConverter(typeof(StringEnumConverter))]
public enum EventType
{
Normal=1,
TestPurpose=2
}
}
\ No newline at end of file
......@@ -26,6 +26,7 @@ namespace IoTSharp.Data
public string NodeProcessMethod { get; set; }
public string NodeProcessParams { get; set; }
public string NodeProcessType{ get; set; }
public string NodeProcessScriptType { get; set; }
public string NodeProcessScript { get; set; }
public string Incoming { get; set; }
public string Outgoing { get; set; }
......
......@@ -18,8 +18,10 @@ namespace IoTSharp.Data
public string OperationDesc { get; set; }
public string Data { get; set; }
public string BizId { get; set; }
public string bpmnid { get; set; }
public long FlowId { get; set; }
public long RuleId { get; set; }
public long EventId { get; set; }
public int Step { get; set; }
public string Tag { get; set; }
}
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IoTSharp.Data
{
class RoleAsset
{
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IoTSharp.Data
{
class RoleFunction
{
}
}
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using IoTSharp.Data;
using IoTSharp.Models;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
namespace IoTSharp.App_Code.Util.Extensions
{
public static class JwtControllerExtension
{
public static string JWTKEY="";
public static async Task<UserProfile> GetUserProfile(this ControllerBase c)
{
string token = await c.HttpContext.GetTokenAsync(JwtBearerDefaults.AuthenticationScheme, "access_token");
if (!string.IsNullOrEmpty(token))
{
var _token = token.Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries);
if (_token.Length == 3)
{
//var header = _token[0];
var payload = _token[1];
// var sign = _token[2];
//// var YOURJWTKEY = "iotsharpiotsharpiotsharpiotsharpiotsharp";
// var hs256 = new HMACSHA256(Encoding.UTF8.GetBytes(JWTKEY));
// var target = Base64UrlEncoder.Encode(
// hs256.ComputeHash(Encoding.UTF8.GetBytes(string.Concat(header, ".", payload))));
// //验签
// if (string.Equals(sign, target))
// {
var claims = JwtHeader.Base64UrlDeserialize(payload);
return new UserProfile()
{
Id = Guid.Parse(claims[ClaimTypes.NameIdentifier].ToString() ?? string.Empty),
Name = claims[ClaimTypes.Name].ToString() ?? string.Empty,
Roles = JsonConvert.DeserializeObject<string[]>(claims[ClaimTypes.Role]?.ToString() ?? string.Empty),
Email = JsonConvert.DeserializeObject<string[]>(claims[ClaimTypes.Email]?.ToString() ?? string.Empty),
Tenant = Guid.Parse(claims[IoTSharpClaimTypes.Tenant]?.ToString() ?? string.Empty),
Comstomer = Guid.Parse(claims[IoTSharpClaimTypes.Customer]?.ToString() ?? string.Empty),
};
//}
}
}
return default;
}
}
}
......@@ -90,6 +90,12 @@ namespace IoTSharp.Controllers
{
try
{
var sss = "";
for (int i = 0; i < 100; i++)
{
sss += Guid.NewGuid().ToString();
}
var result = await _signInManager.PasswordSignInAsync(model.UserName, model.Password, false, false);
if (result.Succeeded)
{
......@@ -101,6 +107,7 @@ namespace IoTSharp.Controllers
new Claim(ClaimTypes.Email, appUser.Email),
new Claim(ClaimTypes.NameIdentifier, appUser.Id),
new Claim(ClaimTypes.Name, appUser.UserName),
new Claim(ClaimTypes.UserData, sss),
};
var lstclaims = await _userManager.GetClaimsAsync(appUser);
claims.AddRange(lstclaims);
......
......@@ -4,7 +4,13 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using IoTSharp.App_Code.Util.Extensions;
using IoTSharp.Data;
using IoTSharp.Models;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
namespace IoTSharp.Controllers
{
......@@ -17,11 +23,358 @@ namespace IoTSharp.Controllers
[ApiController]
public class MenuController : ControllerBase
{
private readonly UserManager<IdentityUser> _userManager;
private readonly ApplicationDbContext _context;
public MenuController(UserManager<IdentityUser> userManager, ApplicationDbContext context)
{
this._userManager = userManager;
this._context = context;
}
public async Task<AppMessage> GetUserAsset(int type)
{
var profile = await this.GetUserProfile();
switch (type)
{
case 1:
if (profile.Roles.Contains("SystemAdmin"))
{
return new AppMessage()
{
ErrType = ErrType.正常返回, Result = new[] {""}
};
}
if (profile.Roles.Contains("SystemAdmin"))
{
return new AppMessage()
{
ErrType = ErrType.正常返回,
Result = new[] { "" }
};
}
if (profile.Roles.Contains("SystemAdmin"))
{
return new AppMessage()
{
ErrType = ErrType.正常返回,
Result = new[] { "" }
};
}
if (profile.Roles.Contains("SystemAdmin"))
{
return new AppMessage()
{
ErrType = ErrType.正常返回,
Result = new[] { "" }
};
}
if (profile.Roles.Contains("SystemAdmin"))
{
return new AppMessage()
{
ErrType = ErrType.正常返回,
Result = new[] { "" }
};
}
break;
}
return new AppMessage();
}
[Authorize]
[HttpGet("[action]")]
public async Task<AppMessage> GetProfile()
{
var profile = await this.GetUserProfile();
if (profile.Roles.Contains("SystemAdmin"))
{
return new AppMessage()
{
Result = new
{
menu = new[]
{
new
{
text = "主导航",i18n="menu.main",group=true ,hideInBreadcrumb=true,
children=new[]
{
new
{
text = "仪表盘",
i18n="menu.dashboard",
icon="anticon-dashboard",
children=new[]
{
new { text = "仪表盘", i18n = "",link="/dashboard/v1" }
}
},
new
{
text = "租户管理",
i18n="",
icon="anticon-rocket",
children=new[]
{
new { text = "租户列表", i18n = "",link="/iot/tenant/tenantlist" }
}
},
new
{
text = "客户管理",
i18n="",
icon="anticon-rocket",
children=new[]
{
new { text = "租户列表", i18n = "",link="/iot/customer/customerlist" }
}
},
new
{
text = "用户管理",
i18n="",
icon="anticon-rocket",
children=new[]
{
new { text = "用户列表", i18n = "",link="/iot/user/userlist" }
}
},
new
{
text = "设备管理",
i18n="",
icon="anticon-rocket",
children=new[]
{
new { text = "设备列表", i18n = "",link="/iot/device/devicelist" },
new { text = "设计", i18n = "",link="/iot/device/devicegraph" },
new { text = "规则链", i18n = "",link="/iot/flow/flowlist" },
}
},
new
{
text = "资源",
i18n="",
icon="anticon-rocket",
children=new[]
{
new { text = "字典分组", i18n = "",link="/iot/dictionary/dictionarygrouplist" },
new { text = "字典", i18n = "",link="/iot/dictionary/dictionarylist" },
new { text = "国际化", i18n = "",link="/iot/resouce/i18nlist" },
new { text = "表单", i18n = "",link="/iot/util/dynamicformlist" },
}
},
}
}
},
funcs = Enumerable.Range(0, 500),
username= profile.Name,
AppName="IOTSHARP",
Email= profile.Email.FirstOrDefault(),
Logo=""
}
};
}
if (profile.Roles.Contains("TenantAdmin"))
{
return new AppMessage()
{
Result = new
{
menu = new[]
{
new
{
text = "主导航",i18n="menu.main",group=true ,hideInBreadcrumb=true,
children=new[]
{
new
{
text = "仪表盘",i18n="menu.dashboard",icon="anticon-dashboard",
children=new[]
{
new { text = "仪表盘", i18n = "menu.dashboard.v1",link="/dashboard/v1" }
}
},
new
{
text = "客户管理",i18n="",icon="anticon-rocket",
children=new[]
{
new { text = "客户列表", i18n = "",link="/iot/customer/customerlist" }
}
},
new
{
text = "用户管理",i18n="",icon="anticon-rocket",
children=new[]
{
new { text = "用户列表", i18n = "menu.customer.userlist",link="/iot/user/userlist" }
}
},
}
}
},
funcs = Enumerable.Range(0, 500),
username = profile.Name,
AppName = "IOTSHARP",
Email = profile.Email.FirstOrDefault(),
Logo = ""
}
};
}
if (profile.Roles.Contains("CustomerAdmin"))
{
return new AppMessage()
{
Result = new
{
menu = new[]
{
new
{
text = "主导航",i18n="menu.main",group=true ,hideInBreadcrumb=true,
children=new[]
{
new
{
text = "仪表盘",i18n="menu.dashboard",icon="anticon-dashboard",
children=new[]
{
new { text = "仪表盘", i18n = "menu.dashboard.v1",link="/dashboard/v1" }
}
},
new
{
text = "设备管理",i18n="menu.tenant.devicemanage",icon="anticon-rocket",
children=new[]
{
new { text = "设备列表", i18n = "",link="/iot/device/devicelist" },
new { text = "规则链", i18n = "",link="/iot/device/devicelist" },
new { text = "设计", i18n = "",link="/iot/device/devicelist" },
new { text = "场景", i18n = "",link="/iot/device/devicelist" },
}
},
new
{
text = "用户管理",i18n="",icon="anticon-rocket",
children=new[]
{
new { text = "用户列表", i18n = "menu.user.customerlist",link="/iot/user/userlist" }
}
},
}
}
},
funcs = Enumerable.Range(0, 500),
username = profile.Name,
AppName = "IOTSHARP",
Email = profile.Email.FirstOrDefault(),
Logo = ""
}
};
}
if (profile.Roles.Contains("NormalUser"))
{
return new AppMessage()
{
Result = new
{
menu = new[]
{
new
{
text = "主导航",i18n="menu.main",group=true ,hideInBreadcrumb=true,
children=new[]
{
new
{
text = "仪表盘",i18n="menu.dashboard",icon="anticon-dashboard",
children=new[]
{
new { text = "仪表盘", i18n = "menu.dashboard.v1",link="/dashboard/v1" }
}
},
new
{
text = "设备管理",i18n="menu.tenant.devicemanage",icon="anticon-rocket",
children=new[]
{
new { text = "设备列表", i18n = "",link="/iot/device/devicelist" },
new { text = "规则链", i18n = "",link="/iot/device/devicelist" },
new { text = "设计", i18n = "",link="/iot/device/devicelist" },
new { text = "场景", i18n = "",link="/iot/device/devicelist" },
}
},
}
}
},
funcs = Enumerable.Range(0, 500),
username = profile.Name,
AppName = "IOTSHARP",
Email = profile.Email.FirstOrDefault(),
Logo = ""
}
};
}
return new AppMessage();
}
[AllowAnonymous]
[HttpGet("[action]")]
public JsonResult getMenuList()
{
return new JsonResult(new[]
{
......@@ -39,7 +392,7 @@ namespace IoTSharp.Controllers
alias="",
redirect="",
caseSensitive="false",
},
......@@ -56,7 +409,7 @@ namespace IoTSharp.Controllers
return new JsonResult(new[]
{
"this","is","test"
});
}
}
......
......@@ -134,10 +134,10 @@ namespace IoTSharp.Data
await _signInManager.UserManager.AddClaimAsync(user, new Claim(ClaimTypes.Email, model.Email));
await _signInManager.UserManager.AddClaimAsync(user, new Claim(IoTSharpClaimTypes.Customer, customer.Id.ToString()));
await _signInManager.UserManager.AddClaimAsync(user, new Claim(IoTSharpClaimTypes.Tenant, tenant.Id.ToString()));
await _signInManager.UserManager.AddToRoleAsync(user, nameof(UserRole.Anonymous));
await _signInManager.UserManager.AddToRoleAsync(user, nameof(UserRole.NormalUser));
await _signInManager.UserManager.AddToRoleAsync(user, nameof(UserRole.CustomerAdmin));
await _signInManager.UserManager.AddToRoleAsync(user, nameof(UserRole.TenantAdmin));
//await _signInManager.UserManager.AddToRoleAsync(user, nameof(UserRole.Anonymous));
//await _signInManager.UserManager.AddToRoleAsync(user, nameof(UserRole.NormalUser));
//await _signInManager.UserManager.AddToRoleAsync(user, nameof(UserRole.CustomerAdmin));
//await _signInManager.UserManager.AddToRoleAsync(user, nameof(UserRole.TenantAdmin));
await _signInManager.UserManager.AddToRoleAsync(user, nameof(UserRole.SystemAdmin));
}
......
......@@ -35,7 +35,7 @@ namespace IoTSharp.FlowRuleEngine.Models
{
RuleName = this.id,
RuleExpressionType = RuleExpressionType.LambdaExpression,
Expression = this.Expression, SuccessEvent = this.id, Properties = new Dictionary<string, object>()
Expression = this.Expression, SuccessEvent = this.id,
};
}
}
......@@ -21,7 +21,7 @@ namespace IoTSharp.FlowRuleEngine.Models.Task
public int WaitTime { get; set; }
}
public class AbstractTaskExcutor : ITaskExcutor<ExcuteEntity>
public class SimpleTaskExcutor : ITaskExcutor<ExcuteEntity>
{
......@@ -43,7 +43,7 @@ namespace IoTSharp.FlowRuleEngine.Models.Task
foreach (var item in Input.Task.outgoing)
{
item.Rule.Properties = new Dictionary<string, object> {{"Flow", item}};
item.Rule.Operator=item.id;
}
mainRules.Rules = Input.Task.outgoing.Select(c => c.Rule).ToList();
var bre = new RulesEngine.RulesEngine(new[] { mainRules }, null);
......
......@@ -67,8 +67,8 @@ namespace IoTSharp.Models.Rule
public string NodeProcessClass { get; set; }
public string conditionexpression { get; set; }
public string NodeProcessParams { get; set; }
public string flowscript { get; set; }
public string flowscripttype { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace IoTSharp.Models
{
public class UserProfile
{
public string[] Roles { get; set; }
public Guid Id { get; set; }
public string[] Email{ get; set; }
public Guid Comstomer { get; set; }
public Guid Tenant { get; set; }
public string Name { get; set; }
}
}
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册