ys 2 недель назад
Родитель
Сommit
f67e2af5a8

+ 4 - 1
yushu-uivue3/src/layout/components/TagsView/ScrollPane.vue

@@ -104,12 +104,15 @@ defineExpose({
   position: relative;
   overflow: hidden;
   width: 100%;
+  height: 100%;
   
   .scroll-wrapper {
-    height: 39px;
+    height: 34px;
     overflow-x: auto;
     overflow-y: hidden;
     white-space: nowrap;
+    display: flex;
+    align-items: center;
     
     &::-webkit-scrollbar {
       height: 0;

+ 74 - 81
yushu-uivue3/src/layout/components/TagsView/index.vue

@@ -1,42 +1,40 @@
 <template>
   <div id="tags-view-container" class="tags-view-container">
     <scroll-pane ref="scrollPaneRef" class="tags-view-wrapper" @scroll="handleScroll">
-      <router-link
+      <a-tag
         v-for="tag in visitedViews"
         :key="tag.path"
         :data-path="tag.path"
-        :class="{ 'active': isActive(tag), 'has-icon': tagsIcon }"
-        :to="{ path: tag.path, query: tag.query, fullPath: tag.fullPath }"
+        :color="isActive(tag) ? theme : ''"
+        :closable="!isAffix(tag)"
         class="tags-view-item"
-        :style="activeStyle(tag)"
-        @click.middle="!isAffix(tag) ? closeSelectedTag(tag) : ''"
+        :class="{ 'active': isActive(tag) }"
+        @click="handleTagClick(tag)"
+        @close="closeSelectedTag(tag)"
         @contextmenu.prevent="openMenu(tag, $event)"
       >
-        <svg-icon v-if="tagsIcon && tag.meta && tag.meta.icon && tag.meta.icon !== '#'" :icon-class="tag.meta.icon" />
+        <svg-icon v-if="tagsIcon && tag.meta && tag.meta.icon && tag.meta.icon !== '#'" :icon-class="tag.meta.icon" style="margin-right: 4px;" />
         {{ tag.title }}
-        <span v-if="!isAffix(tag)" @click.prevent.stop="closeSelectedTag(tag)">
-          <CloseOutlined style="width: 1em; height: 1em;vertical-align: middle;" />
-        </span>
-      </router-link>
+      </a-tag>
     </scroll-pane>
     <ul v-show="visible" :style="{ left: left + 'px', top: top + 'px' }" class="contextmenu">
       <li @click="refreshSelectedTag(selectedTag)">
-        <ReloadOutlined style="width: 1em; height: 1em;" /> 刷新页面
+        <ReloadOutlined /> 刷新页面
       </li>
       <li v-if="!isAffix(selectedTag)" @click="closeSelectedTag(selectedTag)">
-        <CloseOutlined style="width: 1em; height: 1em;" /> 关闭当前
+        <CloseOutlined /> 关闭当前
       </li>
       <li @click="closeOthersTags">
-        <CloseCircleOutlined style="width: 1em; height: 1em;" /> 关闭其他
+        <CloseCircleOutlined /> 关闭其他
       </li>
       <li v-if="!isFirstView()" @click="closeLeftTags">
-        <LeftOutlined style="width: 1em; height: 1em;" /> 关闭左侧
+        <VerticalRightOutlined /> 关闭左侧
       </li>
       <li v-if="!isLastView()" @click="closeRightTags">
-        <RightOutlined style="width: 1em; height: 1em;" /> 关闭右侧
+        <VerticalLeftOutlined /> 关闭右侧
       </li>
       <li @click="closeAllTags(selectedTag)">
-        <CloseCircleOutlined style="width: 1em; height: 1em;" /> 全部关闭
+        <CloseCircleOutlined /> 全部关闭
       </li>
     </ul>
   </div>
@@ -48,7 +46,7 @@ import { getNormalPath } from '@/utils/yushu'
 import useTagsViewStore from '@/store/modules/tagsView'
 import useSettingsStore from '@/store/modules/settings'
 import usePermissionStore from '@/store/modules/permission'
-import { CloseOutlined, ReloadOutlined, CloseCircleOutlined, LeftOutlined, RightOutlined } from '@ant-design/icons-vue'
+import { CloseOutlined, ReloadOutlined, CloseCircleOutlined, VerticalLeftOutlined, VerticalRightOutlined } from '@ant-design/icons-vue'
 
 const visible = ref(false)
 const top = ref(0)
@@ -88,14 +86,6 @@ function isActive(r) {
   return r.path === route.path
 }
 
-function activeStyle(tag) {
-  if (!isActive(tag)) return {}
-  return {
-    "background-color": theme.value,
-    "border-color": theme.value
-  }
-}
-
 function isAffix(tag) {
   return tag.meta && tag.meta.affix
 }
@@ -142,7 +132,6 @@ function initTags() {
   const res = filterAffixTags(routes.value)
   affixTags.value = res
   for (const tag of res) {
-    // Must have tag name
     if (tag.name) {
        useTagsViewStore().addVisitedView(tag)
     }
@@ -161,7 +150,6 @@ function moveToCurrentTag() {
     for (const r of visitedViews.value) {
       if (r.path === route.path) {
         scrollPaneRef.value.moveToTarget(r)
-        // when query is different then update
         if (r.fullPath !== route.fullPath) {
           useTagsViewStore().updateVisitedView(route)
         }
@@ -170,6 +158,10 @@ function moveToCurrentTag() {
   })
 }
 
+function handleTagClick(tag) {
+  router.push({ path: tag.path, query: tag.query, fullPath: tag.fullPath })
+}
+
 function refreshSelectedTag(view) {
   proxy.$tab.refreshPage(view)
   if (route.meta.link) {
@@ -222,10 +214,7 @@ function toLastView(visitedViews, view) {
   if (latestView) {
     router.push(latestView.fullPath)
   } else {
-    // now the default is to redirect to the home page if there is no tags-view,
-    // you can adjust it according to your needs.
     if (view.name === 'Dashboard') {
-      // to reload home page
       router.replace({ path: '/redirect' + view.fullPath })
     } else {
       router.push('/')
@@ -235,10 +224,10 @@ function toLastView(visitedViews, view) {
 
 function openMenu(tag, e) {
   const menuMinWidth = 105
-  const offsetLeft = proxy.$el.getBoundingClientRect().left // container margin left
-  const offsetWidth = proxy.$el.offsetWidth // container width
-  const maxLeft = offsetWidth - menuMinWidth // left boundary
-  const l = e.clientX - offsetLeft + 15 // 15: margin right
+  const offsetLeft = proxy.$el.getBoundingClientRect().left
+  const offsetWidth = proxy.$el.offsetWidth
+  const maxLeft = offsetWidth - menuMinWidth
+  const l = e.clientX - offsetLeft + 15
 
   if (l > maxLeft) {
     left.value = maxLeft
@@ -264,38 +253,26 @@ function handleScroll() {
 .tags-view-container {
   height: 34px;
   width: 100%;
-  background: var(--tags-bg, #fff);
-  border-bottom: 1px solid var(--tags-item-border, #d8dce5);
-  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .12), 0 0 3px 0 rgba(0, 0, 0, .04);
+  background: #fff;
+  border-bottom: 1px solid #d8dce5;
+  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.08);
 
   .tags-view-wrapper {
     .tags-view-item {
-      display: inline-block;
-      position: relative;
       cursor: pointer;
-      height: 26px;
-      line-height: 26px;
-      border: 1px solid var(--tags-item-border, #d8dce5);
-      color: var(--tags-item-text, #495060);
-      background: var(--tags-item-bg, #fff);
-      padding: 0 8px;
-      font-size: 12px;
-      margin-left: 5px;
-      margin-top: 4px;
-
+      margin-left: 4px;
+      
       &:first-of-type {
-        margin-left: 15px;
+        margin-left: 10px;
       }
 
       &:last-of-type {
-        margin-right: 15px;
+        margin-right: 10px;
       }
 
       &.active {
-        background-color: #42b983;
         color: #fff;
-        border-color: #42b983;
-
+        
         &::before {
           content: '';
           background: #fff;
@@ -303,20 +280,15 @@ function handleScroll() {
           width: 8px;
           height: 8px;
           border-radius: 50%;
-          position: relative;
-          margin-right: 5px;
+          margin-right: 4px;
         }
       }
     }
   }
 
-  .tags-view-item.active.has-icon::before {
-    content: none !important;
-  }
-
   .contextmenu {
     margin: 0;
-    background: var(--el-bg-color-overlay, #fff);
+    background: #fff;
     z-index: 3000;
     position: absolute;
     list-style-type: none;
@@ -324,17 +296,21 @@ function handleScroll() {
     border-radius: 4px;
     font-size: 12px;
     font-weight: 400;
-    color: var(--tags-item-text, #333);
-    box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, .3);
-    border: 1px solid var(--el-border-color-light, #e4e7ed);
+    color: #333;
+    box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, 0.3);
+    border: 1px solid #e4e7ed;
 
     li {
       margin: 0;
       padding: 7px 16px;
       cursor: pointer;
+      display: flex;
+      align-items: center;
+      gap: 6px;
 
       &:hover {
-        background: var(--tags-item-hover, #eee);
+        background: #f5f5f5;
+        color: #1890ff;
       }
     }
   }
@@ -342,24 +318,41 @@ function handleScroll() {
 </style>
 
 <style lang="scss">
-// TagsView close icon styles
 .tags-view-wrapper {
-  .tags-view-item {
-    span {
-      display: inline-flex;
-      align-items: center;
-      justify-content: center;
-      width: 16px;
-      height: 16px;
-      vertical-align: 2px;
-      border-radius: 50%;
-      text-align: center;
-      transition: all .3s cubic-bezier(.645, .045, .355, 1);
-      margin-left: 4px;
-      cursor: pointer;
-
+  .ant-tag {
+    font-size: 12px;
+    height: 22px;
+    line-height: 20px;
+    border-radius: 2px;
+    padding: 0 7px;
+    margin-right: 0;
+    
+    &:not(.active) {
+      background: #fff;
+      border-color: #d9d9d9;
+      color: #666;
+      
+      &:hover {
+        color: #1890ff;
+        border-color: #1890ff;
+      }
+    }
+    
+    .ant-tag-close-icon {
+      margin-left: 3px;
+      font-size: 10px;
+      
+      &:hover {
+        color: inherit;
+      }
+    }
+  }
+  
+  .ant-tag.active {
+    .ant-tag-close-icon {
+      color: rgba(255, 255, 255, 0.8);
+      
       &:hover {
-        background-color: var(--tags-close-hover, #b4bccc);
         color: #fff;
       }
     }