修改自适应

This commit is contained in:
2026-08-19 08:53:50 +08:00
parent 0e797c39f4
commit ec5cf96d0b
14 changed files with 941 additions and 48 deletions
+155 -3
View File
@@ -3,8 +3,8 @@ import CommonAside from '@/components/CommonAside.vue';
import CommonHeader from '@/components/CommonHeader.vue';
import { useTabsStore } from '@/stores';
import { useRouter, useRoute } from 'vue-router';
import { ref, watch, reactive, nextTick, onMounted, computed } from 'vue';
import { More, Close, CircleClose, ArrowUp } from '@element-plus/icons-vue';
import { ref, watch, reactive, nextTick, onMounted, onBeforeUnmount, computed } from 'vue';
import { More, Close, CircleClose, ArrowUp, Fold, Expand } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus';
const tabsStore = useTabsStore();
@@ -12,6 +12,44 @@ const router = useRouter();
const route = useRoute();
const defaultDashboardPath = '/home';
// ========== 手机端侧栏抽屉控制 ==========
const MOBILE_QUERY = '(max-width: 768px)';
const mobileMedia = window.matchMedia(MOBILE_QUERY);
const isMobile = ref(mobileMedia.matches);
// 手机端侧栏默认隐藏,桌面端无影响(CSS 仅在媒体查询内生效)
const sidebarVisible = ref(false);
const handleMobileMediaChange = (e) => {
isMobile.value = e.matches;
// 切回桌面端时重置侧栏状态,避免残留
if (!e.matches) {
sidebarVisible.value = false;
}
};
// 兼容旧版 Safari 的 addListener 写法
if (typeof mobileMedia.addEventListener === 'function') {
mobileMedia.addEventListener('change', handleMobileMediaChange);
} else {
mobileMedia.addListener(handleMobileMediaChange);
}
onBeforeUnmount(() => {
if (typeof mobileMedia.removeEventListener === 'function') {
mobileMedia.removeEventListener('change', handleMobileMediaChange);
} else {
mobileMedia.removeListener(handleMobileMediaChange);
}
});
const toggleMobileSidebar = () => {
sidebarVisible.value = !sidebarVisible.value;
};
const closeMobileSidebar = () => {
sidebarVisible.value = false;
};
// 根据当前路由恢复 tab(刷新时使用)
function restoreTabFromRoute() {
const currentPath = route.fullPath;
@@ -88,6 +126,10 @@ watch(
(newPath) => {
if (newPath) {
restoreTabFromRoute();
// 路由变化时自动关闭手机端侧栏
if (isMobile.value) {
sidebarVisible.value = false;
}
}
},
{ immediate: false }
@@ -410,8 +452,33 @@ const canCloseRight = computed(() => {
<template>
<div class="common-layout">
<!-- 手机端汉堡菜单按钮(仅 ≤768px 显示,CSS 控制) -->
<button
class="mobile-menu-btn"
:aria-label="sidebarVisible ? '关闭菜单' : '打开菜单'"
@click="toggleMobileSidebar"
>
<el-icon :size="20">
<Expand v-if="sidebarVisible" />
<Fold v-else />
</el-icon>
</button>
<!-- 手机端遮罩层,点击关闭侧栏 -->
<transition name="mask-fade">
<div
v-if="isMobile && sidebarVisible"
class="mobile-sidebar-mask"
@click="closeMobileSidebar"
></div>
</transition>
<el-container class="main-container">
<common-aside @menu-click="handleAsideMenuClick" />
<common-aside
class="common-aside-wrapper"
:class="{ 'mobile-open': sidebarVisible }"
@menu-click="handleAsideMenuClick"
/>
<el-container>
<el-header class="main-header">
<common-header />
@@ -666,6 +733,91 @@ const canCloseRight = computed(() => {
border-right: none !important;
}
// ========== 手机端侧栏抽屉(仅 ≤768px 生效,桌面端不受影响) ==========
// 汉堡按钮:默认隐藏,手机端显示
.mobile-menu-btn {
display: none;
position: fixed;
top: 20px;
left: 12px;
z-index: 2200;
width: 40px;
height: 40px;
align-items: center;
justify-content: center;
border: none;
border-radius: 50%;
background: var(--el-color-primary);
color: #fff;
box-shadow: 0 4px 12px rgba(57, 115, 255, 0.35);
cursor: pointer;
transition: transform 0.2s ease, box-shadow 0.2s ease;
&:active {
transform: scale(0.92);
}
}
// 遮罩层
.mobile-sidebar-mask {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 2000;
background: rgba(0, 0, 0, 0.45);
backdrop-filter: blur(2px);
}
.mask-fade-enter-active,
.mask-fade-leave-active {
transition: opacity 0.3s ease;
}
.mask-fade-enter-from,
.mask-fade-leave-to {
opacity: 0;
}
@media (max-width: 768px) {
.mobile-menu-btn {
display: flex;
}
// 覆盖 el-aside 的 :width 内联宽度(200px/64px),改为 fixed 抽屉
.common-layout .common-aside-wrapper {
position: fixed !important;
top: 0;
bottom: 0;
left: 0;
width: 260px !important;
max-width: 80vw;
height: 100vh;
z-index: 2100;
transform: translateX(-100%);
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: none;
&.mobile-open {
transform: translateX(0);
box-shadow: 4px 0 24px rgba(0, 0, 0, 0.25);
}
}
// 内容区不再为侧栏预留空间
.main-container {
:deep(.el-header),
:deep(.el-main) {
width: 100%;
}
}
.right-main {
padding: 64px 12px 12px;
}
}
// 回到顶部按钮样式
.backtop-button {
width: 40px;