头部和左边栏实现响应式
This commit is contained in:
parent
8038a618e0
commit
062d599f18
@ -5,13 +5,14 @@
|
||||
quaternary
|
||||
circle
|
||||
@click="$emit('toggle-sidebar')"
|
||||
class="sidebar-toggle"
|
||||
>
|
||||
<template #icon>
|
||||
<Icon icon="tabler:menu" />
|
||||
</template>
|
||||
</n-button>
|
||||
|
||||
<n-breadcrumb>
|
||||
<n-breadcrumb class="breadcrumb">
|
||||
<n-breadcrumb-item>
|
||||
<router-link to="/">{{ appName }}</router-link>
|
||||
</n-breadcrumb-item>
|
||||
@ -28,12 +29,12 @@
|
||||
|
||||
<div class="header-right">
|
||||
<n-space>
|
||||
<!-- 搜索框 -->
|
||||
<!-- 搜索框 - 使用Naive UI的响应式属性 -->
|
||||
<n-input
|
||||
v-model:value="searchQuery"
|
||||
:placeholder="t('Search...')"
|
||||
clearable
|
||||
style="width: 280px"
|
||||
class="search-input"
|
||||
@keyup.enter="handleSearch"
|
||||
@clear="handleSearchClear"
|
||||
>
|
||||
@ -197,11 +198,13 @@ const handleSearchClear = () => {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
min-width: 0; /* 允许flex子项收缩 */
|
||||
}
|
||||
|
||||
.header-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-width: 0; /* 允许flex子项收缩 */
|
||||
}
|
||||
|
||||
.username {
|
||||
@ -209,4 +212,75 @@ const handleSearchClear = () => {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 搜索框响应式样式 */
|
||||
.search-input {
|
||||
width: 280px;
|
||||
}
|
||||
|
||||
/* 面包屑响应式样式 */
|
||||
.breadcrumb {
|
||||
min-width: 0; /* 允许收缩 */
|
||||
}
|
||||
|
||||
/* 平板端样式 (768px - 1024px) */
|
||||
@media (max-width: 1024px) {
|
||||
.app-header {
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.header-left {
|
||||
gap: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 移动端样式 (最大768px) */
|
||||
@media (max-width: 768px) {
|
||||
.app-header {
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.header-left {
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
/* 移动端隐藏面包屑 */
|
||||
.breadcrumb {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 移动端隐藏搜索框 */
|
||||
.search-input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 移动端隐藏用户名文字 */
|
||||
.username {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 移动端调整按钮间距 */
|
||||
.header-right :deep(.n-space) {
|
||||
gap: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 小屏移动端样式 (最大480px) */
|
||||
@media (max-width: 480px) {
|
||||
.app-header {
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
.header-left {
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
/* 小屏移动端进一步压缩间距 */
|
||||
.header-right :deep(.n-space) {
|
||||
gap: 2px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -7,7 +7,10 @@
|
||||
:collapsed-width="64"
|
||||
:width="240"
|
||||
v-model:collapsed="collapsed"
|
||||
show-trigger
|
||||
:show-trigger="!isMobile"
|
||||
:responsive="true"
|
||||
:breakpoint="768"
|
||||
class="sidebar-layout"
|
||||
>
|
||||
<AppSidebar :collapsed="collapsed" />
|
||||
</n-layout-sider>
|
||||
@ -16,7 +19,7 @@
|
||||
<n-layout>
|
||||
<!-- 顶部导航 -->
|
||||
<n-layout-header bordered>
|
||||
<AppHeader @toggle-sidebar="collapsed = !collapsed" />
|
||||
<AppHeader @toggle-sidebar="toggleSidebar" />
|
||||
</n-layout-header>
|
||||
|
||||
<!-- 内容区域 -->
|
||||
@ -28,11 +31,18 @@
|
||||
</n-scrollbar>
|
||||
</n-layout-content>
|
||||
</n-layout>
|
||||
|
||||
<!-- 移动端遮罩层 -->
|
||||
<div
|
||||
v-if="isMobile && !collapsed"
|
||||
class="mobile-overlay"
|
||||
@click="closeMobileDrawer"
|
||||
></div>
|
||||
</n-layout>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
import { ref, watch, onMounted, onUnmounted } from 'vue'
|
||||
import { NLayout, NLayoutSider, NLayoutHeader, NLayoutContent, NScrollbar } from 'naive-ui'
|
||||
import AppSidebar from './AppSidebar.vue'
|
||||
import AppHeader from './AppHeader.vue'
|
||||
@ -40,6 +50,42 @@ import AppHeader from './AppHeader.vue'
|
||||
const SIDEBAR_COLLAPSE_KEY = 'app.sidebar.collapsed'
|
||||
const collapsed = ref(localStorage.getItem(SIDEBAR_COLLAPSE_KEY) === 'true')
|
||||
|
||||
// 移动端检测
|
||||
const isMobile = ref(false)
|
||||
|
||||
// 检测屏幕尺寸
|
||||
const checkIsMobile = () => {
|
||||
isMobile.value = window.innerWidth < 768
|
||||
// 移动端时强制隐藏侧边栏
|
||||
if (isMobile.value) {
|
||||
collapsed.value = true
|
||||
}
|
||||
}
|
||||
|
||||
// 切换侧边栏
|
||||
const toggleSidebar = () => {
|
||||
collapsed.value = !collapsed.value
|
||||
}
|
||||
|
||||
// 关闭移动端抽屉
|
||||
const closeMobileDrawer = () => {
|
||||
collapsed.value = true
|
||||
}
|
||||
|
||||
// 监听窗口大小变化
|
||||
const handleResize = () => {
|
||||
checkIsMobile()
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
checkIsMobile()
|
||||
window.addEventListener('resize', handleResize)
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('resize', handleResize)
|
||||
})
|
||||
|
||||
watch(collapsed, (val) => {
|
||||
localStorage.setItem(SIDEBAR_COLLAPSE_KEY, String(val))
|
||||
})
|
||||
@ -54,4 +100,52 @@ watch(collapsed, (val) => {
|
||||
padding: 20px;
|
||||
min-height: calc(100vh - 64px);
|
||||
}
|
||||
|
||||
/* 移动端遮罩层 */
|
||||
.mobile-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
/* 移动端侧边栏样式 */
|
||||
@media (max-width: 767px) {
|
||||
.sidebar-layout {
|
||||
position: fixed !important;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100vh;
|
||||
z-index: 1000;
|
||||
width: 280px !important;
|
||||
max-width: 80vw;
|
||||
transform: translateX(-100%);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
/* 移动端侧边栏打开时的样式 */
|
||||
.sidebar-layout:not(.n-layout-sider--collapsed) {
|
||||
transform: translateX(0) !important;
|
||||
}
|
||||
|
||||
/* 移动端时隐藏侧边栏触发器 */
|
||||
.sidebar-layout :deep(.n-layout-sider-trigger) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* 桌面端保持原有样式 */
|
||||
@media (min-width: 768px) {
|
||||
.mobile-overlay {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sidebar-layout {
|
||||
position: relative !important;
|
||||
transform: none !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user