wip: 临时提交

This commit is contained in:
Ray.Hao
2025-05-23 13:16:56 +08:00
parent af30411317
commit b5b766487c
6 changed files with 274 additions and 84 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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