Procházet zdrojové kódy

使用 el-menu 重构 NavBar.vue, 使 navbar 适配移动端

reghao před 2 roky
rodič
revize
6cef5814a0

+ 0 - 4
src/App.vue

@@ -2,8 +2,6 @@
   <div id="app">
     <!--导航栏-->
     <nav-bar />
-    <!--手机屏幕下显示的搜索框-->
-    <div class="hidden-sm-and-up searchd"><search-box /></div>
     <!--下面的部分通过路由动态决定渲染与否-->
     <!--exclude,其值为正则,匹配到的组件的名称会被排除在keep-alive之外-->
     <keep-alive exclude="Collection,History">
@@ -18,14 +16,12 @@
 
 <script>
 import NavBar from 'components/layout/NavBar'
-import SearchBox from 'components/layout/SearchBox'
 import FooterBar from 'components/layout/FooterBar'
 
 export default {
   name: 'App',
   components: {
     FooterBar,
-    SearchBox,
     NavBar
   },
   created() {

+ 1 - 22
src/assets/js/mixin.js

@@ -4,7 +4,7 @@
 import { getPubkey, getCaptchaCode, getVerifyCode, login, logout } from '@/api/account'
 import { setUserToken, removeAll } from '@/utils/auth'
 import { JSEncrypt } from 'jsencrypt'
-import Vue from "vue";
+import Vue from 'vue'
 
 export const userMixin = {
   data() {
@@ -198,27 +198,6 @@ export const userMixin = {
         })
       })
     },
-    goToPost() {
-      if (this.$route.path === '/post/list') {
-        this.$router.go(0)
-        return
-      }
-      this.$router.push('/post/list')
-    },
-    goToCollection() {
-      if (this.$route.path === '/u/myfavlist') {
-        this.$router.go(0)
-        return
-      }
-      this.$router.push('/u/myfavlist')
-    },
-    goToHistory() {
-      if (this.$route.path === '/u/history') {
-        this.$router.go(0)
-        return
-      }
-      this.$router.push('/u/history')
-    },
     // 点击注册
     register() {
       if (this.password !== this.repassword) {

+ 244 - 269
src/components/layout/NavBar.vue

@@ -1,187 +1,156 @@
 <template>
-  <div>
-    <el-row id="navbar" class="main">
-      <!--logo-->
-      <el-col :sm="4" class="right">
-        <a href="/" class="tit">
-          <img src="@/assets/img/icon/logo.png" class="logo" alt="img">
-          <span>bili</span>
-        </a>
-      </el-col>
-      <el-col :sm="1" class="right">
-        <a href="/video" class="tit">
-          <span>视频</span>
-        </a>
-      </el-col>
-      <el-col :sm="1" class="right">
-        <a href="/shortvideo" class="tit">
-          <span>短视频</span>
-        </a>
-      </el-col>
-      <el-col :sm="1" class="right">
-        <a href="/image" class="tit">
-          <span>图片</span>
-        </a>
-      </el-col>
-      <el-col :sm="1" class="right">
-        <a href="/article" class="tit">
-          <span>文章</span>
-        </a>
-      </el-col>
-      <el-col :sm="1" class="right">
-        <a href="/discover" class="tit">
-          <span>发现</span>
-        </a>
-      </el-col>
-      <!--搜索框-->
-      <el-col :sm="8" class="search">
-        <search-box />
-      </el-col>
-      <el-col :sm="1" class="right logo">
-        <a href="/message" class="tit logo">
-          <span class="el-icon-bell logo" />
-        </a>
-      </el-col>
-      <el-col :sm="1" class="right logo">
-        <a href="/post/publish" class="tit logo">
-          <span class="el-icon-upload logo" />
-        </a>
-      </el-col>
-      <!--用户信息-->
-      <el-col :sm="5" class="user-info">
-        <!--头像-->
-        <img
-          v-if="!user"
-          src="@/assets/img/icon/avatar.png"
-          title="点击登录"
-          class="el-avatar--medium"
-          style="cursor: pointer"
-          alt=""
-          @click="login"
-        >
-        <img
-          v-else
-          :src="user.avatarUrl"
-          class="el-avatar--circle el-avatar--medium"
-          alt=""
-        >
-        <!--下拉菜单-->
-        <el-dropdown class="drop">
-          <span class="el-dropdown-link">
-            <span v-if="user">{{ user.username }}</span>
-            <span
-              v-else
-              title="点击登录"
-              @click="login"
-            >登录</span>
-            <i class="el-icon-arrow-down el-icon--right" />
-          </span>
-          <el-dropdown-menu /><!--防止该标签隐藏的时候控制台会报错-->
-          <el-dropdown-menu v-if="user" slot="dropdown" class="iconsize">
-            <el-dropdown-item
-              icon="el-icon-user-solid"
-              class="size"
-              @click.native="goToProfile"
-            >我的帐号</el-dropdown-item>
-            <el-dropdown-item
-              icon="el-icon-more"
-              class="size"
-              @click.native="goToTimeline"
-            >时间线</el-dropdown-item>
-            <el-dropdown-item
-              icon="el-icon-s-home"
-              class="size"
-              @click.native="goToHome"
-            >我的主页</el-dropdown-item>
-            <el-dropdown-item
-              icon="el-icon-s-data"
-              class="size"
-              @click.native="goToPost"
-            >我的稿件
-            </el-dropdown-item>
-            <el-dropdown-item
-              icon="el-icon-star-on"
-              class="size"
-              @click.native="goToCollection"
-            >收藏夹
-            </el-dropdown-item>
-            <el-dropdown-item
-              icon="el-icon-video-camera-solid"
-              class="size"
-              @click.native="goToHistory"
-            >历史记录
-            </el-dropdown-item>
-            <el-dropdown-item
-              icon="el-icon-error"
-              class="size"
-              @click.native="goToLogout"
-            >退出</el-dropdown-item>
-          </el-dropdown-menu>
-        </el-dropdown>
-      </el-col>
-    </el-row>
-    <!--防止下面的盒子上移动,nav-bar脱离了标准流-->
-    <div style="height: 50px" />
-    <!--登录弹窗-->
-    <el-dialog
-      title="用户登录"
-      append-to-body
-      :visible.sync="dialogVisible"
-      width="30%"
-      center
-    >
-      <el-input
-        v-model="userLogin.username"
-        placeholder="请输入手机号或邮箱"
-        style="width: 70%; padding-right: 2px"
-        clearable
-      />
-      <br>
-      <br>
-      <el-input
-        v-model="userLogin.password"
-        placeholder="请输入验证码"
-        style="width: 45%; padding-right: 2px"
-      />
-      <el-button :disabled="isBtn" @click="fetchVerifyCode">{{ code }}</el-button>
-      <br>
-      <br>
-      <el-image :src="captchaCode" @click="getCaptcha" />
-      <el-input
-        v-model="userLogin.captchaCode"
-        placeholder="请输入图形验证码"
-        style="width: 45%; padding-right: 2px"
-      />
-      <br>
-      <br>
-      <span
-        class="register"
-      >账号不存在会自动注册</span>
-      <span slot="footer" class="dialog-footer">
-        <el-button
-          type="primary"
-          :loading="isLoading"
-          @click.native="loginBtn"
-        >登 录</el-button>
-      </span>
-    </el-dialog>
-  </div>
+  <el-row class="el-menu-demo">
+    <el-col :md="2">
+      <ul role="menubar" class="el-menu--horizontal el-menu">
+        <li role="menuitem" class="el-menu-item">
+          <a href="/" style="color: #007bff;text-decoration-line: none">
+            <img src="@/assets/img/icon/logo.png" class="logo" alt="img">
+            bili
+          </a>
+        </li>
+      </ul>
+    </el-col>
+    <el-col :md="8">
+      <el-menu
+        mode="horizontal"
+      >
+        <el-menu-item index="1">
+          <a href="/video" style="text-decoration-line: none">
+            <span style="color: #007bff">视频</span>
+          </a>
+        </el-menu-item>
+        <el-menu-item index="2">
+          <a href="/shortvideo" style="text-decoration-line: none">
+            <span style="color: #007bff">短视频</span>
+          </a>
+        </el-menu-item>
+        <el-menu-item index="3">
+          <a href="/image" style="text-decoration-line: none">
+            <span style="color: #007bff">相册</span>
+          </a>
+        </el-menu-item>
+        <el-menu-item index="4">
+          <a href="/article" style="text-decoration-line: none">
+            <span style="color: #007bff">文章</span>
+          </a>
+        </el-menu-item>
+        <el-menu-item index="5">
+          <a href="/discover" style="text-decoration-line: none">
+            <span style="color: #007bff">发现</span>
+          </a>
+        </el-menu-item>
+      </el-menu>
+    </el-col>
+    <el-col :md="8">
+      <ul class="el-menu--horizontal el-menu">
+        <li class="el-menu-item">
+          <el-autocomplete
+            v-model="keyword"
+            :fetch-suggestions="querySearchAsync"
+            :placeholder="placeholder"
+            clearable
+            suffix-icon="el-icon-search"
+            size="medium"
+            :debounce="1000"
+            @keyup.enter.native="onSearch"
+            @select="onSearch"
+          />
+        </li>
+      </ul>
+    </el-col>
+    <el-col :md="6">
+      <ul class="el-menu--horizontal el-menu">
+        <li class="el-menu-item">
+          <el-dropdown v-if="user">
+            <img
+              :src="user.avatarUrl"
+              class="el-avatar--circle el-avatar--medium"
+              alt=""
+            >
+            <el-dropdown-menu v-if="user" slot="dropdown" class="iconsize">
+              <el-dropdown-item
+                icon="el-icon-user-solid"
+                class="size"
+                @click.native="goToProfile"
+              >我的帐号</el-dropdown-item>
+              <el-dropdown-item
+                icon="el-icon-s-home"
+                class="size"
+                @click.native="goToHome"
+              >我的主页</el-dropdown-item>
+              <el-dropdown-item
+                icon="el-icon-s-data"
+                class="size"
+                @click.native="goToPost"
+              >我的稿件
+              </el-dropdown-item>
+              <el-dropdown-item
+                icon="el-icon-star-on"
+                class="size"
+                @click.native="goToFavlist"
+              >收藏夹
+              </el-dropdown-item>
+              <el-dropdown-item
+                icon="el-icon-video-camera-solid"
+                class="size"
+                @click.native="goToHistory"
+              >历史记录
+              </el-dropdown-item>
+              <el-dropdown-item
+                icon="el-icon-error"
+                class="size"
+                @click.native="goToLogout"
+              >退出</el-dropdown-item>
+            </el-dropdown-menu>
+          </el-dropdown>
+          <span
+            v-else
+            style="color: #007bff"
+            @click="login"
+          >登录</span>
+        </li>
+        <li class="el-menu-item" @click="goToTimeline">
+          <el-badge v-if="statusCount > 0" class="item" :value="statusCount" :max="99">
+            <span class="el-icon-view" style="color: #007bff">状态</span>
+          </el-badge>
+          <span v-else class="el-icon-view" style="color: #007bff">状态</span>
+        </li>
+        <li class="el-menu-item" @click="goToMessage">
+          <el-badge v-if="msgCount > 0" class="item" :value="msgCount" :max="99">
+            <span class="el-icon-bell" style="color: #007bff">消息</span>
+          </el-badge>
+          <span v-else class="el-icon-bell" style="color: #007bff">消息</span>
+        </li>
+        <li class="el-menu-item">
+          <el-button size="mini" type="upload" icon="el-icon-upload" @click="goToPublish">投稿</el-button>
+        </li>
+      </ul>
+    </el-col>
+  </el-row>
 </template>
 
 <script>
 import Vue from 'vue'
-import SearchBox from '@/components/layout/SearchBox'
 import { userMixin } from 'assets/js/mixin'
 import { getMyInfo } from '@/api/user'
+import { keywordSuggest } from '@/api/search'
 
 export default {
-  name: 'NavBar',
-  components: { SearchBox },
+  name: 'NavBar1',
   mixins: [userMixin],
   data() {
     return {
       user: null,
-      drawer: false
+      drawer: false,
+      activeIndex: '1',
+      activeIndex2: '1',
+      restaurants: [],
+      placeholder: '想要搜点神马呢',
+      keyword: '',
+      timer: null,
+      statusCount: 0,
+      msgCount: 10,
+      avatarUrl: '//pica.zhimg.com/v2-465c3f851b3e56844bf2be9ad5b54f95.jpg'
     }
   },
   created() {
@@ -195,6 +164,72 @@ export default {
     }
   },
   methods: {
+    handleSelect(key, keyPath) {
+      console.log(key, keyPath)
+    },
+    // 重点:当框中的改变时触发该方法,elementui自动设置了防抖,参见debounce属性
+    // queryString 为输入框中的值。cb为返回显示列表的回调函数
+    querySearchAsync(queryString, cb) {
+      if (queryString === '') {
+        return
+      }
+
+      setTimeout(() => {
+        keywordSuggest(queryString).then(res => {
+          if (res.code === 0) {
+            this.restaurants = res.data.map((item) => {
+              return {
+                value: item.keyword,
+                rank: 1
+              }
+            })
+
+            // 如果 cb 返回一个空数组, 那么模糊搜索输入建议的下拉选项会因为 length 为 0 而消失
+            // cb([])
+            cb(this.restaurants)
+            // eslint-disable-next-line no-empty
+          } else {
+          }
+        })
+      }, 500)
+    },
+    // select 事件或 enter 键事件
+    onSearch() {
+      console.log('回车事件')
+      // 正则去空格
+      if (this.keyword.replace(/\s*/g, '')) {
+        this.toSearchPage()
+      } else {
+        this.$message({
+          showClose: true,
+          message: '不能为空!',
+          type: 'warning'
+        })
+      }
+    },
+    // 跳转搜索页面,传递搜索框的参数
+    toSearchPage() {
+      const currentPath = this.$route.path
+      if (currentPath === '/search') {
+        this.$router.push({
+          path: '/search',
+          query: {
+            keyword: this.keyword,
+            pageNumber: 1
+          }
+        })
+        this.$router.go(0)
+      } else {
+        const routeUrl = this.$router.resolve({
+          path: '/search',
+          query: {
+            keyword: this.keyword,
+            pageNumber: 1
+          }
+        })
+        window.open(routeUrl.href, '_blank')
+      }
+    },
     login() {
       this.fetchPubkey()
       this.dialogVisible2 = false
@@ -228,121 +263,61 @@ export default {
         return
       }
       this.$router.push(path)
+    },
+    goToPost() {
+      if (this.$route.path === '/my/post/list/video') {
+        this.$router.go(0)
+        return
+      }
+      this.$router.push('/my/post/list/video')
+    },
+    goToFavlist() {
+      if (this.$route.path === '/my/favlist/video') {
+        this.$router.go(0)
+        return
+      }
+      this.$router.push('/my/favlist/video')
+    },
+    goToHistory() {
+      if (this.$route.path === '/my/visit') {
+        this.$router.go(0)
+        return
+      }
+      this.$router.push('/my/visit')
+    },
+    goToMessage() {
+      if (this.$route.path === '/my/message/receive') {
+        this.$router.go(0)
+        return
+      }
+      this.$router.push('/my/message/receive')
+    },
+    goToPublish() {
+      if (this.$route.path === '/my/post/publish/video') {
+        this.$router.go(0)
+        return
+      }
+      this.$router.push('/my/post/publish/video')
     }
   }
 }
 </script>
 
 <style scoped>
-#navbar {
-  height: 50px;
-  border-bottom: 1px solid rgba(34, 36, 38, 0.15);
-  box-shadow: 0 1px 2px 0 rgba(34, 36, 38, 0.15);
-
-  position: fixed;
-  top: 0;
-  left: 0;
-  right: 0;
-  background-color: #ffffff;
-  z-index: 9;
-}
-
-.navmenu {
-  height: 50px;
-  border-bottom: 1px solid rgba(34, 36, 38, 0.15);
-  box-shadow: 0 1px 2px 0 rgba(34, 36, 38, 0.15);
-
-  position: fixed;
-  top: 0;
-  left: 0;
-  right: 0;
-  background-color: #ffffff;
-  z-index: 9;
-}
-
-.main {
-  padding-left: 1%;
-  padding-right: 1%;
-}
-
-.search-icon {
-  display: none;
-}
-
 @media screen and (max-width: 768px) {
-  .main {
-    padding-left: 1%;
-    padding-right: 1%;
-  }
-
-  .search,
-  .user-info {
-    display: none;
-  }
-
-  .search-icon {
-    display: inline;
-    cursor: pointer;
-    font-size: 30px;
-    align-content: flex-end;
-  }
-}
-
-.right {
-  word-break: keep-all; /* 不换行 */
-  white-space: nowrap; /* 不换行 */
-  display: flex;
-  align-items: center;
-  justify-content: space-between;
-}
-
-.tit {
-  display: block;
-  font-weight: 700;
-  height: 45px;
-  text-decoration: none;
-  color: #333;
-}
-
-.tit span {
-  margin-left: 5px;
 }
 
 .logo {
   width: 30px;
   position: relative;
-  top: 5px;
-}
-
-.search {
-  text-align: center;
-  padding-top: 6px;
-}
-
-.user-info {
-  padding-top: 6px;
-  word-break: keep-all; /* 不换行 */
-  white-space: nowrap; /* 不换行 */
-}
-
-.drop {
-  cursor: pointer;
-  position: relative;
-  font-size: 16px;
-  bottom: 10px;
-  left: 5px;
 }
 
 .size {
   font-size: 16px;
 }
-.avatar-name {
-  text-align: center;
-}
 
-.avatar {
-  width: 70px;
-  height: 70px;
-  border-radius: 50%;
+.item {
+  margin-top: 10px;
+  margin-right: 10px;
 }
 </style>

+ 0 - 107
src/components/layout/SearchBox.vue

@@ -1,107 +0,0 @@
-<template>
-  <!--搜索框-->
-  <el-autocomplete
-    v-model="keyword"
-    :fetch-suggestions="querySearchAsync"
-    :placeholder="placeholder"
-    clearable
-    suffix-icon="el-icon-search"
-    size="medium"
-    :debounce="1000"
-    :style="sw"
-    @keyup.enter.native="onSearch"
-    @select="onSearch"
-  />
-</template>
-
-<script>
-import { keywordSuggest } from '@/api/search'
-
-export default {
-  name: 'SearchBox',
-  props: {
-    sw: {
-      type: String,
-      default: 'width:60%'
-    }
-  },
-  data() {
-    return {
-      restaurants: [],
-      placeholder: '想要搜点神马呢',
-      keyword: '',
-      timer: null
-    }
-  },
-  created() {
-  },
-  methods: {
-    // 重点:当框中的改变时触发该方法,elementui自动设置了防抖,参见debounce属性
-    // queryString 为输入框中的值。cb为返回显示列表的回调函数
-    querySearchAsync(queryString, cb) {
-      if (queryString === '') {
-        return
-      }
-
-      setTimeout(() => {
-        keywordSuggest(queryString).then(res => {
-          if (res.code === 0) {
-            this.restaurants = res.data.map((item) => {
-              return {
-                value: item.keyword,
-                rank: 1
-              }
-            })
-
-            // 如果 cb 返回一个空数组, 那么模糊搜索输入建议的下拉选项会因为 length 为 0 而消失
-            // cb([])
-            cb(this.restaurants)
-            // eslint-disable-next-line no-empty
-          } else {
-          }
-        })
-      }, 500)
-    },
-    // select 事件或 enter 键事件
-    onSearch() {
-      console.log('回车事件')
-      // 正则去空格
-      if (this.keyword.replace(/\s*/g, '')) {
-        this.toSearchPage()
-      } else {
-        this.$message({
-          showClose: true,
-          message: '不能为空!',
-          type: 'warning'
-        })
-      }
-    },
-    // 跳转搜索页面,传递搜索框的参数
-    toSearchPage() {
-      const currentPath = this.$route.path
-      if (currentPath === '/search') {
-        this.$router.push({
-          path: '/search',
-          query: {
-            keyword: this.keyword,
-            pageNumber: 1
-          }
-        })
-        this.$router.go(0)
-      } else {
-        const routeUrl = this.$router.resolve({
-          path: '/search',
-          query: {
-            keyword: this.keyword,
-            pageNumber: 1
-          }
-        })
-        window.open(routeUrl.href, '_blank')
-      }
-    }
-  }
-}
-</script>
-
-<style scoped>
-</style>