优化:文件列表紧凑布局,智能文件类型图标
This commit is contained in:
@@ -72,32 +72,31 @@
|
||||
:loading="fileLoading"
|
||||
:bordered="false"
|
||||
style="max-height: 500px; overflow-y: auto"
|
||||
:pagination="false"
|
||||
>
|
||||
<template #item="{ item }">
|
||||
<a-list-item class="file-item">
|
||||
<a-list-item class="file-item-compact">
|
||||
<a-list-item-meta>
|
||||
<template #title>
|
||||
<a-space>
|
||||
<span style="font-size: 18px">{{ item.is_dir ? '📁' : '📄' }}</span>
|
||||
<a @click="selectFile(item.path)" class="file-name">{{ item.name }}</a>
|
||||
<div class="file-item-content">
|
||||
<span class="file-icon">{{ getFileIcon(item) }}</span>
|
||||
<a @click="selectFile(item.path)" class="file-name-compact">{{ item.name }}</a>
|
||||
<span class="file-info-inline">
|
||||
<span v-if="!item.is_dir" class="file-size">{{ formatBytes(item.size) }}</span>
|
||||
<span class="file-time">{{ item.mod_time }}</span>
|
||||
</span>
|
||||
<a-button
|
||||
type="text"
|
||||
size="small"
|
||||
size="mini"
|
||||
@click.stop="toggleFavorite(item)"
|
||||
:style="{ color: isFavorite(item.path) ? '#ffcd00' : '#86909c' }"
|
||||
class="favorite-btn"
|
||||
>
|
||||
<template #icon>
|
||||
<icon-star-fill v-if="isFavorite(item.path)" />
|
||||
<icon-star v-else />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
<template #description>
|
||||
<a-space split="|">
|
||||
<span v-if="!item.is_dir">{{ formatBytes(item.size) }}</span>
|
||||
<span>{{ item.mod_time }}</span>
|
||||
</a-space>
|
||||
</div>
|
||||
</template>
|
||||
</a-list-item-meta>
|
||||
</a-list-item>
|
||||
@@ -270,6 +269,61 @@ const formatBytes = (bytes) => {
|
||||
return (bytes / Math.pow(unit, exp)).toFixed(2) + ' ' + 'KMGTPE'[exp - 1] + 'B'
|
||||
}
|
||||
|
||||
// 获取文件图标(根据文件类型)
|
||||
const getFileIcon = (item) => {
|
||||
if (item.is_dir) {
|
||||
return '📁'
|
||||
}
|
||||
|
||||
const ext = item.name.split('.').pop()?.toLowerCase() || ''
|
||||
|
||||
// 图片文件
|
||||
const imageExts = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'svg', 'webp', 'ico', 'heic', 'heif']
|
||||
if (imageExts.includes(ext)) return '🖼️'
|
||||
|
||||
// 视频文件
|
||||
const videoExts = ['mp4', 'avi', 'mkv', 'mov', 'wmv', 'flv', 'webm', 'm4v', 'rmvb', '3gp']
|
||||
if (videoExts.includes(ext)) return '🎬'
|
||||
|
||||
// 音频文件
|
||||
const audioExts = ['mp3', 'wav', 'flac', 'aac', 'ogg', 'wma', 'm4a', 'opus']
|
||||
if (audioExts.includes(ext)) return '🎵'
|
||||
|
||||
// 文档文件
|
||||
const docExts = ['doc', 'docx', 'pdf', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'rtf', 'odt', 'ods', 'odp']
|
||||
if (docExts.includes(ext)) {
|
||||
if (ext === 'pdf') return '📕'
|
||||
if (['doc', 'docx'].includes(ext)) return '📘'
|
||||
if (['xls', 'xlsx'].includes(ext)) return '📗'
|
||||
if (['ppt', 'pptx'].includes(ext)) return '📙'
|
||||
if (ext === 'txt') return '📃'
|
||||
return '📄'
|
||||
}
|
||||
|
||||
// 压缩文件
|
||||
const archiveExts = ['zip', 'rar', '7z', 'tar', 'gz', 'bz2', 'xz', 'z', 'cab', 'iso']
|
||||
if (archiveExts.includes(ext)) return '📦'
|
||||
|
||||
// 代码文件
|
||||
const codeExts = ['js', 'ts', 'jsx', 'tsx', 'vue', 'py', 'java', 'c', 'cpp', 'h', 'go', 'rs', 'php', 'rb', 'cs', 'swift', 'kt', 'scala', 'html', 'css', 'scss', 'less', 'json', 'xml', 'yaml', 'yml', 'sql', 'sh', 'bat', 'ps1']
|
||||
if (codeExts.includes(ext)) return '💻'
|
||||
|
||||
// 数据库文件
|
||||
const dbExts = ['db', 'sqlite', 'mdb', 'accdb']
|
||||
if (dbExts.includes(ext)) return '🗄️'
|
||||
|
||||
// 可执行文件
|
||||
const exeExts = ['exe', 'msi', 'app', 'dmg', 'deb', 'rpm']
|
||||
if (exeExts.includes(ext)) return '⚙️'
|
||||
|
||||
// 字体文件
|
||||
const fontExts = ['ttf', 'otf', 'woff', 'woff2', 'eot']
|
||||
if (fontExts.includes(ext)) return '🔤'
|
||||
|
||||
// 默认文件图标
|
||||
return '📄'
|
||||
}
|
||||
|
||||
// 列出目录
|
||||
const listDirectory = async () => {
|
||||
if (!filePath.value) {
|
||||
@@ -542,17 +596,78 @@ onMounted(() => {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.file-item {
|
||||
padding: 8px 0;
|
||||
/* 紧凑型文件列表项 */
|
||||
.file-item-compact {
|
||||
padding: 4px 0 !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.file-item:hover {
|
||||
background: var(--color-fill-2);
|
||||
.file-item-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
width: 100%;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
|
||||
.file-name {
|
||||
.file-item-content:hover {
|
||||
background: var(--color-fill-2);
|
||||
}
|
||||
|
||||
.file-icon {
|
||||
font-size: 18px;
|
||||
flex-shrink: 0;
|
||||
width: 24px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.file-name-compact {
|
||||
flex: 1;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.file-info-inline {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
font-size: 11px;
|
||||
color: var(--color-text-3);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.file-size {
|
||||
color: var(--color-text-3);
|
||||
}
|
||||
|
||||
.file-time {
|
||||
color: var(--color-text-3);
|
||||
}
|
||||
|
||||
.favorite-btn {
|
||||
flex-shrink: 0;
|
||||
padding: 0 4px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* 移除列表项的默认边距和内边距 */
|
||||
.file-item-compact :deep(.arco-list-item-meta) {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.file-item-compact :deep(.arco-list-item-meta-title) {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.file-item-compact :deep(.arco-list-item) {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.file-content-wrapper {
|
||||
|
||||
Reference in New Issue
Block a user