<template> <!-- 全局容器 --> <div class="app-container"> <!-- 路由视图容器 --> <router-view v-slot="{ Component, route }"> <!-- 智能缓存:仅缓存带有 meta.keepAlive 的路由 --> <keep-alive :include="cachedRoutes"> <component :is="Component" :key="route.fullPath" class="router-view-container" :class="{ 'has-header': showHeader }" /> </keep-alive> </router-view> <!-- 大屏适配容器(用于缩放内容) --> <div v-if="isDashboardPage" ref="scaleContainer" class="scale-container" :style="scaleStyle" > <!-- 实际内容会被挂载到这里 --> </div> </div> </template> <script setup lang="ts"> import { computed, ref, onMounted, onUnmounted, watch } from 'vue' import { useRoute, useRouter } from 'vue-router' const route = useRoute() const router = useRouter() const scaleContainer = ref<HTMLElement>() const scaleValue = ref(1) // 需要缓存的组件名称列表 const cachedRoutes = ref<string[]>([]) // 是否显示头部(根据路由配置) const showHeader = computed(() => route.meta.showHeader ?? true) // 是否大屏页面(需要特殊适配) const isDashboardPage = computed(() => route.meta.isDashboard ?? false) // 缩放样式计算 const scaleStyle = computed(() => ({ transform: `scale(${scaleValue.value}) translate(-50%, -50%)`, width: `${(1 / scaleValue.value) * 100}%`, height: `${(1 / scaleValue.value) * 100}%` })) // 自适应计算函数 const calculateScale = () => { if (!isDashboardPage.value || !scaleContainer.value) return const baseWidth = 1920 // 设计稿基准宽度 const baseHeight = 1080 // 设计稿基准高度 const currentWidth = window.innerWidth const currentHeight = window.innerHeight // 计算缩放比例(考虑宽高比) const widthRatio = currentWidth / baseWidth const heightRatio = currentHeight / baseHeight scaleValue.value = Math.min(widthRatio, heightRatio) } // 监听路由变化 watch( () => route.path, (newVal) => { // 更新缓存路由列表 if (route.meta.keepAlive && route.name) { cachedRoutes.value = [...new Set([...cachedRoutes.value, route.name as string])] } // 大屏页面特殊处理 if (isDashboardPage.value) { nextTick(() => { // 将路由视图移动到缩放容器 const view = document.querySelector('.router-view-container') if (view && scaleContainer.value) { scaleContainer.value.appendChild(view) } calculateScale() }) } } ) // 窗口resize监听(带防抖) let resizeTimer: number const onResize = () => { clearTimeout(resizeTimer) resizeTimer = setTimeout(calculateScale, 300) } onMounted(() => { window.addEventListener('resize', onResize) calculateScale() }) onUnmounted(() => { window.removeEventListener('resize', onResize) }) </script> <style lang="scss"> /* 全局样式重置 */ html, body, #app { width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden; /* 禁用全局滚动条 */ } .app-container { position: relative; width: 100%; height: 100%; /* 路由视图基础样式 */ .router-view-container { width: 100%; height: 100%; } /* 大屏适配容器样式 */ .scale-container { position: fixed; top: 50%; left: 50%; transform-origin: 0 0; transition: transform 0.3s; /* 大屏页面特殊处理 */ .router-view-container { background: #030409; /* 深色背景 */ color: #fff; } } } </style>