From a2237f230d236b09ee39415854e74007b39febe1 Mon Sep 17 00:00:00 2001 From: pengyuthon Date: Fri, 23 Jan 2026 12:32:50 +0800 Subject: [PATCH] mobile --- .../static/src/js/status_bar_buttons.js | 74 ++++++++-- .../static/src/scss/status_bar_buttons.scss | 137 ++++++++++++------ 2 files changed, 153 insertions(+), 58 deletions(-) diff --git a/k_ry_mobile_form/static/src/js/status_bar_buttons.js b/k_ry_mobile_form/static/src/js/status_bar_buttons.js index 38d937f80..7941b3edf 100644 --- a/k_ry_mobile_form/static/src/js/status_bar_buttons.js +++ b/k_ry_mobile_form/static/src/js/status_bar_buttons.js @@ -33,15 +33,25 @@ patch(StatusBarButtons, { if (isMobileDevice()) { const mobileContainers = document.querySelectorAll('.o_statusbar_buttons_mobile_fixed'); mobileContainers.forEach(container => { - container.style.display = 'block'; - container.style.visibility = 'visible'; - container.style.opacity = '1'; + // 使用内联样式强制显示,优先级最高 + container.style.setProperty('display', 'block', 'important'); + container.style.setProperty('visibility', 'visible', 'important'); + container.style.setProperty('opacity', '1', 'important'); + container.style.setProperty('position', 'fixed', 'important'); + container.style.setProperty('bottom', '0', 'important'); + container.style.setProperty('left', '0', 'important'); + container.style.setProperty('right', '0', 'important'); + container.style.setProperty('z-index', '9999', 'important'); + // 确保背景色可见 + if (!container.style.backgroundColor) { + container.style.setProperty('background-color', '#ffffff', 'important'); + } }); // 隐藏桌面端按钮 const desktopButtons = document.querySelectorAll('.o_form_statusbar > .o_statusbar_buttons:not(.o_statusbar_buttons_mobile_fixed .o_statusbar_buttons)'); desktopButtons.forEach(btn => { - btn.style.display = 'none'; + btn.style.setProperty('display', 'none', 'important'); }); } }; @@ -73,24 +83,35 @@ if (typeof window !== 'undefined' && typeof document !== 'undefined') { // 如果是移动设备,确保容器可见 if (isMobileDevice()) { const computedStyle = getComputedStyle(container); - if (computedStyle.display === 'none') { - container.style.display = 'block'; + // 使用 setProperty 的 important 标志强制设置样式 + container.style.setProperty('display', 'block', 'important'); + container.style.setProperty('visibility', 'visible', 'important'); + container.style.setProperty('opacity', '1', 'important'); + container.style.setProperty('position', 'fixed', 'important'); + container.style.setProperty('bottom', '0', 'important'); + container.style.setProperty('left', '0', 'important'); + container.style.setProperty('right', '0', 'important'); + container.style.setProperty('z-index', '9999', 'important'); + // 确保背景色可见 + if (!container.style.backgroundColor || container.style.backgroundColor === 'transparent') { + container.style.setProperty('background-color', '#ffffff', 'important'); } - container.style.visibility = 'visible'; - container.style.opacity = '1'; } // 修复按钮的交互性 const buttons = container.querySelectorAll('button, a.btn, .btn, a[role="button"], .o_statusbar_buttons > * > button'); buttons.forEach(button => { - // 确保pointer-events正确设置 - if (getComputedStyle(button).pointerEvents === 'none') { - button.style.pointerEvents = 'auto'; + // 使用 setProperty 强制设置样式 + button.style.setProperty('pointer-events', 'auto', 'important'); + button.style.setProperty('cursor', 'pointer', 'important'); + button.style.setProperty('touch-action', 'manipulation', 'important'); + button.style.setProperty('visibility', 'visible', 'important'); + button.style.setProperty('opacity', '1', 'important'); + button.style.setProperty('display', 'inline-block', 'important'); + // 确保按钮有最小高度 + if (!button.style.minHeight) { + button.style.setProperty('min-height', '44px', 'important'); } - button.style.cursor = 'pointer'; - button.style.touchAction = 'manipulation'; - button.style.visibility = 'visible'; - button.style.opacity = '1'; }); }); @@ -98,7 +119,7 @@ if (typeof window !== 'undefined' && typeof document !== 'undefined') { if (isMobileDevice()) { const desktopButtons = document.querySelectorAll('.o_form_statusbar > .o_statusbar_buttons:not(.o_statusbar_buttons_mobile_fixed .o_statusbar_buttons)'); desktopButtons.forEach(btn => { - btn.style.display = 'none'; + btn.style.setProperty('display', 'none', 'important'); }); } }; @@ -142,4 +163,25 @@ if (typeof window !== 'undefined' && typeof document !== 'undefined') { window.addEventListener('orientationchange', () => { setTimeout(fixIOSButtons, 200); }); + + // 定期检查按钮是否可见(防止被其他样式覆盖) + if (isMobileDevice()) { + const checkInterval = setInterval(() => { + const containers = document.querySelectorAll('.o_statusbar_buttons_mobile_fixed'); + containers.forEach(container => { + const computedStyle = getComputedStyle(container); + // 如果按钮被隐藏,强制显示 + if (computedStyle.display === 'none' || + computedStyle.visibility === 'hidden' || + parseFloat(computedStyle.opacity) < 0.1) { + fixIOSButtons(); + } + }); + }, 1000); // 每秒检查一次 + + // 页面卸载时清除定时器 + window.addEventListener('beforeunload', () => { + clearInterval(checkInterval); + }); + } } diff --git a/k_ry_mobile_form/static/src/scss/status_bar_buttons.scss b/k_ry_mobile_form/static/src/scss/status_bar_buttons.scss index 56122cd5b..63b6c4850 100644 --- a/k_ry_mobile_form/static/src/scss/status_bar_buttons.scss +++ b/k_ry_mobile_form/static/src/scss/status_bar_buttons.scss @@ -1,70 +1,100 @@ // Mobile: 底部悬浮栏样式 -.o_statusbar_buttons_mobile_fixed { - position: fixed; - bottom: 0; - left: 0; - right: 0; - z-index: 1050; // 确保在其他元素之上,但低于模态框 - background-color: $o-view-background-color; - border-top: 1px solid $border-color; - box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.1); - padding: map-get($spacers, 2) map-get($spacers, 3); +// 使用高优先级选择器,防止被其他主题样式覆盖 +.o_statusbar_buttons_mobile_fixed, +body .o_statusbar_buttons_mobile_fixed, +html body .o_statusbar_buttons_mobile_fixed { + position: fixed !important; + bottom: 0 !important; + left: 0 !important; + right: 0 !important; + z-index: 9999 !important; // 提高z-index,确保在最上层 + background-color: $o-view-background-color !important; + background: $o-view-background-color !important; // 双重保险 + border-top: 1px solid $border-color !important; + box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.1) !important; + padding: map-get($spacers, 2) map-get($spacers, 3) !important; // 为底部悬浮栏预留空间,避免内容被遮挡(支持 iOS safe area) - padding-bottom: calc(#{map-get($spacers, 2)} + env(safe-area-inset-bottom, 0px)); + padding-bottom: calc(#{map-get($spacers, 2)} + env(safe-area-inset-bottom, 0px)) !important; // iOS Safari 修复:确保元素可交互 - -webkit-transform: translateZ(0); - transform: translateZ(0); + -webkit-transform: translateZ(0) !important; + transform: translateZ(0) !important; // iOS Safari 修复:防止滚动时fixed定位失效 - -webkit-backface-visibility: hidden; - backface-visibility: hidden; + -webkit-backface-visibility: hidden !important; + backface-visibility: hidden !important; + // 强制显示属性 + display: block !important; + visibility: visible !important; + opacity: 1 !important; + // 确保元素不会被其他样式隐藏 + overflow: visible !important; + clip: auto !important; + clip-path: none !important; +} .o_statusbar_buttons { - max-width: 100%; - width: 100%; + max-width: 100% !important; + width: 100% !important; // iOS Safari 修复:确保容器可交互 - pointer-events: auto; - -webkit-transform: translateZ(0); - transform: translateZ(0); + pointer-events: auto !important; + -webkit-transform: translateZ(0) !important; + transform: translateZ(0) !important; + // 强制显示 + display: flex !important; + visibility: visible !important; + opacity: 1 !important; > * { - flex: 1; - min-width: 0; + flex: 1 !important; + min-width: 0 !important; // iOS Safari 修复:确保子元素可交互 - pointer-events: auto; + pointer-events: auto !important; + // 强制显示 + display: block !important; + visibility: visible !important; + opacity: 1 !important; > button, > a, > .btn { - width: 100%; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; + width: 100% !important; + white-space: nowrap !important; + overflow: hidden !important; + text-overflow: ellipsis !important; // 确保按钮有足够的点击区域 - min-height: 44px; + min-height: 44px !important; // iOS Safari 修复:确保按钮可点击 - cursor: pointer; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0.1); - touch-action: manipulation; + cursor: pointer !important; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0.1) !important; + touch-action: manipulation !important; // iOS Safari 修复:防止文本选择影响点击 - -webkit-user-select: none; - user-select: none; - -webkit-touch-callout: none; + -webkit-user-select: none !important; + user-select: none !important; + -webkit-touch-callout: none !important; // iOS Safari 修复:确保按钮在层级之上 - position: relative; - z-index: 1; + position: relative !important; + z-index: 1 !important; // iOS Safari 修复:确保pointer-events正确 pointer-events: auto !important; // iOS Safari 修复:防止transform影响点击 - -webkit-transform: translateZ(0); - transform: translateZ(0); + -webkit-transform: translateZ(0) !important; + transform: translateZ(0) !important; + // 强制显示按钮 + display: inline-block !important; + visibility: visible !important; + opacity: 1 !important; + // 确保按钮背景和文字可见 + background-color: inherit !important; + color: inherit !important; } } } -} + // 桌面端隐藏移动端悬浮栏(但保留触摸设备的显示) @include media-breakpoint-up(md) { - .o_statusbar_buttons_mobile_fixed { + .o_statusbar_buttons_mobile_fixed, + body .o_statusbar_buttons_mobile_fixed, + html body .o_statusbar_buttons_mobile_fixed { // 只在非触摸设备上隐藏(桌面浏览器) @media (hover: hover) and (pointer: fine) { display: none !important; @@ -88,14 +118,37 @@ } // iOS Safari 特殊处理:确保在 iOS 设备上按钮可见 +// 使用高优先级选择器,防止被其他主题样式覆盖 @media (hover: none) and (pointer: coarse) { - .o_statusbar_buttons_mobile_fixed { + .o_statusbar_buttons_mobile_fixed, + body .o_statusbar_buttons_mobile_fixed, + html body .o_statusbar_buttons_mobile_fixed { display: block !important; visibility: visible !important; opacity: 1 !important; + position: fixed !important; + bottom: 0 !important; + z-index: 9999 !important; } - .o_form_statusbar > .o_statusbar_buttons:not(.o_statusbar_buttons_mobile_fixed .o_statusbar_buttons) { + .o_form_statusbar > .o_statusbar_buttons:not(.o_statusbar_buttons_mobile_fixed .o_statusbar_buttons), + body .o_form_statusbar > .o_statusbar_buttons:not(.o_statusbar_buttons_mobile_fixed .o_statusbar_buttons) { display: none !important; } } + +// 通用移动设备强制显示规则(防止被其他主题覆盖) +@media (max-width: 767px) { + .o_statusbar_buttons_mobile_fixed, + body .o_statusbar_buttons_mobile_fixed, + html body .o_statusbar_buttons_mobile_fixed { + display: block !important; + visibility: visible !important; + opacity: 1 !important; + position: fixed !important; + bottom: 0 !important; + left: 0 !important; + right: 0 !important; + z-index: 9999 !important; + } +}