提交 | 用户 | age
|
27e50b
|
1 |
<template> |
V |
2 |
<div :class="getWrapClass"> |
|
3 |
<Tabs |
|
4 |
type="editable-card" |
|
5 |
size="small" |
|
6 |
:animated="false" |
|
7 |
:hideAdd="true" |
|
8 |
:tabBarGutter="3" |
|
9 |
:activeKey="activeKeyRef" |
|
10 |
@change="handleChange" |
|
11 |
@edit="handleEdit" |
|
12 |
> |
|
13 |
<template v-for="item in getTabsState" :key="item.query ? item.fullPath : item.path"> |
|
14 |
<TabPane :closable="!(item && item.meta && item.meta.affix)"> |
|
15 |
<template #tab> |
|
16 |
<TabContent :tabItem="item" /> |
|
17 |
</template> |
|
18 |
</TabPane> |
|
19 |
</template> |
a65ad9
|
20 |
|
3fcfac
|
21 |
<template #rightExtra v-if="getShowRedo || getShowQuick"> |
a65ad9
|
22 |
<TabRedo v-if="getShowRedo" /> |
215d8b
|
23 |
<TabContent isExtra :tabItem="$route" v-if="getShowQuick" /> |
0e7c57
|
24 |
<FoldButton v-if="getShowFold" /> |
27e50b
|
25 |
</template> |
V |
26 |
</Tabs> |
|
27 |
</div> |
|
28 |
</template> |
|
29 |
<script lang="ts"> |
e15b4f
|
30 |
import type { RouteLocationNormalized, RouteMeta } from 'vue-router'; |
215d8b
|
31 |
|
a65ad9
|
32 |
import { defineComponent, computed, unref, ref } from 'vue'; |
27e50b
|
33 |
|
V |
34 |
import { Tabs } from 'ant-design-vue'; |
|
35 |
import TabContent from './components/TabContent.vue'; |
2c6aa8
|
36 |
import FoldButton from './components/FoldButton.vue'; |
V |
37 |
import TabRedo from './components/TabRedo.vue'; |
27e50b
|
38 |
|
V |
39 |
import { useGo } from '/@/hooks/web/usePage'; |
|
40 |
|
215d8b
|
41 |
import { useMultipleTabStore } from '/@/store/modules/multipleTab'; |
V |
42 |
import { useUserStore } from '/@/store/modules/user'; |
27e50b
|
43 |
|
V |
44 |
import { initAffixTabs, useTabsDrag } from './useMultipleTabs'; |
|
45 |
import { useDesign } from '/@/hooks/web/useDesign'; |
a65ad9
|
46 |
import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting'; |
2c6aa8
|
47 |
|
V |
48 |
import { REDIRECT_NAME } from '/@/router/constant'; |
6bb19f
|
49 |
import { listenerRouteChange } from '/@/logics/mitt/routeChange'; |
819bcb
|
50 |
|
215d8b
|
51 |
import { useRouter } from 'vue-router'; |
27e50b
|
52 |
|
V |
53 |
export default defineComponent({ |
|
54 |
name: 'MultipleTabs', |
|
55 |
components: { |
215d8b
|
56 |
TabRedo, |
2c6aa8
|
57 |
FoldButton, |
27e50b
|
58 |
Tabs, |
V |
59 |
TabPane: Tabs.TabPane, |
|
60 |
TabContent, |
|
61 |
}, |
|
62 |
setup() { |
|
63 |
const affixTextList = initAffixTabs(); |
|
64 |
const activeKeyRef = ref(''); |
|
65 |
|
|
66 |
useTabsDrag(affixTextList); |
215d8b
|
67 |
const tabStore = useMultipleTabStore(); |
V |
68 |
const userStore = useUserStore(); |
|
69 |
const router = useRouter(); |
|
70 |
|
27e50b
|
71 |
const { prefixCls } = useDesign('multiple-tabs'); |
V |
72 |
const go = useGo(); |
0e7c57
|
73 |
const { getShowQuick, getShowRedo, getShowFold } = useMultipleTabSetting(); |
27e50b
|
74 |
|
819bcb
|
75 |
const getTabsState = computed(() => { |
215d8b
|
76 |
return tabStore.getTabList.filter((item) => !item.meta?.hideTab); |
819bcb
|
77 |
}); |
27e50b
|
78 |
|
a65ad9
|
79 |
const unClose = computed(() => unref(getTabsState).length === 1); |
27e50b
|
80 |
|
V |
81 |
const getWrapClass = computed(() => { |
|
82 |
return [ |
|
83 |
prefixCls, |
|
84 |
{ |
a65ad9
|
85 |
[`${prefixCls}--hide-close`]: unref(unClose), |
27e50b
|
86 |
}, |
V |
87 |
]; |
|
88 |
}); |
|
89 |
|
6bb19f
|
90 |
listenerRouteChange((route) => { |
a65ad9
|
91 |
const { name } = route; |
215d8b
|
92 |
if (name === REDIRECT_NAME || !route || !userStore.getToken) { |
V |
93 |
return; |
|
94 |
} |
27e50b
|
95 |
|
819bcb
|
96 |
const { path, fullPath, meta = {} } = route; |
e15b4f
|
97 |
const { currentActiveMenu, hideTab } = meta as RouteMeta; |
819bcb
|
98 |
const isHide = !hideTab ? null : currentActiveMenu; |
V |
99 |
const p = isHide || fullPath || path; |
a65ad9
|
100 |
if (activeKeyRef.value !== p) { |
c8e84d
|
101 |
activeKeyRef.value = p as string; |
27e50b
|
102 |
} |
819bcb
|
103 |
|
V |
104 |
if (isHide) { |
|
105 |
const findParentRoute = router |
|
106 |
.getRoutes() |
|
107 |
.find((item) => item.path === currentActiveMenu); |
215d8b
|
108 |
|
00fca0
|
109 |
findParentRoute && tabStore.addTab(findParentRoute as unknown as RouteLocationNormalized); |
819bcb
|
110 |
} else { |
215d8b
|
111 |
tabStore.addTab(unref(route)); |
819bcb
|
112 |
} |
a65ad9
|
113 |
}); |
27e50b
|
114 |
|
V |
115 |
function handleChange(activeKey: any) { |
|
116 |
activeKeyRef.value = activeKey; |
|
117 |
go(activeKey, false); |
|
118 |
} |
|
119 |
|
|
120 |
// Close the current tab |
|
121 |
function handleEdit(targetKey: string) { |
|
122 |
// Added operation to hide, currently only use delete operation |
215d8b
|
123 |
if (unref(unClose)) { |
V |
124 |
return; |
|
125 |
} |
27e50b
|
126 |
|
215d8b
|
127 |
tabStore.closeTabByKey(targetKey, router); |
27e50b
|
128 |
} |
V |
129 |
return { |
|
130 |
getWrapClass, |
|
131 |
handleEdit, |
|
132 |
handleChange, |
|
133 |
activeKeyRef, |
|
134 |
getTabsState, |
a65ad9
|
135 |
getShowQuick, |
V |
136 |
getShowRedo, |
0e7c57
|
137 |
getShowFold, |
27e50b
|
138 |
}; |
V |
139 |
}, |
|
140 |
}); |
|
141 |
</script> |
|
142 |
<style lang="less"> |
|
143 |
@import './index.less'; |
|
144 |
</style> |