✨ 优化传输列表显示.
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
:width="388"
|
||||
:footer="false"
|
||||
@close="onClose">
|
||||
<!-- 表头 -->
|
||||
<!-- 标题 -->
|
||||
<template #title>
|
||||
<span class="snippet-drawer-title usn">
|
||||
命令片段
|
||||
@@ -32,9 +32,7 @@
|
||||
<a-input-search class="snippet-header-input"
|
||||
v-model="filterValue"
|
||||
placeholder="名称/命令"
|
||||
allow-clear
|
||||
@search="filterSnippet"
|
||||
@keyup.enter="filterSnippet" />
|
||||
allow-clear />
|
||||
</div>
|
||||
<!-- 加载中 -->
|
||||
<a-skeleton v-if="loading"
|
||||
@@ -73,14 +71,14 @@
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'commandSnippetListDrawer'
|
||||
name: 'commandSnippetDrawer'
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { ISshSession } from '@/views/host/terminal/types/terminal.type';
|
||||
import type { CommandSnippetWrapperResponse, CommandSnippetQueryResponse } from '@/api/asset/command-snippet';
|
||||
import { ref, provide } from 'vue';
|
||||
import { ref, watch, provide } from 'vue';
|
||||
import useVisible from '@/hooks/visible';
|
||||
import useLoading from '@/hooks/loading';
|
||||
import { deleteCommandSnippet, getCommandSnippetList } from '@/api/asset/command-snippet';
|
||||
@@ -143,6 +141,9 @@
|
||||
});
|
||||
};
|
||||
|
||||
// 过滤列表
|
||||
watch(filterValue, filterSnippet);
|
||||
|
||||
// 新建
|
||||
const openAdd = () => {
|
||||
formDrawer.value.openAdd();
|
||||
@@ -3,7 +3,7 @@
|
||||
:width="388"
|
||||
:footer="false"
|
||||
@close="onClose">
|
||||
<!-- 表头 -->
|
||||
<!-- 标题 -->
|
||||
<template #title>
|
||||
<span class="path-drawer-title usn">
|
||||
路径书签
|
||||
@@ -32,9 +32,7 @@
|
||||
<a-input-search class="path-header-input"
|
||||
v-model="filterValue"
|
||||
placeholder="名称/路径"
|
||||
allow-clear
|
||||
@search="filterPath"
|
||||
@keyup.enter="filterPath" />
|
||||
allow-clear />
|
||||
</div>
|
||||
<!-- 加载中 -->
|
||||
<a-skeleton v-if="loading"
|
||||
@@ -73,14 +71,14 @@
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'pathBookmarkListDrawer'
|
||||
name: 'pathBookmarkDrawer'
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ISshSession } from '@/views/host/terminal/types/terminal.type';
|
||||
import type { PathBookmarkWrapperResponse, PathBookmarkQueryResponse } from '@/api/asset/path-bookmark';
|
||||
import { ref, provide, onMounted } from 'vue';
|
||||
import { ref, provide, onMounted, watch } from 'vue';
|
||||
import useVisible from '@/hooks/visible';
|
||||
import useLoading from '@/hooks/loading';
|
||||
import { deletePathBookmark, getPathBookmarkList } from '@/api/asset/path-bookmark';
|
||||
@@ -143,6 +141,9 @@
|
||||
});
|
||||
};
|
||||
|
||||
// 过滤列表
|
||||
watch(filterValue, filterPath);
|
||||
|
||||
// 新建
|
||||
const openAdd = () => {
|
||||
formDrawer.value.openAdd();
|
||||
@@ -14,7 +14,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<!-- 其他颜色 -->
|
||||
<template v-for="color in toOptions(terminalTabColorKey)">
|
||||
<template v-for="color in toOptions(tabColorKey)">
|
||||
<div class="color-wrapper"
|
||||
:class="[formModel.color === color.value ? 'selected-color' : '']"
|
||||
:style="{ '--color': `${color.value}` }"
|
||||
@@ -37,7 +37,7 @@
|
||||
<script lang="ts" setup>
|
||||
import type { LabelExtraSettingModel } from '../../../types/terminal.type';
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { terminalTabColorKey } from '../../../types/terminal.const';
|
||||
import { tabColorKey } from '../../../types/terminal.const';
|
||||
import { getHostExtraItem } from '@/api/asset/host-extra';
|
||||
import { useDictStore } from '@/store';
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<a-select style="width: 160px;"
|
||||
v-model="formModel.terminalEmulationType"
|
||||
size="small"
|
||||
:options="toOptions(terminalEmulationTypeKey)" />
|
||||
:options="toOptions(emulationTypeKey)" />
|
||||
</block-setting-item>
|
||||
<!-- 缓冲区行数 -->
|
||||
<block-setting-item label="缓冲区行数" desc="保存在缓冲区的行数, 多出的行数会被忽略, 此值越大占用内存的内存会更多">
|
||||
@@ -42,7 +42,7 @@
|
||||
import { ref, watch } from 'vue';
|
||||
import { useDictStore, useTerminalStore } from '@/store';
|
||||
import { TerminalPreferenceItem } from '@/store/modules/terminal';
|
||||
import { terminalEmulationTypeKey } from '../../../types/terminal.const';
|
||||
import { emulationTypeKey } from '../../../types/terminal.const';
|
||||
import BlockSettingItem from '../block-setting-item.vue';
|
||||
|
||||
const { toOptions } = useDictStore();
|
||||
|
||||
@@ -83,8 +83,6 @@
|
||||
import { useTerminalStore } from '@/store';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import useVisible from '@/hooks/visible';
|
||||
import { TransferStatus, TransferType } from '../../types/terminal.const';
|
||||
import { nextId } from '@/utils';
|
||||
|
||||
const { visible, setVisible } = useVisible();
|
||||
const { transferManager } = useTerminalStore();
|
||||
|
||||
@@ -1,11 +1,47 @@
|
||||
<template>
|
||||
<a-drawer v-model:visible="visible"
|
||||
title="文件传输列表"
|
||||
class="transfer-drawer"
|
||||
:width="388"
|
||||
:unmount-on-close="false"
|
||||
:footer="false">
|
||||
<a-spin class="full" :loading="loading">
|
||||
<a-list class="hosts-list-container"
|
||||
<!-- 标题 -->
|
||||
<template #title>
|
||||
<span class="path-drawer-title usn">
|
||||
文件传输列表
|
||||
</span>
|
||||
</template>
|
||||
<a-spin class="full transfer-container" :loading="loading">
|
||||
<!-- 头部操作 -->
|
||||
<div class="transfer-header">
|
||||
<!-- 左侧按钮 -->
|
||||
<a-space size="small">
|
||||
<!-- 清空 -->
|
||||
<span class="click-icon-wrapper transfer-header-icon"
|
||||
title="清空"
|
||||
@click="removeAllTask">
|
||||
<icon-close />
|
||||
</span>
|
||||
</a-space>
|
||||
<!-- 右侧数量 -->
|
||||
<a-space size="small">
|
||||
<a-tag v-for="option in toOptions(transferStatusKey)"
|
||||
class="pointer"
|
||||
:color="option.color"
|
||||
:title="option.label"
|
||||
:bordered="option.value === filterStatus"
|
||||
:checked="option.value === filterStatus"
|
||||
@click="checkFilterStatus(option.value)">
|
||||
<!-- 图标 -->
|
||||
<component :is="option.icon" />
|
||||
<!-- 数量 -->
|
||||
<span class="status-count">
|
||||
{{ transferManager.transferList.filter(s => s.status === option.value).length }}
|
||||
</span>
|
||||
</a-tag>
|
||||
</a-space>
|
||||
</div>
|
||||
<!-- 文件列表 -->
|
||||
<a-list class="transfer-item-container"
|
||||
size="small"
|
||||
max-height="100%"
|
||||
:hoverable="true"
|
||||
@@ -17,88 +53,8 @@
|
||||
</template>
|
||||
<!-- 数据 -->
|
||||
<template #item="{ item }">
|
||||
<a-list-item class="transfer-item-wrapper">
|
||||
<div class="transfer-item">
|
||||
<!-- 左侧图标 -->
|
||||
<div class="transfer-item-left">
|
||||
<span class="file-icon">
|
||||
<icon-upload v-if="item.type === TransferType.UPLOAD" />
|
||||
<icon-download v-else-if="item.type === TransferType.DOWNLOAD" />
|
||||
</span>
|
||||
</div>
|
||||
<!-- 中间信息 -->
|
||||
<div class="transfer-item-center">
|
||||
<!-- 文件名称 -->
|
||||
<a-tooltip position="top"
|
||||
:mini="true"
|
||||
:auto-fix-position="false"
|
||||
content-class="terminal-tooltip-content"
|
||||
arrow-class="terminal-tooltip-content"
|
||||
:content="item.name">
|
||||
<span class="file-name">
|
||||
{{ item.name }}
|
||||
</span>
|
||||
</a-tooltip>
|
||||
<!-- 传输进度 -->
|
||||
<span class="transfer-progress">
|
||||
<!-- 当前大小 -->
|
||||
<span v-if="item.status === TransferStatus.TRANSFERRING">{{ getFileSize(item.currentSize) }}</span>
|
||||
<span class="mx4" v-if="item.status === TransferStatus.TRANSFERRING">/</span>
|
||||
<!-- 总大小 -->
|
||||
<span>{{ getFileSize(item.totalSize) }}</span>
|
||||
<!-- 进度百分比 -->
|
||||
<span class="ml8" v-if="item.status === TransferStatus.TRANSFERRING">
|
||||
{{ item.progress }}%
|
||||
</span>
|
||||
</span>
|
||||
<!-- 目标目录 -->
|
||||
<a-tooltip v-if="item.parentPath"
|
||||
position="top"
|
||||
:mini="true"
|
||||
:auto-fix-position="false"
|
||||
content-class="terminal-tooltip-content"
|
||||
arrow-class="terminal-tooltip-content"
|
||||
:content="item.parentPath">
|
||||
<span class="target-path">
|
||||
{{ item.parentPath }}
|
||||
</span>
|
||||
</a-tooltip>
|
||||
<!-- 错误信息 -->
|
||||
<a-tooltip v-if="item.errorMessage"
|
||||
position="top"
|
||||
:mini="true"
|
||||
:auto-fix-position="false"
|
||||
content-class="terminal-tooltip-content"
|
||||
arrow-class="terminal-tooltip-content"
|
||||
:content="item.errorMessage">
|
||||
<span class="error-message">
|
||||
{{ item.errorMessage }}
|
||||
</span>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
<!-- 右侧状态/操作-->
|
||||
<div class="transfer-item-right">
|
||||
<!-- 传输状态 -->
|
||||
<div class="transfer-item-right-progress">
|
||||
<!-- 等待传输 -->
|
||||
<icon-clock-circle v-if="item.status === TransferStatus.WAITING" />
|
||||
<!-- 传输进度 -->
|
||||
<a-progress v-else
|
||||
type="circle"
|
||||
size="mini"
|
||||
:status="item.status"
|
||||
:percent="item.currentSize / item.totalSize" />
|
||||
</div>
|
||||
<!-- 传输操作 -->
|
||||
<div class="transfer-item-right-actions">
|
||||
<!-- 关闭 -->
|
||||
<span class="close-icon" @click="removeTask(item.fileId)">
|
||||
<icon-close />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-list-item>
|
||||
<!-- 传输 item -->
|
||||
<transfer-item v-show="filterItem(item)" :item="item" />
|
||||
</template>
|
||||
</a-list>
|
||||
</a-spin>
|
||||
@@ -112,16 +68,21 @@
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { SftpTransferItem } from '../../types/terminal.type';
|
||||
import { ref } from 'vue';
|
||||
import useLoading from '@/hooks/loading';
|
||||
import useVisible from '@/hooks/visible';
|
||||
import { useTerminalStore } from '@/store';
|
||||
import { getFileSize } from '@/utils/file';
|
||||
import { TransferStatus, TransferType } from '../../types/terminal.const';
|
||||
import { useDictStore, useTerminalStore } from '@/store';
|
||||
import { transferStatusKey } from '../../types/terminal.const';
|
||||
import TransferItem from './transfer-item.vue';
|
||||
|
||||
const { transferManager } = useTerminalStore();
|
||||
const { toOptions } = useDictStore();
|
||||
const { visible, setVisible } = useVisible();
|
||||
const { loading, setLoading } = useLoading();
|
||||
|
||||
const filterStatus = ref<string>();
|
||||
|
||||
// 打开
|
||||
const open = () => {
|
||||
setVisible(true);
|
||||
@@ -129,9 +90,24 @@
|
||||
|
||||
defineExpose({ open });
|
||||
|
||||
// 移除任务
|
||||
const removeTask = (fileId: string) => {
|
||||
transferManager.cancelTransfer(fileId);
|
||||
// 选中过滤状态
|
||||
const checkFilterStatus = (status: string) => {
|
||||
// 相同则设置为空
|
||||
if (status === filterStatus.value) {
|
||||
filterStatus.value = undefined;
|
||||
} else {
|
||||
filterStatus.value = status;
|
||||
}
|
||||
};
|
||||
|
||||
// 过滤传输行
|
||||
const filterItem = (item: SftpTransferItem) => {
|
||||
return !filterStatus.value || item.status === filterStatus.value;
|
||||
};
|
||||
|
||||
// 移除全部任务
|
||||
const removeAllTask = () => {
|
||||
transferManager.cancelAllTransfer();
|
||||
};
|
||||
|
||||
// 关闭
|
||||
@@ -146,14 +122,60 @@
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@icon-size: 20px;
|
||||
@item-left-width: 42px;
|
||||
@item-right-width: 42px;
|
||||
@item-center-width: 388px - @item-left-width - @item-right-width;
|
||||
<style lang="less">
|
||||
|
||||
:deep(.transfer-item-wrapper) {
|
||||
padding: 0 !important;
|
||||
.transfer-drawer {
|
||||
.arco-drawer-body {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@header-height: 48px;
|
||||
|
||||
.transfer-container {
|
||||
position: relative;
|
||||
|
||||
.transfer-header {
|
||||
padding: 8px;
|
||||
width: 100%;
|
||||
height: @header-height;
|
||||
position: absolute;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
&-icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.status-count {
|
||||
display: inline-block;
|
||||
margin-left: 4px;
|
||||
user-select: none;
|
||||
}
|
||||
}
|
||||
|
||||
.transfer-item-container {
|
||||
width: 100%;
|
||||
height: calc(100% - @header-height);
|
||||
position: absolute;
|
||||
top: @header-height;
|
||||
overflow: auto;
|
||||
|
||||
:deep(.arco-list-item) {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
:deep(.arco-scrollbar) {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list-empty {
|
||||
@@ -161,86 +183,4 @@
|
||||
margin-top: 32px;
|
||||
}
|
||||
|
||||
.transfer-item {
|
||||
min-height: 36px;
|
||||
padding: 8px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&:hover {
|
||||
.transfer-item-right-progress {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.transfer-item-right-actions {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
&-left {
|
||||
width: @item-left-width;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
.file-icon {
|
||||
color: rgb(var(--arcoblue-6));
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
&-center {
|
||||
width: @item-center-width;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.file-name {
|
||||
color: var(--color-content-text-1);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
width: fit-content;
|
||||
max-width: 100%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.transfer-progress, .target-path, .error-message {
|
||||
padding-top: 4px;
|
||||
font-size: 13px;
|
||||
color: var(--color-neutral-8);
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
color: rgba(var(--red-6));
|
||||
}
|
||||
}
|
||||
|
||||
&-right {
|
||||
width: @item-right-width;
|
||||
|
||||
&-progress {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
&-actions {
|
||||
display: none;
|
||||
justify-content: center;
|
||||
|
||||
.close-icon {
|
||||
width: @icon-size;
|
||||
height: @icon-size;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background: var(--color-fill-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
<template>
|
||||
<a-list-item class="transfer-item-wrapper">
|
||||
<div class="transfer-item">
|
||||
<!-- 左侧图标 -->
|
||||
<div class="transfer-item-left">
|
||||
<span class="file-icon">
|
||||
<icon-upload v-if="item.type === TransferType.UPLOAD" />
|
||||
<icon-download v-else-if="item.type === TransferType.DOWNLOAD" />
|
||||
</span>
|
||||
</div>
|
||||
<!-- 中间信息 -->
|
||||
<div class="transfer-item-center">
|
||||
<!-- 文件名称 -->
|
||||
<span class="file-name text-copy"
|
||||
:title="item.name"
|
||||
@click="copy(item.name)">
|
||||
{{ item.name }}
|
||||
</span>
|
||||
<!-- 传输进度 -->
|
||||
<span class="transfer-progress">
|
||||
<!-- 当前大小 -->
|
||||
<span v-if="item.status === TransferStatus.TRANSFERRING">{{ getFileSize(item.currentSize) }}</span>
|
||||
<span class="mx4" v-if="item.status === TransferStatus.TRANSFERRING">/</span>
|
||||
<!-- 总大小 -->
|
||||
<span>{{ getFileSize(item.totalSize) }}</span>
|
||||
<!-- 进度百分比 -->
|
||||
<span class="ml8" v-if="item.status === TransferStatus.TRANSFERRING">
|
||||
{{ item.progress }}%
|
||||
</span>
|
||||
</span>
|
||||
<!-- 目标目录 -->
|
||||
<span class="target-path text-copy"
|
||||
:title="item.parentPath"
|
||||
@click="copy(item.parentPath)">
|
||||
{{ item.parentPath }}
|
||||
</span>
|
||||
<!-- 错误信息 -->
|
||||
<a-tooltip v-if="item.errorMessage"
|
||||
position="top"
|
||||
:mini="true"
|
||||
:auto-fix-position="false"
|
||||
content-class="terminal-tooltip-content"
|
||||
arrow-class="terminal-tooltip-content"
|
||||
:content="item.errorMessage">
|
||||
<span class="error-message">
|
||||
{{ item.errorMessage }}
|
||||
</span>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
<!-- 右侧状态/操作-->
|
||||
<div class="transfer-item-right">
|
||||
<!-- 传输状态 -->
|
||||
<div class="transfer-item-right-progress">
|
||||
<!-- 等待传输 -->
|
||||
<icon-clock-circle v-if="item.status === TransferStatus.WAITING" />
|
||||
<!-- 传输进度 -->
|
||||
<a-progress v-else
|
||||
type="circle"
|
||||
size="mini"
|
||||
:status="getDictValue(transferStatusKey, item.status, 'status')"
|
||||
:percent="item.currentSize / item.totalSize" />
|
||||
</div>
|
||||
<!-- 传输操作 -->
|
||||
<div class="transfer-item-right-actions">
|
||||
<!-- 关闭 -->
|
||||
<span class="close-icon" @click="removeTask(item.fileId)">
|
||||
<icon-close />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-list-item>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'transferItem'
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { SftpTransferItem } from '../../types/terminal.type';
|
||||
import useLoading from '@/hooks/loading';
|
||||
import useVisible from '@/hooks/visible';
|
||||
import { useDictStore, useTerminalStore } from '@/store';
|
||||
import { copy } from '@/hooks/copy';
|
||||
import { getFileSize } from '@/utils/file';
|
||||
import { TransferStatus, TransferType, transferStatusKey } from '../../types/terminal.const';
|
||||
|
||||
const props = defineProps<{
|
||||
item: SftpTransferItem;
|
||||
}>();
|
||||
|
||||
const { transferManager } = useTerminalStore();
|
||||
const { getDictValue } = useDictStore();
|
||||
const { visible, setVisible } = useVisible();
|
||||
const { loading, setLoading } = useLoading();
|
||||
|
||||
// 移除任务
|
||||
const removeTask = (fileId: string) => {
|
||||
transferManager.cancelTransfer(fileId);
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@icon-size: 20px;
|
||||
@item-left-width: 42px;
|
||||
@item-right-width: 42px;
|
||||
@item-center-width: 388px - @item-left-width - @item-right-width;
|
||||
|
||||
.transfer-item {
|
||||
min-height: 36px;
|
||||
padding: 8px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&:hover {
|
||||
.transfer-item-right-progress {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.transfer-item-right-actions {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
&-left {
|
||||
width: @item-left-width;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
.file-icon {
|
||||
color: rgb(var(--arcoblue-6));
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
&-center {
|
||||
width: @item-center-width;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.file-name, .target-path {
|
||||
color: var(--color-content-text-1);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
width: fit-content;
|
||||
max-width: 100%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.transfer-progress, .target-path, .error-message {
|
||||
padding-top: 4px;
|
||||
font-size: 13px;
|
||||
color: var(--color-neutral-8);
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
color: rgba(var(--red-6));
|
||||
}
|
||||
}
|
||||
|
||||
&-right {
|
||||
width: @item-right-width;
|
||||
|
||||
&-progress {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
&-actions {
|
||||
display: none;
|
||||
justify-content: center;
|
||||
|
||||
.close-icon {
|
||||
width: @icon-size;
|
||||
height: @icon-size;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background: var(--color-fill-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -96,6 +96,16 @@ export default class SftpTransferManager implements ISftpTransferManager {
|
||||
this.transferList.splice(index, 1);
|
||||
}
|
||||
|
||||
// 取消全部传输
|
||||
cancelAllTransfer(): void {
|
||||
// 从列表中移除非传输中的元素
|
||||
this.transferList.reduceRight((_, value: SftpTransferItem, index: number) => {
|
||||
if (value.status !== TransferStatus.TRANSFERRING) {
|
||||
this.transferList.splice(index, 1);
|
||||
}
|
||||
}, null as any);
|
||||
}
|
||||
|
||||
// 打开会话
|
||||
private async openClient() {
|
||||
this.run = true;
|
||||
|
||||
@@ -30,9 +30,9 @@
|
||||
</div>
|
||||
</main>
|
||||
<!-- 命令片段列表抽屉 -->
|
||||
<command-snippet-list-drawer ref="snippetRef" />
|
||||
<command-snippet-drawer ref="snippetRef" />
|
||||
<!-- 路径书签列表抽屉 -->
|
||||
<path-bookmark-list-drawer ref="pathRef" />
|
||||
<path-bookmark-drawer ref="pathRef" />
|
||||
<!-- 传输列表 -->
|
||||
<transfer-drawer ref="transferRef" />
|
||||
</div>
|
||||
@@ -57,8 +57,8 @@
|
||||
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 CommandSnippetListDrawer from '@/views/host/command-snippet/components/command-snippet-list-drawer.vue';
|
||||
import PathBookmarkListDrawer from '@/views/host/path-bookmark/components/path-bookmark-list-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 '@/assets/style/host-terminal-layout.less';
|
||||
import 'xterm/css/xterm.css';
|
||||
|
||||
|
||||
@@ -320,9 +320,9 @@ export const TerminalShortcutItems: Array<ShortcutKeyItem> = [
|
||||
// 传输状态
|
||||
export const TransferStatus = {
|
||||
WAITING: 'waiting',
|
||||
TRANSFERRING: 'normal',
|
||||
TRANSFERRING: 'transferring',
|
||||
SUCCESS: 'success',
|
||||
ERROR: 'danger',
|
||||
ERROR: 'error',
|
||||
};
|
||||
|
||||
// 传输类型
|
||||
@@ -390,16 +390,19 @@ export const extraSshAuthTypeKey = 'hostExtraSshAuthType';
|
||||
export const connectStatusKey = 'terminalConnectStatus';
|
||||
|
||||
// 终端类型
|
||||
export const terminalEmulationTypeKey = 'terminalEmulationType';
|
||||
export const emulationTypeKey = 'terminalEmulationType';
|
||||
|
||||
// 终端标签颜色
|
||||
export const terminalTabColorKey = 'terminalTabColor';
|
||||
export const tabColorKey = 'terminalTabColor';
|
||||
|
||||
// SFTP 传输状态
|
||||
export const transferStatusKey = 'sftpTransferStatus';
|
||||
|
||||
// 加载的字典值
|
||||
export const dictKeys = [
|
||||
fontFamilyKey, fontSizeKey,
|
||||
fontWeightKey, cursorStyleKey,
|
||||
newConnectionTypeKey, extraSshAuthTypeKey,
|
||||
connectStatusKey, terminalEmulationTypeKey,
|
||||
terminalTabColorKey
|
||||
connectStatusKey, emulationTypeKey,
|
||||
tabColorKey, transferStatusKey,
|
||||
];
|
||||
|
||||
@@ -402,6 +402,8 @@ export interface ISftpTransferManager {
|
||||
addDownload: (hostId: number, currentPath: string, files: Array<SftpFile>) => void;
|
||||
// 取消传输
|
||||
cancelTransfer: (fileId: string) => void;
|
||||
// 取消全部传输
|
||||
cancelAllTransfer: () => void;
|
||||
}
|
||||
|
||||
// sftp 上传器定义
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
<!-- 快捷定义 -->
|
||||
<a-tag v-for="definedExtraKey in definedExtraKeys"
|
||||
color="arcoblue"
|
||||
:title="`添加参数 ${definedExtraKey}`"
|
||||
:title="`添加参数 ${definedExtraKey.name}`"
|
||||
@click="addExtraParam(definedExtraKey.name, definedExtraKey.type)"
|
||||
checkable
|
||||
checked>
|
||||
@@ -72,7 +72,7 @@
|
||||
</a-tag>
|
||||
<!-- 添加参数 -->
|
||||
<a-button title="添加参数"
|
||||
style="width: 180px;"
|
||||
style="width: 140px;"
|
||||
@click="addExtraParam(undefined,undefined)"
|
||||
long>
|
||||
<icon-plus />
|
||||
|
||||
@@ -26,6 +26,9 @@ export const definedExtraKeys = [
|
||||
}, {
|
||||
name: 'color',
|
||||
type: ValueType.COLOR
|
||||
}, {
|
||||
name: 'icon',
|
||||
type: ValueType.STRING
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user