vue-stack-tabs 0.1.50 → 1.0.0

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