zhangwencui
15 小时以前 e38c0656952f70552170fc4ee72420b0c741919e
src/layout/components/Navbar.vue
@@ -1,29 +1,33 @@
<template>
  <div class="navbar">
    <div class="left-menu">
      <hamburger id="hamburger-container"
                 :is-active="appStore.sidebar.opened"
                 class="hamburger-container"
                 @toggleClick="toggleSideBar" />
      <breadcrumb v-if="!settingsStore.topNav"
                  id="breadcrumb-container"
                  class="breadcrumb-container" />
    <div class="navbar-left">
      <div class="navbar-logo"
           v-if="appStore.device !== 'mobile'"
           :style="{ width: logoWidth }">
        <logo v-if="settingsStore.sidebarLogo"
              :collapse="logoCollapse" />
      </div>
      <div v-if="settingsStore.topNav && appStore.device !== 'mobile'"
           class="top-nav-wrapper">
        <top-nav />
      </div>
      <div v-else
           class="left-menu-spacer"></div>
    </div>
    <div class="right-menu">
      <div class="search-wrapper">
        <el-icon class="search-icon"
                 @click="openHeaderSearch">
          <Search />
        </el-icon>
        <el-input v-model="topSearchKeyword"
                  placeholder="快速搜索..."
                  clearable
                  @keyup.enter="openHeaderSearch" />
      <div class="action-icons">
        <!-- 搜索图标 -->
        <div class="right-menu-item hover-effect action-icon-btn"
             @click="openHeaderSearch">
          <el-icon :size="18">
            <Search />
          </el-icon>
        </div>
        <header-search ref="headerSearchRef"
                       :keyword="topSearchKeyword"
                       class="search-popup-trigger" />
      </div>
      <div class="action-icons">
                       class="search-popup-trigger"
                       style="display: none;" />
        <!-- 通知图标 -->
        <el-popover v-model:visible="notificationVisible"
                    :width="500"
                    placement="bottom-end"
@@ -31,7 +35,7 @@
                    :popper-options="{ modifiers: [{ name: 'offset', options: { offset: [0, 10] } }] }"
                    popper-class="notification-popover">
          <template #reference>
            <div class="notification-container right-menu-item hover-effect">
            <div class="notification-container right-menu-item hover-effect action-icon-btn">
              <el-badge :value="unreadCount"
                        :hidden="unreadCount === 0"
                        class="notification-badge">
@@ -44,7 +48,8 @@
          <NotificationCenter @unreadCountChange="handleUnreadCountChange"
                              ref="notificationCenterRef" />
        </el-popover>
        <div class="right-menu-item hover-effect screenfull-container">
        <!-- 全屏图标 -->
        <div class="right-menu-item hover-effect screenfull-container action-icon-btn">
          <screenfull />
        </div>
      </div>
@@ -104,13 +109,21 @@
</template>
<script setup>
  import { ref, computed, watch, onMounted, onUnmounted, nextTick } from "vue";
  import { ElMessageBox } from "element-plus";
  import { Bell, Search } from "@element-plus/icons-vue";
  import Breadcrumb from "@/components/Breadcrumb";
  import Hamburger from "@/components/Hamburger";
  import {
    Bell,
    Search,
    User,
    Setting,
    SwitchButton,
    CaretBottom,
  } from "@element-plus/icons-vue";
  import Screenfull from "@/components/Screenfull";
  import HeaderSearch from "@/components/HeaderSearch";
  import NotificationCenter from "./NotificationCenter/index.vue";
  import Logo from "./Sidebar/Logo.vue";
  import TopNav from "@/components/TopNav/index.vue";
  import useAppStore from "@/store/modules/app";
  import useUserStore from "@/store/modules/user";
  import useSettingsStore from "@/store/modules/settings";
@@ -119,15 +132,27 @@
  const userStore = useUserStore();
  const settingsStore = useSettingsStore();
  const isTopNavLayout = computed(
    () => settingsStore.topNav && appStore.device !== "mobile"
  );
  const logoWidth = computed(() => {
    if (isTopNavLayout.value) {
      return "var(--sidebar-width)";
    }
    return appStore.sidebar.opened
      ? "var(--sidebar-width)"
      : "var(--sidebar-collapsed-width)";
  });
  const logoCollapse = computed(() => {
    if (isTopNavLayout.value) return false;
    return !appStore.sidebar.opened;
  });
  const topSearchKeyword = ref("");
  const headerSearchRef = ref(null);
  const notificationVisible = ref(false);
  const notificationCenterRef = ref(null);
  const unreadCount = ref(0);
  function toggleSideBar() {
    appStore.toggleSideBar();
  }
  function openHeaderSearch() {
    headerSearchRef.value?.open(topSearchKeyword.value);
@@ -205,134 +230,91 @@
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 24px;
    background: var(--navbar-bg);
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
    backdrop-filter: blur(12px);
    padding: 0 24px 0 0;
    background: #fff;
    border-bottom: 1px solid #d8dce5;
    box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
    z-index: var(--layout-header-z);
  }
  .left-menu {
  .navbar-left {
    display: flex;
    align-items: center;
    gap: 12px;
  }
  .hamburger-container {
    height: 32px;
    width: 32px;
    border-radius: var(--radius-sm);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--navbar-text);
    cursor: pointer;
    transition: all 0.2s ease;
    &:hover {
      background: var(--navbar-hover);
      color: #fff;
    }
  }
  .breadcrumb-container {
    height: 100%;
    flex: 1;
    min-width: 0;
  }
    :deep(.el-breadcrumb__inner) {
      color: var(--navbar-text) !important;
      opacity: 0.85;
  .navbar-logo {
    height: 100%;
    display: flex;
    align-items: center;
    transition: width 0.25s ease;
    overflow: hidden;
    flex-shrink: 0;
    background-color: #fff; // 强制设为白色背景
    // border-right: 1px solid #d8dce5; // 增加右侧边框以区分导航栏主体
  }
      &:hover {
        color: #fff !important;
        opacity: 1;
      }
  .top-nav-wrapper {
    display: flex;
    align-items: center;
    height: 100%;
    min-width: 0;
    flex: 1;
    padding: 0 12px;
    overflow: hidden;
  }
      a {
        color: inherit !important;
        font-weight: 500 !important;
      }
    }
    :deep(.no-redirect) {
      color: #fff !important;
      font-weight: 600 !important;
      opacity: 1;
    }
    :deep(.el-breadcrumb__separator) {
      color: var(--navbar-text);
      opacity: 0.5;
    }
  .left-menu-spacer {
    flex: 1;
    min-width: 0;
  }
  .right-menu {
    display: flex;
    align-items: center;
    gap: 20px; // 增加大组之间的间距
    .search-wrapper {
      display: flex;
      align-items: center;
      gap: 8px;
      height: 34px;
      padding: 0 12px;
      background: var(--navbar-hover);
      border: 1px solid var(--surface-border);
      border-radius: 17px;
      width: 240px; // 搜索框更加精致小巧
      transition: all 0.3s ease;
      &:focus-within {
        width: 300px;
        background: rgba(255, 255, 255, 0.1);
        border-color: var(--accent-primary);
        box-shadow: 0 0 0 2px rgba(var(--el-color-primary-rgb), 0.2);
      }
      .search-icon {
        color: var(--sidebar-text);
        font-size: 16px;
        cursor: pointer;
      }
      :deep(.el-input__wrapper) {
        background: transparent;
        box-shadow: none !important;
        padding: 0;
      }
      :deep(.el-input__inner) {
        color: var(--navbar-text);
        font-size: 13px;
        height: 32px;
        &::placeholder {
          color: var(--sidebar-text);
        }
      }
    }
    gap: 16px; // 调整组之间的间距
    .action-icons {
      display: flex;
      align-items: center;
      gap: 4px;
      gap: 12px; // 图标之间的间距
      padding-right: 16px;
      border-right: 1px solid var(--surface-border); // 增加垂直分割线
      border-right: 1px solid var(--surface-border);
      .right-menu-item {
        padding: 0 8px;
        height: 34px;
      .action-icon-btn {
        width: 36px;
        height: 36px;
        padding: 0;
        display: flex;
        align-items: center;
        color: var(--navbar-text);
        border-radius: var(--radius-sm);
        justify-content: center;
        color: var(--text-secondary);
        border-radius: 50%; // 圆形背景
        background: rgba(0, 0, 0, 0.04); // 浅浅的圆形框底色
        transition: all 0.2s ease;
        cursor: pointer;
        &:hover {
          background: var(--navbar-hover);
          color: var(--menu-active-text);
          background: rgba(0, 0, 0, 0.08); // 悬停加深
          color: var(--el-color-primary);
        }
        :deep(.svg-icon) {
          width: 18px !important;
          height: 18px !important;
        }
        :deep(.el-icon) {
          font-size: 18px !important;
        }
      }
      .notification-container {
        display: flex;
        align-items: center;
        justify-content: center;
      }
    }
@@ -348,14 +330,12 @@
        height: 38px;
        padding: 4px 10px 4px 6px;
        border-radius: 999px;
        border: 1px solid rgba(var(--el-color-primary-rgb), 0.32);
        background: rgba(0, 0, 0, 0.16);
        border: 1px solid transparent;
        background: transparent;
        transition: 0.2s ease;
        &:hover {
          background: rgba(0, 0, 0, 0.24);
          border-color: rgba(var(--el-color-primary-rgb), 0.58);
          box-shadow: 0 0 0 2px rgba(var(--el-color-primary-rgb), 0.18);
          background: rgba(0, 0, 0, 0.05);
        }
      }
@@ -368,8 +348,8 @@
      .user-name {
        font-size: 13px;
        font-weight: 700;
        color: var(--navbar-text);
        font-weight: 500;
        color: var(--text-primary);
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
@@ -386,8 +366,7 @@
        width: 30px;
        height: 30px;
        border-radius: 999px;
        border: 2px solid rgba(var(--el-color-primary-rgb), 0.28);
        box-shadow: 0 8px 18px rgba(0, 0, 0, 0.18);
        border: 1px solid rgba(0, 0, 0, 0.1);
        object-fit: cover;
        transition: 0.2s ease;
      }
@@ -403,12 +382,12 @@
        width: 9px;
        height: 9px;
        background: #10b981;
        border: 2px solid var(--navbar-bg);
        border: 2px solid #fff;
        border-radius: 999px;
      }
      .caret-icon {
        color: var(--navbar-text);
        color: var(--text-secondary);
        opacity: 0.76;
        font-size: 12px;
        transition: 0.2s ease;