283 lines
8.6 KiB
JavaScript
283 lines
8.6 KiB
JavaScript
import { defineStore } from 'pinia';
|
|
import { ref, computed } from 'vue';
|
|
|
|
// 屏幕检测管理器类
|
|
class ScreenDetectionManager {
|
|
constructor() {
|
|
this.WIDE_SCREEN_CSS_ID = 'wide-screen-css';
|
|
this.WIDE_SCREEN_CSS_PATH = '../common/wide-screen.css';
|
|
this.resizeTimer = null;
|
|
this.resizeListeners = [];
|
|
this.cssLink = null;
|
|
}
|
|
|
|
// 获取屏幕宽度
|
|
getScreenWidth() {
|
|
if (typeof window === 'undefined') return 0;
|
|
|
|
// 优先使用 uni.getSystemInfo
|
|
if (typeof uni !== 'undefined' && uni.getSystemInfo) {
|
|
return new Promise((resolve) => {
|
|
uni.getSystemInfo({
|
|
success: (res) => {
|
|
const width = res.screenWidth || res.windowWidth || window.innerWidth;
|
|
resolve(width);
|
|
},
|
|
fail: () => {
|
|
resolve(this.getWindowWidth());
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
return Promise.resolve(this.getWindowWidth());
|
|
}
|
|
|
|
// 备用方案:使用 window 对象
|
|
getWindowWidth() {
|
|
if (typeof window === 'undefined') return 0;
|
|
return window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
|
|
}
|
|
|
|
// 检测折叠屏
|
|
checkVisualViewport() {
|
|
if (window.visualViewport?.segments?.length > 1) {
|
|
return {
|
|
foldable: true,
|
|
count: window.visualViewport.segments.length - 1
|
|
}
|
|
}
|
|
else {
|
|
return {
|
|
foldable: false,
|
|
count: 1
|
|
}
|
|
}
|
|
}
|
|
|
|
// 动态加载 CSS
|
|
loadWideScreenCSS() {
|
|
if (typeof window === 'undefined' || this.cssLink) return null;
|
|
|
|
try {
|
|
this.cssLink = document.createElement('link');
|
|
this.cssLink.id = this.WIDE_SCREEN_CSS_ID;
|
|
this.cssLink.rel = 'stylesheet';
|
|
this.cssLink.href = this.WIDE_SCREEN_CSS_PATH;
|
|
|
|
// 添加加载成功/失败监听
|
|
this.cssLink.onload = () => {
|
|
console.log('🎨 宽屏 CSS 文件加载成功');
|
|
};
|
|
|
|
this.cssLink.onerror = () => {
|
|
console.error('❌ 宽屏 CSS 文件加载失败');
|
|
this.cssLink = null;
|
|
};
|
|
|
|
document.head.appendChild(this.cssLink);
|
|
return this.cssLink;
|
|
} catch (error) {
|
|
console.error('加载 CSS 失败:', error);
|
|
this.cssLink = null;
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// 移除 CSS
|
|
removeWideScreenCSS() {
|
|
if (this.cssLink && this.cssLink.parentNode) {
|
|
try {
|
|
this.cssLink.parentNode.removeChild(this.cssLink);
|
|
this.cssLink = null;
|
|
console.log('🗑️ 宽屏 CSS 文件已移除');
|
|
return true;
|
|
} catch (error) {
|
|
console.error('移除 CSS 失败:', error);
|
|
return false;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// 更新 CSS 状态
|
|
updateWideScreenCSS(isWideScreen) {
|
|
if (isWideScreen) {
|
|
return this.loadWideScreenCSS();
|
|
} else {
|
|
return this.removeWideScreenCSS();
|
|
}
|
|
}
|
|
//显示/隐藏默认tabbar
|
|
updateTabbar(isWideScreen){
|
|
if(isWideScreen) uni.hideTabBar()
|
|
else uni.showTabBar()
|
|
}
|
|
|
|
// 添加 resize 监听器
|
|
addResizeListener(callback, delay = 250) {
|
|
if (typeof window === 'undefined') return () => {};
|
|
|
|
const handler = () => {
|
|
clearTimeout(this.resizeTimer);
|
|
this.resizeTimer = setTimeout(() => {
|
|
callback();
|
|
}, delay);
|
|
};
|
|
|
|
window.addEventListener('resize', handler);
|
|
this.resizeListeners.push({ callback, handler });
|
|
|
|
// 返回清理函数
|
|
return () => this.removeResizeListener(callback);
|
|
}
|
|
|
|
// 移除 resize 监听器
|
|
removeResizeListener(callback) {
|
|
const index = this.resizeListeners.findIndex(item => item.callback === callback);
|
|
if (index > -1) {
|
|
const { handler } = this.resizeListeners[index];
|
|
window.removeEventListener('resize', handler);
|
|
this.resizeListeners.splice(index, 1);
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
// 创建屏幕状态 store
|
|
const useScreenStore = defineStore('screen', () => {
|
|
// 状态
|
|
const screenWidth = ref(0);
|
|
const isInitialized = ref(false);
|
|
const isLoading = ref(false);
|
|
const foldFeature = ref(false);
|
|
const foldCount = ref(0);
|
|
|
|
|
|
const isWideScreen = computed(() => {
|
|
return screenWidth.value >= 900;
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 管理器实例
|
|
const manager = new ScreenDetectionManager();
|
|
|
|
// 初始化屏幕检测
|
|
const initScreenDetection = async () => {
|
|
if (isLoading.value || isInitialized.value) return;
|
|
isLoading.value = true;
|
|
try {
|
|
// 检测屏幕状态
|
|
const width = await manager.getScreenWidth();
|
|
const { foldable, count } = manager.checkVisualViewport();
|
|
|
|
foldFeature.value = foldable;
|
|
foldCount.value = count;
|
|
screenWidth.value = width;
|
|
isInitialized.value = true;
|
|
|
|
console.log(`📱 屏幕检测完成: ${width}px, 宽屏: ${isWideScreen.value}`);
|
|
console.log(`是否为折叠屏: ${foldFeature.value},折叠屏数量:${foldCount.value}`);
|
|
|
|
// 根据状态加载或移除 CSS
|
|
manager.updateWideScreenCSS(isWideScreen.value);
|
|
manager.updateTabbar(isWideScreen.value);
|
|
|
|
// 设置 resize 监听
|
|
setupResizeListener();
|
|
return {
|
|
screenWidth: width,
|
|
isWideScreen: isWideScreen.value,
|
|
foldable,
|
|
count
|
|
};
|
|
} catch (error) {
|
|
console.error('初始化屏幕检测失败:', error);
|
|
return null;
|
|
} finally {
|
|
isLoading.value = false;
|
|
}
|
|
};
|
|
|
|
// 手动更新屏幕状态
|
|
const updateScreenStatus = async () => {
|
|
try {
|
|
const width = await manager.getScreenWidth();
|
|
const { foldable, count } = manager.checkVisualViewport();
|
|
|
|
// 保存旧状态
|
|
const oldWidth = screenWidth.value;
|
|
const oldIsWideScreen = isWideScreen.value;
|
|
const oldFoldable = foldFeature.value;
|
|
const oldFoldCount = foldCount.value;
|
|
|
|
// 更新状态
|
|
screenWidth.value = width;
|
|
foldFeature.value = foldable;
|
|
foldCount.value = count;
|
|
|
|
// 检查宽屏状态是否发生变化
|
|
if (oldIsWideScreen !== isWideScreen.value) {
|
|
console.log(`🔄 屏幕状态变化: ${oldIsWideScreen ? '宽屏' : '非宽屏'} -> ${isWideScreen.value ? '宽屏' : '非宽屏'}`);
|
|
console.log(`屏幕宽度变化: ${oldWidth}px -> ${width}px`);
|
|
manager.updateWideScreenCSS(isWideScreen.value);
|
|
manager.updateTabbar(isWideScreen.value);
|
|
}
|
|
|
|
// 检查折叠屏状态是否发生变化
|
|
if (oldFoldable !== foldable || oldFoldCount !== count) {
|
|
console.log(`折叠屏状态变化: ${oldFoldable ? '是' : '否'}->${foldable ? '是' : '否'}, 折叠数: ${oldFoldCount}->${count}`);
|
|
}
|
|
|
|
return {
|
|
screenWidth: width,
|
|
isWideScreen: isWideScreen.value,
|
|
foldable,
|
|
count
|
|
};
|
|
} catch (error) {
|
|
console.error('更新屏幕状态失败:', error);
|
|
return null;
|
|
}
|
|
};
|
|
|
|
// 设置 resize 监听
|
|
let cleanupResizeListener = () => {};
|
|
const setupResizeListener = () => {
|
|
if (typeof window === 'undefined') return;
|
|
|
|
cleanupResizeListener = manager.addResizeListener(async () => {
|
|
await updateScreenStatus();
|
|
}, 300);
|
|
};
|
|
|
|
// 手动触发屏幕检测
|
|
const detectScreen = () => {
|
|
return updateScreenStatus();
|
|
};
|
|
|
|
|
|
|
|
return {
|
|
// 状态
|
|
foldFeature,
|
|
foldCount,
|
|
screenWidth,
|
|
isInitialized,
|
|
isLoading,
|
|
|
|
// 响应式计算属性
|
|
isWideScreen,
|
|
|
|
// 方法
|
|
initScreenDetection,
|
|
updateScreenStatus,
|
|
detectScreen,
|
|
};
|
|
});
|
|
|
|
export default useScreenStore; |