vue-stack-tabs 0.1.37 → 0.1.39
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/dist/favicon.svg +9 -9
- package/dist/src/lib/StackTabs.vue.d.ts +7 -52
- package/dist/src/lib/components/ContextMenu/ContextMenuItem.vue.d.ts +3 -12
- package/dist/src/lib/components/ContextMenu/index.vue.d.ts +4 -29
- package/dist/src/lib/components/PageLoading.vue.d.ts +3 -12
- package/dist/src/lib/components/TabHeader/TabHeaderButton.vue.d.ts +4 -29
- package/dist/src/lib/components/TabHeader/TabHeaderItem.vue.d.ts +7 -16
- package/dist/src/lib/components/TabHeader/TabHeaderScroll.vue.d.ts +5 -30
- package/dist/src/lib/components/TabHeader/index.vue.d.ts +7 -38
- package/dist/src/lib/hooks/useContextMenu.d.ts +1 -1
- package/dist/src/lib/hooks/useStackTab.d.ts +1 -0
- package/dist/src/lib/hooks/useTabpanel.d.ts +21 -2
- package/dist/src/lib/iframe.vue.d.ts +1 -1
- package/dist/vue-stack-tabs.es.js +461 -461
- package/dist/vue-stack-tabs.umd.js +2 -2
- package/package.json +23 -23
- package/src/lib/StackTabs.vue +135 -135
- package/src/lib/assets/style/common/mixins.scss +4 -4
- package/src/lib/assets/style/common/var.scss +29 -28
- package/src/lib/assets/style/icon.scss +1 -1
- package/src/lib/assets/style/index.scss +4 -4
- package/src/lib/assets/style/stackTab.scss +64 -64
- package/src/lib/assets/style/transition.scss +62 -62
- package/src/lib/hooks/useStackTab.ts +119 -116
- package/src/lib/hooks/useTabRouter.ts +103 -103
- package/src/lib/hooks/useTabpanel.tsx +685 -685
- package/src/lib/utils/TabIdHelper.ts +70 -70
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
@use 'sass:math';
|
|
2
|
-
@
|
|
3
|
-
@
|
|
2
|
+
@use 'common/var' as *;
|
|
3
|
+
@use 'common/mixins';
|
|
4
4
|
|
|
5
5
|
.stack-tab {
|
|
6
6
|
display: flex;
|
|
7
7
|
min-height: 300px;
|
|
8
|
-
background-color:
|
|
8
|
+
background-color: $stack-tab-background-color-base;
|
|
9
9
|
flex-direction: column;
|
|
10
10
|
grid-gap: 5px;
|
|
11
11
|
|
|
@@ -30,29 +30,29 @@
|
|
|
30
30
|
//蒙版按钮
|
|
31
31
|
&__mask-button {
|
|
32
32
|
height: 100%;
|
|
33
|
-
width:
|
|
34
|
-
background-color:
|
|
33
|
+
width: $stack-tab-button-size;
|
|
34
|
+
background-color: $stack-tab-text-color;
|
|
35
35
|
margin: 0 5px;
|
|
36
|
-
transition:
|
|
36
|
+
transition: $stack-tab__trans;
|
|
37
37
|
|
|
38
38
|
.stack-tab__header-button[disabled] & {
|
|
39
39
|
cursor: not-allowed;
|
|
40
|
-
background-color:
|
|
40
|
+
background-color: $stack-tab-color-disabled;
|
|
41
41
|
transition: none;
|
|
42
42
|
//pointer-events: none;
|
|
43
43
|
}
|
|
44
44
|
&:hover {
|
|
45
|
-
background-color:
|
|
45
|
+
background-color: $stack-tab-color-primary;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
&:active {
|
|
49
49
|
// cursor: pointer;
|
|
50
|
-
background-color:
|
|
50
|
+
background-color: $stack-tab-color-primary-activate;
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
&__button {
|
|
54
|
-
height:
|
|
55
|
-
width:
|
|
54
|
+
height: $stack-tab-button-size;
|
|
55
|
+
width: $stack-tab-button-size;
|
|
56
56
|
margin: 0 5px;
|
|
57
57
|
}
|
|
58
58
|
|
|
@@ -60,25 +60,25 @@
|
|
|
60
60
|
position: relative;
|
|
61
61
|
display: flex;
|
|
62
62
|
width: 100%;
|
|
63
|
-
height:
|
|
64
|
-
border-bottom: 1px solid
|
|
63
|
+
height: $stack-tab-head-height;
|
|
64
|
+
border-bottom: 1px solid $stack-tab-border-color;
|
|
65
65
|
box-sizing: border-box;
|
|
66
66
|
//user-select: none;
|
|
67
67
|
|
|
68
68
|
//tab header上面的按钮
|
|
69
69
|
&-button {
|
|
70
70
|
z-index: 2;
|
|
71
|
-
height:
|
|
71
|
+
height: $stack-tab-head-height;
|
|
72
72
|
width: fit-content;
|
|
73
73
|
overflow: hidden;
|
|
74
|
-
background-color:
|
|
74
|
+
background-color: $stack-tab-background-color-base;
|
|
75
75
|
cursor: pointer;
|
|
76
76
|
display: flex;
|
|
77
77
|
align-items: center;
|
|
78
78
|
|
|
79
79
|
//按钮禁用样式
|
|
80
80
|
&[disabled] {
|
|
81
|
-
background-color:
|
|
81
|
+
background-color: $stack-tab-background-color-inactive;
|
|
82
82
|
box-shadow: none;
|
|
83
83
|
cursor: not-allowed;
|
|
84
84
|
}
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
&__scroll {
|
|
89
89
|
position: relative;
|
|
90
90
|
flex: 1 1 0;
|
|
91
|
-
height:
|
|
91
|
+
height: $stack-tab-head-height;
|
|
92
92
|
overflow: hidden;
|
|
93
93
|
|
|
94
94
|
&-container {
|
|
@@ -109,11 +109,11 @@
|
|
|
109
109
|
bottom: 0;
|
|
110
110
|
left: 0;
|
|
111
111
|
/*z-index: 2;*/
|
|
112
|
-
height:
|
|
112
|
+
height: $stack-tab-scroll-height;
|
|
113
113
|
background-color: rgb(0 0 0 / 10%);
|
|
114
|
-
border-radius:
|
|
114
|
+
border-radius: $stack-tab-scroll-border-radius;
|
|
115
115
|
opacity: 0;
|
|
116
|
-
transition:
|
|
116
|
+
transition: $stack-tab__trans;
|
|
117
117
|
|
|
118
118
|
.stack-tab__scroll:hover &,
|
|
119
119
|
&.is-dragging {
|
|
@@ -127,7 +127,7 @@
|
|
|
127
127
|
height: 100%;
|
|
128
128
|
background-color: rgba(0, 0, 0, 0.1);
|
|
129
129
|
|
|
130
|
-
border-radius:
|
|
130
|
+
border-radius: $stack-tab-scroll-border-radius;
|
|
131
131
|
transition: background-color 0.3s ease-in-out;
|
|
132
132
|
|
|
133
133
|
&:hover {
|
|
@@ -139,7 +139,7 @@
|
|
|
139
139
|
|
|
140
140
|
.stack-tab__scrollbar.is-dragging &,
|
|
141
141
|
&:hover {
|
|
142
|
-
background-color:
|
|
142
|
+
background-color: $stack-tab-color-primary !important;
|
|
143
143
|
}
|
|
144
144
|
}
|
|
145
145
|
|
|
@@ -163,15 +163,15 @@
|
|
|
163
163
|
&__item {
|
|
164
164
|
position: relative;
|
|
165
165
|
display: flex;
|
|
166
|
-
padding: 0
|
|
167
|
-
font-size:
|
|
168
|
-
color:
|
|
166
|
+
padding: 0 $stack-tab-padding;
|
|
167
|
+
font-size: $stack-tab-font-size;
|
|
168
|
+
color: $stack-tab-text-color;
|
|
169
169
|
cursor: pointer;
|
|
170
|
-
background-color:
|
|
171
|
-
border:
|
|
170
|
+
background-color: $stack-tab-background-color-inactive;
|
|
171
|
+
border: $stack-tab-border;
|
|
172
172
|
border-left: none;
|
|
173
173
|
border-radius: 8px 8px 0 0;
|
|
174
|
-
transition:
|
|
174
|
+
transition: $stack-tab__trans;
|
|
175
175
|
user-select: none;
|
|
176
176
|
flex: none;
|
|
177
177
|
align-items: center;
|
|
@@ -180,7 +180,7 @@
|
|
|
180
180
|
margin-top: 5px;
|
|
181
181
|
|
|
182
182
|
&:first-child {
|
|
183
|
-
border-left:
|
|
183
|
+
border-left: $stack-tab-border;
|
|
184
184
|
}
|
|
185
185
|
|
|
186
186
|
/*
|
|
@@ -195,23 +195,23 @@
|
|
|
195
195
|
*/
|
|
196
196
|
&.is-active {
|
|
197
197
|
z-index: 1;
|
|
198
|
-
background-color:
|
|
198
|
+
background-color: $stack-tab-background-color-base;
|
|
199
199
|
border-bottom-color: #fff;
|
|
200
|
-
box-shadow:
|
|
200
|
+
box-shadow: $stack-tab-shadow-left, $stack-tab-shadow-right;
|
|
201
201
|
margin-top: unset;
|
|
202
202
|
}
|
|
203
203
|
|
|
204
204
|
&:hover,
|
|
205
205
|
&.is-active {
|
|
206
|
-
color:
|
|
206
|
+
color: $stack-tab-color-primary;
|
|
207
207
|
|
|
208
208
|
&.is-icon {
|
|
209
209
|
padding: 0
|
|
210
|
-
(
|
|
210
|
+
($stack-tab-padding - math.div($stack-tab-button-size + $stack-tab-icon-margin, 2));
|
|
211
211
|
|
|
212
212
|
.stack-tab__item-button {
|
|
213
|
-
width:
|
|
214
|
-
margin-left:
|
|
213
|
+
width: $stack-tab-button-size;
|
|
214
|
+
margin-left: $stack-tab-icon-margin;
|
|
215
215
|
}
|
|
216
216
|
}
|
|
217
217
|
}
|
|
@@ -245,18 +245,18 @@
|
|
|
245
245
|
&-button {
|
|
246
246
|
height: 100%;
|
|
247
247
|
width: 0;
|
|
248
|
-
background-color:
|
|
249
|
-
transition:
|
|
248
|
+
background-color: $stack-tab-text-color;
|
|
249
|
+
transition: $stack-tab__trans;
|
|
250
250
|
|
|
251
251
|
&:hover {
|
|
252
|
-
background-color:
|
|
252
|
+
background-color: $stack-tab-color-primary;
|
|
253
253
|
}
|
|
254
254
|
|
|
255
255
|
&:active {
|
|
256
256
|
/*
|
|
257
257
|
cursor: pointer;
|
|
258
258
|
*/
|
|
259
|
-
background-color:
|
|
259
|
+
background-color: $stack-tab-color-primary-activate;
|
|
260
260
|
}
|
|
261
261
|
}
|
|
262
262
|
}
|
|
@@ -278,17 +278,17 @@
|
|
|
278
278
|
line-height: 0.4rem;
|
|
279
279
|
color: #fff;
|
|
280
280
|
text-align: center;
|
|
281
|
-
border: 1px solid
|
|
281
|
+
border: 1px solid $stack-tab-background-color-base;
|
|
282
282
|
border-radius: 0.5rem;
|
|
283
283
|
transform: translateX(100%) translateY(-50%);
|
|
284
284
|
box-sizing: border-box;
|
|
285
285
|
|
|
286
286
|
&.default {
|
|
287
|
-
background:
|
|
287
|
+
background: $stack-tab-color-danger;
|
|
288
288
|
}
|
|
289
289
|
|
|
290
290
|
&.primary {
|
|
291
|
-
background:
|
|
291
|
+
background: $stack-tab-color-primary;
|
|
292
292
|
}
|
|
293
293
|
}
|
|
294
294
|
}
|
|
@@ -312,11 +312,11 @@
|
|
|
312
312
|
z-index: 999;
|
|
313
313
|
min-width: 120px;
|
|
314
314
|
padding: 8px;
|
|
315
|
-
font-size:
|
|
315
|
+
font-size: $stack-tab-font-size;
|
|
316
316
|
background: #fff;
|
|
317
|
-
border:
|
|
317
|
+
border: $stack-tab-border;
|
|
318
318
|
border-radius: 10px 0;
|
|
319
|
-
box-shadow:
|
|
319
|
+
box-shadow: $stack-tab-shadow-context-menu;
|
|
320
320
|
transform-origin: left top;
|
|
321
321
|
transition: all 0.25s ease-in;
|
|
322
322
|
|
|
@@ -326,7 +326,7 @@
|
|
|
326
326
|
align-items: center;
|
|
327
327
|
padding: 0 10px;
|
|
328
328
|
line-height: 30px;
|
|
329
|
-
color:
|
|
329
|
+
color: $stack-tab-text-color;
|
|
330
330
|
cursor: pointer;
|
|
331
331
|
border-radius: 10px 0;
|
|
332
332
|
transition: all 0.2s ease-in-out;
|
|
@@ -334,46 +334,46 @@
|
|
|
334
334
|
|
|
335
335
|
&:hover,
|
|
336
336
|
&:active {
|
|
337
|
-
color:
|
|
338
|
-
background-color:
|
|
337
|
+
color: $stack-tab-color-white;
|
|
338
|
+
background-color: $stack-tab-color-primary;
|
|
339
339
|
|
|
340
340
|
.svg-mask {
|
|
341
|
-
background-color:
|
|
341
|
+
background-color: $stack-tab-color-white;
|
|
342
342
|
}
|
|
343
343
|
}
|
|
344
344
|
|
|
345
345
|
&[disabled] {
|
|
346
|
-
color:
|
|
346
|
+
color: $stack-tab-color-disabled;
|
|
347
347
|
pointer-events: none;
|
|
348
348
|
cursor: default;
|
|
349
349
|
background: none;
|
|
350
350
|
|
|
351
351
|
.svg-mask {
|
|
352
|
-
background-color:
|
|
352
|
+
background-color: $stack-tab-color-disabled;
|
|
353
353
|
}
|
|
354
354
|
}
|
|
355
355
|
}
|
|
356
356
|
|
|
357
357
|
&-icon {
|
|
358
|
-
width:
|
|
359
|
-
height:
|
|
358
|
+
width: $stack-tab-font-size;
|
|
359
|
+
height: $stack-tab-font-size;
|
|
360
360
|
transition: all 0.2s ease-in-out;
|
|
361
361
|
|
|
362
362
|
&.svg-mask {
|
|
363
|
-
width:
|
|
364
|
-
height:
|
|
365
|
-
background-color:
|
|
363
|
+
width: $stack-tab-font-size;
|
|
364
|
+
height: $stack-tab-font-size;
|
|
365
|
+
background-color: $stack-tab-text-color;
|
|
366
366
|
}
|
|
367
367
|
}
|
|
368
368
|
}
|
|
369
369
|
}
|
|
370
370
|
|
|
371
371
|
.stack-tab__shadow-left {
|
|
372
|
-
box-shadow:
|
|
372
|
+
box-shadow: $stack-tab-shadow-left;
|
|
373
373
|
}
|
|
374
374
|
|
|
375
375
|
.stack-tab__shadow-right {
|
|
376
|
-
box-shadow:
|
|
376
|
+
box-shadow: $stack-tab-shadow-right;
|
|
377
377
|
}
|
|
378
378
|
|
|
379
379
|
/**
|
|
@@ -381,15 +381,15 @@
|
|
|
381
381
|
*/
|
|
382
382
|
.stack-tab__shadow-inset {
|
|
383
383
|
&-left::after {
|
|
384
|
-
@include insetShadow();
|
|
385
|
-
box-shadow:
|
|
384
|
+
@include mixins.insetShadow();
|
|
385
|
+
box-shadow: $stack-tab-shadow-left-inset;
|
|
386
386
|
}
|
|
387
387
|
&-right::after {
|
|
388
|
-
@include insetShadow();
|
|
389
|
-
box-shadow:
|
|
388
|
+
@include mixins.insetShadow();
|
|
389
|
+
box-shadow: $stack-tab-shadow-right-inset;
|
|
390
390
|
}
|
|
391
391
|
&-all::after {
|
|
392
|
-
@include insetShadow();
|
|
393
|
-
box-shadow:
|
|
392
|
+
@include mixins.insetShadow();
|
|
393
|
+
box-shadow: $stack-tab-shadow-left-inset, $stack-tab-shadow-right-inset;
|
|
394
394
|
}
|
|
395
395
|
}
|
|
@@ -1,62 +1,62 @@
|
|
|
1
|
-
/*
|
|
2
|
-
transition 过渡样式
|
|
3
|
-
*/
|
|
4
|
-
.stack-tab-zoom {
|
|
5
|
-
&-enter-active,
|
|
6
|
-
&-leave-active {
|
|
7
|
-
transition: all 0.3s ease-in-out;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
&-enter-from,
|
|
11
|
-
&-leave-to {
|
|
12
|
-
transform: scale(0);
|
|
13
|
-
opacity: 0;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/*
|
|
18
|
-
页面交换
|
|
19
|
-
*/
|
|
20
|
-
.stack-tab-swap {
|
|
21
|
-
$trans: 30px;
|
|
22
|
-
|
|
23
|
-
&-enter-active,
|
|
24
|
-
&-leave-active {
|
|
25
|
-
transition: all 0.3s ease-in-out;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
&-enter-from,
|
|
29
|
-
&-leave-to {
|
|
30
|
-
opacity: 0;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
&-enter-from {
|
|
34
|
-
transform: translateX($trans);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
&-leave-to {
|
|
38
|
-
transform: translateX(-$trans);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
.stack-tab-swap-back {
|
|
43
|
-
$trans: 30px;
|
|
44
|
-
|
|
45
|
-
&-enter-active,
|
|
46
|
-
&-leave-active {
|
|
47
|
-
transition: all 0.3s ease-in-out;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
&-enter-from,
|
|
51
|
-
&-leave-to {
|
|
52
|
-
opacity: 0;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
&-enter-from {
|
|
56
|
-
transform: translateX(-$trans);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
&-leave-to {
|
|
60
|
-
transform: translateX($trans);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
1
|
+
/*
|
|
2
|
+
transition 过渡样式
|
|
3
|
+
*/
|
|
4
|
+
.stack-tab-zoom {
|
|
5
|
+
&-enter-active,
|
|
6
|
+
&-leave-active {
|
|
7
|
+
transition: all 0.3s ease-in-out;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
&-enter-from,
|
|
11
|
+
&-leave-to {
|
|
12
|
+
transform: scale(0);
|
|
13
|
+
opacity: 0;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/*
|
|
18
|
+
页面交换
|
|
19
|
+
*/
|
|
20
|
+
.stack-tab-swap {
|
|
21
|
+
$trans: 30px;
|
|
22
|
+
|
|
23
|
+
&-enter-active,
|
|
24
|
+
&-leave-active {
|
|
25
|
+
transition: all 0.3s ease-in-out;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
&-enter-from,
|
|
29
|
+
&-leave-to {
|
|
30
|
+
opacity: 0;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
&-enter-from {
|
|
34
|
+
transform: translateX($trans);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
&-leave-to {
|
|
38
|
+
transform: translateX(-$trans);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.stack-tab-swap-back {
|
|
43
|
+
$trans: 30px;
|
|
44
|
+
|
|
45
|
+
&-enter-active,
|
|
46
|
+
&-leave-active {
|
|
47
|
+
transition: all 0.3s ease-in-out;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
&-enter-from,
|
|
51
|
+
&-leave-to {
|
|
52
|
+
opacity: 0;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
&-enter-from {
|
|
56
|
+
transform: translateX(-$trans);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
&-leave-to {
|
|
60
|
+
transform: translateX($trans);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -1,116 +1,119 @@
|
|
|
1
|
-
import { useRouter } from 'vue-router'
|
|
2
|
-
import useTabpanel from '../hooks/useTabpanel'
|
|
3
|
-
import { throttle } from 'throttle-debounce'
|
|
4
|
-
import type { ITabData } from '../model/TabModel'
|
|
5
|
-
import { defu } from 'defu'
|
|
6
|
-
|
|
7
|
-
import { encodeTabInfo } from '../utils/TabIdHelper'
|
|
8
|
-
import { uriDecode } from '../utils/UriHelper'
|
|
9
|
-
import { ulid } from 'ulid'
|
|
10
|
-
import { MittType, useEmitter } from './useTabMitt'
|
|
11
|
-
import { nextTick } from 'vue'
|
|
12
|
-
|
|
13
|
-
let iframePath: string
|
|
14
|
-
export default () => {
|
|
15
|
-
const router = useRouter()
|
|
16
|
-
const { active, hasTab, pageShown, reset, canAddTab, renewTab, getTab } = useTabpanel()
|
|
17
|
-
const emitter = useEmitter()
|
|
18
|
-
/**
|
|
19
|
-
* 打开新的TAB页面
|
|
20
|
-
* @param tab
|
|
21
|
-
* @param to
|
|
22
|
-
*/
|
|
23
|
-
const openNewTab = throttle(500, (tab: ITabData, renew = false) => {
|
|
24
|
-
return new Promise((resolve, reject) => {
|
|
25
|
-
if (!pageShown.value) {
|
|
26
|
-
reject()
|
|
27
|
-
return
|
|
28
|
-
}
|
|
29
|
-
const tabInfo = defu(tab, {
|
|
30
|
-
refreshable: true,
|
|
31
|
-
closable: true,
|
|
32
|
-
iframe: false
|
|
33
|
-
})
|
|
34
|
-
if (tabInfo.id && renew && hasTab(tabInfo.id!)) {
|
|
35
|
-
renewTab(tab)
|
|
36
|
-
const currentTab = getTab(tab.id!)
|
|
37
|
-
// if current tab is active, then must reload the component of router view for complete remove the cache!!!
|
|
38
|
-
if (currentTab?.active) {
|
|
39
|
-
pageShown.value = false
|
|
40
|
-
nextTick(() => {
|
|
41
|
-
pageShown.value = true
|
|
42
|
-
})
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* In the function of openNewTab, if the tab already 'ACTIVE' then do nothing.
|
|
47
|
-
*/
|
|
48
|
-
if (hasTab(tabInfo.id!) && !renew) {
|
|
49
|
-
emitter.emit(MittType.TAB_ACTIVE, { id: tabInfo.id! })
|
|
50
|
-
// active(tabInfo.id!)
|
|
51
|
-
resolve(tabInfo.id)
|
|
52
|
-
return
|
|
53
|
-
}
|
|
54
|
-
if (!tabInfo.id) {
|
|
55
|
-
tabInfo.id = ulid()
|
|
56
|
-
}
|
|
57
|
-
if (!canAddTab()) {
|
|
58
|
-
reject('Max Size')
|
|
59
|
-
return
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// if (initialed) {
|
|
63
|
-
// // 增加tab
|
|
64
|
-
// let activeTab: ITabItem | null = null
|
|
65
|
-
// for (const tab of unref(tabs)) {
|
|
66
|
-
// tab.active = false
|
|
67
|
-
// }
|
|
68
|
-
// activeTab = {
|
|
69
|
-
// id: tabInfo.id!,
|
|
70
|
-
// title: tabInfo.title,
|
|
71
|
-
// closable: tabInfo.closable!,
|
|
72
|
-
// refreshable: tabInfo.refreshable!,
|
|
73
|
-
// iframe: tabInfo.iframe!,
|
|
74
|
-
// url: tabInfo.iframe ? tab.path : null,
|
|
75
|
-
// active: true,
|
|
76
|
-
// pages: new Stack<ITabPage>()
|
|
77
|
-
// } as ITabItem
|
|
78
|
-
// addTab(activeTab).finally(() => {
|
|
79
|
-
// toPage(tab, tabInfo)
|
|
80
|
-
// resolve(tabInfo.id)
|
|
81
|
-
// })
|
|
82
|
-
// } else {
|
|
83
|
-
toPage(tab, tabInfo)
|
|
84
|
-
resolve(tabInfo.id)
|
|
85
|
-
// }
|
|
86
|
-
})
|
|
87
|
-
})
|
|
88
|
-
const toPage = (tab: ITabData, tabInfo: any) => {
|
|
89
|
-
const __tab = encodeTabInfo(tabInfo)
|
|
90
|
-
let query = defu(
|
|
91
|
-
{
|
|
92
|
-
__tab
|
|
93
|
-
},
|
|
94
|
-
tab.query
|
|
95
|
-
) as Record<string, string>
|
|
96
|
-
let path
|
|
97
|
-
if (!tab.iframe) {
|
|
98
|
-
const url = uriDecode(tab.path)
|
|
99
|
-
path = url.path
|
|
100
|
-
query = defu(url.query, query)
|
|
101
|
-
} else {
|
|
102
|
-
const __src = encodeURIComponent(tab.path as string)
|
|
103
|
-
path = iframePath
|
|
104
|
-
query['__src'] = __src
|
|
105
|
-
}
|
|
106
|
-
router.push({
|
|
107
|
-
path,
|
|
108
|
-
query
|
|
109
|
-
})
|
|
110
|
-
}
|
|
111
|
-
const setIFramePath = (path: string) => {
|
|
112
|
-
iframePath = path
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
1
|
+
import { useRouter } from 'vue-router'
|
|
2
|
+
import useTabpanel from '../hooks/useTabpanel'
|
|
3
|
+
import { throttle } from 'throttle-debounce'
|
|
4
|
+
import type { ITabData } from '../model/TabModel'
|
|
5
|
+
import { defu } from 'defu'
|
|
6
|
+
|
|
7
|
+
import { encodeTabInfo } from '../utils/TabIdHelper'
|
|
8
|
+
import { uriDecode } from '../utils/UriHelper'
|
|
9
|
+
import { ulid } from 'ulid'
|
|
10
|
+
import { MittType, useEmitter } from './useTabMitt'
|
|
11
|
+
import { nextTick } from 'vue'
|
|
12
|
+
|
|
13
|
+
let iframePath: string
|
|
14
|
+
export default () => {
|
|
15
|
+
const router = useRouter()
|
|
16
|
+
const { active, hasTab, pageShown, reset, canAddTab, renewTab, getTab } = useTabpanel()
|
|
17
|
+
const emitter = useEmitter()
|
|
18
|
+
/**
|
|
19
|
+
* 打开新的TAB页面
|
|
20
|
+
* @param tab
|
|
21
|
+
* @param to
|
|
22
|
+
*/
|
|
23
|
+
const openNewTab = throttle(500, (tab: ITabData, renew = false) => {
|
|
24
|
+
return new Promise((resolve, reject) => {
|
|
25
|
+
if (!pageShown.value) {
|
|
26
|
+
reject()
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
const tabInfo = defu(tab, {
|
|
30
|
+
refreshable: true,
|
|
31
|
+
closable: true,
|
|
32
|
+
iframe: false
|
|
33
|
+
})
|
|
34
|
+
if (tabInfo.id && renew && hasTab(tabInfo.id!)) {
|
|
35
|
+
renewTab(tab)
|
|
36
|
+
const currentTab = getTab(tab.id!)
|
|
37
|
+
// if current tab is active, then must reload the component of router view for complete remove the cache!!!
|
|
38
|
+
if (currentTab?.active) {
|
|
39
|
+
pageShown.value = false
|
|
40
|
+
nextTick(() => {
|
|
41
|
+
pageShown.value = true
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* In the function of openNewTab, if the tab already 'ACTIVE' then do nothing.
|
|
47
|
+
*/
|
|
48
|
+
if (hasTab(tabInfo.id!) && !renew) {
|
|
49
|
+
emitter.emit(MittType.TAB_ACTIVE, { id: tabInfo.id! })
|
|
50
|
+
// active(tabInfo.id!)
|
|
51
|
+
resolve(tabInfo.id)
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
if (!tabInfo.id) {
|
|
55
|
+
tabInfo.id = ulid()
|
|
56
|
+
}
|
|
57
|
+
if (!canAddTab()) {
|
|
58
|
+
reject('Max Size')
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// if (initialed) {
|
|
63
|
+
// // 增加tab
|
|
64
|
+
// let activeTab: ITabItem | null = null
|
|
65
|
+
// for (const tab of unref(tabs)) {
|
|
66
|
+
// tab.active = false
|
|
67
|
+
// }
|
|
68
|
+
// activeTab = {
|
|
69
|
+
// id: tabInfo.id!,
|
|
70
|
+
// title: tabInfo.title,
|
|
71
|
+
// closable: tabInfo.closable!,
|
|
72
|
+
// refreshable: tabInfo.refreshable!,
|
|
73
|
+
// iframe: tabInfo.iframe!,
|
|
74
|
+
// url: tabInfo.iframe ? tab.path : null,
|
|
75
|
+
// active: true,
|
|
76
|
+
// pages: new Stack<ITabPage>()
|
|
77
|
+
// } as ITabItem
|
|
78
|
+
// addTab(activeTab).finally(() => {
|
|
79
|
+
// toPage(tab, tabInfo)
|
|
80
|
+
// resolve(tabInfo.id)
|
|
81
|
+
// })
|
|
82
|
+
// } else {
|
|
83
|
+
toPage(tab, tabInfo)
|
|
84
|
+
resolve(tabInfo.id)
|
|
85
|
+
// }
|
|
86
|
+
})
|
|
87
|
+
})
|
|
88
|
+
const toPage = (tab: ITabData, tabInfo: any) => {
|
|
89
|
+
const __tab = encodeTabInfo(tabInfo)
|
|
90
|
+
let query = defu(
|
|
91
|
+
{
|
|
92
|
+
__tab
|
|
93
|
+
},
|
|
94
|
+
tab.query
|
|
95
|
+
) as Record<string, string>
|
|
96
|
+
let path
|
|
97
|
+
if (!tab.iframe) {
|
|
98
|
+
const url = uriDecode(tab.path)
|
|
99
|
+
path = url.path
|
|
100
|
+
query = defu(url.query, query)
|
|
101
|
+
} else {
|
|
102
|
+
const __src = encodeURIComponent(tab.path as string)
|
|
103
|
+
path = iframePath
|
|
104
|
+
query['__src'] = __src
|
|
105
|
+
}
|
|
106
|
+
router.push({
|
|
107
|
+
path,
|
|
108
|
+
query
|
|
109
|
+
})
|
|
110
|
+
}
|
|
111
|
+
const setIFramePath = (path: string) => {
|
|
112
|
+
iframePath = path
|
|
113
|
+
}
|
|
114
|
+
const getWrapper = () =>{
|
|
115
|
+
return document.getElementsByClassName('cache-page-wrapper')[0]
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return { openNewTab, setIFramePath, active, reset,getWrapper }
|
|
119
|
+
}
|