优化 terminal 逻辑.

This commit is contained in:
lijiahang
2024-06-21 10:15:33 +08:00
parent 9ae5a6c627
commit 8dec40553d
27 changed files with 177 additions and 140 deletions

View File

@@ -5,7 +5,7 @@ type ViewType = 'table' | 'card' | undefined;
/**
* 应用状态
*/
export interface AppState extends AppSetting, UserPreferenceLayout, UserPreferenceData, UserPreferenceViews {
export interface AppState extends AppSetting, UserPreferenceLayout, UserPreferenceData, UserPreferenceView {
[key: string]: unknown;
}
@@ -43,7 +43,7 @@ export interface UserPreferenceData {
/**
* 用户偏好 - 页面视图
*/
export interface UserPreferenceViews {
export interface UserPreferenceView {
hostView: ViewType;
hostKeyView: ViewType;
hostIdentityView: ViewType;

View File

@@ -76,15 +76,15 @@
</script>
<script lang="ts" setup>
import type { ISshSession } from '@/views/host/terminal/types/terminal.type';
import type { ISshSession } from '../../types/terminal.type';
import type { CommandSnippetWrapperResponse, CommandSnippetQueryResponse } from '@/api/asset/command-snippet';
import { ref, watch, provide } from 'vue';
import useVisible from '@/hooks/visible';
import useLoading from '@/hooks/loading';
import { deleteCommandSnippet, getCommandSnippetList } from '@/api/asset/command-snippet';
import { useCacheStore, useTerminalStore } from '@/store';
import { openUpdateSnippetKey, removeSnippetKey } from '../types/const';
import { PanelSessionType } from '@/views/host/terminal/types/terminal.const';
import { openUpdateSnippetKey, removeSnippetKey } from './types/const';
import { PanelSessionType } from '../../types/terminal.const';
import CommandSnippetListItem from './command-snippet-list-item.vue';
import CommandSnippetListGroup from './command-snippet-list-group.vue';
import CommandSnippetFormDrawer from './command-snippet-form-drawer.vue';

View File

@@ -52,7 +52,7 @@
import useLoading from '@/hooks/loading';
import useVisible from '@/hooks/visible';
import { createCommandSnippet, updateCommandSnippet } from '@/api/asset/command-snippet';
import formRules from '../types/form.rules';
import formRules from './types/form.rules';
import { Message } from '@arco-design/web-vue';
import CommandSnippetGroupSelect from './command-snippet-group-select.vue';

View File

@@ -113,14 +113,14 @@
</script>
<script lang="ts" setup>
import type { ISshSession } from '@/views/host/terminal/types/terminal.type';
import type { ISshSession } from '../../types/terminal.type';
import type { CommandSnippetQueryResponse } from '@/api/asset/command-snippet';
import { useTerminalStore } from '@/store';
import { useDebounceFn } from '@vueuse/core';
import { copy } from '@/hooks/copy';
import { inject } from 'vue';
import { openUpdateSnippetKey, removeSnippetKey } from '../types/const';
import { PanelSessionType } from '@/views/host/terminal/types/terminal.const';
import { openUpdateSnippetKey, removeSnippetKey } from './types/const';
import { PanelSessionType } from '../../types/terminal.const';
const props = defineProps<{
item: CommandSnippetQueryResponse;

View File

@@ -39,12 +39,12 @@
import { onMounted, onUnmounted, watch } from 'vue';
import { addEventListen, removeEventListen } from '@/utils/event';
import EmptyRecommend from './empty-recommend.vue';
import TerminalPanelsView from './terminal-panels-view.vue';
import NewConnectionView from '../new-connection/new-connection-view.vue';
import TerminalDisplaySetting from '../setting/display/terminal-display-setting.vue';
import TerminalThemeSetting from '../setting/theme/terminal-theme-setting.vue';
import TerminalGeneralSetting from '../setting/general/terminal-general-setting.vue';
import TerminalShortcutSetting from '../setting/shortcut/terminal-shortcut-setting.vue';
import TerminalPanelsView from '@/views/host/terminal/components/layout/terminal-panels-view.vue';
const emits = defineEmits(['openCommandSnippet', 'openPathBookmark', 'openTransferList', 'screenshot']);

View File

@@ -76,15 +76,15 @@
</script>
<script lang="ts" setup>
import { ISshSession } from '@/views/host/terminal/types/terminal.type';
import type { ISshSession } from '../../types/terminal.type';
import type { PathBookmarkWrapperResponse, PathBookmarkQueryResponse } from '@/api/asset/path-bookmark';
import { ref, provide, onMounted, watch } from 'vue';
import { ref, provide, watch } from 'vue';
import useVisible from '@/hooks/visible';
import useLoading from '@/hooks/loading';
import { deletePathBookmark, getPathBookmarkList } from '@/api/asset/path-bookmark';
import { useCacheStore, useDictStore, useTerminalStore } from '@/store';
import { PanelSessionType } from '@/views/host/terminal/types/terminal.const';
import { dictKeys, openUpdatePathKey, removePathKey } from '../types/const';
import { useCacheStore, useTerminalStore } from '@/store';
import { PanelSessionType } from '../../types/terminal.const';
import { openUpdatePathKey, removePathKey } from './types/const';
import PathBookmarkListItem from './path-bookmark-list-item.vue';
import PathBookmarkListGroup from './path-bookmark-list-group.vue';
import PathBookmarkFormDrawer from './path-bookmark-form-drawer.vue';
@@ -281,11 +281,6 @@
getCurrentSession<ISshSession>(PanelSessionType.SSH.type)?.focus();
};
//
onMounted(() => {
useDictStore().loadKeys(dictKeys);
});
</script>
<style lang="less" scoped>

View File

@@ -55,8 +55,9 @@
import useLoading from '@/hooks/loading';
import useVisible from '@/hooks/visible';
import { createPathBookmark, updatePathBookmark } from '@/api/asset/path-bookmark';
import formRules from '../types/form.rules';
import { PathBookmarkType, pathBookmarkTypeKey } from '../types/const';
import formRules from './types/form.rules';
import { PathBookmarkType } from './types/const';
import { pathBookmarkTypeKey } from '../../types/terminal.const';
import { useDictStore } from '@/store';
import { Message } from '@arco-design/web-vue';
import PathBookmarkGroupSelect from './path-bookmark-group-select.vue';

View File

@@ -112,15 +112,15 @@
</script>
<script lang="ts" setup>
import type { ISftpSession, ISshSession } from '@/views/host/terminal/types/terminal.type';
import type { ISftpSession, ISshSession } from '../../types/terminal.type';
import type { PathBookmarkQueryResponse } from '@/api/asset/path-bookmark';
import { useTerminalStore } from '@/store';
import { useDebounceFn } from '@vueuse/core';
import { copy } from '@/hooks/copy';
import { inject } from 'vue';
import { getParentPath } from '@/utils/file';
import { openUpdatePathKey, PathBookmarkType, removePathKey } from '../types/const';
import { PanelSessionType } from '@/views/host/terminal/types/terminal.const';
import { openUpdatePathKey, PathBookmarkType, removePathKey } from './types/const';
import { PanelSessionType } from '../../types/terminal.const';
const props = defineProps<{
item: PathBookmarkQueryResponse;

View File

@@ -9,9 +9,3 @@ export const openUpdatePathKey = Symbol();
// 删除 path key
export const removePathKey = Symbol();
// 路径书签类型 字典项
export const pathBookmarkTypeKey = 'pathBookmarkType';
// 加载的字典值
export const dictKeys = [pathBookmarkTypeKey];

View File

@@ -45,11 +45,12 @@
</script>
<script lang="ts" setup>
import type { ISftpSession } from '../../types/terminal.type';
import useVisible from '@/hooks/visible';
import { nextTick, ref } from 'vue';
import { useTerminalStore } from '@/store';
import { permission10toString } from '@/utils/file';
import SftpSession from '../../handler/sftp-session';
import { PanelSessionType } from '../../types/terminal.const';
const { visible, setVisible } = useVisible();
const { sessionManager } = useTerminalStore();
@@ -92,8 +93,8 @@
return false;
}
// 获取会话
const session = sessionManager.getSession(sessionId.value);
if (session instanceof SftpSession) {
const session = sessionManager.getSession<ISftpSession>(sessionId.value);
if (session.type === PanelSessionType.SFTP.type) {
session.chmod(formModel.value.path, formModel.value.mod);
}
} catch (e) {

View File

@@ -30,10 +30,11 @@
</script>
<script lang="ts" setup>
import type { ISftpSession } from '../../types/terminal.type';
import useVisible from '@/hooks/visible';
import { nextTick, ref } from 'vue';
import { useTerminalStore } from '@/store';
import SftpSession from '../../handler/sftp-session';
import { PanelSessionType } from '../../types/terminal.const';
const { visible, setVisible } = useVisible();
const { sessionManager } = useTerminalStore();
@@ -69,8 +70,8 @@
return false;
}
// 获取会话
const session = sessionManager.getSession(sessionId.value);
if (session instanceof SftpSession) {
const session = sessionManager.getSession<ISftpSession>(sessionId.value);
if (session.type === PanelSessionType.SFTP.type) {
if (touch.value) {
// 创建文件
session.touch(formModel.value.path);

View File

@@ -38,10 +38,11 @@
</script>
<script lang="ts" setup>
import type { ISftpSession } from '../../types/terminal.type';
import useVisible from '@/hooks/visible';
import { nextTick, ref } from 'vue';
import { useTerminalStore } from '@/store';
import SftpSession from '../../handler/sftp-session';
import { PanelSessionType } from '../../types/terminal.const';
const { visible, setVisible } = useVisible();
const { sessionManager } = useTerminalStore();
@@ -77,8 +78,8 @@
return false;
}
// 获取会话
const session = sessionManager.getSession(sessionId.value);
if (session instanceof SftpSession) {
const session = sessionManager.getSession<ISftpSession>(sessionId.value);
if (session.type === PanelSessionType.SFTP.type) {
session.move(formModel.value.path, formModel.value.target);
}
} catch (e) {

View File

@@ -0,0 +1,46 @@
import type { ITerminalSession, TerminalPanelTabItem } from '../types/terminal.type';
// 会话基类
export default abstract class BaseSession implements ITerminalSession {
public type: string;
public hostId: number;
public title: string;
public address: string;
public sessionId: string;
public connected: boolean;
public canReconnect: boolean;
public canWrite: boolean;
protected constructor(type: string, tab: TerminalPanelTabItem) {
this.type = type;
this.hostId = tab.hostId;
this.title = tab.title;
this.address = tab.address;
this.sessionId = tab.sessionId;
this.connected = false;
this.canWrite = false;
this.canReconnect = false;
}
// 设置是否可写
setCanWrite(canWrite: boolean): void {
this.canWrite = canWrite;
}
// 连接
connect(): void {
this.connected = true;
}
// 断开连接
disconnect(): void {
this.connected = false;
}
// 关闭
close(): void {
this.connected = false;
}
}

View File

@@ -1,17 +1,11 @@
import type { ISftpSession, ISftpSessionResolver, ITerminalChannel } from '../types/terminal.type';
import type { ISftpSession, ISftpSessionResolver, ITerminalChannel, TerminalPanelTabItem } from '../types/terminal.type';
import { InputProtocol } from '../types/terminal.protocol';
import { PanelSessionType } from '../types/terminal.const';
import { Modal } from '@arco-design/web-vue';
import BaseSession from './base-session';
// sftp 会话实现
export default class SftpSession implements ISftpSession {
public readonly hostId: number;
public sessionId: string;
public connected: boolean;
public canReconnect: boolean;
export default class SftpSession extends BaseSession implements ISftpSession {
public resolver: ISftpSessionResolver;
@@ -19,14 +13,10 @@ export default class SftpSession implements ISftpSession {
private readonly channel: ITerminalChannel;
constructor(hostId: number,
sessionId: string,
constructor(tab: TerminalPanelTabItem,
channel: ITerminalChannel) {
this.hostId = hostId;
this.sessionId = sessionId;
super(PanelSessionType.SFTP.type, tab);
this.channel = channel;
this.connected = false;
this.canReconnect = false;
this.showHiddenFile = false;
this.resolver = undefined as unknown as ISftpSessionResolver;
}
@@ -38,7 +28,7 @@ export default class SftpSession implements ISftpSession {
// 设置已连接
connect(): void {
this.connected = true;
super.connect();
// 连接回调
this.resolver.connectCallback();
}
@@ -140,14 +130,11 @@ export default class SftpSession implements ISftpSession {
// 断开连接
disconnect(): void {
super.disconnect();
// 发送关闭消息
this.channel.send(InputProtocol.CLOSE, {
sessionId: this.sessionId
});
}
// 关闭
close(): void {
}
}

View File

@@ -1,13 +1,13 @@
import type { UnwrapRef } from 'vue';
import type { ISearchOptions } from '@xterm/addon-search';
import { SearchAddon } from '@xterm/addon-search';
import type { TerminalPreference } from '@/store/modules/terminal/types';
import type { ISshSession, ISshSessionHandler, ITerminalChannel, XtermAddons, XtermDomRef } from '../types/terminal.type';
import type { ISshSession, ISshSessionHandler, ITerminalChannel, TerminalPanelTabItem, XtermAddons, XtermDomRef } from '../types/terminal.type';
import { useTerminalStore } from '@/store';
import { InputProtocol } from '../types/terminal.protocol';
import { fontFamilySuffix, TerminalShortcutType, TerminalStatus } from '../types/terminal.const';
import { fontFamilySuffix, PanelSessionType, TerminalShortcutType, TerminalStatus, } from '../types/terminal.const';
import { Terminal } from '@xterm/xterm';
import { FitAddon } from '@xterm/addon-fit';
import { SearchAddon } from '@xterm/addon-search';
import { WebLinksAddon } from '@xterm/addon-web-links';
import { ImageAddon } from '@xterm/addon-image';
import { Unicode11Addon } from '@xterm/addon-unicode11';
@@ -16,22 +16,13 @@ import { WebglAddon } from '@xterm/addon-webgl';
import { playBell } from '@/utils/bell';
import { addEventListen } from '@/utils/event';
import SshSessionHandler from './ssh-session-handler';
import BaseSession from './base-session';
// ssh 会话实现
export default class SshSession implements ISshSession {
public readonly hostId: number;
public sessionId: string;
export default class SshSession extends BaseSession implements ISshSession {
public inst: Terminal;
public connected: boolean;
public canReconnect: boolean;
public canWrite: boolean;
public status: number;
public handler: ISshSessionHandler;
@@ -40,15 +31,10 @@ export default class SshSession implements ISshSession {
private readonly addons: XtermAddons;
constructor(hostId: number,
sessionId: string,
constructor(tab: TerminalPanelTabItem,
channel: ITerminalChannel) {
this.hostId = hostId;
this.sessionId = sessionId;
super(PanelSessionType.SSH.type, tab);
this.channel = channel;
this.connected = false;
this.canReconnect = false;
this.canWrite = false;
this.status = TerminalStatus.CONNECTING;
this.inst = undefined as unknown as Terminal;
this.handler = undefined as unknown as ISshSessionHandler;
@@ -213,14 +199,14 @@ export default class SshSession implements ISshSession {
// 设置已连接
connect(): void {
super.connect();
this.status = TerminalStatus.CONNECTED;
this.connected = true;
this.inst.focus();
}
// 设置是否可写
setCanWrite(canWrite: boolean): void {
this.canWrite = canWrite;
super.setCanWrite(canWrite);
if (canWrite) {
this.inst.options.cursorBlink = useTerminalStore().preference.displaySetting.cursorBlink;
} else {
@@ -229,7 +215,7 @@ export default class SshSession implements ISshSession {
}
// 写入数据
write(value: string | Uint8Array): void {
write(value: string): void {
this.inst.write(value);
}
@@ -259,6 +245,7 @@ export default class SshSession implements ISshSession {
// 断开连接
disconnect(): void {
super.disconnect();
// 发送关闭消息
this.channel.send(InputProtocol.CLOSE, {
sessionId: this.sessionId
@@ -267,6 +254,7 @@ export default class SshSession implements ISshSession {
// 关闭
close(): void {
super.close();
try {
// 卸载插件
Object.values(this.addons)

View File

@@ -1,10 +1,16 @@
import { ISftpSession, ISshSession, ITerminalChannel, ITerminalOutputProcessor, ITerminalSessionManager, OutputPayload } from '../types/terminal.type';
import {
ISftpSession,
ISshSession,
ITerminalChannel,
ITerminalOutputProcessor,
ITerminalSession,
ITerminalSessionManager,
OutputPayload
} from '../types/terminal.type';
import { InputProtocol } from '../types/terminal.protocol';
import { TerminalStatus } from '../types/terminal.const';
import { PanelSessionType, 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 {
@@ -23,7 +29,8 @@ export default class TerminalOutputProcessor implements ITerminalOutputProcessor
const success = !!Number.parseInt(result);
const session = this.sessionManager.getSession(sessionId);
session.canReconnect = !success;
if (session instanceof SshSession) {
// 处理
this.processWithType(session, ssh => {
// ssh 会话
if (success) {
// 检查成功发送 connect 命令
@@ -31,15 +38,15 @@ export default class TerminalOutputProcessor implements ITerminalOutputProcessor
this.channel.send(InputProtocol.CONNECT, {
sessionId,
terminalType: preference.sessionSetting.terminalEmulationType || 'xterm',
cols: session.inst.cols,
rows: session.inst.rows
cols: ssh.inst.cols,
rows: ssh.inst.rows
});
} else {
// 未成功展示错误信息
session.write(`${msg || ''}\r\n输入回车重新连接...\r\n\r\n`);
session.status = TerminalStatus.CLOSED;
ssh.write(`${msg || ''}\r\n输入回车重新连接...\r\n\r\n`);
ssh.status = TerminalStatus.CLOSED;
}
} else if (session instanceof SftpSession) {
}, sftp => {
// sftp 会话
if (success) {
// 检查成功发送 connect 命令
@@ -48,10 +55,10 @@ export default class TerminalOutputProcessor implements ITerminalOutputProcessor
});
} else {
// 未成功提示错误信息
session.resolver?.onClose(false, msg);
sftp.resolver?.onClose(false, msg);
Message.error(msg || '建立 SFTP 失败');
}
}
});
}
// 处理连接消息
@@ -59,29 +66,32 @@ export default class TerminalOutputProcessor implements ITerminalOutputProcessor
const success = !!Number.parseInt(result);
const session = this.sessionManager.getSession(sessionId);
session.canReconnect = !success;
if (session instanceof SshSession) {
// 处理
this.processWithType(session, ssh => {
// ssh 会话
if (success) {
// 设置可写
session.setCanWrite(true);
ssh.setCanWrite(true);
// 执行连接逻辑
session.connect();
ssh.connect();
} else {
// 未成功展示错误信息
session.write(`${msg || ''}\r\n输入回车重新连接...\r\n\r\n`);
session.status = TerminalStatus.CLOSED;
ssh.write(`${msg || ''}\r\n输入回车重新连接...\r\n\r\n`);
ssh.status = TerminalStatus.CLOSED;
}
} else if (session instanceof SftpSession) {
}, sftp => {
// sftp 会话
if (success) {
// 设置可写
sftp.setCanWrite(true);
// 执行连接逻辑
session.connect();
sftp.connect();
} else {
// 未成功提示错误信息
session.resolver?.onClose(false, msg);
sftp.resolver?.onClose(false, msg);
Message.error(msg || '打开 SFTP 失败');
}
}
});
}
// 处理关闭消息
@@ -94,20 +104,23 @@ export default class TerminalOutputProcessor implements ITerminalOutputProcessor
const isForceClose = !!Number.parseInt(forceClose);
session.connected = false;
session.canReconnect = !isForceClose;
if (session instanceof SshSession) {
// 处理
this.processWithType(session, ssh => {
// ssh 拼接关闭消息
session.write(`\r\n\r\n${msg || ''}\r\n`);
ssh.write(`\r\n\r\n${msg || ''}\r\n`);
if (!isForceClose) {
session.write('输入回车重新连接...\r\n\r\n');
ssh.write('输入回车重新连接...\r\n\r\n');
}
// 设置状态
session.status = TerminalStatus.CLOSED;
ssh.status = TerminalStatus.CLOSED;
// 设置不可写
session.setCanWrite(false);
} else if (session instanceof SftpSession) {
ssh.setCanWrite(false);
}, sftp => {
// 设置不可写
sftp.setCanWrite(false);
// sftp 设置状态
session.resolver?.onClose(isForceClose, msg);
}
sftp.resolver?.onClose(isForceClose, msg);
});
}
// 处理 pong 消息
@@ -184,4 +197,17 @@ export default class TerminalOutputProcessor implements ITerminalOutputProcessor
session && session.resolver.resolveSftpSetContent(result, msg);
}
// 根据类型处理操作
private processWithType(session: ITerminalSession,
sshProcess: (ssh: ISshSession) => any | void,
sftpProcess: (ssh: ISftpSession) => any | void) {
if (session.type === PanelSessionType.SSH.type) {
// SSH 操作
return sshProcess(session as ISshSession);
} else if (session.type === PanelSessionType.SFTP.type) {
// SFTP 操作
return sftpProcess(session as ISftpSession);
}
}
}

View File

@@ -35,26 +35,21 @@ export default class TerminalSessionManager implements ITerminalSessionManager {
// 打开 ssh 会话
async openSsh(tab: TerminalPanelTabItem, domRef: XtermDomRef) {
const sessionId = tab.sessionId;
const hostId = tab.hostId as number;
// 初始化客户端
await this.initChannel();
// 新建会话
const session = new SshSession(
hostId,
sessionId,
this.channel
);
const session = new SshSession(tab, this.channel);
// 初始化
session.init(domRef);
// 等待前端渲染完成
await sleep(100);
// 添加会话
const sessionId = tab.sessionId;
this.sessions[sessionId] = session;
// 发送会话初始化请求
this.channel.send(InputProtocol.CHECK, {
sessionId,
hostId,
hostId: tab.hostId,
connectType: PanelSessionType.SSH.type
});
return session;
@@ -62,24 +57,19 @@ export default class TerminalSessionManager implements ITerminalSessionManager {
// 打开 sftp 会话
async openSftp(tab: TerminalPanelTabItem, resolver: ISftpSessionResolver): Promise<ISftpSession> {
const sessionId = tab.sessionId;
const hostId = tab.hostId as number;
// 初始化客户端
await this.initChannel();
// 新建会话
const session = new SftpSession(
hostId,
sessionId,
this.channel
);
const session = new SftpSession(tab, this.channel);
// 初始化
session.init(resolver);
// 添加会话
const sessionId = tab.sessionId;
this.sessions[sessionId] = session;
// 发送会话初始化请求
this.channel.send(InputProtocol.CHECK, {
sessionId,
hostId,
hostId: tab.hostId,
connectType: PanelSessionType.SFTP.type
});
return session;
@@ -145,7 +135,7 @@ export default class TerminalSessionManager implements ITerminalSessionManager {
private dispatchResize() {
// 对所有已连接的会话重置大小
Object.values(this.sessions)
.filter(s => s instanceof SshSession)
.filter(s => s.type === PanelSessionType.SSH.type)
.map(s => s as SshSession)
.filter(h => h.connected)
.forEach(h => h.fit());

View File

@@ -56,9 +56,9 @@
import RightSidebar from './components/layout/right-sidebar.vue';
import MainContent from './components/layout/main-content.vue';
import LoadingSkeleton from './components/layout/loading-skeleton.vue';
import TransferDrawer from '@/views/host/terminal/components/transfer/transfer-drawer.vue';
import CommandSnippetDrawer from '@/views/host/command-snippet/components/command-snippet-drawer.vue';
import PathBookmarkDrawer from '@/views/host/path-bookmark/components/path-bookmark-drawer.vue';
import TransferDrawer from './components/transfer/transfer-drawer.vue';
import CommandSnippetDrawer from './components/command-snippet/command-snippet-drawer.vue';
import PathBookmarkDrawer from './components/path-bookmark/path-bookmark-drawer.vue';
import '@/assets/style/host-terminal-layout.less';
import '@xterm/xterm/css/xterm.css';
@@ -124,7 +124,7 @@
// 卸载处理
onUnmounted(() => {
// 卸载时清除 cache
cacheStore.reset('authorizedHostKeys', 'authorizedHostIdentities', 'commandSnippetGroups');
cacheStore.reset('authorizedHostKeys', 'authorizedHostIdentities', 'commandSnippetGroups', 'pathBookmarkGroups');
// 移除关闭视口事件
window.removeEventListener('beforeunload', handleBeforeUnload);
// 去除 body style

View File

@@ -403,6 +403,9 @@ export const tabColorKey = 'terminalTabColor';
// SFTP 传输状态
export const transferStatusKey = 'sftpTransferStatus';
// 路径书签类型
export const pathBookmarkTypeKey = 'pathBookmarkType';
// 加载的字典值
export const dictKeys = [
fontFamilyKey, fontSizeKey,
@@ -410,4 +413,5 @@ export const dictKeys = [
newConnectionTypeKey, extraSshAuthTypeKey,
connectStatusKey, emulationTypeKey,
tabColorKey, transferStatusKey,
pathBookmarkTypeKey,
];

View File

@@ -234,13 +234,20 @@ export interface XtermAddons {
// 终端会话定义
export interface ITerminalSession {
type: string;
title: string;
address: string;
hostId: number;
sessionId: string;
// 是否已连接
connected: boolean;
// 是否可以重新连接
canReconnect: boolean;
// 是否可写
canWrite: boolean;
// 设置是否可写
setCanWrite: (canWrite: boolean) => void;
// 连接
connect: () => void;
// 断开连接
@@ -253,8 +260,6 @@ export interface ITerminalSession {
export interface ISshSession extends ITerminalSession {
// terminal 实例
inst: Terminal;
// 是否可写
canWrite: boolean;
// 状态
status: number;
// 处理器
@@ -262,10 +267,8 @@ export interface ISshSession extends ITerminalSession {
// 初始化
init: (domRef: XtermDomRef) => void;
// 设置是否可写
setCanWrite: (canWrite: boolean) => void;
// 写入数据
write: (value: string | Uint8Array) => void;
write: (value: string) => void;
// 聚焦
focus: () => void;
// 失焦