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 @@