-
-
-
-
-
+
+
diff --git a/web-app/src/app/routes/dashboard/dashboard.component.less b/web-app/src/app/routes/dashboard/dashboard.component.less
index 6b1d3e6..e6bd4b0 100644
--- a/web-app/src/app/routes/dashboard/dashboard.component.less
+++ b/web-app/src/app/routes/dashboard/dashboard.component.less
@@ -1,61 +1,3 @@
-@import '~@delon/theme/index';
-:host ::ng-deep {
- .map-chart {
- height: 457px;
- padding-top: 24px;
- text-align: center;
- img {
- display: inline-block;
- max-width: 100%;
- max-height: 437px;
- }
- }
- .pie-card {
- .pie-stat {
- font-size: 24px !important;
- }
- }
- .active-chart {
- position: relative;
- g2-mini-area {
- margin-top: 32px;
- }
- .active-grid {
- p {
- position: absolute;
- top: 80px;
- width: 100%;
- padding-bottom: 4px;
- border-bottom: 1px dashed #e9e9e9;
- }
- p:last-child {
- top: 115px;
- }
- }
- .active-legend {
- position: relative;
- height: 20px;
- margin-top: 8px;
- font-size: 0;
- line-height: 20px;
- span {
- display: inline-block;
- width: 33.33%;
- font-size: 12px;
- text-align: center;
- }
- span:first-child {
- text-align: left;
- }
- span:last-child {
- text-align: right;
- }
- }
- }
-
- @media screen and (max-width: @screen-lg) {
- .map-chart {
- height: auto;
- }
- }
+.demo-chart {
+ height: auto;
}
diff --git a/web-app/src/app/routes/dashboard/dashboard.component.ts b/web-app/src/app/routes/dashboard/dashboard.component.ts
index 6002576..0b154dc 100644
--- a/web-app/src/app/routes/dashboard/dashboard.component.ts
+++ b/web-app/src/app/routes/dashboard/dashboard.component.ts
@@ -1,6 +1,17 @@
-import {ChangeDetectionStrategy, Component, ViewChild} from '@angular/core';
+import {
+ ChangeDetectionStrategy,
+ ChangeDetectorRef,
+ Component,
+ Inject,
+ OnDestroy,
+ OnInit
+} from '@angular/core';
import {NzMessageService} from "ng-zorro-antd/message";
-import {G2PieClickItem, G2PieComponent, G2PieData} from "@delon/chart/pie";
+import {MonitorService} from "../../service/monitor.service";
+import { EChartsOption } from 'echarts';
+import {I18NService} from "@core";
+import {ALAIN_I18N_TOKEN} from "@delon/theme";
+import {Router} from "@angular/router";
@Component({
selector: 'app-dashboard',
@@ -8,55 +19,147 @@ import {G2PieClickItem, G2PieComponent, G2PieData} from "@delon/chart/pie";
styleUrls: ['./dashboard.component.less'],
changeDetection: ChangeDetectionStrategy.OnPush
})
-export class DashboardComponent {
+export class DashboardComponent implements OnInit, OnDestroy {
- @ViewChild('pie', { static: false }) readonly pie!: G2PieComponent;
- salesPieData: G2PieData[] = [];
- total = '';
+ constructor(private msg: NzMessageService,
+ private monitorSvc: MonitorService,
+ @Inject(ALAIN_I18N_TOKEN) private i18nSvc: I18NService,
+ private router: Router,
+ private cdr: ChangeDetectorRef){}
- constructor(private msg: NzMessageService){}
+ interval$!: number;
+ appsCountLoading: boolean = true;
+ appsCountTableData: any[] = [];
+ appsCountEChartOption!: EChartsOption;
ngOnInit(): void {
+ this.appsCountLoading = true;
this.refresh();
+ this.appsCountLoading = false;
+ // https://stackoverflow.com/questions/43908009/why-is-setinterval-in-an-angular-service-only-firing-one-time
+ this.interval$ = setInterval(this.refresh.bind(this), 10000);
+ }
+
+ ngOnDestroy(): void {
+ clearInterval(this.interval$);
}
refresh(): void {
- const rv = (min: number = 0, max: number = 5000) => Math.floor(Math.random() * (max - min + 1) + min);
- this.salesPieData = [
- {
- x: '应用服务',
- y: rv(),
- },
- {
- x: '数据库',
- y: rv(),
- },
- {
- x: '中间件',
- y: rv(),
- },
- {
- x: '自定义',
- y: rv(),
- },
- {
- x: '其它',
- y: rv(),
- },
- ];
- this.total = `${this.salesPieData.reduce((pre, now) => now.y + pre, 0).toFixed(2)}`;
- if (this.pie) {
- // 等待组件渲染
- setTimeout(() => this.pie.changeData());
+ let dashboard$ = this.monitorSvc.getAppsMonitorSummary()
+ .subscribe(message => {
+ dashboard$.unsubscribe();
+ if (message.code === 0) {
+ // {app:'linux',size: 12}
+ let apps: any[] = message.data.apps;
+ this.appsCountTableData = [];
+ let total = 0;
+ apps.forEach(app => {
+ let appName = this.i18nSvc.fanyi('monitor.app.' + app.app);
+ this.appsCountTableData.push({
+ // 自定义属性
+ app: app.app,
+ // 默认属性
+ name: appName,
+ value: app.size
+ });
+ total = total + app.size? app.size : 0;
+ });
+
+ this.appsCountEChartOption = {
+ title: {
+ text: '监控总览',
+ subtext: '监控类型纳管数量分布',
+ left: 'center'
+ },
+ tooltip: {
+ trigger: 'item',
+ formatter: '{a}
{b} : {c}个监控 占比({d}%)'
+ },
+ legend: {
+ itemWidth: 80,
+ itemHeight: 20,
+ right: 0,
+ orient: 'vertical'
+ },
+ calculable: true,
+ series: [
+ {
+ name: '总量',
+ type: 'pie',
+ selectedMode: 'single',
+ color: '#722ED1',
+ radius: [0, '30%'],
+ label: {
+ position: 'center',
+ fontSize: 15,
+ color: '#ffffff',
+ fontStyle: 'oblique',
+ formatter: '{a}:{c}',
+ },
+ labelLine: {
+ show: false
+ },
+ data: [
+ { value: total, name: '监控总量' },
+ ]
+ },
+ {
+ name: '纳管数量分布',
+ type: 'pie',
+ radius: ['45%', '65%'],
+ labelLine: {
+ length: 30
+ },
+ label: {
+ formatter: '{a|{a}}{abg|}\n{hr|}\n {b|{b}:}{c} {per|{d}%} ',
+ backgroundColor: '#F6F8FC',
+ borderColor: '#8C8D8E',
+ borderWidth: 1,
+ borderRadius: 4,
+ rich: {
+ a: {
+ color: '#6E7079',
+ lineHeight: 22,
+ align: 'center'
+ },
+ hr: {
+ borderColor: '#8C8D8E',
+ width: '100%',
+ borderWidth: 1,
+ height: 0
+ },
+ b: {
+ color: '#4C5058',
+ fontSize: 14,
+ fontWeight: 'bold',
+ lineHeight: 33
+ },
+ per: {
+ color: '#fff',
+ backgroundColor: '#4C5058',
+ padding: [3, 4],
+ borderRadius: 4
+ }
+ }
+ },
+ data: this.appsCountTableData
+ }
+ ]
+ };
+ this.cdr.detectChanges();
+ }
+ }, error => {
+ console.error(error);
+ dashboard$.unsubscribe();
+ });
+ }
+
+ onChartClick(click: any) {
+ if (click != undefined) {
+ let app = click.data?.app;
+ if (app != undefined) {
+ this.router.navigate(['/monitors'], { queryParams: { app: app } });
+ }
}
}
-
- format(val: number): string {
- return `${val.toFixed()}`;
- }
-
- handleClick(data: G2PieClickItem): void {
- this.msg.info(`${data.item.x} - ${data.item.y}`);
- }
-
}
diff --git a/web-app/src/app/routes/routes.module.ts b/web-app/src/app/routes/routes.module.ts
index ceca254..e1427b9 100644
--- a/web-app/src/app/routes/routes.module.ts
+++ b/web-app/src/app/routes/routes.module.ts
@@ -1,9 +1,9 @@
import { NgModule, Type } from '@angular/core';
import { SharedModule } from '@shared';
-import {G2PieModule} from "@delon/chart/pie";
-import {G2WaterWaveModule} from "@delon/chart/water-wave";
// dashboard pages
import { DashboardComponent } from './dashboard/dashboard.component';
+import { RouteRoutingModule } from './routes-routing.module';
+import {NgxEchartsModule} from "ngx-echarts";
// single pages
import { CallbackComponent } from './passport/callback.component';
import { UserLockComponent } from './passport/lock/lock.component';
@@ -11,7 +11,6 @@ import { UserLockComponent } from './passport/lock/lock.component';
import { UserLoginComponent } from './passport/login/login.component';
import { UserRegisterResultComponent } from './passport/register-result/register-result.component';
import { UserRegisterComponent } from './passport/register/register.component';
-import { RouteRoutingModule } from './routes-routing.module';
const COMPONENTS: Array
> = [
DashboardComponent,
@@ -25,7 +24,7 @@ const COMPONENTS: Array> = [
];
@NgModule({
- imports: [SharedModule, RouteRoutingModule, G2PieModule, G2WaterWaveModule],
+ imports: [SharedModule, RouteRoutingModule, NgxEchartsModule],
declarations: COMPONENTS,
})
export class RoutesModule {}
diff --git a/web-app/src/app/service/monitor.service.ts b/web-app/src/app/service/monitor.service.ts
index 4e05865..b1f195e 100644
--- a/web-app/src/app/service/monitor.service.ts
+++ b/web-app/src/app/service/monitor.service.ts
@@ -9,6 +9,7 @@ const monitor_uri = "/monitor";
const monitors_uri = "/monitors";
const detect_monitor_uri = "/monitor/detect"
const manage_monitors_uri = "/monitors/manage";
+const summary_uri = "/summary";
@Injectable({
providedIn: 'root'
@@ -86,4 +87,9 @@ export class MonitorService {
public getMonitorMetricData(monitorId: number, metric: string) : Observable> {
return this.http.get>(`/monitors/${monitorId}/metrics/${metric}`);
}
+
+ public getAppsMonitorSummary() : Observable> {
+ return this.http.get>(summary_uri);
+ }
+
}