Files
qingdao-employment-service/stores/useScreenStore.js
2025-12-16 10:34:40 +08:00

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;