Bladeren bron

refactor: modernize Header component styles

- Use CSS custom properties (variables) for consistent theming
- Implement flexbox layout throughout
- Simplify navigation structure and styling
- Add smooth hover animations with underline effect
- Modern dropdown menu with fade/slide transition
- Improved mobile navigation with collapse animation
- Clean responsive breakpoints (768px, 991px, 1200px)
- Remove redundant CSS and Bootstrap dependencies
- Add sticky header positioning
- Better visual hierarchy and spacing
- Accessible alt text for logo images

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Ryuiso 3 weken geleden
bovenliggende
commit
368bc1dfe8
1 gewijzigde bestanden met toevoegingen van 286 en 273 verwijderingen
  1. 286 273
      src/components/Header.vue

+ 286 - 273
src/components/Header.vue

@@ -1,390 +1,403 @@
 <template>
-  <!-- 头部整体盒子 -->
-  <div id="header" class="container-fuild">
-    <!-- 头部顶部 -->
-    <div class="header-top container-fuild hidden-xs">
+  <header id="header">
+    <!-- 顶部信息栏 (桌面端) -->
+    <div class="header-top hidden-xs">
       <div class="container">
-        <div class="server pull-left">
-          <span class="glyphicon glyphicon-earphone"></span>15086621233
-          <span class="glyphicon glyphicon-envelope"></span>zhanyuhangkong@163.com
-          <span class="glyphicon glyphicon-time"></span>全天候服务
+        <div class="header-top-left">
+          <span><i class="glyphicon glyphicon-earphone"></i> 15086621233</span>
+          <span><i class="glyphicon glyphicon-envelope"></i> zhanyuhangkong@163.com</span>
+          <span><i class="glyphicon glyphicon-time"></i> 全天候服务</span>
         </div>
-        <div class="shejiao pull-right">
-          <span class="glyphicon glyphicon-hand-right"></span>赶快联系我们吧!
-          <span class="glyphicon glyphicon-hand-left"></span>
+        <div class="header-top-right">
+          <span><i class="glyphicon glyphicon-hand-right"></i> 赶快联系我们吧!</span>
+          <i class="glyphicon glyphicon-hand-left"></i>
         </div>
       </div>
     </div>
-    <!-- 电脑导航 -->
-    <div class="header-nav container hidden-xs ">
-      <!-- 导航 logo -->
-      <div class="header-nav-logo">
-        <img src="@/assets/img/logo_black.svg" alt="logo">
+
+    <!-- 主导航 (桌面端) -->
+    <nav class="header-nav container hidden-xs">
+      <div class="header-logo">
+        <img src="@/assets/img/logo_black.svg" alt="Logo">
       </div>
-      <!-- 导航内容 -->
-      <ul class="header-nav-wrapper">
+      <ul class="nav-menu">
         <li
-          v-for="(item,index) in navList"
+          v-for="(item, index) in navList"
           :key="index"
-          :class="index==navIndex?'active':''"
-          @click="navClick(index,item.name)"
+          :class="{ active: index === navIndex }"
+          @click="navClick(index, item.name)"
         >
           <router-link :to="item.path">
             {{ item.name }}
-            <span v-if="item.children.length>0" class="glyphicon glyphicon-menu-down"></span>
-            <i class="underline"></i>
+            <i v-if="item.children.length > 0" class="glyphicon glyphicon-menu-down"></i>
+            <span class="nav-underline"></span>
           </router-link>
-          <dl v-if="item.children.length>0">
-            <dt v-for="(i,n) in item.children" :key="n">
-              <router-link :to="i.path">{{ i.name }}</router-link>
-            </dt>
-          </dl>
+          <!-- 二级菜单 -->
+          <ul v-if="item.children.length > 0" class="submenu">
+            <li v-for="(child, n) in item.children" :key="n">
+              <router-link :to="child.path">{{ child.name }}</router-link>
+            </li>
+          </ul>
         </li>
       </ul>
-    </div>
-    <!-- 手机导航 -->
-    <div class="header-nav-m container-fuild visible-xs">
-      <div class="header-nav-m-logo">
-        <img class="center-block" src="@/assets/img/logo_black.svg" alt="logo">
+    </nav>
+
+    <!-- 移动端导航 -->
+    <div class="header-mobile visible-xs">
+      <div class="header-mobile-logo">
+        <img src="@/assets/img/logo_black.svg" alt="Logo">
       </div>
-      <!-- 导航栏 -->
-      <div class="header-nav-m-menu text-center">
-        {{ menuName }}
-        <div
-          class="header-nav-m-menu-wrapper"
-          data-toggle="collapse"
-          data-target="#menu"
-          @click="menuClick"
-        >
-          <span :class="menuClass"></span>
-        </div>
-        <!-- 导航内容 -->
-        <ul id="menu" class="header-nav-m-wrapper collapse">
-          <li
-            v-for="(item,index) in navList"
-            :key="index"
-            :class="index==navIndex?'active':''"
-            @click="navClick(index,item.name)"
-            data-toggle="collapse"
-            data-target="#menu"
-          >
-            <router-link :to="item.path">
-              {{ item.name }}
-              <i class="underline"></i>
-            </router-link>
-          </li>
-        </ul>
+      <div class="header-mobile-menu" @click="toggleMenu">
+        <span>{{ menuName }}</span>
+        <i :class="menuClass"></i>
       </div>
+      <ul class="mobile-nav-menu collapse" id="mobileMenu">
+        <li
+          v-for="(item, index) in navList"
+          :key="index"
+          :class="{ active: index === navIndex }"
+          @click="navClick(index, item.name)"
+        >
+          <router-link :to="item.path">{{ item.name }}</router-link>
+        </li>
+      </ul>
     </div>
-  </div>
+  </header>
 </template>
+
 <script>
 export default {
   name: "Header",
   data() {
     return {
-      navIndex: sessionStorage.getItem('navIndex') ? sessionStorage.getItem('navIndex') : 0,
+      navIndex: sessionStorage.getItem('navIndex') || 0,
       menuName: "首页",
       menuClass: "glyphicon glyphicon-menu-down",
       navList: [
-        {
-          name: "首页",
-          path: "/",
-          children: []
-        },
+        { name: "首页", path: "/", children: [] },
         {
           name: "产品",
           path: "/products",
           children: [
-            {
-              name: "行业应用无人机",
-              path: "/products/djiAircraft"
-            },
-            {
-              name: "无人机负载",
-              path: "/products/payloads"
-            },
-            {
-              name: "软件与服务",
-              path: "/products/software"
-            },
-            {
-              name: "软件定制开发",
-              path: "/products/develop"
-            },
+            { name: "行业应用无人机", path: "/products/djiAircraft" },
+            { name: "无人机负载", path: "/products/payloads" },
+            { name: "软件与服务", path: "/products/software" },
+            { name: "软件定制开发", path: "/products/develop" }
           ]
         },
-        {
-          name: "解决方案",
-          path: "/solutions",
-          children: []
-        },
-        {
-          name: "公司动态",
-          path: "/news",
-          children: []
-        },
-        {
-          name: "公司介绍",
-          path: "/info",
-          children: []
-        },
+        { name: "解决方案", path: "/solutions", children: [] },
+        { name: "公司动态", path: "/news", children: [] },
+        { name: "公司介绍", path: "/info", children: [] }
       ]
     };
   },
   methods: {
     navClick(index, name) {
       this.navIndex = index;
-      sessionStorage.setItem('navIndex', index)
+      sessionStorage.setItem('navIndex', index);
       this.menuName = name;
     },
-    menuClick() {
-      if (this.menuClass == "glyphicon glyphicon-menu-down") {
-        this.menuClass = "glyphicon glyphicon-menu-up";
-      } else {
-        this.menuClass = "glyphicon glyphicon-menu-down";
-      }
+    toggleMenu() {
+      this.menuClass = this.menuClass.includes('menu-down')
+        ? "glyphicon glyphicon-menu-up"
+        : "glyphicon glyphicon-menu-down";
     }
   }
 };
 </script>
+
 <style scoped>
-/* 顶部 */
+/* ===== CSS 变量 ===== */
 #header {
-  background: #f4f4f4;
-  transition: all ease 0.6s;
-  box-shadow: 0 1px 2px lightgrey;
+  --header-bg: #f4f4f4;
+  --header-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+  --top-bar-bg: #474747;
+  --top-bar-text: #fff;
+  --nav-text: #333;
+  --nav-hover: #1e73be;
+  --nav-active: #1e73be;
+  --submenu-bg: #fff;
+  --submenu-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+  --transition: all 0.3s ease;
 }
 
-#header .header-top {
-  height: 30px;
-  color: #fff;
-  font-size: 10px;
-  line-height: 30px;
-  background: #474747;
+/* ===== 基础样式 ===== */
+#header {
+  background: var(--header-bg);
+  box-shadow: var(--header-shadow);
+  position: sticky;
+  top: 0;
+  z-index: 1000;
 }
 
-/* 顶部的图标 */
-#header .header-top span {
-  margin: 0 8px;
+/* ===== 顶部信息栏 ===== */
+.header-top {
+  background: var(--top-bar-bg);
+  color: var(--top-bar-text);
+  font-size: 12px;
+  height: 36px;
+  line-height: 36px;
 }
 
-/* 导航栏 */
-#header .header-nav {
-  height: 80px;
+.header-top .container {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
 }
 
-/* 导航栏 logo */
-#header .header-nav .header-nav-logo {
-  width: 140px;
-  height: 80px;
-  float: left;
-  padding: 15px 20px;
-  box-sizing: border-box;
+.header-top-left,
+.header-top-right {
+  display: flex;
+  gap: 16px;
+  align-items: center;
 }
 
-/* 导航栏 logo 图片 */
-#header .header-nav .header-nav-logo img {
-  width: 100%;
-  height: 100%;
-  object-fit: contain;
+.header-top i {
+  margin-right: 4px;
+  font-size: 11px;
 }
 
-/* 导航栏 导航容器 */
-#header .header-nav-fixed .header-nav-wrapper {
-  line-height: 30px;
+/* ===== 主导航 ===== */
+.header-nav {
+  display: flex;
+  align-items: center;
+  height: 80px;
+  gap: 40px;
 }
 
-#header .header-nav .header-nav-wrapper {
-  float: right;
+/* Logo */
+.header-logo {
+  flex-shrink: 0;
+  width: 140px;
   height: 50px;
   display: flex;
-  align-items: flex-end;
-  padding-bottom: 15px;
-  box-sizing: border-box;
+  align-items: center;
+}
+
+.header-logo img {
+  max-width: 100%;
+  max-height: 100%;
+  object-fit: contain;
 }
 
-/* 导航栏 每个导航 */
-#header .header-nav .header-nav-wrapper > li {
-  float: left;
-  margin: 0 15px;
+/* 导航菜单 */
+.nav-menu {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+  list-style: none;
+  margin: 0;
+  padding: 0;
+  flex: 1;
+  justify-content: flex-end;
+}
+
+.nav-menu > li {
   position: relative;
 }
 
-/* 导航栏 每个导航下面的 a 链接 */
-#header .header-nav .header-nav-wrapper > li > a {
-  color: #000;
+.nav-menu > li > a {
+  display: flex;
+  align-items: center;
+  gap: 4px;
+  padding: 12px 16px;
+  color: var(--nav-text);
   font-size: 14px;
-  font-weight: bold;
-  padding: 13px 0;
-  position: relative;
+  font-weight: 600;
+  text-decoration: none;
+  transition: var(--transition);
 }
 
-/* 导航栏 每个导航下面的 a 链接的下划线 */
-#header .header-nav .header-nav-wrapper > li > a > i {
-  display: block;
+.nav-menu > li > a:hover,
+.nav-menu > li.active > a {
+  color: var(--nav-hover);
+}
+
+.nav-menu > li > a i {
+  font-size: 10px;
+  transition: transform 0.3s ease;
+}
+
+.nav-menu > li > a:hover i {
+  transform: rotate(180deg);
+}
+
+/* 下划线动画 */
+.nav-underline {
   position: absolute;
-  bottom: -2px;
+  bottom: 8px;
   left: 50%;
   width: 0;
-  height: 1px;
-  opacity: 0;
-  transition: all 0.3s ease;
-  background-color: #1e73be;
+  height: 2px;
+  background: var(--nav-active);
+  transition: var(--transition);
+  transform: translateX(-50%);
 }
 
-/* 导航栏 每个导航下面的 a 链接的右侧小三角 */
-#header .header-nav .header-nav-wrapper > li > a > span {
-  font-size: 10px;
-  transition: transform ease 0.4s;
+.nav-menu > li > a:hover .nav-underline,
+.nav-menu > li.active .nav-underline {
+  width: calc(100% - 32px);
 }
 
-/* 导航栏 每个导航下面的 a 链接 鼠标滑上去的样式 */
-#header .header-nav .header-nav-wrapper > li > a:hover {
-  color: #1e73be;
-  text-decoration: none;
+.nav-menu > li.active > a {
+  color: var(--nav-active);
 }
 
-/* 导航栏 每个导航下面的 a 链接 鼠标滑上去下划线的样式 */
-#header .header-nav .header-nav-wrapper > li > a:hover .underline {
-  opacity: 1;
-  width: 100%;
+/* 二级菜单 */
+.submenu {
+  position: absolute;
+  top: 100%;
   left: 0;
+  min-width: 160px;
+  background: var(--submenu-bg);
+  border-radius: 8px;
+  box-shadow: var(--submenu-shadow);
+  list-style: none;
+  margin-top: 8px;
+  padding: 8px 0;
+  opacity: 0;
+  visibility: hidden;
+  transform: translateY(-10px);
+  transition: var(--transition);
 }
 
-/* 导航栏 每个导航下面的 a 链接 鼠标滑上去三角标的样式 */
-#header .header-nav .header-nav-wrapper > li > a:hover span {
-  transform: rotate(180deg);
+.nav-menu > li:hover .submenu {
+  opacity: 1;
+  visibility: visible;
+  transform: translateY(0);
 }
 
-/* 导航栏 每个导航下面的 a 链接 鼠标点击后的样式 */
-#header .header-nav .header-nav-wrapper > li.active > a {
-  color: #1e73be;
+.submenu li a {
+  display: block;
+  padding: 10px 20px;
+  color: var(--nav-text);
+  font-size: 13px;
   text-decoration: none;
-  border-bottom: 2px solid #1e73be;
+  transition: var(--transition);
 }
 
-/* 导航栏 每个导航下面的二级导航容器 */
-#header .header-nav .header-nav-wrapper > li > dl {
-  display: none;
-  position: absolute;
-  width: 150px;
-  margin-top: 14px;
-  left: 0;
-  z-index: 999999;
-  box-shadow: 0 0 1px 1px #f3f3f3;
-  border-radius: 5px;
-  background: #fff;
+.submenu li a:hover {
+  background: #f5f5f5;
+  color: var(--nav-hover);
 }
 
-/* 导航栏 每个导航下面的二级导航容器的每个导航 */
-#header .header-nav .header-nav-wrapper > li > dl > dt {
-  width: 100%;
-  padding: 10px;
-  border-bottom: 1px solid #f3f3f3;
+/* ===== 移动端导航 ===== */
+.header-mobile {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  height: 70px;
+  padding: 0 20px;
+  background: var(--header-bg);
 }
 
-/* 导航栏 每个导航下面的二级导航容器的每个导航 当鼠标滑上时的样式 */
-#header .header-nav .header-nav-wrapper > li > dl > dt > a:hover {
-  text-decoration: none;
+.header-mobile-logo {
+  width: 120px;
+  height: 40px;
+  display: flex;
+  align-items: center;
 }
 
-/* 导航栏 滑上一级导航显示二级导航 */
-#header .header-nav .header-nav-wrapper > li:hover dl {
-  display: block;
+.header-mobile-logo img {
+  max-width: 100%;
+  max-height: 100%;
+  object-fit: contain;
 }
 
-#header .header-nav .header-nav-wrapper > li > dl > dt:hover {
+.header-mobile-menu {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+  padding: 8px 16px;
+  background: #474747;
+  color: #fff;
+  border-radius: 4px;
   cursor: pointer;
-  background: #f5f5f5;
-  text-decoration: underline;
-  text-decoration-color: #1e73be;
+  font-size: 13px;
 }
 
-/* 移动端适配 */
-@media screen and (max-width: 997px) {
-  /* 导航栏 logo 容器 */
-  #header .header-nav-m .header-nav-m-logo {
-    height: 70px;
-    padding: 10px 15px;
-    box-sizing: border-box;
-  }
+.header-mobile-menu i {
+  font-size: 12px;
+}
 
-  /* 导航栏 logo 图片 */
-  #header .header-nav-m .header-nav-m-logo img {
-    width: 100%;
-    height: 100%;
-    object-fit: contain;
-  }
+.mobile-nav-menu {
+  position: absolute;
+  top: 70px;
+  left: 0;
+  right: 0;
+  background: #474747;
+  list-style: none;
+  margin: 0;
+  padding: 0;
+  max-height: 0;
+  overflow: hidden;
+  transition: max-height 0.3s ease;
+}
 
-  /* 导航栏 菜单容器 */
-  #header .header-nav-m .header-nav-m-menu {
-    color: #fff;
-    height: 40px;
-    font-size: 13px;
-    line-height: 40px;
-    background: #474747;
-    position: relative;
-  }
+.mobile-nav-menu.collapse.in {
+  max-height: 300px;
+}
 
-  /* 导航栏 菜单图标 */
-  #header .header-nav-m .header-nav-m-menu-wrapper {
-    position: absolute;
-    top: 50%;
-    right: 20px;
-    margin-top: -20px;
-    width: 50px;
-    height: 40px;
-    color: #fff;
-    z-index: 999999;
-    font-size: 12px;
-  }
+.mobile-nav-menu > li {
+  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
+}
 
-  /* 导航栏 */
-  #header .header-nav-m .header-nav-m-wrapper {
-    position: absolute;
-    top: 40px;
-    left: 0;
-    width: 100%;
-    background: #474747;
-    z-index: 9999999;
-  }
+.mobile-nav-menu > li > a {
+  display: block;
+  padding: 14px 20px;
+  color: #fff;
+  font-size: 14px;
+  text-decoration: none;
+  transition: var(--transition);
+}
 
-  /* 导航栏 每个导航 */
-  #header .header-nav-m .header-nav-m-wrapper > li {
-    height: 40px;
-    line-height: 40px;
-    border-bottom: 1px solid #ccc;
-  }
+.mobile-nav-menu > li > a:hover,
+.mobile-nav-menu > li.active > a {
+  background: rgba(30, 115, 190, 0.3);
+  color: #fff;
+}
 
-  /* 导航栏 每个导航下面的 a 链接 */
-  #header .header-nav-m .header-nav-m-wrapper > li > a {
-    color: #fff;
-    font-size: 13px;
-    font-weight: bold;
-    padding: 15px 0;
-    position: relative;
+/* ===== 响应式 ===== */
+@media (max-width: 767px) {
+  .header-top .container {
+    flex-direction: column;
+    gap: 8px;
+    padding: 8px 0;
   }
-
-  /* 导航栏 每个导航下面的 a 链接的右侧小三角 */
-  #header .header-nav .header-nav-wrapper > li > a > span {
-    font-size: 10px;
+  
+  .header-top-left,
+  .header-top-right {
+    flex-wrap: wrap;
+    justify-content: center;
   }
 }
 
-/* 平板适配 */
-@media screen and (min-width: 768px) and (max-width: 997px) {
-  #header .header-nav .header-nav-logo {
+@media (min-width: 768px) and (max-width: 991px) {
+  .header-logo {
     width: 120px;
-    padding: 12px 15px;
+  }
+  
+  .nav-menu {
+    gap: 4px;
+  }
+  
+  .nav-menu > li > a {
+    padding: 12px 10px;
+    font-size: 13px;
   }
 }
 
-/* 大屏幕优化 */
-@media screen and (min-width: 1200px) {
-  #header .header-nav .header-nav-logo {
+@media (min-width: 1200px) {
+  .header-logo {
     width: 160px;
-    padding: 15px 25px;
+  }
+  
+  .nav-menu {
+    gap: 12px;
+  }
+  
+  .nav-menu > li > a {
+    padding: 12px 20px;
   }
 }
 </style>