reghao před 3 měsíci
rodič
revize
52086a91f6

+ 23 - 8
src/api/blog.js

@@ -1,19 +1,34 @@
 import { delete0, get, post } from '@/utils/request'
 
 const blogApi = {
-  getBlogPostApi: '/api/blog/post',
-  newsListApi: '/api/content/post/news/list',
-  newsDetailApi: '/api/content/post/news/detail'
+  getBlogPost: '/api/blog/post',
+  getBlogCategory: '/api/blog/category',
+  getBlogTag: '/api/blog/tag',
+  getBlogArchive: '/api/blog/archive',
+  getBlogAbout: '/api/blog/about',
+  getSearchList: '/api/blog/search'
+}
+
+export function getBlogPostList(pn) {
+  return get(blogApi.getBlogPost + '/list?pn=' + pn)
 }
 
 export function getBlogPost(postId) {
-  return get(blogApi.getBlogPostApi + '?articleId=' + postId)
+  return get(blogApi.getBlogPost + '/detail?articleId=' + postId)
+}
+
+export function getBlogTag(queryInfo) {
+  return get(blogApi.getBlogTag, queryInfo)
+}
+
+export function getTagPost(queryInfo) {
+  return get(blogApi.getBlogTag + '/post', queryInfo)
 }
 
-export function getNewsList(page) {
-  return get(blogApi.newsListApi + '?pn=' + page)
+export function getBlogArchive() {
+  return get(blogApi.getBlogArchive)
 }
 
-export function getNewsDetail(newsId) {
-  return get(blogApi.newsDetailApi + '/' + newsId)
+export function getBlogAbout() {
+  return get(blogApi.getBlogAbout)
 }

+ 6 - 6
src/components/layout/NavBar.vue

@@ -3,7 +3,7 @@
     <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">
+          <a href="/vod" style="color: #007bff;text-decoration-line: none">
             <img src="@/assets/img/icon/logo.png" class="logo" alt="img">
             tnb
           </a>
@@ -15,22 +15,22 @@
         mode="horizontal"
       >
         <el-menu-item index="1">
-          <a href="/video" style="text-decoration-line: none">
+          <a href="/vod/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">
+          <a href="/vod/shortvideo" style="text-decoration-line: none">
             <span style="color: #007bff">短视频</span>
           </a>
         </el-menu-item>
         <el-menu-item index="3">
-          <a href="/playlist" style="text-decoration-line: none">
+          <a href="/vod/playlist" style="text-decoration-line: none">
             <span style="color: #007bff">播放列表</span>
           </a>
         </el-menu-item>
         <el-menu-item index="9">
-          <a href="/discover" style="text-decoration-line: none">
+          <a href="/vod/discover" style="text-decoration-line: none">
             <span style="color: #007bff">发现</span>
           </a>
         </el-menu-item>
@@ -308,7 +308,7 @@ export default {
       this.$router.push(path)
     },
     goToTimeline() {
-      const path = '/timeline'
+      const path = '/vod/timeline'
       if (this.$route.path === path) {
         this.$router.go(0)
         return

+ 1 - 1
src/components/layout/NavBarNoSearch.vue

@@ -147,7 +147,7 @@ export default {
       this.$router.push(path)
     },
     goToTimeline() {
-      const path = '/timeline'
+      const path = '/vod/timeline'
       if (this.$route.path === path) {
         this.$router.go(0)
         return

+ 50 - 3
src/router/blog.js

@@ -1,18 +1,23 @@
 const Blog = () => import('views/blog/Blog')
 const ArticleIndex = () => import('views/blog/Article')
 const ArticlePage = () => import('views/blog/ArticlePage')
+const TagIndex = () => import('views/blog/TagIndex')
+const TagPage = () => import('views/blog/TagPage')
+const ArchivePage = () => import('views/blog/ArchivePage')
+const AboutPage = () => import('views/blog/AboutPage')
+const SearchPage = () => import('views/blog/SearchPage')
 
 export default {
   path: '/blog',
   name: 'Blog',
   component: Blog,
-  meta: { needAuth: true },
+  meta: { needAuth: false },
   children: [
     {
       path: '',
       name: 'Blog',
       component: ArticleIndex,
-      meta: { needAuth: true }
+      meta: { needAuth: false }
     },
     {
       path: '/blog',
@@ -21,10 +26,52 @@ export default {
       meta: { needAuth: false }
     },
     {
-      path: '/blog/:articleId',
+      path: '/blog/post/:articleId',
       name: 'ArticlePage',
       component: ArticlePage,
       meta: { needAuth: false }
+    },
+    {
+      path: '/blog/category',
+      name: 'TagIndex',
+      component: TagIndex,
+      meta: { needAuth: false }
+    },
+    {
+      path: '/blog/category/:tag',
+      name: 'TagPage',
+      component: TagPage,
+      meta: { needAuth: false }
+    },
+    {
+      path: '/blog/tag',
+      name: 'TagIndex',
+      component: TagIndex,
+      meta: { needAuth: false }
+    },
+    {
+      path: '/blog/tag/:tag',
+      name: 'TagPage',
+      component: TagPage,
+      meta: { needAuth: false }
+    },
+    {
+      path: '/blog/archive',
+      name: 'ArchivePage',
+      component: ArchivePage,
+      meta: { needAuth: false }
+    },
+    {
+      path: '/blog/about',
+      name: 'AboutPage',
+      component: AboutPage,
+      meta: { needAuth: false }
+    },
+    {
+      path: '/blog/search',
+      name: 'SearchPage',
+      component: SearchPage,
+      meta: { needAuth: false }
     }
   ]
 }

+ 0 - 17
src/router/chat.js

@@ -1,17 +0,0 @@
-const Chat = () => import('views/chat/Chat')
-const ChatIndex = () => import('views/chat/ChatIndex')
-
-export default {
-  path: '/chat',
-  name: 'Chat',
-  component: Chat,
-  meta: { needAuth: true },
-  children: [
-    {
-      path: '',
-      name: 'ChatIndex',
-      component: ChatIndex,
-      meta: { needAuth: true }
-    }
-  ]
-}

+ 3 - 81
src/router/index.js

@@ -6,6 +6,7 @@ import UserRouter from './user'
 import SearchRouter from './search'
 import DevopsRouter from './devops'
 import BlogRouter from './blog'
+import VodRouter from './vod'
 import BackgroundAccountRouter from './background_account'
 import BackgroundMyRouter from './background_my'
 import BackgroundPostRouter from './background_post'
@@ -44,6 +45,7 @@ export const constantRoutes = [
   SearchRouter,
   DevopsRouter,
   BlogRouter,
+  VodRouter,
   BackgroundAccountRouter,
   BackgroundMyRouter,
   BackgroundPostRouter,
@@ -55,87 +57,7 @@ export const constantRoutes = [
     path: '/',
     name: 'Index',
     component: Index,
-    meta: { needAuth: true },
-    children: [
-      {
-        path: '',
-        name: 'Home',
-        component: Home,
-        meta: { needAuth: false }
-      },
-      {
-        path: '/timeline',
-        name: 'TimelineIndex',
-        component: TimelineIndex,
-        meta: { needAuth: true }
-      },
-      {
-        path: '/shortvideo',
-        name: 'ShortVideoIndex',
-        component: ShortVideoIndex,
-        meta: { needAuth: false }
-      },
-      {
-        path: '/video',
-        name: 'VideoIndex',
-        component: VideoIndex,
-        meta: { needAuth: false }
-      },
-      {
-        path: '/video/:id',
-        name: 'VideoPage',
-        component: VideoPage,
-        meta: { needAuth: false }
-      },
-      {
-        path: '/video/tag/:tag',
-        name: 'VideoTag',
-        component: VideoTag,
-        meta: { needAuth: false }
-      },
-      {
-        path: '/audio',
-        name: 'AudioIndex',
-        component: AudioIndex,
-        meta: { needAuth: false }
-      },
-      {
-        path: '/audio/:audioId',
-        name: 'AudioPage',
-        component: AudioPage,
-        meta: { needAuth: false }
-      },
-      {
-        path: '/image/:albumId',
-        name: 'ImagePage',
-        component: ImagePage,
-        meta: { needAuth: false }
-      },
-      {
-        path: '/playlist',
-        name: 'PlaylistIndex',
-        component: PlaylistIndex,
-        meta: { needAuth: false }
-      },
-      {
-        path: '/playlist/:albumId',
-        name: 'PlaylistView',
-        component: PlaylistView,
-        meta: { needAuth: false }
-      },
-      {
-        path: '/s/:shareId',
-        name: 'ShareVideo',
-        component: ShareVideo,
-        meta: { needAuth: false }
-      },
-      {
-        path: '/discover',
-        name: 'Discover',
-        component: Discover,
-        meta: { needAuth: false }
-      }
-    ]
+    meta: { needAuth: false }
   },
   {
     path: '/background',

+ 107 - 0
src/router/vod.js

@@ -0,0 +1,107 @@
+const Chat = () => import('views/chat/Chat')
+const ChatIndex = () => import('views/chat/ChatIndex')
+const Login = () => import('views/Login')
+const Register = () => import('views/Register')
+const Forgot = () => import('views/Forgot')
+const Index = () => import('views/vod/Index')
+const ShareVideo = () => import('views/home/ShareVideo')
+
+const Home = () => import('views/home/Home')
+const TimelineIndex = () => import('views/home/Timeline')
+const VideoIndex = () => import('views/home/Video')
+const VideoTag = () => import('views/home/VideoTag')
+const ShortVideoIndex = () => import('views/home/ShortVideo')
+const VideoPage = () => import('views/home/VideoPage')
+const AudioIndex = () => import('views/home/Audio')
+const AudioPage = () => import('views/home/AudioPage')
+const ImagePage = () => import('views/home/ImagePage')
+const PlaylistIndex = () => import('views/home/PlaylistIndex')
+const PlaylistView = () => import('views/home/PlaylistView')
+const Discover = () => import('views/home/Discover')
+
+export default {
+  path: '/vod',
+  name: 'Vod',
+  component: Index,
+  meta: { needAuth: true },
+  children: [
+    {
+      path: '',
+      name: 'Home',
+      component: Home,
+      meta: { needAuth: false }
+    },
+    {
+      path: '/vod/timeline',
+      name: 'TimelineIndex',
+      component: TimelineIndex,
+      meta: { needAuth: true }
+    },
+    {
+      path: '/vod/shortvideo',
+      name: 'ShortVideoIndex',
+      component: ShortVideoIndex,
+      meta: { needAuth: false }
+    },
+    {
+      path: '/vod/video',
+      name: 'VideoIndex',
+      component: VideoIndex,
+      meta: { needAuth: false }
+    },
+    {
+      path: '/vod/video/:id',
+      name: 'VideoPage',
+      component: VideoPage,
+      meta: { needAuth: false }
+    },
+    {
+      path: '/vod/video/tag/:tag',
+      name: 'VideoTag',
+      component: VideoTag,
+      meta: { needAuth: false }
+    },
+    {
+      path: '/vod/audio',
+      name: 'AudioIndex',
+      component: AudioIndex,
+      meta: { needAuth: false }
+    },
+    {
+      path: '/vod/audio/:audioId',
+      name: 'AudioPage',
+      component: AudioPage,
+      meta: { needAuth: false }
+    },
+    {
+      path: '/vod/image/:albumId',
+      name: 'ImagePage',
+      component: ImagePage,
+      meta: { needAuth: false }
+    },
+    {
+      path: '/vod/playlist',
+      name: 'PlaylistIndex',
+      component: PlaylistIndex,
+      meta: { needAuth: false }
+    },
+    {
+      path: '/vod/playlist/:albumId',
+      name: 'PlaylistView',
+      component: PlaylistView,
+      meta: { needAuth: false }
+    },
+    {
+      path: '/vod/s/:shareId',
+      name: 'ShareVideo',
+      component: ShareVideo,
+      meta: { needAuth: false }
+    },
+    {
+      path: '/vod/discover',
+      name: 'Discover',
+      component: Discover,
+      meta: { needAuth: false }
+    }
+  ]
+}

+ 67 - 28
src/views/Index.vue

@@ -1,57 +1,96 @@
 <template>
   <el-container>
     <el-main>
-      <nav-bar />
-      <router-view />
+      <el-col
+        v-for="(more, index) in moreList"
+        :key="index"
+        :md="6"
+        :sm="12"
+        :xs="12"
+        style="padding: 5px;"
+      >
+        <el-card class="box-card">
+          <div slot="header" class="clearfix">
+            <el-row>
+              <el-col :md="4">
+                <router-link target="_blank" :to="more.link">
+                  <el-avatar>
+                    <el-image :src="more.coverUrl" />
+                  </el-avatar>
+                </router-link>
+              </el-col>
+              <el-col :md="16">
+                <el-row style="padding: 5px;">
+                  <span v-html="more.title" />
+                </el-row>
+                <el-row style="padding: 5px;">
+                  <span v-html="more.desc" />
+                </el-row>
+              </el-col>
+            </el-row>
+          </div>
+        </el-card>
+      </el-col>
     </el-main>
   </el-container>
 </template>
 
 <script>
-import NavBar from 'components/layout/NavBar'
-
 export default {
   name: 'Index',
-  components: {
-    NavBar
-  },
   data() {
     return {
-      isCollapse: false,
-      navList: [
-        { path: '/my', name: '我的帐号', icon: 'el-icon-upload' }
-      ]
+      moreList: []
     }
   },
-  /*  watch: {
+  watch: {
     // 地址栏 url 发生变化时重新加载本页面
     $route() {
       this.$router.go()
     }
-  },*/
+  },
   created() {
     document.title = 'tnb'
+    this.getData()
   },
   methods: {
-    handleOpen(key, keyPath) {
-      console.log(key, keyPath)
-    },
-    handleClose(key, keyPath) {
-      console.log(key, keyPath)
+    getData() {
+      this.moreList.push(
+        {
+          title: 'vod',
+          desc: '地图',
+          link: '/vod',
+          coverUrl: ''
+        },
+        {
+          title: 'blog',
+          desc: '地图',
+          link: '/blog',
+          coverUrl: ''
+        },
+        {
+          title: 'disk',
+          desc: '考试',
+          link: '/disk',
+          coverUrl: ''
+        },
+        {
+          title: 'devops',
+          desc: '商城',
+          link: '/devops',
+          coverUrl: ''
+        },
+        {
+          title: 'bg',
+          desc: '图表',
+          link: '/background',
+          coverUrl: ''
+        }
+      )
     }
   }
 }
 </script>
 
 <style>
-.el-menu-vertical-demo:not(.el-menu--collapse) {
-  width: 200px;
-  min-height: 800px;
-}
-
-#aside-style {
-  min-width: 120px;
-  max-width: 240px;
-  width: 30%;
-}
 </style>

+ 49 - 0
src/views/blog/AboutPage.vue

@@ -0,0 +1,49 @@
+<template>
+  <div>
+    <el-row class="movie-list">
+    </el-row>
+  </div>
+</template>
+
+<script>
+import { getBlogAbout } from '@/api/blog'
+
+export default {
+  name: 'AboutPage',
+  data() {
+    return {
+      blogAbout: null
+    }
+  },
+  created() {
+    document.title = '关于'
+    this.getData()
+  },
+  methods: {
+    getData() {
+      getBlogAbout().then(resp => {
+        if (resp.code === 0) {
+          this.blogAbout = resp.data
+        } else {
+          this.$message.error(resp.msg)
+        }
+      }).catch(error => {
+        this.$message.error(error.message)
+      })
+    }
+  }
+}
+</script>
+
+<style scoped>
+/*处于手机屏幕时*/
+@media screen and (max-width: 768px) {
+  .movie-list {
+    padding: 5px;
+  }
+}
+
+.movie-list {
+  padding: 5px;
+}
+</style>

+ 49 - 0
src/views/blog/ArchivePage.vue

@@ -0,0 +1,49 @@
+<template>
+  <div>
+    <el-row class="movie-list">
+    </el-row>
+  </div>
+</template>
+
+<script>
+import { getBlogArchive } from '@/api/blog'
+
+export default {
+  name: 'ArchivePage',
+  data() {
+    return {
+      blogArchive: null
+    }
+  },
+  created() {
+    document.title = '文章归档'
+    this.getData()
+  },
+  methods: {
+    getData() {
+      getBlogArchive().then(resp => {
+        if (resp.code === 0) {
+          this.blogArchive = resp.data
+        } else {
+          this.$message.error(resp.msg)
+        }
+      }).catch(error => {
+        this.$message.error(error.message)
+      })
+    }
+  }
+}
+</script>
+
+<style scoped>
+/*处于手机屏幕时*/
+@media screen and (max-width: 768px) {
+  .movie-list {
+    padding: 5px;
+  }
+}
+
+.movie-list {
+  padding: 5px;
+}
+</style>

+ 38 - 33
src/views/blog/Article.vue

@@ -10,7 +10,7 @@
             <div class="text item">
               <el-row>
                 <el-col :md="4">
-                  <router-link target="_blank" :to="`/news/${item.contentId}`">
+                  <router-link target="_blank" :to="`/blog/post/${item.articleId}`">
                     <el-image
                       lazy
                       fit="cover"
@@ -20,7 +20,7 @@
                   </router-link>
                 </el-col>
                 <el-col :md="20">
-                  <router-link style="text-decoration-line: none" target="_blank" :to="`/news/${item.contentId}`">
+                  <router-link style="text-decoration-line: none" target="_blank" :to="`/blog/post/${item.articleId}`">
                     <el-row>
                       <div style="padding: 14px">
                         <span style="left: 0;margin-bottom: 0px;color: black;">{{ item.title | ellipsis }}</span>
@@ -37,13 +37,17 @@
             </div>
           </el-card>
         </el-row>
-        <el-row>
-          <div v-if="hasMore" style="display: flex; justify-content: center;">
-            <el-button link type="plain" icon="el-icon-bottom" @click="loadMore">
-              加载更多
-            </el-button>
-          </div>
-        </el-row>
+        <el-pagination
+          background
+          :small="screenWidth <= 768"
+          layout="prev, pager, next"
+          :page-size="pageSize"
+          :current-page="currentPage"
+          :total="totalSize"
+          @current-change="handleCurrentChange"
+          @prev-click="handleCurrentChange"
+          @next-click="handleCurrentChange"
+        />
       </el-col>
       <el-col :md="6">
         <el-row class="movie-list">
@@ -64,7 +68,7 @@
 </template>
 
 <script>
-import { getNewsList } from '@/api/blog'
+import {getBlogPostList } from '@/api/blog'
 
 export default {
   name: 'ArticleIndex',
@@ -86,17 +90,25 @@ export default {
   components: {},
   data() {
     return {
+      queryInfo: {
+        pn: 1
+      },
       // 屏幕宽度, 为了控制分页条的大小
       screenWidth: document.body.clientWidth,
       currentPage: 1,
-      pageSize: 12,
+      pageSize: 10,
       totalSize: 0,
-      dataList: [],
-      hasMore: true
+      dataList: []
     }
   },
   created() {
-    document.title = 'News'
+    const pageNumber = this.$route.query.pn
+    if (pageNumber !== undefined && pageNumber !== null) {
+      this.currentPage = parseInt(pageNumber)
+      this.queryInfo.pn = parseInt(pageNumber)
+    }
+
+    document.title = 'MyBlog'
     this.getArticlesWrapper(this.currentPage)
   },
   mounted() {
@@ -110,28 +122,28 @@ export default {
   },
   methods: {
     handleCurrentChange(currentPage) {
+      this.queryInfo.pn = currentPage
+      this.$router.push({
+        path: '/blog',
+        query: this.queryInfo
+      })
       this.currentPage = currentPage
       this.getArticlesWrapper(this.currentPage)
       // 回到顶部
       scrollTo(0, 0)
     },
     getArticlesWrapper(page) {
-      getNewsList(page).then(resp => {
+      getBlogPostList(page).then(resp => {
         if (resp.code === 0) {
           const respData = resp.data
-          this.hasMore = respData.hasNext
-          for (const item of respData.list) {
-            this.dataList.push(item)
-          }
+          this.dataList = respData.list
+          this.totalSize = respData.totalSize
+        } else {
+          this.$message.error(resp.msg)
         }
+      }).catch(error => {
+        this.$message.error(error.message)
       })
-    },
-    loadMore() {
-      this.currentPage = this.currentPage + 1
-      this.getArticlesWrapper(this.currentPage)
-    },
-    refresh() {
-      this.$message.info('暂未实现')
     }
   }
 }
@@ -167,11 +179,4 @@ export default {
 .clearfix:after {
   clear: both;
 }
-
-.not-result {
-  padding-top: 100px;
-  padding-bottom: 100px;
-  text-align: center;
-}
-
 </style>

+ 10 - 0
src/views/blog/Blog.vue

@@ -24,6 +24,16 @@
                 <span style="color: #007bff">分类</span>
               </template>
             </el-menu-item>
+            <el-menu-item index="/blog/tag">
+              <template slot="title">
+                <span style="color: #007bff">标签</span>
+              </template>
+            </el-menu-item>
+            <el-menu-item index="/blog/archive">
+              <template slot="title">
+                <span style="color: #007bff">归档</span>
+              </template>
+            </el-menu-item>
             <el-menu-item index="/blog/about">
               <template slot="title">
                 <span style="color: #007bff">关于</span>

+ 119 - 0
src/views/blog/SearchPage.vue

@@ -0,0 +1,119 @@
+<template>
+  <div>
+    <el-row class="movie-list">
+    </el-row>
+  </div>
+</template>
+
+<script>
+import {getBlogPostList } from '@/api/blog'
+
+export default {
+  name: 'ArticleIndex',
+  metaInfo: {
+    meta: [
+      { name: 'referrer', content: 'no-referrer' }
+    ]
+  },
+  filters: {
+    ellipsis(value) {
+      if (!value) return ''
+      const max = 50
+      if (value.length > max) {
+        return value.slice(0, max) + '...'
+      }
+      return value
+    }
+  },
+  components: {},
+  data() {
+    return {
+      queryInfo: {
+        pn: 1
+      },
+      // 屏幕宽度, 为了控制分页条的大小
+      screenWidth: document.body.clientWidth,
+      currentPage: 1,
+      pageSize: 10,
+      totalSize: 0,
+      dataList: []
+    }
+  },
+  created() {
+    const pageNumber = this.$route.query.pn
+    if (pageNumber !== undefined && pageNumber !== null) {
+      this.currentPage = parseInt(pageNumber)
+      this.queryInfo.pn = parseInt(pageNumber)
+    }
+
+    document.title = '搜索结果'
+  },
+  mounted() {
+    // 当窗口宽度改变时获取屏幕宽度
+    window.onresize = () => {
+      return () => {
+        window.screenWidth = document.body.clientWidth
+        this.screenWidth = window.screenWidth
+      }
+    }
+  },
+  methods: {
+    handleCurrentChange(currentPage) {
+      this.queryInfo.pn = currentPage
+      this.$router.push({
+        path: '/blog',
+        query: this.queryInfo
+      })
+      this.currentPage = currentPage
+      this.getArticlesWrapper(this.currentPage)
+      // 回到顶部
+      scrollTo(0, 0)
+    },
+    getArticlesWrapper(page) {
+      getBlogPostList(page).then(resp => {
+        if (resp.code === 0) {
+          const respData = resp.data
+          this.dataList = respData.list
+          this.totalSize = respData.totalSize
+        } else {
+          this.$message.error(resp.msg)
+        }
+      }).catch(error => {
+        this.$message.error(error.message)
+      })
+    }
+  }
+}
+</script>
+
+<style scoped>
+/*处于手机屏幕时*/
+@media screen and (max-width: 768px) {
+  .movie-list {
+    padding: 5px;
+  }
+  .coverImg {
+    height: 120px !important;
+  }
+}
+
+.movie-list {
+  padding: 5px;
+}
+
+.coverImg {
+  width: 100%;
+  height: 120px;
+  display: block;
+}
+
+.clearfix:before,
+.clearfix:after {
+  display: table;
+  content: "";
+}
+
+.clearfix:after {
+  clear: both;
+}
+</style>

+ 87 - 0
src/views/blog/TagIndex.vue

@@ -0,0 +1,87 @@
+<template>
+  <div>
+    <el-row class="movie-list">
+      <el-tag
+        v-for="(tag,index) in dataList"
+        :key="index"
+        class="tag"
+        size="medium"
+        effect="plain"
+      >
+        <router-link v-if="blogTag" style="text-decoration-line: none" target="_blank" :to="`/blog/tag/` + tag.name">
+          {{ tag.name }}
+        </router-link>
+        <router-link v-else style="text-decoration-line: none" target="_blank" :to="`/blog/category/` + tag.name">
+          {{ tag.name }}
+        </router-link>
+      </el-tag>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import { getBlogTag } from '@/api/blog'
+
+export default {
+  name: 'TagIndex',
+  data() {
+    return {
+      queryInfo: {
+        type: 'tag'
+      },
+      dataList: [],
+      blogTag: false
+    }
+  },
+  created() {
+    const path = this.$route.path
+    if (path !== undefined && path !== null) {
+      if (path.endsWith('category')) {
+        document.title = '文章分类'
+        this.queryInfo.type = 'category'
+        this.getData()
+      } else if (path.endsWith('tag')) {
+        document.title = '文章标签'
+        this.queryInfo.type = 'tag'
+        this.blogTag = true
+        this.getData1()
+      }
+    } else {
+      document.title = 'BlogTag'
+    }
+  },
+  methods: {
+    getData() {
+      getBlogTag(this.queryInfo).then(resp => {
+        if (resp.code === 0) {
+          this.dataList = resp.data
+        } else {
+          this.$message.error(resp.msg)
+        }
+      }).catch(error => {
+        this.$message.error(error.message)
+      })
+    }
+  }
+}
+</script>
+
+<style scoped>
+/*处于手机屏幕时*/
+@media screen and (max-width: 768px) {
+  .movie-list {
+    padding: 5px;
+  }
+}
+
+.movie-list {
+  padding: 5px;
+}
+
+.tag{
+  padding-top: 1px;
+  padding-bottom: 1px;
+  margin-left: 3px;
+  margin-right: 3px;
+}
+</style>

+ 121 - 0
src/views/blog/TagPage.vue

@@ -0,0 +1,121 @@
+<template>
+  <div>
+    <el-row class="movie-list">
+    </el-row>
+  </div>
+</template>
+
+<script>
+import { getTagPost } from '@/api/blog'
+
+export default {
+  name: 'TagPage',
+  metaInfo: {
+    meta: [
+      { name: 'referrer', content: 'no-referrer' }
+    ]
+  },
+  filters: {
+    ellipsis(value) {
+      if (!value) return ''
+      const max = 50
+      if (value.length > max) {
+        return value.slice(0, max) + '...'
+      }
+      return value
+    }
+  },
+  components: {},
+  data() {
+    return {
+      queryInfo: {
+        pn: 1,
+        type: 'tag',
+        name: ''
+      },
+      // 屏幕宽度, 为了控制分页条的大小
+      screenWidth: document.body.clientWidth,
+      currentPage: 1,
+      pageSize: 10,
+      totalSize: 0,
+      dataList: []
+    }
+  },
+  created() {
+    const pageNumber = this.$route.query.pn
+    if (pageNumber !== undefined && pageNumber !== null) {
+      this.currentPage = parseInt(pageNumber)
+      this.queryInfo.pn = parseInt(pageNumber)
+    }
+
+    const path = this.$route.path
+    const arr = path.split('/')
+    console.log(arr)
+    if (arr.length !== 4) {
+      return
+    }
+
+    this.queryInfo.name = arr[3]
+    if (arr[2] === 'tag') {
+      this.queryInfo.type = 'tag'
+      document.title = '包含标签 ' + this.queryInfo.name + ' 的文章'
+      this.getData()
+    } else if (arr[2] === 'category') {
+      this.queryInfo.type = 'category'
+      document.title = '包含分类 ' + this.queryInfo.name + ' 的文章'
+      this.getData()
+    }
+  },
+  mounted() {
+    // 当窗口宽度改变时获取屏幕宽度
+    window.onresize = () => {
+      return () => {
+        window.screenWidth = document.body.clientWidth
+        this.screenWidth = window.screenWidth
+      }
+    }
+  },
+  methods: {
+    handleCurrentChange(currentPage) {
+      this.queryInfo.pn = currentPage
+      this.$router.push({
+        path: '/blog/tag',
+        query: this.queryInfo
+      })
+      this.currentPage = currentPage
+      this.getData(this.currentPage)
+      // 回到顶部
+      scrollTo(0, 0)
+    },
+    getData() {
+      getTagPost(this.queryInfo).then(resp => {
+        if (resp.code === 0) {
+          const respData = resp.data
+          this.dataList = respData.list
+          this.totalSize = respData.totalSize
+        } else {
+          this.$message.error(resp.msg)
+        }
+      }).catch(error => {
+        this.$message.error(error.message)
+      })
+    }
+  }
+}
+</script>
+
+<style scoped>
+/*处于手机屏幕时*/
+@media screen and (max-width: 768px) {
+  .movie-list {
+    padding: 5px;
+  }
+  .coverImg {
+    height: 120px !important;
+  }
+}
+
+.movie-list {
+  padding: 5px;
+}
+</style>

+ 57 - 0
src/views/vod/Index.vue

@@ -0,0 +1,57 @@
+<template>
+  <el-container>
+    <el-main>
+      <nav-bar />
+      <router-view />
+    </el-main>
+  </el-container>
+</template>
+
+<script>
+import NavBar from 'components/layout/NavBar'
+
+export default {
+  name: 'Index',
+  components: {
+    NavBar
+  },
+  data() {
+    return {
+      isCollapse: false,
+      navList: [
+        { path: '/my', name: '我的帐号', icon: 'el-icon-upload' }
+      ]
+    }
+  },
+  /*  watch: {
+    // 地址栏 url 发生变化时重新加载本页面
+    $route() {
+      this.$router.go()
+    }
+  },*/
+  created() {
+    document.title = 'tnb'
+  },
+  methods: {
+    handleOpen(key, keyPath) {
+      console.log(key, keyPath)
+    },
+    handleClose(key, keyPath) {
+      console.log(key, keyPath)
+    }
+  }
+}
+</script>
+
+<style>
+.el-menu-vertical-demo:not(.el-menu--collapse) {
+  width: 200px;
+  min-height: 800px;
+}
+
+#aside-style {
+  min-width: 120px;
+  max-width: 240px;
+  width: 30%;
+}
+</style>