From f093053ea440fb590a313f5fd1f52d183eea5c90 Mon Sep 17 00:00:00 2001 From: jxxghp Date: Sat, 23 Aug 2025 19:32:23 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=AF=B9=E8=AF=9D=E6=A1=86?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scss/_default-layout-w-vertical-nav.scss | 4 +-- src/@layouts/components/VerticalNavLayout.vue | 30 ++++++++++++++--- src/styles/common.scss | 32 ------------------- 3 files changed, 28 insertions(+), 38 deletions(-) diff --git a/src/@core/scss/_default-layout-w-vertical-nav.scss b/src/@core/scss/_default-layout-w-vertical-nav.scss index 0f60c6d3..873f82d5 100644 --- a/src/@core/scss/_default-layout-w-vertical-nav.scss +++ b/src/@core/scss/_default-layout-w-vertical-nav.scss @@ -46,10 +46,10 @@ $header: ".layout-navbar"; } /* ℹ️ Ensure header styles are preserved when dialog is opened, - regardless of scroll state + but only if window was scrolled before dialog opened */ html.v-overlay-scroll-blocked &.window-scrolled.layout-navbar-fixed, - html.dialog-scroll-locked &.layout-navbar-fixed { + html.dialog-scroll-locked &.window-scrolled.layout-navbar-fixed { #{$header} { padding-inline: 1rem; diff --git a/src/@layouts/components/VerticalNavLayout.vue b/src/@layouts/components/VerticalNavLayout.vue index 5bc9baa1..eec98eba 100644 --- a/src/@layouts/components/VerticalNavLayout.vue +++ b/src/@layouts/components/VerticalNavLayout.vue @@ -17,11 +17,36 @@ export default defineComponent({ syncRef(isOverlayNavActive, isLayoutOverlayVisible) const scrollDistance = ref(window.scrollY) + const isDialogOpen = ref(false) + const wasScrolledBeforeDialog = ref(false) + + // 监听弹窗状态变化 + const checkDialogState = () => { + const wasDialogOpen = isDialogOpen.value + isDialogOpen.value = + document.documentElement.classList.contains('dialog-scroll-locked') || + document.documentElement.classList.contains('v-overlay-scroll-blocked') + + // 当弹窗刚打开时,记录当前的滚动状态 + if (!wasDialogOpen && isDialogOpen.value) { + wasScrolledBeforeDialog.value = scrollDistance.value > 0 + } + } onMounted(() => { window.addEventListener('scroll', () => { scrollDistance.value = window.scrollY }) + + // 初始检查弹窗状态 + checkDialogState() + + // 监听 DOM 变化以检测弹窗状态 + const observer = new MutationObserver(checkDialogState) + observer.observe(document.documentElement, { + attributes: true, + attributeFilter: ['class'], + }) }) return () => { @@ -88,9 +113,6 @@ export default defineComponent({ }, }) - // 检查是否有弹窗打开(通过CSS类名判断) - const isDialogOpen = document.documentElement.classList.contains('dialog-scroll-locked') - return h( 'div', { @@ -99,7 +121,7 @@ export default defineComponent({ 'layout-navbar-fixed', mdAndDown.value && 'layout-overlay-nav', route.meta.layoutWrapperClasses, - (scrollDistance.value || isDialogOpen) && 'window-scrolled', + (scrollDistance.value > 0 || (isDialogOpen.value && wasScrolledBeforeDialog.value)) && 'window-scrolled', ], }, [verticalNav, h('div', { class: 'layout-content-wrapper' }, [navbar, main, footer]), layoutOverlay], diff --git a/src/styles/common.scss b/src/styles/common.scss index 6fe46340..fbf902f3 100644 --- a/src/styles/common.scss +++ b/src/styles/common.scss @@ -3,38 +3,6 @@ @tailwind components; @tailwind utilities; -// 基础样式 -html.v-overlay-scroll-blocked { - position: fixed; - position: relative; - - --v-body-scroll-y: 0px !important; -} - -body { - overscroll-behavior: none; -} - -// 防止弹窗滚动穿透 -.v-dialog { - .v-overlay__content { - overscroll-behavior: contain; - } - - .v-card { - overscroll-behavior: contain; - touch-action: pan-y; - } - - .v-card-text { - overscroll-behavior: contain; - } -} - -// 防止滚动穿透的通用样式 -.v-overlay--active { - overscroll-behavior: contain; -} @mixin hide-scrollbar { -ms-overflow-style: none;