Private
Public Access
1
0

优化:文件列表紧凑布局,智能文件类型图标

This commit is contained in:
2026-01-26 02:31:12 +08:00
parent 307e0d987d
commit 3ec5446f80

View File

@@ -72,32 +72,31 @@
:loading="fileLoading" :loading="fileLoading"
:bordered="false" :bordered="false"
style="max-height: 500px; overflow-y: auto" style="max-height: 500px; overflow-y: auto"
:pagination="false"
> >
<template #item="{ item }"> <template #item="{ item }">
<a-list-item class="file-item"> <a-list-item class="file-item-compact">
<a-list-item-meta> <a-list-item-meta>
<template #title> <template #title>
<a-space> <div class="file-item-content">
<span style="font-size: 18px">{{ item.is_dir ? '📁' : '📄' }}</span> <span class="file-icon">{{ getFileIcon(item) }}</span>
<a @click="selectFile(item.path)" class="file-name">{{ item.name }}</a> <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 <a-button
type="text" type="text"
size="small" size="mini"
@click.stop="toggleFavorite(item)" @click.stop="toggleFavorite(item)"
:style="{ color: isFavorite(item.path) ? '#ffcd00' : '#86909c' }" class="favorite-btn"
> >
<template #icon> <template #icon>
<icon-star-fill v-if="isFavorite(item.path)" /> <icon-star-fill v-if="isFavorite(item.path)" />
<icon-star v-else /> <icon-star v-else />
</template> </template>
</a-button> </a-button>
</a-space> </div>
</template>
<template #description>
<a-space split="|">
<span v-if="!item.is_dir">{{ formatBytes(item.size) }}</span>
<span>{{ item.mod_time }}</span>
</a-space>
</template> </template>
</a-list-item-meta> </a-list-item-meta>
</a-list-item> </a-list-item>
@@ -270,6 +269,61 @@ const formatBytes = (bytes) => {
return (bytes / Math.pow(unit, exp)).toFixed(2) + ' ' + 'KMGTPE'[exp - 1] + 'B' 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 () => { const listDirectory = async () => {
if (!filePath.value) { if (!filePath.value) {
@@ -542,17 +596,78 @@ onMounted(() => {
padding: 16px; padding: 16px;
} }
.file-item { /* 紧凑型文件列表项 */
padding: 8px 0; .file-item-compact {
padding: 4px 0 !important;
margin: 0 !important;
} }
.file-item:hover { .file-item-content {
background: var(--color-fill-2); display: flex;
align-items: center;
gap: 8px;
width: 100%;
padding: 4px 8px;
border-radius: 4px; 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; 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 { .file-content-wrapper {