优化对话框状态管理

This commit is contained in:
jxxghp
2025-08-23 19:32:23 +08:00
parent 9faa0ded59
commit f093053ea4
3 changed files with 28 additions and 38 deletions

View File

@@ -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;

View File

@@ -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],

View File

@@ -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;