diff --git a/src/renderer/index.css b/src/renderer/index.css
index 1af7489..ffa64ea 100644
--- a/src/renderer/index.css
+++ b/src/renderer/index.css
@@ -136,3 +136,43 @@
font-size: 2.25rem;
}
}
+
+/* 骨架屏 shimmer 动画 */
+.skeleton-shimmer {
+ position: relative;
+ overflow: hidden;
+ background: #e5e7eb;
+}
+
+.skeleton-shimmer::after {
+ content: '';
+ position: absolute;
+ inset: 0;
+ background: linear-gradient(
+ 90deg,
+ transparent 0%,
+ rgba(255, 255, 255, 0.4) 50%,
+ transparent 100%
+ );
+ animation: shimmer 1.5s infinite;
+ transform: translateX(-100%);
+}
+
+:root.dark .skeleton-shimmer {
+ background: #262626;
+}
+
+:root.dark .skeleton-shimmer::after {
+ background: linear-gradient(
+ 90deg,
+ transparent 0%,
+ rgba(255, 255, 255, 0.06) 50%,
+ transparent 100%
+ );
+}
+
+@keyframes shimmer {
+ 100% {
+ transform: translateX(100%);
+ }
+}
diff --git a/src/renderer/layout/AppLayout.vue b/src/renderer/layout/AppLayout.vue
index 8b7f895..0e3a1c9 100644
--- a/src/renderer/layout/AppLayout.vue
+++ b/src/renderer/layout/AppLayout.vue
@@ -69,6 +69,10 @@ import { usePlayerStore } from '@/store/modules/player';
import { useSettingsStore } from '@/store/modules/settings';
import { isElectron } from '@/utils';
+// 关键布局组件同步导入(始终可见,避免加载闪烁)
+import AppMenu from './components/AppMenu.vue';
+import SearchBar from './components/SearchBar.vue';
+import TitleBar from './components/TitleBar.vue';
// 移动端专用布局
import MobileLayout from './MobileLayout.vue';
@@ -87,11 +91,9 @@ const keepAliveInclude = computed(() => {
.filter(Boolean);
});
-const AppMenu = defineAsyncComponent(() => import('./components/AppMenu.vue'));
+// 非关键组件保持异步加载
const PlayBar = defineAsyncComponent(() => import('@/components/player/PlayBar.vue'));
const MobilePlayBar = defineAsyncComponent(() => import('@/components/player/MobilePlayBar.vue'));
-const SearchBar = defineAsyncComponent(() => import('./components/SearchBar.vue'));
-const TitleBar = defineAsyncComponent(() => import('./components/TitleBar.vue'));
const PlayingListDrawer = defineAsyncComponent(
() => import('@/components/player/PlayingListDrawer.vue')
);
@@ -151,7 +153,7 @@ provide('openPlaylistDrawer', openPlaylistDrawer);
}
.menu {
- @apply h-full;
+ @apply h-full bg-light dark:bg-black;
}
.main {
diff --git a/src/renderer/layout/MobileLayout.vue b/src/renderer/layout/MobileLayout.vue
index ea503f2..d3f73d0 100644
--- a/src/renderer/layout/MobileLayout.vue
+++ b/src/renderer/layout/MobileLayout.vue
@@ -37,9 +37,8 @@ import otherRouter from '@/router/other';
import { useMenuStore } from '@/store/modules/menu';
import { usePlayerStore } from '@/store/modules/player';
+import AppMenu from './components/AppMenu.vue';
import MobileHeader from './components/MobileHeader.vue';
-
-const AppMenu = defineAsyncComponent(() => import('./components/AppMenu.vue'));
const MobilePlayBar = defineAsyncComponent(() => import('@/components/player/MobilePlayBar.vue'));
const PlayingListDrawer = defineAsyncComponent(
() => import('@/components/player/PlayingListDrawer.vue')
diff --git a/src/renderer/views/album/index.vue b/src/renderer/views/album/index.vue
index 2c326b3..60a0021 100644
--- a/src/renderer/views/album/index.vue
+++ b/src/renderer/views/album/index.vue
@@ -30,11 +30,9 @@