|
@@ -8,6 +8,21 @@ import './index.css';
|
|
|
// 设置 CSS 变量,用于 CSS 文件中的 OSS 资源 URL
|
|
// 设置 CSS 变量,用于 CSS 文件中的 OSS 资源 URL
|
|
|
document.documentElement.style.setProperty('--oss-chatbot-bg-url', `url("${getOssUrl('chatbot-bg.svg')}")`);
|
|
document.documentElement.style.setProperty('--oss-chatbot-bg-url', `url("${getOssUrl('chatbot-bg.svg')}")`);
|
|
|
|
|
|
|
|
|
|
+// 立即初始化 --vw(在 installViewportHeightFix 之前,确保尽早设置)
|
|
|
|
|
+// 解决曲面屏问题:使用 visualViewport.width 获取实际可视宽度
|
|
|
|
|
+if (typeof window !== 'undefined') {
|
|
|
|
|
+ const getInitialWidth = (): number => {
|
|
|
|
|
+ if (window.visualViewport?.width) {
|
|
|
|
|
+ return window.visualViewport.width;
|
|
|
|
|
+ }
|
|
|
|
|
+ return window.innerWidth;
|
|
|
|
|
+ };
|
|
|
|
|
+ const initialWidth = getInitialWidth();
|
|
|
|
|
+ const initialVw = initialWidth * 0.01;
|
|
|
|
|
+ document.documentElement.style.setProperty('--vw', `${initialVw}px`);
|
|
|
|
|
+ console.log(`[ViewportFix] 🚀 立即初始化 --vw: width=${initialWidth}px, --vw=${initialVw}px`);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// 全局视口高度修复:为所有使用 px2vh / vh 的地方提供统一、准确的高度基准
|
|
// 全局视口高度修复:为所有使用 px2vh / vh 的地方提供统一、准确的高度基准
|
|
|
// 修复移动端浏览器地址栏/工具栏导致的可视区域变化问题
|
|
// 修复移动端浏览器地址栏/工具栏导致的可视区域变化问题
|
|
|
// 激进方案:完全阻止键盘弹出时的 --vh 更新,使用固定屏幕高度
|
|
// 激进方案:完全阻止键盘弹出时的 --vh 更新,使用固定屏幕高度
|
|
@@ -41,6 +56,15 @@ const installViewportHeightFix = () => {
|
|
|
return window.innerHeight;
|
|
return window.innerHeight;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+ // 获取当前实际宽度(用于计算 --vw,解决曲面屏问题)
|
|
|
|
|
+ // 优先使用 visualViewport.width,因为它不包含曲面不可见区域
|
|
|
|
|
+ const getCurrentWidth = (): number => {
|
|
|
|
|
+ if (window.visualViewport?.width) {
|
|
|
|
|
+ return window.visualViewport.width;
|
|
|
|
|
+ }
|
|
|
|
|
+ return window.innerWidth;
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
// 强制锁定视口高度(立即执行,无防抖)
|
|
// 强制锁定视口高度(立即执行,无防抖)
|
|
|
const forceLockViewportHeight = (reason = 'unknown') => {
|
|
const forceLockViewportHeight = (reason = 'unknown') => {
|
|
|
if (initialHeight === null) {
|
|
if (initialHeight === null) {
|
|
@@ -50,7 +74,13 @@ const installViewportHeightFix = () => {
|
|
|
isLocked = true;
|
|
isLocked = true;
|
|
|
const vh = initialHeight * 0.01;
|
|
const vh = initialHeight * 0.01;
|
|
|
document.documentElement.style.setProperty('--vh', `${vh}px`);
|
|
document.documentElement.style.setProperty('--vh', `${vh}px`);
|
|
|
- console.log(`[ViewportFix] 🔒 锁定视口高度: initialHeight=${initialHeight}px, --vh=${vh}px, reason=${reason}, isInputFocused=${isInputFocused}`);
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // 同时更新 --vw(基于实际可视宽度,解决曲面屏问题)
|
|
|
|
|
+ const currentWidth = getCurrentWidth();
|
|
|
|
|
+ const vw = currentWidth * 0.01;
|
|
|
|
|
+ document.documentElement.style.setProperty('--vw', `${vw}px`);
|
|
|
|
|
+
|
|
|
|
|
+ console.log(`[ViewportFix] 🔒 锁定视口: initialHeight=${initialHeight}px, --vh=${vh}px, currentWidth=${currentWidth}px, --vw=${vw}px, reason=${reason}, isInputFocused=${isInputFocused}`);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
// 设置视口高度(带防抖)
|
|
// 设置视口高度(带防抖)
|
|
@@ -113,7 +143,13 @@ const installViewportHeightFix = () => {
|
|
|
const vh = height * 0.01;
|
|
const vh = height * 0.01;
|
|
|
// 全局 1vh 的真实像素值
|
|
// 全局 1vh 的真实像素值
|
|
|
document.documentElement.style.setProperty('--vh', `${vh}px`);
|
|
document.documentElement.style.setProperty('--vh', `${vh}px`);
|
|
|
- console.log(`[ViewportFix] 🔧 setViewportHeight: 更新 --vh, height=${height}px, --vh=${vh}px, isLocked=${isLocked}, skipKeyboardCheck=${skipKeyboardCheck}`);
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // 同时更新 --vw(基于实际可视宽度,解决曲面屏问题)
|
|
|
|
|
+ const currentWidth = getCurrentWidth();
|
|
|
|
|
+ const vw = currentWidth * 0.01;
|
|
|
|
|
+ document.documentElement.style.setProperty('--vw', `${vw}px`);
|
|
|
|
|
+
|
|
|
|
|
+ console.log(`[ViewportFix] 🔧 setViewport: 更新 --vh=${vh}px (height=${height}px), --vw=${vw}px (width=${currentWidth}px), isLocked=${isLocked}, skipKeyboardCheck=${skipKeyboardCheck}`);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
// 防抖处理(除非立即执行)
|
|
// 防抖处理(除非立即执行)
|
|
@@ -170,7 +206,13 @@ const installViewportHeightFix = () => {
|
|
|
// 立即设置 --vh,确保在自动聚焦前就已完成初始化
|
|
// 立即设置 --vh,确保在自动聚焦前就已完成初始化
|
|
|
const vh = initialHeight * 0.01;
|
|
const vh = initialHeight * 0.01;
|
|
|
document.documentElement.style.setProperty('--vh', `${vh}px`);
|
|
document.documentElement.style.setProperty('--vh', `${vh}px`);
|
|
|
- console.log(`[ViewportFix] 🚀 初始化高度: source=${source}, initialHeight=${initialHeight}px, --vh=${vh}px, readyState=${document.readyState}`);
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // 同时初始化 --vw(基于实际可视宽度,解决曲面屏问题)
|
|
|
|
|
+ const currentWidth = getCurrentWidth();
|
|
|
|
|
+ const vw = currentWidth * 0.01;
|
|
|
|
|
+ document.documentElement.style.setProperty('--vw', `${vw}px`);
|
|
|
|
|
+
|
|
|
|
|
+ console.log(`[ViewportFix] 🚀 初始化: source=${source}, initialHeight=${initialHeight}px, --vh=${vh}px, currentWidth=${currentWidth}px, --vw=${vw}px, readyState=${document.readyState}`);
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
|
|
@@ -200,7 +242,13 @@ const installViewportHeightFix = () => {
|
|
|
initialHeight = window.innerHeight;
|
|
initialHeight = window.innerHeight;
|
|
|
const vh = initialHeight * 0.01;
|
|
const vh = initialHeight * 0.01;
|
|
|
document.documentElement.style.setProperty('--vh', `${vh}px`);
|
|
document.documentElement.style.setProperty('--vh', `${vh}px`);
|
|
|
- console.log(`[ViewportFix] 🚀 初始化高度: source=requestAnimationFrame, initialHeight=${initialHeight}px, --vh=${vh}px`);
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // 同时初始化 --vw
|
|
|
|
|
+ const currentWidth = getCurrentWidth();
|
|
|
|
|
+ const vw = currentWidth * 0.01;
|
|
|
|
|
+ document.documentElement.style.setProperty('--vw', `${vw}px`);
|
|
|
|
|
+
|
|
|
|
|
+ console.log(`[ViewportFix] 🚀 初始化: source=requestAnimationFrame, initialHeight=${initialHeight}px, --vh=${vh}px, currentWidth=${currentWidth}px, --vw=${vw}px`);
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
};
|
|
};
|
|
@@ -305,12 +353,17 @@ const installViewportHeightFix = () => {
|
|
|
forceLockViewportHeight('resize-init-keyboard-detected');
|
|
forceLockViewportHeight('resize-init-keyboard-detected');
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
- // 否则正常设置高度
|
|
|
|
|
|
|
+ // 否则正常设置高度和宽度
|
|
|
setViewportHeight(false, true);
|
|
setViewportHeight(false, true);
|
|
|
lastHeight = currentHeight;
|
|
lastHeight = currentHeight;
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // 同时更新 --vw(visualViewport 变化时,宽度也可能变化,如横竖屏切换)
|
|
|
|
|
+ const currentWidth = getCurrentWidth();
|
|
|
|
|
+ const vw = currentWidth * 0.01;
|
|
|
|
|
+ document.documentElement.style.setProperty('--vw', `${vw}px`);
|
|
|
|
|
+
|
|
|
// 检查当前活跃元素是否为输入框(即使 focusin 还没触发)
|
|
// 检查当前活跃元素是否为输入框(即使 focusin 还没触发)
|
|
|
const heightDiff = initialHeight - currentHeight;
|
|
const heightDiff = initialHeight - currentHeight;
|
|
|
|
|
|
|
@@ -378,7 +431,7 @@ const installViewportHeightFix = () => {
|
|
|
isInputFocused = false; // 重置焦点状态
|
|
isInputFocused = false; // 重置焦点状态
|
|
|
if (blurRecoveryTimer) clearTimeout(blurRecoveryTimer);
|
|
if (blurRecoveryTimer) clearTimeout(blurRecoveryTimer);
|
|
|
if (debounceTimer) clearTimeout(debounceTimer);
|
|
if (debounceTimer) clearTimeout(debounceTimer);
|
|
|
- setViewportHeight(true, true); // 强制更新
|
|
|
|
|
|
|
+ setViewportHeight(true, true); // 强制更新(会同时更新 --vw)
|
|
|
}, 100);
|
|
}, 100);
|
|
|
});
|
|
});
|
|
|
|
|
|
|
@@ -386,6 +439,10 @@ const installViewportHeightFix = () => {
|
|
|
window.addEventListener('resize', () => {
|
|
window.addEventListener('resize', () => {
|
|
|
// 如果已锁定,不处理(防止键盘弹出时的误判)
|
|
// 如果已锁定,不处理(防止键盘弹出时的误判)
|
|
|
if (isLocked && initialHeight !== null) {
|
|
if (isLocked && initialHeight !== null) {
|
|
|
|
|
+ // 即使锁定,也要更新 --vw(宽度变化不影响键盘状态)
|
|
|
|
|
+ const currentWidth = getCurrentWidth();
|
|
|
|
|
+ const vw = currentWidth * 0.01;
|
|
|
|
|
+ document.documentElement.style.setProperty('--vw', `${vw}px`);
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|