🚧 重构中 🚧

This commit is contained in:
lijiahang
2024-02-01 19:24:49 +08:00
parent 0263231fdb
commit 94e8d439a7
12 changed files with 117 additions and 96 deletions

View File

@@ -17,7 +17,7 @@ import { defineStore } from 'pinia';
import { getPreference, updatePreference } from '@/api/user/preference'; import { getPreference, updatePreference } from '@/api/user/preference';
import { nextSessionId } from '@/utils'; import { nextSessionId } from '@/utils';
import { Message } from '@arco-design/web-vue'; import { Message } from '@arco-design/web-vue';
import { TerminalTabType } from '@/views/host/terminal/types/terminal.const'; import { TerminalTabs } from '@/views/host/terminal/types/terminal.const';
import TerminalTabManager from '@/views/host/terminal/handler/terminal-tab-manager'; import TerminalTabManager from '@/views/host/terminal/handler/terminal-tab-manager';
import TerminalSessionManager from '@/views/host/terminal/handler/terminal-session-manager'; import TerminalSessionManager from '@/views/host/terminal/handler/terminal-session-manager';
@@ -62,7 +62,8 @@ export default defineStore('terminal', {
} as TerminalShortcutSetting, } as TerminalShortcutSetting,
}, },
hosts: {} as AuthorizedHostQueryResponse, hosts: {} as AuthorizedHostQueryResponse,
tabManager: new TerminalTabManager(), tabManager: new TerminalTabManager(TerminalTabs.NEW_CONNECTION),
routerTabManager: [new TerminalTabManager()],
sessionManager: new TerminalSessionManager() sessionManager: new TerminalSessionManager()
}), }),
@@ -130,9 +131,11 @@ export default defineStore('terminal', {
}, },
// 打开终端 // 打开终端
openTerminal(record: HostQueryResponse) { openTerminal(record: HostQueryResponse, panelIndex: number = 0) {
// 添加到最近连接 // 添加到最近连接
this.hosts.latestHosts = [...new Set([record.id, ...this.hosts.latestHosts])]; this.hosts.latestHosts = [...new Set([record.id, ...this.hosts.latestHosts])];
// 切换到终端面板页面
this.tabManager.openTab(TerminalTabs.TERMINAL_PANEL);
// 获取 seq // 获取 seq
const tabSeqArr = this.tabManager.items const tabSeqArr = this.tabManager.items
.map(s => s.seq) .map(s => s.seq)
@@ -141,9 +144,9 @@ export default defineStore('terminal', {
const nextSeq = tabSeqArr.length const nextSeq = tabSeqArr.length
? Math.max(...tabSeqArr) + 1 ? Math.max(...tabSeqArr) + 1
: 1; : 1;
// FIXME
// 打开 tab // 打开 tab
this.tabManager.openTab({ this.tabManager.openTab({
type: TerminalTabType.TERMINAL,
key: nextSessionId(10), key: nextSessionId(10),
seq: nextSeq, seq: nextSeq,
title: `(${nextSeq}) ${record.alias || record.name}`, title: `(${nextSeq}) ${record.alias || record.name}`,
@@ -164,7 +167,8 @@ export default defineStore('terminal', {
// 获取当前终端会话 // 获取当前终端会话
getCurrentTerminalSession(tips: boolean = true) { getCurrentTerminalSession(tips: boolean = true) {
const tab = this.tabManager.getCurrentTab(); const tab = this.tabManager.getCurrentTab();
if (!tab || tab.type !== TerminalTabType.TERMINAL) { // FIXME
if (!tab || tab.type !== 'TERMINAL') {
if (tips) { if (tips) {
Message.warning('请切换到终端标签页'); Message.warning('请切换到终端标签页');
} }

View File

@@ -6,6 +6,7 @@ export interface TerminalState {
preference: TerminalPreference; preference: TerminalPreference;
hosts: AuthorizedHostQueryResponse; hosts: AuthorizedHostQueryResponse;
tabManager: ITerminalTabManager; tabManager: ITerminalTabManager;
routerTabManager: Array<ITerminalTabManager>;
sessionManager: ITerminalSessionManager; sessionManager: ITerminalSessionManager;
} }

View File

@@ -1,5 +1,5 @@
<template> <template>
<a-dropdown class="terminal-context-menu" <a-dropdown class="host-space-context-menu"
:popup-max-height="false" :popup-max-height="false"
trigger="contextMenu" trigger="contextMenu"
position="bl" position="bl"
@@ -43,44 +43,45 @@
</div> </div>
</div> </div>
<!-- 命令 --> <!-- 命令 -->
<span class="snippet-item-command"> <span class="snippet-item-command"
{{ item.command }} @click="clickCommand">
</span> {{ item.command }}
</span>
</div> </div>
</div> </div>
<!-- 右键菜单 --> <!-- 右键菜单 -->
<template #content> <template #content>
<!-- 复制 --> <!-- 复制 -->
<a-doption @click="copyCommand"> <a-doption @click="copyCommand">
<div class="terminal-context-menu-icon"> <div class="host-space-context-menu-icon">
<icon-copy /> <icon-copy />
</div> </div>
<div>复制</div> <div>复制</div>
</a-doption> </a-doption>
<!-- 粘贴 --> <!-- 粘贴 -->
<a-doption @click="paste"> <a-doption @click="paste">
<div class="terminal-context-menu-icon"> <div class="host-space-context-menu-icon">
<icon-paste /> <icon-paste />
</div> </div>
<div>粘贴</div> <div>粘贴</div>
</a-doption> </a-doption>
<!-- 执行 --> <!-- 执行 -->
<a-doption @click="exec"> <a-doption @click="exec">
<div class="terminal-context-menu-icon"> <div class="host-space-context-menu-icon">
<icon-thunderbolt /> <icon-thunderbolt />
</div> </div>
<div>执行</div> <div>执行</div>
</a-doption> </a-doption>
<!-- 修改 --> <!-- 修改 -->
<a-doption @click="openUpdateSnippet(item)"> <a-doption @click="openUpdateSnippet(item)">
<div class="terminal-context-menu-icon"> <div class="host-space-context-menu-icon">
<icon-edit /> <icon-edit />
</div> </div>
<div>修改</div> <div>修改</div>
</a-doption> </a-doption>
<!-- 删除 --> <!-- 删除 -->
<a-doption @click="removeSnippet(item.id)"> <a-doption @click="removeSnippet(item.id)">
<div class="terminal-context-menu-icon"> <div class="host-space-context-menu-icon">
<icon-delete /> <icon-delete />
</div> </div>
<div>删除</div> <div>删除</div>
@@ -88,7 +89,7 @@
<!-- 展开 --> <!-- 展开 -->
<a-doption v-if="!item.expand" <a-doption v-if="!item.expand"
@click="() => item.expand = true"> @click="() => item.expand = true">
<div class="terminal-context-menu-icon"> <div class="host-space-context-menu-icon">
<icon-expand /> <icon-expand />
</div> </div>
<div>展开</div> <div>展开</div>
@@ -96,7 +97,7 @@
<!-- 收起 --> <!-- 收起 -->
<a-doption v-else <a-doption v-else
@click="() => item.expand = false"> @click="() => item.expand = false">
<div class="terminal-context-menu-icon"> <div class="host-space-context-menu-icon">
<icon-shrink /> <icon-shrink />
</div> </div>
<div>收起</div> <div>收起</div>
@@ -155,6 +156,17 @@
}, 50); }, 50);
}); });
// 点击命令
const clickCommand = (e: PointerEvent) => {
if (props.item.expand) {
// 获取选中的文本
const selectedText = window.getSelection()?.toString();
if (selectedText) {
e.stopPropagation();
}
}
};
// 复制命令 // 复制命令
const copyCommand = () => { const copyCommand = () => {
copy(props.item.command, false); copy(props.item.command, false);

View File

@@ -32,27 +32,25 @@
import type { HostQueryResponse } from '@/api/asset/host'; import type { HostQueryResponse } from '@/api/asset/host';
import { onMounted, ref } from 'vue'; import { onMounted, ref } from 'vue';
import { useTerminalStore } from '@/store'; import { useTerminalStore } from '@/store';
import { InnerTabs, TerminalTabType } from '../../types/terminal.const'; import { TerminalTabs } from '../../types/terminal.const';
import { get } from 'lodash';
const totalCount = 7; const totalCount = 7;
const { tabManager, hosts, openTerminal } = useTerminalStore(); const { tabManager, hosts, openTerminal } = useTerminalStore();
const combinedHandlers = ref<Array<CombinedHandlerItem>>([{ const combinedHandlers = ref<Array<CombinedHandlerItem>>([{
title: InnerTabs.NEW_CONNECTION.title, title: TerminalTabs.NEW_CONNECTION.title,
settingTab: InnerTabs.NEW_CONNECTION, tab: TerminalTabs.NEW_CONNECTION,
type: TerminalTabType.SETTING, icon: TerminalTabs.NEW_CONNECTION.icon
icon: InnerTabs.NEW_CONNECTION.icon
}]); }]);
// 点击组合操作元素 // 点击组合操作元素
const clickHandlerItem = (item: CombinedHandlerItem) => { const clickHandlerItem = (item: CombinedHandlerItem) => {
if (item.type === TerminalTabType.SETTING) { if (item.host) {
// 打开内置 tab
tabManager.openTab(item.settingTab as TerminalTabItem);
} else {
// 打开终端 // 打开终端
openTerminal(item.host as HostQueryResponse); openTerminal(item.host as HostQueryResponse);
} else {
// 打开 tab
tabManager.openTab(item.tab as TerminalTabItem);
} }
}; };
@@ -71,7 +69,6 @@
.map(s => { .map(s => {
return { return {
title: `${s.alias || s.name} (${s.address})`, title: `${s.alias || s.name} (${s.address})`,
type: TerminalTabType.TERMINAL,
host: s, host: s,
icon: 'icon-desktop' icon: 'icon-desktop'
}; };
@@ -80,15 +77,13 @@
combinedHandlers.value.push(...combinedHosts); combinedHandlers.value.push(...combinedHosts);
// 不足显示的行数用设置补充 // 不足显示的行数用设置补充
if (totalCount - 1 - combinedHosts.length > 0) { if (totalCount - 1 - combinedHosts.length > 0) {
const fillTabs = Object.keys(InnerTabs) const fillTabs = Object.values(TerminalTabs)
.filter(s => s !== 'NEW_CONNECTION') .filter(s => s.key !== TerminalTabs.NEW_CONNECTION.key)
.map(s => get(InnerTabs, s) as TerminalTabItem)
.slice(0, totalCount - 1 - combinedHosts.length) .slice(0, totalCount - 1 - combinedHosts.length)
.map(s => { .map(s => {
return { return {
title: s.title, title: s.title,
settingTab: s, tab: s,
type: TerminalTabType.SETTING,
icon: s.icon as string icon: s.icon as string
}; };
}); });

View File

@@ -19,7 +19,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { SidebarAction } from '../../types/terminal.type'; import type { SidebarAction } from '../../types/terminal.type';
import { InnerTabs } from '../../types/terminal.const'; import { TerminalTabs } from '../../types/terminal.const';
import { useTerminalStore } from '@/store'; import { useTerminalStore } from '@/store';
import IconActions from './icon-actions.vue'; import IconActions from './icon-actions.vue';
@@ -28,33 +28,33 @@
// 顶部操作 // 顶部操作
const topActions: Array<SidebarAction> = [ const topActions: Array<SidebarAction> = [
{ {
icon: InnerTabs.NEW_CONNECTION.icon, icon: TerminalTabs.NEW_CONNECTION.icon,
content: InnerTabs.NEW_CONNECTION.title, content: TerminalTabs.NEW_CONNECTION.title,
click: () => tabManager.openTab(InnerTabs.NEW_CONNECTION) click: () => tabManager.openTab(TerminalTabs.NEW_CONNECTION)
}, },
]; ];
// 底部操作 // 底部操作
const bottomActions: Array<SidebarAction> = [ const bottomActions: Array<SidebarAction> = [
{ {
icon: InnerTabs.SHORTCUT_SETTING.icon, icon: TerminalTabs.SHORTCUT_SETTING.icon,
content: InnerTabs.SHORTCUT_SETTING.title, content: TerminalTabs.SHORTCUT_SETTING.title,
click: () => tabManager.openTab(InnerTabs.SHORTCUT_SETTING) click: () => tabManager.openTab(TerminalTabs.SHORTCUT_SETTING)
}, },
{ {
icon: InnerTabs.DISPLAY_SETTING.icon, icon: TerminalTabs.DISPLAY_SETTING.icon,
content: InnerTabs.DISPLAY_SETTING.title, content: TerminalTabs.DISPLAY_SETTING.title,
click: () => tabManager.openTab(InnerTabs.DISPLAY_SETTING) click: () => tabManager.openTab(TerminalTabs.DISPLAY_SETTING)
}, },
{ {
icon: InnerTabs.THEME_SETTING.icon, icon: TerminalTabs.THEME_SETTING.icon,
content: InnerTabs.THEME_SETTING.title, content: TerminalTabs.THEME_SETTING.title,
click: () => tabManager.openTab(InnerTabs.THEME_SETTING) click: () => tabManager.openTab(TerminalTabs.THEME_SETTING)
}, },
{ {
icon: InnerTabs.TERMINAL_SETTING.icon, icon: TerminalTabs.TERMINAL_SETTING.icon,
content: InnerTabs.TERMINAL_SETTING.title, content: TerminalTabs.TERMINAL_SETTING.title,
click: () => tabManager.openTab(InnerTabs.TERMINAL_SETTING) click: () => tabManager.openTab(TerminalTabs.TERMINAL_SETTING)
}, },
]; ];

View File

@@ -6,23 +6,18 @@
<a-tab-pane v-for="tab in tabManager.items" <a-tab-pane v-for="tab in tabManager.items"
:key="tab.key" :key="tab.key"
:title="tab.title"> :title="tab.title">
<!-- 设置 --> <!-- 新建连接 -->
<template v-if="tab.type === TerminalTabType.SETTING"> <new-connection-view v-if="tab.key === TerminalTabs.NEW_CONNECTION.key" />
<!-- 新建连接 --> <!-- 快捷键设置 -->
<new-connection-view v-if="tab.key === InnerTabs.NEW_CONNECTION.key" /> <terminal-shortcut-setting v-else-if="tab.key === TerminalTabs.SHORTCUT_SETTING.key" />
<!-- 快捷键设置 --> <!-- 显示设置 -->
<terminal-shortcut-setting v-else-if="tab.key === InnerTabs.SHORTCUT_SETTING.key" /> <terminal-display-setting v-else-if="tab.key === TerminalTabs.DISPLAY_SETTING.key" />
<!-- 显示设置 --> <!-- 主题设置 -->
<terminal-display-setting v-else-if="tab.key === InnerTabs.DISPLAY_SETTING.key" /> <terminal-theme-setting v-else-if="tab.key === TerminalTabs.THEME_SETTING.key" />
<!-- 主题设置 --> <!-- 终端设置 -->
<terminal-theme-setting v-else-if="tab.key === InnerTabs.THEME_SETTING.key" /> <terminal-general-setting v-else-if="tab.key === TerminalTabs.TERMINAL_SETTING.key" />
<!-- 终端设置 --> <!-- 主机终端 -->
<terminal-general-setting v-else-if="tab.key === InnerTabs.TERMINAL_SETTING.key" /> <terminal-panel-view v-else-if="tab.key === TerminalTabs.TERMINAL_PANEL.key" />
</template>
<!-- 终端 -->
<template v-else-if="tab.type === TerminalTabType.TERMINAL">
<terminal-view :tab="tab" />
</template>
</a-tab-pane> </a-tab-pane>
</a-tabs> </a-tabs>
<!-- 承载页推荐 --> <!-- 承载页推荐 -->
@@ -37,7 +32,7 @@
</script> </script>
<script lang="ts" setup> <script lang="ts" setup>
import { TerminalTabType, InnerTabs, TerminalShortcutKeys } from '../../types/terminal.const'; import { TerminalTabs, TerminalShortcutKeys } from '../../types/terminal.const';
import { useTerminalStore } from '@/store'; import { useTerminalStore } from '@/store';
import { onMounted, onUnmounted, watch } from 'vue'; import { onMounted, onUnmounted, watch } from 'vue';
import { addEventListen, removeEventListen } from '@/utils/event'; import { addEventListen, removeEventListen } from '@/utils/event';
@@ -47,16 +42,17 @@
import TerminalThemeSetting from '../setting/theme/terminal-theme-setting.vue'; import TerminalThemeSetting from '../setting/theme/terminal-theme-setting.vue';
import TerminalGeneralSetting from '../setting/general/terminal-general-setting.vue'; import TerminalGeneralSetting from '../setting/general/terminal-general-setting.vue';
import TerminalShortcutSetting from '../setting/shortcut/terminal-shortcut-setting.vue'; import TerminalShortcutSetting from '../setting/shortcut/terminal-shortcut-setting.vue';
import TerminalView from '../xterm/terminal-view.vue'; import TerminalPanelView from '@/views/host/terminal/components/layout/terminal-panel-view.vue';
const { preference, tabManager, sessionManager } = useTerminalStore(); const { preference, tabManager, sessionManager } = useTerminalStore();
// fixme TerminalTabType.TERMINAL
// 监听 tab 修改 // 监听 tab 修改
watch(() => tabManager.active, (active, before) => { watch(() => tabManager.active, (active, before) => {
if (before) { if (before) {
// 失焦已经切换的终端 // 失焦已经切换的终端
const beforeTab = tabManager.items.find(s => s.key === before); const beforeTab = tabManager.items.find(s => s.key === before);
if (beforeTab && beforeTab?.type === TerminalTabType.TERMINAL) { if (beforeTab && beforeTab?.type === 'TerminalTabType.TERMINAL') {
sessionManager.getSession(before)?.blur(); sessionManager.getSession(before)?.blur();
} }
} }
@@ -66,10 +62,11 @@
if (!activeTab) { if (!activeTab) {
return; return;
} }
console.log(activeTab.title);
// 修改标题 // 修改标题
document.title = activeTab.title; document.title = activeTab.title;
// 终端自动聚焦 // 终端自动聚焦
if (activeTab?.type === TerminalTabType.TERMINAL) { if (activeTab?.type === 'TerminalTabType.TERMINAL') {
sessionManager.getSession(active)?.focus(); sessionManager.getSession(active)?.focus();
} }
} else { } else {
@@ -82,7 +79,7 @@
const handlerKeyboard = (event: Event) => { const handlerKeyboard = (event: Event) => {
// 当前页面非 terminal 的时候再触发快捷键 (terminal 有内置逻辑) // 当前页面非 terminal 的时候再触发快捷键 (terminal 有内置逻辑)
if (tabManager.active if (tabManager.active
&& tabManager.items.find(s => s.key === tabManager.active)?.type === TerminalTabType.TERMINAL) { && tabManager.items.find(s => s.key === tabManager.active)?.type === 'TerminalTabType.TERMINAL') {
return; return;
} }
const e = event as KeyboardEvent; const e = event as KeyboardEvent;
@@ -114,7 +111,7 @@
break; break;
case TerminalShortcutKeys.OPEN_NEW_CONNECT_TAB: case TerminalShortcutKeys.OPEN_NEW_CONNECT_TAB:
// 切换到新建连接 tab // 切换到新建连接 tab
tabManager.openTab(InnerTabs.NEW_CONNECTION); tabManager.openTab(TerminalTabs.NEW_CONNECTION);
break; break;
default: default:
break; break;

View File

@@ -0,0 +1,17 @@
<template>
</template>
<script lang="ts">
export default {
name: 'terminalPanelView'
};
</script>
<script lang="ts" setup>
</script>
<style lang="less" scoped>
</style>

View File

@@ -4,7 +4,7 @@ import type { Terminal } from 'xterm';
import useCopy from '@/hooks/copy'; import useCopy from '@/hooks/copy';
import html2canvas from 'html2canvas'; import html2canvas from 'html2canvas';
import { useTerminalStore, useUserStore } from '@/store'; import { useTerminalStore, useUserStore } from '@/store';
import { InnerTabs } from '../types/terminal.const'; import { TerminalTabs } from '../types/terminal.const';
import { saveAs } from 'file-saver'; import { saveAs } from 'file-saver';
import { Message } from '@arco-design/web-vue'; import { Message } from '@arco-design/web-vue';
import { dateFormat } from '@/utils'; import { dateFormat } from '@/utils';
@@ -328,7 +328,7 @@ export default class TerminalSessionHandler implements ITerminalSessionHandler {
// 打开新建连接 tab // 打开新建连接 tab
openNewConnectTab() { openNewConnectTab() {
this.tabManager.openTab(InnerTabs.NEW_CONNECTION); this.tabManager.openTab(TerminalTabs.NEW_CONNECTION);
} }
} }

View File

@@ -1,5 +1,4 @@
import type { ITerminalTabManager, TerminalTabItem } from '../types/terminal.type'; import type { ITerminalTabManager, TerminalTabItem } from '../types/terminal.type';
import { InnerTabs } from '../types/terminal.const';
// 终端 tab 管理器实现 // 终端 tab 管理器实现
export default class TerminalTabManager implements ITerminalTabManager { export default class TerminalTabManager implements ITerminalTabManager {
@@ -8,9 +7,14 @@ export default class TerminalTabManager implements ITerminalTabManager {
public items: Array<TerminalTabItem>; public items: Array<TerminalTabItem>;
constructor() { constructor(def: TerminalTabItem | undefined = undefined) {
this.active = InnerTabs.NEW_CONNECTION.key; if (def) {
this.items = [InnerTabs.NEW_CONNECTION]; this.active = def.key;
this.items = [def];
} else {
this.active = undefined as unknown as string;
this.items = [];
}
} }
// 获取当前 tab // 获取当前 tab

View File

@@ -33,7 +33,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import { ref, onBeforeMount, onUnmounted, onMounted } from 'vue'; import { ref, onBeforeMount, onUnmounted, onMounted } from 'vue';
import { dictKeys, InnerTabs } from './types/terminal.const'; import { dictKeys, TerminalTabs } from './types/terminal.const';
import { useCacheStore, useDictStore, useTerminalStore } from '@/store'; import { useCacheStore, useDictStore, useTerminalStore } from '@/store';
import useLoading from '@/hooks/loading'; import useLoading from '@/hooks/loading';
import LayoutHeader from './components/layout/layout-header.vue'; import LayoutHeader from './components/layout/layout-header.vue';
@@ -85,7 +85,7 @@
// 事件处理 // 事件处理
onMounted(() => { onMounted(() => {
// 默认标题 // 默认标题
document.title = InnerTabs.NEW_CONNECTION.title; document.title = TerminalTabs.NEW_CONNECTION.title;
// 注册关闭视口事件 // 注册关闭视口事件
// FIXME 开发阶段 // FIXME 开发阶段
// window.addEventListener('beforeunload', handleBeforeUnload); // window.addEventListener('beforeunload', handleBeforeUnload);

View File

@@ -1,43 +1,36 @@
// tab 类型
import { ShortcutKeyItem } from './terminal.type'; import { ShortcutKeyItem } from './terminal.type';
// tab 类型 // 终端 tab
export const TerminalTabType = { export const TerminalTabs = {
SETTING: 'setting',
TERMINAL: 'terminal',
};
// 内置 tab
export const InnerTabs = {
NEW_CONNECTION: { NEW_CONNECTION: {
key: 'newConnection', key: 'newConnection',
title: '新建连接', title: '新建连接',
icon: 'icon-plus', icon: 'icon-plus',
type: TerminalTabType.SETTING
}, },
SHORTCUT_SETTING: { SHORTCUT_SETTING: {
key: 'shortcutSetting', key: 'shortcutSetting',
title: '快捷键设置', title: '快捷键设置',
icon: 'icon-command', icon: 'icon-command',
type: TerminalTabType.SETTING
}, },
DISPLAY_SETTING: { DISPLAY_SETTING: {
key: 'displaySetting', key: 'displaySetting',
title: '显示设置', title: '显示设置',
icon: 'icon-stamp', icon: 'icon-stamp',
type: TerminalTabType.SETTING
}, },
THEME_SETTING: { THEME_SETTING: {
key: 'themeSetting', key: 'themeSetting',
title: '主题设置', title: '主题设置',
icon: 'icon-palette', icon: 'icon-palette',
type: TerminalTabType.SETTING
}, },
TERMINAL_SETTING: { TERMINAL_SETTING: {
key: 'terminalSetting', key: 'terminalSetting',
title: '终端设置', title: '终端设置',
icon: 'icon-settings', icon: 'icon-settings',
type: TerminalTabType.SETTING },
TERMINAL_PANEL: {
key: 'terminalPanel',
title: '主机终端',
icon: 'icon-desktop',
}, },
}; };

View File

@@ -12,7 +12,6 @@ import type { HostQueryResponse } from '@/api/asset/host';
export interface TerminalTabItem { export interface TerminalTabItem {
key: string; key: string;
title: string; title: string;
type: string;
icon?: string; icon?: string;
[key: string]: unknown; [key: string]: unknown;
@@ -32,9 +31,8 @@ export interface SidebarAction {
// 组合操作元素 // 组合操作元素
export interface CombinedHandlerItem { export interface CombinedHandlerItem {
icon: string, icon: string,
type: string,
title: string; title: string;
settingTab?: TerminalTabItem; tab?: TerminalTabItem;
host?: HostQueryResponse; host?: HostQueryResponse;
} }