From 374238d15f2c8d9c19b9b359e96d88717e7e8777 Mon Sep 17 00:00:00 2001 From: yuyx <237899745@qq.com> Date: Thu, 19 Feb 2026 20:46:31 +0800 Subject: [PATCH] feat: restyle desktop file grid to baidu-style icon layout --- desktop-client/src/App.vue | 261 ++++++++++++++++++++++++++----------- 1 file changed, 187 insertions(+), 74 deletions(-) diff --git a/desktop-client/src/App.vue b/desktop-client/src/App.vue index 1984062..d58c7ce 100644 --- a/desktop-client/src/App.vue +++ b/desktop-client/src/App.vue @@ -563,17 +563,31 @@ function applyNativeUploadProgress(payload: NativeUploadProgressEvent) { } } -function fileIcon(item: FileItem) { - if (item.isDirectory || item.type === "directory") return "📁"; - const name = String(item.name || "").toLowerCase(); - if (/\.(jpg|jpeg|png|webp|gif|bmp|svg)$/.test(name)) return "🖼️"; - if (/\.(mp4|mkv|mov|avi)$/.test(name)) return "🎬"; - if (/\.(mp3|wav|flac|aac)$/.test(name)) return "🎵"; - if (/\.(zip|rar|7z|tar|gz)$/.test(name)) return "🗜️"; - if (/\.(pdf)$/.test(name)) return "📕"; - if (/\.(doc|docx)$/.test(name)) return "📘"; - if (/\.(xls|xlsx)$/.test(name)) return "📗"; - return "📄"; +function getFileExt(item: FileItem) { + if (item.isDirectory || item.type === "directory") return ""; + const text = String(item.displayName || item.name || "").trim(); + const idx = text.lastIndexOf("."); + if (idx <= 0 || idx >= text.length - 1) return ""; + return text.slice(idx + 1).toLowerCase(); +} + +function fileVisualKind(item: FileItem) { + if (item.isDirectory || item.type === "directory") return "folder"; + const ext = getFileExt(item); + if (!ext) return "file"; + if (["jpg", "jpeg", "png", "webp", "gif", "bmp", "svg", "heic"].includes(ext)) return "image"; + if (["mp4", "mkv", "mov", "avi", "webm", "flv"].includes(ext)) return "video"; + if (["mp3", "wav", "flac", "aac", "ogg", "m4a"].includes(ext)) return "audio"; + if (["zip", "rar", "7z", "tar", "gz", "bz2", "xz"].includes(ext)) return "archive"; + if (["pdf", "doc", "docx", "xls", "xlsx", "ppt", "pptx", "txt", "md", "csv"].includes(ext)) return "document"; + if (["apk", "exe", "msi", "dmg", "deb", "rpm"].includes(ext)) return "app"; + return "file"; +} + +function fileExtLabel(item: FileItem) { + const ext = getFileExt(item).toUpperCase(); + if (!ext) return "FILE"; + return ext.slice(0, 4); } function matchFileTypeFilter(item: FileItem, type: string) { @@ -2480,6 +2494,13 @@ onBeforeUnmount(() => { {{ pathState.mode === "search" ? "搜索结果" : "当前目录" }} {{ pathState.currentPath }} +
+ + {{ pathState.mode === "search" ? `搜索完成,共 ${filteredFiles.length} 个结果` : `已加载完成,共 ${filteredFiles.length} 个` }} + + 双击打开,右键查看更多操作 +
+
正在加载目录...
{{ pathState.error }}
@@ -2501,7 +2522,15 @@ onBeforeUnmount(() => {
{{ isBatchSelected(item.name) ? "✓" : "" }}
-
{{ fileIcon(item) }}
+
+ + +
-
{{ fileTypeLabel(item) }} · {{ item.isDirectory ? "-" : (item.sizeFormatted || formatBytes(item.size)) }}
-
{{ formatDate(item.modifiedAt) }}
@@ -3330,7 +3357,7 @@ select:focus { align-items: center; gap: 8px; flex-wrap: wrap; - justify-content: flex-end; + justify-content: flex-start; } .search-input { @@ -3447,21 +3474,49 @@ select:focus { text-overflow: ellipsis; } +.files-summary-bar { + height: 34px; + border: 1px solid #e8eef7; + border-radius: 10px; + background: #f8fbff; + padding: 0 12px; + display: flex; + align-items: center; + justify-content: space-between; + gap: 10px; + margin-bottom: 10px; +} + +.files-summary-main { + font-size: 12px; + color: #385373; + font-weight: 600; +} + +.files-summary-sub { + font-size: 12px; + color: #6b8097; +} + .icon-grid { display: grid; - gap: 12px; - grid-template-columns: repeat(auto-fill, 144px); + gap: 8px 10px; + grid-template-columns: repeat(auto-fill, 112px); justify-content: flex-start; align-content: start; min-height: 0; overflow: auto; - padding: 2px 4px 2px 2px; + padding: 4px; } .file-drop-surface { position: relative; min-height: 0; flex: 1; + border: 1px solid #e8eef7; + border-radius: 12px; + background: #fff; + padding: 12px 10px 10px; } .file-drop-surface.active .icon-grid { @@ -3469,19 +3524,19 @@ select:focus { } .file-card { - border: 1px solid #d8e1ee; - border-radius: 14px; - background: #fff; + border: 1px solid transparent; + border-radius: 10px; + background: transparent; text-align: left; - padding: 12px; + padding: 8px 6px; cursor: pointer; display: flex; flex-direction: column; - align-items: flex-start; + align-items: center; justify-content: flex-start; - gap: 6px; - width: 144px; - height: 144px; + gap: 4px; + width: 112px; + min-height: 132px; overflow: hidden; position: relative; } @@ -3492,66 +3547,139 @@ select:focus { } .file-card:hover { - border-color: #c6d7ee; - box-shadow: 0 6px 12px rgba(34, 72, 116, 0.08); + border-color: #d7e6fb; + background: #f3f8ff; } .file-card.selected { - border-color: #7baaf8; - background: #eef5ff; - box-shadow: 0 0 0 2px rgba(29, 111, 255, 0.1); + border-color: #a5c7f8; + background: #e8f2ff; + box-shadow: 0 0 0 1px rgba(73, 128, 216, 0.14) inset; } .file-card.batchSelected { - border-color: #3f84ec; - box-shadow: 0 0 0 2px rgba(63, 132, 236, 0.14); + border-color: #82b0f3; + background: #eaf3ff; + box-shadow: 0 0 0 1px rgba(63, 132, 236, 0.2) inset; } .file-card.renaming { border-color: #7baaf8; - box-shadow: 0 0 0 2px rgba(29, 111, 255, 0.14); + background: #eff6ff; } .batch-check { position: absolute; - right: 8px; - top: 8px; - width: 18px; - height: 18px; - border-radius: 6px; - border: 1px solid #c3d3e7; + right: 6px; + top: 6px; + width: 16px; + height: 16px; + border-radius: 999px; + border: 1px solid #bad0eb; background: #fff; - color: #2a5da6; + color: #1f67c9; display: grid; place-items: center; - font-size: 12px; + font-size: 11px; font-weight: 700; } .batch-check.active { - border-color: #3f84ec; - background: #e6f0ff; + border-color: #2e7be8; + background: #2e7be8; + color: #fff; } -.file-icon-glyph { - width: 48px; - height: 48px; +.file-icon-shell { + width: 62px; + height: 52px; + position: relative; + margin-top: 2px; border-radius: 10px; - border: 1px solid #d7e4f8; - background: #f2f7ff; - display: grid; - place-items: center; - font-size: 24px; + border: 1px solid #cfdced; + background: linear-gradient(180deg, #7ab5ff 0%, #4689dd 100%); + box-shadow: 0 2px 4px rgba(32, 77, 131, 0.14); +} + +.file-icon-shell.kind-folder { + height: 44px; + margin-top: 8px; + border-radius: 8px; + border-color: #d8b860; + background: linear-gradient(180deg, #f2c85e 0%, #e3b145 100%); + box-shadow: 0 2px 4px rgba(152, 106, 14, 0.14); +} + +.folder-tab { + position: absolute; + left: 9px; + top: -7px; + width: 24px; + height: 10px; + border-radius: 6px 6px 0 0; + background: linear-gradient(180deg, #f8d379 0%, #e8bc53 100%); + border: 1px solid #d8b860; + border-bottom: 0; +} + +.file-corner { + position: absolute; + right: 0; + top: 0; + width: 16px; + height: 16px; + background: rgba(255, 255, 255, 0.9); + clip-path: polygon(100% 0, 0 0, 100% 100%); + border-top-right-radius: 8px; +} + +.file-ext { + position: absolute; + left: 50%; + bottom: 7px; + transform: translateX(-50%); + color: #fff; + font-size: 10px; + font-weight: 700; + letter-spacing: 0.4px; line-height: 1; - margin-bottom: 2px; +} + +.file-icon-shell.kind-document { + background: linear-gradient(180deg, #79b6ff 0%, #4c8ee2 100%); +} + +.file-icon-shell.kind-image { + background: linear-gradient(180deg, #6fc7a1 0%, #3fa67b 100%); +} + +.file-icon-shell.kind-video { + background: linear-gradient(180deg, #88b4ff 0%, #5b7fd9 100%); +} + +.file-icon-shell.kind-audio { + background: linear-gradient(180deg, #ff9f7b 0%, #eb7059 100%); +} + +.file-icon-shell.kind-archive { + background: linear-gradient(180deg, #f6bc74 0%, #e58e3a 100%); +} + +.file-icon-shell.kind-app { + background: linear-gradient(180deg, #9cc36f 0%, #6ea649 100%); +} + +.file-icon-shell.kind-file { + background: linear-gradient(180deg, #95b0d3 0%, #6684ad 100%); } .file-name { - font-size: 13px; - font-weight: 600; + font-size: 12px; + font-weight: 500; color: #1f2b3a; - line-height: 1.35; + line-height: 1.4; width: 100%; + text-align: center; overflow: hidden; white-space: normal; overflow-wrap: anywhere; @@ -3559,13 +3687,13 @@ select:focus { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; - min-height: 34px; - max-height: 34px; + min-height: 33px; + max-height: 33px; } .inline-rename-input { width: 100%; - height: 28px; + height: 30px; border: 1px solid #7baaf8; border-radius: 8px; background: #fff; @@ -3581,21 +3709,6 @@ select:focus { box-shadow: 0 0 0 2px rgba(63, 132, 236, 0.16); } -.file-meta, -.file-time { - font-size: 11px; - color: #60768f; - line-height: 1.35; - width: 100%; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.file-time { - margin-top: auto; -} - .task-list { display: flex; flex-direction: column;