✨ 回车重连.
This commit is contained in:
@@ -8,7 +8,7 @@ import type {
|
|||||||
TerminalShortcutSetting,
|
TerminalShortcutSetting,
|
||||||
TerminalState
|
TerminalState
|
||||||
} from './types';
|
} from './types';
|
||||||
import type { ISshSession, PanelSessionTab, TerminalPanelTabItem } from '@/views/host/terminal/types/terminal.type';
|
import type { ISshSession, PanelSessionTabType, TerminalPanelTabItem } from '@/views/host/terminal/types/terminal.type';
|
||||||
import type { AuthorizedHostQueryResponse } from '@/api/asset/asset-authorized-data';
|
import type { AuthorizedHostQueryResponse } from '@/api/asset/asset-authorized-data';
|
||||||
import { getCurrentAuthorizedHost } from '@/api/asset/asset-authorized-data';
|
import { getCurrentAuthorizedHost } from '@/api/asset/asset-authorized-data';
|
||||||
import type { HostQueryResponse } from '@/api/asset/host';
|
import type { HostQueryResponse } from '@/api/asset/host';
|
||||||
@@ -135,7 +135,7 @@ export default defineStore('terminal', {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// 打开会话
|
// 打开会话
|
||||||
openSession(record: HostQueryResponse, type: PanelSessionTab, panelIndex: number = 0) {
|
openSession(record: HostQueryResponse, type: PanelSessionTabType, panelIndex: number = 0) {
|
||||||
// 添加到最近连接
|
// 添加到最近连接
|
||||||
this.hosts.latestHosts = [...new Set([record.id, ...this.hosts.latestHosts])];
|
this.hosts.latestHosts = [...new Set([record.id, ...this.hosts.latestHosts])];
|
||||||
// 切换到终端面板页面
|
// 切换到终端面板页面
|
||||||
@@ -151,8 +151,10 @@ export default defineStore('terminal', {
|
|||||||
? Math.max(...seqArr) + 1
|
? Math.max(...seqArr) + 1
|
||||||
: 1;
|
: 1;
|
||||||
// 打开 tab
|
// 打开 tab
|
||||||
|
const sessionId = nextId(10);
|
||||||
this.panelManager.getPanel(panelIndex).openTab({
|
this.panelManager.getPanel(panelIndex).openTab({
|
||||||
key: nextId(10),
|
key: sessionId,
|
||||||
|
sessionId,
|
||||||
seq: nextSeq,
|
seq: nextSeq,
|
||||||
title: `(${nextSeq}) ${record.alias || record.name}`,
|
title: `(${nextSeq}) ${record.alias || record.name}`,
|
||||||
hostId: record.id,
|
hostId: record.id,
|
||||||
@@ -163,20 +165,18 @@ export default defineStore('terminal', {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// 重新打开 terminal 会话
|
// 重新打开会话
|
||||||
async reOpenTerminal(hostId: number, sessionId: string, panelIndex: number = 0) {
|
async reOpenSession(sessionId: string, panelIndex: number = 0) {
|
||||||
console.log('rec');
|
|
||||||
// 添加到最近连接
|
|
||||||
this.hosts.latestHosts = [...new Set([hostId, ...this.hosts.latestHosts])];
|
|
||||||
// 切换到终端面板页面
|
// 切换到终端面板页面
|
||||||
this.tabManager.openTab(TerminalTabs.TERMINAL_PANEL);
|
this.tabManager.openTab(TerminalTabs.TERMINAL_PANEL);
|
||||||
// 获取当前面板并且分配新的 sessionId
|
// 获取当前面板并且分配新的 sessionId
|
||||||
const panel = this.panelManager.getPanel(panelIndex);
|
const panel = this.panelManager.getPanel(panelIndex);
|
||||||
const tab = panel.getTab(sessionId);
|
const tab = panel.getTab(sessionId);
|
||||||
const newSessionId = nextId(10);
|
const newSessionId = tab.sessionId = nextId(10);
|
||||||
tab.key = newSessionId;
|
// 添加到最近连接
|
||||||
// 重新打开 ssh
|
this.hosts.latestHosts = [...new Set([tab.hostId, ...this.hosts.latestHosts])];
|
||||||
await this.sessionManager.reOpenSsh(sessionId, newSessionId);
|
// 重新打开会话
|
||||||
|
await this.sessionManager.reOpenSession(tab.type, sessionId, newSessionId);
|
||||||
},
|
},
|
||||||
|
|
||||||
// 复制并且打开会话
|
// 复制并且打开会话
|
||||||
@@ -220,7 +220,7 @@ export default defineStore('terminal', {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 获取会话
|
// 获取会话
|
||||||
return this.sessionManager.getSession<ISshSession>(sessionTab.key);
|
return this.sessionManager.getSession<ISshSession>(sessionTab.sessionId);
|
||||||
},
|
},
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -16,9 +16,8 @@
|
|||||||
</span>
|
</span>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<!-- 终端面板 FIXME -->
|
<!-- 终端面板 这里的 key 只能使用 key 字段, 否则重连有问题 -->
|
||||||
<a-tab-pane v-for="tab in panel.items"
|
<a-tab-pane v-for="tab in panel.items" :key="tab.key">
|
||||||
:key="tab.key">
|
|
||||||
<!-- 标题 -->
|
<!-- 标题 -->
|
||||||
<template #title>
|
<template #title>
|
||||||
<span class="tab-title-wrapper usn"
|
<span class="tab-title-wrapper usn"
|
||||||
@@ -64,6 +63,9 @@
|
|||||||
|
|
||||||
// 监听 tab 切换
|
// 监听 tab 切换
|
||||||
watch(() => props.panel.active, (active, before) => {
|
watch(() => props.panel.active, (active, before) => {
|
||||||
|
console.log(active);
|
||||||
|
console.log(before);
|
||||||
|
console.log(props.panel);
|
||||||
// 失焦自动终端
|
// 失焦自动终端
|
||||||
if (before) {
|
if (before) {
|
||||||
const beforeTab = props.panel.items.find(s => s.key === before);
|
const beforeTab = props.panel.items.find(s => s.key === before);
|
||||||
@@ -78,7 +80,7 @@
|
|||||||
sessionManager.getSession<ISshSession>(active)?.focus();
|
sessionManager.getSession<ISshSession>(active)?.focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 无终端自动关闭
|
// 无终端自动关闭 FIXME
|
||||||
if (!props.panel.items.length) {
|
if (!props.panel.items.length) {
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,7 +80,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { PanelSessionTab } from '../../types/terminal.type';
|
import type { PanelSessionTabType } from '../../types/terminal.type';
|
||||||
import type { HostQueryResponse } from '@/api/asset/host';
|
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';
|
||||||
@@ -129,7 +129,7 @@
|
|||||||
defineExpose({ open });
|
defineExpose({ open });
|
||||||
|
|
||||||
// 打开终端
|
// 打开终端
|
||||||
const clickHost = (item: HostQueryResponse, tab: PanelSessionTab) => {
|
const clickHost = (item: HostQueryResponse, tab: PanelSessionTabType) => {
|
||||||
openSession(item, tab, panelIndex.value);
|
openSession(item, tab, panelIndex.value);
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -45,12 +45,27 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- 已关闭-右侧操作 -->
|
<!-- 已关闭-右侧操作 -->
|
||||||
<div v-if="closed" class="sftp-table-header-right">
|
<div v-if="session?.connected === false && closeMessage !== undefined"
|
||||||
|
class="sftp-table-header-right">
|
||||||
|
<!-- 错误信息 -->
|
||||||
<a-tag class="close-message"
|
<a-tag class="close-message"
|
||||||
color="red"
|
color="red"
|
||||||
:title="closeMessage">
|
:title="closeMessage">
|
||||||
已断开: {{ closeMessage }}
|
已断开: {{ closeMessage }}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
|
<!-- 重连 FIXME -->
|
||||||
|
<a-tooltip position="top"
|
||||||
|
:mini="true"
|
||||||
|
:overlay-inverse="true"
|
||||||
|
:auto-fix-position="false"
|
||||||
|
content-class="terminal-tooltip-content"
|
||||||
|
arrow-class="terminal-tooltip-content"
|
||||||
|
content="重连">
|
||||||
|
<span class="click-icon-wrapper header-action-icon ml8"
|
||||||
|
@click="reConnect">
|
||||||
|
<icon-refresh />
|
||||||
|
</span>
|
||||||
|
</a-tooltip>
|
||||||
</div>
|
</div>
|
||||||
<!-- 路径编辑模式-右侧操作 -->
|
<!-- 路径编辑模式-右侧操作 -->
|
||||||
<a-space v-else-if="pathEditable" class="sftp-table-header-right">
|
<a-space v-else-if="pathEditable" class="sftp-table-header-right">
|
||||||
@@ -191,16 +206,16 @@
|
|||||||
import { inject, nextTick, ref, watch } from 'vue';
|
import { inject, nextTick, ref, watch } from 'vue';
|
||||||
import { getParentPath, getPathAnalysis } from '@/utils/file';
|
import { getParentPath, getPathAnalysis } from '@/utils/file';
|
||||||
import { openSftpCreateModalKey, openSftpUploadModalKey } from '../../types/terminal.const';
|
import { openSftpCreateModalKey, openSftpUploadModalKey } from '../../types/terminal.const';
|
||||||
|
import { useTerminalStore } from '@/store';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
closed: boolean;
|
|
||||||
closeMessage?: string;
|
closeMessage?: string;
|
||||||
currentPath: string;
|
currentPath: string;
|
||||||
session?: ISftpSession;
|
session?: ISftpSession;
|
||||||
selectedFiles: Array<string>;
|
selectedFiles: Array<string>;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emits = defineEmits(['update:selectedFiles', 'loadFile', 'download']);
|
const emits = defineEmits(['update:selectedFiles', 'loadFile', 'download', 'setLoading']);
|
||||||
|
|
||||||
const showHiddenFile = ref(false);
|
const showHiddenFile = ref(false);
|
||||||
const analysisPaths = ref<Array<PathAnalysis>>([]);
|
const analysisPaths = ref<Array<PathAnalysis>>([]);
|
||||||
@@ -229,7 +244,7 @@
|
|||||||
// 设置命令编辑模式
|
// 设置命令编辑模式
|
||||||
const setPathEditable = (editable: boolean) => {
|
const setPathEditable = (editable: boolean) => {
|
||||||
// 检查是否断开
|
// 检查是否断开
|
||||||
if (editable && props.closed) {
|
if (editable && !props.session?.connected) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pathEditable.value = editable;
|
pathEditable.value = editable;
|
||||||
@@ -251,7 +266,7 @@
|
|||||||
// 加载文件列表
|
// 加载文件列表
|
||||||
const loadFileList = (path: string = props.currentPath) => {
|
const loadFileList = (path: string = props.currentPath) => {
|
||||||
// 检查是否断开
|
// 检查是否断开
|
||||||
if (props.closed) {
|
if (!props.session?.connected) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
emits('loadFile', path);
|
emits('loadFile', path);
|
||||||
@@ -284,6 +299,15 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 重新连接
|
||||||
|
const reConnect = () => {
|
||||||
|
if (props.session) {
|
||||||
|
emits('setLoading', true);
|
||||||
|
// 重新连接
|
||||||
|
useTerminalStore().reOpenSession(props.session.sessionId);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 下载文件
|
// 下载文件
|
||||||
const downloadFile = () => {
|
const downloadFile = () => {
|
||||||
emits('download', [...props.selectedFiles]);
|
emits('download', [...props.selectedFiles]);
|
||||||
|
|||||||
@@ -158,7 +158,6 @@
|
|||||||
session?: ISftpSession;
|
session?: ISftpSession;
|
||||||
list: Array<SftpFile>;
|
list: Array<SftpFile>;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
closed: boolean;
|
|
||||||
selectedFiles: Array<string>;
|
selectedFiles: Array<string>;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
@@ -214,7 +213,7 @@
|
|||||||
const clickFilename = (record: TableData) => {
|
const clickFilename = (record: TableData) => {
|
||||||
if (record.isDir) {
|
if (record.isDir) {
|
||||||
// 检查是否断开
|
// 检查是否断开
|
||||||
if (props.closed) {
|
if (!props.session?.connected) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 进入文件夹
|
// 进入文件夹
|
||||||
@@ -227,7 +226,7 @@
|
|||||||
// 编辑文件
|
// 编辑文件
|
||||||
const editFile = (record: TableData) => {
|
const editFile = (record: TableData) => {
|
||||||
// 检查是否断开
|
// 检查是否断开
|
||||||
if (props.closed) {
|
if (!props.session?.connected) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
emits('editFile', record.name, record.path);
|
emits('editFile', record.name, record.path);
|
||||||
@@ -237,7 +236,7 @@
|
|||||||
// 删除文件
|
// 删除文件
|
||||||
const deleteFile = (path: string) => {
|
const deleteFile = (path: string) => {
|
||||||
// 检查是否断开
|
// 检查是否断开
|
||||||
if (props.closed) {
|
if (!props.session?.connected) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
props.session?.remove([path]);
|
props.session?.remove([path]);
|
||||||
@@ -246,7 +245,7 @@
|
|||||||
// 下载文件
|
// 下载文件
|
||||||
const downloadFile = (path: string) => {
|
const downloadFile = (path: string) => {
|
||||||
// 检查是否断开
|
// 检查是否断开
|
||||||
if (props.closed) {
|
if (!props.session?.connected) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
emits('download', [path]);
|
emits('download', [path]);
|
||||||
@@ -255,7 +254,7 @@
|
|||||||
// 移动文件
|
// 移动文件
|
||||||
const moveFile = (path: string) => {
|
const moveFile = (path: string) => {
|
||||||
// 检查是否断开
|
// 检查是否断开
|
||||||
if (props.closed) {
|
if (!props.session?.connected) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
openSftpMoveModal(props.session?.sessionId as string, path);
|
openSftpMoveModal(props.session?.sessionId as string, path);
|
||||||
@@ -264,7 +263,7 @@
|
|||||||
// 文件提权
|
// 文件提权
|
||||||
const chmodFile = (path: string, permission: number) => {
|
const chmodFile = (path: string, permission: number) => {
|
||||||
// 检查是否断开
|
// 检查是否断开
|
||||||
if (props.closed) {
|
if (!props.session?.connected) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
openSftpChmodModal(props.session?.sessionId as string, path, permission);
|
openSftpChmodModal(props.session?.sessionId as string, path, permission);
|
||||||
|
|||||||
@@ -12,17 +12,16 @@
|
|||||||
<!-- 表头 -->
|
<!-- 表头 -->
|
||||||
<sftp-table-header class="sftp-table-header"
|
<sftp-table-header class="sftp-table-header"
|
||||||
v-model:selected-files="selectFiles"
|
v-model:selected-files="selectFiles"
|
||||||
:closed="closed"
|
|
||||||
:close-message="closeMessage"
|
:close-message="closeMessage"
|
||||||
:current-path="currentPath"
|
:current-path="currentPath"
|
||||||
:session="session"
|
:session="session"
|
||||||
@load-file="loadFiles"
|
@load-file="loadFiles"
|
||||||
@download="downloadFiles" />
|
@download="downloadFiles"
|
||||||
|
@set-loading="setTableLoading" />
|
||||||
<!-- 表格 -->
|
<!-- 表格 -->
|
||||||
<sftp-table class="sftp-table-wrapper"
|
<sftp-table class="sftp-table-wrapper"
|
||||||
v-model:selected-files="selectFiles"
|
v-model:selected-files="selectFiles"
|
||||||
:session="session"
|
:session="session"
|
||||||
:closed="closed"
|
|
||||||
:list="fileList"
|
:list="fileList"
|
||||||
:loading="tableLoading"
|
:loading="tableLoading"
|
||||||
@load-file="loadFiles"
|
@load-file="loadFiles"
|
||||||
@@ -63,7 +62,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { ISftpSession, SftpFile, TerminalTabItem } from '../../types/terminal.type';
|
import type { ISftpSession, SftpFile, TerminalPanelTabItem } from '../../types/terminal.type';
|
||||||
import { onMounted, onUnmounted, provide, ref } from 'vue';
|
import { onMounted, onUnmounted, provide, ref } from 'vue';
|
||||||
import { useTerminalStore } from '@/store';
|
import { useTerminalStore } from '@/store';
|
||||||
import { Message } from '@arco-design/web-vue';
|
import { Message } from '@arco-design/web-vue';
|
||||||
@@ -79,7 +78,7 @@
|
|||||||
import SftpUploadModal from './sftp-upload-modal.vue';
|
import SftpUploadModal from './sftp-upload-modal.vue';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
tab: TerminalTabItem;
|
tab: TerminalPanelTabItem;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const { preference, sessionManager, transferManager } = useTerminalStore();
|
const { preference, sessionManager, transferManager } = useTerminalStore();
|
||||||
@@ -91,8 +90,7 @@
|
|||||||
const fileList = ref<Array<SftpFile>>([]);
|
const fileList = ref<Array<SftpFile>>([]);
|
||||||
const selectFiles = ref<Array<string>>([]);
|
const selectFiles = ref<Array<string>>([]);
|
||||||
const splitSize = ref(1);
|
const splitSize = ref(1);
|
||||||
const closed = ref(false);
|
const closeMessage = ref<string>();
|
||||||
const closeMessage = ref('');
|
|
||||||
const editorView = ref(false);
|
const editorView = ref(false);
|
||||||
const editorRef = ref();
|
const editorRef = ref();
|
||||||
const editorFileName = ref('');
|
const editorFileName = ref('');
|
||||||
@@ -170,7 +168,8 @@
|
|||||||
|
|
||||||
// 连接成功回调
|
// 连接成功回调
|
||||||
const connectCallback = () => {
|
const connectCallback = () => {
|
||||||
loadFiles('~');
|
// FIXME TEST
|
||||||
|
loadFiles(currentPath.value || '~');
|
||||||
};
|
};
|
||||||
|
|
||||||
// 加载文件列表
|
// 加载文件列表
|
||||||
@@ -189,8 +188,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 关闭回调
|
// 关闭回调
|
||||||
const onClose = (forceClose: string, msg: string) => {
|
const onClose = (forceClose: boolean, msg: string) => {
|
||||||
closed.value = true;
|
|
||||||
closeMessage.value = msg;
|
closeMessage.value = msg;
|
||||||
setTableLoading(false);
|
setTableLoading(false);
|
||||||
setEditorLoading(false);
|
setEditorLoading(false);
|
||||||
@@ -267,7 +265,7 @@
|
|||||||
|
|
||||||
// 关闭会话
|
// 关闭会话
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
sessionManager.closeSession(props.tab.key);
|
sessionManager.closeSession(props.tab.sessionId);
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -68,7 +68,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { ISshSession, TerminalTabItem, SidebarAction } from '../../types/terminal.type';
|
import type { ISshSession, TerminalPanelTabItem, SidebarAction } from '../../types/terminal.type';
|
||||||
import { computed, onMounted, onUnmounted, ref } from 'vue';
|
import { computed, onMounted, onUnmounted, ref } from 'vue';
|
||||||
import { useDictStore, useTerminalStore } from '@/store';
|
import { useDictStore, useTerminalStore } from '@/store';
|
||||||
import { copy } from '@/hooks/copy';
|
import { copy } from '@/hooks/copy';
|
||||||
@@ -79,7 +79,7 @@
|
|||||||
import XtermSearchModal from '@/components/xtrem/search-modal/index.vue';
|
import XtermSearchModal from '@/components/xtrem/search-modal/index.vue';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
tab: TerminalTabItem;
|
tab: TerminalPanelTabItem;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const { getDictValue } = useDictStore();
|
const { getDictValue } = useDictStore();
|
||||||
@@ -137,7 +137,6 @@
|
|||||||
|
|
||||||
// 初始化会话
|
// 初始化会话
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
console.log('onMounted', props.tab.key);
|
|
||||||
// 创建终端处理器
|
// 创建终端处理器
|
||||||
session.value = await sessionManager.openSsh(props.tab, {
|
session.value = await sessionManager.openSsh(props.tab, {
|
||||||
el: terminalRef.value,
|
el: terminalRef.value,
|
||||||
@@ -148,7 +147,7 @@
|
|||||||
|
|
||||||
// 关闭会话
|
// 关闭会话
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
sessionManager.closeSession(props.tab.key);
|
sessionManager.closeSession(props.tab.sessionId);
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ export default class SftpSession implements ISftpSession {
|
|||||||
|
|
||||||
public connected: boolean;
|
public connected: boolean;
|
||||||
|
|
||||||
|
public canReconnect: boolean;
|
||||||
|
|
||||||
public resolver: ISftpSessionResolver;
|
public resolver: ISftpSessionResolver;
|
||||||
|
|
||||||
private showHiddenFile: boolean;
|
private showHiddenFile: boolean;
|
||||||
@@ -24,6 +26,7 @@ export default class SftpSession implements ISftpSession {
|
|||||||
this.sessionId = sessionId;
|
this.sessionId = sessionId;
|
||||||
this.channel = channel;
|
this.channel = channel;
|
||||||
this.connected = false;
|
this.connected = false;
|
||||||
|
this.canReconnect = false;
|
||||||
this.showHiddenFile = false;
|
this.showHiddenFile = false;
|
||||||
this.resolver = undefined as unknown as ISftpSessionResolver;
|
this.resolver = undefined as unknown as ISftpSessionResolver;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ export default class SshSession implements ISshSession {
|
|||||||
|
|
||||||
public connected: boolean;
|
public connected: boolean;
|
||||||
|
|
||||||
|
public canReconnect: boolean;
|
||||||
|
|
||||||
public canWrite: boolean;
|
public canWrite: boolean;
|
||||||
|
|
||||||
public status: number;
|
public status: number;
|
||||||
@@ -43,6 +45,7 @@ export default class SshSession implements ISshSession {
|
|||||||
this.sessionId = sessionId;
|
this.sessionId = sessionId;
|
||||||
this.channel = channel;
|
this.channel = channel;
|
||||||
this.connected = false;
|
this.connected = false;
|
||||||
|
this.canReconnect = false;
|
||||||
this.canWrite = false;
|
this.canWrite = false;
|
||||||
this.status = TerminalStatus.CONNECTING;
|
this.status = TerminalStatus.CONNECTING;
|
||||||
this.inst = undefined as unknown as Terminal;
|
this.inst = undefined as unknown as Terminal;
|
||||||
@@ -85,7 +88,6 @@ export default class SshSession implements ISshSession {
|
|||||||
if (e.type !== 'keydown') {
|
if (e.type !== 'keydown') {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
console.log(e);
|
|
||||||
// 检测是否为内置快捷键
|
// 检测是否为内置快捷键
|
||||||
if (this.handler.checkIsBuiltin(e)) {
|
if (this.handler.checkIsBuiltin(e)) {
|
||||||
return true;
|
return true;
|
||||||
@@ -94,11 +96,12 @@ export default class SshSession implements ISshSession {
|
|||||||
if (this.handler.checkPreventDefault(e)) {
|
if (this.handler.checkPreventDefault(e)) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
if (e.key === 'Enter') {
|
// 重新连接
|
||||||
console.log("enter start");
|
if (!this.connected && this.canReconnect && e.key === 'Enter') {
|
||||||
// TODO 回车 重新连接
|
setTimeout(async () => {
|
||||||
useTerminalStore().reOpenTerminal(this.hostId, this.sessionId);
|
await useTerminalStore().reOpenSession(this.sessionId);
|
||||||
console.log("enter end");
|
}, 50);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
// 自定义快捷键
|
// 自定义快捷键
|
||||||
if (preference.shortcutSetting.enabled && preference.shortcutSetting.keys.length) {
|
if (preference.shortcutSetting.enabled && preference.shortcutSetting.keys.length) {
|
||||||
|
|||||||
@@ -42,7 +42,6 @@ export default class TerminalChannel implements ITerminalChannel {
|
|||||||
|
|
||||||
// 发送消息
|
// 发送消息
|
||||||
send(protocol: Protocol, payload: InputPayload): void {
|
send(protocol: Protocol, payload: InputPayload): void {
|
||||||
console.log('send', payload);
|
|
||||||
// 检查是否连接
|
// 检查是否连接
|
||||||
if (!this.isConnected()) {
|
if (!this.isConnected()) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ export default class TerminalOutputProcessor implements ITerminalOutputProcessor
|
|||||||
processCheck({ sessionId, result, msg }: OutputPayload): void {
|
processCheck({ sessionId, result, msg }: OutputPayload): void {
|
||||||
const success = !!Number.parseInt(result);
|
const success = !!Number.parseInt(result);
|
||||||
const session = this.sessionManager.getSession(sessionId);
|
const session = this.sessionManager.getSession(sessionId);
|
||||||
|
session.canReconnect = !success;
|
||||||
if (session instanceof SshSession) {
|
if (session instanceof SshSession) {
|
||||||
// ssh 会话
|
// ssh 会话
|
||||||
if (success) {
|
if (success) {
|
||||||
@@ -35,7 +36,7 @@ export default class TerminalOutputProcessor implements ITerminalOutputProcessor
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// 未成功展示错误信息
|
// 未成功展示错误信息
|
||||||
session.write(`[91m${msg || ''}[0m`);
|
session.write(`[91m${msg || ''}\r\n输入回车重新连接...[0m\r\n\r\n`);
|
||||||
session.status = TerminalStatus.CLOSED;
|
session.status = TerminalStatus.CLOSED;
|
||||||
}
|
}
|
||||||
} else if (session instanceof SftpSession) {
|
} else if (session instanceof SftpSession) {
|
||||||
@@ -47,7 +48,7 @@ export default class TerminalOutputProcessor implements ITerminalOutputProcessor
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// 未成功提示错误信息
|
// 未成功提示错误信息
|
||||||
session.resolver?.onClose('0', msg);
|
session.resolver?.onClose(false, msg);
|
||||||
Message.error(msg || '建立 SFTP 失败');
|
Message.error(msg || '建立 SFTP 失败');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -57,6 +58,7 @@ export default class TerminalOutputProcessor implements ITerminalOutputProcessor
|
|||||||
processConnect({ sessionId, result, msg }: OutputPayload): void {
|
processConnect({ sessionId, result, msg }: OutputPayload): void {
|
||||||
const success = !!Number.parseInt(result);
|
const success = !!Number.parseInt(result);
|
||||||
const session = this.sessionManager.getSession(sessionId);
|
const session = this.sessionManager.getSession(sessionId);
|
||||||
|
session.canReconnect = !success;
|
||||||
if (session instanceof SshSession) {
|
if (session instanceof SshSession) {
|
||||||
// ssh 会话
|
// ssh 会话
|
||||||
if (success) {
|
if (success) {
|
||||||
@@ -66,7 +68,7 @@ export default class TerminalOutputProcessor implements ITerminalOutputProcessor
|
|||||||
session.connect();
|
session.connect();
|
||||||
} else {
|
} else {
|
||||||
// 未成功展示错误信息
|
// 未成功展示错误信息
|
||||||
session.write(`[91m${msg || ''}[0m`);
|
session.write(`[91m${msg || ''}\r\n输入回车重新连接...[0m\r\n\r\n`);
|
||||||
session.status = TerminalStatus.CLOSED;
|
session.status = TerminalStatus.CLOSED;
|
||||||
}
|
}
|
||||||
} else if (session instanceof SftpSession) {
|
} else if (session instanceof SftpSession) {
|
||||||
@@ -76,7 +78,7 @@ export default class TerminalOutputProcessor implements ITerminalOutputProcessor
|
|||||||
session.connect();
|
session.connect();
|
||||||
} else {
|
} else {
|
||||||
// 未成功提示错误信息
|
// 未成功提示错误信息
|
||||||
session.resolver?.onClose('0', msg);
|
session.resolver?.onClose(false, msg);
|
||||||
Message.error(msg || '打开 SFTP 失败');
|
Message.error(msg || '打开 SFTP 失败');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -89,18 +91,22 @@ export default class TerminalOutputProcessor implements ITerminalOutputProcessor
|
|||||||
if (!session) {
|
if (!session) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const isForceClose = !!Number.parseInt(forceClose);
|
||||||
|
session.connected = false;
|
||||||
|
session.canReconnect = !isForceClose;
|
||||||
if (session instanceof SshSession) {
|
if (session instanceof SshSession) {
|
||||||
// ssh 拼接关闭消息
|
// ssh 拼接关闭消息
|
||||||
session.write(`\r\n\r\n[91m${msg || ''}[0m\r\n\r\n`);
|
session.write(`\r\n\r\n[91m${msg || ''}[0m\r\n`);
|
||||||
|
if (!isForceClose) {
|
||||||
|
session.write('[91m输入回车重新连接...[0m\r\n\r\n');
|
||||||
|
}
|
||||||
// 设置状态
|
// 设置状态
|
||||||
session.status = TerminalStatus.CLOSED;
|
session.status = TerminalStatus.CLOSED;
|
||||||
session.connected = false;
|
|
||||||
// 设置不可写
|
// 设置不可写
|
||||||
session.setCanWrite(false);
|
session.setCanWrite(false);
|
||||||
} else if (session instanceof SftpSession) {
|
} else if (session instanceof SftpSession) {
|
||||||
// sftp 设置状态
|
// sftp 设置状态
|
||||||
session.connected = false;
|
session.resolver?.onClose(isForceClose, msg);
|
||||||
session.resolver?.onClose(forceClose, msg);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
import type { ITerminalPanelManager, TerminalPanelTabItem } from '../types/terminal.type';
|
import type { ITerminalPanelManager } from '../types/terminal.type';
|
||||||
import TerminalTabManager from '../handler/terminal-tab-manager';
|
import TerminalPanelTabManager from '../handler/terminal-panel-tab-manager';
|
||||||
|
|
||||||
// 终端面板管理器实现
|
// 终端面板管理器实现
|
||||||
export default class TerminalPanelManager<T extends TerminalPanelTabItem = TerminalPanelTabItem> implements ITerminalPanelManager<T> {
|
export default class TerminalPanelManager implements ITerminalPanelManager {
|
||||||
|
|
||||||
// 当前面板
|
// 当前面板
|
||||||
active: number;
|
active: number;
|
||||||
// 面板列表
|
// 面板列表
|
||||||
panels: Array<TerminalTabManager<T>>;
|
panels: Array<TerminalPanelTabManager>;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.active = 0;
|
this.active = 0;
|
||||||
this.panels = [new TerminalTabManager()];
|
this.panels = [new TerminalPanelTabManager()];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取当前面板
|
// 获取当前面板
|
||||||
getCurrentPanel(): TerminalTabManager<T> {
|
getCurrentPanel(): TerminalPanelTabManager {
|
||||||
return this.panels[this.active];
|
return this.panels[this.active];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ export default class TerminalPanelManager<T extends TerminalPanelTabItem = Termi
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 获取面板
|
// 获取面板
|
||||||
getPanel(index: number): TerminalTabManager<T> {
|
getPanel(index: number): TerminalPanelTabManager {
|
||||||
return this.panels[index];
|
return this.panels[index];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ export default class TerminalPanelManager<T extends TerminalPanelTabItem = Termi
|
|||||||
panel.clear();
|
panel.clear();
|
||||||
}
|
}
|
||||||
this.active = 0;
|
this.active = 0;
|
||||||
this.panels = [new TerminalTabManager()];
|
this.panels = [new TerminalPanelTabManager()];
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,91 @@
|
|||||||
|
import type { ITerminalTabManager, TerminalPanelTabItem } from '../types/terminal.type';
|
||||||
|
|
||||||
|
// 终端面板 tab 管理器实现
|
||||||
|
export default class TerminalPanelTabManager implements ITerminalTabManager<TerminalPanelTabItem> {
|
||||||
|
|
||||||
|
public active: string;
|
||||||
|
|
||||||
|
public items: Array<TerminalPanelTabItem>;
|
||||||
|
|
||||||
|
constructor(def: TerminalPanelTabItem | undefined = undefined) {
|
||||||
|
if (def) {
|
||||||
|
this.active = def.sessionId;
|
||||||
|
this.items = [def];
|
||||||
|
} else {
|
||||||
|
this.active = undefined as unknown as string;
|
||||||
|
this.items = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前 tab
|
||||||
|
getCurrentTab() {
|
||||||
|
if (!this.active) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return this.items.find(s => s.sessionId === this.active);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取 tab
|
||||||
|
getTab(sessionId: string): TerminalPanelTabItem {
|
||||||
|
return this.items.find(s => s.sessionId === sessionId) as TerminalPanelTabItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 点击 tab
|
||||||
|
clickTab(sessionId: string): void {
|
||||||
|
this.active = sessionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除 tab
|
||||||
|
deleteTab(sessionId: string): void {
|
||||||
|
// 获取当前 tab
|
||||||
|
const tabIndex = this.items.findIndex(s => s.sessionId === sessionId);
|
||||||
|
// 删除 tab
|
||||||
|
this.items.splice(tabIndex, 1);
|
||||||
|
if (sessionId === this.active && this.items.length !== 0) {
|
||||||
|
// 切换为前一个 tab
|
||||||
|
this.active = this.items[Math.max(tabIndex - 1, 0)].sessionId;
|
||||||
|
} else {
|
||||||
|
this.active = undefined as unknown as string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打开 tab
|
||||||
|
openTab(tab: TerminalPanelTabItem): void {
|
||||||
|
// 不存在则创建 tab
|
||||||
|
if (!this.items.find(s => s.sessionId === tab.sessionId)) {
|
||||||
|
this.items.push(tab);
|
||||||
|
}
|
||||||
|
this.active = tab.sessionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 切换到前一个 tab
|
||||||
|
changeToPrevTab() {
|
||||||
|
this.changeToIndex(this.getCurrentTabIndex() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 切换到后一个 tab
|
||||||
|
changeToNextTab() {
|
||||||
|
this.changeToIndex(this.getCurrentTabIndex() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 切换索引 tab
|
||||||
|
changeToIndex(index: number) {
|
||||||
|
if (index < 0 || index >= this.items.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 切换 tab
|
||||||
|
this.active = this.items[index].sessionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前索引
|
||||||
|
private getCurrentTabIndex(): number {
|
||||||
|
return this.items.findIndex(s => s.sessionId === this.active);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清空
|
||||||
|
clear() {
|
||||||
|
this.active = undefined as unknown as string;
|
||||||
|
this.items = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -4,10 +4,9 @@ import type {
|
|||||||
ITerminalChannel,
|
ITerminalChannel,
|
||||||
ITerminalSession,
|
ITerminalSession,
|
||||||
ITerminalSessionManager,
|
ITerminalSessionManager,
|
||||||
TerminalTabItem,
|
TerminalPanelTabItem,
|
||||||
XtermDomRef
|
XtermDomRef
|
||||||
} from '../types/terminal.type';
|
} from '../types/terminal.type';
|
||||||
import type { ISshSession } from '../types/terminal.type';
|
|
||||||
import { sleep } from '@/utils';
|
import { sleep } from '@/utils';
|
||||||
import { InputProtocol } from '../types/terminal.protocol';
|
import { InputProtocol } from '../types/terminal.protocol';
|
||||||
import { PanelSessionType } from '../types/terminal.const';
|
import { PanelSessionType } from '../types/terminal.const';
|
||||||
@@ -35,8 +34,8 @@ export default class TerminalSessionManager implements ITerminalSessionManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 打开 ssh 会话
|
// 打开 ssh 会话
|
||||||
async openSsh(tab: TerminalTabItem, domRef: XtermDomRef) {
|
async openSsh(tab: TerminalPanelTabItem, domRef: XtermDomRef) {
|
||||||
const sessionId = tab.key;
|
const sessionId = tab.sessionId;
|
||||||
const hostId = tab.hostId as number;
|
const hostId = tab.hostId as number;
|
||||||
// 初始化客户端
|
// 初始化客户端
|
||||||
await this.initChannel();
|
await this.initChannel();
|
||||||
@@ -61,28 +60,9 @@ export default class TerminalSessionManager implements ITerminalSessionManager {
|
|||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 重新打开 ssh 会话
|
|
||||||
async reOpenSsh(sessionId: string, newSessionId: string): Promise<void> {
|
|
||||||
console.log('sessionId', sessionId, 'newSessionId', newSessionId);
|
|
||||||
// 初始化客户端
|
|
||||||
await this.initChannel();
|
|
||||||
// 获取会话并且重新设置 sessionId
|
|
||||||
const session = this.sessions[sessionId] as ISshSession;
|
|
||||||
session.sessionId = newSessionId;
|
|
||||||
this.sessions[sessionId] = undefined as unknown as ISshSession;
|
|
||||||
this.sessions[newSessionId] = session;
|
|
||||||
console.log('ckckck');
|
|
||||||
// 发送会话初始化请求
|
|
||||||
this.channel.send(InputProtocol.CHECK, {
|
|
||||||
sessionId: newSessionId,
|
|
||||||
hostId: session.hostId,
|
|
||||||
connectType: PanelSessionType.SSH.type
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 打开 sftp 会话
|
// 打开 sftp 会话
|
||||||
async openSftp(tab: TerminalTabItem, resolver: ISftpSessionResolver): Promise<ISftpSession> {
|
async openSftp(tab: TerminalPanelTabItem, resolver: ISftpSessionResolver): Promise<ISftpSession> {
|
||||||
const sessionId = tab.key;
|
const sessionId = tab.sessionId;
|
||||||
const hostId = tab.hostId as number;
|
const hostId = tab.hostId as number;
|
||||||
// 初始化客户端
|
// 初始化客户端
|
||||||
await this.initChannel();
|
await this.initChannel();
|
||||||
@@ -105,6 +85,23 @@ export default class TerminalSessionManager implements ITerminalSessionManager {
|
|||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 重新打开会话
|
||||||
|
async reOpenSession(type: string, sessionId: string, newSessionId: string): Promise<void> {
|
||||||
|
// 初始化客户端
|
||||||
|
await this.initChannel();
|
||||||
|
// 获取会话并且重新设置 sessionId
|
||||||
|
const session = this.sessions[sessionId] as ITerminalSession;
|
||||||
|
session.sessionId = newSessionId;
|
||||||
|
this.sessions[sessionId] = undefined as unknown as ITerminalSession;
|
||||||
|
this.sessions[newSessionId] = session;
|
||||||
|
// 发送会话初始化请求
|
||||||
|
this.channel.send(InputProtocol.CHECK, {
|
||||||
|
sessionId: newSessionId,
|
||||||
|
hostId: session.hostId,
|
||||||
|
connectType: type,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 获取终端会话
|
// 获取终端会话
|
||||||
getSession<T>(sessionId: string): T {
|
getSession<T>(sessionId: string): T {
|
||||||
return this.sessions[sessionId] as T;
|
return this.sessions[sessionId] as T;
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import type { ITerminalTabManager, TerminalTabItem } from '../types/terminal.type';
|
import type { ITerminalTabManager, TerminalTabItem } from '../types/terminal.type';
|
||||||
|
|
||||||
// 终端 tab 管理器实现
|
// 终端 tab 管理器实现
|
||||||
export default class TerminalTabManager<T extends TerminalTabItem = TerminalTabItem> implements ITerminalTabManager<T> {
|
export default class TerminalTabManager implements ITerminalTabManager {
|
||||||
|
|
||||||
public active: string;
|
public active: string;
|
||||||
|
|
||||||
public items: Array<T>;
|
public items: Array<TerminalTabItem>;
|
||||||
|
|
||||||
constructor(def: T | undefined = undefined) {
|
constructor(def: TerminalTabItem | undefined = undefined) {
|
||||||
if (def) {
|
if (def) {
|
||||||
this.active = def.key;
|
this.active = def.key;
|
||||||
this.items = [def];
|
this.items = [def];
|
||||||
@@ -26,8 +26,8 @@ export default class TerminalTabManager<T extends TerminalTabItem = TerminalTabI
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取 tab
|
// 获取 tab
|
||||||
getTab(key: string): T {
|
getTab(key: string): TerminalTabItem {
|
||||||
return this.items.find(s => s.key === key) as T;
|
return this.items.find(s => s.key === key) as TerminalTabItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 点击 tab
|
// 点击 tab
|
||||||
@@ -50,7 +50,7 @@ export default class TerminalTabManager<T extends TerminalTabItem = TerminalTabI
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 打开 tab
|
// 打开 tab
|
||||||
openTab(tab: T): void {
|
openTab(tab: TerminalTabItem): void {
|
||||||
// 不存在则创建 tab
|
// 不存在则创建 tab
|
||||||
if (!this.items.find(s => s.key === tab.key)) {
|
if (!this.items.find(s => s.key === tab.key)) {
|
||||||
this.items.push(tab);
|
this.items.push(tab);
|
||||||
|
|||||||
@@ -34,6 +34,18 @@ export const TerminalTabs = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 面板会话 tab 类型
|
||||||
|
export const PanelSessionType = {
|
||||||
|
SSH: {
|
||||||
|
type: 'SSH',
|
||||||
|
icon: 'icon-desktop'
|
||||||
|
},
|
||||||
|
SFTP: {
|
||||||
|
type: 'SFTP',
|
||||||
|
icon: 'icon-folder'
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
// 新建连接类型
|
// 新建连接类型
|
||||||
export const NewConnectionType = {
|
export const NewConnectionType = {
|
||||||
GROUP: 'group',
|
GROUP: 'group',
|
||||||
@@ -97,18 +109,6 @@ export const FILE_TYPE = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 面板会话 tab 类型
|
|
||||||
export const PanelSessionType = {
|
|
||||||
SSH: {
|
|
||||||
type: 'SSH',
|
|
||||||
icon: 'icon-desktop'
|
|
||||||
},
|
|
||||||
SFTP: {
|
|
||||||
type: 'SFTP',
|
|
||||||
icon: 'icon-folder'
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// 终端状态
|
// 终端状态
|
||||||
export const TerminalStatus = {
|
export const TerminalStatus = {
|
||||||
// 连接中
|
// 连接中
|
||||||
|
|||||||
@@ -19,10 +19,11 @@ export interface TerminalTabItem {
|
|||||||
|
|
||||||
// 终端面板 tab 元素
|
// 终端面板 tab 元素
|
||||||
export interface TerminalPanelTabItem extends TerminalTabItem {
|
export interface TerminalPanelTabItem extends TerminalTabItem {
|
||||||
|
type: string;
|
||||||
|
sessionId: string;
|
||||||
seq: number;
|
seq: number;
|
||||||
hostId: number;
|
hostId: number;
|
||||||
address: string;
|
address: string;
|
||||||
type: string;
|
|
||||||
color?: string;
|
color?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +75,7 @@ export interface LabelExtraSettingModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// session tab
|
// session tab
|
||||||
export interface PanelSessionTab {
|
export interface PanelSessionTabType {
|
||||||
type: string;
|
type: string;
|
||||||
icon: string;
|
icon: string;
|
||||||
}
|
}
|
||||||
@@ -131,18 +132,18 @@ export interface ITerminalTabManager<T extends TerminalTabItem = TerminalTabItem
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 终端面板管理器定义
|
// 终端面板管理器定义
|
||||||
export interface ITerminalPanelManager<T extends TerminalPanelTabItem = TerminalPanelTabItem> {
|
export interface ITerminalPanelManager {
|
||||||
// 当前面板
|
// 当前面板
|
||||||
active: number;
|
active: number;
|
||||||
// 面板列表
|
// 面板列表
|
||||||
panels: Array<ITerminalTabManager<T>>;
|
panels: Array<ITerminalTabManager<TerminalPanelTabItem>>;
|
||||||
|
|
||||||
// 获取当前面板
|
// 获取当前面板
|
||||||
getCurrentPanel: () => ITerminalTabManager<T>;
|
getCurrentPanel: () => ITerminalTabManager<TerminalPanelTabItem>;
|
||||||
// 设置当前面板
|
// 设置当前面板
|
||||||
setCurrentPanel: (active: number) => void;
|
setCurrentPanel: (active: number) => void;
|
||||||
// 获取面板
|
// 获取面板
|
||||||
getPanel: (index: number) => ITerminalTabManager<T>;
|
getPanel: (index: number) => ITerminalTabManager<TerminalPanelTabItem>;
|
||||||
// 移除面板
|
// 移除面板
|
||||||
removePanel: (index: number) => void;
|
removePanel: (index: number) => void;
|
||||||
// 重置
|
// 重置
|
||||||
@@ -152,11 +153,11 @@ export interface ITerminalPanelManager<T extends TerminalPanelTabItem = Terminal
|
|||||||
// 终端会话管理器定义
|
// 终端会话管理器定义
|
||||||
export interface ITerminalSessionManager {
|
export interface ITerminalSessionManager {
|
||||||
// 打开 ssh 会话
|
// 打开 ssh 会话
|
||||||
openSsh: (tab: TerminalTabItem, domRef: XtermDomRef) => Promise<ISshSession>;
|
openSsh: (tab: TerminalPanelTabItem, domRef: XtermDomRef) => Promise<ISshSession>;
|
||||||
// 重新打开 ssh 会话
|
|
||||||
reOpenSsh: (sessionId: string, newSessionId: string) => Promise<void>;
|
|
||||||
// 打开 sftp 会话
|
// 打开 sftp 会话
|
||||||
openSftp: (tab: TerminalTabItem, resolver: ISftpSessionResolver) => Promise<ISftpSession>;
|
openSftp: (tab: TerminalPanelTabItem, resolver: ISftpSessionResolver) => Promise<ISftpSession>;
|
||||||
|
// 重新打开会话
|
||||||
|
reOpenSession: (type: string, sessionId: string, newSessionId: string) => Promise<void>;
|
||||||
// 获取终端会话
|
// 获取终端会话
|
||||||
getSession: <T extends ITerminalSession>(sessionId: string) => T;
|
getSession: <T extends ITerminalSession>(sessionId: string) => T;
|
||||||
// 关闭终端会话
|
// 关闭终端会话
|
||||||
@@ -232,6 +233,8 @@ export interface ITerminalSession {
|
|||||||
sessionId: string;
|
sessionId: string;
|
||||||
// 是否已连接
|
// 是否已连接
|
||||||
connected: boolean;
|
connected: boolean;
|
||||||
|
// 是否可以重新连接
|
||||||
|
canReconnect: boolean;
|
||||||
|
|
||||||
// 连接
|
// 连接
|
||||||
connect: () => void;
|
connect: () => void;
|
||||||
@@ -355,7 +358,7 @@ export interface ISftpSessionResolver {
|
|||||||
// 连接后回调
|
// 连接后回调
|
||||||
connectCallback: () => void;
|
connectCallback: () => void;
|
||||||
// 关闭回调
|
// 关闭回调
|
||||||
onClose: (forceClose: string, msg: string) => void;
|
onClose: (forceClose: boolean, msg: string) => void;
|
||||||
// 接受文件列表响应
|
// 接受文件列表响应
|
||||||
resolveList: (result: string, path: string, list: Array<SftpFile>) => void;
|
resolveList: (result: string, path: string, list: Array<SftpFile>) => void;
|
||||||
// 接收创建文件夹响应
|
// 接收创建文件夹响应
|
||||||
|
|||||||
Reference in New Issue
Block a user