wip: 临时提交
This commit is contained in:
@@ -88,15 +88,27 @@ function handleProfileClick() {
|
||||
|
||||
// 根据主题和侧边栏配色方案选择样式类
|
||||
const navbarActionsClass = computed(() => {
|
||||
// 暗黑主题
|
||||
if (settingStore.theme === ThemeMode.DARK) {
|
||||
const { theme, sidebarColorScheme, layout } = settingStore;
|
||||
|
||||
// 暗黑主题下,所有布局都使用白色文字
|
||||
if (theme === ThemeMode.DARK) {
|
||||
return "navbar-actions--white-text";
|
||||
}
|
||||
|
||||
// 经典蓝侧边栏
|
||||
if (settingStore.sidebarColorScheme === SidebarColor.CLASSIC_BLUE) {
|
||||
// 明亮主题下
|
||||
if (theme === ThemeMode.LIGHT) {
|
||||
// 顶部布局和混合布局的顶部区域使用深色背景,需要白色文字
|
||||
if (layout === "top" || layout === "mix") {
|
||||
return "navbar-actions--white-text";
|
||||
}
|
||||
|
||||
// 左侧布局下,如果侧边栏是经典蓝色,顶部导航栏仍使用默认颜色
|
||||
if (layout === "left" && sidebarColorScheme === SidebarColor.CLASSIC_BLUE) {
|
||||
return ""; // 使用默认的深色文字
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -130,19 +142,22 @@ function logout() {
|
||||
height: $navbar-height;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
|
||||
// 默认图标样式(明亮模式 + 左侧布局)
|
||||
:deep([class^="i-svg:"]) {
|
||||
font-size: 18px;
|
||||
color: var(--el-text-color-regular);
|
||||
transition: color 0.3s;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: rgba(0, 0, 0, 0.04);
|
||||
|
||||
:deep([class^="i-svg:"]) {
|
||||
color: var(--el-text-color);
|
||||
|
||||
&:hover {
|
||||
color: var(--el-text-color-primary);
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: var(--el-text-color-primary);
|
||||
background: rgb(0 0 0 / 10%);
|
||||
}
|
||||
}
|
||||
|
||||
.user-profile {
|
||||
@@ -160,19 +175,41 @@ function logout() {
|
||||
|
||||
&__name {
|
||||
margin-left: 10px;
|
||||
color: var(--el-text-color-regular);
|
||||
transition: color 0.3s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 白色文字样式(用于深色背景:暗黑主题、顶部布局、混合布局)
|
||||
.navbar-actions--white-text {
|
||||
.navbar-actions__item {
|
||||
:deep([class^="i-svg:"]) {
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
|
||||
:deep([class^="i-svg:"]) {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.layout-top,
|
||||
.layout-mix {
|
||||
.user-profile__name {
|
||||
color: #fff !important;
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
}
|
||||
}
|
||||
|
||||
.layout-top .navbar-actions--white-text :deep([class^="i-svg:"]),
|
||||
.layout-mix .navbar-actions--white-text :deep([class^="i-svg:"]) {
|
||||
color: #fff !important;
|
||||
// 确保下拉菜单中的图标不受影响
|
||||
:deep(.el-dropdown-menu) {
|
||||
[class^="i-svg:"] {
|
||||
color: var(--el-text-color-regular) !important;
|
||||
|
||||
&:hover {
|
||||
color: var(--el-color-primary) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -26,7 +26,10 @@ const isSidebarOpened = computed(() => appStore.sidebar.opened);
|
||||
|
||||
// 切换侧边栏展开/折叠状态
|
||||
function toggleSideBar() {
|
||||
console.log("🔄 Hamburger clicked! Current state:", isSidebarOpened.value);
|
||||
console.log("🔄 Device type:", appStore.device);
|
||||
appStore.toggleSidebar();
|
||||
console.log("🔄 New state:", appStore.sidebar.opened);
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<!-- 混合布局顶部菜单 -->
|
||||
<template>
|
||||
<el-scrollbar>
|
||||
<el-menu
|
||||
mode="horizontal"
|
||||
:default-active="activePath"
|
||||
@@ -36,7 +35,6 @@
|
||||
</template>
|
||||
</el-menu-item>
|
||||
</el-menu>
|
||||
</el-scrollbar>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@@ -117,3 +115,25 @@ onMounted(() => {
|
||||
topMenus.value = permissionStore.routes.filter((item) => !item.meta || !item.meta.hidden);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.el-menu {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
&--horizontal {
|
||||
height: $navbar-height !important;
|
||||
|
||||
// 确保菜单项垂直居中
|
||||
:deep(.el-menu-item) {
|
||||
height: 100%;
|
||||
line-height: $navbar-height;
|
||||
}
|
||||
|
||||
// 移除默认的底部边框
|
||||
&:after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -35,10 +35,14 @@ import AppMain from "@/layout/components/AppMain/index.vue";
|
||||
import SidebarMenu from "../LayoutMenu.vue";
|
||||
|
||||
// 布局相关参数
|
||||
const { isShowTagsView, isShowLogo, isSidebarOpen } = useLayout();
|
||||
const { isShowTagsView, isShowLogo, isSidebarOpen, isMobile } = useLayout();
|
||||
|
||||
// 菜单相关
|
||||
const { routes } = useLayoutMenu();
|
||||
|
||||
// 添加调试日志
|
||||
console.log("🔍 LeftSideLayout - isSidebarOpen:", isSidebarOpen.value);
|
||||
console.log("🔍 LeftSideLayout - isMobile:", isMobile.value);
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -78,32 +82,34 @@ const { routes } = useLayoutMenu();
|
||||
}
|
||||
}
|
||||
|
||||
/* 移动端样式 */
|
||||
:deep(.mobile) {
|
||||
/* 移动端样式 - 注意这里需要正确应用到父元素 */
|
||||
.mobile {
|
||||
.layout__sidebar {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
transition: transform 0.28s;
|
||||
width: $sidebar-width !important;
|
||||
transition:
|
||||
transform 0.28s,
|
||||
width 0s;
|
||||
}
|
||||
|
||||
&.hideSidebar {
|
||||
.layout__sidebar {
|
||||
width: $sidebar-width !important;
|
||||
transform: translateX(-$sidebar-width);
|
||||
}
|
||||
}
|
||||
|
||||
&.openSidebar {
|
||||
.layout__sidebar {
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
.layout__main {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.layout__main {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.hasTagsView) {
|
||||
.app-main {
|
||||
.hasTagsView {
|
||||
:deep(.app-main) {
|
||||
height: calc(100vh - $navbar-height - $tags-view-height) !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,22 @@
|
||||
<LayoutBase>
|
||||
<!-- 顶部菜单栏 -->
|
||||
<div class="layout__header">
|
||||
<LayoutSidebar :show-logo="isShowLogo" :is-collapsed="false">
|
||||
<div class="layout__header-content">
|
||||
<!-- Logo区域 -->
|
||||
<div v-if="isShowLogo" class="layout__header-logo">
|
||||
<SidebarLogo :collapse="false" />
|
||||
</div>
|
||||
|
||||
<!-- 顶部菜单区域 -->
|
||||
<div class="layout__header-menu">
|
||||
<SidebarMixTopMenu />
|
||||
</div>
|
||||
|
||||
<!-- 右侧操作区域 -->
|
||||
<div class="layout__header-actions">
|
||||
<NavbarActions />
|
||||
</LayoutSidebar>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 主内容区容器 -->
|
||||
@@ -13,7 +25,22 @@
|
||||
<!-- 左侧菜单栏 -->
|
||||
<div class="layout__sidebar--left" :class="{ 'layout__sidebar--collapsed': !isSidebarOpen }">
|
||||
<el-scrollbar>
|
||||
<SidebarMenu :data="sideMenuRoutes" :base-path="activeTopMenuPath" />
|
||||
<el-menu
|
||||
:default-active="activeMenu"
|
||||
:collapse="!isSidebarOpen"
|
||||
:collapse-transition="false"
|
||||
:unique-opened="false"
|
||||
:background-color="variables['menu-background']"
|
||||
:text-color="variables['menu-text']"
|
||||
:active-text-color="variables['menu-active-text']"
|
||||
>
|
||||
<SidebarMenuItem
|
||||
v-for="route in sideMenuRoutes"
|
||||
:key="route.path"
|
||||
:item="route"
|
||||
:base-path="resolvePath(route.path)"
|
||||
/>
|
||||
</el-menu>
|
||||
</el-scrollbar>
|
||||
<!-- 侧边栏切换按钮 -->
|
||||
<div class="layout__sidebar-toggle">
|
||||
@@ -31,22 +58,52 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from "vue";
|
||||
import { useRoute } from "vue-router";
|
||||
import { useLayout } from "../../composables/useLayout";
|
||||
import { useLayoutMenu } from "../../composables/useLayoutMenu";
|
||||
import LayoutBase from "../LayoutBase.vue";
|
||||
import LayoutSidebar from "../common/LayoutSidebar.vue";
|
||||
import SidebarLogo from "@/layout/components/Sidebar/components/SidebarLogo.vue";
|
||||
import SidebarMixTopMenu from "@/layout/components/Sidebar/components/SidebarMixTopMenu.vue";
|
||||
import NavbarActions from "@/layout/components/NavBar/components/NavbarActions.vue";
|
||||
import TagsView from "@/layout/components/TagsView/index.vue";
|
||||
import AppMain from "@/layout/components/AppMain/index.vue";
|
||||
import SidebarMenu from "../LayoutMenu.vue";
|
||||
import SidebarMenuItem from "@/layout/components/Sidebar/components/SidebarMenuItem.vue";
|
||||
import Hamburger from "@/components/Hamburger/index.vue";
|
||||
import variables from "@/styles/variables.module.scss";
|
||||
|
||||
const route = useRoute();
|
||||
|
||||
// 布局相关参数
|
||||
const { isShowTagsView, isShowLogo, isSidebarOpen, toggleSidebar } = useLayout();
|
||||
|
||||
// 菜单相关
|
||||
const { sideMenuRoutes, activeTopMenuPath } = useLayoutMenu();
|
||||
|
||||
// 当前激活的菜单
|
||||
const activeMenu = computed(() => {
|
||||
const { meta, path } = route;
|
||||
// 如果设置了activeMenu,则使用
|
||||
if (meta?.activeMenu && typeof meta.activeMenu === "string") {
|
||||
return meta.activeMenu;
|
||||
}
|
||||
return path;
|
||||
});
|
||||
|
||||
/**
|
||||
* 解析路径 - 混合模式下,左侧菜单是从顶级菜单下的子菜单开始的
|
||||
* 所以需要拼接顶级菜单路径
|
||||
*/
|
||||
function resolvePath(routePath: string) {
|
||||
// 如果已经是绝对路径,直接返回
|
||||
if (routePath.startsWith("/")) {
|
||||
return activeTopMenuPath.value + routePath;
|
||||
}
|
||||
// 否则拼接
|
||||
return `${activeTopMenuPath.value}/${routePath}`;
|
||||
}
|
||||
|
||||
console.log("🎨 MixMenuLayout rendered");
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -57,12 +114,74 @@ const { sideMenuRoutes, activeTopMenuPath } = useLayoutMenu();
|
||||
z-index: 999;
|
||||
width: 100%;
|
||||
height: $navbar-height;
|
||||
background-color: $menu-background;
|
||||
background-color: var(--menu-background);
|
||||
border-bottom: 1px solid var(--el-border-color-lighter);
|
||||
|
||||
:deep(.layout-sidebar) {
|
||||
&-content {
|
||||
display: flex;
|
||||
width: 100% !important;
|
||||
height: $navbar-height;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
&-logo {
|
||||
flex-shrink: 0;
|
||||
width: 200px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
:deep(.logo) {
|
||||
height: 100%;
|
||||
|
||||
a {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-menu {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 0 16px;
|
||||
overflow: hidden;
|
||||
|
||||
:deep(.el-menu) {
|
||||
height: 100%;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
:deep(.el-menu--horizontal) {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
|
||||
.el-menu-item {
|
||||
height: 100%;
|
||||
line-height: $navbar-height;
|
||||
border-bottom: none;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
|
||||
&.is-active {
|
||||
background-color: rgba(255, 255, 255, 0.12);
|
||||
border-bottom: 2px solid var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-actions {
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +197,7 @@ const { sideMenuRoutes, activeTopMenuPath } = useLayoutMenu();
|
||||
background-color: var(--menu-background);
|
||||
transition: width 0.28s;
|
||||
|
||||
&--collapsed {
|
||||
&.layout__sidebar--collapsed {
|
||||
width: $sidebar-width-collapsed !important;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { computed, watchEffect } from "vue";
|
||||
import { computed } from "vue";
|
||||
import { useAppStore, useSettingsStore } from "@/store";
|
||||
import defaultSettings from "@/settings";
|
||||
|
||||
@@ -24,6 +24,9 @@ export function useLayout() {
|
||||
// 是否显示Logo
|
||||
const isShowLogo = computed(() => settingsStore.sidebarLogo);
|
||||
|
||||
// 是否移动设备
|
||||
const isMobile = computed(() => appStore.device === "mobile");
|
||||
|
||||
// 布局CSS类
|
||||
const layoutClass = computed(() => ({
|
||||
hideSidebar: !appStore.sidebar.opened,
|
||||
@@ -46,12 +49,13 @@ export function useLayout() {
|
||||
appStore.closeSideBar();
|
||||
}
|
||||
|
||||
// 暂时注释掉这个逻辑,避免影响手动操作
|
||||
// 监听路由变化,在移动端自动关闭侧边栏
|
||||
watchEffect(() => {
|
||||
if (appStore.device === "mobile" && appStore.sidebar.opened) {
|
||||
appStore.closeSideBar();
|
||||
}
|
||||
});
|
||||
// watchEffect(() => {
|
||||
// if (appStore.device === "mobile" && appStore.sidebar.opened) {
|
||||
// appStore.closeSideBar();
|
||||
// }
|
||||
// });
|
||||
|
||||
return {
|
||||
currentLayout,
|
||||
@@ -59,6 +63,7 @@ export function useLayout() {
|
||||
isShowTagsView,
|
||||
isShowSettings,
|
||||
isShowLogo,
|
||||
isMobile,
|
||||
layoutClass,
|
||||
toggleSidebar,
|
||||
closeSidebar,
|
||||
|
||||
Reference in New Issue
Block a user