169 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			169 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <template>
 | |
|   <section class="AiNavTab">
 | |
|     <el-tabs class="layout fill" type="card" :value="currentTab" @tab-click="handleTabClick" @tab-remove="handleTabRemove">
 | |
|       <el-tab-pane v-for="(op,i) in tabs" :key="i" :name="op.id" :label="op.label" lazy :closable="!op.fixed"/>
 | |
|     </el-tabs>
 | |
|     <el-dropdown flex class="more" @visible-change="handleIcon" trigger="click" @command="handleOpt">
 | |
|       <ai-icon :icon="dropdownIcon"/>
 | |
|       <el-dropdown-menu>
 | |
|         <el-dropdown-item command="clearAllPages">关闭所有</el-dropdown-item>
 | |
|         <el-dropdown-item command="clearOtherPages">只留当前页</el-dropdown-item>
 | |
|       </el-dropdown-menu>
 | |
|     </el-dropdown>
 | |
|   </section>
 | |
| </template>
 | |
| 
 | |
| <script>
 | |
| import {mapMutations, mapState} from "vuex";
 | |
| 
 | |
| export default {
 | |
|   name: "AiNavTab",
 | |
|   props: {
 | |
|     routes: {default: () => []},
 | |
|     fixed: {default: () => ({label: "首页", id: "/"})}
 | |
|   },
 | |
|   computed: {
 | |
|     ...mapState(['logs']),
 | |
|     currentTab: v => v.isHome ? v.fixed.id : v.$route.fullPath,
 | |
|     tabs: v => [{...v.fixed, fixed: 1}, v.logs.pages].flat(),
 | |
|     isHome: v => v.fixed.id == v.$route.fullPath
 | |
|   },
 | |
|   data() {
 | |
|     return {
 | |
|       dropdownIcon: "iconDouble_Down"
 | |
|     }
 | |
|   },
 | |
|   watch: {
 | |
|     $route: {
 | |
|       immediate: true,
 | |
|       handler(v) {
 | |
|         const currentPage = this.routes.find(e => e.name == v.name);
 | |
|         currentPage && this.addPage(currentPage)
 | |
|       }
 | |
|     }
 | |
|   },
 | |
|   methods: {
 | |
|     ...mapMutations(['addPage', 'deletePage']),
 | |
|     handleTabClick(pageTab) {
 | |
|       const {name} = pageTab
 | |
|       name != this.$route.fullPath && this.$router.push(name)
 | |
|     },
 | |
|     handleTabRemove(id) {
 | |
|       const {pages} = this.logs
 | |
|       if (id == this.currentTab) {
 | |
|         const index = pages.findIndex(e => e.id == id)
 | |
|         const next = pages?.[index + 1] || pages?.[index - 1] || {id: this.fixed.id || "/"}
 | |
|         this.handleTabClick({name: next.id})
 | |
|       }
 | |
|       this.deletePage(id)
 | |
|     },
 | |
|     handleIcon(v) {
 | |
|       this.dropdownIcon = v ? "iconDouble_Up" : "iconDouble_Down"
 | |
|     },
 | |
|     handleOpt(v) {
 | |
|       this.$store.commit(v)
 | |
|       v == "clearAllPages" && this.handleTabClick({name: this.fixed.id || "/"})
 | |
|     }
 | |
|   }
 | |
| }
 | |
| </script>
 | |
| 
 | |
| <style lang="scss" scoped>
 | |
| .AiNavTab {
 | |
|   display: flex;
 | |
|   background: linear-gradient(180deg, #FCFCFC 0%, #E0E2E4 100%);
 | |
| 
 | |
|   :deep(.layout ) {
 | |
|     display: flex;
 | |
|     flex-direction: column;
 | |
| 
 | |
|     .el-tabs__nav-prev, .el-tabs__nav-next {
 | |
|       top: 50%;
 | |
|       line-height: normal;
 | |
|       transform: translateY(-50%);
 | |
| 
 | |
|       & > i {
 | |
|         font-weight: bold !important;
 | |
|       }
 | |
| 
 | |
|     }
 | |
| 
 | |
|     & > .el-tabs__header {
 | |
|       margin-bottom: 0;
 | |
|       height: 40px;
 | |
|       display: flex;
 | |
|       align-items: flex-end;
 | |
|       border: none;
 | |
| 
 | |
|       .el-tabs__nav {
 | |
|         border: none;
 | |
|       }
 | |
| 
 | |
|       .el-tabs__item {
 | |
|         padding: 0 8px 0 12px !important;
 | |
|         text-align: left;
 | |
|         min-width: 130px;
 | |
|         height: 36px;
 | |
|         line-height: 36px;
 | |
|         border: none;
 | |
|         color: #555;
 | |
|         font-size: 12px;
 | |
| 
 | |
|         & + .el-tabs__item {
 | |
|           margin-left: 2px;
 | |
|         }
 | |
| 
 | |
|         .el-icon-close {
 | |
|           float: right;
 | |
|           width: auto;
 | |
|           height: 100%;
 | |
|           line-height: 36px;
 | |
|           background: transparent;
 | |
|           font-size: 16px;
 | |
|           color: #89b;
 | |
| 
 | |
|           &:hover {
 | |
|             color: #000;
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         &.is-active {
 | |
|           border: 1px solid #D8DCE3;
 | |
|           border-bottom: none;
 | |
|           border-radius: 4px 4px 0 0;
 | |
|           background: #F5F6F9;
 | |
|           color: #222;
 | |
| 
 | |
|           &:after {
 | |
|             display: none;
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         &:after {
 | |
|           position: absolute;
 | |
|           right: 0;
 | |
|           content: " ";
 | |
|           width: 1px;
 | |
|           background: #D8DCE3;
 | |
|           height: 24px;
 | |
|           top: 50%;
 | |
|           transform: translateY(-50%);
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   :deep(.more) {
 | |
|     .AiIcon {
 | |
|       height: 100%;
 | |
| 
 | |
|       .iconfont {
 | |
|         display: flex;
 | |
|         align-items: center;
 | |
|         justify-content: center;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 | |
| </style>
 |