From e4ab98dc017b18bd3493ed5e8ee94e626e6c3a33 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E2=80=9Chuailei000=E2=80=9D?= <2280131253@qq.com>
Date: Tue, 26 Dec 2023 17:53:55 +0800
Subject: [PATCH] =?UTF-8?q?perf:=20=E5=A2=9E=E5=8A=A0=E6=99=BA=E8=83=BD?=
=?UTF-8?q?=E9=97=AE=E7=AD=94?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
proxy.conf.json | 5 +
src/app/elements/chat/chat.component.html | 27 +++++
src/app/elements/chat/chat.component.scss | 107 ++++++++++++++++++++
src/app/elements/chat/chat.component.ts | 116 ++++++++++++++++++++++
src/app/elements/elements.component.ts | 3 +-
src/app/model.ts | 1 +
src/app/pages/main/main.component.html | 2 +
src/app/pages/main/main.component.ts | 4 +
src/app/services/view.ts | 10 ++
src/assets/i18n/en.json | 1 +
src/assets/i18n/ja.json | 1 +
src/assets/i18n/zh.json | 1 +
src/assets/icons/robot-assistant.png | Bin 0 -> 4024 bytes
13 files changed, 277 insertions(+), 1 deletion(-)
create mode 100644 src/app/elements/chat/chat.component.html
create mode 100644 src/app/elements/chat/chat.component.scss
create mode 100644 src/app/elements/chat/chat.component.ts
create mode 100644 src/assets/icons/robot-assistant.png
diff --git a/proxy.conf.json b/proxy.conf.json
index f4cb5046..f53d9620 100644
--- a/proxy.conf.json
+++ b/proxy.conf.json
@@ -56,5 +56,10 @@
"secure": false,
"ws": true,
"changeOrigin": true
+ },
+ "/ui/": {
+ "target": "http://localhost:9528",
+ "secure": false,
+ "changeOrigin": true
}
}
diff --git a/src/app/elements/chat/chat.component.html b/src/app/elements/chat/chat.component.html
new file mode 100644
index 00000000..f058956a
--- /dev/null
+++ b/src/app/elements/chat/chat.component.html
@@ -0,0 +1,27 @@
+
\ No newline at end of file
diff --git a/src/app/elements/chat/chat.component.scss b/src/app/elements/chat/chat.component.scss
new file mode 100644
index 00000000..4a5db55f
--- /dev/null
+++ b/src/app/elements/chat/chat.component.scss
@@ -0,0 +1,107 @@
+.chat-container {
+ overflow: hidden;
+ .content {
+ height: 100%;
+ iframe {
+ border: none;
+ }
+ }
+}
+
+.drawer-panel {
+ position: fixed;
+ top: 0;
+ right: 0;
+ width: 100%;
+ width: 440px;
+ min-width: 260px;
+ height: 100vh;
+ user-select: none;
+ border-radius: 10px 0 0 10px;
+ transition: transform .25s cubic-bezier(.7, .3, .1, 1);
+ box-shadow: 0 0 8px 4px #00000014;
+ transform: translate(100%);
+ background: #FFFFFF;
+ z-index: 1200;
+}
+
+#dragBox {
+ position: absolute;
+ top: 30%;
+ left: -48px;
+}
+
+.drag-button {
+ // position: absolute;
+ // top: 30%;
+ // left: -48px;
+ width: 48px;
+ height: 45px;
+ line-height: 45px;
+ box-sizing: border-box;
+ text-align: center;
+ font-size: 24px;
+ border-radius: 20px 0 0 20px;
+ z-index: 0;
+ pointer-events: auto;
+ color: #fff;
+ background-color: #FFFFFF;
+ box-shadow: 0 0 8px 4px #00000014;
+ cursor: pointer;
+
+ &:hover {
+ left: -50px !important;
+ width: 50px !important;
+ transform: translateZ(0) scale(1.06);
+ transform-style: preserve-3d;
+ backface-visibility: hidden;
+ }
+ i {
+ font-size: 20px;
+ line-height: 45px;
+ }
+ img {
+ width: 22px;
+ height: 22px;
+ transform: translateY(10%);
+ margin-left: 3px;
+ }
+}
+
+.drag-setting {
+ width: 36px;
+ height: 36px;
+ line-height: 38px;
+ margin-bottom: 10px;
+ text-align: center;
+ border-radius: 50%;
+ cursor: pointer;
+ transform: translateX(20%);
+ background-color: #FFFFFF;
+ border: 1px solid transparent;
+ transition: border-color 0.3s ease;
+ &:hover {
+ background-color: #f0f1f5;
+ border-color: #1d271f;
+ }
+ i {
+ font-size: 18px;
+ }
+}
+
+.show {
+ transition: all .3s cubic-bezier(.7, .3, .1, 1);
+}
+
+.show .modal {
+ position: fixed;
+ top: 0;
+ width: 100%;
+ height: 100%;
+ z-index: 999;
+ opacity: 1;
+}
+
+.show .drawer-panel {
+ transform: translate(0);
+}
\ No newline at end of file
diff --git a/src/app/elements/chat/chat.component.ts b/src/app/elements/chat/chat.component.ts
new file mode 100644
index 00000000..a81ab3b3
--- /dev/null
+++ b/src/app/elements/chat/chat.component.ts
@@ -0,0 +1,116 @@
+import {OnInit, OnDestroy, Component} from '@angular/core';
+import {ViewService} from '@app/services';
+import {View} from '@app/model';
+
+@Component({
+ selector: 'elements-chat',
+ templateUrl: './chat.component.html',
+ styleUrls: ['./chat.component.scss'],
+})
+
+export class ElementChatComponent implements OnInit, OnDestroy {
+ isShow = true;
+ element: any;
+ iframeURL: String;
+ currentView: View;
+
+ constructor(
+ public viewSrv: ViewService
+ ) {}
+
+ get isShowSetting() {
+ const componentType = ['koko', 'lion'];
+ return (
+ this.currentView.hasOwnProperty('connectMethod')
+ && componentType.includes(this.currentView.connectMethod.component)
+ );
+ }
+
+ ngOnInit() {
+ this.viewSrv.currentView$.subscribe((state: View) => {
+ this.currentView = state;
+ });
+ this.iframeURL = '/ui/#/chat/chat-ai';
+ this.init();
+ this.insertToBody();
+ }
+
+ ngOnDestroy() {
+ this.element.remove();
+ this.viewSrv.currentView$.unsubscribe();
+ }
+
+ init() {
+ const clientOffset: any = {};
+ const dragBox = document.getElementById('dragBox');
+ const dragSetting = document.querySelector('.drag-setting');
+ dragBox.addEventListener('mousedown', (event) => {
+ event.stopPropagation();
+ const offsetX = dragBox.getBoundingClientRect().left;
+ const offsetY = dragBox.getBoundingClientRect().top;
+ const innerX = event.clientX - offsetX;
+ const innerY = event.clientY - offsetY;
+
+ clientOffset.clientX = event.clientX;
+ clientOffset.clientY = event.clientY;
+ document.onmousemove = function(ev: any) {
+ dragBox.style.left = ev.clientX - innerX + 'px';
+ dragBox.style.top = ev.clientY - innerY + 'px';
+ const dragDivTop = window.innerHeight - dragBox.getBoundingClientRect().height;
+ const dragDivLeft = window.innerWidth - dragBox.getBoundingClientRect().width;
+ dragBox.style.left = dragDivLeft + 'px';
+ dragBox.style.left = '-48px';
+ if (dragBox.getBoundingClientRect().top <= 0) {
+ dragBox.style.top = '0px';
+ }
+ if (dragBox.getBoundingClientRect().top >= dragDivTop) {
+ dragBox.style.top = dragDivTop + 'px';
+ }
+ ev.preventDefault();
+ ev.stopPropagation();
+ };
+ document.onmouseup = function() {
+ document.onmousemove = null;
+ document.onmouseup = null;
+ };
+ }, false);
+ dragBox.addEventListener('mouseup', (event) => {
+ const clientX = event.clientX;
+ const clientY = event.clientY;
+ if (
+ this.isDifferenceWithinThreshold(clientX, clientOffset.clientX)
+ && this.isDifferenceWithinThreshold(clientY, clientOffset.clientY)
+ && event.target !== dragSetting
+ && this.isDescendant(event.target, dragSetting)
+ ) {
+ this.isShow = !this.isShow;
+ }
+ });
+ }
+
+ isDescendant(element, ancestor) {
+ if (element.parentNode === ancestor) {
+ return false;
+ }
+ return true;
+ }
+
+ insertToBody() {
+ this.element = document.getElementById('chatContainer');
+ const body = document.querySelector('body');
+ body.insertBefore(this.element, body.firstChild);
+ }
+
+ onOpenDrawer() {
+ window.postMessage({name: 'OPEN'}, '*');
+ }
+
+ isDifferenceWithinThreshold(num1, num2, threshold = 5) {
+ const difference = Math.abs(num1 - num2);
+ return difference <= threshold;
+ }
+
+ toggle() {
+ this.isShow = !this.isShow;
+ }
+}
diff --git a/src/app/elements/elements.component.ts b/src/app/elements/elements.component.ts
index 387b95ca..77baaaa1 100644
--- a/src/app/elements/elements.component.ts
+++ b/src/app/elements/elements.component.ts
@@ -30,7 +30,7 @@ import {ElementsReplayMp4Component} from './replay/mp4/mp4.component';
import {ElementConnectorGuideComponent} from '@app/elements/content/content-window/guide/guide.component';
import {ElementCommandDialogComponent} from '@app/elements/content/command-dialog/command-dialog.component';
import {ElementSendCommandDialogComponent} from '@app/elements/content/send-command-dialog/send-command-dialog.component';
-
+import {ElementChatComponent} from '@app/elements/chat/chat.component';
export const ElementComponents = [
ElementLeftBarComponent,
@@ -43,6 +43,7 @@ export const ElementComponents = [
ElementUserFileComponent,
ElementTermComponent,
ElementNavComponent,
+ ElementChatComponent,
ElementIframeComponent,
ElementDialogAlertComponent,
ElementAssetTreeComponent,
diff --git a/src/app/model.ts b/src/app/model.ts
index 2f970d36..f4695087 100644
--- a/src/app/model.ts
+++ b/src/app/model.ts
@@ -271,6 +271,7 @@ export class GlobalSetting {
INTERFACE: any;
TERMINAL_GRAPHICAL_RESOLUTION: string;
CONNECTION_TOKEN_REUSABLE: boolean;
+ CHAT_AI_ENABLED: boolean;
}
export class Setting {
diff --git a/src/app/pages/main/main.component.html b/src/app/pages/main/main.component.html
index dd9797b1..b3e4f39e 100644
--- a/src/app/pages/main/main.component.html
+++ b/src/app/pages/main/main.component.html
@@ -57,3 +57,5 @@
+
+
diff --git a/src/app/pages/main/main.component.ts b/src/app/pages/main/main.component.ts
index 4b3d1d9c..6fb446f7 100644
--- a/src/app/pages/main/main.component.ts
+++ b/src/app/pages/main/main.component.ts
@@ -35,6 +35,10 @@ export class PageMainComponent implements OnInit {
return this._isMobile;
}
+ get chatAiEnabled() {
+ return this._settingSvc.globalSetting.CHAT_AI_ENABLED;
+ }
+
set isMobile(value) {
this._isMobile = value;
let settings: any = {};
diff --git a/src/app/services/view.ts b/src/app/services/view.ts
index fe2e8bac..e4909e32 100644
--- a/src/app/services/view.ts
+++ b/src/app/services/view.ts
@@ -1,5 +1,6 @@
import {Injectable} from '@angular/core';
import {View} from '@app/model';
+import {BehaviorSubject} from 'rxjs';
@Injectable()
export class ViewService {
@@ -7,6 +8,7 @@ export class ViewService {
currentView: View;
num = 0;
viewIds: Array = [];
+ public currentView$ = new BehaviorSubject<{}>({});
addView(view: View) {
this.num += 1;
@@ -35,6 +37,7 @@ export class ViewService {
}
}, 100);
this.currentView = view;
+ this.setCurrentView();
}
removeView(view: View) {
@@ -48,12 +51,14 @@ export class ViewService {
this.currentView.subViews.push(view);
const index = this.currentView.subViews.length;
this.setCurrentViewTitle(view, index + 1, 'concat');
+ this.setCurrentView();
}
clearSubViewOfCurrentView(view: View) {
const index = this.currentView.subViews.indexOf(view);
this.currentView.subViews.splice(index, 1);
this.setCurrentViewTitle(view, index + 1, 'delete');
+ this.setCurrentView();
}
setCurrentViewTitle(view, index, status) {
@@ -70,6 +75,7 @@ export class ViewService {
this.currentView.name = names.join('|');
break;
}
+ this.setCurrentView();
}
keyboardSwitchTab(key) {
@@ -97,4 +103,8 @@ export class ViewService {
this.activeView(nextActiveView);
}
}
+
+ setCurrentView() {
+ this.currentView$.next(this.currentView);
+ }
}
diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json
index a31c9b2c..9e2ed3ee 100644
--- a/src/assets/i18n/en.json
+++ b/src/assets/i18n/en.json
@@ -141,6 +141,7 @@
"Run it by client": "Run it by client",
"Name": "Name",
"Tips": "Tips",
+ "Question answer": "Question answer",
"Asset not found or You have no permission to access it, please refresh asset tree": "Asset not found or You have no permission to access it, please refresh asset tree",
"With secret accounts": "With secret accounts",
"Close": "Close",
diff --git a/src/assets/i18n/ja.json b/src/assets/i18n/ja.json
index 3308134e..1632da88 100644
--- a/src/assets/i18n/ja.json
+++ b/src/assets/i18n/ja.json
@@ -145,6 +145,7 @@
"General": "基本構成",
"GUI": "グラフィカル",
"CLI": "コマンドライン",
+ "Question answer": "質問-答え",
"Asset not found or You have no permission to access it, please refresh asset tree": "アセットが見つからないか、アクセスする権限がありません。アセット ツリーを更新してください",
"Run it by client": "クライアントで実行する",
"Name": "めいしょう",
diff --git a/src/assets/i18n/zh.json b/src/assets/i18n/zh.json
index 6b64e3b7..bacd53db 100644
--- a/src/assets/i18n/zh.json
+++ b/src/assets/i18n/zh.json
@@ -149,6 +149,7 @@
"Applet": "远程应用",
"GUI": "图形化",
"Tips": "提示",
+ "Question answer": "智能问答",
"Asset not found or You have no permission to access it, please refresh asset tree": "未找到资产或您无权访问它,请刷新资产树",
"CLI": "命令行",
"Close": "关闭",
diff --git a/src/assets/icons/robot-assistant.png b/src/assets/icons/robot-assistant.png
new file mode 100644
index 0000000000000000000000000000000000000000..4a3bd44cf1dd622291868c322debed6248dd035a
GIT binary patch
literal 4024
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
eV1a!xkLT0000