🔨 sftp 表头.
This commit is contained in:
@@ -7,7 +7,7 @@ import { TablePageSizeOptions } from '@/types/const';
|
||||
/**
|
||||
* 创建列表分页
|
||||
*/
|
||||
export const usePagination = (): PaginationProps => {
|
||||
export const usePagination = (ext?: PaginationProps): PaginationProps => {
|
||||
const appStore = useAppStore();
|
||||
return reactive({
|
||||
total: 0,
|
||||
@@ -15,17 +15,19 @@ export const usePagination = (): PaginationProps => {
|
||||
pageSize: isNumber(appStore.defaultTablePageSize) ? appStore.defaultTablePageSize : TablePageSizeOptions[0],
|
||||
showTotal: true,
|
||||
showPageSize: true,
|
||||
pageSizeOptions: TablePageSizeOptions
|
||||
pageSizeOptions: TablePageSizeOptions,
|
||||
...ext
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 创建行选择器
|
||||
*/
|
||||
export const useRowSelection = (type = 'checkbox'): TableRowSelection => {
|
||||
export const useRowSelection = (ext?: TableRowSelection): TableRowSelection => {
|
||||
return reactive({
|
||||
type: type as any,
|
||||
type: 'checkbox',
|
||||
showCheckedAll: true,
|
||||
onlyCurrent: true,
|
||||
...ext
|
||||
});
|
||||
};
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
<template>
|
||||
<!-- 表头 -->
|
||||
<div class="sftp-table-header">
|
||||
<!-- 左侧操作 -->
|
||||
<div class="sftp-table-header-left">
|
||||
<!-- 返回上级 -->
|
||||
<a-tooltip position="top"
|
||||
:mini="true"
|
||||
:overlay-inverse="true"
|
||||
:auto-fix-position="false"
|
||||
content-class="terminal-tooltip-content"
|
||||
arrow-class="terminal-tooltip-content"
|
||||
content="返回上级">
|
||||
<span class="click-icon-wrapper header-action-icon mr4">
|
||||
<icon-left />
|
||||
</span>
|
||||
</a-tooltip>
|
||||
<!-- 当前路径 -->
|
||||
<div class="sftp-path-wrapper">
|
||||
<a-breadcrumb>
|
||||
<!-- 分隔符 -->
|
||||
<template #separator>
|
||||
<icon-right />
|
||||
</template>
|
||||
<a-breadcrumb-item class="sftp-path-unit">/</a-breadcrumb-item>
|
||||
<a-breadcrumb-item class="sftp-path-unit">root</a-breadcrumb-item>
|
||||
<a-breadcrumb-item class="sftp-path-unit">orion</a-breadcrumb-item>
|
||||
<a-breadcrumb-item class="sftp-path-unit">space</a-breadcrumb-item>
|
||||
<a-breadcrumb-item class="sftp-path-unit">logs</a-breadcrumb-item>
|
||||
</a-breadcrumb>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 右侧操作 -->
|
||||
<a-space class="sftp-table-header-right">
|
||||
<!-- 刷新 -->
|
||||
<a-tooltip position="top"
|
||||
:mini="true"
|
||||
:overlay-inverse="true"
|
||||
:auto-fix-position="false"
|
||||
content-class="terminal-tooltip-content"
|
||||
arrow-class="terminal-tooltip-content"
|
||||
content="刷新">
|
||||
<span class="click-icon-wrapper header-action-icon">
|
||||
<icon-refresh />
|
||||
</span>
|
||||
</a-tooltip>
|
||||
<!-- 显示隐藏文件 -->
|
||||
<a-tooltip position="top"
|
||||
:mini="true"
|
||||
:overlay-inverse="true"
|
||||
:auto-fix-position="false"
|
||||
content-class="terminal-tooltip-content"
|
||||
arrow-class="terminal-tooltip-content"
|
||||
content="显示隐藏文件">
|
||||
<span class="click-icon-wrapper header-action-icon">
|
||||
<icon-eye />
|
||||
</span>
|
||||
</a-tooltip>
|
||||
<!-- 创建文件 -->
|
||||
<a-tooltip position="top"
|
||||
:mini="true"
|
||||
:overlay-inverse="true"
|
||||
:auto-fix-position="false"
|
||||
content-class="terminal-tooltip-content"
|
||||
arrow-class="terminal-tooltip-content"
|
||||
content="创建文件">
|
||||
<span class="click-icon-wrapper header-action-icon">
|
||||
<icon-drive-file />
|
||||
</span>
|
||||
</a-tooltip>
|
||||
<!-- 创建文件夹 -->
|
||||
<a-tooltip position="top"
|
||||
:mini="true"
|
||||
:overlay-inverse="true"
|
||||
:auto-fix-position="false"
|
||||
content-class="terminal-tooltip-content"
|
||||
arrow-class="terminal-tooltip-content"
|
||||
content="创建文件夹">
|
||||
<span class="click-icon-wrapper header-action-icon">
|
||||
<icon-folder-add />
|
||||
</span>
|
||||
</a-tooltip>
|
||||
<!-- 删除 -->
|
||||
<a-tooltip position="top"
|
||||
:mini="true"
|
||||
:overlay-inverse="true"
|
||||
:auto-fix-position="false"
|
||||
content-class="terminal-tooltip-content"
|
||||
arrow-class="terminal-tooltip-content"
|
||||
content="删除">
|
||||
<span class="click-icon-wrapper header-action-icon">
|
||||
<icon-delete />
|
||||
</span>
|
||||
</a-tooltip>
|
||||
<!-- 复制 -->
|
||||
<a-tooltip position="top"
|
||||
:mini="true"
|
||||
:overlay-inverse="true"
|
||||
:auto-fix-position="false"
|
||||
content-class="terminal-tooltip-content"
|
||||
arrow-class="terminal-tooltip-content"
|
||||
content="复制">
|
||||
<span class="click-icon-wrapper header-action-icon">
|
||||
<icon-copy />
|
||||
</span>
|
||||
</a-tooltip>
|
||||
<!-- 移动 -->
|
||||
<a-tooltip position="top"
|
||||
:mini="true"
|
||||
:overlay-inverse="true"
|
||||
:auto-fix-position="false"
|
||||
content-class="terminal-tooltip-content"
|
||||
arrow-class="terminal-tooltip-content"
|
||||
content="移动">
|
||||
<span class="click-icon-wrapper header-action-icon">
|
||||
<icon-paste />
|
||||
</span>
|
||||
</a-tooltip>
|
||||
<!-- 上传 -->
|
||||
<a-tooltip position="top"
|
||||
:mini="true"
|
||||
:overlay-inverse="true"
|
||||
:auto-fix-position="false"
|
||||
content-class="terminal-tooltip-content"
|
||||
arrow-class="terminal-tooltip-content"
|
||||
content="上传">
|
||||
<span class="click-icon-wrapper header-action-icon">
|
||||
<icon-upload />
|
||||
</span>
|
||||
</a-tooltip>
|
||||
<!-- 下载 -->
|
||||
<a-tooltip position="top"
|
||||
:mini="true"
|
||||
:overlay-inverse="true"
|
||||
:auto-fix-position="false"
|
||||
content-class="terminal-tooltip-content"
|
||||
arrow-class="terminal-tooltip-content"
|
||||
content="下载">
|
||||
<span class="click-icon-wrapper header-action-icon">
|
||||
<icon-download />
|
||||
</span>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'sftpTableHeader'
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
.sftp-table-header {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
&-left, &-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
&-left {
|
||||
width: calc(100% - 302px);
|
||||
}
|
||||
|
||||
&-right {
|
||||
width: 302px;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
.sftp-path-wrapper {
|
||||
background: var(--color-fill-2);
|
||||
width: 100%;
|
||||
border-radius: 2px;
|
||||
padding: 1px 6px;
|
||||
overflow: hidden;
|
||||
|
||||
:deep(.sftp-path-unit) {
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: rgb(var(--arcoblue-6));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.header-action-icon {
|
||||
font-size: 16px;
|
||||
padding: 4px;
|
||||
}
|
||||
</style>
|
||||
@@ -27,10 +27,88 @@
|
||||
</a-space>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 文件名称 -->
|
||||
<template #fileName="{ record }">
|
||||
<!-- 文件图标 -->
|
||||
<span class="file-name-icon" :title="formatFileType(record.attr).label">
|
||||
<component :is="formatFileType(record.attr).icon" />
|
||||
</span>
|
||||
<span>
|
||||
{{ record.name }}
|
||||
</span>
|
||||
</template>
|
||||
<!-- 文件大小 -->
|
||||
<template #size="{ record }">
|
||||
<span v-if="editRecord.name === record.name">操作</span>
|
||||
<span v-else>{{ record.size }}</span>
|
||||
<span>{{ record.size }}</span>
|
||||
</template>
|
||||
<!-- 修改时间/操作 -->
|
||||
<template #modifyTime="{ record }">
|
||||
<!-- 修改时间 -->
|
||||
<span v-if="editName !== record.name">{{ dateFormat(new Date(record.modifyTime)) }}</span>
|
||||
<!-- 操作 -->
|
||||
<a-space v-else>
|
||||
<!-- 复制路径 -->
|
||||
<a-tooltip position="top"
|
||||
:mini="true"
|
||||
:overlay-inverse="true"
|
||||
:auto-fix-position="false"
|
||||
content-class="terminal-tooltip-content"
|
||||
arrow-class="terminal-tooltip-content"
|
||||
content="复制路径">
|
||||
<span class="click-icon-wrapper row-action-icon"
|
||||
@click="copy(record.path, false)">
|
||||
<icon-copy />
|
||||
</span>
|
||||
</a-tooltip>
|
||||
<!-- 删除 -->
|
||||
<a-tooltip position="top"
|
||||
:mini="true"
|
||||
:auto-fix-position="false"
|
||||
content-class="terminal-tooltip-content"
|
||||
arrow-class="terminal-tooltip-content"
|
||||
content="删除">
|
||||
<span class="click-icon-wrapper row-action-icon"
|
||||
@click="deleteFile(record.path)">
|
||||
<icon-delete />
|
||||
</span>
|
||||
</a-tooltip>
|
||||
<!-- 下载 -->
|
||||
<a-tooltip position="top"
|
||||
:mini="true"
|
||||
:auto-fix-position="false"
|
||||
content-class="terminal-tooltip-content"
|
||||
arrow-class="terminal-tooltip-content"
|
||||
content="下载">
|
||||
<span class="click-icon-wrapper row-action-icon"
|
||||
@click="downloadFile(record.path)">
|
||||
<icon-download />
|
||||
</span>
|
||||
</a-tooltip>
|
||||
<!-- 移动 -->
|
||||
<a-tooltip position="top"
|
||||
:mini="true"
|
||||
:auto-fix-position="false"
|
||||
content-class="terminal-tooltip-content"
|
||||
arrow-class="terminal-tooltip-content"
|
||||
content="移动">
|
||||
<span class="click-icon-wrapper row-action-icon"
|
||||
@click="moveFile(record.path)">
|
||||
<icon-paste />
|
||||
</span>
|
||||
</a-tooltip>
|
||||
<!-- 提权 -->
|
||||
<a-tooltip position="top"
|
||||
:mini="true"
|
||||
:auto-fix-position="false"
|
||||
content-class="terminal-tooltip-content"
|
||||
arrow-class="terminal-tooltip-content"
|
||||
content="提权">
|
||||
<span class="click-icon-wrapper row-action-icon"
|
||||
@click="chmodFile(record.path)">
|
||||
<icon-user-group />
|
||||
</span>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</template>
|
||||
</a-table>
|
||||
</template>
|
||||
@@ -46,33 +124,62 @@
|
||||
import type { SftpFile } from '../../types/terminal.type';
|
||||
import { ref } from 'vue';
|
||||
import { useRowSelection } from '@/types/table';
|
||||
import { dateFormat } from '@/utils';
|
||||
import columns from './types/table.columns';
|
||||
import useCopy from '@/hooks/copy';
|
||||
import { FILE_TYPE } from '../../types/terminal.const';
|
||||
|
||||
const props = defineProps<{
|
||||
list: Array<SftpFile>;
|
||||
loading: boolean;
|
||||
}>();
|
||||
|
||||
const rowSelection = useRowSelection();
|
||||
const rowSelection = useRowSelection({ width: 40 });
|
||||
const { copy } = useCopy();
|
||||
|
||||
const selectedKeys = ref<Array<string>>([]);
|
||||
const editRecord = ref<TableData>({});
|
||||
const editName = ref<string>('');
|
||||
|
||||
// 设置选中状态
|
||||
const setEditable = (record: TableData) => {
|
||||
editRecord.value = record;
|
||||
editName.value = record.name;
|
||||
record.hover = true;
|
||||
};
|
||||
|
||||
// 设置未选中状态
|
||||
const unsetEditable = (record: TableData) => {
|
||||
setTimeout(() => {
|
||||
if (record.name === editRecord.value.name && !record.hover) {
|
||||
editRecord.value = {};
|
||||
// 等待后如果还是当前行 但是未被选中则代表已经被失焦
|
||||
if (record.name === editName.value && !record.hover) {
|
||||
editName.value = '';
|
||||
}
|
||||
}, 20);
|
||||
record.hover = false;
|
||||
};
|
||||
|
||||
// 删除文件
|
||||
const deleteFile = (path: string) => {
|
||||
};
|
||||
|
||||
// 下载文件
|
||||
const downloadFile = (path: string) => {
|
||||
};
|
||||
|
||||
// 移动文件
|
||||
const moveFile = (path: string) => {
|
||||
};
|
||||
|
||||
// 文件提权
|
||||
const chmodFile = (path: string) => {
|
||||
};
|
||||
|
||||
// 格式化文件类型
|
||||
const formatFileType = (attr: string) => {
|
||||
return Object.values(FILE_TYPE).find(s => {
|
||||
return s.value === attr.charAt(0);
|
||||
}) || FILE_TYPE.NORMAL_FILE;
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@@ -94,4 +201,28 @@
|
||||
}
|
||||
}
|
||||
|
||||
.file-name-icon {
|
||||
font-size: 16px;
|
||||
line-height: 16px;
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
.row-action-icon {
|
||||
font-size: 16px;
|
||||
padding: 4px;
|
||||
background: unset;
|
||||
|
||||
&:hover {
|
||||
background: var(--color-fill-3);
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.action-cell .arco-table-cell) {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
:deep(.arco-table-th-title) {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -1,24 +1,19 @@
|
||||
<template>
|
||||
<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" />
|
||||
<div class="sftp-table-container">
|
||||
<!-- 表头 -->
|
||||
<sftp-table-header class="sftp-table-header" />
|
||||
<!-- 表格 -->
|
||||
<sftp-table class="sftp-table-wrapper"
|
||||
:list="list"
|
||||
:loading="loading" />
|
||||
</div>
|
||||
</template>
|
||||
<template #second v-if="editView">
|
||||
<div>editor</div>
|
||||
@@ -39,7 +34,8 @@
|
||||
import { useTerminalStore } from '@/store';
|
||||
import useLoading from '@/hooks/loading';
|
||||
import data from './data';
|
||||
import SftpTable from '@/views/host/terminal/components/sftp/sftp-table.vue';
|
||||
import SftpTable from './sftp-table.vue';
|
||||
import SftpTableHeader from './sftp-table-header.vue';
|
||||
|
||||
const props = defineProps<{
|
||||
tab: TerminalTabItem
|
||||
@@ -72,36 +68,31 @@
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@sftp-header-height: 36px;
|
||||
@sftp-table-header-height: 32px + 8px;
|
||||
|
||||
.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;
|
||||
.split-view {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&-right {
|
||||
justify-content: flex-end;
|
||||
.sftp-table-container {
|
||||
padding: 8px;
|
||||
height: 100%;
|
||||
|
||||
.sftp-table-header {
|
||||
width: 100%;
|
||||
height: @sftp-table-header-height;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
.sftp-table-wrapper {
|
||||
height: calc(100% - @sftp-table-header-height);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import type { TableColumnData } from '@arco-design/web-vue/es/table/interface';
|
||||
import { dateFormat } from '@/utils';
|
||||
|
||||
// 表格列
|
||||
const columns = [
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
slotName: 'name',
|
||||
fixed: 'left',
|
||||
slotName: 'fileName',
|
||||
ellipsis: true,
|
||||
tooltip: true,
|
||||
sortable: {
|
||||
sortDirections: ['ascend', 'descend'],
|
||||
},
|
||||
@@ -34,15 +34,7 @@ const columns = [
|
||||
sortable: {
|
||||
sortDirections: ['ascend', 'descend'],
|
||||
},
|
||||
render: ({ record }) => {
|
||||
return dateFormat(new Date(record.modifyTime));
|
||||
},
|
||||
}, {
|
||||
title: '操作',
|
||||
dataIndex: 'actions',
|
||||
slotName: 'actions',
|
||||
align: 'left',
|
||||
fixed: 'right',
|
||||
cellClass: 'action-cell',
|
||||
},
|
||||
] as TableColumnData[];
|
||||
|
||||
|
||||
@@ -52,6 +52,45 @@ export const ExtraSshAuthType = {
|
||||
CUSTOM_IDENTITY: 'CUSTOM_IDENTITY',
|
||||
};
|
||||
|
||||
// 文件类型
|
||||
export const FILE_TYPE = {
|
||||
NORMAL_FILE: {
|
||||
value: '-',
|
||||
label: '普通文件',
|
||||
icon: 'icon-file'
|
||||
},
|
||||
DIRECTORY: {
|
||||
value: 'd',
|
||||
label: '目录',
|
||||
icon: 'icon-folder'
|
||||
},
|
||||
LINK_FILE: {
|
||||
value: 'l',
|
||||
label: '链接文件',
|
||||
icon: 'icon-link'
|
||||
},
|
||||
MANAGE_FILE: {
|
||||
value: 'p',
|
||||
label: '管理文件',
|
||||
icon: 'icon-drive-file'
|
||||
},
|
||||
BLOCK_DEVICE_FILE: {
|
||||
value: 'b',
|
||||
label: '块设备文件',
|
||||
icon: 'icon-drive-file'
|
||||
},
|
||||
CHARACTER_DEVICE_FILE: {
|
||||
value: 'c',
|
||||
label: '字符设备文件',
|
||||
icon: 'icon-drive-file'
|
||||
},
|
||||
SOCKET_FILE: {
|
||||
value: 's',
|
||||
label: '套接字文件',
|
||||
icon: 'icon-drive-file'
|
||||
}
|
||||
};
|
||||
|
||||
// 面板会话 tab 类型
|
||||
export const PanelSessionType = {
|
||||
SSH: {
|
||||
|
||||
Reference in New Issue
Block a user