♻️ 添加终端面板快捷键.

This commit is contained in:
lijiahang
2024-02-02 19:04:03 +08:00
parent cff8b7e0d1
commit de82a94f13
8 changed files with 150 additions and 44 deletions

View File

@@ -62,6 +62,18 @@ public class TerminalPreferenceStrategy implements IPreferenceStrategy<TerminalP
String shortcutSetting = TerminalPreferenceModel.ShortcutSettingModel.builder() String shortcutSetting = TerminalPreferenceModel.ShortcutSettingModel.builder()
.enabled(true) .enabled(true)
.keys(Lists.of( .keys(Lists.of(
// 全局快捷键
new TerminalPreferenceModel.ShortcutKeysModel("closeTab", true, true, true, "KeyW", true),
new TerminalPreferenceModel.ShortcutKeysModel("changeToPrevTab", true, true, true, "BracketLeft", true),
new TerminalPreferenceModel.ShortcutKeysModel("changeToNextTab", true, true, true, "BracketRight", true),
new TerminalPreferenceModel.ShortcutKeysModel("openNewConnectTab", true, true, true, "KeyN", true),
// 终端面板快捷键
new TerminalPreferenceModel.ShortcutKeysModel("openNewConnectModal", true, false, true, "KeyN", true),
new TerminalPreferenceModel.ShortcutKeysModel("copyTerminal", true, false, true, "KeyO", true),
new TerminalPreferenceModel.ShortcutKeysModel("closeTerminal", true, false, true, "KeyW", true),
new TerminalPreferenceModel.ShortcutKeysModel("changeToPrevTerminal", true, false, true, "BracketLeft", true),
new TerminalPreferenceModel.ShortcutKeysModel("changeToNextTerminal", true, false, true, "BracketRight", true),
// 终端会话快捷键
new TerminalPreferenceModel.ShortcutKeysModel("copy", true, true, false, "KeyC", true), new TerminalPreferenceModel.ShortcutKeysModel("copy", true, true, false, "KeyC", true),
new TerminalPreferenceModel.ShortcutKeysModel("paste", true, true, false, "KeyV", true), new TerminalPreferenceModel.ShortcutKeysModel("paste", true, true, false, "KeyV", true),
new TerminalPreferenceModel.ShortcutKeysModel("toTop", true, true, false, "ArrowUp", true), new TerminalPreferenceModel.ShortcutKeysModel("toTop", true, true, false, "ArrowUp", true),
@@ -70,12 +82,7 @@ public class TerminalPreferenceStrategy implements IPreferenceStrategy<TerminalP
new TerminalPreferenceModel.ShortcutKeysModel("search", true, true, false, "KeyF", true), new TerminalPreferenceModel.ShortcutKeysModel("search", true, true, false, "KeyF", true),
new TerminalPreferenceModel.ShortcutKeysModel("commandEditor", true, false, true, "KeyE", true), new TerminalPreferenceModel.ShortcutKeysModel("commandEditor", true, false, true, "KeyE", true),
new TerminalPreferenceModel.ShortcutKeysModel("fontSizePlus", true, false, true, "Equal", true), new TerminalPreferenceModel.ShortcutKeysModel("fontSizePlus", true, false, true, "Equal", true),
new TerminalPreferenceModel.ShortcutKeysModel("fontSizeSubtract", true, false, true, "Minus", true), new TerminalPreferenceModel.ShortcutKeysModel("fontSizeSubtract", true, false, true, "Minus", true)
new TerminalPreferenceModel.ShortcutKeysModel("closeTab", true, false, true, "KeyW", true),
new TerminalPreferenceModel.ShortcutKeysModel("changeToPrevTab", true, false, true, "ArrowLeft", true),
new TerminalPreferenceModel.ShortcutKeysModel("changeToNextTab", true, false, true, "ArrowRight", true),
new TerminalPreferenceModel.ShortcutKeysModel("openCopyTerminalTab", true, false, true, "KeyO", true),
new TerminalPreferenceModel.ShortcutKeysModel("openNewConnectTab", true, false, true, "KeyN", true)
)) ))
.build() .build()
.toJsonString(); .toJsonString();

View File

@@ -5,11 +5,11 @@
// Read more: https://github.com/vuejs/core/pull/3399 // Read more: https://github.com/vuejs/core/pull/3399
import '@vue/runtime-core'; import '@vue/runtime-core';
export {}; export {}
declare module '@vue/runtime-core' { declare module '@vue/runtime-core' {
export interface GlobalComponents { export interface GlobalComponents {
RouterLink: typeof import('vue-router')['RouterLink']; RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']; RouterView: typeof import('vue-router')['RouterView']
} }
} }

View File

@@ -157,7 +157,7 @@
}); });
// 点击命令 // 点击命令
const clickCommand = (e: PointerEvent) => { const clickCommand = (e: Event) => {
if (props.item.expand) { if (props.item.expand) {
// 获取选中的文本 // 获取选中的文本
const selectedText = window.getSelection()?.toString(); const selectedText = window.getSelection()?.toString();

View File

@@ -5,7 +5,7 @@
:editable="true" :editable="true"
:auto-switch="true" :auto-switch="true"
:show-add-button="true" :show-add-button="true"
@add="openHostModal" @add="openNewConnect"
@tab-click="k => panel.clickTab(k as string)" @tab-click="k => panel.clickTab(k as string)"
@delete="k => panel.deleteTab(k as string)"> @delete="k => panel.deleteTab(k as string)">
<!-- 右侧按钮 --> <!-- 右侧按钮 -->
@@ -32,9 +32,6 @@
<terminal-view :tab="tab" /> <terminal-view :tab="tab" />
</a-tab-pane> </a-tab-pane>
</a-tabs> </a-tabs>
<!-- 新建连接模态框 -->
<host-list-modal ref="hostModal"
@choose="item => openTerminal(item, index)" />
</div> </div>
</template> </template>
@@ -46,22 +43,19 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { ITerminalTabManager, TerminalPanelTabItem } from '../../types/terminal.type'; import type { ITerminalTabManager, TerminalPanelTabItem } from '../../types/terminal.type';
import { ref, watch } from 'vue'; import { watch } from 'vue';
import { useTerminalStore } from '@/store'; import { useTerminalStore } from '@/store';
import { TerminalPanelTabType } from '../../types/terminal.const'; import { TerminalPanelTabType } from '../../types/terminal.const';
import TerminalView from '../xterm/terminal-view.vue'; import TerminalView from '../xterm/terminal-view.vue';
import HostListModal from '../new-connection/host-list-modal.vue';
const props = defineProps<{ const props = defineProps<{
index: number, index: number,
panel: ITerminalTabManager<TerminalPanelTabItem>, panel: ITerminalTabManager<TerminalPanelTabItem>,
}>(); }>();
const emits = defineEmits(['close']); const emits = defineEmits(['close', 'openNewConnect']);
const { sessionManager, openTerminal } = useTerminalStore(); const { sessionManager } = useTerminalStore();
const hostModal = ref();
// 监听 tab 切换 // 监听 tab 切换
watch(() => props.panel.active, (active, before) => { watch(() => props.panel.active, (active, before) => {
@@ -86,8 +80,8 @@
}); });
// 打开主机模态框 // 打开主机模态框
const openHostModal = () => { const openNewConnect = () => {
hostModal.value.open(); emits('openNewConnect', props.index);
}; };
// 关闭面板 // 关闭面板

View File

@@ -1,11 +1,14 @@
<template> <template>
<div class="terminal-panels-container"> <div class="terminal-panels-container">
<!-- 面板 --> <!-- 终端面板 -->
<terminal-panel v-for="(panel, index) in panelManager.panels" <terminal-panel v-for="(panel, index) in panelManager.panels"
:key="index" :key="index"
:index="index" :index="index"
:panel="panel" :panel="panel"
@open-new-connect="openHostModal"
@close="closePanel" /> @close="closePanel" />
<!-- 新建连接模态框 -->
<host-list-modal ref="hostModal" />
</div> </div>
</template> </template>
@@ -17,11 +20,20 @@
<script lang="ts" setup> <script lang="ts" setup>
import { useTerminalStore } from '@/store'; import { useTerminalStore } from '@/store';
import { onUnmounted } from 'vue'; import { ref, onMounted, onUnmounted } from 'vue';
import { TerminalTabs } from '../../types/terminal.const'; import { TerminalShortcutKeys, TerminalTabs } from '../../types/terminal.const';
import { addEventListen, removeEventListen } from '@/utils/event';
import TerminalPanel from './terminal-panel.vue'; import TerminalPanel from './terminal-panel.vue';
import HostListModal from '../new-connection/host-list-modal.vue';
const { tabManager, panelManager } = useTerminalStore(); const { preference, tabManager, panelManager, copyTerminalSession } = useTerminalStore();
const hostModal = ref();
// 打开主机模态框
const openHostModal = (index: number) => {
hostModal.value.open(index);
};
// 移除面板 // 移除面板
const closePanel = (index: number) => { const closePanel = (index: number) => {
@@ -35,9 +47,67 @@
} }
}; };
// 卸载清空 // 处理全局快捷键逻辑
const handlerKeyboard = (event: Event) => {
const e = event as KeyboardEvent;
// 检测触发的快捷键
const key = preference.shortcutSetting.keys.find(key => {
return key.code === e.code
&& key.altKey === e.altKey
&& key.shiftKey === e.shiftKey
&& key.ctrlKey === e.ctrlKey;
});
if (!key) {
return;
}
// 触发逻辑
switch (key.item) {
case TerminalShortcutKeys.OPEN_NEW_CONNECT_MODAL:
// 打开新建连接弹框
hostModal.value.open(panelManager.active);
break;
case TerminalShortcutKeys.COPY_TERMINAL:
// 复制终端
const hostId = panelManager.getCurrentPanel().getCurrentTab()?.hostId;
if (hostId) {
copyTerminalSession(hostId, panelManager.active);
}
break;
case TerminalShortcutKeys.CLOSE_TERMINAL:
// 关闭终端
const panel = panelManager.getCurrentPanel();
if (panel.active) {
panel.deleteTab(panel.active);
}
break;
case TerminalShortcutKeys.CHANGE_TO_PREV_TERMINAL:
// 切换至前一个终端
panelManager.getCurrentPanel().changeToPrevTab();
break;
case TerminalShortcutKeys.CHANGE_TO_NEXT_TERMINAL:
// 切换至后一个终端
panelManager.getCurrentPanel().changeToNextTab();
break;
default:
break;
}
};
// 监听键盘事件
onMounted(() => {
if (preference.shortcutSetting.enabled) {
addEventListen(window, 'keydown', handlerKeyboard);
}
});
// 卸载回调
onUnmounted(() => { onUnmounted(() => {
// 清空面板
panelManager.reset(); panelManager.reset();
// 移除键盘事件
if (preference.shortcutSetting.enabled) {
removeEventListen(window, 'keydown', handlerKeyboard);
}
}); });
</script> </script>

View File

@@ -49,17 +49,17 @@
</script> </script>
<script lang="ts" setup> <script lang="ts" setup>
import type { HostQueryResponse } from '@/api/asset/host';
import { computed, ref } from 'vue'; import { computed, ref } from 'vue';
import { useTerminalStore } from '@/store'; import { useTerminalStore } from '@/store';
import useVisible from '@/hooks/visible'; import useVisible from '@/hooks/visible';
import { HostQueryResponse } from '@/api/asset/host';
const emits = defineEmits(['choose']); const { hosts, openTerminal } = useTerminalStore();
const { hosts } = useTerminalStore();
const { visible, setVisible } = useVisible(); const { visible, setVisible } = useVisible();
const panelIndex = ref();
const filterValue = ref(''); const filterValue = ref('');
const hostList = computed(() => { const hostList = computed(() => {
const filterVal = filterValue.value.toLowerCase(); const filterVal = filterValue.value.toLowerCase();
let list; let list;
@@ -88,7 +88,8 @@
}); });
// 打开配置 // 打开配置
const open = () => { const open = (index: number) => {
panelIndex.value = index;
setVisible(true); setVisible(true);
}; };
@@ -96,7 +97,7 @@
// 打开终端 // 打开终端
const clickHost = (item: HostQueryResponse) => { const clickHost = (item: HostQueryResponse) => {
emits('choose', item); openTerminal(item, panelIndex.value);
setVisible(false); setVisible(false);
}; };

View File

@@ -26,8 +26,15 @@
@set-editable="setEditableStatus" @set-editable="setEditableStatus"
@clear-editable="clearEditableStatus" @clear-editable="clearEditableStatus"
@update-enabled="updateEnabledStatus" /> @update-enabled="updateEnabledStatus" />
<!-- 终端快捷键 --> <!-- 终端面板快捷键 -->
<terminal-shortcut-keys-block title="终端快捷键" <terminal-shortcut-keys-block title="终端面板快捷键"
:type="TerminalShortcutType.PANEL"
:items="shortcutKeys"
@set-editable="setEditableStatus"
@clear-editable="clearEditableStatus"
@update-enabled="updateEnabledStatus" />
<!-- 终端会话快捷键 -->
<terminal-shortcut-keys-block title="终端会话快捷键"
:type="TerminalShortcutType.TERMINAL" :type="TerminalShortcutType.TERMINAL"
:items="shortcutKeys" :items="shortcutKeys"
@set-editable="setEditableStatus" @set-editable="setEditableStatus"

View File

@@ -131,8 +131,9 @@ export const ActionBarItems = [
// 终端快捷键操作类型 // 终端快捷键操作类型
export const TerminalShortcutType = { export const TerminalShortcutType = {
TAB: 1, GLOBAL: 1,
TERMINAL: 2 PANEL: 2,
TERMINAL: 3
}; };
// 终端操作快捷键 key // 终端操作快捷键 key
@@ -145,6 +146,16 @@ export const TerminalShortcutKeys = {
CLOSE_TAB: 'closeTab', CLOSE_TAB: 'closeTab',
// 打开新建连接 tab // 打开新建连接 tab
OPEN_NEW_CONNECT_TAB: 'openNewConnectTab', OPEN_NEW_CONNECT_TAB: 'openNewConnectTab',
// 打开新建连接弹框
OPEN_NEW_CONNECT_MODAL: 'openNewConnectModal',
// 复制终端
COPY_TERMINAL: 'copyTerminal',
// 关闭终端
CLOSE_TERMINAL: 'closeTerminal',
// 切换至前一个终端
CHANGE_TO_PREV_TERMINAL: 'changeToPrevTerminal',
// 切换至后一个终端
CHANGE_TO_NEXT_TERMINAL: 'changeToNextTerminal',
}; };
// 终端操作快捷键 // 终端操作快捷键
@@ -152,23 +163,39 @@ export const TerminalShortcutItems: Array<ShortcutKeyItem> = [
{ {
item: TerminalShortcutKeys.CHANGE_TO_PREV_TAB, item: TerminalShortcutKeys.CHANGE_TO_PREV_TAB,
content: '切换为前一个 tab', content: '切换为前一个 tab',
type: TerminalShortcutType.TAB type: TerminalShortcutType.GLOBAL
}, { }, {
item: TerminalShortcutKeys.CHANGE_TO_NEXT_TAB, item: TerminalShortcutKeys.CHANGE_TO_NEXT_TAB,
content: '切换为后一个 tab', content: '切换为后一个 tab',
type: TerminalShortcutType.TAB type: TerminalShortcutType.GLOBAL
}, { }, {
item: TerminalShortcutKeys.CLOSE_TAB, item: TerminalShortcutKeys.CLOSE_TAB,
content: '关闭当前 tab', content: '关闭当前 tab',
type: TerminalShortcutType.TAB type: TerminalShortcutType.GLOBAL
}, { }, {
item: TerminalShortcutKeys.OPEN_NEW_CONNECT_TAB, item: TerminalShortcutKeys.OPEN_NEW_CONNECT_TAB,
content: '打开新建连接 tab', content: '打开新建连接 tab',
type: TerminalShortcutType.TAB type: TerminalShortcutType.GLOBAL
}, { }, {
item: 'openCopyTerminalTab', item: TerminalShortcutKeys.OPEN_NEW_CONNECT_MODAL,
content: '复制当前终端 tab', content: '打开新建连接弹框',
type: TerminalShortcutType.TERMINAL type: TerminalShortcutType.PANEL
}, {
item: TerminalShortcutKeys.COPY_TERMINAL,
content: '复制终端',
type: TerminalShortcutType.PANEL
}, {
item: TerminalShortcutKeys.CLOSE_TERMINAL,
content: '关闭终端',
type: TerminalShortcutType.PANEL
}, {
item: TerminalShortcutKeys.CHANGE_TO_PREV_TERMINAL,
content: '切换至前一个终端',
type: TerminalShortcutType.PANEL
}, {
item: TerminalShortcutKeys.CHANGE_TO_NEXT_TERMINAL,
content: '切换至后一个终端',
type: TerminalShortcutType.PANEL
}, { }, {
item: 'copy', item: 'copy',
content: '复制', content: '复制',