🔨 上传.
This commit is contained in:
@@ -22,6 +22,7 @@ import { PanelSessionType, TerminalTabs } from '@/views/host/terminal/types/term
|
|||||||
import TerminalTabManager from '@/views/host/terminal/handler/terminal-tab-manager';
|
import TerminalTabManager from '@/views/host/terminal/handler/terminal-tab-manager';
|
||||||
import TerminalSessionManager from '@/views/host/terminal/handler/terminal-session-manager';
|
import TerminalSessionManager from '@/views/host/terminal/handler/terminal-session-manager';
|
||||||
import TerminalPanelManager from '@/views/host/terminal/handler/terminal-panel-manager';
|
import TerminalPanelManager from '@/views/host/terminal/handler/terminal-panel-manager';
|
||||||
|
import SftpTransferManager from '@/views/host/terminal/handler/sftp-transfer-manager';
|
||||||
|
|
||||||
// 终端偏好项
|
// 终端偏好项
|
||||||
export const TerminalPreferenceItem = {
|
export const TerminalPreferenceItem = {
|
||||||
@@ -66,7 +67,8 @@ export default defineStore('terminal', {
|
|||||||
hosts: {} as AuthorizedHostQueryResponse,
|
hosts: {} as AuthorizedHostQueryResponse,
|
||||||
tabManager: new TerminalTabManager(TerminalTabs.NEW_CONNECTION),
|
tabManager: new TerminalTabManager(TerminalTabs.NEW_CONNECTION),
|
||||||
panelManager: new TerminalPanelManager(),
|
panelManager: new TerminalPanelManager(),
|
||||||
sessionManager: new TerminalSessionManager()
|
sessionManager: new TerminalSessionManager(),
|
||||||
|
transferManager: new SftpTransferManager(),
|
||||||
}),
|
}),
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ITerminalPanelManager, ITerminalSessionManager, ITerminalTabManager } from '@/views/host/terminal/types/terminal.type';
|
import type { ITerminalPanelManager, ITerminalSessionManager, ITerminalTabManager,ISftpTransferManager } 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 type { TerminalTheme } from '@/api/asset/host-terminal';
|
import type { TerminalTheme } from '@/api/asset/host-terminal';
|
||||||
|
|
||||||
@@ -8,6 +8,7 @@ export interface TerminalState {
|
|||||||
tabManager: ITerminalTabManager;
|
tabManager: ITerminalTabManager;
|
||||||
panelManager: ITerminalPanelManager;
|
panelManager: ITerminalPanelManager;
|
||||||
sessionManager: ITerminalSessionManager;
|
sessionManager: ITerminalSessionManager;
|
||||||
|
transferManager: ISftpTransferManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 终端配置
|
// 终端配置
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
position="left" />
|
position="left" />
|
||||||
<!-- 命令片段列表抽屉 -->
|
<!-- 命令片段列表抽屉 -->
|
||||||
<command-snippet-list-drawer ref="snippetRef" />
|
<command-snippet-list-drawer ref="snippetRef" />
|
||||||
|
<!-- 传输列表 -->
|
||||||
|
<transfer-drawer ref="transferRef" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -25,12 +27,12 @@
|
|||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import IconActions from './icon-actions.vue';
|
import IconActions from './icon-actions.vue';
|
||||||
import CommandSnippetListDrawer from '../../../command-snippet/components/command-snippet-list-drawer.vue';
|
import CommandSnippetListDrawer from '../../../command-snippet/components/command-snippet-list-drawer.vue';
|
||||||
|
import TransferDrawer from '@/views/host/terminal/components/transfer/transfer-drawer.vue';
|
||||||
const emits = defineEmits(['openTransfer']);
|
|
||||||
|
|
||||||
const { getAndCheckCurrentSshSession } = useTerminalStore();
|
const { getAndCheckCurrentSshSession } = useTerminalStore();
|
||||||
|
|
||||||
const snippetRef = ref();
|
const snippetRef = ref();
|
||||||
|
const transferRef = ref();
|
||||||
|
|
||||||
// 顶部操作
|
// 顶部操作
|
||||||
const topActions = [
|
const topActions = [
|
||||||
@@ -44,7 +46,7 @@
|
|||||||
iconStyle: {
|
iconStyle: {
|
||||||
transform: 'rotate(90deg)'
|
transform: 'rotate(90deg)'
|
||||||
},
|
},
|
||||||
click: () => emits('openTransfer')
|
click: () => transferRef.value.open()
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -150,7 +150,7 @@
|
|||||||
arrow-class="terminal-tooltip-content"
|
arrow-class="terminal-tooltip-content"
|
||||||
content="上传">
|
content="上传">
|
||||||
<span class="click-icon-wrapper header-action-icon"
|
<span class="click-icon-wrapper header-action-icon"
|
||||||
@click="uploadFile">
|
@click="openSftpUploadModal">
|
||||||
<icon-upload />
|
<icon-upload />
|
||||||
</span>
|
</span>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
@@ -182,7 +182,7 @@
|
|||||||
import type { ISftpSession } from '../../types/terminal.type';
|
import type { ISftpSession } from '../../types/terminal.type';
|
||||||
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 } from '../../types/terminal.const';
|
import { openSftpCreateModalKey, openSftpUploadModalKey } from '../../types/terminal.const';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
currentPath: string;
|
currentPath: string;
|
||||||
@@ -200,6 +200,8 @@
|
|||||||
|
|
||||||
const openSftpCreateModal = inject(openSftpCreateModalKey) as (sessionId: string, path: string, isTouch: boolean) => void;
|
const openSftpCreateModal = inject(openSftpCreateModalKey) as (sessionId: string, path: string, isTouch: boolean) => void;
|
||||||
|
|
||||||
|
const openSftpUploadModal = inject(openSftpUploadModalKey) as () => void;
|
||||||
|
|
||||||
// 监听路径变化
|
// 监听路径变化
|
||||||
watch(() => props.currentPath, (path) => {
|
watch(() => props.currentPath, (path) => {
|
||||||
if (path) {
|
if (path) {
|
||||||
@@ -264,12 +266,6 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 上传文件
|
|
||||||
const uploadFile = () => {
|
|
||||||
// TODO openModal("props.currentPath")
|
|
||||||
console.log(props.currentPath);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 下载文件
|
// 下载文件
|
||||||
const downloadFile = () => {
|
const downloadFile = () => {
|
||||||
// TODO
|
// TODO
|
||||||
|
|||||||
@@ -1,14 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<a-modal :visible="true"
|
<a-modal v-model:visible="visible"
|
||||||
top="80px"
|
top="80px"
|
||||||
title-align="start"
|
title-align="start"
|
||||||
title="文件上传"
|
title="文件上传"
|
||||||
ok-text="上传"
|
ok-text="上传"
|
||||||
|
:body-style="{ padding: '20px' }"
|
||||||
:align-center="false"
|
:align-center="false"
|
||||||
:mask-closable="false"
|
:mask-closable="false"
|
||||||
:unmount-on-close="true"
|
:unmount-on-close="true"
|
||||||
:on-before-ok="handlerOk">
|
:on-before-ok="handlerOk"
|
||||||
|
@cancel="handleClose">
|
||||||
<div class="upload-container">
|
<div class="upload-container">
|
||||||
|
<div class="mb16">
|
||||||
|
上传至文件夹: {{ parentPath }}
|
||||||
|
</div>
|
||||||
<a-space>
|
<a-space>
|
||||||
<!-- 选择文件 -->
|
<!-- 选择文件 -->
|
||||||
<a-upload v-model:file-list="fileList"
|
<a-upload v-model:file-list="fileList"
|
||||||
@@ -28,14 +33,36 @@
|
|||||||
<a-button type="primary">选择文件夹</a-button>
|
<a-button type="primary">选择文件夹</a-button>
|
||||||
</template>
|
</template>
|
||||||
</a-upload>
|
</a-upload>
|
||||||
|
|
||||||
</a-space>
|
</a-space>
|
||||||
<!-- 文件列表 -->
|
<!-- 文件列表 -->
|
||||||
<a-upload class="file-list-uploader"
|
<a-upload v-if="fileList.length" class="file-list-uploader"
|
||||||
v-model:file-list="fileList"
|
v-model:file-list="fileList"
|
||||||
:auto-upload="false"
|
:auto-upload="false"
|
||||||
:show-file-list="true">
|
:show-file-list="true">
|
||||||
<template #upload-button>
|
<template #upload-button />
|
||||||
|
<template #file-name="{ fileItem }">
|
||||||
|
<!-- 上传文件夹 -->
|
||||||
|
<template v-if="fileItem.file.webkitRelativePath">
|
||||||
|
<a-tooltip position="top"
|
||||||
|
:mini="true"
|
||||||
|
:auto-fix-position="false"
|
||||||
|
content-class="terminal-tooltip-content"
|
||||||
|
arrow-class="terminal-tooltip-content"
|
||||||
|
:content="fileItem.file.webkitRelativePath">
|
||||||
|
<span>{{ fileItem.file.webkitRelativePath }}</span>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
|
<!-- 上传文件 -->
|
||||||
|
<template v-else>
|
||||||
|
<a-tooltip position="top"
|
||||||
|
:mini="true"
|
||||||
|
:auto-fix-position="false"
|
||||||
|
content-class="terminal-tooltip-content"
|
||||||
|
arrow-class="terminal-tooltip-content"
|
||||||
|
:content="fileItem.file.name">
|
||||||
|
<span>{{ fileItem.file.name }}</span>
|
||||||
|
</a-tooltip>
|
||||||
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</a-upload>
|
</a-upload>
|
||||||
</div>
|
</div>
|
||||||
@@ -49,20 +76,56 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import type { SftpUploadItem } from '../../types/terminal.type';
|
||||||
import useVisible from '@/hooks/visible';
|
import useVisible from '@/hooks/visible';
|
||||||
import { nextTick, ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { useTerminalStore } from '@/store';
|
import { useTerminalStore } from '@/store';
|
||||||
import { permission10toString } from '@/utils/file';
|
import { Message } from '@arco-design/web-vue';
|
||||||
import SftpSession from '../../handler/sftp-session';
|
|
||||||
|
|
||||||
const { visible, setVisible } = useVisible(true);
|
const { visible, setVisible } = useVisible();
|
||||||
const { sessionManager } = useTerminalStore();
|
const { transferManager } = useTerminalStore();
|
||||||
|
|
||||||
const fileList = ref([]);
|
const hostId = ref();
|
||||||
|
const parentPath = ref('');
|
||||||
|
const fileList = ref<any[]>([]);
|
||||||
|
|
||||||
|
// 打开
|
||||||
|
const open = (host: number, parent: string) => {
|
||||||
|
hostId.value = host;
|
||||||
|
parentPath.value = parent;
|
||||||
|
setVisible(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
defineExpose({ open });
|
||||||
|
|
||||||
|
// 确定
|
||||||
const handlerOk = () => {
|
const handlerOk = () => {
|
||||||
console.log(fileList.value);
|
if (!fileList.value.length) {
|
||||||
return false;
|
return true;
|
||||||
|
}
|
||||||
|
// 添加到上传列表
|
||||||
|
const files = fileList.value.map(s => {
|
||||||
|
return {
|
||||||
|
hostId: hostId.value,
|
||||||
|
targetPath: parentPath.value + '/' + (s.file.webkitRelativePath || s.file.name),
|
||||||
|
file: s.file as File
|
||||||
|
} as SftpUploadItem;
|
||||||
|
});
|
||||||
|
transferManager.addUpload(files);
|
||||||
|
Message.success('已开始上传, 点击右侧传输列表查看进度');
|
||||||
|
// 清空
|
||||||
|
handlerClear();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 关闭
|
||||||
|
const handleClose = () => {
|
||||||
|
handlerClear();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 清空
|
||||||
|
const handlerClear = () => {
|
||||||
|
fileList.value = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
@@ -80,7 +143,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
:deep(.arco-upload-list) {
|
:deep(.arco-upload-list) {
|
||||||
max-height: calc(100vh - 328px);
|
max-height: calc(100vh - 388px);
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding: 0 12px 0 0;
|
padding: 0 12px 0 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
import { useTerminalStore } from '@/store';
|
import { useTerminalStore } from '@/store';
|
||||||
import { Message } from '@arco-design/web-vue';
|
import { Message } from '@arco-design/web-vue';
|
||||||
import useLoading from '@/hooks/loading';
|
import useLoading from '@/hooks/loading';
|
||||||
import { openSftpCreateModalKey, openSftpMoveModalKey, openSftpChmodModalKey } from '../../types/terminal.const';
|
import { openSftpCreateModalKey, openSftpMoveModalKey, openSftpChmodModalKey, openSftpUploadModalKey } from '../../types/terminal.const';
|
||||||
import SftpTableHeader from './sftp-table-header.vue';
|
import SftpTableHeader from './sftp-table-header.vue';
|
||||||
import SftpTable from './sftp-table.vue';
|
import SftpTable from './sftp-table.vue';
|
||||||
import SftpEditorHeader from './sftp-editor-header.vue';
|
import SftpEditorHeader from './sftp-editor-header.vue';
|
||||||
@@ -94,6 +94,7 @@
|
|||||||
const createModal = ref();
|
const createModal = ref();
|
||||||
const moveModal = ref();
|
const moveModal = ref();
|
||||||
const chmodModal = ref();
|
const chmodModal = ref();
|
||||||
|
const uploadModal = ref();
|
||||||
|
|
||||||
// 暴露打开创建模态框
|
// 暴露打开创建模态框
|
||||||
provide(openSftpCreateModalKey, (sessionId: string, path: string, isTouch: boolean) => {
|
provide(openSftpCreateModalKey, (sessionId: string, path: string, isTouch: boolean) => {
|
||||||
@@ -110,6 +111,11 @@
|
|||||||
chmodModal.value?.open(sessionId, path, permission);
|
chmodModal.value?.open(sessionId, path, permission);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 暴露打开上传模态框
|
||||||
|
provide(openSftpUploadModalKey, () => {
|
||||||
|
uploadModal.value?.open(props.tab.hostId, currentPath.value);
|
||||||
|
});
|
||||||
|
|
||||||
// 编辑文件
|
// 编辑文件
|
||||||
const editFile = (name: string, path: string) => {
|
const editFile = (name: string, path: string) => {
|
||||||
setEditorLoading(true);
|
setEditorLoading(true);
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
<template>
|
||||||
|
<a-drawer v-model:visible="visible"
|
||||||
|
title="文件传输列表"
|
||||||
|
:width="388"
|
||||||
|
:mask-closable="false"
|
||||||
|
:unmount-on-close="false"
|
||||||
|
:footer="false">
|
||||||
|
<a-spin class="full" :loading="loading">
|
||||||
|
{{ transferManager.transferList }}
|
||||||
|
</a-spin>
|
||||||
|
</a-drawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'transferDrawer'
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import useLoading from '@/hooks/loading';
|
||||||
|
import useVisible from '@/hooks/visible';
|
||||||
|
import { useTerminalStore } from '@/store';
|
||||||
|
|
||||||
|
const { transferManager } = useTerminalStore();
|
||||||
|
const { visible, setVisible } = useVisible();
|
||||||
|
const { loading, setLoading } = useLoading();
|
||||||
|
|
||||||
|
// 打开
|
||||||
|
const open = () => {
|
||||||
|
setVisible(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
defineExpose({ open });
|
||||||
|
|
||||||
|
// 关闭
|
||||||
|
const handleClose = () => {
|
||||||
|
handlerClear();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 清空
|
||||||
|
const handlerClear = () => {
|
||||||
|
setLoading(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.form-container {
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.command-editor {
|
||||||
|
height: calc(100vh - 330px);
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import type { ISftpTransferManager, SftpUploadItem } from '../types/terminal.type';
|
||||||
|
|
||||||
|
// sftp 传输管理器实现
|
||||||
|
export default class SftpTransferManager implements ISftpTransferManager {
|
||||||
|
|
||||||
|
transferList: Array<SftpUploadItem>;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.transferList = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加上传文件
|
||||||
|
addUpload(items: Array<SftpUploadItem>): void {
|
||||||
|
this.transferList.push(...items);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -297,6 +297,9 @@ export const openSftpMoveModalKey = Symbol();
|
|||||||
// 打开 sftpChmodModal key
|
// 打开 sftpChmodModal key
|
||||||
export const openSftpChmodModalKey = Symbol();
|
export const openSftpChmodModalKey = Symbol();
|
||||||
|
|
||||||
|
// 打开 sftpUploadModal key
|
||||||
|
export const openSftpUploadModalKey = Symbol();
|
||||||
|
|
||||||
// 字体后缀 兜底
|
// 字体后缀 兜底
|
||||||
export const fontFamilySuffix = ',courier-new, courier, monospace';
|
export const fontFamilySuffix = ',courier-new, courier, monospace';
|
||||||
|
|
||||||
|
|||||||
@@ -367,3 +367,17 @@ export interface SftpFile {
|
|||||||
gid: number;
|
gid: number;
|
||||||
modifyTime: number;
|
modifyTime: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sftp 传输管理器定义
|
||||||
|
export interface ISftpTransferManager {
|
||||||
|
transferList: Array<SftpUploadItem>;
|
||||||
|
// 添加上传文件
|
||||||
|
addUpload: (items: Array<SftpUploadItem>) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sftp 上传文件项
|
||||||
|
export interface SftpUploadItem {
|
||||||
|
hostId: number;
|
||||||
|
targetPath: string;
|
||||||
|
file: File;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user