Commit 052eff91c4b63f4c9e08b80ae171e96d656ec607
Committed by
GitHub
1 parent
e1cbe23e
perf: Improve the dynamic routing and automatically close the Tab function (#1264)
* 增加动态路由最大打开Tab数控制 * 增加动态路由打开数控制Router参数 * feat(Tab): 新增动态路由打开数限制Demo * fix(multipleTab.ts): 将原来的打开数限制从固定的 5 修改为读取配置 Co-authored-by: Haceral <18274416193@163.com>
Showing
8 changed files
with
65 additions
and
4 deletions
src/locales/lang/en/layout.ts
@@ -84,6 +84,7 @@ export default { | @@ -84,6 +84,7 @@ export default { | ||
84 | breadcrumb: 'Breadcrumbs', | 84 | breadcrumb: 'Breadcrumbs', |
85 | breadcrumbIcon: 'Breadcrumbs Icon', | 85 | breadcrumbIcon: 'Breadcrumbs Icon', |
86 | tabs: 'Tabs', | 86 | tabs: 'Tabs', |
87 | + tabDetail: 'Tab Detail', | ||
87 | tabsQuickBtn: 'Tabs quick button', | 88 | tabsQuickBtn: 'Tabs quick button', |
88 | tabsRedoBtn: 'Tabs redo button', | 89 | tabsRedoBtn: 'Tabs redo button', |
89 | tabsFoldBtn: 'Tabs flod button', | 90 | tabsFoldBtn: 'Tabs flod button', |
src/locales/lang/en/routes/demo.ts
@@ -67,6 +67,7 @@ export default { | @@ -67,6 +67,7 @@ export default { | ||
67 | feat: 'Page Function', | 67 | feat: 'Page Function', |
68 | icon: 'Icon', | 68 | icon: 'Icon', |
69 | tabs: 'Tabs', | 69 | tabs: 'Tabs', |
70 | + tabDetail: 'Tab Detail', | ||
70 | sessionTimeout: 'Session Timeout', | 71 | sessionTimeout: 'Session Timeout', |
71 | print: 'Print', | 72 | print: 'Print', |
72 | contextMenu: 'Context Menu', | 73 | contextMenu: 'Context Menu', |
src/locales/lang/zh-CN/layout.ts
@@ -84,6 +84,7 @@ export default { | @@ -84,6 +84,7 @@ export default { | ||
84 | breadcrumb: '面包屑', | 84 | breadcrumb: '面包屑', |
85 | breadcrumbIcon: '面包屑图标', | 85 | breadcrumbIcon: '面包屑图标', |
86 | tabs: '标签页', | 86 | tabs: '标签页', |
87 | + tabDetail: '标签详情页', | ||
87 | tabsQuickBtn: '标签页快捷按钮', | 88 | tabsQuickBtn: '标签页快捷按钮', |
88 | tabsRedoBtn: '标签页刷新按钮', | 89 | tabsRedoBtn: '标签页刷新按钮', |
89 | tabsFoldBtn: '标签页折叠按钮', | 90 | tabsFoldBtn: '标签页折叠按钮', |
src/locales/lang/zh-CN/routes/demo.ts
@@ -67,6 +67,7 @@ export default { | @@ -67,6 +67,7 @@ export default { | ||
67 | icon: '图标', | 67 | icon: '图标', |
68 | sessionTimeout: '登录过期', | 68 | sessionTimeout: '登录过期', |
69 | tabs: '标签页操作', | 69 | tabs: '标签页操作', |
70 | + tabDetail: '标签详情页', | ||
70 | print: '打印', | 71 | print: '打印', |
71 | contextMenu: '右键菜单', | 72 | contextMenu: '右键菜单', |
72 | download: '文件下载', | 73 | download: '文件下载', |
src/router/routes/modules/demo/feat.ts
@@ -53,7 +53,22 @@ const feat: AppRouteModule = { | @@ -53,7 +53,22 @@ const feat: AppRouteModule = { | ||
53 | component: () => import('/@/views/demo/feat/tabs/index.vue'), | 53 | component: () => import('/@/views/demo/feat/tabs/index.vue'), |
54 | meta: { | 54 | meta: { |
55 | title: t('routes.demo.feat.tabs'), | 55 | title: t('routes.demo.feat.tabs'), |
56 | + hideChildrenInMenu: true, | ||
56 | }, | 57 | }, |
58 | + children: [ | ||
59 | + { | ||
60 | + path: 'detail/:id', | ||
61 | + name: 'TabDetail', | ||
62 | + component: () => import('/@/views/demo/feat/tabs/TabDetail.vue'), | ||
63 | + meta: { | ||
64 | + currentActiveMenu: '/feat/tabs', | ||
65 | + title: t('routes.demo.feat.tabDetail'), | ||
66 | + hideMenu: true, | ||
67 | + dynamicLevel: 3, | ||
68 | + realPath: '/feat/tabs/detail', | ||
69 | + }, | ||
70 | + }, | ||
71 | + ], | ||
57 | }, | 72 | }, |
58 | { | 73 | { |
59 | path: 'breadcrumb', | 74 | path: 'breadcrumb', |
src/store/modules/multipleTab.ts
@@ -149,7 +149,7 @@ export const useMultipleTabStore = defineStore({ | @@ -149,7 +149,7 @@ export const useMultipleTabStore = defineStore({ | ||
149 | this.tabList.splice(updateIndex, 1, curTab); | 149 | this.tabList.splice(updateIndex, 1, curTab); |
150 | } else { | 150 | } else { |
151 | // Add tab | 151 | // Add tab |
152 | - // 获取动态路由层级 | 152 | + // 获取动态路由打开数,超过 0 即代表需要控制打开数 |
153 | const dynamicLevel = meta?.dynamicLevel ?? -1; | 153 | const dynamicLevel = meta?.dynamicLevel ?? -1; |
154 | if (dynamicLevel > 0) { | 154 | if (dynamicLevel > 0) { |
155 | // 如果动态路由层级大于 0 了,那么就要限制该路由的打开数限制了 | 155 | // 如果动态路由层级大于 0 了,那么就要限制该路由的打开数限制了 |
@@ -157,8 +157,9 @@ export const useMultipleTabStore = defineStore({ | @@ -157,8 +157,9 @@ export const useMultipleTabStore = defineStore({ | ||
157 | // const realName: string = path.match(/(\S*)\//)![1]; | 157 | // const realName: string = path.match(/(\S*)\//)![1]; |
158 | const realPath = meta?.realPath ?? ''; | 158 | const realPath = meta?.realPath ?? ''; |
159 | // 获取到已经打开的动态路由数, 判断是否大于某一个值 | 159 | // 获取到已经打开的动态路由数, 判断是否大于某一个值 |
160 | - // 这里先固定为 每个动态路由最大能打开【5】个Tab | ||
161 | - if (this.tabList.filter((e) => e.meta?.realPath ?? '' === realPath).length >= 5) { | 160 | + if ( |
161 | + this.tabList.filter((e) => e.meta?.realPath ?? '' === realPath).length >= dynamicLevel | ||
162 | + ) { | ||
162 | // 关闭第一个 | 163 | // 关闭第一个 |
163 | const index = this.tabList.findIndex((item) => item.meta.realPath === realPath); | 164 | const index = this.tabList.findIndex((item) => item.meta.realPath === realPath); |
164 | index !== -1 && this.tabList.splice(index, 1); | 165 | index !== -1 && this.tabList.splice(index, 1); |
src/views/demo/feat/tabs/TabDetail.vue
0 → 100644
1 | +<template> | ||
2 | + <PageWrapper title="Tab详情页面"> | ||
3 | + <div>{{ index }} - 详情页内容在此</div> | ||
4 | + </PageWrapper> | ||
5 | +</template> | ||
6 | + | ||
7 | +<script lang="ts"> | ||
8 | + import { defineComponent } from 'vue'; | ||
9 | + import { PageWrapper } from '/@/components/Page'; | ||
10 | + import { useTabs } from '/@/hooks/web/useTabs'; | ||
11 | + import { useRoute } from 'vue-router'; | ||
12 | + | ||
13 | + export default defineComponent({ | ||
14 | + name: 'TabDetail', | ||
15 | + components: { PageWrapper }, | ||
16 | + setup() { | ||
17 | + const route = useRoute(); | ||
18 | + const index = route.params?.id ?? -1; | ||
19 | + const { setTitle } = useTabs(); | ||
20 | + | ||
21 | + // 设置标识 | ||
22 | + setTitle(`No.${index} - 详情信息`); | ||
23 | + return { | ||
24 | + index, | ||
25 | + }; | ||
26 | + }, | ||
27 | + }); | ||
28 | +</script> |
src/views/demo/feat/tabs/index.vue
@@ -16,20 +16,28 @@ | @@ -16,20 +16,28 @@ | ||
16 | <a-button class="mr-2" @click="closeCurrent"> 关闭当前 </a-button> | 16 | <a-button class="mr-2" @click="closeCurrent"> 关闭当前 </a-button> |
17 | <a-button class="mr-2" @click="refreshPage"> 刷新当前 </a-button> | 17 | <a-button class="mr-2" @click="refreshPage"> 刷新当前 </a-button> |
18 | </CollapseContainer> | 18 | </CollapseContainer> |
19 | + | ||
20 | + <CollapseContainer class="mt-4" title="标签页复用超出限制自动关闭(使用场景: 动态路由)"> | ||
21 | + <a-button v-for="index in 6" :key="index" class="mr-2" @click="toDetail(index)"> | ||
22 | + 打开{{ index }}详情页 | ||
23 | + </a-button> | ||
24 | + </CollapseContainer> | ||
19 | </PageWrapper> | 25 | </PageWrapper> |
20 | </template> | 26 | </template> |
21 | <script lang="ts"> | 27 | <script lang="ts"> |
22 | import { defineComponent, ref } from 'vue'; | 28 | import { defineComponent, ref } from 'vue'; |
23 | - import { CollapseContainer } from '/@/components/Container/index'; | 29 | + import { CollapseContainer } from '/@/components/Container'; |
24 | import { useTabs } from '/@/hooks/web/useTabs'; | 30 | import { useTabs } from '/@/hooks/web/useTabs'; |
25 | import { PageWrapper } from '/@/components/Page'; | 31 | import { PageWrapper } from '/@/components/Page'; |
26 | import { Input, Alert } from 'ant-design-vue'; | 32 | import { Input, Alert } from 'ant-design-vue'; |
27 | import { useMessage } from '/@/hooks/web/useMessage'; | 33 | import { useMessage } from '/@/hooks/web/useMessage'; |
34 | + import { useGo } from '/@/hooks/web/usePage'; | ||
28 | 35 | ||
29 | export default defineComponent({ | 36 | export default defineComponent({ |
30 | name: 'TabsDemo', | 37 | name: 'TabsDemo', |
31 | components: { CollapseContainer, PageWrapper, [Input.name]: Input, [Alert.name]: Alert }, | 38 | components: { CollapseContainer, PageWrapper, [Input.name]: Input, [Alert.name]: Alert }, |
32 | setup() { | 39 | setup() { |
40 | + const go = useGo(); | ||
33 | const title = ref<string>(''); | 41 | const title = ref<string>(''); |
34 | const { closeAll, closeLeft, closeRight, closeOther, closeCurrent, refreshPage, setTitle } = | 42 | const { closeAll, closeLeft, closeRight, closeOther, closeCurrent, refreshPage, setTitle } = |
35 | useTabs(); | 43 | useTabs(); |
@@ -41,12 +49,17 @@ | @@ -41,12 +49,17 @@ | ||
41 | createMessage.error('请输入要设置的Tab标题!'); | 49 | createMessage.error('请输入要设置的Tab标题!'); |
42 | } | 50 | } |
43 | } | 51 | } |
52 | + | ||
53 | + function toDetail(index: number) { | ||
54 | + go(`/feat/tabs/detail/${index}`); | ||
55 | + } | ||
44 | return { | 56 | return { |
45 | closeAll, | 57 | closeAll, |
46 | closeLeft, | 58 | closeLeft, |
47 | closeRight, | 59 | closeRight, |
48 | closeOther, | 60 | closeOther, |
49 | closeCurrent, | 61 | closeCurrent, |
62 | + toDetail, | ||
50 | refreshPage, | 63 | refreshPage, |
51 | setTabTitle, | 64 | setTabTitle, |
52 | title, | 65 | title, |