diff --git a/src/store/modules/tagsView.js b/src/store/modules/tagsView.js
index eed8b694..1fccaf69 100644
--- a/src/store/modules/tagsView.js
+++ b/src/store/modules/tagsView.js
@@ -29,6 +29,25 @@ const tagsView = {
           break
         }
       }
+    },
+    DEL_OTHER_VIEWS: (state, view) => {
+      for (const [i, v] of state.visitedViews.entries()) {
+        if (v.path === view.path) {
+          state.visitedViews = [].concat(state.visitedViews.slice(i, i + 1))
+          break
+        }
+      }
+      for (const i of state.cachedViews) {
+        if (i === view.name) {
+          const index = state.cachedViews.indexOf(i)
+          state.cachedViews = [].concat(state.cachedViews.slice(index, i + 1))
+          break
+        }
+      }
+    },
+    DEL_ALL_VIEWS: (state) => {
+      state.visitedViews = []
+      state.cachedViews = []
     }
   },
   actions: {
@@ -40,6 +59,18 @@ const tagsView = {
         commit('DEL_VISITED_VIEWS', view)
         resolve([...state.visitedViews])
       })
+    },
+    delOtherViews({ commit, state }, view) {
+      return new Promise((resolve) => {
+        commit('DEL_OTHER_VIEWS', view)
+        resolve([...state.visitedViews])
+      })
+    },
+    delAllViews({ commit, state }) {
+      return new Promise((resolve) => {
+        commit('DEL_ALL_VIEWS')
+        resolve([...state.visitedViews])
+      })
     }
   }
 }
diff --git a/src/views/layout/components/TagsView.vue b/src/views/layout/components/TagsView.vue
index 7e730280..c06d5979 100644
--- a/src/views/layout/components/TagsView.vue
+++ b/src/views/layout/components/TagsView.vue
@@ -1,139 +1,204 @@
 <template>
-  <scroll-pane class='tags-view-container' ref='scrollPane'>
-    <router-link ref='tag' class="tags-view-item" :class="isActive(tag)?'active':''" v-for="tag in Array.from(visitedViews)" :to="tag.path":key="tag.path">
-      {{generateTitle(tag.title)}}
-      <span class='el-icon-close' @click='closeViewTags(tag,$event)'></span>
-    </router-link>
-  </scroll-pane>
+  <div class="tag-container">
+    <scroll-pane class='tags-view-container' ref='scrollPane'>
+      <router-link ref='tag' class="tags-view-item" :class="isActive(tag)?'active':''" v-for="tag in Array.from(visitedViews)" :to="tag.path":key="tag.path" @contextmenu.prevent.native="openMenu(tag,$event)">
+        {{generateTitle(tag.title)}}
+        <span class='el-icon-close' @click='closeViewTags(tag,$event)'></span>
+      </router-link>
+    </scroll-pane>
+    <ul class='contextmenu' v-show="visible" :style="{left:left+'px',top:top+'px'}">
+      <li @click="closePage(0,$event)">关闭</li>
+      <li @click="closePage(1,$event)">关闭其他</li>
+      <li @click="closePage(2,$event)">关闭所有</li>
+    </ul>
+  </div>
 </template>
 
 <script>
-import ScrollPane from '@/components/ScrollPane'
-import { generateTitle } from '@/utils/i18n'
+  import ScrollPane from '@/components/ScrollPane'
+  import { generateTitle } from '@/utils/i18n'
 
-export default {
-  components: { ScrollPane },
-  computed: {
-    visitedViews() {
-      return this.$store.state.tagsView.visitedViews
-    }
-  },
-  mounted() {
-    this.addViewTags()
-  },
-  methods: {
-    generateTitle,
-    closeViewTags(view, $event) {
-      this.$store.dispatch('delVisitedViews', view).then((views) => {
-        if (this.isActive(view)) {
-          const latestView = views.slice(-1)[0]
-          if (latestView) {
-            this.$router.push(latestView.path)
-          } else {
-            this.$router.push('/')
-          }
-        }
-      })
-      $event.preventDefault()
-    },
-    generateRoute() {
-      if (this.$route.name) {
-        return this.$route
+  export default {
+    components: { ScrollPane },
+    data() {
+      return {
+        visible: false,
+        isOverflow: false,
+        top: 0,
+        left: 0,
+        isSelect: {}
       }
-      return false
     },
-    addViewTags() {
-      const route = this.generateRoute()
-      if (!route) {
-        return false
+    computed: {
+      visitedViews() {
+        return this.$store.state.tagsView.visitedViews
       }
-      this.$store.dispatch('addVisitedViews', route)
     },
-    isActive(route) {
-      return route.path === this.$route.path || route.name === this.$route.name
-    },
-    moveToCurrentTag() {
-      const tags = this.$refs.tag
-      this.$nextTick(() => {
-        for (const tag of tags) {
-          if (tag.to === this.$route.path) {
-            this.$refs.scrollPane.moveToTarget(tag.$el)
-            break
-          }
-        }
-      })
-    }
-  },
-  watch: {
-    $route() {
+    mounted() {
       this.addViewTags()
-      this.moveToCurrentTag()
+    },
+    methods: {
+      generateTitle,
+      closeViewTags(view, $event) {
+        this.$store.dispatch('delVisitedViews', view).then((views) => {
+          if (this.isActive(view)) {
+            const latestView = views.slice(-1)[0]
+            if (latestView) {
+              this.$router.push(latestView.path)
+            } else {
+              this.$router.push('/')
+            }
+          }
+        })
+        $event.preventDefault()
+      },
+      closePage(flag, $event) {
+        if (flag === 0) {
+          this.closeViewTags(this.isSelect, $event)
+        } else if (flag === 1) {
+          this.$router.push(this.isSelect.path)
+          this.$store.dispatch('delOtherViews', this.isSelect)
+          $event.preventDefault()
+        } else {
+          this.$store.dispatch('delAllViews')
+          this.$router.push('/')
+          $event.preventDefault()
+        }
+      },
+      generateRoute() {
+        if (this.$route.name) {
+          return this.$route
+        }
+        return false
+      },
+      addViewTags() {
+        const route = this.generateRoute()
+        if (!route) {
+          return false
+        }
+        this.$store.dispatch('addVisitedViews', route)
+      },
+      isActive(route) {
+        return route.path === this.$route.path || route.name === this.$route.name
+      },
+      moveToCurrentTag() {
+        const tags = this.$refs.tag
+        this.$nextTick(() => {
+          for (const tag of tags) {
+            if (tag.to === this.$route.path) {
+              this.$refs.scrollPane.moveToTarget(tag.$el)
+              break
+            }
+          }
+        })
+      },
+      openMenu(tag, e) {
+        this.visible = true
+        this.isSelect = tag
+        this.left = e.clientX
+        this.top = e.clientY
+      }
+    },
+    watch: {
+      $route() {
+        this.addViewTags()
+        this.moveToCurrentTag()
+      },
+      visible(v) {
+        if (v) {
+          window.addEventListener('click', () => {
+            this.visible = false
+          }, false)
+        } else {
+          window.removeEventListener('click')
+        }
+      }
     }
   }
-}
 </script>
 
 <style rel="stylesheet/scss" lang="scss" scoped>
-.tags-view-container {
-  background: #fff;
-  height: 34px;
-  border-bottom: 1px solid #d8dce5;
-  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .12), 0 0 3px 0 rgba(0, 0, 0, .04);
-  .tags-view-item {
-    display: inline-block;
-    position: relative;
-    height: 26px;
-    line-height: 26px;
-    border: 1px solid #d8dce5;
-    color: #495060;
-    background: #fff;
-    padding: 0 8px;
-    font-size: 12px;
-    margin-left: 5px;
-    margin-top: 4px;
-    &:first-of-type {
-      margin-left: 15px;
+  .tag-container {
+    .contextmenu {
+      margin: 0;
+      background: #fff;
+      z-index: 99999;
+      position: absolute;
+      list-style-type: none;
+      padding-left: 0;
+      border: 1px solid rgba(0, 0, 0, 0.4);
+      font-size: 0.8rem;
+      box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, .5);
+      li {
+        margin: 0;
+        padding: 0.2rem 1.5rem 0.3rem 0.8rem;
+        &:hover {
+          background: #eee;
+          cursor: default;
+        }
+      }
     }
-    &.active {
-      background-color: #42b983;
-      color: #fff;
-      border-color: #42b983;
-      &::before {
-        content: '';
-        background: #fff;
+    .tags-view-container {
+      background: #fff;
+      height: 34px;
+      border-bottom: 1px solid #d8dce5;
+      box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .12), 0 0 3px 0 rgba(0, 0, 0, .04);
+      .tags-view-item {
         display: inline-block;
-        width: 8px;
-        height: 8px;
-        border-radius: 50%;
         position: relative;
-        margin-right: 2px;
+        height: 26px;
+        line-height: 26px;
+        border: 1px solid #d8dce5;
+        color: #495060;
+        background: #fff;
+        padding: 0 8px;
+        font-size: 12px;
+        margin-left: 5px;
+        margin-top: 4px;
+        &:first-of-type {
+          margin-left: 15px;
+        }
+        &.active {
+          background-color: #42b983;
+          color: #fff;
+          border-color: #42b983;
+          &::before {
+            content: '';
+            background: #fff;
+            display: inline-block;
+            width: 8px;
+            height: 8px;
+            border-radius: 50%;
+            position: relative;
+            margin-right: 2px;
+          }
+        }
       }
     }
   }
-}
 </style>
 
 <style rel="stylesheet/scss" lang="scss">
-.tags-view-container {
-  .tags-view-item {
-    .el-icon-close {
-      width: 16px;
-      height: 16px;
-      vertical-align: 2px;
-      border-radius: 50%;
-      text-align: center;
-      transition: all .3s cubic-bezier(.645, .045, .355, 1);
-      transform-origin: 100% 50%;
-      &:before {
-        transform: scale(.6);
-        display: inline-block;
-        vertical-align: -3px;
-      }
-      &:hover {
-        background-color: #b4bccc;
-        color: #fff;
+  .tags-view-container {
+    .tags-view-item {
+      .el-icon-close {
+        width: 16px;
+        height: 16px;
+        vertical-align: 2px;
+        border-radius: 50%;
+        text-align: center;
+        transition: all .3s cubic-bezier(.645, .045, .355, 1);
+        transform-origin: 100% 50%;
+        &:before {
+          transform: scale(.6);
+          display: inline-block;
+          vertical-align: -3px;
+        }
+        &:hover {
+          background-color: #b4bccc;
+          color: #fff;
+        }
       }
     }
   }
-}
 </style>