vue-vben-admin/src/store/modules/tab.ts

332 lines
9.1 KiB
TypeScript
Raw Normal View History

2020-12-03 21:49:32 +08:00
import { toRaw } from 'vue';
2020-09-28 20:19:10 +08:00
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 store from '/@/store';
import router from '/@/router';
import { PAGE_NOT_FOUND_ROUTE, REDIRECT_ROUTE } from '/@/router/constant';
2020-12-03 21:49:32 +08:00
import { RouteLocationNormalized, RouteLocationRaw } from 'vue-router';
import { getRoute } from '/@/router/helper/routeHelper';
import { useGo, useRedo } from '/@/hooks/web/usePage';
2020-12-15 00:13:23 +08:00
import { cloneDeep } from 'lodash-es';
2020-09-28 20:19:10 +08:00
const NAME = 'tab';
2020-11-21 22:47:10 +08:00
2020-09-28 20:19:10 +08:00
hotModuleUnregisterModule(NAME);
2020-12-03 21:49:32 +08:00
export const PAGE_LAYOUT_KEY = '__PAGE_LAYOUT__';
function isGotoPage() {
const go = useGo();
go(unref(router.currentRoute).path, true);
}
2020-09-28 20:19:10 +08:00
@Module({ namespaced: true, name: NAME, dynamic: true, store })
class Tab extends VuexModule {
2020-12-03 21:49:32 +08:00
cachedMapState = new Map<string, string[]>();
2020-09-28 20:19:10 +08:00
2020-12-03 21:49:32 +08:00
// tab list
tabsState: RouteLocationNormalized[] = [];
2020-09-28 20:19:10 +08:00
2020-12-03 21:49:32 +08:00
lastDragEndIndexState = 0;
2020-11-10 21:58:19 +08:00
2020-09-28 20:19:10 +08:00
get getTabsState() {
return this.tabsState;
}
2020-12-03 21:49:32 +08:00
get getCurrentTab(): RouteLocationNormalized {
const route = unref(router.currentRoute);
return this.tabsState.find((item) => item.path === route.path)!;
2020-09-28 20:19:10 +08:00
}
2020-12-03 21:49:32 +08:00
get getCachedMapState(): Map<string, string[]> {
return this.cachedMapState;
2020-09-28 20:19:10 +08:00
}
2020-12-03 21:49:32 +08:00
get getLastDragEndIndexState(): number {
return this.lastDragEndIndexState;
2020-09-28 20:19:10 +08:00
}
@Mutation
commitClearCache(): void {
2020-12-03 21:49:32 +08:00
this.cachedMapState = new Map();
2020-09-28 20:19:10 +08:00
}
@Mutation
2020-12-03 21:49:32 +08:00
goToPage() {
const go = useGo();
const len = this.tabsState.length;
const { path } = unref(router.currentRoute);
let toPath: PageEnum | string = PageEnum.BASE_HOME;
if (len > 0) {
const page = this.tabsState[len - 1];
const p = page.fullPath || page.path;
if (p) {
toPath = p;
}
}
// Jump to the current page and report an error
path !== toPath && go(toPath as PageEnum, true);
2020-09-28 20:19:10 +08:00
}
@Mutation
2020-12-03 21:49:32 +08:00
commitCachedMapState(): void {
const cacheMap = new Map<string, string[]>();
const pageCacheSet = new Set<string>();
this.tabsState.forEach((tab) => {
const item = getRoute(tab);
2020-12-05 16:14:27 +08:00
const needCache = !item.meta?.ignoreKeepAlive;
2020-12-05 09:30:51 +08:00
if (!needCache) return;
2020-12-05 16:14:27 +08:00
if (item.meta?.affix) {
2020-12-03 21:49:32 +08:00
const name = item.name as string;
pageCacheSet.add(name);
2020-12-21 23:38:16 +08:00
} else if (item?.matched && needCache) {
const matched = item?.matched;
if (!matched) return;
2020-12-03 21:49:32 +08:00
const len = matched.length;
if (len < 2) return;
for (let i = 0; i < matched.length; i++) {
const key = matched[i].name as string;
if (i < 2) {
pageCacheSet.add(key);
}
if (i < len - 1) {
const { meta, name } = matched[i + 1];
2020-12-05 09:30:51 +08:00
if (meta && (meta.affix || needCache)) {
2020-12-03 21:49:32 +08:00
const mapList = cacheMap.get(key) || [];
if (!mapList.includes(name as string)) {
mapList.push(name as string);
}
cacheMap.set(key, mapList);
}
}
}
}
});
cacheMap.set(PAGE_LAYOUT_KEY, Array.from(pageCacheSet));
this.cachedMapState = cacheMap;
2020-09-28 20:19:10 +08:00
}
@Mutation
2020-12-03 21:49:32 +08:00
commitTabRoutesState(route: RouteLocationNormalized) {
const { path, fullPath, params, query } = route;
2020-10-14 21:08:07 +08:00
let updateIndex = -1;
2020-09-28 20:19:10 +08:00
// 已经存在的页面不重复添加tab
const hasTab = this.tabsState.some((tab, index) => {
updateIndex = index;
return (tab.fullPath || tab.path) === (fullPath || path);
2020-09-28 20:19:10 +08:00
});
if (hasTab) {
const curTab = toRaw(this.tabsState)[updateIndex];
if (!curTab) return;
curTab.params = params || curTab.params;
curTab.query = query || curTab.query;
curTab.fullPath = fullPath || curTab.fullPath;
this.tabsState.splice(updateIndex, 1, curTab);
return;
}
2020-12-15 00:13:23 +08:00
this.tabsState = cloneDeep([...this.tabsState, route]);
2020-09-28 20:19:10 +08:00
}
/**
* @description: close tab
*/
@Mutation
2020-12-03 21:49:32 +08:00
commitCloseTab(route: RouteLocationNormalized): void {
const { fullPath, meta: { affix } = {} } = route;
if (affix) return;
const index = this.tabsState.findIndex((item) => item.fullPath === fullPath);
index !== -1 && this.tabsState.splice(index, 1);
2020-09-28 20:19:10 +08:00
}
@Mutation
commitCloseAllTab(): void {
this.tabsState = this.tabsState.filter((item) => {
return item.meta && item.meta.affix;
});
}
@Mutation
commitResetState(): void {
this.tabsState = [];
2020-12-03 21:49:32 +08:00
this.cachedMapState = new Map();
2020-09-28 20:19:10 +08:00
}
2020-11-25 22:28:58 +08:00
@Mutation
commitSortTabs({ oldIndex, newIndex }: { oldIndex: number; newIndex: number }): void {
const currentTab = this.tabsState[oldIndex];
this.tabsState.splice(oldIndex, 1);
this.tabsState.splice(newIndex, 0, currentTab);
2020-12-03 21:49:32 +08:00
this.lastDragEndIndexState = this.lastDragEndIndexState + 1;
2020-11-25 22:28:58 +08:00
}
2020-09-28 20:19:10 +08:00
@Mutation
2020-12-03 21:49:32 +08:00
closeMultipleTab({ pathList }: { pathList: string[] }): void {
2020-10-14 21:08:07 +08:00
this.tabsState = toRaw(this.tabsState).filter((item) => !pathList.includes(item.fullPath));
2020-12-03 21:49:32 +08:00
}
@Action
addTabAction(route: RouteLocationNormalized) {
const { path, name } = route;
// 404 页面不需要添加tab
if (
path === PageEnum.ERROR_PAGE ||
!name ||
[REDIRECT_ROUTE.name, PAGE_NOT_FOUND_ROUTE.name].includes(name as string)
) {
return;
}
this.commitTabRoutesState(getRoute(route));
this.commitCachedMapState();
}
@Mutation
2020-12-15 00:13:23 +08:00
async commitRedoPage() {
2020-12-03 21:49:32 +08:00
const route = router.currentRoute.value;
for (const [key, value] of this.cachedMapState) {
const index = value.findIndex((item) => item === (route.name as string));
if (index === -1) {
continue;
}
if (value.length === 1) {
this.cachedMapState.delete(key);
continue;
}
value.splice(index, 1);
this.cachedMapState.set(key, value);
}
const redo = useRedo();
2020-12-15 00:13:23 +08:00
await redo();
2020-12-03 21:49:32 +08:00
}
@Action
closeAllTabAction() {
this.commitCloseAllTab();
this.commitClearCache();
this.goToPage();
}
@Action
closeTabAction(tab: RouteLocationNormalized) {
function getObj(tabItem: RouteLocationNormalized) {
const { params, path, query } = tabItem;
return {
params: params || {},
path,
query: query || {},
};
}
const { currentRoute, replace } = router;
const { path } = unref(currentRoute);
if (path !== tab.path) {
// Closed is not the activation tab
this.commitCloseTab(tab);
return;
}
// Closed is activated atb
let toObj: RouteLocationRaw = {};
const index = this.getTabsState.findIndex((item) => item.path === path);
// If the current is the leftmost tab
if (index === 0) {
// There is only one tab, then jump to the homepage, otherwise jump to the right tab
if (this.getTabsState.length === 1) {
toObj = PageEnum.BASE_HOME;
} else {
// Jump to the right tab
const page = this.getTabsState[index + 1];
toObj = getObj(page);
}
} else {
// Close the current tab
const page = this.getTabsState[index - 1];
toObj = getObj(page);
2020-09-28 20:19:10 +08:00
}
2020-12-03 21:49:32 +08:00
this.commitCloseTab(currentRoute.value);
replace(toObj);
2020-09-28 20:19:10 +08:00
}
@Action
2020-12-03 21:49:32 +08:00
closeTabByKeyAction(key: string) {
const index = this.tabsState.findIndex((item) => (item.fullPath || item.path) === key);
index !== -1 && this.closeTabAction(this.tabsState[index]);
}
@Action
closeLeftTabAction(route: RouteLocationNormalized): void {
2020-09-28 20:19:10 +08:00
const index = this.tabsState.findIndex((item) => item.path === route.path);
if (index > 0) {
const leftTabs = this.tabsState.slice(0, index);
const pathList: 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
}
}
2020-12-03 21:49:32 +08:00
this.closeMultipleTab({ pathList });
2020-10-14 21:08:07 +08:00
}
2020-12-03 21:49:32 +08:00
this.commitCachedMapState();
isGotoPage();
}
2020-09-28 20:19:10 +08:00
@Action
2020-12-03 21:49:32 +08:00
closeRightTabAction(route: RouteLocationNormalized): 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[] = [];
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
}
}
2020-12-03 21:49:32 +08:00
this.closeMultipleTab({ pathList });
2020-09-28 20:19:10 +08:00
}
2020-12-03 21:49:32 +08:00
this.commitCachedMapState();
isGotoPage();
2020-09-28 20:19:10 +08:00
}
@Action
2020-12-03 21:49:32 +08:00
closeOtherTabAction(route: RouteLocationNormalized): 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[] = [];
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
}
}
});
2020-12-03 21:49:32 +08:00
this.closeMultipleTab({ pathList });
this.commitCachedMapState();
isGotoPage();
2020-09-28 20:19:10 +08:00
}
}
export const tabStore = getModule<Tab>(Tab);