From 13997ea579ecfc378185923c6c3c2dd28d885897 Mon Sep 17 00:00:00 2001 From: lanyuanxiaoyao Date: Wed, 11 Dec 2024 16:25:17 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=88=97=E8=A1=A8=E9=A1=B9?= =?UTF-8?q?=E5=86=85=E5=AE=B9=E5=B8=83=E5=B1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.vue | 10 +++++++--- src/components/VirtualList.vue | 36 +++++++++++++++++++++++++--------- src/types/index.ts | 2 ++ 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/src/App.vue b/src/App.vue index 41e0d39..bdd9859 100644 --- a/src/App.vue +++ b/src/App.vue @@ -2,16 +2,20 @@ import ProjectList from './components/ProjectList.vue' import type { ListItem, MenuItem } from '@/types' +const samplePic = +'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHgAAAB4CAMAAAAOusbgAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAACf1BMVEVGQksvbmYyaWM0ZGA3X107WFk9U1VATlNDSU8ucWgyamQ2Yl88VlhDSE8wbWY1ZGAvb2c1ZGA+U1U6WloucWgzZ2I/UFQ0ZmFATVIyaWM/T1MyaWMwbWY7V1gucWg1Yl8wbWUucWg0ZWAvb2cwbWYxa2QzaGI0ZWFBTFE5XFszZmI0ZmE9VFY7WFkxa2RERk5BTVIxamQ2YV4xbGUvcGdATlI8Vlgvb2c6Wlo5XFswbWYucWgzZ2IucWgxa2Q9U1U7WFg5W1pCSlAucWgzZ2IyaWMucWg1Y19DSE43X103X104XlwvcGc8VlcxbGUvb2c3X10wbWU6WVk4XlxATlMyaWMucWg2YV4vbmYxa2RDR041Y18ucWgyaGM2YV4vb2c1Y185W1ovb2cwbGU8VVdCSU82Yl8+UVQxa2Q4XVs0ZWE1Yl8xbGU4XVwyaWM6WlowbWY2Yl8wbGUwbWY4XVs/T1M0ZmEvb2c3X109U1YwbWYwbmYxbGU4Xlw2YV4+UVU5XFs0ZmEvbmY5W1o+UlUwbmY6Wlo/UFQ1Y181Y180ZWEyamQzZ2JBS1Evb2c8Vlc5XFsvb2cyaWM2Yl8vcGcvb2dDSU80ZWE7V1g1Yl9BTFExamRER049VFY6WVk6WlpBS1AwbWU0ZWEyaWM7WFkvb2c0ZmE5W1ozaGIxbGU4XVs1ZGAyamQzaGIxa2RCSVAzaGI7V1g6WVk2YV4zZ2I9VFYxbGU0ZmEucWgwbmYzZmIzaGIxa2QwbWY4Xlw3YF03YF5CSlAxamQvb2cyaWM0ZWA2YV43X11AT1M3X107V1gwbGVFRU1GQktFRExERU1GQ0tFQ0xERk5ERk3///+ARxMXAAAAzHRSTlMAMXyqzeXy+f4UdL7s/jivKrDz4wiX9pz6ffh/RusKuU0CqBdFao+n+9qbofHnaP77cMNfIfrrH+DbQwSSBmTz6Nz9FpN6ErP+y8rQI+1aMM9P5dL6gQ7CNWf+sgyHxBu03SxU7v279mXYprZc1YPhQbxZStf5mR3M8kg8V9HA9dygM9/0PuL3uLWidpb8KOzZJoa9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' // 生成模拟数据 -const listData: ListItem[] = Array.from({ length: 50 }, (_, i) => ({ +const listData: ListItem[] = Array.from({ length: 1000 }, (_, i) => ({ id: i, name: `project-${i + 1}`, path: `/Users/lanyuanxiaoyao/Project/IdeaProjects/project-${i + 1}`, + // 随机选择一个图标 + icon: samplePic, tags: [ { id: 1, name: 'Vue', color: '#42b883' }, { id: 2, name: 'TypeScript', color: '#3178c6' }, - ...(i % 3 === 0 ? [{ id: 3, name: 'React', color: '#61dafb' }] : []), - ...(i % 4 === 0 ? [{ id: 4, name: 'Node.js', color: '#339933' }] : []), + ...(i % 3 === 0 ? [{ id: 3, name: 'React', color: '#149eca' }] : []), + ...(i % 4 === 0 ? [{ id: 4, name: 'Node.js', color: '#539e43' }] : []), ] })) diff --git a/src/components/VirtualList.vue b/src/components/VirtualList.vue index e138b47..f11f80c 100644 --- a/src/components/VirtualList.vue +++ b/src/components/VirtualList.vue @@ -28,7 +28,7 @@ const ITEM_HEIGHT = 50 /** 列表项内边距总和(像素) */ const ITEM_PADDING = 16 /** 上下缓冲区域的项目数量 */ -const BUFFER_COUNT = 10 +const BUFFER_COUNT = 100 /** 滚动防抖时间(毫秒) */ const SCROLL_DEBOUNCE_TIME = 16 /** 虚拟滚动阈值,少于此数量则直接渲染全部 */ @@ -386,8 +386,15 @@ onBeforeUnmount(() => {
- - + + +
@@ -401,7 +408,7 @@ onBeforeUnmount(() => { v-for="tag in item.tags" :key="tag.id" class="item-tag" - :style="{ backgroundColor: `${tag.color}15`, color: tag.color }" + :style="{ backgroundColor: tag.color }" > {{ tag.name }} @@ -431,7 +438,7 @@ onBeforeUnmount(() => { height: 100%; } -/* 虚拟高度容器:用于保持滚动条比例 */ +/* 拟高度容器:用于保持滚动条比例 */ .virtual-list-phantom { position: relative; width: 100%; @@ -447,7 +454,7 @@ onBeforeUnmount(() => { /* 列表项基础样式 */ .list-item { - padding: 8px 16px; + padding: 8px 12px 8px 8px; display: flex; align-items: center; transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1); @@ -473,12 +480,20 @@ onBeforeUnmount(() => { /* 图标容器 */ .item-icon { flex-shrink: 0; - width: 24px; - height: 24px; + width: 45px; + height: 45px; display: flex; align-items: center; justify-content: center; color: rgba(0, 0, 0, 0.54); + overflow: hidden; +} + +/* 图标图片样式 */ +.item-icon img { + width: 32px; + height: 32px; + object-fit: contain; } /* 内容区域布局 */ @@ -494,7 +509,6 @@ onBeforeUnmount(() => { .item-header { display: flex; align-items: center; - gap: 12px; min-width: 0; } @@ -508,6 +522,7 @@ onBeforeUnmount(() => { text-overflow: ellipsis; flex-shrink: 1; min-width: 0; + margin-right: auto; } /* 信息行布局 */ @@ -533,6 +548,7 @@ onBeforeUnmount(() => { flex-wrap: nowrap; flex-shrink: 0; overflow: hidden; + margin-left: 12px; } /* 单个标签样式 */ @@ -545,6 +561,8 @@ onBeforeUnmount(() => { flex-shrink: 0; letter-spacing: 0.4px; text-transform: uppercase; + color: #fff !important; + opacity: 0.9; } /* 列表冻结状态样式 */ diff --git a/src/types/index.ts b/src/types/index.ts index 3185e91..3882bf0 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -20,6 +20,8 @@ export interface ListItem { name: string /** 项目路径 */ path: string + /** 项目图标 URL */ + icon?: string /** 项目标签列表 */ tags?: Tag[] /** 在虚拟列表中的索引位置 */