This commit is contained in:
2026-06-12 14:39:36 +08:00
parent 55b003c2bf
commit 32f0978108
2 changed files with 107 additions and 8 deletions

View File

@ -1,15 +1,20 @@
<template> <template>
<div class="app-container"> <MobileScale
:design-width="1920"
:min-scale="0.6"
:breakpoint="992"
>
<TopLoading ref="topLoadingRef" /> <TopLoading ref="topLoadingRef" />
<KeepAlive> <KeepAlive>
<router-view></router-view> <router-view></router-view>
</KeepAlive> </KeepAlive>
</div> </MobileScale>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted } from 'vue' import { ref, onMounted } from 'vue'
import TopLoading from '@/components/common/TopLoading.vue' import TopLoading from '@/components/common/TopLoading.vue'
import MobileScale from '@/components/common/MobileScale.vue'
import { useTabsStore } from '@/stores/modules/tabs' import { useTabsStore } from '@/stores/modules/tabs'
const tabsStore = useTabsStore() const tabsStore = useTabsStore()
@ -27,10 +32,4 @@ onMounted(() => {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.app-container {
width: 100%;
height: 100vh;
overflow: hidden;
position: relative;
}
</style> </style>

View File

@ -0,0 +1,100 @@
/**
* 移动端 viewport 缩放方案
*
* 功能说明
* 1. PC 端保持原有布局不变
* 2. 移动端通过动态调整 viewport scale 等比例缩放
* 3. 滚动功能正常工作
* 4. 有最小缩放值限制防止内容过小
*
* 使用方式
* App.vue 中引入并使用
*/
<template>
<div class="mobile-scale-wrapper">
<slot />
</div>
</template>
<script setup lang="ts">
/**
* 移动端 viewport 缩放组件
*
* 使用 viewport 缩放实现整体缩放滚动功能正常工作
*
* Props:
* - designWidth: 设计稿宽度默认 1920
* - minScale: 最小缩放比例默认 0.5
* - breakpoint: 移动端断点默认 992
*/
const props = withDefaults(defineProps<{
designWidth?: number
minScale?: number
breakpoint?: number
}>(), {
designWidth: 1920,
minScale: 0.5,
breakpoint: 992,
})
//
const currentScale = ref(1)
// viewport meta
const setViewportMeta = (scale: number) => {
const viewportMeta = document.querySelector('meta[name="viewport"]')
if (viewportMeta) {
viewportMeta.setAttribute(
'content',
`width=device-width, initial-scale=${scale}, maximum-scale=${scale}, minimum-scale=${scale}, user-scalable=no`
)
}
}
//
const calculateScale = () => {
const windowWidth = window.innerWidth
if (windowWidth >= props.breakpoint) {
// PC viewport
currentScale.value = 1
setViewportMeta(1)
return
}
// / 稿
let calculatedScale = windowWidth / props.designWidth
//
calculatedScale = Math.max(props.minScale, calculatedScale)
currentScale.value = calculatedScale
setViewportMeta(calculatedScale)
}
//
const handleResize = () => {
calculateScale()
}
onMounted(() => {
calculateScale()
window.addEventListener('resize', handleResize)
window.addEventListener('orientationchange', handleResize)
})
onUnmounted(() => {
window.removeEventListener('resize', handleResize)
window.removeEventListener('orientationchange', handleResize)
// viewport
setViewportMeta(1)
})
</script>
<style scoped lang="scss">
.mobile-scale-wrapper {
width: 100%;
height: 100%;
}
</style>