From 6490b7d4e73ae8cb1a7fdb0acf2e59aac56f1906 Mon Sep 17 00:00:00 2001
From: zhaojisen <1301338853@qq.com>
Date: Mon, 30 Dec 2024 18:40:57 +0800
Subject: [PATCH] Perf: Optimize code structure
---
src/app/model.ts | 2 +-
src/app/pages/pages.component.ts | 6 +-
.../pam/gui.component/gui.component.html | 20 -
.../pam/gui.component/gui.component.scss | 102 ----
src/app/pages/pam/pam.component.html | 140 ++++++
src/app/pages/pam/pam.component.scss | 453 ++++++++++++++++++
.../gui.component.ts => pam.component.ts} | 151 ++++--
src/app/pages/pam/pam.module.ts | 1 +
.../terminal.component.html | 94 ----
.../terminal.component.scss | 264 ----------
.../terminal.component/terminal.component.ts | 232 ---------
src/app/router.module.ts | 6 +-
src/app/services/http.ts | 2 +-
13 files changed, 704 insertions(+), 769 deletions(-)
delete mode 100644 src/app/pages/pam/gui.component/gui.component.html
delete mode 100644 src/app/pages/pam/gui.component/gui.component.scss
create mode 100644 src/app/pages/pam/pam.component.html
create mode 100644 src/app/pages/pam/pam.component.scss
rename src/app/pages/pam/{gui.component/gui.component.ts => pam.component.ts} (63%)
create mode 100644 src/app/pages/pam/pam.module.ts
delete mode 100644 src/app/pages/pam/terminal.component/terminal.component.html
delete mode 100644 src/app/pages/pam/terminal.component/terminal.component.scss
delete mode 100644 src/app/pages/pam/terminal.component/terminal.component.ts
diff --git a/src/app/model.ts b/src/app/model.ts
index 68d8e846..6bce1bae 100644
--- a/src/app/model.ts
+++ b/src/app/model.ts
@@ -376,7 +376,7 @@ export class ConnectOption {
export class AdminConnectData {
asset: Asset;
account: Account;
- protocol: Protocol;
+ protocol: string;
input_username: string;
method: string;
}
diff --git a/src/app/pages/pages.component.ts b/src/app/pages/pages.component.ts
index 8cf61061..4e87a30b 100644
--- a/src/app/pages/pages.component.ts
+++ b/src/app/pages/pages.component.ts
@@ -4,9 +4,8 @@ import { PagesBlankComponent } from "./blank/blank.component";
import { PagesReplayComponent } from "./replay/replay.component";
import { PagesConnectComponent } from "./connect/connect.component";
import { PagesMonitorComponent } from "./monitor/monitor.component";
-import { PagePamGUIComponent } from "./pam/gui.component/gui.component";
import { PagesNotFoundComponent } from "./not-found/not-found.component";
-import { PagePamTerminalComponent } from "./pam/terminal.component/terminal.component";
+import { PagePamComponent } from "./pam/pam.component";
export const PagesComponents = [
PageMainComponent,
@@ -16,6 +15,5 @@ export const PagesComponents = [
PagesNotFoundComponent,
PageSftpComponent,
PagesMonitorComponent,
- PagePamTerminalComponent,
- PagePamGUIComponent,
+ PagePamComponent
];
diff --git a/src/app/pages/pam/gui.component/gui.component.html b/src/app/pages/pam/gui.component/gui.component.html
deleted file mode 100644
index f9547f54..00000000
--- a/src/app/pages/pam/gui.component/gui.component.html
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
{{ totalConnectTime }}
-
-
-
-
-
-
-
diff --git a/src/app/pages/pam/gui.component/gui.component.scss b/src/app/pages/pam/gui.component/gui.component.scss
deleted file mode 100644
index 2493ca56..00000000
--- a/src/app/pages/pam/gui.component/gui.component.scss
+++ /dev/null
@@ -1,102 +0,0 @@
-.pam-gui {
- position: relative;
- width: 100%;
- height: 100%;
-
- elements-iframe {
- width: 100%;
- height: 100%;
- display: block;
- }
-}
-
-.timer-container {
- position: fixed;
- bottom: 70px;
- right: 20px;
- z-index: 999999;
-
- .timer {
- display: flex;
- align-items: center;
- background: rgba(0, 0, 0, 0.8);
- padding: 6px 12px;
- border-radius: 100px;
- color: white;
- font-family: monospace;
- font-size: 14px;
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
-
- span {
- margin-left: 4px;
- }
-
- .status-dot {
- width: 8px;
- height: 8px;
- border-radius: 50%;
- background-color: #dc3545;
- margin-right: 6px;
- transition: opacity 0.3s ease;
-
- &.active {
- animation: blink 1s infinite;
- }
- }
- }
-}
-
-.action-icons {
- position: fixed;
- top: 20px;
- right: 20px;
- z-index: 999999;
- display: flex;
- gap: 10px;
- opacity: 0;
- visibility: hidden;
- transition: opacity 0.3s ease;
- transition-delay: 0s, 0.3s;
-
- &.show {
- opacity: 1;
- visibility: visible;
- transition-delay: 0s;
- }
-
- .close-icon {
- display: flex;
- align-items: center;
- justify-content: center;
- width: 32px;
- height: 32px;
- border-radius: 50%;
- background: rgba(0, 0, 0, 0.8);
- cursor: pointer;
- transition: all 0.3s ease;
-
- &:hover {
- background: rgba(0, 0, 0, 0.9);
- transform: scale(1.05);
- }
-
- mat-icon {
- color: white;
- font-size: 20px;
- width: 20px;
- height: 20px;
- }
- }
-}
-
-@keyframes blink {
- 0% {
- opacity: 1;
- }
- 50% {
- opacity: 0.4;
- }
- 100% {
- opacity: 1;
- }
-}
diff --git a/src/app/pages/pam/pam.component.html b/src/app/pages/pam/pam.component.html
new file mode 100644
index 00000000..c5854ab8
--- /dev/null
+++ b/src/app/pages/pam/pam.component.html
@@ -0,0 +1,140 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SSH 会话
+
+
+
+
+
+
dvr
+
+
+ 资产信息:
+
+ {{ assetName }}
+
+
+
+
+
date_range
+
+
+
+ 连接时间:
+
+ {{ startTime.toLocaleString() }}
+
+
+
+
+
+
+
+
+
{{ totalConnectTime }}
+
+
+
+
+
+
+
+ folder
+
+
+
+ close
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ totalConnectTime }}
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ totalConnectTime }}
+
+
+
+
+
+
+
+
diff --git a/src/app/pages/pam/pam.component.scss b/src/app/pages/pam/pam.component.scss
new file mode 100644
index 00000000..f3d145bd
--- /dev/null
+++ b/src/app/pages/pam/pam.component.scss
@@ -0,0 +1,453 @@
+@mixin time-container {
+ position: fixed;
+ bottom: 40px;
+ right: 40px;
+ z-index: 999999;
+
+ .timer {
+ display: flex;
+ align-items: center;
+ background: rgba(0, 0, 0, 0.8);
+ padding: 6px 12px;
+ border-radius: 100px;
+ color: white;
+ font-family: monospace;
+ font-size: 14px;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
+
+ span {
+ margin-left: 4px;
+ }
+
+ .status-dot {
+ width: 8px;
+ height: 8px;
+ border-radius: 50%;
+ background-color: #dc3545;
+ margin-right: 6px;
+ transition: opacity 0.3s ease;
+
+ &.active {
+ animation: blink 1s infinite;
+ }
+ }
+ }
+
+ @media screen and (max-width: 768px) {
+ bottom: calc(env(safe-area-inset-bottom, 0px) + 20px);
+ right: 50%;
+ transform: translateX(50%);
+ }
+}
+
+@mixin time-icons {
+ position: fixed;
+ top: 20px;
+ right: 20px;
+ z-index: 999999;
+ display: flex;
+ gap: 10px;
+ opacity: 0;
+ visibility: hidden;
+ transition: opacity 0.3s ease;
+ transition-delay: 0s, 0.3s;
+
+ &.show {
+ opacity: 1;
+ visibility: visible;
+ transition-delay: 0s;
+ }
+
+ .close-icon {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 32px;
+ height: 32px;
+ border-radius: 50%;
+ background: rgba(0, 0, 0, 0.8);
+ cursor: pointer;
+ transition: all 0.3s ease;
+
+ &:hover {
+ background: rgba(0, 0, 0, 0.9);
+ transform: scale(1.05);
+ }
+
+ mat-icon {
+ color: white;
+ font-size: 20px;
+ width: 20px;
+ height: 20px;
+ }
+ }
+}
+
+.terminal-connect {
+ display: flex;
+ justify-content: center;
+ height: 100vh;
+ width: 100vw;
+
+ .file-manage-drawer {
+ position: absolute;
+ width: 800px;
+ z-index: 999999;
+
+ @media screen and (max-width: 768px) {
+ width: 100% !important;
+ }
+ }
+
+ .mat-drawer-container {
+ width: 100%;
+
+ .mat-sidenav-content {
+ height: 100vh;
+ overflow: hidden;
+
+ @media screen and (max-width: 768px) {
+ height: calc(100vh - env(safe-area-inset-bottom));
+ padding-bottom: env(safe-area-inset-bottom);
+
+ mat-card {
+ &:first-child {
+ margin: 0;
+ border-radius: 0;
+
+ mat-card-header {
+ flex-direction: column;
+ height: auto !important;
+ padding: 15px;
+
+ .mat-card-title {
+ font-size: 18px;
+ margin-bottom: 15px;
+ padding-bottom: 10px;
+ border-bottom: 1px solid #eee;
+ width: 100%;
+ text-align: center;
+ }
+
+ .info-section {
+ width: 100%;
+ margin: 0;
+ padding: 10px 0;
+
+ .top-part,
+ .bottom-part {
+ padding: 8px 0;
+ margin: 0;
+ gap: 10px;
+
+ .mat-icon {
+ color: #666;
+ }
+
+ .desc {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ gap: 5px;
+
+ div:first-child {
+ color: #666;
+ font-size: 13px;
+ }
+
+ div:last-child {
+ color: #333;
+ font-weight: 500;
+ }
+ }
+ }
+ }
+
+ .action-section {
+ width: 100%;
+ margin-top: 10px;
+ padding-top: 15px;
+ border-top: 1px solid #eee;
+
+ .timer-container {
+ @include time-container;
+ }
+
+ .mat-divider {
+ display: none;
+ }
+
+ .actions {
+ width: 100%;
+ justify-content: space-around;
+
+ .action-icon {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 5px;
+ padding: 8px 15px;
+
+ .mat-icon {
+ font-size: 24px;
+ width: 24px;
+ height: 24px;
+ }
+
+ &::after {
+ content: attr(mattooltip);
+ font-size: 12px;
+ color: #666;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ &:last-child {
+ margin: 0;
+ height: calc(100% - 355px) !important;
+ background-color: #f7f8f9;
+ }
+ }
+ }
+ }
+ }
+
+ ::ng-deep .mat-card-header-text {
+ display: flex;
+ align-items: center;
+ height: 100%;
+
+ .mat-card-title {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 100%;
+ margin: 0 20px;
+ }
+ }
+
+ .mat-divider {
+ height: 100%;
+ border-right-width: 2px;
+ border-right-color: #dcddde;
+ }
+
+ .info-section {
+ display: flex;
+ flex: 2;
+ flex-direction: column;
+ justify-content: center;
+ align-items: flex-start;
+ height: 100%;
+ margin: 0 20px;
+ font-size: 14px;
+
+ @media screen and (max-width: 768px) {
+ margin: 15px 0;
+ padding: 0 10px;
+
+ flex: none;
+ width: 100%;
+ height: auto;
+ }
+
+ .top-part,
+ .bottom-part {
+ display: flex;
+ align-items: center;
+ width: 100%;
+ height: 50%;
+ color: #313538;
+ font-size: 14px;
+
+ @media screen and (max-width: 768px) {
+ height: auto;
+ margin: 8px 0;
+
+ .mat-icon {
+ margin-right: 8px;
+ }
+
+ .desc {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ margin-left: 0;
+
+ div {
+ display: flex;
+ align-items: center;
+
+ &:first-child {
+ margin-right: 8px;
+ }
+ }
+ }
+ }
+
+ .mat-icon {
+ width: 20px;
+ height: 20px;
+ font-size: 20px;
+ cursor: pointer;
+ }
+
+ .desc {
+ display: flex;
+ align-items: stretch;
+ margin-left: 5px;
+ }
+ }
+ }
+
+ .action-section {
+ display: flex;
+ flex: 1;
+ justify-content: flex-end;
+ align-items: center;
+ height: 100%;
+ padding: 0 20px;
+
+ .timer-container {
+ @include time-container;
+ }
+
+ @media screen and (max-width: 768px) {
+ width: 100%;
+ margin-top: 15px;
+ padding: 15px 0 0;
+ border-top: 1px solid #eee;
+
+ .mat-divider {
+ display: none;
+ }
+
+ .actions {
+ width: 100%;
+ display: grid !important;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 15px !important;
+ padding: 0 10px;
+
+ .action-icon {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ background: #f5f6f7;
+ border-radius: 8px;
+ padding: 12px;
+ gap: 8px;
+ height: auto;
+ transition: all 0.2s ease;
+
+ &:hover {
+ background: #eef0f2;
+ transform: translateY(-1px);
+ }
+
+ .mat-icon {
+ font-size: 24px !important;
+ width: 24px !important;
+ height: 24px !important;
+ color: #666;
+ }
+
+ &::after {
+ content: attr(mattooltip);
+ font-size: 13px;
+ color: #666;
+ font-weight: 500;
+ }
+ }
+ }
+ }
+
+ .mat-divider {
+ height: 40%;
+ margin: 0 20px;
+ }
+
+ .actions {
+ display: flex;
+ align-items: center;
+ gap: 20px;
+
+ .action-icon {
+ display: flex;
+ align-items: center;
+ height: 100%;
+ cursor: pointer;
+ transition: all 0.3s ease-in-out;
+ padding: 8px;
+
+ &:hover {
+ color: #1ab394;
+ }
+
+ .mat-icon {
+ font-size: 20px;
+ width: 20px;
+ height: 20px;
+ }
+ }
+ }
+ }
+}
+
+.sftp-connect {
+ position: relative;
+ display: flex;
+ justify-content: center;
+ height: 100vh;
+ width: 100vw;
+
+ .timer-container {
+ @include time-container;
+ }
+
+ .action-icons {
+ @include time-icons;
+ }
+
+ pages-sftp {
+ width: 100%;
+ height: 100%;
+ display: block;
+ }
+}
+
+.pam-gui {
+ position: relative;
+ width: 100%;
+ height: 100%;
+
+ .timer-container {
+ @include time-container;
+ }
+
+ .action-icons {
+ @include time-icons;
+ }
+
+ elements-iframe {
+ width: 100%;
+ height: 100%;
+ display: block;
+ }
+}
+
+@keyframes blink {
+ 0% {
+ opacity: 1;
+ }
+ 50% {
+ opacity: 0.4;
+ }
+ 100% {
+ opacity: 1;
+ }
+}
diff --git a/src/app/pages/pam/gui.component/gui.component.ts b/src/app/pages/pam/pam.component.ts
similarity index 63%
rename from src/app/pages/pam/gui.component/gui.component.ts
rename to src/app/pages/pam/pam.component.ts
index b9f604ed..21a8a8a2 100644
--- a/src/app/pages/pam/gui.component/gui.component.ts
+++ b/src/app/pages/pam/pam.component.ts
@@ -1,54 +1,61 @@
+import { MatSidenav } from "@angular/material/sidenav";
import { ActivatedRoute, Params } from "@angular/router";
-import { Component, OnInit, OnDestroy, ViewChild } from "@angular/core";
import { Protocol, Account, Endpoint, Asset } from "@app/model";
+import { HttpService, I18nService, LogService } from "@app/services";
import {
- HttpService,
- DialogService,
- I18nService,
- LogService,
-} from "@app/services";
-import { MatSidenav } from "@angular/material/sidenav";
+ Component,
+ ViewChild,
+ OnInit,
+ OnDestroy,
+ ElementRef,
+} from "@angular/core";
@Component({
- selector: "pages-pam-gui",
- templateUrl: "./gui.component.html",
- styleUrls: ["./gui.component.scss"],
+ selector: "pages-pam",
+ templateUrl: "./pam.component.html",
+ styleUrls: ["./pam.component.scss"],
})
-export class PagePamGUIComponent implements OnInit, OnDestroy {
+export class PagePamComponent implements OnInit, OnDestroy {
@ViewChild("sidenav", { static: false }) sidenav: MatSidenav;
+ @ViewChild("iFrame", { static: false }) iframeRef: ElementRef;
public startTime: Date;
public endpoint: Endpoint;
public userId: string = "";
- public username: string = "";
public assetId: string = "";
+ public username: string = "";
public assetName: string = "";
- public iframeURL: string = "";
+ public protocol: string = "";
+
+ public iframeRDPURL: string = "";
+ public iframeVNCURL: string = "";
+ public iframeSFTPURL: string = "";
+ public iframeTerminalURL: string = "";
+
public totalConnectTime: string = "00:00:00";
public isActive: boolean = true;
+ public showActionIcons: boolean = false;
private timerInterval: any;
private pausedElapsedTime: number = 0;
- public showActionIcons: boolean = false;
-
constructor(
private _http: HttpService,
private _i18n: I18nService,
private _logger: LogService,
- private _dialogAlert: DialogService,
- private route: ActivatedRoute
+ private _route: ActivatedRoute
) {
this.startTime = new Date();
}
- ngOnInit(): void {
- this.route.params.subscribe(async (params: Params) => {
+ ngOnInit() {
+ this._route.params.subscribe(async (params: Params) => {
this.userId = params["userId"];
this.username = params["username"];
this.assetId = params["assetId"];
this.assetName = params["assetName"];
+ this.protocol = params["protocol"];
this._http.getAssetDetail(this.assetId).subscribe((asset: Asset) => {
const currentUserInfo = asset.permed_accounts.find(
@@ -56,24 +63,23 @@ export class PagePamGUIComponent implements OnInit, OnDestroy {
);
let method: string = "";
- let protocol: Protocol = asset.permed_protocols[0];
- switch (protocol.name) {
+ switch (this.protocol) {
case "ssh":
case "telnet":
- method = "ssh_client";
+ method = "web_cli";
break;
case "rdp":
- method = "mstsc";
+ method = "web_gui";
break;
case "sftp":
- method = "sftp_client";
+ method = "web_sftp";
break;
case "vnc":
- method = "vnc_client";
+ method = "web_gui";
break;
default:
- method = "db_client";
+ method = "web_cli";
}
const assetMessage = {
@@ -89,7 +95,7 @@ export class PagePamGUIComponent implements OnInit, OnDestroy {
};
const connectData = {
method,
- protocol,
+ protocol: this.protocol,
asset: assetMessage,
account: currentUserInfo,
input_username: this.username,
@@ -101,7 +107,31 @@ export class PagePamGUIComponent implements OnInit, OnDestroy {
if (res) {
const url = this.getUrl();
- this.iframeURL = `${url}/lion/connect?token=${res.id}`;
+ switch (this.protocol) {
+ case "ssh": {
+ this.iframeTerminalURL = `${url}/koko/connect?token=${res.id}`;
+ break;
+ }
+ case "sftp": {
+ this.iframeSFTPURL = `${url}/koko/elfinder/sftp/`;
+ break;
+ }
+ case "rdp": {
+ this.iframeRDPURL = `${url}/lion/connect?token=${res.id}`;
+ break;
+ }
+ case "vnc": {
+ this.iframeVNCURL = `${url}/lion/connect?token=${res.id}`;
+ break;
+ }
+ case "telnet": {
+ this.iframeTerminalURL = `${url}/koko/connect?token=${res.id}`;
+ break;
+ }
+ default: {
+ break;
+ }
+ }
}
});
});
@@ -127,12 +157,45 @@ export class PagePamGUIComponent implements OnInit, OnDestroy {
document.addEventListener("mousemove", this.handleMouseMove.bind(this));
}
+ ngOnDestroy() {
+ this.stopTimer();
+ document.removeEventListener("mousemove", this.handleMouseMove.bind(this));
+ }
+
+ /**
+ * 关闭当前连接
+ */
public async handleCloseConnect() {
- window.confirm("确定要关闭当前连接吗?");
+ if (window.confirm("确定要关闭当前连接吗?")) {
+ window.close();
+ }
+ }
+
+ /**
+ * 打开文件管理器
+ */
+ public handleOpenFileManage() {
+ const iframeWindow = (this.iframeRef as unknown as { iframeWindow: Window })
+ .iframeWindow;
- window.close();
+ if (iframeWindow) {
+ iframeWindow.postMessage({ name: "FILE" }, "*");
+ this._logger.info(`[Luna] Send FILE`);
+ }
+ }
+
+ /**
+ * windows 的关闭按钮
+ * @param event
+ */
+ private handleMouseMove(event: MouseEvent): void {
+ this.showActionIcons = event.clientY <= 65;
}
+ /**
+ * @description 获取当前 host 的信息
+ * @returns
+ */
private getUrl(): string {
let host: string = "";
@@ -165,6 +228,15 @@ export class PagePamGUIComponent implements OnInit, OnDestroy {
}
}
+ /**
+ * 补零
+ * @param value
+ * @returns
+ */
+ private padZero(value: number): string {
+ return String(value).padStart(2, "0");
+ }
+
/**
* 更新连接时间
*/
@@ -183,24 +255,9 @@ export class PagePamGUIComponent implements OnInit, OnDestroy {
}
/**
- * 补零
- * @param value
- * @returns
+ * 关闭抽屉
*/
- private padZero(value: number): string {
- return String(value).padStart(2, "0");
- }
-
- private handleMouseMove(event: MouseEvent): void {
- this.showActionIcons = event.clientY <= 65;
- }
-
- ngOnDestroy() {
- this.stopTimer();
- document.removeEventListener("mousemove", this.handleMouseMove.bind(this));
- }
-
- public closeDrawer() {
+ private closeDrawer(): void {
this.sidenav.close();
}
}
diff --git a/src/app/pages/pam/pam.module.ts b/src/app/pages/pam/pam.module.ts
new file mode 100644
index 00000000..0519ecba
--- /dev/null
+++ b/src/app/pages/pam/pam.module.ts
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/app/pages/pam/terminal.component/terminal.component.html b/src/app/pages/pam/terminal.component/terminal.component.html
deleted file mode 100644
index 20543c36..00000000
--- a/src/app/pages/pam/terminal.component/terminal.component.html
+++ /dev/null
@@ -1,94 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
- SSH 会话
-
-
-
-
-
-
dvr
-
-
资产信息:
- {{ assetName }}
-
-
-
-
-
date_range
-
-
-
连接时间:
- {{ startTime.toLocaleString() }}
-
-
-
-
-
-
-
-
-
{{ totalConnectTime }}
-
-
-
-
-
-
-
- folder
-
-
-
- close
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/app/pages/pam/terminal.component/terminal.component.scss b/src/app/pages/pam/terminal.component/terminal.component.scss
deleted file mode 100644
index 160ea343..00000000
--- a/src/app/pages/pam/terminal.component/terminal.component.scss
+++ /dev/null
@@ -1,264 +0,0 @@
-.pam-connect {
- display: flex;
- justify-content: center;
- height: 100vh;
- width: 100vw;
-
- .file-manage-drawer {
- position: absolute;
- width: 800px;
- z-index: 999999;
- }
-
- .mat-drawer-container {
- width: 100%;
-
- ::ng-deep .mat-drawer-inner-container {
- //overflow: hidden;
-
- .drawer-header {
- display: flex;
- justify-content: flex-start;
- align-items: center;
- width: 100%;
- padding: 0 20px;
-
- p {
- font-size: 16px;
- font-weight: 700;
- margin-left: 10px;
- }
- }
-
- .mat-divider {
- height: 10px;
- }
-
- .drawer-manage {
- display: flex;
- align-items: center;
- justify-content: space-between;
- padding: 0 20px;
- height: 50px;
-
- .path {
- display: flex;
- align-items: center;
- justify-content: flex-start;
- flex: 2;
- height: 100%;
-
- .delimiter {
- margin-left: 5px;
- font-size: 1.3rem;
- }
- }
-
- .upload-btn {
- position: relative;
- display: flex;
- align-items: center;
- justify-content: flex-end;
- flex: 1;
-
- .mat-raised-button {
- display: flex;
- justify-content: center;
- align-items: center;
- height: 30px;
- width: 100px;
- }
-
- input[type="file"] {
- opacity: 0;
- position: absolute;
- width: 100%;
- height: 100%;
- cursor: pointer;
- }
- }
- }
-
- .drawer-table {
- width: 100%;
- height: calc(100% - 114px);
- overflow: auto;
-
- .mat-table {
- width: inherit;
- height: 100%;
- //box-shadow: unset;
- }
-
- table {
- width: 100%;
-
- ::ng-deep .mat-column-name {
- width: 500px;
- }
-
- ::ng-deep .mat-cell {
- }
- }
-
- &::-webkit-scrollbar {
- width: 10px;
- height: 10px;
- }
-
- &::-webkit-scrollbar-track {
- background: #f1f1f1;
- }
-
- &::-webkit-scrollbar-thumb {
- background: #888;
- border-radius: 10px;
- }
-
- &::-webkit-scrollbar-thumb:hover {
- background: #555;
- }
- }
- }
-
- ::ng-deep .mat-drawer-content {
- overflow: hidden;
- }
- }
-
- ::ng-deep .mat-card-header-text {
- display: flex;
- align-items: center;
- height: 100%;
-
- .mat-card-title {
- display: flex;
- align-items: center;
- justify-content: center;
- height: 100%;
- margin: 0 20px;
- }
- }
-
- .mat-divider {
- height: 100%;
- border-right-width: 2px;
- border-right-color: #dcddde;
- }
-
- .info-section {
- display: flex;
- flex: 2;
- flex-direction: column;
- justify-content: center;
- align-items: flex-start;
- height: 100%;
- margin: 0 20px;
- font-size: 14px;
-
- .top-part,
- .bottom-part {
- display: flex;
- align-items: center;
- width: 100%;
- height: 50%;
- color: #313538;
- font-size: 14px;
-
- .mat-icon {
- width: 20px;
- height: 20px;
- font-size: 20px;
- cursor: pointer;
- }
-
- .desc {
- display: flex;
- align-items: stretch;
- margin-left: 5px;
- }
- }
- }
-
- .action-section {
- display: flex;
- flex: 1;
- justify-content: flex-end;
- align-items: center;
- height: 100%;
- padding: 0 20px;
-
- .mat-divider {
- height: 40%;
- margin: 0 20px;
- }
-
- .actions {
- display: flex;
- align-items: center;
- gap: 20px;
-
- .action-icon {
- display: flex;
- align-items: center;
- height: 100%;
- cursor: pointer;
- transition: all 0.3s ease-in-out;
- padding: 8px;
-
- &:hover {
- color: #1ab394;
- }
-
- .mat-icon {
- font-size: 20px;
- width: 20px;
- height: 20px;
- }
- }
- }
- }
-}
-
-.timer-container {
- .timer {
- display: flex;
- align-items: center;
- background: rgba(0, 0, 0, 0.8);
- padding: 6px 12px;
- border-radius: 100px;
- color: white;
- font-family: monospace;
- font-size: 14px;
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
-
- span {
- margin-left: 4px;
- }
-
- .status-dot {
- width: 8px;
- height: 8px;
- border-radius: 50%;
- background-color: #dc3545;
- margin-right: 6px;
- transition: opacity 0.3s ease;
-
- &.active {
- animation: blink 1s infinite;
- }
- }
- }
-}
-
-@keyframes blink {
- 0% {
- opacity: 1;
- }
- 50% {
- opacity: 0.4;
- }
- 100% {
- opacity: 1;
- }
-}
diff --git a/src/app/pages/pam/terminal.component/terminal.component.ts b/src/app/pages/pam/terminal.component/terminal.component.ts
deleted file mode 100644
index 61f6ffa7..00000000
--- a/src/app/pages/pam/terminal.component/terminal.component.ts
+++ /dev/null
@@ -1,232 +0,0 @@
-import { ActivatedRoute } from "@angular/router";
-import { MatSidenav } from "@angular/material/sidenav";
-import {
- Account,
- Asset,
- ConnectData,
- ConnectionToken,
- View,
- Protocol,
-} from "@app/model";
-import {
- LogService,
- AppService,
- HttpService,
- I18nService,
- DialogService,
- ConnectTokenService,
-} from "@app/services";
-import {
- OnInit,
- Output,
- Component,
- ViewChild,
- OnDestroy,
- ElementRef,
- EventEmitter,
-} from "@angular/core";
-
-export interface PeriodicElement {
- name: string;
- size: string;
- modificationTime: string;
- attributes: string;
- action: object;
-}
-
-@Component({
- selector: "pages-pam-terminal",
- templateUrl: "./terminal.component.html",
- styleUrls: ["./terminal.component.scss"],
-})
-export class PagePamTerminalComponent implements OnInit, OnDestroy {
- @ViewChild("sidenav", { static: false }) sidenav: MatSidenav;
- @ViewChild("iFrame", { static: false }) iframeRef: ElementRef;
- @Output() onNewView: EventEmitter = new EventEmitter();
-
- constructor(
- private _http: HttpService,
- private _i18n: I18nService,
- private _logger: LogService,
- private route: ActivatedRoute
- ) {
- this.checkPageVisibility();
- this.startTime = new Date();
- }
-
- public isActive: boolean = true;
- public iframeWindow: Window;
-
- public userId: string = "";
- public username: string = "";
- public assetId: string = "";
- public assetName: string = "";
-
- public connectType: string = "SSH";
- public totalConnectTime: string;
-
- iframeURL: string;
-
- private pausedElapsedTime: number = 0;
- private isTimerPaused: boolean = false;
-
- private startTime: Date;
- private timerInterval: any;
-
- async ngOnInit(): Promise {
- this.route.params.subscribe(async (params) => {
- this.userId = params["userId"];
- this.username = params["username"];
- this.assetId = params["assetId"];
- this.assetName = params["assetName"];
-
- this._http
- .getAssetDetail(this.assetId)
- .subscribe(async (asset: Asset) => {
- const currentUserInfo = asset.permed_accounts.find(
- (item: Account) => item.id === this.userId
- );
-
- let method: string = "";
- let protocol: Protocol = asset.permed_protocols[0];
-
- switch (protocol.name) {
- case "ssh":
- case "telnet":
- method = "ssh_client";
- break;
- case "rdp":
- method = "mstsc";
- break;
- case "sftp":
- method = "sftp_client";
- break;
- case "vnc":
- method = "vnc_client";
- break;
- default:
- method = "db_client";
- }
-
- const assetMessage = {
- id: this.assetId,
- name: this.assetName,
- address: asset.address,
- comment: asset.comment,
- type: asset.type,
- category: asset.category,
- permed_protocols: asset.permed_protocols,
- permed_accounts: asset.permed_accounts,
- spec_info: asset.spec_info,
- };
- const connectData = {
- method,
- protocol,
- asset: assetMessage,
- account: currentUserInfo,
- input_username: this.username,
- };
-
- this._http
- .adminConnectToken(assetMessage, connectData)
- .subscribe((res) => {
- if (res) {
- const url = this.getUrl();
-
- this.iframeURL = `${url}/koko/connect?token=${res.id}`;
- }
- });
- });
- });
-
- this.startTimer();
-
- document.addEventListener("visibilitychange", () => {
- if (document.hidden) {
- this.isActive = false;
- this.stopTimer();
- const currentTime = new Date().getTime();
- this.pausedElapsedTime += currentTime - this.startTime.getTime();
- } else {
- setTimeout(() => {
- this.isActive = true;
- this.startTime = new Date();
- this.startTimer();
- }, 0);
- }
- });
- }
-
- public handleCloseConnect() {
- window.confirm("确定要关闭当前连接吗?");
-
- window.close();
- }
-
- public closeDrawer() {
- this.sidenav.close();
- }
-
- public handleOpenFileManage() {
- const iframeWindow = (this.iframeRef as unknown as { iframeWindow: Window })
- .iframeWindow;
-
- if (iframeWindow) {
- iframeWindow.postMessage({ name: "FILE" }, "*");
- this._logger.info(`[Luna] Send FILE`);
- }
- }
-
- private getUrl(): string {
- let host: string = "";
-
- const endpoint = window.location.host.split(":")[0];
- const protocole = window.location.protocol;
- const port = "9530";
-
- if (port) {
- host = `${endpoint}:${port}`;
- }
-
- this._logger.info(`Current host: ${protocole}//${host}`);
-
- return `${protocole}//${host}`;
- }
-
- private checkPageVisibility() {
- this.isActive = !document.hidden;
- }
-
- private padZero(value: number): string {
- return String(value).padStart(2, "0");
- }
-
- private updateConnectTime(): void {
- const currentTime = new Date();
- const elapsed =
- currentTime.getTime() - this.startTime.getTime() + this.pausedElapsedTime;
-
- const hours = Math.floor((elapsed / (1000 * 60 * 60)) % 24);
- const minutes = Math.floor((elapsed / (1000 * 60)) % 60);
- const seconds = Math.floor((elapsed / 1000) % 60);
-
- this.totalConnectTime = `${this.padZero(hours)}:${this.padZero(
- minutes
- )}:${this.padZero(seconds)}`;
- }
-
- private startTimer(): void {
- this.timerInterval = setInterval(() => this.updateConnectTime(), 1000);
- }
-
- private stopTimer(): void {
- clearInterval(this.timerInterval);
- this.isTimerPaused = true;
- }
-
- ngOnDestroy(): void {
- if (this.timerInterval) {
- clearInterval(this.timerInterval);
- }
- }
-}
diff --git a/src/app/router.module.ts b/src/app/router.module.ts
index 4d57c8da..92702727 100644
--- a/src/app/router.module.ts
+++ b/src/app/router.module.ts
@@ -7,8 +7,7 @@ import { PagesReplayComponent } from "./pages/replay/replay.component";
import { PagesMonitorComponent } from "./pages/monitor/monitor.component";
import { PageMainComponent } from "./pages/main/main.component";
import { PageSftpComponent } from "./pages/sftp/sftp.component";
-import { PagePamGUIComponent } from "./pages/pam/gui.component/gui.component";
-import { PagePamTerminalComponent } from "./pages/pam/terminal.component/terminal.component";
+import { PagePamComponent } from "./pages/pam/pam.component";
const appRoutes: Routes = [
{ path: "replay/:sid", component: PagesReplayComponent },
@@ -17,8 +16,7 @@ const appRoutes: Routes = [
{ path: "sftp", component: PageSftpComponent },
{ path: "undefined", component: PagesBlankComponent },
{ path: "", component: PageMainComponent },
- { path: "pam_terminal_connect/:userId/:username/:assetId/:assetName", component: PagePamTerminalComponent },
- { path: "pam_gui_connect/:userId/:username/:assetId/:assetName", component: PagePamGUIComponent },
+ { path: "pam_connect/:userId/:username/:assetId/:assetName/:protocol", component: PagePamComponent },
// { path: '**', component: PagesNotFoundComponent }
];
diff --git a/src/app/services/http.ts b/src/app/services/http.ts
index b84b6ff6..9b726025 100644
--- a/src/app/services/http.ts
+++ b/src/app/services/http.ts
@@ -289,7 +289,7 @@ export class HttpService {
const data = {
asset: asset.id,
account: account.alias,
- protocol: protocol.name,
+ protocol: protocol,
input_username: connectData.input_username,
connect_method: connectData.method,
};