🔨 sftp 表格.

This commit is contained in:
lijiahangmax
2024-02-06 22:26:44 +08:00
parent 9b79ebb6e6
commit 734f7a40cd
35 changed files with 1634 additions and 75 deletions

View File

@@ -0,0 +1,457 @@
export default [{
'attr': '-rw-r--r--',
'gid': 0,
'isDir': false,
'modifyTime': 1639399737000,
'name': '04',
'path': '/root/04',
'permission': 644,
'size': '34.2 MB',
'sizeByte': 35845278,
'suffix': '',
'uid': 0
}, {
'attr': 'drwxr-xr-x',
'gid': 0,
'isDir': true,
'modifyTime': 1662630786000,
'name': 'j3',
'path': '/root/j3',
'permission': 755,
'size': '4 KB',
'sizeByte': 4096,
'suffix': '',
'uid': 0
}, {
'attr': '-rw-r--r--',
'gid': 0,
'isDir': false,
'modifyTime': 1658895079000,
'name': '123',
'path': '/root/123',
'permission': 644,
'size': '13 B',
'sizeByte': 13,
'suffix': '',
'uid': 0
}, {
'attr': '-rw-r--rwx',
'gid': 0,
'isDir': false,
'modifyTime': 1664427351000,
'name': 'bug.txt',
'path': '/root/bug.txt',
'permission': 647,
'size': '50.3 KB',
'sizeByte': 51491,
'suffix': 'txt',
'uid': 0
}, {
'attr': 'drwxr-xr-x',
'gid': 0,
'isDir': true,
'modifyTime': 1659888021000,
'name': 'ops-monitor-agent',
'path': '/root/ops-monitor-agent',
'permission': 755,
'size': '4 KB',
'sizeByte': 4096,
'suffix': '',
'uid': 0
}, {
'attr': '-rw-r--r--',
'gid': 0,
'isDir': false,
'modifyTime': 1635143381000,
'name': '04_体验一下面试官对于消息队列的7个连环炮.zip',
'path': '/root/04_体验一下面试官对于消息队列的7个连环炮.zip',
'permission': 644,
'size': '34.2 MB',
'sizeByte': 35845278,
'suffix': 'zip',
'uid': 0
}, {
'attr': '-rw-r--r--',
'gid': 0,
'isDir': false,
'modifyTime': 1637921002000,
'name': '一个超长的文件一个超长的文件一个超长的文件一个超长的文件一个超长的文件一个超长的文件',
'path': '/root/一个超长的文件一个超长的文件一个超长的文件一个超长的文件一个超长的文件一个超长的文件',
'permission': 644,
'size': '4 B',
'sizeByte': 4,
'suffix': '',
'uid': 0
}, {
'attr': '-rw-r--r--',
'gid': 0,
'isDir': false,
'modifyTime': 1662627298000,
'name': 'WebStorm-2021.2.2.exe',
'path': '/root/WebStorm-2021.2.2.exe',
'permission': 644,
'size': '366.2 MB',
'sizeByte': 383998600,
'suffix': 'exe',
'uid': 0
}, {
'attr': 'drwxrwxr-x',
'gid': 0,
'isDir': true,
'modifyTime': 1557936457000,
'name': 'redis-5.0.5',
'path': '/root/redis-5.0.5',
'permission': 775,
'size': '4 KB',
'sizeByte': 4096,
'suffix': '5',
'uid': 0
}, {
'attr': 'drwxr-xr-x',
'gid': 0,
'isDir': true,
'modifyTime': 1643003400000,
'name': 'pic',
'path': '/root/pic',
'permission': 755,
'size': '4 KB',
'sizeByte': 4096,
'suffix': '',
'uid': 0
}, {
'attr': '-rw-r--r--',
'gid': 0,
'isDir': false,
'modifyTime': 1635127278000,
'name': 'pvzβv6.25-R4.7z',
'path': '/root/pvzβv6.25-R4.7z',
'permission': 644,
'size': '37.2 MB',
'sizeByte': 38978762,
'suffix': '7z',
'uid': 0
}, {
'attr': '-rw-r--r--',
'gid': 0,
'isDir': false,
'modifyTime': 1652947847000,
'name': '1.txt',
'path': '/root/1.txt',
'permission': 644,
'size': '133 B',
'sizeByte': 133,
'suffix': 'txt',
'uid': 0
}, {
'attr': 'drw-r--r--',
'gid': 0,
'isDir': true,
'modifyTime': 1653015555000,
'name': 'write',
'path': '/root/write',
'permission': 644,
'size': '4 KB',
'sizeByte': 4096,
'suffix': '',
'uid': 0
}, {
'attr': '-rw-r--r--',
'gid': 0,
'isDir': false,
'modifyTime': 1660552691000,
'name': 'k.pub',
'path': '/root/k.pub',
'permission': 644,
'size': '401 B',
'sizeByte': 401,
'suffix': 'pub',
'uid': 0
}, {
'attr': '-rw-r--r--',
'gid': 0,
'isDir': false,
'modifyTime': 1625065314000,
'name': 'ideaIU-2021.1.1.exe',
'path': '/root/ideaIU-2021.1.1.exe',
'permission': 644,
'size': '729.3 MB',
'sizeByte': 764705864,
'suffix': 'exe',
'uid': 0
}, {
'attr': '-rw-r--r--',
'gid': 0,
'isDir': false,
'modifyTime': 1636525624000,
'name': '文本.txt',
'path': '/root/文本.txt',
'permission': 644,
'size': '0 B',
'sizeByte': 0,
'suffix': 'txt',
'uid': 0
}, {
'attr': '-rw-r--r--',
'gid': 0,
'isDir': false,
'modifyTime': 1635090233000,
'name': '数据头.txt',
'path': '/root/数据头.txt',
'permission': 644,
'size': '4.3 KB',
'sizeByte': 4376,
'suffix': 'txt',
'uid': 0
}, {
'attr': 'drwxr-xr-x',
'gid': 0,
'isDir': true,
'modifyTime': 1662627659000,
'name': 'j1',
'path': '/root/j1',
'permission': 755,
'size': '4 KB',
'sizeByte': 4096,
'suffix': '',
'uid': 0
}, {
'attr': '-rw-r--r--',
'gid': 0,
'isDir': false,
'modifyTime': 1642956894000,
'name': 'PowerShell-7.1.4-win-x64.msi',
'path': '/root/PowerShell-7.1.4-win-x64.msi',
'permission': 644,
'size': '94.9 MB',
'sizeByte': 99524608,
'suffix': 'msi',
'uid': 0
}, {
'attr': '-rw-------',
'gid': 0,
'isDir': false,
'modifyTime': 1660552691000,
'name': 'k',
'path': '/root/k',
'permission': 600,
'size': '1.7 KB',
'sizeByte': 1766,
'suffix': '',
'uid': 0
}, {
'attr': 'drwxr-xr-x',
'gid': 0,
'isDir': true,
'modifyTime': 1652942938000,
'name': 'bbb',
'path': '/root/bbb',
'permission': 755,
'size': '4 KB',
'sizeByte': 4096,
'suffix': '',
'uid': 0
}, {
'attr': 'drwxr-xr-x',
'gid': 0,
'isDir': true,
'modifyTime': 1675653580000,
'name': 'swapper',
'path': '/root/swapper',
'permission': 755,
'size': '4 KB',
'sizeByte': 4096,
'suffix': '',
'uid': 0
}, {
'attr': '-rw-r--r--',
'gid': 0,
'isDir': false,
'modifyTime': 1639443147000,
'name': 'tmp2.txt',
'path': '/root/tmp2.txt',
'permission': 644,
'size': '184 B',
'sizeByte': 184,
'suffix': 'txt',
'uid': 0
}, {
'attr': 'drwxr-xr-x',
'gid': 0,
'isDir': true,
'modifyTime': 1653277297000,
'name': 'test',
'path': '/root/test',
'permission': 755,
'size': '4 KB',
'sizeByte': 4096,
'suffix': '',
'uid': 0
}, {
'attr': '-rw-r--r--',
'gid': 0,
'isDir': false,
'modifyTime': 1625064193000,
'name': 'a1.rar',
'path': '/root/a1.rar',
'permission': 644,
'size': '52 MB',
'sizeByte': 54528512,
'suffix': 'rar',
'uid': 0
}, {
'attr': '-rwxrwxrwx',
'gid': 0,
'isDir': false,
'modifyTime': 1704289282000,
'name': 'bridge.sh',
'path': '/root/bridge.sh',
'permission': 777,
'size': '396 B',
'sizeByte': 396,
'suffix': 'sh',
'uid': 0
}, {
'attr': 'drwxr-xr-x',
'gid': 0,
'isDir': true,
'modifyTime': 1663829274000,
'name': 'orion-ops',
'path': '/root/orion-ops',
'permission': 755,
'size': '4 KB',
'sizeByte': 4096,
'suffix': '',
'uid': 0
}, {
'attr': '-rw-r--r--',
'gid': 0,
'isDir': false,
'modifyTime': 1668680082000,
'name': 'ub.txt',
'path': '/root/ub.txt',
'permission': 644,
'size': '71.7 MB',
'sizeByte': 75167744,
'suffix': 'txt',
'uid': 0
}, {
'attr': '-rwxrwxrwx',
'gid': 0,
'isDir': false,
'modifyTime': 1668594989000,
'name': 'osx.d',
'path': '/root/osx.d',
'permission': 777,
'size': '170 B',
'sizeByte': 170,
'suffix': 'd',
'uid': 0
}, {
'attr': 'drwxr-xr-x',
'gid': 0,
'isDir': true,
'modifyTime': 1636337848000,
'name': 'temp',
'path': '/root/temp',
'permission': 755,
'size': '4 KB',
'sizeByte': 4096,
'suffix': '',
'uid': 0
}, {
'attr': '-rw-r--r--',
'gid': 0,
'isDir': false,
'modifyTime': 1659524667000,
'name': '46746619-175F-41c0-8D0E-0007E9271507.png',
'path': '/root/46746619-175F-41c0-8D0E-0007E9271507.png',
'permission': 644,
'size': '158.1 KB',
'sizeByte': 161927,
'suffix': 'png',
'uid': 0
}, {
'attr': 'drwxr-xr-x',
'gid': 0,
'isDir': true,
'modifyTime': 1646190836000,
'name': 'video',
'path': '/root/video',
'permission': 755,
'size': '4 KB',
'sizeByte': 4096,
'suffix': '',
'uid': 0
}, {
'attr': '-rw-r--r--',
'gid': 0,
'isDir': false,
'modifyTime': 1625136042000,
'name': 'sql1.txt',
'path': '/root/sql1.txt',
'permission': 644,
'size': '16.9 KB',
'sizeByte': 17334,
'suffix': 'txt',
'uid': 0
}, {
'attr': '-rw-r--r--',
'gid': 0,
'isDir': false,
'modifyTime': 1665545226000,
'name': 'ts.txt',
'path': '/root/ts.txt',
'permission': 644,
'size': '101.6 KB',
'sizeByte': 104004,
'suffix': 'txt',
'uid': 0
}, {
'attr': '-rw-r--r--',
'gid': 0,
'isDir': false,
'modifyTime': 1635090505000,
'name': 'shop.xlsx',
'path': '/root/shop.xlsx',
'permission': 644,
'size': '87.9 KB',
'sizeByte': 89993,
'suffix': 'xlsx',
'uid': 0
}, {
'attr': '-rw-r--r--',
'gid': 0,
'isDir': false,
'modifyTime': 1635127741000,
'name': 'Java 8实战.pdf',
'path': '/root/Java 8实战.pdf',
'permission': 644,
'size': '12.9 MB',
'sizeByte': 13490536,
'suffix': 'pdf',
'uid': 0
}, {
'attr': '-rw-r--r--',
'gid': 0,
'isDir': false,
'modifyTime': 1662626999000,
'name': 'Postman-win64-6.5.3-Setup.exe',
'path': '/root/Postman-win64-6.5.3-Setup.exe',
'permission': 644,
'size': '68.1 MB',
'sizeByte': 71401080,
'suffix': 'exe',
'uid': 0
}, {
'attr': 'drwxr-xr-x',
'gid': 0,
'isDir': true,
'modifyTime': 1662627183000,
'name': 'jar',
'path': '/root/jar',
'permission': 755,
'size': '4 KB',
'sizeByte': 4096,
'suffix': '',
'uid': 0
}];

View File

@@ -0,0 +1,97 @@
<template>
<a-table row-key="name"
class="sftp-table"
label-align="left"
:columns="columns"
v-model:selected-keys="selectedKeys"
:row-selection="rowSelection"
:sticky-header="true"
:data="list"
:pagination="false"
:bordered="false"
@cell-mouse-enter="setEditable"
@cell-mouse-leave="unsetEditable">
<!-- 文件搜索框 -->
<template #nameFilter="{ filterValue, setFilterValue, handleFilterConfirm, handleFilterReset}">
<div class="name-filter">
<a-space direction="vertical">
<!-- 过滤输入框 -->
<a-input size="small"
:model-value="filterValue[0]"
@input="(value) => setFilterValue([value])" />
<!-- 按钮 -->
<div class="name-filter-footer">
<a-button size="small" @click="handleFilterConfirm">过滤</a-button>
<a-button size="small" @click="handleFilterReset">重置</a-button>
</div>
</a-space>
</div>
</template>
<!-- 文件大小 -->
<template #size="{ record }">
<span v-if="editRecord.name === record.name">操作</span>
<span v-else>{{ record.size }}</span>
</template>
</a-table>
</template>
<script lang="ts">
export default {
name: 'sftpTable'
};
</script>
<script lang="ts" setup>
import type { TableData } from '@arco-design/web-vue/es/table/interface';
import type { SftpFile } from '../../types/terminal.type';
import { ref } from 'vue';
import { useRowSelection } from '@/types/table';
import columns from './types/table.columns';
const props = defineProps<{
list: Array<SftpFile>;
loading: boolean;
}>();
const rowSelection = useRowSelection();
const selectedKeys = ref<Array<string>>([]);
const editRecord = ref<TableData>({});
// 设置选中状态
const setEditable = (record: TableData) => {
editRecord.value = record;
record.hover = true;
};
// 设置未选中状态
const unsetEditable = (record: TableData) => {
setTimeout(() => {
if (record.name === editRecord.value.name && !record.hover) {
editRecord.value = {};
}
}, 20);
record.hover = false;
};
</script>
<style lang="less" scoped>
.sftp-table {
position: relative;
height: 100%;
}
.name-filter {
padding: 12px;
background: var(--color-bg-5);
border: 1px solid var(--color-neutral-3);
border-radius: var(--border-radius-medium);
box-shadow: 0 2px 5px rgb(0 0 0 / 10%);
&-footer {
display: flex;
justify-content: space-between;
}
}
</style>

View File

@@ -1,8 +1,29 @@
<template>
<div>
{{ tab }}
<div>header</div>
<div>table</div>
<div class="sftp-container">
<!-- 头部 -->
<div class="sftp-header">
<!-- 左侧操作 -->
<div class="sftp-header-left">
home input
</div>
<!-- 右侧操作 -->
<div class="sftp-header-right">
上传 下载 删除 刷新 copy touch mk
</div>
</div>
<a-split class="split-view"
v-model:size="splitSize"
:min="0.3"
:disabled="!editView">
<!-- 表格 -->
<template #first>
<sftp-table :list="list"
:loading="loading" />
</template>
<template #second v-if="editView">
<div>editor</div>
</template>
</a-split>
</div>
</template>
@@ -13,14 +34,75 @@
</script>
<script lang="ts" setup>
import { TerminalTabItem } from '../../types/terminal.type';
import type { ISftpSession, SftpFile, TerminalTabItem } from '../../types/terminal.type';
import { onMounted, onUnmounted, ref } from 'vue';
import { useTerminalStore } from '@/store';
import useLoading from '@/hooks/loading';
import data from './data';
import SftpTable from '@/views/host/terminal/components/sftp/sftp-table.vue';
const props = defineProps<{
tab: TerminalTabItem
}>();
const { preference, sessionManager } = useTerminalStore();
const { loading, setLoading } = useLoading(true);
const session = ref<ISftpSession>();
const currentPath = ref<string>('');
const list = ref<Array<SftpFile>>(data);
const splitSize = ref(1);
const editView = ref(true);
// 初始化会话
onMounted(async () => {
// 创建终端处理器
session.value = await sessionManager.openSftp(props.tab, {
list,
currentPath,
setLoading
});
});
// 关闭会话
onUnmounted(() => {
sessionManager.closeSession(props.tab.key);
});
</script>
<style lang="less" scoped>
@sftp-header-height: 36px;
.sftp-container {
width: 100%;
height: calc(100vh - var(--header-height) - var(--panel-nav-height));
position: relative;
}
.split-view {
width: 100%;
height: calc(100% - @sftp-header-height);
}
.sftp-header {
width: 100%;
height: @sftp-header-height;
padding: 0 8px;
display: flex;
align-items: center;
justify-content: space-between;
background: var(--color-bg-panel-bar);
&-left, &-right {
display: flex;
align-items: center;
height: 100%;
}
&-right {
justify-content: flex-end;
}
}
</style>

View File

@@ -0,0 +1,49 @@
import type { TableColumnData } from '@arco-design/web-vue/es/table/interface';
import { dateFormat } from '@/utils';
// 表格列
const columns = [
{
title: '名称',
dataIndex: 'name',
slotName: 'name',
fixed: 'left',
sortable: {
sortDirections: ['ascend', 'descend'],
},
filterable: {
filter: (value, record) => record.name.includes(value),
slotName: 'nameFilter',
}
}, {
title: '大小',
dataIndex: 'sizeByte',
slotName: 'size',
sortable: {
sortDirections: ['ascend', 'descend'],
},
}, {
title: '属性',
dataIndex: 'attr',
slotName: 'attr',
}, {
title: '修改时间',
dataIndex: 'modifyTime',
slotName: 'modifyTime',
align: 'center',
sortable: {
sortDirections: ['ascend', 'descend'],
},
render: ({ record }) => {
return dateFormat(new Date(record.modifyTime));
},
}, {
title: '操作',
dataIndex: 'actions',
slotName: 'actions',
align: 'left',
fixed: 'right',
},
] as TableColumnData[];
export default columns;

View File

@@ -0,0 +1,29 @@
import type { ISftpSession, ISftpSessionResolver, SftpDataRef, SftpFile } from '../types/terminal.type';
import { Message } from '@arco-design/web-vue';
// sftp 会话接收器实现
export default class SftpSessionResolver implements ISftpSessionResolver {
private readonly dataRef: SftpDataRef;
private readonly session: ISftpSession;
constructor(session: ISftpSession,
dataRef: SftpDataRef) {
this.session = session;
this.dataRef = dataRef;
}
// 接受文件列表响应
resolveList(result: string, path: string, list: Array<SftpFile>) {
const success = !!Number.parseInt(result);
this.dataRef.setLoading(false);
if (!success) {
Message.error('查询失败');
return;
}
this.dataRef.currentPath = path;
this.dataRef.list = list;
}
}

View File

@@ -1,5 +1,6 @@
import type { ISftpSession, ITerminalChannel } from '../types/terminal.type';
import type { ISftpSession, ISftpSessionResolver, ITerminalChannel, SftpDataRef } from '../types/terminal.type';
import { InputProtocol } from '../types/terminal.protocol';
import SftpSessionResolver from './sftp-session-resolver';
// sftp 会话实现
export default class SftpSession implements ISftpSession {
@@ -10,6 +11,10 @@ export default class SftpSession implements ISftpSession {
public connected: boolean;
public resolver: ISftpSessionResolver;
private dataRef: SftpDataRef;
private readonly channel: ITerminalChannel;
constructor(hostId: number,
@@ -19,13 +24,33 @@ export default class SftpSession implements ISftpSession {
this.sessionId = sessionId;
this.channel = channel;
this.connected = false;
this.dataRef = undefined as unknown as SftpDataRef;
this.resolver = undefined as unknown as ISftpSessionResolver;
}
// 初始化
init(dataRef: SftpDataRef): void {
this.dataRef = dataRef;
// 处理器
this.resolver = new SftpSessionResolver(this, dataRef);
}
// 设置已连接
connect(): void {
this.connected = true;
// 加载 home 目录文件数据
this.list(undefined);
}
// 查询文件列表
list(path: string | undefined) {
this.dataRef.setLoading(true);
this.channel.send(InputProtocol.SFTP_LIST, {
sessionId: this.sessionId,
path
});
};
// 断开连接
disconnect(): void {
// 发送关闭消息

View File

@@ -110,7 +110,7 @@ export default class SshSession implements ISshSession {
return;
}
// 输入
this.channel.send(InputProtocol.INPUT, {
this.channel.send(InputProtocol.SSH_INPUT, {
sessionId: this.sessionId,
command: s
});
@@ -134,7 +134,7 @@ export default class SshSession implements ISshSession {
if (!this.connected) {
return;
}
this.channel.send(InputProtocol.RESIZE, {
this.channel.send(InputProtocol.SSH_RESIZE, {
sessionId: this.sessionId,
cols,
rows

View File

@@ -1,4 +1,4 @@
import { ISshSession, ITerminalChannel, ITerminalOutputProcessor, ITerminalSessionManager, OutputPayload } from '../types/terminal.type';
import { ISftpSession, 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';
@@ -42,8 +42,9 @@ export default class TerminalOutputProcessor implements ITerminalOutputProcessor
// sftp 会话
if (success) {
// 检查成功发送 connect 命令
// TODO
this.channel.send(InputProtocol.CONNECT, {
sessionId,
});
} else {
// 未成功提示错误信息
Message.error(msg || '建立 SFTP 失败');
@@ -105,10 +106,17 @@ export default class TerminalOutputProcessor implements ITerminalOutputProcessor
// console.log('pong');
}
// 处理输出消息
processOutput({ sessionId, body }: OutputPayload): void {
// 处理 SSH 输出消息
processSshOutput({ sessionId, body }: OutputPayload): void {
const session = this.sessionManager.getSession<ISshSession>(sessionId);
session && session.write(body);
}
// 处理 SFTP 文件列表
processSftpList({ sessionId, result, path, body }: OutputPayload): void {
// 获取会话
const session = this.sessionManager.getSession<ISftpSession>(sessionId);
session && session.resolver.resolveList(result, path, JSON.parse(body));
}
}

View File

@@ -1,4 +1,12 @@
import type { ISftpSession, ITerminalChannel, ITerminalSession, ITerminalSessionManager, TerminalTabItem, XtermDomRef } from '../types/terminal.type';
import type {
ISftpSession,
ITerminalChannel,
ITerminalSession,
ITerminalSessionManager,
SftpDataRef,
TerminalTabItem,
XtermDomRef
} from '../types/terminal.type';
import { sleep } from '@/utils';
import { InputProtocol } from '../types/terminal.protocol';
import { PanelSessionType } from '../types/terminal.const';
@@ -54,7 +62,7 @@ export default class TerminalSessionManager implements ITerminalSessionManager {
}
// 打开 sftp 会话
async openSftp(tab: TerminalTabItem): Promise<ISftpSession> {
async openSftp(tab: TerminalTabItem, dataRef: SftpDataRef): Promise<ISftpSession> {
const sessionId = tab.key;
const hostId = tab.hostId as number;
// 初始化客户端
@@ -65,6 +73,8 @@ export default class TerminalSessionManager implements ITerminalSessionManager {
sessionId,
this.channel
);
// 初始化
session.init(dataRef);
// 添加会话
this.sessions[sessionId] = session;
// 发送会话初始化请求

View File

@@ -55,11 +55,11 @@ export const ExtraSshAuthType = {
// 面板会话 tab 类型
export const PanelSessionType = {
SSH: {
type: 'ssh',
type: 'SSH',
icon: 'icon-desktop'
},
SFTP: {
type: 'sftp',
type: 'SFTP',
icon: 'icon-folder'
},
};

View File

@@ -20,16 +20,21 @@ export const InputProtocol = {
type: 'p',
template: ['type']
},
// 修改大小
RESIZE: {
// SSH 修改大小
SSH_RESIZE: {
type: 'rs',
template: ['type', 'sessionId', 'cols', 'rows']
},
// 输入
INPUT: {
// SSH 输入
SSH_INPUT: {
type: 'i',
template: ['type', 'sessionId', 'command']
}
},
// SFTP 文件列表
SFTP_LIST: {
type: 'ls',
template: ['type', 'sessionId', 'path']
},
};
// 输出协议
@@ -58,10 +63,16 @@ export const OutputProtocol = {
template: ['type'],
processMethod: 'processPong'
},
// 输出
OUTPUT: {
// SSH 输出
SSH_OUTPUT: {
type: 'o',
template: ['type', 'sessionId', 'body'],
processMethod: 'processOutput'
processMethod: 'processSshOutput'
},
// SFTP 文件列表
SFTP_LIST: {
type: 'ls',
template: ['type', 'sessionId', 'result', 'path', 'body'],
processMethod: 'processSftpList'
},
};

View File

@@ -145,7 +145,7 @@ export interface ITerminalSessionManager {
// 打开 ssh 会话
openSsh: (tab: TerminalTabItem, domRef: XtermDomRef) => Promise<ISshSession>;
// 打开 sftp 会话
openSftp: (tab: TerminalTabItem) => Promise<ISftpSession>;
openSftp: (tab: TerminalTabItem, dataRef: SftpDataRef) => Promise<ISftpSession>;
// 获取终端会话
getSession: <T extends ITerminalSession>(sessionId: string) => T;
// 关闭终端会话
@@ -176,18 +176,20 @@ export interface ITerminalOutputProcessor {
processClose: (payload: OutputPayload) => void;
// 处理 pong 消息
processPong: (payload: OutputPayload) => void;
// 处理输出消息
processOutput: (payload: OutputPayload) => void;
// 处理 SSH 输出消息
processSshOutput: (payload: OutputPayload) => void;
// 处理 SFTP 文件列表
processSftpList: (payload: OutputPayload) => void;
}
// 终端 dom 元素引用
// xterm dom 元素引用
export interface XtermDomRef {
el: HTMLElement;
searchModal: any;
editorModal: any;
}
// 终端插件
// xterm 插件
export interface XtermAddons {
fit: FitAddon;
webgl: WebglAddon;
@@ -197,6 +199,16 @@ export interface XtermAddons {
image: ImageAddon;
}
// sftp 数据引用
export interface SftpDataRef {
// 文件列表
list: any;
// 当前路径
currentPath: any;
// 设置加载状态
setLoading: (loading: boolean) => void;
}
// 终端会话定义
export interface ITerminalSession {
hostId: number;
@@ -288,5 +300,32 @@ export interface ISshSessionHandler {
// sftp 会话定义
export interface ISftpSession extends ITerminalSession {
// 接收器
resolver: ISftpSessionResolver;
// 初始化
init: (dataRef: SftpDataRef) => void;
// 查询文件列表
list: (path: string | undefined) => void;
}
// sftp 会话接收器定义
export interface ISftpSessionResolver {
// 接受文件列表响应
resolveList: (result: string, path: string, list: Array<SftpFile>) => void;
}
// sftp 文件
export interface SftpFile {
name: string;
path: string;
suffix: string;
size: string;
sizeByte: number;
attr: string;
isDir: boolean;
permission: number;
uid: number;
gid: number;
modifyTime: number;
}