🔨 添加 sftp 会话类型.
This commit is contained in:
@@ -8,7 +8,7 @@ import type {
|
||||
TerminalShortcutSetting,
|
||||
TerminalState
|
||||
} from './types';
|
||||
import type { PanelSessionTab, TerminalPanelTabItem } from '@/views/host/terminal/types/terminal.type';
|
||||
import type { ISshSession, PanelSessionTab, TerminalPanelTabItem } from '@/views/host/terminal/types/terminal.type';
|
||||
import type { AuthorizedHostQueryResponse } from '@/api/asset/asset-authorized-data';
|
||||
import { getCurrentAuthorizedHost } from '@/api/asset/asset-authorized-data';
|
||||
import type { HostQueryResponse } from '@/api/asset/host';
|
||||
@@ -64,7 +64,8 @@ export default defineStore('terminal', {
|
||||
} as TerminalShortcutSetting,
|
||||
},
|
||||
hosts: {} as AuthorizedHostQueryResponse,
|
||||
tabManager: new TerminalTabManager(TerminalTabs.NEW_CONNECTION),
|
||||
// fixme
|
||||
tabManager: new TerminalTabManager(TerminalTabs.TERMINAL_PANEL),
|
||||
panelManager: new TerminalPanelManager(),
|
||||
sessionManager: new TerminalSessionManager()
|
||||
}),
|
||||
@@ -173,8 +174,8 @@ export default defineStore('terminal', {
|
||||
}
|
||||
},
|
||||
|
||||
// 检查当前是否为终端页面 并且获取当前终端会话
|
||||
getAndCheckCurrentTerminalSession(tips: boolean = true) {
|
||||
// 检查当前是否为终端页面 并且获取当前 ssh 会话
|
||||
getAndCheckCurrentSshSession(tips: boolean = true) {
|
||||
// 获取当前 activeTab
|
||||
const activeTab = this.tabManager.active;
|
||||
if (activeTab !== TerminalTabs.TERMINAL_PANEL.key) {
|
||||
@@ -184,15 +185,15 @@ export default defineStore('terminal', {
|
||||
return;
|
||||
}
|
||||
// 获取当前会话
|
||||
const session = this.getCurrentTerminalSession();
|
||||
const session = this.getCurrentSshSession();
|
||||
if (!session && tips) {
|
||||
Message.warning('请打开终端');
|
||||
}
|
||||
return session;
|
||||
},
|
||||
|
||||
// 获取当前终端会话
|
||||
getCurrentTerminalSession() {
|
||||
// 获取当前 ssh 会话
|
||||
getCurrentSshSession() {
|
||||
// 获取面板会话
|
||||
const sessionTab = this.panelManager
|
||||
.getCurrentPanel()
|
||||
@@ -201,7 +202,7 @@ export default defineStore('terminal', {
|
||||
return;
|
||||
}
|
||||
// 获取会话
|
||||
return this.sessionManager.getSession(sessionTab.key);
|
||||
return this.sessionManager.getSession<ISshSession>(sessionTab.key);
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
|
||||
const { loading, setLoading } = useLoading();
|
||||
const { visible, setVisible } = useVisible();
|
||||
const { getCurrentTerminalSession } = useTerminalStore();
|
||||
const { getCurrentSshSession } = useTerminalStore();
|
||||
const cacheStore = useCacheStore();
|
||||
|
||||
const formDrawer = ref();
|
||||
@@ -267,7 +267,7 @@
|
||||
// 关闭回调
|
||||
const onClose = () => {
|
||||
// 聚焦终端
|
||||
getCurrentTerminalSession()?.focus();
|
||||
getCurrentSshSession()?.focus();
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
@@ -125,7 +125,7 @@
|
||||
}>();
|
||||
|
||||
const { copy } = useCopy();
|
||||
const { getAndCheckCurrentTerminalSession } = useTerminalStore();
|
||||
const { getAndCheckCurrentSshSession } = useTerminalStore();
|
||||
|
||||
let clickCount = 0;
|
||||
|
||||
@@ -184,7 +184,7 @@
|
||||
|
||||
// 写入命令
|
||||
const write = (command: string) => {
|
||||
const handler = getAndCheckCurrentTerminalSession()?.handler;
|
||||
const handler = getAndCheckCurrentSshSession()?.handler;
|
||||
if (handler && handler.enabledStatus('checkAppendMissing')) {
|
||||
handler.checkAppendMissing(command);
|
||||
}
|
||||
|
||||
@@ -45,17 +45,17 @@
|
||||
import TerminalShortcutSetting from '../setting/shortcut/terminal-shortcut-setting.vue';
|
||||
import TerminalPanelsView from '@/views/host/terminal/components/layout/terminal-panels-view.vue';
|
||||
|
||||
const { preference, tabManager, getCurrentTerminalSession } = useTerminalStore();
|
||||
const { preference, tabManager, getCurrentSshSession } = useTerminalStore();
|
||||
|
||||
// 监听 tab 切换
|
||||
watch(() => tabManager.active, (active, before) => {
|
||||
// 失焦 tab
|
||||
if (before === TerminalTabs.TERMINAL_PANEL.key) {
|
||||
getCurrentTerminalSession()?.blur();
|
||||
getCurrentSshSession()?.blur();
|
||||
}
|
||||
// 聚焦 tab
|
||||
if (active === TerminalTabs.TERMINAL_PANEL.key) {
|
||||
getCurrentTerminalSession()?.focus();
|
||||
getCurrentSshSession()?.focus();
|
||||
}
|
||||
// 修改标题
|
||||
document.title = Object.values(TerminalTabs)
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
const emits = defineEmits(['openTransfer']);
|
||||
|
||||
const { getAndCheckCurrentTerminalSession } = useTerminalStore();
|
||||
const { getAndCheckCurrentSshSession } = useTerminalStore();
|
||||
|
||||
const snippetRef = ref();
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
|
||||
// 终端截屏
|
||||
const screenshot = () => {
|
||||
const handler = getAndCheckCurrentTerminalSession()?.handler;
|
||||
const handler = getAndCheckCurrentSshSession()?.handler;
|
||||
if (handler && handler.enabledStatus('screenshot')) {
|
||||
handler.screenshot();
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { ITerminalTabManager, TerminalPanelTabItem } from '../../types/terminal.type';
|
||||
import type { ISshSession, ITerminalTabManager, TerminalPanelTabItem } from '../../types/terminal.type';
|
||||
import { watch } from 'vue';
|
||||
import { useTerminalStore } from '@/store';
|
||||
import { PanelSessionType } from '../../types/terminal.const';
|
||||
@@ -66,14 +66,14 @@
|
||||
if (before) {
|
||||
const beforeTab = props.panel.items.find(s => s.key === before);
|
||||
if (beforeTab && beforeTab?.type === PanelSessionType.SSH.type) {
|
||||
sessionManager.getSession(before)?.blur();
|
||||
sessionManager.getSession<ISshSession>(before)?.blur();
|
||||
}
|
||||
}
|
||||
// 终端自动聚焦
|
||||
if (active) {
|
||||
const activeTab = props.panel.items.find(s => s.key === active);
|
||||
if (activeTab && activeTab?.type === PanelSessionType.SSH.type) {
|
||||
sessionManager.getSession(active)?.focus();
|
||||
sessionManager.getSession<ISshSession>(active)?.focus();
|
||||
}
|
||||
}
|
||||
// 无终端自动关闭
|
||||
@@ -214,12 +214,13 @@
|
||||
}
|
||||
|
||||
.arco-tabs-tab-title {
|
||||
padding: 11px 18px 11px 14px;
|
||||
padding: 11px 18px 7px 14px;
|
||||
background: var(--color-bg-panel-tabs);
|
||||
font-size: 14px;
|
||||
height: var(--panel-nav-height);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom: 4px transparent solid;
|
||||
|
||||
&::before {
|
||||
display: none;
|
||||
|
||||
@@ -31,12 +31,12 @@
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { ContextMenuItem, ITerminalSession } from '../../types/terminal.type';
|
||||
import type { ContextMenuItem, ISshSession } from '../../types/terminal.type';
|
||||
import { ActionBarItems } from '../../types/terminal.const';
|
||||
import { useTerminalStore } from '@/store';
|
||||
|
||||
defineProps<{
|
||||
session: ITerminalSession | undefined
|
||||
session: ISshSession | undefined
|
||||
}>();
|
||||
|
||||
const emits = defineEmits(['click']);
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { ITerminalSession, TerminalTabItem, SidebarAction } from '../../types/terminal.type';
|
||||
import type { ISshSession, TerminalTabItem, SidebarAction } from '../../types/terminal.type';
|
||||
import { computed, onMounted, onUnmounted, ref } from 'vue';
|
||||
import { useDictStore, useTerminalStore } from '@/store';
|
||||
import useCopy from '@/hooks/copy';
|
||||
@@ -89,7 +89,7 @@
|
||||
const searchModal = ref();
|
||||
const commandInput = ref();
|
||||
const terminalRef = ref();
|
||||
const session = ref<ITerminalSession>();
|
||||
const session = ref<ISshSession>();
|
||||
|
||||
// 发送命令
|
||||
const writeCommandInput = async (e: KeyboardEvent) => {
|
||||
@@ -138,7 +138,7 @@
|
||||
// 初始化会话
|
||||
onMounted(async () => {
|
||||
// 创建终端处理器
|
||||
session.value = await sessionManager.openSession(props.tab, {
|
||||
session.value = await sessionManager.openSsh(props.tab, {
|
||||
el: terminalRef.value,
|
||||
editorModal: editorModal.value,
|
||||
searchModal: searchModal.value
|
||||
|
||||
41
orion-ops-ui/src/views/host/terminal/handler/sftp-session.ts
Normal file
41
orion-ops-ui/src/views/host/terminal/handler/sftp-session.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import type { ISftpSession, ITerminalChannel } from '../types/terminal.type';
|
||||
import { InputProtocol } from '../types/terminal.protocol';
|
||||
|
||||
// sftp 会话实现
|
||||
export default class SftpSession implements ISftpSession {
|
||||
|
||||
public readonly hostId: number;
|
||||
|
||||
public sessionId: string;
|
||||
|
||||
public connected: boolean;
|
||||
|
||||
private readonly channel: ITerminalChannel;
|
||||
|
||||
constructor(hostId: number,
|
||||
sessionId: string,
|
||||
channel: ITerminalChannel) {
|
||||
this.hostId = hostId;
|
||||
this.sessionId = sessionId;
|
||||
this.channel = channel;
|
||||
this.connected = false;
|
||||
}
|
||||
|
||||
// 设置已连接
|
||||
connect(): void {
|
||||
this.connected = true;
|
||||
}
|
||||
|
||||
// 断开连接
|
||||
disconnect(): void {
|
||||
// 发送关闭消息
|
||||
this.channel.send(InputProtocol.CLOSE, {
|
||||
sessionId: this.sessionId
|
||||
});
|
||||
}
|
||||
|
||||
// 关闭
|
||||
close(): void {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { ShortcutKey, TerminalInteractSetting, TerminalShortcutKey } from '@/store/modules/terminal/types';
|
||||
import type { ITerminalSession, ITerminalSessionHandler, TerminalDomRef } from '../types/terminal.type';
|
||||
import type { ISshSession, ISshSessionHandler, XtermDomRef } from '../types/terminal.type';
|
||||
import type { Terminal } from 'xterm';
|
||||
import useCopy from '@/hooks/copy';
|
||||
import html2canvas from 'html2canvas';
|
||||
@@ -31,21 +31,21 @@ const preventKeys: Array<ShortcutKey> = [
|
||||
|
||||
const { copy: copyValue, readText } = useCopy();
|
||||
|
||||
// 终端会话处理器实现
|
||||
export default class TerminalSessionHandler implements ITerminalSessionHandler {
|
||||
// ssh 会话处理器实现
|
||||
export default class SshSessionHandler implements ISshSessionHandler {
|
||||
|
||||
private readonly domRef: TerminalDomRef;
|
||||
private readonly domRef: XtermDomRef;
|
||||
|
||||
private readonly inst: Terminal;
|
||||
|
||||
private readonly session: ITerminalSession;
|
||||
private readonly session: ISshSession;
|
||||
|
||||
private readonly interactSetting: TerminalInteractSetting;
|
||||
|
||||
private readonly shortcutKeys: Array<TerminalShortcutKey>;
|
||||
|
||||
constructor(session: ITerminalSession,
|
||||
domRef: TerminalDomRef) {
|
||||
constructor(session: ISshSession,
|
||||
domRef: XtermDomRef) {
|
||||
this.session = session;
|
||||
this.inst = session.inst;
|
||||
this.domRef = domRef;
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { UnwrapRef } from 'vue';
|
||||
import type { TerminalPreference } from '@/store/modules/terminal/types';
|
||||
import type { ITerminalChannel, ITerminalSession, ITerminalSessionHandler, TerminalAddons, TerminalDomRef } from '../types/terminal.type';
|
||||
import type { ISshSession, ISshSessionHandler, ITerminalChannel, XtermAddons, XtermDomRef } from '../types/terminal.type';
|
||||
import { useTerminalStore } from '@/store';
|
||||
import { InputProtocol } from '../types/terminal.protocol';
|
||||
import { fontFamilySuffix, TerminalShortcutType, TerminalStatus } from '../types/terminal.const';
|
||||
@@ -13,10 +13,10 @@ import { CanvasAddon } from 'xterm-addon-canvas';
|
||||
import { WebglAddon } from 'xterm-addon-webgl';
|
||||
import { playBell } from '@/utils/bell';
|
||||
import { addEventListen } from '@/utils/event';
|
||||
import TerminalSessionHandler from './terminal-session-handler';
|
||||
import SshSessionHandler from './ssh-session-handler';
|
||||
|
||||
// 终端会话实现
|
||||
export default class TerminalSession implements ITerminalSession {
|
||||
// ssh 会话实现
|
||||
export default class SshSession implements ISshSession {
|
||||
|
||||
public readonly hostId: number;
|
||||
|
||||
@@ -30,11 +30,11 @@ export default class TerminalSession implements ITerminalSession {
|
||||
|
||||
public status: number;
|
||||
|
||||
public handler: ITerminalSessionHandler;
|
||||
public handler: ISshSessionHandler;
|
||||
|
||||
private readonly channel: ITerminalChannel;
|
||||
|
||||
private readonly addons: TerminalAddons;
|
||||
private readonly addons: XtermAddons;
|
||||
|
||||
constructor(hostId: number,
|
||||
sessionId: string,
|
||||
@@ -46,12 +46,12 @@ export default class TerminalSession implements ITerminalSession {
|
||||
this.canWrite = false;
|
||||
this.status = TerminalStatus.CONNECTING;
|
||||
this.inst = undefined as unknown as Terminal;
|
||||
this.handler = undefined as unknown as ITerminalSessionHandler;
|
||||
this.addons = {} as TerminalAddons;
|
||||
this.handler = undefined as unknown as ISshSessionHandler;
|
||||
this.addons = {} as XtermAddons;
|
||||
}
|
||||
|
||||
// 初始化
|
||||
init(domRef: TerminalDomRef): void {
|
||||
init(domRef: XtermDomRef): void {
|
||||
const { preference } = useTerminalStore();
|
||||
// 初始化实例
|
||||
this.inst = new Terminal({
|
||||
@@ -65,7 +65,7 @@ export default class TerminalSession implements ITerminalSession {
|
||||
scrollback: preference.sessionSetting.scrollBackLine,
|
||||
});
|
||||
// 处理器
|
||||
this.handler = new TerminalSessionHandler(this, domRef);
|
||||
this.handler = new SshSessionHandler(this, domRef);
|
||||
// 注册快捷键
|
||||
this.registerShortcut(preference);
|
||||
// 注册事件
|
||||
@@ -1,7 +1,10 @@
|
||||
import { ITerminalChannel, ITerminalOutputProcessor, ITerminalSessionManager, OutputPayload } from '../types/terminal.type';
|
||||
import { ISshSession, ITerminalChannel, ITerminalOutputProcessor, ITerminalSessionManager, OutputPayload } from '../types/terminal.type';
|
||||
import { InputProtocol } from '../types/terminal.protocol';
|
||||
import { TerminalStatus } from '../types/terminal.const';
|
||||
import { useTerminalStore } from '@/store';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import SshSession from './ssh-session';
|
||||
import SftpSession from './sftp-session';
|
||||
|
||||
// 终端输出消息体处理器实现
|
||||
export default class TerminalOutputProcessor implements ITerminalOutputProcessor {
|
||||
@@ -19,50 +22,81 @@ export default class TerminalOutputProcessor implements ITerminalOutputProcessor
|
||||
processCheck({ sessionId, result, msg }: OutputPayload): void {
|
||||
const success = !!Number.parseInt(result);
|
||||
const session = this.sessionManager.getSession(sessionId);
|
||||
// 未成功展示错误信息
|
||||
if (!success) {
|
||||
session.write(`[91m${msg || ''}[0m`);
|
||||
session.status = TerminalStatus.CLOSED;
|
||||
return;
|
||||
if (session instanceof SshSession) {
|
||||
// ssh 会话
|
||||
if (success) {
|
||||
// 检查成功发送 connect 命令
|
||||
const { preference } = useTerminalStore();
|
||||
this.channel.send(InputProtocol.CONNECT, {
|
||||
sessionId,
|
||||
terminalType: preference.sessionSetting.terminalEmulationType || 'xterm',
|
||||
cols: session.inst.cols,
|
||||
rows: session.inst.rows
|
||||
});
|
||||
} else {
|
||||
// 未成功展示错误信息
|
||||
session.write(`[91m${msg || ''}[0m`);
|
||||
session.status = TerminalStatus.CLOSED;
|
||||
}
|
||||
} else if (session instanceof SftpSession) {
|
||||
// sftp 会话
|
||||
if (success) {
|
||||
// 检查成功发送 connect 命令
|
||||
// TODO
|
||||
|
||||
} else {
|
||||
// 未成功提示错误信息
|
||||
Message.error(msg || '建立 SFTP 失败');
|
||||
}
|
||||
}
|
||||
const { preference } = useTerminalStore();
|
||||
// 发送 connect 命令
|
||||
this.channel.send(InputProtocol.CONNECT, {
|
||||
sessionId,
|
||||
terminalType: preference.sessionSetting.terminalEmulationType || 'xterm',
|
||||
cols: session.inst.cols,
|
||||
rows: session.inst.rows
|
||||
});
|
||||
}
|
||||
|
||||
// 处理连接消息
|
||||
processConnect({ sessionId, result, msg }: OutputPayload): void {
|
||||
const success = !!Number.parseInt(result);
|
||||
const session = this.sessionManager.getSession(sessionId);
|
||||
// 未成功展示错误信息
|
||||
if (!success) {
|
||||
session.write(`[91m${msg || ''}[0m`);
|
||||
session.status = TerminalStatus.CLOSED;
|
||||
return;
|
||||
if (session instanceof SshSession) {
|
||||
// ssh 会话
|
||||
if (success) {
|
||||
// 设置可写
|
||||
session.setCanWrite(true);
|
||||
// 执行连接逻辑
|
||||
session.connect();
|
||||
} else {
|
||||
// 未成功展示错误信息
|
||||
session.write(`[91m${msg || ''}[0m`);
|
||||
session.status = TerminalStatus.CLOSED;
|
||||
}
|
||||
} else if (session instanceof SftpSession) {
|
||||
// sftp 会话
|
||||
if (success) {
|
||||
// 执行连接逻辑
|
||||
session.connect();
|
||||
} else {
|
||||
// 未成功提示错误信息
|
||||
Message.error(msg || '打开 SFTP 失败');
|
||||
}
|
||||
}
|
||||
// 设置可写
|
||||
session.setCanWrite(true);
|
||||
// 执行连接逻辑
|
||||
session.connect();
|
||||
}
|
||||
|
||||
// 处理关闭消息
|
||||
processClose({ sessionId, msg }: OutputPayload): void {
|
||||
const session = this.sessionManager.getSession(sessionId);
|
||||
// 关闭 tab 则无需处理
|
||||
if (session) {
|
||||
// 提示消息
|
||||
// 无需处理 (直接关闭 tab )
|
||||
if (!session) {
|
||||
return;
|
||||
}
|
||||
if (session instanceof SshSession) {
|
||||
// ssh 拼接关闭消息
|
||||
session.write(`\r\n[91m${msg || ''}[0m`);
|
||||
// 设置状态
|
||||
session.status = TerminalStatus.CLOSED;
|
||||
session.connected = false;
|
||||
// 设置不可写
|
||||
session.setCanWrite(false);
|
||||
} else if (session instanceof SftpSession) {
|
||||
// sftp 设置状态
|
||||
session.connected = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +107,7 @@ export default class TerminalOutputProcessor implements ITerminalOutputProcessor
|
||||
|
||||
// 处理输出消息
|
||||
processOutput({ sessionId, body }: OutputPayload): void {
|
||||
const session = this.sessionManager.getSession(sessionId);
|
||||
const session = this.sessionManager.getSession<ISshSession>(sessionId);
|
||||
session && session.write(body);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import type { ITerminalChannel, ITerminalSession, ITerminalSessionManager, TerminalDomRef, TerminalTabItem } from '../types/terminal.type';
|
||||
import type { ISftpSession, ITerminalChannel, ITerminalSession, ITerminalSessionManager, TerminalTabItem, XtermDomRef } from '../types/terminal.type';
|
||||
import { sleep } from '@/utils';
|
||||
import { InputProtocol } from '../types/terminal.protocol';
|
||||
import { PanelSessionType } from '../types/terminal.const';
|
||||
import { useDebounceFn } from '@vueuse/core';
|
||||
import { addEventListen, removeEventListen } from '@/utils/event';
|
||||
import TerminalSession from './terminal-session';
|
||||
import TerminalChannel from './terminal-channel';
|
||||
import SshSession from './ssh-session';
|
||||
import SftpSession from './sftp-session';
|
||||
|
||||
// 终端会话管理器实现
|
||||
export default class TerminalSessionManager implements ITerminalSessionManager {
|
||||
@@ -23,15 +25,15 @@ export default class TerminalSessionManager implements ITerminalSessionManager {
|
||||
this.dispatchResizeFn = useDebounceFn(this.dispatchResize).bind(this);
|
||||
}
|
||||
|
||||
// 打开终端会话
|
||||
async openSession(tab: TerminalTabItem,
|
||||
domRef: TerminalDomRef) {
|
||||
// 打开 ssh 会话
|
||||
async openSsh(tab: TerminalTabItem,
|
||||
domRef: XtermDomRef) {
|
||||
const sessionId = tab.key;
|
||||
const hostId = tab.hostId as number;
|
||||
// 初始化客户端
|
||||
await this.initChannel();
|
||||
// 新建会话
|
||||
const session = new TerminalSession(
|
||||
const session = new SshSession(
|
||||
hostId,
|
||||
sessionId,
|
||||
this.channel
|
||||
@@ -46,14 +48,37 @@ export default class TerminalSessionManager implements ITerminalSessionManager {
|
||||
this.channel.send(InputProtocol.CHECK, {
|
||||
sessionId,
|
||||
hostId,
|
||||
connectType: 'SSH'
|
||||
connectType: PanelSessionType.SSH.type
|
||||
});
|
||||
return session;
|
||||
}
|
||||
|
||||
// 打开 sftp 会话
|
||||
async openSftp(tab: TerminalTabItem): Promise<ISftpSession> {
|
||||
const sessionId = tab.key;
|
||||
const hostId = tab.hostId as number;
|
||||
// 初始化客户端
|
||||
await this.initChannel();
|
||||
// 新建会话
|
||||
const session = new SftpSession(
|
||||
hostId,
|
||||
sessionId,
|
||||
this.channel
|
||||
);
|
||||
// 添加会话
|
||||
this.sessions[sessionId] = session;
|
||||
// 发送会话初始化请求
|
||||
this.channel.send(InputProtocol.CHECK, {
|
||||
sessionId,
|
||||
hostId,
|
||||
connectType: PanelSessionType.SFTP.type
|
||||
});
|
||||
return session;
|
||||
}
|
||||
|
||||
// 获取终端会话
|
||||
getSession(sessionId: string): ITerminalSession {
|
||||
return this.sessions[sessionId];
|
||||
getSession<T>(sessionId: string): T {
|
||||
return this.sessions[sessionId] as T;
|
||||
}
|
||||
|
||||
// 关闭终端会话
|
||||
@@ -64,7 +89,7 @@ export default class TerminalSessionManager implements ITerminalSessionManager {
|
||||
}
|
||||
// 关闭连接
|
||||
session.disconnect();
|
||||
// 关闭 session
|
||||
// 关闭会话
|
||||
session.close();
|
||||
// 移除 session
|
||||
this.sessions[sessionId] = undefined as unknown as ITerminalSession;
|
||||
@@ -94,6 +119,8 @@ export default class TerminalSessionManager implements ITerminalSessionManager {
|
||||
private dispatchResize() {
|
||||
// 对所有已连接的会话重置大小
|
||||
Object.values(this.sessions)
|
||||
.filter(s => s instanceof SshSession)
|
||||
.map(s => s as SshSession)
|
||||
.filter(h => h.connected)
|
||||
.forEach(h => h.fit());
|
||||
}
|
||||
|
||||
@@ -96,13 +96,6 @@ export interface OutputPayload {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
// 终端 dom 元素引用
|
||||
export interface TerminalDomRef {
|
||||
el: HTMLElement;
|
||||
searchModal: any;
|
||||
editorModal: any;
|
||||
}
|
||||
|
||||
// 终端 tab 管理器定义
|
||||
export interface ITerminalTabManager<T extends TerminalTabItem = TerminalTabItem> {
|
||||
// 当前 tab
|
||||
@@ -149,10 +142,12 @@ export interface ITerminalPanelManager<T extends TerminalPanelTabItem = Terminal
|
||||
|
||||
// 终端会话管理器定义
|
||||
export interface ITerminalSessionManager {
|
||||
// 打开终端会话
|
||||
openSession: (tab: TerminalTabItem, domRef: TerminalDomRef) => Promise<ITerminalSession>;
|
||||
// 打开 ssh 会话
|
||||
openSsh: (tab: TerminalTabItem, domRef: XtermDomRef) => Promise<ISshSession>;
|
||||
// 打开 sftp 会话
|
||||
openSftp: (tab: TerminalTabItem) => Promise<ISftpSession>;
|
||||
// 获取终端会话
|
||||
getSession: (sessionId: string) => ITerminalSession;
|
||||
getSession: <T extends ITerminalSession>(sessionId: string) => T;
|
||||
// 关闭终端会话
|
||||
closeSession: (sessionId: string) => void;
|
||||
// 重置
|
||||
@@ -185,8 +180,15 @@ export interface ITerminalOutputProcessor {
|
||||
processOutput: (payload: OutputPayload) => void;
|
||||
}
|
||||
|
||||
// 终端 dom 元素引用
|
||||
export interface XtermDomRef {
|
||||
el: HTMLElement;
|
||||
searchModal: any;
|
||||
editorModal: any;
|
||||
}
|
||||
|
||||
// 终端插件
|
||||
export interface TerminalAddons {
|
||||
export interface XtermAddons {
|
||||
fit: FitAddon;
|
||||
webgl: WebglAddon;
|
||||
canvas: CanvasAddon;
|
||||
@@ -199,21 +201,30 @@ export interface TerminalAddons {
|
||||
export interface ITerminalSession {
|
||||
hostId: number;
|
||||
sessionId: string;
|
||||
// terminal 实例
|
||||
inst: Terminal;
|
||||
// 是否已连接
|
||||
connected: boolean;
|
||||
|
||||
// 连接
|
||||
connect: () => void;
|
||||
// 断开连接
|
||||
disconnect: () => void;
|
||||
// 关闭
|
||||
close: () => void;
|
||||
}
|
||||
|
||||
// ssh 会话定义
|
||||
export interface ISshSession extends ITerminalSession {
|
||||
// terminal 实例
|
||||
inst: Terminal;
|
||||
// 是否可写
|
||||
canWrite: boolean;
|
||||
// 状态
|
||||
status: number;
|
||||
// 处理器
|
||||
handler: ITerminalSessionHandler;
|
||||
handler: ISshSessionHandler;
|
||||
|
||||
// 初始化
|
||||
init: (domRef: TerminalDomRef) => void;
|
||||
// 连接
|
||||
connect: () => void;
|
||||
init: (domRef: XtermDomRef) => void;
|
||||
// 设置是否可写
|
||||
setCanWrite: (canWrite: boolean) => void;
|
||||
// 写入数据
|
||||
@@ -226,14 +237,10 @@ export interface ITerminalSession {
|
||||
fit: () => void;
|
||||
// 查找
|
||||
find: (word: string, next: boolean, options: ISearchOptions) => void;
|
||||
// 断开连接
|
||||
disconnect: () => void;
|
||||
// 关闭
|
||||
close: () => void;
|
||||
}
|
||||
|
||||
// 终端会话处理器定义
|
||||
export interface ITerminalSessionHandler {
|
||||
// ssh 会话处理器定义
|
||||
export interface ISshSessionHandler {
|
||||
// 检测是否忽略默认行为
|
||||
checkPreventDefault: (e: KeyboardEvent) => boolean;
|
||||
// 启用状态
|
||||
@@ -278,3 +285,8 @@ export interface ITerminalSessionHandler {
|
||||
// 检查追加缺失的部分
|
||||
checkAppendMissing: (value: string) => void;
|
||||
}
|
||||
|
||||
// sftp 会话定义
|
||||
export interface ISftpSession extends ITerminalSession {
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user