diff --git a/easyflow-ui-admin/app/src/components/page/ListPageShell.vue b/easyflow-ui-admin/app/src/components/page/ListPageShell.vue index b42d92b0..ef4ea700 100644 --- a/easyflow-ui-admin/app/src/components/page/ListPageShell.vue +++ b/easyflow-ui-admin/app/src/components/page/ListPageShell.vue @@ -131,7 +131,7 @@ const contentStyle = computed((): CSSProperties => { inset 0 1px 0 hsl(var(--glass-border) / 72%), 0 24px 54px -42px hsl(var(--primary) / 22%), 0 18px 42px -34px hsl(var(--foreground) / 10%); - backdrop-filter: blur(calc(var(--glass-blur) * 0.7)) saturate(145%); + backdrop-filter: var(--persistent-surface-backdrop-filter); } .list-page-shell.is-subtle .list-page-shell__content { diff --git a/easyflow-ui-admin/packages/@core/base/design/src/css/global.css b/easyflow-ui-admin/packages/@core/base/design/src/css/global.css index 6c93b44f..dbff2b35 100644 --- a/easyflow-ui-admin/packages/@core/base/design/src/css/global.css +++ b/easyflow-ui-admin/packages/@core/base/design/src/css/global.css @@ -16,6 +16,7 @@ html { @apply text-foreground bg-background font-sans text-[100%]; + background-color: hsl(var(--surface-canvas)); font-variation-settings: normal; line-height: 1.15; text-size-adjust: 100%; diff --git a/easyflow-ui-admin/packages/@core/base/design/src/design-tokens/dark.css b/easyflow-ui-admin/packages/@core/base/design/src/design-tokens/dark.css index 1f3e13a7..c0566f47 100644 --- a/easyflow-ui-admin/packages/@core/base/design/src/design-tokens/dark.css +++ b/easyflow-ui-admin/packages/@core/base/design/src/design-tokens/dark.css @@ -104,6 +104,7 @@ /* header */ --header: 220 18% 12.5%; --nav-surface: 220 18% 12.5%; + --nav-shell-surface: var(--nav-surface); --nav-surface-subtle: 219 18% 15.4%; --nav-border: 217 18% 23%; --nav-item-hover: 217 28% 18.8%; diff --git a/easyflow-ui-admin/packages/@core/base/design/src/design-tokens/default.css b/easyflow-ui-admin/packages/@core/base/design/src/design-tokens/default.css index 6252fb0c..3b145387 100644 --- a/easyflow-ui-admin/packages/@core/base/design/src/design-tokens/default.css +++ b/easyflow-ui-admin/packages/@core/base/design/src/design-tokens/default.css @@ -104,6 +104,7 @@ /* header */ --header: 212 100% 98.7%; --nav-surface: 212 100% 98.7%; + --nav-shell-surface: 211.2 86.2% 94.3%; --nav-surface-subtle: 211 84% 97.3%; --nav-border: 214 34% 89%; --nav-item-hover: 211 100% 96.3%; @@ -133,6 +134,8 @@ --glass-tint: 212 100% 98.9%; --glass-border: 0 0% 100%; --glass-blur: 20px; + /* 常驻大面积表面避免创建高开销背景模糊合成层 */ + --persistent-surface-backdrop-filter: none; --radius-modal: 20px; --modal-surface: 0 0% 100%; --modal-surface-strong: 0 0% 100%; diff --git a/easyflow-ui-admin/packages/@core/ui-kit/layout-ui/src/components/layout-header.vue b/easyflow-ui-admin/packages/@core/ui-kit/layout-ui/src/components/layout-header.vue index 2e30ac03..cd915881 100644 --- a/easyflow-ui-admin/packages/@core/ui-kit/layout-ui/src/components/layout-header.vue +++ b/easyflow-ui-admin/packages/@core/ui-kit/layout-ui/src/components/layout-header.vue @@ -47,7 +47,7 @@ const style = computed((): CSSProperties => { const right = !show || !fullWidth ? undefined : 0; return { - backgroundColor: 'transparent', + backgroundColor: 'hsl(var(--nav-shell-surface))', backgroundImage: 'none', backdropFilter: 'none', boxShadow: 'none', diff --git a/easyflow-ui-admin/packages/@core/ui-kit/layout-ui/src/components/layout-sidebar.vue b/easyflow-ui-admin/packages/@core/ui-kit/layout-ui/src/components/layout-sidebar.vue index 96b27c63..e13df3d0 100644 --- a/easyflow-ui-admin/packages/@core/ui-kit/layout-ui/src/components/layout-sidebar.vue +++ b/easyflow-ui-admin/packages/@core/ui-kit/layout-ui/src/components/layout-sidebar.vue @@ -123,10 +123,9 @@ const style = computed((): CSSProperties => { return { '--scroll-shadow': 'var(--surface-elevated)', - backgroundColor: 'hsl(var(--nav-surface-subtle) / 0.16)', - backgroundImage: - 'linear-gradient(180deg, hsl(var(--nav-surface) / 0.3) 0%, hsl(var(--nav-surface-subtle) / 0.2) 28%, hsl(var(--glass-tint) / 0.12) 100%)', - backdropFilter: 'blur(calc(var(--glass-blur) * 1.5)) saturate(188%)', + backgroundColor: 'hsl(var(--nav-shell-surface))', + backgroundImage: 'none', + backdropFilter: 'var(--persistent-surface-backdrop-filter)', boxShadow: 'inset 0 1px 0 hsl(var(--nav-sheen) / 0.14), inset -1px 0 0 hsl(var(--nav-border) / 0.08)', ...calcMenuWidthStyle(false), @@ -142,10 +141,9 @@ const extraStyle = computed((): CSSProperties => { const { extraWidth, show, width, zIndex } = props; return { - backgroundColor: 'hsl(var(--nav-surface-subtle) / 0.12)', - backgroundImage: - 'linear-gradient(180deg, hsl(var(--nav-surface-subtle) / 0.24) 0%, hsl(var(--glass-tint) / 0.12) 100%)', - backdropFilter: 'blur(calc(var(--glass-blur) * 1.34)) saturate(182%)', + backgroundColor: 'hsl(var(--nav-shell-surface))', + backgroundImage: 'none', + backdropFilter: 'var(--persistent-surface-backdrop-filter)', boxShadow: 'inset 0 1px 0 hsl(var(--nav-sheen) / 0.12), inset -1px 0 0 hsl(var(--nav-border) / 0.08)', left: `${width}px`, diff --git a/easyflow-ui-admin/packages/@core/ui-kit/layout-ui/src/components/layout-tabbar.vue b/easyflow-ui-admin/packages/@core/ui-kit/layout-ui/src/components/layout-tabbar.vue index 3da88f8a..d5622f5d 100644 --- a/easyflow-ui-admin/packages/@core/ui-kit/layout-ui/src/components/layout-tabbar.vue +++ b/easyflow-ui-admin/packages/@core/ui-kit/layout-ui/src/components/layout-tabbar.vue @@ -15,7 +15,7 @@ const props = withDefaults(defineProps(), {}); const style = computed((): CSSProperties => { const { height } = props; return { - backgroundColor: 'transparent', + backgroundColor: 'hsl(var(--nav-shell-surface))', backgroundImage: 'none', backdropFilter: 'none', boxShadow: 'none', diff --git a/easyflow-ui-admin/packages/@core/ui-kit/layout-ui/src/easyflow-layout.vue b/easyflow-ui-admin/packages/@core/ui-kit/layout-ui/src/easyflow-layout.vue index 7022d76c..c7774bb2 100644 --- a/easyflow-ui-admin/packages/@core/ui-kit/layout-ui/src/easyflow-layout.vue +++ b/easyflow-ui-admin/packages/@core/ui-kit/layout-ui/src/easyflow-layout.vue @@ -334,8 +334,8 @@ const headerZIndex = computed(() => { const headerWrapperStyle = computed((): CSSProperties => { const fixed = headerFixed.value; return { - backdropFilter: 'blur(calc(var(--glass-blur) * 1.1)) saturate(158%)', - backgroundColor: 'hsl(var(--glass-tint) / 0.18)', + backdropFilter: 'var(--persistent-surface-backdrop-filter)', + backgroundColor: 'hsl(var(--glass-tint) / 0.9)', backgroundImage: 'linear-gradient(180deg, hsl(var(--nav-surface) / 0.22), hsl(var(--glass-tint) / 0.08))', boxShadow: 'inset 0 -1px 0 hsl(var(--nav-border) / 0.05)', diff --git a/easyflow-ui-admin/packages/effects/layouts/src/widgets/check-updates/check-updates.vue b/easyflow-ui-admin/packages/effects/layouts/src/widgets/check-updates/check-updates.vue index 939e2682..ff3d8e3a 100644 --- a/easyflow-ui-admin/packages/effects/layouts/src/widgets/check-updates/check-updates.vue +++ b/easyflow-ui-admin/packages/effects/layouts/src/widgets/check-updates/check-updates.vue @@ -20,6 +20,7 @@ const props = withDefaults(defineProps(), { }); let isCheckingUpdates = false; +let resumeCheckFrame: number | undefined; const currentVersionTag = ref(''); const lastVersionTag = ref(''); const timer = ref>(); @@ -81,6 +82,7 @@ function handleNotice(versionTag: string) { } function start() { + stop(); if (props.checkUpdatesInterval <= 0) { return; } @@ -92,22 +94,47 @@ function start() { ); } -function handleVisibilitychange() { - if (document.hidden) { - stop(); - } else { - if (!isCheckingUpdates) { +function cancelResumeCheck() { + if (resumeCheckFrame === undefined) { + return; + } + cancelAnimationFrame(resumeCheckFrame); + resumeCheckFrame = undefined; +} + +function scheduleResumeCheck() { + cancelResumeCheck(); + // 页面恢复后先让浏览器完成两帧绘制,再发起版本检查请求。 + resumeCheckFrame = requestAnimationFrame(() => { + resumeCheckFrame = requestAnimationFrame(() => { + resumeCheckFrame = undefined; + if (document.hidden || isCheckingUpdates) { + return; + } isCheckingUpdates = true; checkForUpdates().finally(() => { isCheckingUpdates = false; start(); }); - } + }); + }); +} + +function handleVisibilitychange() { + if (document.hidden) { + cancelResumeCheck(); + stop(); + } else { + scheduleResumeCheck(); } } function stop() { + if (timer.value === undefined) { + return; + } clearInterval(timer.value); + timer.value = undefined; } onMounted(() => { @@ -116,6 +143,7 @@ onMounted(() => { }); onUnmounted(() => { + cancelResumeCheck(); stop(); document.removeEventListener('visibilitychange', handleVisibilitychange); });