diff --git a/orion-ops-ui/src/store/modules/terminal/index.ts b/orion-ops-ui/src/store/modules/terminal/index.ts index 42adea66..c13f921d 100644 --- a/orion-ops-ui/src/store/modules/terminal/index.ts +++ b/orion-ops-ui/src/store/modules/terminal/index.ts @@ -143,6 +143,15 @@ export default defineStore('terminal', { }); }, + // 复制并且打开终端 + openCopyTerminal(hostId: number) { + const host = this.hosts.hostList + .find(s => s.id === hostId); + if (host) { + this.openTerminal(host); + } + } + }, }); diff --git a/orion-ops-ui/src/store/modules/terminal/types.ts b/orion-ops-ui/src/store/modules/terminal/types.ts index 1ac82dfb..8a1d9464 100644 --- a/orion-ops-ui/src/store/modules/terminal/types.ts +++ b/orion-ops-ui/src/store/modules/terminal/types.ts @@ -80,5 +80,5 @@ export interface TerminalShortcutKey { ctrlKey: boolean; shiftKey: boolean; altKey: boolean; - key: string; + code: string; } diff --git a/orion-ops-ui/src/views/host/terminal/handler/terminal-session-handler.ts b/orion-ops-ui/src/views/host/terminal/handler/terminal-session-handler.ts index fab3649e..5864f9b1 100644 --- a/orion-ops-ui/src/views/host/terminal/handler/terminal-session-handler.ts +++ b/orion-ops-ui/src/views/host/terminal/handler/terminal-session-handler.ts @@ -1,8 +1,9 @@ import type { TerminalInteractSetting, TerminalShortcutKey } from '@/store/modules/terminal/types'; import type { ITerminalSession, ITerminalSessionHandler, ITerminalTabManager, TerminalDomRef } from '../types/terminal.type'; import type { Terminal } from 'xterm'; -import { useTerminalStore } from '@/store'; import useCopy from '@/hooks/copy'; +import { useTerminalStore } from '@/store'; +import { InnerTabs } from '../types/terminal.const'; const { copy: copyValue, readText } = useCopy(); @@ -35,62 +36,86 @@ export default class TerminalSessionHandler implements ITerminalSessionHandler { ctrlKey: true, shiftKey: true, altKey: false, - key: 'C' + code: 'KeyC' }, { option: 'paste', ctrlKey: true, shiftKey: true, altKey: false, - key: 'V' + code: 'KeyV' }, { option: 'toTop', ctrlKey: true, shiftKey: true, altKey: false, - key: 'ArrowUp' + code: 'ArrowUp' }, { option: 'toBottom', ctrlKey: true, shiftKey: true, altKey: false, - key: 'ArrowDown' + code: 'ArrowDown' }, { option: 'selectAll', ctrlKey: true, shiftKey: true, altKey: false, - key: 'A' + code: 'KeyA' }, { option: 'search', ctrlKey: true, shiftKey: true, altKey: false, - key: 'F' + code: 'KeyF' }, { option: 'fontSizePlus', ctrlKey: true, - shiftKey: true, - altKey: false, - key: '+' + shiftKey: false, + altKey: true, + code: 'Equal' }, { option: 'fontSizeSubtract', ctrlKey: true, - shiftKey: true, - altKey: false, - key: '_' + shiftKey: false, + altKey: true, + code: 'Minus' }, { option: 'commandEditor', ctrlKey: true, - shiftKey: true, - altKey: false, - key: 'O' + shiftKey: false, + altKey: true, + code: 'KeyE' }, { option: 'close', ctrlKey: true, - shiftKey: true, - altKey: false, - key: 'W' - } + shiftKey: false, + altKey: true, + code: 'KeyW' + }, { + option: 'changeToPrev', + ctrlKey: true, + shiftKey: false, + altKey: true, + code: 'ArrowLeft' + }, { + option: 'changeToNext', + ctrlKey: true, + shiftKey: false, + altKey: true, + code: 'ArrowRight' + }, { + option: 'openCopyTerminal', + ctrlKey: true, + shiftKey: false, + altKey: true, + code: 'KeyO' + }, { + option: 'openNewConnect', + ctrlKey: true, + shiftKey: false, + altKey: true, + code: 'KeyN' + }, ]; this.tabManager = tabManager; } @@ -126,7 +151,7 @@ export default class TerminalSessionHandler implements ITerminalSessionHandler { triggerShortcutKey(e: KeyboardEvent): boolean { // 检测触发的快捷键 const key = this.shortcutKeys.find(key => { - return key.key === e.key + return key.code === e.code && key.altKey === e.altKey && key.shiftKey === e.shiftKey && key.ctrlKey === e.ctrlKey; @@ -240,13 +265,29 @@ export default class TerminalSessionHandler implements ITerminalSessionHandler { this.session.disconnect(); } - // 关闭 - close() { + // 关闭 tab + closeTab() { this.tabManager.deleteTab(this.session.sessionId); } - // todo - // 切换 tab - // 打开 新 + // 切换到前一个 tab + changeToPrev() { + this.tabManager.changeToPrev(); + } + + // 切换到后一个 tab + changeToNext() { + this.tabManager.changeToNext(); + } + + // 复制终端 + openCopyTerminal() { + useTerminalStore().openCopyTerminal(this.session.hostId); + } + + // 打开新建连接页面 + openNewConnect() { + this.tabManager.openTab(InnerTabs.NEW_CONNECTION); + } } diff --git a/orion-ops-ui/src/views/host/terminal/handler/terminal-session-manager.ts b/orion-ops-ui/src/views/host/terminal/handler/terminal-session-manager.ts index 976de2c7..3210dcf2 100644 --- a/orion-ops-ui/src/views/host/terminal/handler/terminal-session-manager.ts +++ b/orion-ops-ui/src/views/host/terminal/handler/terminal-session-manager.ts @@ -99,16 +99,19 @@ export default class TerminalSessionManager implements ITerminalSessionManager { // 重置 reset(): void { - this.sessions = {}; - // 关闭 channel - this.channel.close(); - // 清除 ping 事件 - if (this.keepAliveTask) { - clearInterval(this.keepAliveTask); - this.keepAliveTask = undefined; + try { + this.sessions = {}; + // 关闭 channel + this.channel.close(); + // 清除 ping 事件 + if (this.keepAliveTask) { + clearInterval(this.keepAliveTask); + this.keepAliveTask = undefined; + } + // 移除 resize 事件 + removeEventListen(window, 'resize', this.dispatchResizeFn); + } catch (e) { } - // 移除 resize 事件 - removeEventListen(window, 'resize', this.dispatchResizeFn); } } diff --git a/orion-ops-ui/src/views/host/terminal/handler/terminal-tab-manager.ts b/orion-ops-ui/src/views/host/terminal/handler/terminal-tab-manager.ts index 0815357b..303974a2 100644 --- a/orion-ops-ui/src/views/host/terminal/handler/terminal-tab-manager.ts +++ b/orion-ops-ui/src/views/host/terminal/handler/terminal-tab-manager.ts @@ -44,6 +44,30 @@ export default class TerminalTabManager implements ITerminalTabManager { this.active = tab.key; } + // 切换到前一个 tab + changeToPrev() { + this.changeToIndex(this.getCurrentTabIndex() - 1); + } + + // 切换到后一个 tab + changeToNext() { + this.changeToIndex(this.getCurrentTabIndex() + 1); + } + + // 切换索引 tab + changeToIndex(index: number) { + if (index < 0 || index >= this.items.length) { + return; + } + // 切换 tab + this.active = this.items[index].key; + } + + // 获取当前索引 + private getCurrentTabIndex(): number { + return this.items.findIndex(s => s.key === this.active); + } + // 清空 clear() { this.active = undefined as unknown as string; diff --git a/orion-ops-ui/src/views/host/terminal/types/terminal.const.ts b/orion-ops-ui/src/views/host/terminal/types/terminal.const.ts index c8b827fd..0e089196 100644 --- a/orion-ops-ui/src/views/host/terminal/types/terminal.const.ts +++ b/orion-ops-ui/src/views/host/terminal/types/terminal.const.ts @@ -121,7 +121,7 @@ export const ActionBarItems = [ icon: 'icon-poweroff', content: '断开连接', }, { - item: 'close', + item: 'closeTab', icon: 'icon-close', content: '关闭终端', } diff --git a/orion-ops-ui/src/views/host/terminal/types/terminal.type.ts b/orion-ops-ui/src/views/host/terminal/types/terminal.type.ts index 00c2642d..e6edcc55 100644 --- a/orion-ops-ui/src/views/host/terminal/types/terminal.type.ts +++ b/orion-ops-ui/src/views/host/terminal/types/terminal.type.ts @@ -97,6 +97,12 @@ export interface ITerminalTabManager { deleteTab: (key: string) => void; // 打开 tab openTab: (tab: TerminalTabItem) => void; + // 切换到前一个 tab + changeToPrev: () => void; + // 切换到后一个 tab + changeToNext: () => void; + // 切换索引 tab + changeToIndex: (index: number) => void; // 清空 clear: () => void; } @@ -172,10 +178,12 @@ export interface ITerminalSession { setCanWrite: (canWrite: boolean) => void; // 写入数据 write: (value: string | Uint8Array) => void; - // 自适应 - fit: () => void; // 聚焦 focus: () => void; + // 失焦 + blur: () => void; + // 自适应 + fit: () => void; // 查找 find: (word: string, next: boolean, options: ISearchOptions) => void; // 断开连接 @@ -221,6 +229,14 @@ export interface ITerminalSessionHandler { clear: () => void; // 断开连接 disconnect: () => void; - // 关闭 - close: () => void; + // 关闭 tab + closeTab: () => void; + // 切换到前一个 tab + changeToPrev: () => void; + // 切换到后一个 tab + changeToNext: () => void; + // 复制终端 + openCopyTerminal: () => void; + // 打开新建连接页面 + openNewConnect: () => void; }