diff --git a/src/composables/usePWA.ts b/src/composables/usePWA.ts index 22077622..7007cd7e 100644 --- a/src/composables/usePWA.ts +++ b/src/composables/usePWA.ts @@ -12,6 +12,16 @@ const globalPwaStatus = ref<{ const globalLoading = ref(false) let initPromise: Promise | null = null +// UI模式设置 +export type UIMode = 'auto' | 'desktop' | 'app' +const uiMode = ref((localStorage.getItem('ui-mode') as UIMode) || 'auto') + +// 设置UI模式 +function setUIMode(mode: UIMode) { + uiMode.value = mode + localStorage.setItem('ui-mode', mode) +} + // 全局初始化函数 async function initializePWAGlobally() { if (initPromise) return initPromise @@ -50,6 +60,8 @@ export function usePWA() { }) const appMode = computed(() => { + if (uiMode.value === 'app') return true + if (uiMode.value === 'desktop') return false return pwaMode.value && display.mdAndDown.value }) @@ -70,6 +82,8 @@ export function usePWA() { pwaMode, appMode, pwaStatus, + uiMode, + setUIMode, loading: globalLoading, initializePWA: initializePWAGlobally, } diff --git a/src/composables/usePullDownGesture.ts b/src/composables/usePullDownGesture.ts index 787329bb..439b3947 100644 --- a/src/composables/usePullDownGesture.ts +++ b/src/composables/usePullDownGesture.ts @@ -236,16 +236,15 @@ export function usePullDownGesture(options: PullDownOptions = {}) { } } - // PWA状态确定后,一次性决定是否添加事件监听器 + // 监听 appMode 变化动态添加/移除事件监听器 onMounted(() => { - // 等待PWA检测完成后添加事件监听器 - const stopWatcher = watch( + watch( appMode, newValue => { if (newValue) { addEventListeners() - // PWA状态确定后停止监听 - stopWatcher() + } else { + removeEventListeners() } }, { immediate: true }, diff --git a/src/layouts/components/UserProfile.vue b/src/layouts/components/UserProfile.vue index 233626d4..2f764178 100644 --- a/src/layouts/components/UserProfile.vue +++ b/src/layouts/components/UserProfile.vue @@ -16,6 +16,7 @@ import { saveLocalTheme } from '@/@core/utils/theme' import type { ThemeSwitcherTheme } from '@layouts/types' import { useConfirm } from '@/composables/useConfirm' import { themeManager } from '@/utils/themeManager' +import { usePWA, type UIMode } from '@/composables/usePWA' // 认证 Store const authStore = useAuthStore() @@ -27,6 +28,8 @@ const globalSettingsStore = useGlobalSettingsStore() const { t } = useI18n() // 显示器 const display = useDisplay() +// PWA +const { uiMode, setUIMode } = usePWA() // 提示框 const $toast = useToast() @@ -40,6 +43,9 @@ const siteAuthDialog = ref(false) // 自定义CSS弹窗 const cssDialog = ref(false) +// UI模式菜单是否显示 +const showUIModeMenu = ref(false) + // 主题菜单是否显示 const showThemeMenu = ref(false) @@ -233,6 +239,39 @@ const isAdvancedMode = computed(() => { return globalSettingsStore.get('ADVANCED_MODE') !== false }) +// UI模式相关 +const uiModes = computed(() => [ + { + name: 'auto', + title: t('theme.autoUI'), + icon: 'mdi-devices', + }, + { + name: 'desktop', + title: t('pwa.platforms.desktop'), + icon: 'mdi-monitor', + }, + { + name: 'app', + title: t('pwa.platforms.mobile'), + icon: 'mdi-cellphone', + }, +]) + +// 切换UI模式 +function changeUIMode(mode: UIMode) { + setUIMode(mode) + showUIModeMenu.value = false + // 刷新页面以应用更改 + window.location.reload() +} + +// 获取当前UI模式图标 +const getUIModeIcon = computed(() => { + const mode = uiModes.value.find(m => m.name === uiMode.value) + return mode?.icon || 'mdi-devices' +}) + // 主题相关功能 const { name: themeName, global: globalTheme } = useTheme() const savedTheme = ref(localStorage.getItem('theme') ?? themeName) @@ -546,6 +585,41 @@ onUnmounted(() => { {{ t('user.siteAuth') }} + + + + + + + {{ mode.title }} + + + + +