feat(components): 完善了动态tabs的逻辑处理

This commit is contained in:
Coffee-crocodile 2022-08-19 14:05:00 +08:00
parent 30ef04efe3
commit 518689f64d
4 changed files with 94 additions and 8 deletions

View File

@ -21,7 +21,7 @@
<UserCenter /> <UserCenter />
</div> </div>
</n-layout-header> </n-layout-header>
<n-layout-header bordered class="h-45px"><TabBar /></n-layout-header> <n-layout-header class="h-45px"><TabBar /></n-layout-header>
<div class="p-16px"> <div class="p-16px">
<n-layout-content class="bg-transparent"> <n-layout-content class="bg-transparent">
<router-view v-slot="{ Component }"> <router-view v-slot="{ Component }">

View File

@ -1,24 +1,37 @@
<template> <template>
<div class="wh-full px-3 flex items-end"> <div class="wh-full flex items-end">
<n-tabs type="card" size="small"> <n-tabs type="card" size="small" :tabs-padding="15" :value="tabStore.currentTab" @close="handleClose">
<n-tab name="幸福">工作台</n-tab> <n-tab v-for="item in tabStore.inherentTab" :key="item.path" :name="item.name" @click="toRoot">
<n-tab v-for="item in tabStore.tabs" :key="item.path" closable :name="item.meta.title" @click="handleTab(item)"> {{ item.title }}
</n-tab>
<n-tab
v-for="item in tabStore.tabs"
:key="item.path"
closable
:name="item.name as string"
@click="handleTab(item)"
>
{{ item.meta.title }} {{ item.meta.title }}
</n-tab> </n-tab>
</n-tabs> </n-tabs>
</div> </div>
</template> </template>
<script setup lang="ts"> <script lang="ts" setup>
import { useTabStore } from '@/store'; import { useTabStore } from '@/store';
import { useAppRouter } from '~/src/hook'; import { useAppRouter } from '~/src/hook';
import { RouteLocationNormalized } from 'vue-router'; import { RouteLocationNormalized } from 'vue-router';
import { defineComponent } from 'vue';
const tabStore = useTabStore(); const tabStore = useTabStore();
const { routerPush } = useAppRouter(); const { routerPush, toRoot } = useAppRouter();
const handleTab = (route: RouteLocationNormalized) => { const handleTab = (route: RouteLocationNormalized) => {
routerPush(route.path); routerPush(route.path);
}; };
const handleClose = (name: string) => {
tabStore.closeTab(name);
};
</script> </script>
<style scoped></style> <style scoped></style>

View File

@ -42,7 +42,10 @@ export async function createPermissionGuard(
} else { } else {
routeStore.setActiveMenu(to.fullPath); routeStore.setActiveMenu(to.fullPath);
} }
// 添加动态tabs
// 添加tabs
tabStore.addTab(to); tabStore.addTab(to);
// 设置高亮标签;
tabStore.setCurrentTab(to.name as string);
next(); next();
} }

View File

@ -1,18 +1,88 @@
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { RouteLocationNormalized } from 'vue-router'; import { RouteLocationNormalized } from 'vue-router';
import { useAppRouter } from '@/hook';
interface TabState { interface TabState {
inherentTab: {
name: string;
title: string;
path: string;
}[];
tabs: RouteLocationNormalized[]; tabs: RouteLocationNormalized[];
currentTab: string;
} }
export const useTabStore = defineStore('tab-store', { export const useTabStore = defineStore('tab-store', {
state: (): TabState => { state: (): TabState => {
return { return {
inherentTab: [
{
name: 'dashboard_workbench',
title: '工作台',
path: '/',
},
],
tabs: [], tabs: [],
currentTab: 'dashboard_workbench',
}; };
}, },
getters: {
inherentTabName(): string[] {
return this.inherentTab.map((item) => {
return item.name;
});
},
},
actions: { actions: {
addTab(route: RouteLocationNormalized) { addTab(route: RouteLocationNormalized) {
// 如果已经在固有标签里则不添加
if (this.inherentTabName.includes(route.name as string)) {
return;
}
// 如果标签名称已存在则不添加
if (this.hasExistTab(route.name as string)) {
return;
}
this.tabs.push(route); this.tabs.push(route);
}, },
closeTab(name: string) {
const { routerPush, toRoot } = useAppRouter(false);
const tabsLength = this.tabs.length;
// 如果动态标签大于一个,才会标签跳转
if (this.tabs.length > 1) {
// 获取关闭的标签索引
const index = this.getTabIndex(name);
const isLast = index + 1 === tabsLength;
// 如果是关闭的当前页面,路由跳转到原先标签的后一个标签
if (this.currentTab === name && !isLast) {
// 跳转到后一个标签
routerPush(this.tabs[index + 1].path);
} else {
// 已经是最后一个了,就跳转前一个
routerPush(this.tabs[index - 1].path);
}
}
// 删除标签
this.tabs = this.tabs.filter((item) => {
return item.name !== name;
});
// 删除后如果清空了,就跳转到默认首页
if (tabsLength - 1 === 0) {
toRoot();
}
},
hasExistTab(name: string) {
return this.tabs.some((item) => {
return item.name === name;
});
},
/* 设置当前激活的标签 */
setCurrentTab(name: string) {
this.currentTab = name;
},
getTabIndex(name: string) {
return this.tabs.findIndex((item) => {
return item.name === name;
});
},
}, },
}); });