2020-09-28 20:19:10 +08:00
|
|
|
|
import { computed, toRaw } from 'vue';
|
|
|
|
|
|
import type { AppRouteRecordRaw, RouteMeta } from '/@/router/types.d';
|
|
|
|
|
|
|
|
|
|
|
|
import { unref } from 'vue';
|
|
|
|
|
|
import { Action, Module, Mutation, VuexModule, getModule } from 'vuex-module-decorators';
|
|
|
|
|
|
import { hotModuleUnregisterModule } from '/@/utils/helper/vuexHelper';
|
|
|
|
|
|
|
|
|
|
|
|
import { PageEnum } from '/@/enums/pageEnum';
|
|
|
|
|
|
import { appStore } from '/@/store/modules/app';
|
|
|
|
|
|
|
|
|
|
|
|
import store from '/@/store';
|
|
|
|
|
|
import router from '/@/router';
|
|
|
|
|
|
import { PAGE_NOT_FOUND_ROUTE, REDIRECT_ROUTE } from '/@/router/constant';
|
2020-10-14 21:08:07 +08:00
|
|
|
|
import { getCurrentTo } from '/@/utils/helper/routeHelper';
|
2020-09-28 20:19:10 +08:00
|
|
|
|
|
|
|
|
|
|
type CacheName = string | symbol | null | undefined;
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @description: vuex Tab模块
|
|
|
|
|
|
*/
|
|
|
|
|
|
// declare namespace TabsStore {
|
|
|
|
|
|
export interface TabItem {
|
2020-10-14 21:08:07 +08:00
|
|
|
|
fullPath: string;
|
|
|
|
|
|
path?: string;
|
|
|
|
|
|
params?: any;
|
|
|
|
|
|
query?: any;
|
2020-09-28 20:19:10 +08:00
|
|
|
|
name?: CacheName;
|
|
|
|
|
|
meta?: RouteMeta;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const NAME = 'tab';
|
|
|
|
|
|
hotModuleUnregisterModule(NAME);
|
|
|
|
|
|
|
|
|
|
|
|
const getOpenKeepAliveRef = computed(() => appStore.getProjectConfig.openKeepAlive);
|
|
|
|
|
|
|
|
|
|
|
|
@Module({ namespaced: true, name: NAME, dynamic: true, store })
|
|
|
|
|
|
class Tab extends VuexModule {
|
|
|
|
|
|
// tab列表
|
|
|
|
|
|
tabsState: TabItem[] = [];
|
|
|
|
|
|
// 缓存列表
|
|
|
|
|
|
keepAliveTabsState: CacheName[] = [];
|
|
|
|
|
|
|
|
|
|
|
|
currentContextMenuIndexState = -1;
|
|
|
|
|
|
|
|
|
|
|
|
currentContextMenuState: TabItem | null = null;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @description: 获取tabs
|
|
|
|
|
|
*/
|
|
|
|
|
|
get getTabsState() {
|
|
|
|
|
|
return this.tabsState;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
get getCurrentContextMenuIndexState() {
|
|
|
|
|
|
return this.currentContextMenuIndexState;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
get getCurrentContextMenuState() {
|
|
|
|
|
|
return this.currentContextMenuState;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @description: 获取缓存的tab列表
|
|
|
|
|
|
*/
|
|
|
|
|
|
get getKeepAliveTabsState() {
|
|
|
|
|
|
return this.keepAliveTabsState;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
get getCurrentTab(): TabItem {
|
|
|
|
|
|
const route = unref(router.currentRoute);
|
|
|
|
|
|
return this.tabsState.find((item) => item.path === route.path)!;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Mutation
|
|
|
|
|
|
commitClearCache(): void {
|
|
|
|
|
|
this.keepAliveTabsState = [];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Mutation
|
|
|
|
|
|
commitCurrentContextMenuIndexState(index: number): void {
|
|
|
|
|
|
this.currentContextMenuIndexState = index;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Mutation
|
|
|
|
|
|
commitCurrentContextMenuState(item: TabItem): void {
|
|
|
|
|
|
this.currentContextMenuState = item;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @description: add tab
|
|
|
|
|
|
*/
|
|
|
|
|
|
@Mutation
|
|
|
|
|
|
commitAddTab(route: AppRouteRecordRaw | TabItem): void {
|
2020-10-14 21:08:07 +08:00
|
|
|
|
const { path, name, meta, fullPath, params, query } = route as TabItem;
|
2020-09-28 20:19:10 +08:00
|
|
|
|
// 404 页面不需要添加tab
|
|
|
|
|
|
if (path === PageEnum.ERROR_PAGE) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
} else if ([REDIRECT_ROUTE.name, PAGE_NOT_FOUND_ROUTE.name].includes(name as string)) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2020-10-14 21:08:07 +08:00
|
|
|
|
|
2020-09-28 20:19:10 +08:00
|
|
|
|
// 已经存在的页面,不重复添加tab
|
|
|
|
|
|
const hasTab = this.tabsState.some((tab) => {
|
2020-10-14 21:08:07 +08:00
|
|
|
|
return tab.fullPath === fullPath;
|
2020-09-28 20:19:10 +08:00
|
|
|
|
});
|
|
|
|
|
|
if (hasTab) return;
|
|
|
|
|
|
|
2020-10-14 21:08:07 +08:00
|
|
|
|
this.tabsState.push({ path, fullPath, name, meta, params, query });
|
2020-09-28 20:19:10 +08:00
|
|
|
|
if (unref(getOpenKeepAliveRef) && name) {
|
|
|
|
|
|
const noKeepAlive = meta && meta.ignoreKeepAlive;
|
|
|
|
|
|
const hasName = this.keepAliveTabsState.includes(name);
|
|
|
|
|
|
!noKeepAlive && !hasName && this.keepAliveTabsState.push(name);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @description: close tab
|
|
|
|
|
|
*/
|
|
|
|
|
|
@Mutation
|
|
|
|
|
|
commitCloseTab(route: AppRouteRecordRaw | TabItem): void {
|
|
|
|
|
|
try {
|
2020-10-14 21:08:07 +08:00
|
|
|
|
const { fullPath, name, meta: { affix } = {} } = route;
|
2020-09-28 20:19:10 +08:00
|
|
|
|
if (affix) return;
|
2020-10-14 21:08:07 +08:00
|
|
|
|
const index = this.tabsState.findIndex((item) => item.fullPath === fullPath);
|
2020-09-28 20:19:10 +08:00
|
|
|
|
index !== -1 && this.tabsState.splice(index, 1);
|
|
|
|
|
|
|
|
|
|
|
|
if (unref(getOpenKeepAliveRef) && name) {
|
|
|
|
|
|
const i = this.keepAliveTabsState.findIndex((item) => item === name);
|
|
|
|
|
|
i !== -1 && this.keepAliveTabsState.splice(i, 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Mutation
|
|
|
|
|
|
commitCloseTabKeepAlive(route: AppRouteRecordRaw | TabItem): void {
|
|
|
|
|
|
const { name } = route;
|
|
|
|
|
|
if (unref(getOpenKeepAliveRef) && name) {
|
|
|
|
|
|
const i = this.keepAliveTabsState.findIndex((item) => item === name);
|
|
|
|
|
|
i !== -1 && toRaw(this.keepAliveTabsState).splice(i, 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Mutation
|
|
|
|
|
|
commitCloseAllTab(): void {
|
|
|
|
|
|
this.tabsState = this.tabsState.filter((item) => {
|
|
|
|
|
|
return item.meta && item.meta.affix;
|
|
|
|
|
|
});
|
|
|
|
|
|
const names = this.tabsState.map((item) => item.name);
|
|
|
|
|
|
this.keepAliveTabsState = names as string[];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Mutation
|
|
|
|
|
|
commitResetState(): void {
|
|
|
|
|
|
this.tabsState = [];
|
|
|
|
|
|
this.currentContextMenuState = null;
|
|
|
|
|
|
this.currentContextMenuIndexState = -1;
|
|
|
|
|
|
this.keepAliveTabsState = [];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Mutation
|
|
|
|
|
|
closeMultipleTab({ pathList, nameList }: { pathList: string[]; nameList: string[] }): void {
|
2020-10-14 21:08:07 +08:00
|
|
|
|
this.tabsState = toRaw(this.tabsState).filter((item) => !pathList.includes(item.fullPath));
|
2020-09-28 20:19:10 +08:00
|
|
|
|
if (unref(getOpenKeepAliveRef) && nameList) {
|
|
|
|
|
|
this.keepAliveTabsState = toRaw(this.keepAliveTabsState).filter(
|
|
|
|
|
|
(item) => !nameList.includes(item as string)
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Action
|
|
|
|
|
|
closeLeftTabAction(route: AppRouteRecordRaw | TabItem): void {
|
|
|
|
|
|
const index = this.tabsState.findIndex((item) => item.path === route.path);
|
|
|
|
|
|
|
|
|
|
|
|
if (index > 0) {
|
|
|
|
|
|
const leftTabs = this.tabsState.slice(0, index);
|
|
|
|
|
|
const pathList: string[] = [];
|
|
|
|
|
|
const nameList: string[] = [];
|
|
|
|
|
|
for (const item of leftTabs) {
|
|
|
|
|
|
const affix = item.meta ? item.meta.affix : false;
|
|
|
|
|
|
if (!affix) {
|
2020-10-14 21:08:07 +08:00
|
|
|
|
pathList.push(item.fullPath);
|
2020-09-28 20:19:10 +08:00
|
|
|
|
nameList.push(item.name as string);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
this.closeMultipleTab({ pathList, nameList });
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-10-12 00:18:32 +08:00
|
|
|
|
@Action
|
2020-10-14 21:08:07 +08:00
|
|
|
|
addTabByPathAction(): void {
|
|
|
|
|
|
const toRoute = getCurrentTo();
|
|
|
|
|
|
if (!toRoute) return;
|
|
|
|
|
|
const { meta } = toRoute;
|
|
|
|
|
|
if (meta && meta.affix) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
this.commitAddTab((toRoute as unknown) as AppRouteRecordRaw);
|
2020-10-12 00:18:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2020-09-28 20:19:10 +08:00
|
|
|
|
@Action
|
|
|
|
|
|
closeRightTabAction(route: AppRouteRecordRaw | TabItem): void {
|
2020-10-14 21:08:07 +08:00
|
|
|
|
const index = this.tabsState.findIndex((item) => item.fullPath === route.fullPath);
|
2020-09-28 20:19:10 +08:00
|
|
|
|
|
|
|
|
|
|
if (index >= 0 && index < this.tabsState.length - 1) {
|
|
|
|
|
|
const rightTabs = this.tabsState.slice(index + 1, this.tabsState.length);
|
|
|
|
|
|
|
|
|
|
|
|
const pathList: string[] = [];
|
|
|
|
|
|
const nameList: string[] = [];
|
|
|
|
|
|
for (const item of rightTabs) {
|
|
|
|
|
|
const affix = item.meta ? item.meta.affix : false;
|
|
|
|
|
|
if (!affix) {
|
2020-10-14 21:08:07 +08:00
|
|
|
|
pathList.push(item.fullPath);
|
2020-09-28 20:19:10 +08:00
|
|
|
|
nameList.push(item.name as string);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
this.closeMultipleTab({ pathList, nameList });
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Action
|
|
|
|
|
|
closeOtherTabAction(route: AppRouteRecordRaw | TabItem): void {
|
2020-10-14 21:08:07 +08:00
|
|
|
|
const closePathList = this.tabsState.map((item) => item.fullPath);
|
2020-09-28 20:19:10 +08:00
|
|
|
|
const pathList: string[] = [];
|
|
|
|
|
|
const nameList: string[] = [];
|
|
|
|
|
|
closePathList.forEach((path) => {
|
2020-10-14 21:08:07 +08:00
|
|
|
|
if (path !== route.fullPath) {
|
2020-09-28 20:19:10 +08:00
|
|
|
|
const closeItem = this.tabsState.find((item) => item.path === path);
|
|
|
|
|
|
if (!closeItem) return;
|
|
|
|
|
|
const affix = closeItem.meta ? closeItem.meta.affix : false;
|
|
|
|
|
|
if (!affix) {
|
2020-10-14 21:08:07 +08:00
|
|
|
|
pathList.push(closeItem.fullPath);
|
2020-09-28 20:19:10 +08:00
|
|
|
|
nameList.push(closeItem.name as string);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
this.closeMultipleTab({ pathList, nameList });
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
export { Tab };
|
|
|
|
|
|
export const tabStore = getModule<Tab>(Tab);
|