Compare commits

...
Author SHA1 Message Date
tomsun28 ee2fcda0ad Merge branch 'master' into update-monitor-list
# Conflicts:
#	web-app/src/app/routes/monitor/monitor.module.ts
2025-03-31 15:47:32 +08:00
tomsun28 7dddc0b2ac update 2025-03-31 14:27:58 +08:00
tomsun28 6cf717ed4d update 2025-03-31 14:01:22 +08:00
tomsun28 d356633e69 update 2025-03-31 13:55:06 +08:00
tomsun28 514e5773ce update 2025-03-31 11:37:31 +08:00
tomsun28 3815ce01d9 update 2025-03-31 11:23:42 +08:00
tomsun28 42ee28dd59 update 2025-03-31 10:55:38 +08:00
tomsun28 30284892ca [improve] update monitor detail ui
Signed-off-by: tomsun28 <tomsun28@outlook.com>
2025-03-31 09:42:45 +08:00
4 changed files with 370 additions and 148 deletions
@@ -85,12 +85,6 @@
</button>
</nz-upload>
</li>
<li nz-menu-item>
<button nz-button (click)="copyMonitor()">
<i nz-icon nzType="copy" nzTheme="outline"></i>
{{ 'monitor.copy' | i18n }}
</button>
</li>
</ul>
</nz-dropdown-menu>
</ng-template>
@@ -139,139 +133,137 @@
</ng-template>
</app-toolbar>
<nz-table
#fixedTable
[nzData]="monitors"
[nzPageIndex]="pageIndex"
[nzPageSize]="pageSize"
[nzTotal]="total"
nzFrontPagination="false"
[nzLoading]="tableLoading"
nzShowSizeChanger
[nzShowTotal]="rangeTemplate"
[nzPageSizeOptions]="[8, 15, 25]"
(nzQueryParams)="onTablePageChange($event)"
nzShowPagination="true"
[nzScroll]="{ x: '1240px' }"
>
<thead>
<tr>
<th nzAlign="center" nzLeft nzWidth="3%" [(nzChecked)]="checkedAll" (nzCheckedChange)="onAllChecked($event)"></th>
<th nzAlign="center" nzWidth="20%" nzColumnKey="name" [nzSortFn]="true">{{ 'monitor.name' | i18n }}</th>
<th nzAlign="center" nzWidth="10%" nzColumnKey="status" [nzSortFn]="true">{{ 'monitor.status' | i18n }}</th>
<th nzAlign="center" nzWidth="12%">{{ 'monitor.host' | i18n }}</th>
<th nzAlign="center" nzWidth="10%">{{ 'monitor.app' | i18n }}</th>
<th nzAlign="center" nzWidth="21%">{{ 'label' | i18n }}</th>
<th nzAlign="center" nzWidth="14%" nzColumnKey="gmtUpdate" [nzSortFn]="true">{{ 'common.edit-time' | i18n }}</th>
<th nzAlign="center" nzWidth="10%" nzRight>{{ 'common.edit' | i18n }}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let data of fixedTable.data">
<td nzAlign="center" nzLeft [nzChecked]="checkedMonitorIds.has(data.id)" (nzCheckedChange)="onItemChecked(data.id, $event)"></td>
<td nzAlign="center" nzEllipsis>
<button nz-button nzSize="default" nzType="link" [routerLink]="['/monitors/' + data.id]">
{{ data.name }}
<span nz-icon nzType="area-chart"></span>
</button>
</td>
<td nzAlign="center">
<nz-tag *ngIf="data.status == 0" [nzColor]="'#b2b2b2'">
<i nz-icon nzType="meh" nzTheme="outline"></i>
<span>{{ 'monitor.status.paused' | i18n }}</span>
</nz-tag>
<nz-tag *ngIf="data.status == 1" [nzColor]="'#498765'">
<i nz-icon nzType="smile" nzTheme="outline"></i>
<span>{{ 'monitor.status.up' | i18n }}</span>
</nz-tag>
<nz-tag *ngIf="data.status == 2" [nzColor]="'#fd4357'">
<i nz-icon nzType="frown" nzTheme="outline"></i>
<span>{{ 'monitor.status.down' | i18n }}</span>
</nz-tag>
</td>
<td nzAlign="center" nzEllipsis>
<button
nz-button
nzSize="default"
nzType="text"
[cdkCopyToClipboard]="data.host"
nz-tooltip
[nzTooltipTitle]="'common.button.copy.tip' | i18n"
(click)="notifyCopySuccess()"
>
{{ data.host }}
<span nz-icon nzType="copy"></span>
</button>
</td>
<td nzAlign="center">
<a routerLink="/monitors" [queryParams]="{ app: data.app }">
<nz-tag nzColor="processing" class="hoverClass">
<i nz-icon nzType="cloud"></i>
<span>{{ 'monitor.app.' + data.app | i18n }}</span>
</nz-tag>
</a>
</td>
<td nzAlign="left">
<nz-tag *ngFor="let label of data.labels | keyvalue" style="margin-top: 2px" [nzColor]="getLabelColor(label.key)">
{{ label.key }}:{{ label.value }}
</nz-tag>
</td>
<td nzAlign="center">{{ (data.gmtUpdate ? data.gmtUpdate : data.gmtCreate) | date : 'YYYY-MM-dd HH:mm:ss' }}</td>
<td nzAlign="center" nzRight>
<div class="actions">
<button nz-button nzType="primary" [routerLink]="['/monitors/' + data.id]" nz-tooltip [nzTooltipTitle]="'monitor.detail' | i18n">
<i nz-icon nzType="area-chart" nzTheme="outline"></i>
</button>
<button nz-button nz-dropdown [nzDropdownMenu]="more_menu">
<span nz-icon nzType="ellipsis"></span>
</button>
<nz-dropdown-menu #more_menu="nzDropdownMenu">
<div class="monitor-card-list">
<div class="monitor-list-header">
<div class="monitor-header-actions">
<label nz-checkbox [(ngModel)]="checkedAll" (ngModelChange)="onAllChecked($event)"></label>
<nz-pagination [(nzPageIndex)]="pageIndex" [nzTotal]="total" (nzPageIndexChange)="onPageIndexChange($event)" nzSimple></nz-pagination>
</div>
</div>
<nz-spin [nzSpinning]="tableLoading">
<div class="monitor-card-list-content">
<div class="monitor-card" *ngFor="let data of monitors">
<div class="monitor-card-checkbox">
<label nz-checkbox [ngModel]="checkedMonitorIds.has(data.id)" (ngModelChange)="onItemChecked(data.id, $event)"></label>
</div>
<div class="monitor-card-content">
<div class="monitor-card-header">
<div class="monitor-card-title">
<button nz-button nzType="link" [routerLink]="['/monitors/' + data.id]">
<span nz-icon nzType="area-chart"></span>
{{ data.name }}
</button>
</div>
<div class="monitor-card-status">
<nz-tag *ngIf="data.status == 0" [nzColor]="'#b2b2b2'">
<i nz-icon nzType="meh" nzTheme="outline"></i>
<span>{{ 'monitor.status.paused' | i18n }}</span>
</nz-tag>
<nz-tag *ngIf="data.status == 1" [nzColor]="'#498765'">
<i nz-icon nzType="smile" nzTheme="outline"></i>
<span>{{ 'monitor.status.up' | i18n }}</span>
</nz-tag>
<nz-tag *ngIf="data.status == 2" [nzColor]="'#fd4357'">
<i nz-icon nzType="frown" nzTheme="outline"></i>
<span>{{ 'monitor.status.down' | i18n }}</span>
</nz-tag>
</div>
</div>
<div class="monitor-card-info">
<div class="monitor-card-info-item host-item">
<button
nz-button
nzType="text"
[cdkCopyToClipboard]="data.host"
nz-tooltip
[nzTooltipTitle]="'common.button.copy.tip' | i18n"
(click)="notifyCopySuccess()"
>
<i nz-icon nzType="global"></i>
{{ data.host }}
</button>
<button nz-button nz-dropdown [nzDropdownMenu]="actionMenu" class="action-button">
<i nz-icon nzType="ellipsis"></i>
</button>
</div>
<div class="monitor-card-info-item meta-row">
<a routerLink="/monitors" [queryParams]="{ app: data.app }">
<nz-tag nzColor="processing">
<i nz-icon nzType="cloud"></i>
<span>{{ 'monitor.app.' + data.app | i18n }}</span>
</nz-tag>
</a>
<div class="label-tags">
<nz-tag *ngFor="let label of data.labels | keyvalue" [nzColor]="getLabelColor(label.key)">
{{ label.key }}:{{ label.value }}
</nz-tag>
</div>
<span
class="time-ago"
nz-tooltip
[nzTooltipTitle]="
('common.edit-time' | i18n) + ': ' + ((data.gmtUpdate ? data.gmtUpdate : data.gmtCreate) | date : 'yyyy-MM-dd HH:mm:ss')
"
>
<i nz-icon nzType="clock-circle"></i>
{{ (data.gmtUpdate ? data.gmtUpdate : data.gmtCreate) | elapsedTime }}
</span>
</div>
</div>
<nz-dropdown-menu #actionMenu="nzDropdownMenu">
<ul nz-menu>
<li nz-menu-item>
<button nz-button (click)="onEditOneMonitor(data.id)" nz-tooltip [nzTooltipTitle]="'monitor.edit-monitor' | i18n">
<i nz-icon nzType="edit" nzTheme="outline"></i>
<button nz-button [routerLink]="['/monitors/' + data.id]">
<i nz-icon nzType="area-chart"></i>
{{ 'monitor.detail' | i18n }}
</button>
</li>
<li nz-menu-item>
<button
*ngIf="data.status == 0"
nz-button
(click)="onEnableManageOneMonitor(data.id)"
nz-tooltip
[nzTooltipTitle]="'monitor.enable' | i18n"
>
<i nz-icon nzType="play-circle" nzTheme="outline"></i>
<button nz-button (click)="onEditOneMonitor(data.id)">
<i nz-icon nzType="edit"></i>
{{ 'monitor.edit-monitor' | i18n }}
</button>
</li>
<li nz-menu-item>
<button
*ngIf="data.status != 0"
nz-button
(click)="onCancelManageOneMonitor(data.id)"
nz-tooltip
[nzTooltipTitle]="'monitor.cancel' | i18n"
>
<i nz-icon nzType="pause-circle" nzTheme="outline"></i>
<button nz-button (click)="copyMonitor(data.id)">
<i nz-icon nzType="copy"></i>
{{ 'monitor.copy' | i18n }}
</button>
</li>
<li nz-menu-divider></li>
<li nz-menu-item *ngIf="data.status == 0">
<button nz-button (click)="onEnableManageOneMonitor(data.id)">
<i nz-icon nzType="play-circle"></i>
{{ 'monitor.enable' | i18n }}
</button>
</li>
<li nz-menu-item *ngIf="data.status != 0">
<button nz-button (click)="onCancelManageOneMonitor(data.id)">
<i nz-icon nzType="pause-circle"></i>
{{ 'monitor.cancel' | i18n }}
</button>
</li>
<li nz-menu-divider></li>
<li nz-menu-item>
<button
nz-button
nzDanger
(click)="onDeleteOneMonitor(data.id)"
nz-tooltip
[nzTooltipTitle]="'monitor.delete-monitor' | i18n"
>
<i nz-icon nzType="delete" nzTheme="outline"></i>
<button nz-button nzDanger (click)="onDeleteOneMonitor(data.id)">
<i nz-icon nzType="delete"></i>
{{ 'monitor.delete-monitor' | i18n }}
</button>
</li>
</ul>
</nz-dropdown-menu>
</div>
</td>
</tr>
</tbody>
</nz-table>
</div>
</div>
</nz-spin>
</div>
<ng-template #rangeTemplate> {{ 'common.total' | i18n }} {{ total }} </ng-template>
@@ -1,4 +1,5 @@
@import '@delon/theme/index';
@import "~src/styles/theme";
::ng-deep {
.monitor-select-menu-modal {
.ant-spin-container {
@@ -64,3 +65,251 @@
opacity: 0.7;
cursor: not-allowed;
}
.monitor-card-list {
width: 100%;
position: relative;
}
.monitor-list-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 16px;
padding: 8px 0;
flex-wrap: wrap;
gap: 8px;
}
.monitor-header-actions {
display: flex;
align-items: center;
}
.monitor-card-list-content {
position: relative;
display: flex;
flex-direction: column;
gap: 12px;
}
.monitor-card {
display: flex;
width: 100%;
border: 1px solid #e8e8e8;
border-radius: 8px;
padding: 12px;
transition: all 0.3s;
background-color: #fff;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
}
.monitor-card:hover {
border-color: @primary-color;
box-shadow: 0 1px 8px rgba(24, 144, 255, 0.2);
transform: translateY(-2px);
}
.monitor-card-checkbox {
padding-right: 16px;
display: flex;
align-items: center;
}
.monitor-card-content {
flex: 1;
display: flex;
flex-direction: column;
}
.monitor-card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
}
.monitor-card-title {
font-size: 16px;
font-weight: 500;
}
.monitor-card-title button {
padding: 0;
height: auto;
font-size: 16px;
font-weight: 500;
color: @primary-color;
}
.monitor-card-info {
display: grid;
grid-template-columns: 1fr;
grid-gap: 8px;
}
.monitor-card-info-item {
display: flex;
align-items: center;
flex-wrap: wrap;
}
.host-item {
display: flex;
justify-content: space-between;
align-items: center;
button {
padding: 0;
height: auto;
i {
margin-right: 4px;
}
}
.action-button {
height: 32px;
padding: 0 8px;
min-width: 32px;
margin-left: auto;
}
}
.meta-row {
display: flex;
justify-content: flex-start;
align-items: center;
flex-wrap: wrap;
gap: 8px;
}
.label-tags {
display: flex;
flex-wrap: wrap;
gap: 4px;
flex: 1;
max-width: 60%;
}
.time-ago {
margin-left: auto;
color: #999;
font-size: 12px;
white-space: nowrap;
i {
margin-right: 4px;
}
}
.info-label {
display: none;
}
.monitor-card-status {
margin-left: auto;
.ant-tag {
margin-right: 0;
}
}
.label-item {
display: none;
}
.danger-text {
color: #ff4d4f;
}
@media (max-width: 768px) {
.meta-row {
flex-direction: column;
align-items: flex-start;
}
.time-ago {
margin-left: 0;
margin-top: 8px;
}
.label-tags {
max-width: 100%;
}
}
[data-theme='dark'] {
:host {
.monitor-card {
background-color: @common-background-color-dark;
border-color: #303030;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
&:hover {
border-color: @primary-color;
box-shadow: 0 1px 8px rgba(24, 144, 255, 0.3);
}
}
.monitor-card-title button {
color: @primary-color;
}
.time-ago {
color: #a0a0a0;
}
.host-item button[nzType="text"] {
color: #d9d9d9;
&:hover {
color: @primary-color;
}
}
.action-button {
background-color: #303030;
border-color: #434343;
&:hover {
background-color: #1f1f1f;
border-color: @primary-color;
}
}
.label-tags .ant-tag {
background-color: #303030;
}
.export-type-card {
background-color: @common-background-color-dark;
border-color: #303030;
&:hover {
border-color: @primary-color;
box-shadow: 0 0 8px rgba(24, 144, 255, 0.3);
}
&.loading {
opacity: 0.5;
background-color: #1f1f1f;
}
}
.export-type-icon {
color: @primary-color;
background: rgba(24, 144, 255, 0.2);
}
.export-type-info {
h3 {
color: #d9d9d9;
}
p {
color: #a0a0a0;
}
}
}
}
@@ -24,7 +24,6 @@ import { ALAIN_I18N_TOKEN, MenuService } from '@delon/theme';
import { NzModalService } from 'ng-zorro-antd/modal';
import { ModalButtonOptions } from 'ng-zorro-antd/modal/modal-types';
import { NzNotificationService } from 'ng-zorro-antd/notification';
import { NzTableQueryParams } from 'ng-zorro-antd/table';
import { NzUploadChangeParam } from 'ng-zorro-antd/upload';
import { finalize } from 'rxjs/operators';
@@ -492,18 +491,8 @@ export class MonitorListComponent implements OnInit, OnDestroy {
this.notifySvc.success(this.i18nSvc.fanyi('common.notify.copy-success'), '');
}
/**
* Paging callback
*
* @param params page info
*/
onTablePageChange(params: NzTableQueryParams) {
const { pageSize, pageIndex, sort, filter } = params;
onPageIndexChange(pageIndex: number) {
this.pageIndex = pageIndex;
this.pageSize = pageSize;
const currentSort = sort.find(item => item.value !== null);
this.currentSortField = (currentSort && currentSort.key) || null;
this.currentSortOrder = (currentSort && currentSort.value) || null;
this.changeMonitorTable(this.currentSortField, this.currentSortOrder);
}
@@ -604,17 +593,7 @@ export class MonitorListComponent implements OnInit, OnDestroy {
return hash;
}
copyMonitor() {
if (this.checkedMonitorIds == null || this.checkedMonitorIds.size === 0) {
this.notifySvc.warning(this.i18nSvc.fanyi('common.notify.no-select-delete'), '');
return;
}
if (this.checkedMonitorIds.size > 1) {
this.notifySvc.warning(this.i18nSvc.fanyi('monitor.copy.notify.one-select'), '');
return;
}
const monitorId = Array.from(this.checkedMonitorIds)[0];
copyMonitor(monitorId: number) {
this.monitorSvc.copyMonitor(monitorId).subscribe(
message => {
if (message.code === 0) {
@@ -26,6 +26,7 @@ import { NzDescriptionsModule } from 'ng-zorro-antd/descriptions';
import { NzDividerModule } from 'ng-zorro-antd/divider';
import { NzLayoutModule } from 'ng-zorro-antd/layout';
import { NzListModule } from 'ng-zorro-antd/list';
import { NzPaginationModule } from 'ng-zorro-antd/pagination';
import { NzRadioModule } from 'ng-zorro-antd/radio';
import { NzSpaceModule } from 'ng-zorro-antd/space';
import { NzSwitchModule } from 'ng-zorro-antd/switch';
@@ -70,7 +71,8 @@ const COMPONENTS: Array<Type<void>> = [
NzUploadModule,
SafePipe,
NzListModule,
NzDescriptionsModule
NzDescriptionsModule,
NzPaginationModule
],
declarations: COMPONENTS
})