1
2
3
4
5
6
7
8
9
10
11
12
13
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';
vben
authored
5 years ago
14
import { getCurrentTo } from '/@/utils/helper/routeHelper';
15
16
17
18
19
20
21
type CacheName = string | symbol | null | undefined;
/**
* @description: vuex Tab模块
*/
// declare namespace TabsStore {
export interface TabItem {
vben
authored
5 years ago
22
23
24
25
fullPath: string;
path?: string;
params?: any;
query?: any;
26
27
28
29
30
31
32
33
34
35
36
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 {
vben
authored
5 years ago
37
// tab list
38
tabsState: TabItem[] = [];
vben
authored
5 years ago
39
// tab cache list
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
keepAliveTabsState: CacheName[] = [];
currentContextMenuIndexState = -1;
currentContextMenuState: TabItem | null = null;
get getTabsState() {
return this.tabsState;
}
get getCurrentContextMenuIndexState() {
return this.currentContextMenuIndexState;
}
get getCurrentContextMenuState() {
return this.currentContextMenuState;
}
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 {
vben
authored
5 years ago
87
const { path, name, meta, fullPath, params, query } = route as TabItem;
88
89
90
91
92
93
// 404 页面不需要添加tab
if (path === PageEnum.ERROR_PAGE) {
return;
} else if ([REDIRECT_ROUTE.name, PAGE_NOT_FOUND_ROUTE.name].includes(name as string)) {
return;
}
vben
authored
5 years ago
94
vben
authored
5 years ago
95
let updateIndex = -1;
96
// 已经存在的页面,不重复添加tab
vben
authored
5 years ago
97
98
99
const hasTab = this.tabsState.some((tab, index) => {
updateIndex = index;
return (tab.fullPath || tab.path) === (fullPath || path);
100
});
vben
authored
5 years ago
101
102
103
104
105
106
107
108
109
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;
}
110
vben
authored
5 years ago
111
this.tabsState.push({ path, fullPath, name, meta, params, query });
112
113
114
115
116
117
118
119
120
121
122
123
124
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 {
vben
authored
5 years ago
125
const { fullPath, name, meta: { affix } = {} } = route;
126
if (affix) return;
vben
authored
5 years ago
127
const index = this.tabsState.findIndex((item) => item.fullPath === fullPath);
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
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 {
vben
authored
5 years ago
165
this.tabsState = toRaw(this.tabsState).filter((item) => !pathList.includes(item.fullPath));
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
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) {
vben
authored
5 years ago
184
pathList.push(item.fullPath);
185
186
187
188
189
190
191
192
nameList.push(item.name as string);
}
}
this.closeMultipleTab({ pathList, nameList });
}
}
@Action
vben
authored
5 years ago
193
194
195
196
197
198
199
200
addTabByPathAction(): void {
const toRoute = getCurrentTo();
if (!toRoute) return;
const { meta } = toRoute;
if (meta && meta.affix) {
return;
}
this.commitAddTab((toRoute as unknown) as AppRouteRecordRaw);
vben
authored
5 years ago
201
202
203
}
@Action
204
closeRightTabAction(route: AppRouteRecordRaw | TabItem): void {
vben
authored
5 years ago
205
const index = this.tabsState.findIndex((item) => item.fullPath === route.fullPath);
206
207
208
209
210
211
212
213
214
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) {
vben
authored
5 years ago
215
pathList.push(item.fullPath);
216
217
218
219
220
221
222
223
224
nameList.push(item.name as string);
}
}
this.closeMultipleTab({ pathList, nameList });
}
}
@Action
closeOtherTabAction(route: AppRouteRecordRaw | TabItem): void {
vben
authored
5 years ago
225
const closePathList = this.tabsState.map((item) => item.fullPath);
226
227
228
const pathList: string[] = [];
const nameList: string[] = [];
closePathList.forEach((path) => {
vben
authored
5 years ago
229
if (path !== route.fullPath) {
230
231
232
233
const closeItem = this.tabsState.find((item) => item.path === path);
if (!closeItem) return;
const affix = closeItem.meta ? closeItem.meta.affix : false;
if (!affix) {
vben
authored
5 years ago
234
pathList.push(closeItem.fullPath);
235
236
237
238
239
240
241
242
243
nameList.push(closeItem.name as string);
}
}
});
this.closeMultipleTab({ pathList, nameList });
}
}
export { Tab };
export const tabStore = getModule<Tab>(Tab);