diff --git a/web/src/App.vue b/web/src/App.vue index 916f511..f3a74e0 100644 --- a/web/src/App.vue +++ b/web/src/App.vue @@ -3,14 +3,39 @@ + +
+
+ +
+
+
- + + + + - + { filterTypeIds.value = [] const query = ids.length ? { crowd_ids: ids.join(',') } : {} router.push({ path: '/', query }) + // 移动端关闭菜单 + menuOpen.value = false +} + +// 抽屉菜单选择分类 +const handleDrawerSelectType = (typeId) => { + const ids = filterTypeIds.value + const idx = ids.indexOf(typeId) + if (idx >= 0) ids.splice(idx, 1) + else ids.push(typeId) + filterCrowdIds.value = [] + const query = ids.length ? { type_ids: ids.join(',') } : {} + router.push({ path: '/', query }) + // 移动端关闭菜单 + menuOpen.value = false } // provide 必须在函数定义之后 @@ -192,6 +236,37 @@ onMounted(async () => { --tag-crowd-bg: #0a2040; } +/* ============================================================ + 响应式断点变量 + ============================================================ */ +:root { + /* 左侧边栏 */ + --sidebar-width: 0px; + /* 副导航栏 */ + --subnav-width: 220px; + /* 右侧边栏 */ + --rightbar-width: 260px; + /* 内容区域最大宽度 */ + --content-max-width: 1440px; + /* 顶部导航高度 */ + --header-height: 64px; +} + +/* 平板(768px+)显示副导航 */ +@media (min-width: 768px) { + :root { + --subnav-width: 220px; + } +} + +/* 大屏幕(1200px+)显示完整布局 */ +@media (min-width: 1200px) { + :root { + --sidebar-width: 220px; + --rightbar-width: 260px; + } +} + /* ============================================================ 全局基础样式 ============================================================ */ @@ -220,13 +295,40 @@ body { .content-wrapper { display: flex; flex: 1; - max-width: 1440px; + max-width: var(--content-max-width); margin: 0 auto; width: 100%; - padding-top: 64px; + padding-top: var(--header-height); min-height: 100vh; } +/* 默认隐藏侧边栏,小屏幕适配 */ +.left-sidebar { display: none; } + +/* 平板及以上显示副导航 */ +@media (min-width: 768px) { + .left-subnav { + width: var(--subnav-width); + min-width: var(--subnav-width); + flex-shrink: 0; + } +} + +/* 大屏幕显示所有侧边栏 */ +@media (min-width: 1200px) { + .left-sidebar { + display: block; + width: var(--sidebar-width); + min-width: var(--sidebar-width); + flex-shrink: 0; + } + .rightbar { + width: var(--rightbar-width); + min-width: var(--rightbar-width); + flex-shrink: 0; + } +} + .main-content { flex: 1; min-width: 0; @@ -254,6 +356,53 @@ body { .el-button { border-radius: 8px !important; } .el-pagination.is-background .el-pager li.is-active { background: var(--primary) !important; } +/* ============================================================ + 移动端抽屉菜单 + ============================================================ */ +.mobile-drawer { + display: none; + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.5); + z-index: 1000; + opacity: 0; + transition: opacity 0.3s; +} + +.mobile-drawer.open { + display: block; + opacity: 1; +} + +.drawer-content { + position: absolute; + left: 0; + top: 0; + bottom: 0; + width: 280px; + max-width: 80vw; + transform: translateX(-100%); + transition: transform 0.3s; +} + +.mobile-drawer.open .drawer-content { + transform: translateX(0); +} + +/* 移动端:小屏幕隐藏副导航,显示汉堡菜单按钮 */ +@media (max-width: 767px) { + .content-wrapper { + padding-top: var(--header-height); + } + + .main-content { + padding: 16px 12px 40px; + } +} + /* ============================================================ 深色主题 Element Plus 额外覆盖 ============================================================ */ diff --git a/web/src/components/AppHeader.vue b/web/src/components/AppHeader.vue index 7349993..ab70d5f 100644 --- a/web/src/components/AppHeader.vue +++ b/web/src/components/AppHeader.vue @@ -1,13 +1,20 @@