From 1abc47bb56cb0a6eec82c205eceb5bc83d00c715 Mon Sep 17 00:00:00 2001 From: lijiahangmax Date: Mon, 7 Jul 2025 14:47:18 +0800 Subject: [PATCH] =?UTF-8?q?:hammer:=20=E6=B7=BB=E5=8A=A0=20vnc=20=E4=BC=9A?= =?UTF-8?q?=E8=AF=9D.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../assets/style/host-terminal-layout.less | 186 ++++++++++++- .../src/store/modules/terminal/index.ts | 12 +- .../src/store/modules/terminal/types.ts | 28 ++ .../components/layout/empty-recommend.vue | 54 +--- .../new-connection/host-list-modal.vue | 56 ++-- .../new-connection/host-list-view.vue | 59 ++-- .../new-connection/new-connection-view.vue | 4 +- .../rdp-status.vue => guacd/guacd-status.vue} | 10 +- .../components/view/rdp/rdp-action-bar.vue | 262 ++++-------------- .../terminal/components/view/rdp/rdp-view.vue | 75 +---- .../components/view/sftp/sftp-view.vue | 18 +- .../terminal/components/view/ssh/ssh-view.vue | 8 +- .../src/views/terminal/interfaces/handler.ts | 8 +- .../src/views/terminal/interfaces/session.ts | 42 +-- .../terminal/service/session/base-session.ts | 7 +- .../terminal/types/use-guacd-action-bar.ts | 84 ++++++ 16 files changed, 466 insertions(+), 447 deletions(-) rename orion-visor-ui/src/views/terminal/components/view/{rdp/rdp-status.vue => guacd/guacd-status.vue} (93%) create mode 100644 orion-visor-ui/src/views/terminal/types/use-guacd-action-bar.ts diff --git a/orion-visor-ui/src/assets/style/host-terminal-layout.less b/orion-visor-ui/src/assets/style/host-terminal-layout.less index 090d5bf3..926c7f37 100644 --- a/orion-visor-ui/src/assets/style/host-terminal-layout.less +++ b/orion-visor-ui/src/assets/style/host-terminal-layout.less @@ -619,5 +619,189 @@ body[terminal-theme='dark'] .arco-modal-container { font-size: 16px; margin: 0 8px 0 4px; } - +} + +// guacd 容器 +.guacd-container { + + // guacd 视口 + .guacd-viewport { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + + :deep(> div) { + position: relative; + z-index: 8; + } + } + + // guacd 状态遮罩 + .guacd-status-mask { + width: 100%; + height: 100%; + position: absolute; + backdrop-filter: blur(10px); + display: flex; + align-items: center; + justify-content: center; + z-index: 9999; + } + + // guacd 工具栏 + .guacd-action-bar { + position: absolute; + cursor: pointer; + z-index: 9998; + + &.top { + top: 4px; + left: 50%; + transform: translateX(-50%); + } + + &.right { + right: 4px; + top: 50%; + transform: translateY(-50%); + } + + // 工具栏触发器 + .action-bar-trigger { + display: flex; + border-radius: 8px; + transition: .3s all; + background: var(--color-bg-rdp-toolbar); + filter: contrast(50%) brightness(50%); + + &.top { + width: 240px; + height: 8px; + + &:hover { + transform: translateY(2px); + } + } + + &.right { + width: 8px; + height: 228px; + + &:hover { + transform: translateX(-2px); + } + } + + &:hover { + background: var(--color-bg-rdp-toolbar-hover); + } + } + + } +} + +// guacd 工具栏 +@guacd-action-size: 42px; + +.guacd-action-bar-popover { + --actions-width: calc(var(--action-count) * @guacd-action-size + (var(--action-count) - 1) * 16px); + background: var(--color-bg-2); + + .arco-popover-content { + margin-top: 0; + display: flex; + } + + .action-bar-button { + width: @guacd-action-size !important; + height: @guacd-action-size !important; + font-size: 20px; + } + + .action-bar-content { + display: flex; + flex-direction: column; + } + + .action-bar-content-footer { + margin-top: 12px; + display: flex; + justify-content: flex-end; + } + + .display-size-label { + padding-right: 6px; + user-select: none; + text-align: end; + } + + .display-size-input { + width: 198px; + } + + .action-bar-upload, .action-bar-clipboard { + display: flex; + } + + .combination-key-item { + span { + display: block; + padding: 6px 12px; + cursor: pointer; + background: var(--color-fill-1); + border-radius: 2px; + user-select: none; + transition: 0.2s ALL; + + &:hover { + background: var(--color-fill-2); + } + } + } +} + +.guacd-action-bar-popover.top { + .arco-popover-content { + flex-direction: column; + width: var(--actions-width); + } + + .action-bar-content { + margin-top: 16px; + max-height: 224px; + overflow-x: hidden; + overflow-y: auto; + + &::-webkit-scrollbar { + display: none; + } + } + + .action-bar-upload, .action-bar-clipboard { + height: 186px; + } +} + +.guacd-action-bar-popover.right { + .arco-popover-content { + flex-direction: row-reverse; + height: var(--actions-width); + } + + .action-bar-content { + margin-right: 16px; + width: 344px; + overflow-x: hidden; + overflow-y: auto; + + &::-webkit-scrollbar { + display: none; + } + } + + .action-bar-upload, .action-bar-clipboard { + height: calc(var(--actions-width) - 40px); + } } diff --git a/orion-visor-ui/src/store/modules/terminal/index.ts b/orion-visor-ui/src/store/modules/terminal/index.ts index a7faab8b..2d142b16 100644 --- a/orion-visor-ui/src/store/modules/terminal/index.ts +++ b/orion-visor-ui/src/store/modules/terminal/index.ts @@ -8,7 +8,9 @@ import type { TerminalSshDisplaySetting, TerminalSshInteractSetting, TerminalSshPluginsSetting, - TerminalState + TerminalState, + TerminalVncActionBarSetting, + TerminalVncGraphSetting } from './types'; import type { IDomViewportHandler, @@ -56,8 +58,12 @@ export const TerminalPreferenceItem = { RDP_GRAPH_SETTING: 'rdpGraphSetting', // rdp 操作栏设置 RDP_ACTION_BAR_SETTING: 'rdpActionBarSetting', - // 会话设置 + // rdp 会话设置 RDP_SESSION_SETTING: 'rdpSessionSetting', + // vnc 图形化设置 + VNC_GRAPH_SETTING: 'vncGraphSetting', + // vnc 工具栏设置 + VNC_ACTION_BAR_SETTING: 'vncActionBarSetting', // 快捷键设置 SHORTCUT_SETTING: 'shortcutSetting', }; @@ -77,6 +83,8 @@ export default defineStore('terminal', { rdpGraphSetting: {} as TerminalRdpGraphSetting, rdpSessionSetting: {} as TerminalRdpSessionSetting, rdpActionBarSetting: {} as TerminalRdpActionBarSetting, + vncGraphSetting: {} as TerminalVncGraphSetting, + vncActionBarSetting: {} as TerminalVncActionBarSetting, shortcutSetting: { enabled: false, keys: [] diff --git a/orion-visor-ui/src/store/modules/terminal/types.ts b/orion-visor-ui/src/store/modules/terminal/types.ts index cb067a25..7bd40f11 100644 --- a/orion-visor-ui/src/store/modules/terminal/types.ts +++ b/orion-visor-ui/src/store/modules/terminal/types.ts @@ -23,6 +23,8 @@ export interface TerminalPreference { rdpGraphSetting: TerminalRdpGraphSetting; rdpActionBarSetting: TerminalRdpActionBarSetting; rdpSessionSetting: TerminalRdpSessionSetting; + vncGraphSetting: TerminalVncGraphSetting; + vncActionBarSetting: TerminalVncActionBarSetting; shortcutSetting: TerminalShortcutSetting; } @@ -68,6 +70,7 @@ export interface TerminalSshInteractSetting { wordSeparator: string; terminalEmulationType: string; scrollBackLine: number; + replaceBackspace: boolean; } // RDP 图形化设置 @@ -111,6 +114,31 @@ export interface TerminalRdpSessionSetting { driveMountMode?: string; } +// VNC 图形化设置 +export interface TerminalVncGraphSetting { + displaySize?: string; + displayWidth?: number; + displayHeight?: number; + colorDepth?: number; + forceLossless?: boolean; + swapRedBlue?: boolean; + cursor?: string; + compressLevel?: number; + qualityLevel?: number; +} + +// VNC 操作栏设置 +export interface TerminalVncActionBarSetting { + position?: string; + display?: boolean; + combinationKey?: boolean; + clipboard?: boolean; + disconnect?: boolean; + close?: boolean; + + [key: string]: unknown; +} + // 终端快捷键设置 export interface TerminalShortcutSetting { enabled: boolean; diff --git a/orion-visor-ui/src/views/terminal/components/layout/empty-recommend.vue b/orion-visor-ui/src/views/terminal/components/layout/empty-recommend.vue index 796b0a06..159e9b47 100644 --- a/orion-visor-ui/src/views/terminal/components/layout/empty-recommend.vue +++ b/orion-visor-ui/src/views/terminal/components/layout/empty-recommend.vue @@ -31,45 +31,21 @@ - - - - - - - - - - - - - - - - - - + + diff --git a/orion-visor-ui/src/views/terminal/components/new-connection/host-list-modal.vue b/orion-visor-ui/src/views/terminal/components/new-connection/host-list-modal.vue index 14c3746a..33fb7b47 100644 --- a/orion-visor-ui/src/views/terminal/components/new-connection/host-list-modal.vue +++ b/orion-visor-ui/src/views/terminal/components/new-connection/host-list-modal.vue @@ -40,45 +40,21 @@
- - - - - - - - - - - - - - - - - - + +
@@ -144,7 +120,7 @@ defineExpose({ open }); // 打开终端 - const clickHost = (item: HostQueryResponse, tab: TerminalSessionType) => { + const openHostSession = (item: HostQueryResponse, tab: TerminalSessionType) => { openSession(item, tab, panelIndex.value); setVisible(false); }; diff --git a/orion-visor-ui/src/views/terminal/components/new-connection/host-list-view.vue b/orion-visor-ui/src/views/terminal/components/new-connection/host-list-view.vue index 29144cec..ca67b2e6 100644 --- a/orion-visor-ui/src/views/terminal/components/new-connection/host-list-view.vue +++ b/orion-visor-ui/src/views/terminal/components/new-connection/host-list-view.vue @@ -111,48 +111,23 @@
- - -
- - - -
-
- - -
- - - -
-
- - -
- - - -
-
+ + import type { SelectOptionData } from '@arco-design/web-vue'; - import { onBeforeMount, ref } from 'vue'; + import { ref, onMounted } from 'vue'; import { NewConnectionType, newConnectionTypeKey } from '../../types/const'; import { useDictStore, useTerminalStore } from '@/store'; import { TerminalPreferenceItem } from '@/store/modules/terminal'; @@ -86,7 +86,7 @@ const filterOptions = ref>([]); // 初始化过滤器项 - onBeforeMount(() => { + onMounted(() => { filterOptions.value = getAuthorizedHostOptions(hosts.hostList); }); diff --git a/orion-visor-ui/src/views/terminal/components/view/rdp/rdp-status.vue b/orion-visor-ui/src/views/terminal/components/view/guacd/guacd-status.vue similarity index 93% rename from orion-visor-ui/src/views/terminal/components/view/rdp/rdp-status.vue rename to orion-visor-ui/src/views/terminal/components/view/guacd/guacd-status.vue index b6be3f58..7e0f8343 100644 --- a/orion-visor-ui/src/views/terminal/components/view/rdp/rdp-status.vue +++ b/orion-visor-ui/src/views/terminal/components/view/guacd/guacd-status.vue @@ -6,7 +6,7 @@ dot /> export default { - name: 'rdpStatus' + name: 'guacdStatus' }; - - diff --git a/orion-visor-ui/src/views/terminal/components/view/rdp/rdp-view.vue b/orion-visor-ui/src/views/terminal/components/view/rdp/rdp-view.vue index c2d01382..1d529fff 100644 --- a/orion-visor-ui/src/views/terminal/components/view/rdp/rdp-view.vue +++ b/orion-visor-ui/src/views/terminal/components/view/rdp/rdp-view.vue @@ -1,17 +1,17 @@ @@ -25,8 +25,9 @@ import type { TerminalSessionTabItem, IRdpSession } from '@/views/terminal/interfaces'; import { onMounted, ref, onUnmounted } from 'vue'; import { useTerminalStore } from '@/store'; - import RdpStatus from './rdp-status.vue'; + import { ActionBarPosition } from '@/views/terminal/types/const'; import RdpActionBar from './rdp-action-bar.vue'; + import GuacdStatus from '../guacd/guacd-status.vue'; const props = defineProps<{ item: TerminalSessionTabItem; @@ -34,7 +35,7 @@ const { preference, sessionManager } = useTerminalStore(); - const toolbarDirection = ref('top'); + const actionBarDirection = ref(ActionBarPosition.TOP); const viewport = ref(); const session = ref(); @@ -42,7 +43,7 @@ // 初始化会话 onMounted(async () => { // 工具栏方向 - toolbarDirection.value = preference.rdpActionBarSetting.position || 'top'; + actionBarDirection.value = preference.rdpActionBarSetting.position || ActionBarPosition.TOP; // 创建终端会话 session.value = sessionManager.createSession(props.item); // 打开终端会话 @@ -60,53 +61,5 @@ - diff --git a/orion-visor-ui/src/views/terminal/components/view/sftp/sftp-view.vue b/orion-visor-ui/src/views/terminal/components/view/sftp/sftp-view.vue index 6d4f51c5..05c5c067 100644 --- a/orion-visor-ui/src/views/terminal/components/view/sftp/sftp-view.vue +++ b/orion-visor-ui/src/views/terminal/components/view/sftp/sftp-view.vue @@ -1,5 +1,5 @@