vue-stack-tabs 0.1.51 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +717 -3
- package/dist/index.d.ts +3 -0
- package/dist/src/lib/StackTabs.vue.d.ts +33 -161
- package/dist/src/lib/components/ContextMenu/ContextMenuItem.vue.d.ts +6 -6
- package/dist/src/lib/components/ContextMenu/index.vue.d.ts +14 -14
- package/dist/src/lib/components/PageLoading.vue.d.ts +5 -5
- package/dist/src/lib/components/TabHeader/TabHeaderButton.vue.d.ts +24 -15
- package/dist/src/lib/components/TabHeader/TabHeaderItem.vue.d.ts +10 -8
- package/dist/src/lib/components/TabHeader/TabHeaderScroll.vue.d.ts +31 -13
- package/dist/src/lib/components/TabHeader/index.vue.d.ts +172 -20
- package/dist/src/lib/hooks/tabPanel/evict.d.ts +24 -0
- package/dist/src/lib/hooks/tabPanel/evict.spec.d.ts +1 -0
- package/dist/src/lib/hooks/tabPanel/scroll.d.ts +8 -0
- package/dist/src/lib/hooks/tabPanel/session.d.ts +9 -0
- package/dist/src/lib/hooks/tabPanel/state.d.ts +77 -0
- package/dist/src/lib/hooks/useContextMenu.d.ts +6 -1
- package/dist/src/lib/hooks/useTabActions.d.ts +68 -0
- package/dist/src/lib/hooks/{useTabMitt.d.ts → useTabEventBus.d.ts} +4 -3
- package/dist/src/lib/hooks/useTabLoading.d.ts +6 -0
- package/dist/src/lib/hooks/{useTabpanel.d.ts → useTabPanel.d.ts} +20 -14
- package/dist/src/lib/hooks/useTabPanel.spec.d.ts +1 -0
- package/dist/src/lib/hooks/useTabRouter.d.ts +14 -5
- package/dist/src/lib/i18n/index.d.ts +1 -1
- package/dist/src/lib/i18n/lang/en.d.ts +1 -0
- package/dist/src/lib/i18n/lang/zh-CN.d.ts +1 -0
- package/dist/src/lib/index.d.ts +5 -4
- package/dist/src/lib/model/TabModel.d.ts +20 -3
- package/dist/src/lib/model/TabModel.spec.d.ts +1 -0
- package/dist/src/lib/utils/iframeBridge.d.ts +31 -0
- package/dist/src/lib/utils/iframeBridge.spec.d.ts +1 -0
- package/dist/src/lib/utils/scrollUtils.d.ts +28 -0
- package/dist/src/lib/utils/tabInfoEncoder.d.ts +19 -0
- package/dist/src/lib/utils/tabInfoEncoder.spec.d.ts +1 -0
- package/dist/src/lib/utils/urlParser.d.ts +19 -0
- package/dist/src/lib/utils/urlParser.spec.d.ts +1 -0
- package/dist/src/lib/versionLogger.d.ts +2 -0
- package/dist/style.css +1 -1
- package/dist/vue-stack-tabs.css +1 -0
- package/dist/vue-stack-tabs.es.js +1795 -1679
- package/dist/vue-stack-tabs.umd.js +1 -5
- package/package.json +76 -39
- package/src/lib/StackTabs.vue +222 -47
- package/src/lib/assets/image/open.svg +1 -0
- package/src/lib/assets/style/common/var.scss +1 -1
- package/src/lib/assets/style/icon.scss +6 -0
- package/src/lib/assets/style/stackTab.scss +46 -3
- package/src/lib/assets/style/transition.scss +63 -62
- package/src/lib/components/ContextMenu/ContextMenuItem.vue +7 -0
- package/src/lib/components/ContextMenu/index.vue +50 -38
- package/src/lib/components/PageLoading.vue +30 -10
- package/src/lib/components/TabHeader/TabHeaderButton.vue +12 -3
- package/src/lib/components/TabHeader/TabHeaderItem.vue +31 -27
- package/src/lib/components/TabHeader/TabHeaderScroll.vue +83 -77
- package/src/lib/components/TabHeader/index.vue +45 -40
- package/src/lib/hooks/tabPanel/evict.spec.ts +85 -0
- package/src/lib/hooks/tabPanel/evict.ts +57 -0
- package/src/lib/hooks/tabPanel/scroll.ts +52 -0
- package/src/lib/hooks/tabPanel/session.ts +33 -0
- package/src/lib/hooks/tabPanel/state.ts +52 -0
- package/src/lib/hooks/useContextMenu.ts +22 -20
- package/src/lib/hooks/useTabActions.ts +148 -0
- package/src/lib/hooks/useTabEventBus.ts +31 -0
- package/src/lib/hooks/useTabLoading.ts +12 -4
- package/src/lib/hooks/useTabPanel.spec.ts +34 -0
- package/src/lib/hooks/useTabPanel.tsx +546 -0
- package/src/lib/hooks/useTabRouter.ts +114 -103
- package/src/lib/i18n/index.ts +14 -18
- package/src/lib/i18n/lang/en.ts +2 -1
- package/src/lib/i18n/lang/zh-CN.ts +2 -1
- package/src/lib/iframe.vue +6 -0
- package/src/lib/index.ts +27 -8
- package/src/lib/model/TabModel.spec.ts +40 -0
- package/src/lib/model/TabModel.ts +22 -9
- package/src/lib/nuxt/module.d.ts +19 -0
- package/src/lib/nuxt/module.ts +34 -0
- package/src/lib/nuxt/runtime/plugin.client.ts +11 -0
- package/src/lib/utils/iframeBridge.spec.ts +37 -0
- package/src/lib/utils/iframeBridge.ts +52 -0
- package/src/lib/utils/{TabScrollHelper.ts → scrollUtils.ts} +23 -29
- package/src/lib/utils/tabInfoEncoder.spec.ts +42 -0
- package/src/lib/utils/tabInfoEncoder.ts +65 -0
- package/src/lib/utils/urlParser.spec.ts +45 -0
- package/src/lib/utils/urlParser.ts +42 -0
- package/src/lib/{banner.ts → versionLogger.ts} +4 -5
- package/dist/src/lib/banner.d.ts +0 -2
- package/dist/src/lib/hooks/useStackTab.d.ts +0 -11
- package/dist/src/lib/utils/TabIdHelper.d.ts +0 -11
- package/dist/src/lib/utils/TabScrollHelper.d.ts +0 -33
- package/dist/src/lib/utils/UriHelper.d.ts +0 -4
- package/src/lib/hooks/useStackTab.ts +0 -119
- package/src/lib/hooks/useTabMitt.ts +0 -30
- package/src/lib/hooks/useTabpanel.tsx +0 -708
- package/src/lib/utils/TabIdHelper.ts +0 -70
- package/src/lib/utils/UriHelper.ts +0 -22
|
@@ -1,708 +0,0 @@
|
|
|
1
|
-
import type { ITabBase, ITabData, ITabItem, ITabPage } from '../model/TabModel'
|
|
2
|
-
import {
|
|
3
|
-
defineComponent,
|
|
4
|
-
nextTick,
|
|
5
|
-
onActivated,
|
|
6
|
-
onDeactivated,
|
|
7
|
-
onMounted,
|
|
8
|
-
onUnmounted,
|
|
9
|
-
ref,
|
|
10
|
-
unref
|
|
11
|
-
} from 'vue'
|
|
12
|
-
import type { DefineComponent, VNode } from 'vue'
|
|
13
|
-
import { useRouter } from 'vue-router'
|
|
14
|
-
import type { RouteLocationNormalizedLoaded } from 'vue-router'
|
|
15
|
-
import { ulid } from 'ulid'
|
|
16
|
-
import { encodeTabInfo, createPageId, decodeTabInfo } from '../utils/TabIdHelper'
|
|
17
|
-
import { defu } from 'defu'
|
|
18
|
-
import { Stack } from '../model/TabModel'
|
|
19
|
-
import { uriDecode } from '../utils/UriHelper'
|
|
20
|
-
import PageLoading from '../components/PageLoading.vue'
|
|
21
|
-
import { MittType, useEmitter } from './useTabMitt'
|
|
22
|
-
import { useI18n } from 'vue-i18n-lite'
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const tabs = ref<ITabItem[]>([])
|
|
26
|
-
const defaultTabs: ITabItem[] = []
|
|
27
|
-
// cache
|
|
28
|
-
const caches = ref<string[]>([])
|
|
29
|
-
// Dynamic components
|
|
30
|
-
const components = new Map<string, any>()
|
|
31
|
-
const deletableCache = new Set<string>()
|
|
32
|
-
const deletableTab = new Set<string>()
|
|
33
|
-
const pageShown = ref<boolean>(true)
|
|
34
|
-
const SESSION_TAB_NAME = 'stacktab-active-tab'
|
|
35
|
-
const pageScroller = new Map<string, Map<string, any>>()
|
|
36
|
-
const initialed = ref<boolean>(false)
|
|
37
|
-
let max = 0
|
|
38
|
-
let scrollbar = false
|
|
39
|
-
let sessionPrefix = ''
|
|
40
|
-
export default () => {
|
|
41
|
-
const router = useRouter()
|
|
42
|
-
const emitter = useEmitter()
|
|
43
|
-
const { t } = useI18n()
|
|
44
|
-
const size = (): number => {
|
|
45
|
-
return tabs.value.length
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Init the Tab list
|
|
49
|
-
*/
|
|
50
|
-
const initial = (staticTabs: ITabData[]) => {
|
|
51
|
-
// add default tabs
|
|
52
|
-
// defaultTabs.splice(0)
|
|
53
|
-
// caches.value.splice(0)
|
|
54
|
-
// deletableCache.clear()
|
|
55
|
-
// deletableTab.clear()
|
|
56
|
-
// components.clear()
|
|
57
|
-
for (const item of staticTabs) {
|
|
58
|
-
// const id = ulid()
|
|
59
|
-
const fullItem = defu(item, { id: ulid(), refreshable: true, closable: true, iframe: false })
|
|
60
|
-
const __tab = encodeTabInfo(fullItem)
|
|
61
|
-
const uri = uriDecode(fullItem.path)
|
|
62
|
-
const config = defu(fullItem, {
|
|
63
|
-
closable: true,
|
|
64
|
-
refreshable: true,
|
|
65
|
-
iframe: false
|
|
66
|
-
})
|
|
67
|
-
const cacheName = createPageId(fullItem.id, uri.path, uri.query)
|
|
68
|
-
const page: ITabPage = {
|
|
69
|
-
id: cacheName,
|
|
70
|
-
tabId: fullItem.id,
|
|
71
|
-
path: uri.path,
|
|
72
|
-
query: defu(uri.query, { __tab })
|
|
73
|
-
}
|
|
74
|
-
const pages = new Stack<ITabPage>()
|
|
75
|
-
pages.push(page)
|
|
76
|
-
const tab: ITabItem = {
|
|
77
|
-
id: fullItem.id,
|
|
78
|
-
title: config.title,
|
|
79
|
-
closable: config.closable,
|
|
80
|
-
refreshable: config.refreshable,
|
|
81
|
-
iframe: config.iframe,
|
|
82
|
-
active: false,
|
|
83
|
-
pages
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
caches.value.push(cacheName)
|
|
87
|
-
|
|
88
|
-
defaultTabs.push(tab)
|
|
89
|
-
tabs.value.push({ ...tab })
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// add temp tab from session
|
|
93
|
-
const tempTab = window.sessionStorage.getItem(sessionPrefix+SESSION_TAB_NAME)
|
|
94
|
-
if (tempTab !== null && tempTab !== undefined) {
|
|
95
|
-
// const tempItems = JSON.parse(window.sessionStorage.getItem('tabItems')!)
|
|
96
|
-
const temp = JSON.parse(tempTab, (k, v) => {
|
|
97
|
-
if (k === 'pages') {
|
|
98
|
-
return new Stack<ITabPage>(v)
|
|
99
|
-
} else {
|
|
100
|
-
return v
|
|
101
|
-
}
|
|
102
|
-
})
|
|
103
|
-
// const temp = defu({ pages: new Stack<ITabPage>() }, tempItems) as ITabItem
|
|
104
|
-
let hasTab = false
|
|
105
|
-
for (const tab of tabs.value) {
|
|
106
|
-
if (tab.id === temp.id) {
|
|
107
|
-
hasTab = true
|
|
108
|
-
break
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
if (!hasTab) {
|
|
112
|
-
tabs.value.push(temp)
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
initialed.value = true
|
|
116
|
-
}
|
|
117
|
-
const hasTab = (id: string) => {
|
|
118
|
-
for (const tab of tabs.value) {
|
|
119
|
-
if (tab.id === id) {
|
|
120
|
-
return true
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
return false
|
|
124
|
-
}
|
|
125
|
-
const canAddTab = () => {
|
|
126
|
-
return max <= 0 || (max > 0 && max > tabs.value.length)
|
|
127
|
-
}
|
|
128
|
-
const addTab = (tab: ITabItem) => {
|
|
129
|
-
return new Promise((resolve) => {
|
|
130
|
-
tabs.value.push(tab)
|
|
131
|
-
resolve(true)
|
|
132
|
-
})
|
|
133
|
-
}
|
|
134
|
-
const getTab = (id: string) => {
|
|
135
|
-
for (const tab of tabs.value) {
|
|
136
|
-
if (tab.id === id) {
|
|
137
|
-
return tab
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
return null
|
|
141
|
-
}
|
|
142
|
-
const addPage = (route: RouteLocationNormalizedLoaded, component: VNode): DefineComponent => {
|
|
143
|
-
let cacheComponent: DefineComponent
|
|
144
|
-
let tabInfo: ITabBase
|
|
145
|
-
if (route.query.__tab) {
|
|
146
|
-
tabInfo = decodeTabInfo(route.query.__tab as string)
|
|
147
|
-
} else {
|
|
148
|
-
tabInfo = {
|
|
149
|
-
id: ulid(),
|
|
150
|
-
title: t('VueStackTab.undefined'),
|
|
151
|
-
closable: true,
|
|
152
|
-
refreshable: true,
|
|
153
|
-
iframe: false
|
|
154
|
-
}
|
|
155
|
-
route.query.__tab = encodeTabInfo(tabInfo)
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
if (deletableTab.has(tabInfo.id!) || !component) {
|
|
159
|
-
return
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* if using nginx as web server, it will add '/' at the end of url.
|
|
164
|
-
*
|
|
165
|
-
*/
|
|
166
|
-
const matchPath = route.matched[route.matched.length - 1].path
|
|
167
|
-
const tmpPath = route.path.endsWith('/')
|
|
168
|
-
? route.path.substring(0, route.path.length - 1)
|
|
169
|
-
: route.path
|
|
170
|
-
|
|
171
|
-
const cacheName = createPageId(
|
|
172
|
-
tabInfo.id!,
|
|
173
|
-
matchPath === tmpPath ? tmpPath : route.path,
|
|
174
|
-
route.query.valueOf()
|
|
175
|
-
)
|
|
176
|
-
if(deletableCache.has(cacheName)) {
|
|
177
|
-
return components.get(cacheName)!
|
|
178
|
-
}
|
|
179
|
-
const src = route.query.__src
|
|
180
|
-
// 增加tab
|
|
181
|
-
let activeTab: ITabItem | null = null
|
|
182
|
-
for (const tab of unref(tabs)) {
|
|
183
|
-
tab.active = false
|
|
184
|
-
if (tab.id === tabInfo.id) {
|
|
185
|
-
activeTab = tab as ITabItem
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
const page: ITabPage = {
|
|
189
|
-
id: cacheName,
|
|
190
|
-
tabId: tabInfo.id!,
|
|
191
|
-
path: route.path,
|
|
192
|
-
query: route.query as Record<string, string>
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
if (activeTab === null) {
|
|
196
|
-
const pages = new Stack<ITabPage>()
|
|
197
|
-
pages.push(page)
|
|
198
|
-
activeTab = {
|
|
199
|
-
id: tabInfo.id!,
|
|
200
|
-
title: tabInfo.title,
|
|
201
|
-
closable: tabInfo.closable!,
|
|
202
|
-
refreshable: tabInfo.refreshable!,
|
|
203
|
-
iframe: tabInfo.iframe!,
|
|
204
|
-
url: decodeURIComponent(src as string),
|
|
205
|
-
active: true,
|
|
206
|
-
pages
|
|
207
|
-
}
|
|
208
|
-
addTab(activeTab).then(() => {
|
|
209
|
-
emitter.emit(MittType.TAB_ACTIVE, { id: tabInfo.id!, isRoute: false })
|
|
210
|
-
})
|
|
211
|
-
} else {
|
|
212
|
-
activeTab.active = true
|
|
213
|
-
if (activeTab.pages.isEmpty() || activeTab.pages.peek()!.id !== page.id) {
|
|
214
|
-
activeTab.pages.push(page)
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
updateSession(activeTab)
|
|
218
|
-
// const cacheSet = new Set(caches.value)
|
|
219
|
-
if (components.has(cacheName)) {
|
|
220
|
-
cacheComponent = components.get(cacheName)!
|
|
221
|
-
} else {
|
|
222
|
-
// 增加控件
|
|
223
|
-
cacheComponent = defineComponent({
|
|
224
|
-
name: cacheName!,
|
|
225
|
-
components: {
|
|
226
|
-
DynamicComponent: component
|
|
227
|
-
},
|
|
228
|
-
emits: {
|
|
229
|
-
onLoaded: null
|
|
230
|
-
},
|
|
231
|
-
setup(props, context) {
|
|
232
|
-
onMounted(() => {
|
|
233
|
-
context.emit('onLoaded')
|
|
234
|
-
addPageScroller(cacheName, '.cache-page-wrapper')
|
|
235
|
-
})
|
|
236
|
-
onDeactivated(() => {
|
|
237
|
-
saveScroller(cacheName)
|
|
238
|
-
})
|
|
239
|
-
onActivated(() => {
|
|
240
|
-
context.emit('onLoaded')
|
|
241
|
-
restoreScroller(cacheName)
|
|
242
|
-
console.log(pageScroller.get(cacheName))
|
|
243
|
-
removeDeletableCache()
|
|
244
|
-
deletableTab.clear()
|
|
245
|
-
component.props = null
|
|
246
|
-
})
|
|
247
|
-
onUnmounted(() => {
|
|
248
|
-
console.log('on unMounted', cacheName)
|
|
249
|
-
removeScroller(cacheName)
|
|
250
|
-
// setTimeout(() => {
|
|
251
|
-
// 刷新时重置路由
|
|
252
|
-
// pageShown.value = true
|
|
253
|
-
// }, 500)
|
|
254
|
-
})
|
|
255
|
-
return () => (
|
|
256
|
-
<div
|
|
257
|
-
class="cache-page-wrapper"
|
|
258
|
-
id={'W-' + tabInfo.id}
|
|
259
|
-
style={[scrollbar ? 'overflow:auto' : 'overflow:hidden']}
|
|
260
|
-
>
|
|
261
|
-
<dynamic-component tId={tabInfo.id} pId={cacheName} />
|
|
262
|
-
<PageLoading tId={tabInfo.id!} />
|
|
263
|
-
</div>
|
|
264
|
-
)
|
|
265
|
-
}
|
|
266
|
-
})
|
|
267
|
-
components.set(cacheName, cacheComponent)
|
|
268
|
-
|
|
269
|
-
//
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// 加入缓存
|
|
273
|
-
// const cacheSet = new Set(caches.value)
|
|
274
|
-
// if (routerAlive.value) {
|
|
275
|
-
// if (!cacheSet.has(cacheName)) {
|
|
276
|
-
// caches.value.push(cacheName)
|
|
277
|
-
// }
|
|
278
|
-
// }
|
|
279
|
-
addCache(cacheName)
|
|
280
|
-
return cacheComponent
|
|
281
|
-
}
|
|
282
|
-
const restoreScroller = (pageId: string) => {
|
|
283
|
-
const scroller = pageScroller.get(pageId)
|
|
284
|
-
if (scroller) {
|
|
285
|
-
for (const key of scroller.keys()) {
|
|
286
|
-
if (document.querySelector(key)) {
|
|
287
|
-
const result = scroller.get(key)!
|
|
288
|
-
document.querySelector(key)!.scrollTop = result.top
|
|
289
|
-
document.querySelector(key)!.scrollLeft = result.left
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
const saveScroller = (pageId: string) => {
|
|
295
|
-
const scroller = pageScroller.get(pageId)
|
|
296
|
-
if (scroller) {
|
|
297
|
-
for (const key of scroller.keys()) {
|
|
298
|
-
const result = {
|
|
299
|
-
top: document.querySelector(key)?.scrollTop ?? 0,
|
|
300
|
-
left: document.querySelector(key)?.scrollLeft ?? 0
|
|
301
|
-
}
|
|
302
|
-
scroller.set(key, result)
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
const removeScroller = (pageId: string) => {
|
|
308
|
-
const scroller = pageScroller.get(pageId)!
|
|
309
|
-
if (scroller) {
|
|
310
|
-
scroller.clear()
|
|
311
|
-
pageScroller.delete(pageId)
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
const addPageScroller = (pageId: string, ...scrollerIds: string[]) => {
|
|
315
|
-
if (!pageScroller.has(pageId)) {
|
|
316
|
-
pageScroller.set(pageId, new Map<string, number>())
|
|
317
|
-
}
|
|
318
|
-
const scroller = pageScroller.get(pageId)!
|
|
319
|
-
for (const sId of scrollerIds) {
|
|
320
|
-
scroller.set(sId, { top: 0, left: 0 })
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
// use new url for renwTab like refresh tab
|
|
324
|
-
const renewTab = (tab: ITabData) => {
|
|
325
|
-
const currentTab = getTab(tab.id!)
|
|
326
|
-
for (const item of currentTab!.pages.list()) {
|
|
327
|
-
// removeComponent(item.id)
|
|
328
|
-
markDeletableCache(item.id)
|
|
329
|
-
}
|
|
330
|
-
removeDeletableCache()
|
|
331
|
-
currentTab!.pages.clear()
|
|
332
|
-
}
|
|
333
|
-
/**
|
|
334
|
-
* if id is null , then remove all tab that deleted is true
|
|
335
|
-
* @param id
|
|
336
|
-
*/
|
|
337
|
-
const removeTab = (id: string): string => {
|
|
338
|
-
let activeTabId = ''
|
|
339
|
-
const currentTab = getTab(id)
|
|
340
|
-
for (let i = tabs.value.length - 1; i >= 0; i--) {
|
|
341
|
-
if (id === unref(tabs)[i].id) {
|
|
342
|
-
//if it's not closable then return
|
|
343
|
-
if (!unref(tabs)[i].closable) {
|
|
344
|
-
return id
|
|
345
|
-
}
|
|
346
|
-
for (const item of unref(tabs)[i].pages.list()) {
|
|
347
|
-
// removeComponent(item.id)
|
|
348
|
-
markDeletableCache(item.id)
|
|
349
|
-
deletableTab.add(unref(tabs)[i].id)
|
|
350
|
-
}
|
|
351
|
-
unref(tabs)[i].pages.clear()
|
|
352
|
-
if (tabs.value.length > 1 && unref(tabs)[i].active) {
|
|
353
|
-
if (i === 0) {
|
|
354
|
-
activeTabId = unref(tabs)[i + 1].id
|
|
355
|
-
} else {
|
|
356
|
-
activeTabId = unref(tabs)[i - 1].id
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
unref(tabs).splice(i, 1)
|
|
360
|
-
|
|
361
|
-
break
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
if (activeTabId !== '') {
|
|
366
|
-
emitter.emit(MittType.TAB_ACTIVE, { id: activeTabId })
|
|
367
|
-
// active(activeTabId)
|
|
368
|
-
}
|
|
369
|
-
// if remove inactive tab,then we need remove the cache manually.
|
|
370
|
-
|
|
371
|
-
if (!currentTab?.active) {
|
|
372
|
-
removeDeletableCache()
|
|
373
|
-
deletableTab.clear()
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
return activeTabId
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
const removeAllTabs = () => {
|
|
380
|
-
const uTabs = unref(tabs)
|
|
381
|
-
for (let i = uTabs.length - 1; i >= 0; i--) {
|
|
382
|
-
if (uTabs[i].closable) {
|
|
383
|
-
for (const item of uTabs[i].pages.list()) {
|
|
384
|
-
// removeComponent(item.id)
|
|
385
|
-
markDeletableCache(item.id)
|
|
386
|
-
deletableTab.add(uTabs[i].id)
|
|
387
|
-
}
|
|
388
|
-
unref(tabs)[i].pages.clear()
|
|
389
|
-
|
|
390
|
-
unref(tabs).splice(i, 1)
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
for (const stay of uTabs) {
|
|
394
|
-
if (stay.active) {
|
|
395
|
-
removeDeletableCache()
|
|
396
|
-
deletableTab.clear()
|
|
397
|
-
return
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
// 如果都是非Active状态,就把最后一个active
|
|
401
|
-
emitter.emit(MittType.TAB_ACTIVE, { id: uTabs[uTabs.length - 1].id })
|
|
402
|
-
// active(uTabs[uTabs.length - 1].id)
|
|
403
|
-
}
|
|
404
|
-
const removeOtherTabs = (id: string) => {
|
|
405
|
-
const uTabs = unref(tabs)
|
|
406
|
-
let activeTab
|
|
407
|
-
for (let i = uTabs.length - 1; i >= 0; i--) {
|
|
408
|
-
if (uTabs[i].id === id) {
|
|
409
|
-
activeTab = uTabs[i]
|
|
410
|
-
} else if (uTabs[i].closable && uTabs[i].id !== id) {
|
|
411
|
-
for (const item of uTabs[i].pages.list()) {
|
|
412
|
-
// removeComponent(item.id)
|
|
413
|
-
markDeletableCache(item.id)
|
|
414
|
-
deletableTab.add(uTabs[i].id)
|
|
415
|
-
}
|
|
416
|
-
unref(tabs)[i].pages.clear()
|
|
417
|
-
unref(tabs).splice(i, 1)
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
if (!activeTab!.active) {
|
|
421
|
-
emitter.emit(MittType.TAB_ACTIVE, { id })
|
|
422
|
-
// active(id)
|
|
423
|
-
} else {
|
|
424
|
-
removeDeletableCache()
|
|
425
|
-
deletableTab.clear()
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
/**
|
|
429
|
-
* 关闭左边
|
|
430
|
-
* @param id
|
|
431
|
-
*/
|
|
432
|
-
const removeLeftTabs = (id: string) => {
|
|
433
|
-
let startIndex = -1
|
|
434
|
-
const uTabs = unref(tabs)
|
|
435
|
-
for (let i = 0; i < uTabs.length; i++) {
|
|
436
|
-
if (uTabs[i].id === id) {
|
|
437
|
-
startIndex = i - 1
|
|
438
|
-
break
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
for (let i = startIndex; i >= 0; i--) {
|
|
442
|
-
if (uTabs[i].closable) {
|
|
443
|
-
for (const item of uTabs[i].pages.list()) {
|
|
444
|
-
// removeComponent(item.id)
|
|
445
|
-
markDeletableCache(item.id)
|
|
446
|
-
deletableTab.add(uTabs[i].id)
|
|
447
|
-
}
|
|
448
|
-
unref(tabs)[i].pages.clear()
|
|
449
|
-
unref(tabs).splice(i, 1)
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
for (const stay of uTabs) {
|
|
453
|
-
if (stay.active) {
|
|
454
|
-
removeDeletableCache()
|
|
455
|
-
deletableTab.clear()
|
|
456
|
-
return
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
// 如果都是非Active状态,就把最后一个active
|
|
460
|
-
emitter.emit(MittType.TAB_ACTIVE, { id: uTabs[0].id })
|
|
461
|
-
// active(uTabs[0].id)
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
/**
|
|
465
|
-
* 关闭右边
|
|
466
|
-
* @param id
|
|
467
|
-
*/
|
|
468
|
-
const removeRightTabs = (id: string) => {
|
|
469
|
-
const uTabs = unref(tabs)
|
|
470
|
-
let startIndex = uTabs.length
|
|
471
|
-
for (let i = 0; i < uTabs.length; i++) {
|
|
472
|
-
if (uTabs[i].id === id) {
|
|
473
|
-
startIndex = i + 1
|
|
474
|
-
break
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
for (let i = uTabs.length - 1; i >= startIndex; i--) {
|
|
478
|
-
if (uTabs[i].closable) {
|
|
479
|
-
for (const item of uTabs[i].pages.list()) {
|
|
480
|
-
// removeComponent(item.id)
|
|
481
|
-
markDeletableCache(item.id)
|
|
482
|
-
deletableTab.add(uTabs[i].id)
|
|
483
|
-
}
|
|
484
|
-
unref(tabs)[i].pages.clear()
|
|
485
|
-
unref(tabs).splice(i, 1)
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
for (const stay of uTabs) {
|
|
489
|
-
if (stay.active) {
|
|
490
|
-
removeDeletableCache()
|
|
491
|
-
deletableTab.clear()
|
|
492
|
-
return
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
emitter.emit(MittType.TAB_ACTIVE, { id: uTabs[uTabs.length - 1].id })
|
|
496
|
-
// active(uTabs[uTabs.length - 1].id)
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
/**
|
|
500
|
-
* 刷新
|
|
501
|
-
*/
|
|
502
|
-
const refreshTab = (id: string) => {
|
|
503
|
-
// const uTabs = unref(tabs)
|
|
504
|
-
for (const uTabs of unref(tabs)) {
|
|
505
|
-
if (uTabs.id === id) {
|
|
506
|
-
const currentPageId = uTabs.pages.peek()?.id
|
|
507
|
-
for (let i = caches.value.length - 1; i >= 0; i--) {
|
|
508
|
-
const cacheId = caches.value[i]
|
|
509
|
-
if (cacheId === currentPageId) {
|
|
510
|
-
caches.value.splice(i, 1)
|
|
511
|
-
// 如果要刷新的是显示的TAB
|
|
512
|
-
if (uTabs.active) {
|
|
513
|
-
pageShown.value = false
|
|
514
|
-
nextTick(() => {
|
|
515
|
-
pageShown.value = true
|
|
516
|
-
})
|
|
517
|
-
}
|
|
518
|
-
break
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
break
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
/**
|
|
526
|
-
* 全部刷新
|
|
527
|
-
*/
|
|
528
|
-
const refreshAllTabs = () => {
|
|
529
|
-
const refreshPage = new Set<string>()
|
|
530
|
-
tabs.value.forEach((value) => {
|
|
531
|
-
refreshPage.add(value.pages.peek()!.id)
|
|
532
|
-
})
|
|
533
|
-
for (let i = caches.value.length - 1; i >= 0; i--) {
|
|
534
|
-
const cacheId = caches.value[i]
|
|
535
|
-
if (refreshPage.has(cacheId)) {
|
|
536
|
-
caches.value.splice(i, 1)
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
nextTick(() => {
|
|
540
|
-
pageShown.value = false
|
|
541
|
-
nextTick(() => {
|
|
542
|
-
setTimeout(() => {
|
|
543
|
-
pageShown.value = true
|
|
544
|
-
}, 300)
|
|
545
|
-
})
|
|
546
|
-
})
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
const addComponent = (id: string, comp: DefineComponent) => {
|
|
550
|
-
components.set(id, comp)
|
|
551
|
-
}
|
|
552
|
-
const getComponent = (id: string) => {
|
|
553
|
-
return components.get(id)
|
|
554
|
-
}
|
|
555
|
-
const removeComponent = (id: string) => {
|
|
556
|
-
components.delete(id)
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
/**
|
|
560
|
-
* Delete the cache after new Page loaded.
|
|
561
|
-
* @param cacheName
|
|
562
|
-
*/
|
|
563
|
-
const markDeletableCache = (cacheName: string) => {
|
|
564
|
-
deletableCache.add(cacheName)
|
|
565
|
-
}
|
|
566
|
-
const removeDeletableCache = () => {
|
|
567
|
-
if(deletableCache.size>0){
|
|
568
|
-
for (let i = caches.value.length - 1; i >= 0; i--) {
|
|
569
|
-
if (deletableCache.has(caches.value[i])) {
|
|
570
|
-
unref(caches).splice(i, 1)
|
|
571
|
-
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
for(const cacheName of deletableCache) {
|
|
575
|
-
removeComponent(cacheName)
|
|
576
|
-
}
|
|
577
|
-
deletableCache.clear()
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
}
|
|
581
|
-
const removeCache = (cacheName: string) => {
|
|
582
|
-
for (let i = caches.value.length - 1; i >= 0; i--) {
|
|
583
|
-
if (cacheName === caches.value[i]) {
|
|
584
|
-
unref(caches).splice(i, 1)
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
const addCache = (cacheName: string) => {
|
|
589
|
-
const cacheSet = new Set(caches.value)
|
|
590
|
-
if (!cacheSet.has(cacheName)) {
|
|
591
|
-
caches.value.push(cacheName)
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
/**
|
|
596
|
-
* active the tab,
|
|
597
|
-
* @param id
|
|
598
|
-
* @param route
|
|
599
|
-
* @return true if already actived
|
|
600
|
-
*/
|
|
601
|
-
const active = (id: string, route = true) => {
|
|
602
|
-
// return new Promise((resolve)=>{
|
|
603
|
-
emitter.emit('FORWARD')
|
|
604
|
-
for (let i = tabs.value.length - 1; i >= 0; i--) {
|
|
605
|
-
const tab = tabs.value[i] as ITabItem
|
|
606
|
-
if (tab.id === id) {
|
|
607
|
-
if (tab.active) {
|
|
608
|
-
break
|
|
609
|
-
} else {
|
|
610
|
-
tab.active = true
|
|
611
|
-
// pageShown.value = false
|
|
612
|
-
updateSession(tab)
|
|
613
|
-
if (route) {
|
|
614
|
-
const top = tab.pages.peek()
|
|
615
|
-
router.push({
|
|
616
|
-
path: top!.path,
|
|
617
|
-
query: top!.query
|
|
618
|
-
})
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
} else {
|
|
622
|
-
tabs.value[i].active = false
|
|
623
|
-
}
|
|
624
|
-
}
|
|
625
|
-
// resolve(true)
|
|
626
|
-
// })
|
|
627
|
-
}
|
|
628
|
-
/**
|
|
629
|
-
* save current tab info into Browser's session
|
|
630
|
-
* @param id
|
|
631
|
-
*/
|
|
632
|
-
const updateSession = (tab: ITabItem) => {
|
|
633
|
-
// window.sessionStorage.setItem('tabItems', JSON.stringify(currentItems?.values()))
|
|
634
|
-
window.sessionStorage.setItem(sessionPrefix+SESSION_TAB_NAME, JSON.stringify(tab))
|
|
635
|
-
}
|
|
636
|
-
const clearSession = () => {
|
|
637
|
-
// window.sessionStorage.setItem('tabItems', JSON.stringify(currentItems?.values()))
|
|
638
|
-
window.sessionStorage.removeItem(sessionPrefix+SESSION_TAB_NAME)
|
|
639
|
-
}
|
|
640
|
-
const reset = () => {
|
|
641
|
-
removeAllTabs()
|
|
642
|
-
// pageShown.value = false
|
|
643
|
-
// destroy()
|
|
644
|
-
// nextTick(() => {
|
|
645
|
-
// // unref(tabs).push(...defaultTabs)
|
|
646
|
-
// // emitter.emit(MittType.TAB_ACTIVE, { id: defaultTabs[0].id! })
|
|
647
|
-
// // // pageShown.value = false
|
|
648
|
-
// nextTick(() => {
|
|
649
|
-
// pageShown.value = true
|
|
650
|
-
// })
|
|
651
|
-
// })
|
|
652
|
-
// active(defaultTabs[0].id)
|
|
653
|
-
}
|
|
654
|
-
const destroy = () => {
|
|
655
|
-
unref(tabs).splice(0)
|
|
656
|
-
deletableCache.clear()
|
|
657
|
-
deletableTab.clear()
|
|
658
|
-
unref(caches).splice(0)
|
|
659
|
-
components.clear()
|
|
660
|
-
clearSession()
|
|
661
|
-
}
|
|
662
|
-
const setMaxSize = (size: number) => {
|
|
663
|
-
max = size
|
|
664
|
-
}
|
|
665
|
-
const setGlobalScroll = (globalScroll: boolean) => {
|
|
666
|
-
scrollbar = globalScroll
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
const setSessionPrefix = (prefix: string) => {
|
|
670
|
-
sessionPrefix = prefix
|
|
671
|
-
}
|
|
672
|
-
return {
|
|
673
|
-
tabs,
|
|
674
|
-
caches,
|
|
675
|
-
pageShown,
|
|
676
|
-
initialed,
|
|
677
|
-
setMaxSize,
|
|
678
|
-
canAddTab,
|
|
679
|
-
initial,
|
|
680
|
-
size,
|
|
681
|
-
active,
|
|
682
|
-
destroy,
|
|
683
|
-
reset,
|
|
684
|
-
addCache,
|
|
685
|
-
removeCache,
|
|
686
|
-
getTab,
|
|
687
|
-
addTab,
|
|
688
|
-
removeTab,
|
|
689
|
-
removeAllTabs,
|
|
690
|
-
removeLeftTabs,
|
|
691
|
-
removeRightTabs,
|
|
692
|
-
removeOtherTabs,
|
|
693
|
-
hasTab,
|
|
694
|
-
renewTab,
|
|
695
|
-
addPage,
|
|
696
|
-
addComponent,
|
|
697
|
-
getComponent,
|
|
698
|
-
removeComponent,
|
|
699
|
-
markDeletableCache,
|
|
700
|
-
removeDeletableCache,
|
|
701
|
-
refreshTab,
|
|
702
|
-
refreshAllTabs,
|
|
703
|
-
addPageScroller,
|
|
704
|
-
setGlobalScroll,
|
|
705
|
-
clearSession,
|
|
706
|
-
setSessionPrefix
|
|
707
|
-
}
|
|
708
|
-
}
|