From 6e173210a874ff7601aa68eab56e912f5619c79c Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期四, 21 五月 2026 15:32:09 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_宁夏_英泽防锈' into dev_宁夏_英泽防锈

---
 src/layout/components/Navbar.vue |  753 +++++++++++++++++++++++++++++----------------------------
 1 files changed, 382 insertions(+), 371 deletions(-)

diff --git a/src/layout/components/Navbar.vue b/src/layout/components/Navbar.vue
index 0901626..206205d 100644
--- a/src/layout/components/Navbar.vue
+++ b/src/layout/components/Navbar.vue
@@ -1,371 +1,382 @@
-<template>
-  <div class="navbar">
-    <div class="left-zone">
-      <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>
-
-    <div class="center-zone">
-      <el-icon class="search-icon"><Search /></el-icon>
-      <el-input
-        v-model="topSearchKeyword"
-        placeholder="鎼滅储鑿滃崟 / 鍔熻兘 / 鏁版嵁"
-        clearable
-      />
-      <header-search class="search-popup-trigger" />
-    </div>
-
-    <div class="right-menu">
-      <el-popover
-        v-model:visible="notificationVisible"
-        :width="500"
-        placement="bottom-end"
-        trigger="click"
-        :popper-options="{ modifiers: [{ name: 'offset', options: { offset: [0, 10] } }] }"
-        popper-class="notification-popover"
-      >
-        <template #reference>
-          <div class="notification-container right-menu-item hover-effect">
-            <el-badge :value="unreadCount" :hidden="unreadCount === 0" class="notification-badge">
-              <el-icon :size="18">
-                <Bell />
-              </el-icon>
-            </el-badge>
-          </div>
-        </template>
-        <NotificationCenter @unreadCountChange="handleUnreadCountChange" ref="notificationCenterRef" />
-      </el-popover>
-
-      <div class="right-menu-item hover-effect screenfull-container">
-        <screenfull />
-      </div>
-
-      <div class="avatar-container">
-        <el-dropdown @command="handleCommand" class="right-menu-item hover-effect" trigger="click">
-          <div class="avatar-wrapper">
-            <div class="user-summary">
-              <div class="user-name">{{ userStore.nickName || userStore.name || "绠$悊鍛�" }}</div>
-              <div class="user-role">{{ userStore.roleName || "绯荤粺鐢ㄦ埛" }}</div>
-            </div>
-            <img :src="userStore.avatar" class="user-avatar" />
-            <el-icon><caret-bottom /></el-icon>
-          </div>
-          <template #dropdown>
-            <el-dropdown-menu>
-              <router-link to="/user/profile">
-                <el-dropdown-item>涓汉涓績</el-dropdown-item>
-              </router-link>
-              <el-dropdown-item command="setLayout" v-if="settingsStore.showSettings">
-                <span>甯冨眬璁剧疆</span>
-              </el-dropdown-item>
-              <el-dropdown-item divided command="logout">
-                <span>閫�鍑虹櫥褰�</span>
-              </el-dropdown-item>
-            </el-dropdown-menu>
-          </template>
-        </el-dropdown>
-      </div>
-    </div>
-  </div>
-</template>
-
-<script setup>
-import { ElMessageBox } from "element-plus";
-import { Bell, Search } from "@element-plus/icons-vue";
-import Breadcrumb from "@/components/Breadcrumb";
-import Hamburger from "@/components/Hamburger";
-import Screenfull from "@/components/Screenfull";
-import HeaderSearch from "@/components/HeaderSearch";
-import NotificationCenter from "./NotificationCenter/index.vue";
-import useAppStore from "@/store/modules/app";
-import useUserStore from "@/store/modules/user";
-import useSettingsStore from "@/store/modules/settings";
-
-const appStore = useAppStore();
-const userStore = useUserStore();
-const settingsStore = useSettingsStore();
-
-const topSearchKeyword = ref("");
-const notificationVisible = ref(false);
-const notificationCenterRef = ref(null);
-const unreadCount = ref(0);
-
-function toggleSideBar() {
-  appStore.toggleSideBar();
-}
-
-function handleCommand(command) {
-  switch (command) {
-    case "setLayout":
-      setLayout();
-      break;
-    case "logout":
-      logout();
-      break;
-    default:
-      break;
-  }
-}
-
-function logout() {
-  ElMessageBox.confirm("纭畾娉ㄩ攢骞堕��鍑虹郴缁熷悧锛�", "鎻愮ず", {
-    confirmButtonText: "纭畾",
-    cancelButtonText: "鍙栨秷",
-    type: "warning",
-  })
-    .then(() => {
-      userStore.logOut().then(() => {
-        location.href = "/index";
-      });
-    })
-    .catch(() => {});
-}
-
-const emits = defineEmits(["setLayout"]);
-function setLayout() {
-  emits("setLayout");
-}
-
-function handleUnreadCountChange(count) {
-  unreadCount.value = count;
-}
-
-let unreadCountTimer = null;
-onMounted(() => {
-  nextTick(() => {
-    if (notificationCenterRef.value) {
-      notificationCenterRef.value.loadUnreadCount();
-    }
-  });
-
-  unreadCountTimer = setInterval(() => {
-    if (notificationCenterRef.value) {
-      notificationCenterRef.value.loadUnreadCount();
-    }
-  }, 30000);
-});
-
-watch(notificationVisible, (val) => {
-  if (val && notificationCenterRef.value) {
-    nextTick(() => {
-      notificationCenterRef.value.loadMessages();
-    });
-  }
-});
-
-onUnmounted(() => {
-  if (unreadCountTimer) {
-    clearInterval(unreadCountTimer);
-  }
-});
-</script>
-
-<style lang="scss" scoped>
-.navbar {
-  height: var(--topbar-height);
-  display: flex;
-  align-items: center;
-  justify-content: space-between;
-  gap: 14px;
-  background: rgba(255, 255, 255, 0.86);
-  border: 1px solid rgba(148, 163, 184, 0.18);
-  border-radius: var(--content-radius);
-  backdrop-filter: blur(16px);
-  box-shadow: 0 8px 20px rgba(15, 23, 42, 0.05);
-  padding: 0 18px;
-}
-
-.left-zone {
-  flex: 0 1 420px;
-  min-width: 0;
-  display: flex;
-  align-items: center;
-  gap: 10px;
-}
-
-.hamburger-container {
-  line-height: 36px;
-  height: 36px;
-  width: 36px;
-  border-radius: 10px;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  color: var(--navbar-text);
-
-  &:hover {
-    background: var(--navbar-hover);
-  }
-}
-
-.breadcrumb-container {
-  min-width: 0;
-}
-
-.center-zone {
-  width: clamp(360px, 34vw, 560px);
-  min-width: 320px;
-  height: 38px;
-  border-radius: 999px;
-  border: 1px solid rgba(148, 163, 184, 0.24);
-  background: rgba(248, 251, 255, 0.92);
-  display: flex;
-  align-items: center;
-  padding: 0 12px;
-  gap: 8px;
-}
-
-.search-icon {
-  color: #5b86c9;
-}
-
-.center-zone :deep(.el-input__wrapper) {
-  border: 0;
-  box-shadow: none !important;
-  background: transparent;
-  padding: 0;
-}
-
-.center-zone :deep(.el-input__inner) {
-  color: #334155;
-  font-size: 13px;
-}
-
-.search-popup-trigger :deep(.search-icon) {
-  color: #5b86c9;
-  font-size: 16px;
-  cursor: pointer;
-}
-
-.right-menu {
-  height: 100%;
-  align-items: center;
-  display: flex;
-  gap: 14px;
-}
-
-.right-menu-item {
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  color: var(--navbar-text);
-  border-radius: 8px;
-}
-
-.hover-effect {
-  cursor: pointer;
-  transition: background 0.2s;
-
-  &:hover {
-    background: var(--navbar-hover);
-  }
-}
-
-.notification-container,
-.screenfull-container {
-  width: 36px;
-  height: 36px;
-}
-
-.notification-badge :deep(.el-badge__content) {
-  border: none;
-}
-
-.screenfull-container :deep(.svg-icon) {
-  width: 16px;
-  height: 16px;
-  color: var(--navbar-text);
-}
-
-.avatar-container {
-  height: 100%;
-  display: flex;
-  align-items: center;
-}
-
-.avatar-container :deep(.el-dropdown) {
-  height: 100%;
-  display: flex;
-  align-items: center;
-}
-
-.avatar-wrapper {
-  display: flex;
-  align-items: center;
-  gap: 10px;
-  padding: 4px 10px 4px 8px;
-  height: 44px;
-  border-radius: 22px;
-  background: rgba(255, 255, 255, 0.9);
-  border: 1px solid rgba(148, 163, 184, 0.22);
-}
-
-.user-summary {
-  display: flex;
-  flex-direction: column;
-  align-items: flex-end;
-  gap: 2px;
-}
-
-.user-name {
-  color: var(--text-primary);
-  font-size: 13px;
-  line-height: 1;
-}
-
-.user-role {
-  color: var(--text-tertiary);
-  font-size: 11px;
-  line-height: 1;
-}
-
-.user-avatar {
-  cursor: pointer;
-  width: 36px;
-  height: 36px;
-  border-radius: 50%;
-  border: 1px solid rgba(148, 163, 184, 0.3);
-}
-
-@media (max-width: 1200px) {
-  .center-zone {
-    display: none;
-  }
-
-  .user-summary {
-    display: none;
-  }
-}
-</style>
-
-<style lang="scss">
-.notification-popover {
-  padding: 0 !important;
-  border-radius: 16px !important;
-  border: 1px solid rgba(148, 163, 184, 0.22) !important;
-  box-shadow: 0 18px 40px rgba(15, 23, 42, 0.12) !important;
-  background: rgba(255, 255, 255, 0.94) !important;
-  backdrop-filter: blur(16px);
-
-  .el-popover__title {
-    display: none;
-  }
-
-  .el-popover__body {
-    padding: 0 !important;
-  }
-}
-
-.el-badge__content.is-fixed {
-  top: 8px;
-}
-</style>
+<template>
+  <div class="navbar">
+    <div class="left-zone">
+      <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>
+
+    <div class="center-zone">
+      <el-icon class="search-icon" @click="openHeaderSearch"><Search /></el-icon>
+      <el-input
+        v-model="topSearchKeyword"
+        placeholder="鎼滅储鑿滃崟 / 鍔熻兘 / 鏁版嵁"
+        clearable
+        @keyup.enter="openHeaderSearch"
+      />
+      <header-search
+        ref="headerSearchRef"
+        :keyword="topSearchKeyword"
+        class="search-popup-trigger"
+      />
+    </div>
+
+    <div class="right-menu">
+      <el-popover
+        v-model:visible="notificationVisible"
+        :width="500"
+        placement="bottom-end"
+        trigger="click"
+        :popper-options="{ modifiers: [{ name: 'offset', options: { offset: [0, 10] } }] }"
+        popper-class="notification-popover"
+      >
+        <template #reference>
+          <div class="notification-container right-menu-item hover-effect">
+            <el-badge :value="unreadCount" :hidden="unreadCount === 0" class="notification-badge">
+              <el-icon :size="18">
+                <Bell />
+              </el-icon>
+            </el-badge>
+          </div>
+        </template>
+        <NotificationCenter @unreadCountChange="handleUnreadCountChange" ref="notificationCenterRef" />
+      </el-popover>
+
+      <div class="right-menu-item hover-effect screenfull-container">
+        <screenfull />
+      </div>
+
+      <div class="avatar-container">
+        <el-dropdown @command="handleCommand" class="right-menu-item hover-effect" trigger="click">
+          <div class="avatar-wrapper">
+            <div class="user-summary">
+              <div class="user-name">{{ userStore.nickName || userStore.name || "绠$悊鍛�" }}</div>
+              <div class="user-role">{{ userStore.roleName || "绯荤粺鐢ㄦ埛" }}</div>
+            </div>
+            <img :src="userStore.avatar" class="user-avatar" />
+            <el-icon><caret-bottom /></el-icon>
+          </div>
+          <template #dropdown>
+            <el-dropdown-menu>
+              <router-link to="/user/profile">
+                <el-dropdown-item>涓汉涓績</el-dropdown-item>
+              </router-link>
+              <el-dropdown-item command="setLayout" v-if="settingsStore.showSettings">
+                <span>甯冨眬璁剧疆</span>
+              </el-dropdown-item>
+              <el-dropdown-item divided command="logout">
+                <span>閫�鍑虹櫥褰�</span>
+              </el-dropdown-item>
+            </el-dropdown-menu>
+          </template>
+        </el-dropdown>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ElMessageBox } from "element-plus";
+import { Bell, Search } from "@element-plus/icons-vue";
+import Breadcrumb from "@/components/Breadcrumb";
+import Hamburger from "@/components/Hamburger";
+import Screenfull from "@/components/Screenfull";
+import HeaderSearch from "@/components/HeaderSearch";
+import NotificationCenter from "./NotificationCenter/index.vue";
+import useAppStore from "@/store/modules/app";
+import useUserStore from "@/store/modules/user";
+import useSettingsStore from "@/store/modules/settings";
+
+const appStore = useAppStore();
+const userStore = useUserStore();
+const settingsStore = useSettingsStore();
+
+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);
+}
+
+function handleCommand(command) {
+  switch (command) {
+    case "setLayout":
+      setLayout();
+      break;
+    case "logout":
+      logout();
+      break;
+    default:
+      break;
+  }
+}
+
+function logout() {
+  ElMessageBox.confirm("纭畾娉ㄩ攢骞堕��鍑虹郴缁熷悧锛�", "鎻愮ず", {
+    confirmButtonText: "纭畾",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  })
+    .then(() => {
+      userStore.logOut().then(() => {
+        location.href = "/index";
+      });
+    })
+    .catch(() => {});
+}
+
+const emits = defineEmits(["setLayout"]);
+function setLayout() {
+  emits("setLayout");
+}
+
+function handleUnreadCountChange(count) {
+  unreadCount.value = count;
+}
+
+let unreadCountTimer = null;
+onMounted(() => {
+  nextTick(() => {
+    if (notificationCenterRef.value) {
+      notificationCenterRef.value.loadUnreadCount();
+    }
+  });
+
+  unreadCountTimer = setInterval(() => {
+    if (notificationCenterRef.value) {
+      notificationCenterRef.value.loadUnreadCount();
+    }
+  }, 30000);
+});
+
+watch(notificationVisible, (val) => {
+  if (val && notificationCenterRef.value) {
+    nextTick(() => {
+      notificationCenterRef.value.loadMessages();
+    });
+  }
+});
+
+onUnmounted(() => {
+  if (unreadCountTimer) {
+    clearInterval(unreadCountTimer);
+  }
+});
+</script>
+
+<style lang="scss" scoped>
+.navbar {
+  height: var(--topbar-height);
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  gap: 14px;
+  background: rgba(255, 255, 255, 0.86);
+  border: 1px solid rgba(148, 163, 184, 0.18);
+  border-radius: var(--content-radius);
+  backdrop-filter: blur(16px);
+  box-shadow: 0 8px 20px rgba(15, 23, 42, 0.05);
+  padding: 0 18px;
+}
+
+.left-zone {
+  flex: 0 1 420px;
+  min-width: 0;
+  display: flex;
+  align-items: center;
+  gap: 10px;
+}
+
+.hamburger-container {
+  line-height: 36px;
+  height: 36px;
+  width: 36px;
+  border-radius: 10px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  color: var(--navbar-text);
+
+  &:hover {
+    background: var(--navbar-hover);
+  }
+}
+
+.breadcrumb-container {
+  min-width: 0;
+}
+
+.center-zone {
+  width: clamp(360px, 34vw, 560px);
+  min-width: 320px;
+  height: 38px;
+  border-radius: 999px;
+  border: 1px solid rgba(148, 163, 184, 0.24);
+  background: rgba(248, 251, 255, 0.92);
+  display: flex;
+  align-items: center;
+  padding: 0 12px;
+  gap: 8px;
+}
+
+.search-icon {
+  color: #5b86c9;
+  cursor: pointer;
+}
+
+.center-zone :deep(.el-input__wrapper) {
+  border: 0;
+  box-shadow: none !important;
+  background: transparent;
+  padding: 0;
+}
+
+.center-zone :deep(.el-input__inner) {
+  color: #334155;
+  font-size: 13px;
+}
+
+.search-popup-trigger :deep(.search-icon) {
+  color: #5b86c9;
+  font-size: 16px;
+  cursor: pointer;
+}
+
+.right-menu {
+  height: 100%;
+  align-items: center;
+  display: flex;
+  gap: 14px;
+}
+
+.right-menu-item {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  color: var(--navbar-text);
+  border-radius: 8px;
+}
+
+.hover-effect {
+  cursor: pointer;
+  transition: background 0.2s;
+
+  &:hover {
+    background: var(--navbar-hover);
+  }
+}
+
+.notification-container,
+.screenfull-container {
+  width: 36px;
+  height: 36px;
+}
+
+.notification-badge :deep(.el-badge__content) {
+  border: none;
+}
+
+.screenfull-container :deep(.svg-icon) {
+  width: 16px;
+  height: 16px;
+  color: var(--navbar-text);
+}
+
+.avatar-container {
+  height: 100%;
+  display: flex;
+  align-items: center;
+}
+
+.avatar-container :deep(.el-dropdown) {
+  height: 100%;
+  display: flex;
+  align-items: center;
+}
+
+.avatar-wrapper {
+  display: flex;
+  align-items: center;
+  gap: 10px;
+  padding: 4px 10px 4px 8px;
+  height: 44px;
+  border-radius: 22px;
+  background: rgba(255, 255, 255, 0.9);
+  border: 1px solid rgba(148, 163, 184, 0.22);
+}
+
+.user-summary {
+  display: flex;
+  flex-direction: column;
+  align-items: flex-end;
+  gap: 2px;
+}
+
+.user-name {
+  color: var(--text-primary);
+  font-size: 13px;
+  line-height: 1;
+}
+
+.user-role {
+  color: var(--text-tertiary);
+  font-size: 11px;
+  line-height: 1;
+}
+
+.user-avatar {
+  cursor: pointer;
+  width: 36px;
+  height: 36px;
+  border-radius: 50%;
+  border: 1px solid rgba(148, 163, 184, 0.3);
+}
+
+@media (max-width: 1200px) {
+  .center-zone {
+    display: none;
+  }
+
+  .user-summary {
+    display: none;
+  }
+}
+</style>
+
+<style lang="scss">
+.notification-popover {
+  padding: 0 !important;
+  border-radius: 16px !important;
+  border: 1px solid rgba(148, 163, 184, 0.22) !important;
+  box-shadow: 0 18px 40px rgba(15, 23, 42, 0.12) !important;
+  background: rgba(255, 255, 255, 0.94) !important;
+  backdrop-filter: blur(16px);
+
+  .el-popover__title {
+    display: none;
+  }
+
+  .el-popover__body {
+    padding: 0 !important;
+  }
+}
+
+.el-badge__content.is-fixed {
+  top: 8px;
+}
+</style>

--
Gitblit v1.9.3