[webapp] 通知红标,近期未处理告警展示
This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component } from '@angular/core';
|
||||
import { NoticeIconList, NoticeIconSelect, NoticeItem } from '@delon/abc/notice-icon';
|
||||
import { add, formatDistanceToNow, parse } from 'date-fns';
|
||||
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, Inject, OnInit} from '@angular/core';
|
||||
import {NoticeIconSelect, NoticeItem } from '@delon/abc/notice-icon';
|
||||
import { NzI18nService } from 'ng-zorro-antd/i18n';
|
||||
import { NzMessageService } from 'ng-zorro-antd/message';
|
||||
import {AlertService} from "../../../service/alert.service";
|
||||
import {ALAIN_I18N_TOKEN} from "@delon/theme";
|
||||
import {I18NService} from "@core";
|
||||
import {Router} from "@angular/router";
|
||||
|
||||
@Component({
|
||||
selector: 'header-notify',
|
||||
@@ -13,53 +16,35 @@ import { NzMessageService } from 'ng-zorro-antd/message';
|
||||
[loading]="loading"
|
||||
btnClass="alain-default__nav-item"
|
||||
btnIconClass="alain-default__nav-item-icon"
|
||||
(select)="select($event)"
|
||||
(clear)="clear($event)"
|
||||
(clear)="gotoAlertCenter($event)"
|
||||
(popoverVisibleChange)="loadData()"
|
||||
></notice-icon>
|
||||
`,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class HeaderNotifyComponent {
|
||||
export class HeaderNotifyComponent implements OnInit{
|
||||
|
||||
data: NoticeItem[] = [
|
||||
{
|
||||
title: '告警通知',
|
||||
title: '近期未处理告警',
|
||||
list: [],
|
||||
emptyText: '暂无告警通知',
|
||||
emptyText: '暂无未处理告警',
|
||||
emptyImage: 'https://gw.alipayobjects.com/zos/rmsportal/wAhyIChODzsoKIOBHcBk.svg',
|
||||
clearText: '清空告警'
|
||||
clearText: '进入告警中心'
|
||||
}
|
||||
];
|
||||
count = 5;
|
||||
count = 0;
|
||||
loading = false;
|
||||
|
||||
constructor(private msg: NzMessageService, private nzI18n: NzI18nService, private cdr: ChangeDetectorRef) {}
|
||||
constructor(private msg: NzMessageService,
|
||||
private nzI18n: NzI18nService,
|
||||
private router: Router,
|
||||
@Inject(ALAIN_I18N_TOKEN) private i18nSvc: I18NService,
|
||||
private alertSvc: AlertService,
|
||||
private cdr: ChangeDetectorRef) {}
|
||||
|
||||
private updateNoticeData(notices: NoticeIconList[]): NoticeItem[] {
|
||||
const data = this.data.slice();
|
||||
data.forEach(i => (i.list = []));
|
||||
|
||||
notices.forEach(item => {
|
||||
const newItem = { ...item } as NoticeIconList;
|
||||
if (typeof newItem.datetime === 'string') {
|
||||
newItem.datetime = parse(newItem.datetime, 'yyyy-MM-dd', new Date());
|
||||
}
|
||||
if (newItem.datetime) {
|
||||
newItem.datetime = formatDistanceToNow(newItem.datetime as Date, { locale: this.nzI18n.getDateLocale() });
|
||||
}
|
||||
if (newItem.extra && newItem.status) {
|
||||
newItem.color = (
|
||||
{
|
||||
todo: undefined,
|
||||
processing: 'blue',
|
||||
urgent: 'red',
|
||||
doing: 'gold'
|
||||
} as { [key: string]: string | undefined }
|
||||
)[newItem.status];
|
||||
}
|
||||
data.find(w => w.title === newItem.type)!.list.push(newItem);
|
||||
});
|
||||
return data;
|
||||
ngOnInit(): void {
|
||||
this.loadData();
|
||||
}
|
||||
|
||||
loadData(): void {
|
||||
@@ -67,60 +52,39 @@ export class HeaderNotifyComponent {
|
||||
return;
|
||||
}
|
||||
this.loading = true;
|
||||
setTimeout(() => {
|
||||
const now = new Date();
|
||||
this.data = this.updateNoticeData([
|
||||
{
|
||||
id: '000000001',
|
||||
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png',
|
||||
title: '监控-MYSQL_192.135.34.2-发出2级告警',
|
||||
datetime: add(now, { days: 10 }),
|
||||
type: '告警通知'
|
||||
},
|
||||
{
|
||||
id: '000000002',
|
||||
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png',
|
||||
title: '监控-MYSQL_192.135.44.2-发出1级告警',
|
||||
datetime: add(now, { days: -3 }),
|
||||
type: '告警通知'
|
||||
},
|
||||
{
|
||||
id: '000000003',
|
||||
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png',
|
||||
title: '监控-WEBSITE_www.baidu.com-发出4级告警',
|
||||
datetime: add(now, { months: -3 }),
|
||||
read: true,
|
||||
type: '告警通知'
|
||||
},
|
||||
{
|
||||
id: '000000004',
|
||||
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png',
|
||||
title: '监控-REDIS_192.34.55.3-发出4级告警',
|
||||
datetime: add(now, { years: -1 }),
|
||||
type: '告警通知'
|
||||
},
|
||||
{
|
||||
id: '000000005',
|
||||
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png',
|
||||
title: '监控-REDIS_192.34.55.6-发出4级告警',
|
||||
datetime: '2020-08-07',
|
||||
type: '告警通知'
|
||||
let loadAlerts$ = this.alertSvc.searchAlerts(0, undefined,undefined, 0, 5)
|
||||
.subscribe(message => {
|
||||
loadAlerts$.unsubscribe();
|
||||
if (message.code === 0) {
|
||||
let page = message.data;
|
||||
let alerts = page.content;
|
||||
this.data[0].list = [];
|
||||
alerts.forEach(alert => {
|
||||
let item = {
|
||||
id: alert.id,
|
||||
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png',
|
||||
title: '监控-' + alert.monitorName +'-发出' + this.i18nSvc.fanyi(`alert.priority.${alert.priority}`),
|
||||
datetime: alert.gmtCreate,
|
||||
color: 'blue',
|
||||
type: '近期未处理告警'
|
||||
}
|
||||
this.data[0].list.push(item);
|
||||
})
|
||||
this.count = page.totalElements;
|
||||
} else {
|
||||
console.warn(message.msg);
|
||||
}
|
||||
]);
|
||||
|
||||
this.loading = false;
|
||||
this.cdr.detectChanges();
|
||||
}, 500);
|
||||
this.loading = false;
|
||||
this.cdr.detectChanges();
|
||||
}, error => {
|
||||
loadAlerts$.unsubscribe();
|
||||
console.error(error.msg);
|
||||
this.loading = false;
|
||||
})
|
||||
}
|
||||
|
||||
clear(type: string): void {
|
||||
this.loading = true;
|
||||
setTimeout(() => {
|
||||
this.data = this.updateNoticeData([]);
|
||||
this.loading = false;
|
||||
this.cdr.detectChanges();
|
||||
}, 500);
|
||||
this.msg.success(`已清空 ${type}`);
|
||||
gotoAlertCenter(type: string): void {
|
||||
this.router.navigateByUrl(`/alert/center`);
|
||||
}
|
||||
|
||||
select(res: NoticeIconSelect): void {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { ChangeDetectionStrategy, Component, Inject } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { DA_SERVICE_TOKEN, ITokenService } from '@delon/auth';
|
||||
import { SettingsService, User } from '@delon/theme';
|
||||
import {LocalStorageService} from "../../../service/local-storage.service";
|
||||
|
||||
@Component({
|
||||
selector: 'header-user',
|
||||
@@ -20,10 +20,6 @@ import { SettingsService, User } from '@delon/theme';
|
||||
<i nz-icon nzType="setting" class="mr-sm"></i>
|
||||
{{ 'menu.account.settings' | i18n }}
|
||||
</div>
|
||||
<div nz-menu-item routerLink="/exception/trigger">
|
||||
<i nz-icon nzType="close-circle" class="mr-sm"></i>
|
||||
{{ 'menu.account.trigger' | i18n }}
|
||||
</div>
|
||||
<li nz-menu-divider></li>
|
||||
<div nz-menu-item (click)="logout()">
|
||||
<i nz-icon nzType="logout" class="mr-sm"></i>
|
||||
@@ -39,10 +35,12 @@ export class HeaderUserComponent {
|
||||
return this.settings.user;
|
||||
}
|
||||
|
||||
constructor(private settings: SettingsService, private router: Router, @Inject(DA_SERVICE_TOKEN) private tokenService: ITokenService) {}
|
||||
constructor(private settings: SettingsService,
|
||||
private router: Router,
|
||||
private localStorageSvc : LocalStorageService) {}
|
||||
|
||||
logout(): void {
|
||||
this.tokenService.clear();
|
||||
this.router.navigateByUrl(this.tokenService.login_url!);
|
||||
this.localStorageSvc.clear();
|
||||
this.router.navigateByUrl('/passport/login');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ export class Alert {
|
||||
monitorName!: string;
|
||||
// 告警级别 0:高-emergency-紧急告警-红色 1:中-critical-严重告警-橙色 2:低-warning-警告告警-黄色
|
||||
priority: number = 2;
|
||||
// 告警状态: 0-正常告警(未读) 3-已读已知
|
||||
// 告警状态: 0-正常告警(待处理) 1-阈值触发但未达到告警次数 2-恢复告警 3-已处理
|
||||
status!: number;
|
||||
content!: string;
|
||||
times!: number;
|
||||
|
||||
@@ -20,11 +20,11 @@
|
||||
</button>
|
||||
<button nz-button nzType="primary" (click)="onMarkReadAlerts()">
|
||||
<i nz-icon nzType="down-circle" nzTheme="outline"></i>
|
||||
标记已读
|
||||
标记已处理
|
||||
</button>
|
||||
<button nz-button nzType="primary" (click)="onMarkUnReadAlerts()">
|
||||
<i nz-icon nzType="up-circle" nzTheme="outline"></i>
|
||||
标记未读
|
||||
标记未处理
|
||||
</button>
|
||||
<button nz-button nzType="primary" (click)="sync()" nz-tooltip nzTooltipTitle="刷新">
|
||||
<i nz-icon nzType="sync" nzTheme="outline"></i>
|
||||
@@ -38,8 +38,8 @@
|
||||
<nz-select style="margin-right: 10px;float: right;width: 120px;" nzAllowClear
|
||||
[nzPlaceHolder]="'告警状态过滤'" [(ngModel)]="filterStatus">
|
||||
<nz-option nzLabel="全部状态" nzValue="9"></nz-option>
|
||||
<nz-option nzLabel="未读告警" nzValue="0"></nz-option>
|
||||
<nz-option nzLabel="已读告警" nzValue="3"></nz-option>
|
||||
<nz-option nzLabel="未处理" nzValue="0"></nz-option>
|
||||
<nz-option nzLabel="已处理" nzValue="3"></nz-option>
|
||||
</nz-select>
|
||||
<nz-select style="margin-right: 10px;float: right;width: 120px;" nzAllowClear
|
||||
[nzPlaceHolder]="'告警级别过滤'" [(ngModel)]="filterPriority">
|
||||
@@ -97,17 +97,17 @@
|
||||
</td>
|
||||
<td nzAlign="center">{{ data.content }}</td>
|
||||
<td nzAlign="center">
|
||||
{{ data.status === 0 ? '未读' : '已读' }}
|
||||
{{ data.status === 0 ? '未处理' : '已处理' }}
|
||||
</td>
|
||||
<td nzAlign="center">{{ data.gmtCreate }}</td>
|
||||
<td nzAlign="center" nzRight>
|
||||
<button nz-button nzType="primary" (click)="onDeleteOneAlert(data.id)" nz-tooltip nzTooltipTitle="删除告警">
|
||||
<i nz-icon nzType="delete" nzTheme="outline"></i>
|
||||
</button>
|
||||
<button nz-button nzType="primary" (click)="onMarkReadOneAlert(data.id)" nz-tooltip nzTooltipTitle="标记已读">
|
||||
<button nz-button nzType="primary" (click)="onMarkReadOneAlert(data.id)" nz-tooltip nzTooltipTitle="标记已处理">
|
||||
<i nz-icon nzType="down-circle" nzTheme="outline"></i>
|
||||
</button>
|
||||
<button nz-button nzType="primary" (click)="onMarkUnReadOneAlert(data.id)" nz-tooltip nzTooltipTitle="标记未读">
|
||||
<button nz-button nzType="primary" (click)="onMarkUnReadOneAlert(data.id)" nz-tooltip nzTooltipTitle="标记未处理">
|
||||
<i nz-icon nzType="up-circle" nzTheme="outline"></i>
|
||||
</button>
|
||||
</td>
|
||||
|
||||
@@ -2,13 +2,11 @@ import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
|
||||
import { ExceptionComponent } from './exception.component';
|
||||
import { ExceptionTriggerComponent } from './trigger.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '403', component: ExceptionComponent, data: { type: 403 } },
|
||||
{ path: '404', component: ExceptionComponent, data: { type: 404 } },
|
||||
{ path: '500', component: ExceptionComponent, data: { type: 500 } },
|
||||
{ path: 'trigger', component: ExceptionTriggerComponent }
|
||||
{ path: '500', component: ExceptionComponent, data: { type: 500 } }
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
||||
@@ -6,10 +6,9 @@ import { NzCardModule } from 'ng-zorro-antd/card';
|
||||
|
||||
import { ExceptionRoutingModule } from './exception-routing.module';
|
||||
import { ExceptionComponent } from './exception.component';
|
||||
import { ExceptionTriggerComponent } from './trigger.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule, DelonExceptionModule, NzButtonModule, NzCardModule, ExceptionRoutingModule],
|
||||
declarations: [ExceptionComponent, ExceptionTriggerComponent]
|
||||
declarations: [ExceptionComponent]
|
||||
})
|
||||
export class ExceptionModule {}
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { DA_SERVICE_TOKEN, ITokenService } from '@delon/auth';
|
||||
import { _HttpClient } from '@delon/theme';
|
||||
|
||||
@Component({
|
||||
selector: 'exception-trigger',
|
||||
template: `
|
||||
<div class="pt-lg">
|
||||
<nz-card>
|
||||
<button *ngFor="let t of types" (click)="go(t)" nz-button nzDanger>触发{{ t }}</button>
|
||||
<button nz-button nzType="link" (click)="refresh()">触发刷新Token</button>
|
||||
</nz-card>
|
||||
</div>
|
||||
`
|
||||
})
|
||||
export class ExceptionTriggerComponent {
|
||||
types = [401, 403, 404, 500];
|
||||
|
||||
constructor(private http: _HttpClient, @Inject(DA_SERVICE_TOKEN) private tokenService: ITokenService) {}
|
||||
|
||||
go(type: number): void {
|
||||
this.http.get(`/api/${type}`).subscribe();
|
||||
}
|
||||
|
||||
refresh(): void {
|
||||
this.tokenService.set({ token: 'invalid-token' });
|
||||
// 必须提供一个后端地址,无法通过 Mock 来模拟
|
||||
this.http.post(`https://localhost:5001/auth`).subscribe(
|
||||
res => console.warn('成功', res),
|
||||
err => {
|
||||
console.log('最后结果失败', err);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
<nz-form-item>
|
||||
<nz-form-control [nzErrorTip]="'validation.password.required' | i18n">
|
||||
<nz-input-group nzSuffixIcon="lock">
|
||||
<input type="password" nz-input formControlName="password" />
|
||||
<input type="password" nz-input formControlName="password" placeholder="输入任意解锁"/>
|
||||
</nz-input-group>
|
||||
</nz-form-control>
|
||||
</nz-form-item>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { Component } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { Router } from '@angular/router';
|
||||
import { DA_SERVICE_TOKEN, ITokenService } from '@delon/auth';
|
||||
import { SettingsService, User } from '@delon/theme';
|
||||
|
||||
@Component({
|
||||
@@ -18,7 +17,6 @@ export class UserLockComponent {
|
||||
|
||||
constructor(
|
||||
fb: FormBuilder,
|
||||
@Inject(DA_SERVICE_TOKEN) private tokenService: ITokenService,
|
||||
private settings: SettingsService,
|
||||
private router: Router
|
||||
) {
|
||||
@@ -33,11 +31,6 @@ export class UserLockComponent {
|
||||
this.f.controls[i].updateValueAndValidity();
|
||||
}
|
||||
if (this.f.valid) {
|
||||
console.log('Valid!');
|
||||
console.log(this.f.value);
|
||||
this.tokenService.set({
|
||||
token: '123'
|
||||
});
|
||||
this.router.navigate(['dashboard']);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,4 +35,8 @@ export class LocalStorageService {
|
||||
return this.putData(Authorization, token);
|
||||
}
|
||||
|
||||
public clear() {
|
||||
localStorage.clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -55,6 +55,21 @@
|
||||
"redis": "Redis"
|
||||
}
|
||||
},
|
||||
"alert": {
|
||||
"": "告警",
|
||||
"status": {
|
||||
"": "告警状态",
|
||||
"0": "待处理",
|
||||
"2": "已恢复",
|
||||
"3": "已处理"
|
||||
},
|
||||
"priority": {
|
||||
"": "告警级别",
|
||||
"0": "紧急告警",
|
||||
"1": "严重告警",
|
||||
"2": "警告告警"
|
||||
}
|
||||
},
|
||||
"app.lock": "锁屏",
|
||||
"app.login.message-invalid-credentials": "账户或密码错误(admin/ant.design)",
|
||||
"app.login.message-invalid-verification-code": "验证码错误",
|
||||
|
||||
Reference in New Issue
Block a user