Skip to content

Commit fe5522d

Browse files
author
Jason
committed
多标签tabs 调整
1 parent aee93d8 commit fe5522d

49 files changed

Lines changed: 273 additions & 109 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

admin/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
"vite": "^3.0.0",
5656
"vite-plugin-style-import": "^2.0.0",
5757
"vite-plugin-svg-icons": "^2.0.1",
58+
"vite-plugin-vue-setup-extend": "^0.4.0",
5859
"vue-tsc": "^0.38.1"
5960
}
6061
}

admin/src/hooks/useMultipleTabs.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import useTabsStore from '@/stores/modules/multipleTabs'
2+
import useSettingStore from '@/stores/modules/setting'
3+
4+
export default function useMultipleTabs() {
5+
const router = useRouter()
6+
const route = useRoute()
7+
const tabsStore = useTabsStore()
8+
const settingStore = useSettingStore()
9+
10+
const tabsLists = computed(() => {
11+
return tabsStore.getTabList
12+
})
13+
14+
const currentTab = computed(() => {
15+
return route.fullPath
16+
})
17+
18+
const addTab = () => {
19+
if (!settingStore.openMultipleTabs) return
20+
tabsStore.addTab(router)
21+
}
22+
23+
const removeTab = (fullPath?: any) => {
24+
if (!settingStore.openMultipleTabs) return
25+
fullPath = fullPath ?? route.fullPath
26+
tabsStore.removeTab(fullPath, router)
27+
}
28+
29+
const removeOtherTab = () => {
30+
if (!settingStore.openMultipleTabs) return
31+
tabsStore.removeOtherTab(route)
32+
}
33+
34+
const removeAllTab = () => {
35+
if (!settingStore.openMultipleTabs) return
36+
tabsStore.removeAllTab(router)
37+
}
38+
39+
return {
40+
tabsLists,
41+
currentTab,
42+
addTab,
43+
removeTab,
44+
removeOtherTab,
45+
removeAllTab
46+
}
47+
}

admin/src/layout/default/components/header/multiple-tabs.vue

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
<div class="flex-1 min-w-0">
44
<el-tabs
55
:model-value="currentTab"
6-
:closable="tabsState.length > 1"
6+
:closable="tabsLists.length > 1"
77
@tab-change="handleChange"
8-
@tab-remove="handleRemove"
8+
@tab-remove="removeTab($event)"
99
>
10-
<template v-for="item in tabsState" :key="item.path">
11-
<el-tab-pane :label="item.title" :name="item.path"></el-tab-pane>
10+
<template v-for="item in tabsLists" :key="item.fullPath">
11+
<el-tab-pane :label="item.title" :name="item.fullPath"></el-tab-pane>
1212
</template>
1313
</el-tabs>
1414
</div>
@@ -28,40 +28,31 @@
2828
</template>
2929

3030
<script setup lang="ts">
31+
import useMultipleTabs from '@/hooks/useMultipleTabs'
3132
import { useWatchRoute } from '@/hooks/useWatchRoute'
3233
import useTabsStore, { getRouteParams } from '@/stores/modules/multipleTabs'
3334
const router = useRouter()
3435
const tabsStore = useTabsStore()
35-
const { route } = useWatchRoute((route) => {
36-
tabsStore.addTab(route, router)
36+
const { removeOtherTab, addTab, removeAllTab, removeTab, tabsLists, currentTab } = useMultipleTabs()
37+
useWatchRoute(() => {
38+
addTab()
3739
})
3840
39-
const currentTab = computed(() => {
40-
return route.path
41-
})
42-
43-
const tabsState = computed(() => {
44-
return tabsStore.getTabList
45-
})
46-
47-
const handleChange = (path: any) => {
48-
const tabItem = tabsStore.tasMap[path]
41+
const handleChange = (fullPath: any) => {
42+
const tabItem = tabsStore.tasMap[fullPath]
4943
router.push(getRouteParams(tabItem))
5044
}
5145
52-
const handleRemove = (path: any) => {
53-
tabsStore.removeTab(path, router)
54-
}
5546
const handleCommand = (command: any) => {
5647
switch (command) {
5748
case 'closeCurrent':
58-
handleRemove(route.path)
49+
removeTab()
5950
break
6051
case 'closeOther':
61-
tabsStore.removeOtherTab(route.path)
52+
removeOtherTab()
6253
break
6354
case 'closeAll':
64-
tabsStore.removeAllTab(router)
55+
removeAllTab()
6556
break
6657
}
6758
}

admin/src/layout/default/components/main.vue

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
<el-scrollbar>
44
<div class="p-4">
55
<router-view v-if="isRouteShow" v-slot="{ Component, route }">
6-
<component :is="Component" :key="route.fullPath" />
6+
<keep-alive :include="includeList" :max="20">
7+
<component :is="Component" :key="route.fullPath" />
8+
</keep-alive>
79
</router-view>
810
</div>
911
</el-scrollbar>
@@ -12,8 +14,13 @@
1214

1315
<script setup lang="ts">
1416
import useAppStore from '@/stores/modules/app'
17+
import useTabsStore from '@/stores/modules/multipleTabs'
18+
import useSettingStore from '@/stores/modules/setting'
1519
const appStore = useAppStore()
20+
const tabsStore = useTabsStore()
21+
const settingStore = useSettingStore()
1622
const isRouteShow = computed(() => appStore.isRouteShow)
23+
const includeList = computed(() => (settingStore.openMultipleTabs ? tabsStore.getCacheTabList : []))
1724
</script>
1825

1926
<style></style>

admin/src/layout/default/components/setting/drawer.vue

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ import theme_light from '@/assets/images/theme_white.png'
6565
import theme_dark from '@/assets/images/theme_black.png'
6666
6767
const settingStore = useSettingStore()
68-
6968
const predefineColors = ref(['#409EFF', '#28C76F', '#EA5455', '#FF9F43', '#01CFE8', '#4A5DFF'])
7069
const sideThemeList = [
7170
{

admin/src/stores/modules/multipleTabs.ts

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { PageEnum } from '@/enums/pageEnum'
1111

1212
interface TabItem {
1313
name: RouteRecordName
14+
fullPath: string
1415
path: string
1516
title?: string
1617
query?: LocationQuery
@@ -24,8 +25,8 @@ interface TabsSate {
2425
indexRouteName: RouteRecordName
2526
}
2627

27-
const getHasTabIndex = (path: string, tabList: TabItem[]) => {
28-
return tabList.findIndex((item) => item.path == path)
28+
const getHasTabIndex = (fullPath: string, tabList: TabItem[]) => {
29+
return tabList.findIndex((item) => item.fullPath == fullPath)
2930
}
3031

3132
const isCannotAddRoute = (route: RouteLocationNormalized, router: Router) => {
@@ -39,8 +40,12 @@ const isCannotAddRoute = (route: RouteLocationNormalized, router: Router) => {
3940
return false
4041
}
4142

42-
const findTabsIndex = (path: string, tabList: TabItem[]) => {
43-
return tabList.findIndex((item) => item.path === path)
43+
const findTabsIndex = (fullPath: string, tabList: TabItem[]) => {
44+
return tabList.findIndex((item) => item.fullPath === fullPath)
45+
}
46+
47+
const getComponentName = (route: RouteLocationNormalized) => {
48+
return route.matched.at(-1)?.components?.default?.name
4449
}
4550

4651
export const getRouteParams = (tabItem: TabItem) => {
@@ -63,45 +68,67 @@ const useTabsStore = defineStore({
6368
getters: {
6469
getTabList(): TabItem[] {
6570
return this.tabList
71+
},
72+
getCacheTabList(): string[] {
73+
return Array.from(this.cacheTabList)
6674
}
6775
},
6876
actions: {
6977
setRouteName(name: RouteRecordName) {
7078
this.indexRouteName = name
7179
},
80+
addCache(componentName?: string) {
81+
if (componentName) this.cacheTabList.add(componentName)
82+
},
83+
removeCache(componentName?: string) {
84+
if (componentName && this.cacheTabList.has(componentName)) {
85+
this.cacheTabList.delete(componentName)
86+
}
87+
console.log(this.cacheTabList)
88+
},
89+
clearCache() {
90+
this.cacheTabList.clear()
91+
},
7292
resetState() {
7393
this.cacheTabList = new Set()
7494
this.tabList = []
7595
this.tasMap = {}
7696
this.indexRouteName = ''
7797
},
78-
addTab(route: RouteLocationNormalized, router: Router) {
79-
const { name, path, query, meta, params } = route
98+
addTab(router: Router) {
99+
const route = unref(router.currentRoute)
100+
const { name, query, meta, params, fullPath, path } = route
80101
if (isCannotAddRoute(route, router)) return
81-
const hasTabIndex = getHasTabIndex(path!, this.tabList)
82-
102+
const hasTabIndex = getHasTabIndex(fullPath!, this.tabList)
103+
const componentName = getComponentName(route)
83104
const tabItem = {
84105
name: name!,
85106
path,
107+
fullPath,
86108
title: meta?.title,
87109
query,
88110
params
89111
}
90-
this.tasMap[path] = tabItem
112+
this.tasMap[fullPath] = tabItem
113+
if (meta?.keepAlive) {
114+
this.addCache(componentName)
115+
}
91116
if (hasTabIndex != -1) {
92-
this.tabList.splice(hasTabIndex, 1, tabItem)
93117
return
94118
}
119+
95120
this.tabList.push(tabItem)
96121
},
97-
removeTab(path: string, router: Router) {
122+
removeTab(fullPath: string, router: Router) {
98123
const { currentRoute, push } = router
99-
const index = findTabsIndex(path, this.tabList)
124+
const index = findTabsIndex(fullPath, this.tabList)
100125
// 移除tab
101126
if (this.tabList.length > 1) {
102127
index !== -1 && this.tabList.splice(index, 1)
103128
}
104-
if (path !== currentRoute.value.path) {
129+
const componentName = getComponentName(currentRoute.value)
130+
this.removeCache(componentName)
131+
if (fullPath !== currentRoute.value.fullPath) {
105132
return
106133
}
107134
// 删除选中的tab
@@ -116,17 +143,24 @@ const useTabsStore = defineStore({
116143
const toRoute = getRouteParams(toTab)
117144
push(toRoute)
118145
},
119-
removeOtherTab(path: string) {
120-
this.tabList = this.tabList.filter((item) => item.path == path)
146+
removeOtherTab(route: RouteLocationNormalized) {
147+
this.tabList = this.tabList.filter((item) => item.fullPath == route.fullPath)
148+
const componentName = getComponentName(route)
149+
this.cacheTabList.forEach((name) => {
150+
if (componentName !== name) {
151+
this.removeCache(name)
152+
}
153+
})
121154
},
122155
removeAllTab(router: Router) {
123156
const { push, currentRoute } = router
124-
const { path, name } = unref(currentRoute)
157+
const { name } = unref(currentRoute)
125158
if (name == this.indexRouteName) {
126-
this.removeOtherTab(path)
159+
this.removeOtherTab(currentRoute.value)
127160
return
128161
}
129162
this.tabList = []
163+
this.clearCache()
130164
push(PageEnum.INDEX)
131165
}
132166
}

admin/src/stores/modules/user.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,6 @@ const useUserStore = defineStore({
2828
}),
2929
getters: {},
3030
actions: {
31-
resetState() {
32-
this.token = ''
33-
this.userInfo = {}
34-
this.perms = []
35-
this.menu = []
36-
},
3731
login(playload: any) {
3832
const { account, password } = playload
3933
return new Promise((resolve, reject) => {
@@ -54,8 +48,9 @@ const useUserStore = defineStore({
5448
logout() {
5549
return new Promise((resolve, reject) => {
5650
logout()
57-
.then((data) => {
58-
router.push(PageEnum.LOGIN)
51+
.then(async (data) => {
52+
this.token = ''
53+
await router.push(PageEnum.LOGIN)
5954
clearAuthInfo()
6055
resolve(data)
6156
})

admin/src/utils/auth.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ export function getToken() {
1111
export function clearAuthInfo() {
1212
const userStore = useUserStore()
1313
const tabsStore = useTabsStore()
14-
userStore.resetState()
15-
tabsStore.resetState()
14+
userStore.$reset()
15+
tabsStore.$reset()
1616
cache.remove(TOKEN_KEY)
1717
resetRouter()
1818
}

admin/src/views/article/column/index.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565
<edit-popup v-if="showEdit" ref="editRef" @success="getLists" @close="showEdit = false" />
6666
</div>
6767
</template>
68-
<script lang="ts" setup>
68+
<script lang="ts" setup name="articleColumn">
6969
import { articleCateDelete, articleCateLists, articleCateStatus } from '@/api/article'
7070
import { usePaging } from '@/hooks/usePaging'
7171
import feedback from '@/utils/feedback'

admin/src/views/article/lists/edit.vue

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
v-model="formData.title"
2020
placeholder="请输入文章标题"
2121
type="textarea"
22-
:autosize="{ minRows: 3, maxRows: 6 }"
23-
maxlength="200"
22+
:autosize="{ minRows: 3, maxRows: 3 }"
23+
maxlength="64"
2424
show-word-limit
2525
clearable
2626
/>
@@ -111,11 +111,12 @@
111111
</div>
112112
</template>
113113

114-
<script lang="ts" setup>
114+
<script lang="ts" setup name="articleListsEdit">
115115
import type { FormInstance } from 'element-plus'
116116
import feedback from '@/utils/feedback'
117117
import { useDictOptions } from '@/hooks/useDictOptions'
118118
import { articleCateAll, articleDetail, articleEdit, articleAdd } from '@/api/article'
119+
import useMultipleTabs from '@/hooks/useMultipleTabs'
119120
120121
const route = useRoute()
121122
const router = useRouter()
@@ -133,6 +134,7 @@ const formData = reactive({
133134
summary: ''
134135
})
135136
137+
const { removeTab } = useMultipleTabs()
136138
const formRef = shallowRef<FormInstance>()
137139
const rules = reactive({
138140
title: [{ required: true, message: '请输入文章标题', trigger: 'blur' }],
@@ -165,6 +167,7 @@ const handleSave = async () => {
165167
await articleAdd(formData)
166168
}
167169
feedback.msgSuccess('操作成功')
170+
removeTab()
168171
router.back()
169172
}
170173

0 commit comments

Comments
 (0)