2024-07-23 00:03:59 +08:00
|
|
|
import type { TabDefinition } from '@vben/types';
|
2024-05-19 21:20:42 +08:00
|
|
|
import type { IContextMenuItem } from '@vben-core/tabs-ui';
|
2024-06-08 19:49:06 +08:00
|
|
|
import type {
|
|
|
|
RouteLocationNormalized,
|
2024-07-05 11:12:38 +08:00
|
|
|
RouteLocationNormalizedGeneric,
|
2024-06-08 19:49:06 +08:00
|
|
|
} from 'vue-router';
|
2024-05-19 21:20:42 +08:00
|
|
|
|
2024-07-05 10:04:16 +08:00
|
|
|
import { computed, ref, watch } from 'vue';
|
2024-06-08 19:49:06 +08:00
|
|
|
import { useRoute, useRouter } from 'vue-router';
|
|
|
|
|
2024-07-23 00:03:59 +08:00
|
|
|
import { useContentMaximize, useTabs } from '@vben/hooks';
|
2024-05-19 21:20:42 +08:00
|
|
|
import {
|
2024-07-17 22:25:27 +08:00
|
|
|
ArrowLeftToLine,
|
|
|
|
ArrowRightLeft,
|
|
|
|
ArrowRightToLine,
|
|
|
|
ExternalLink,
|
|
|
|
FoldHorizontal,
|
|
|
|
Fullscreen,
|
2024-05-19 21:20:42 +08:00
|
|
|
MdiPin,
|
|
|
|
MdiPinOff,
|
2024-07-17 22:25:27 +08:00
|
|
|
Minimize2,
|
|
|
|
RotateCw,
|
|
|
|
X,
|
2024-07-23 00:03:59 +08:00
|
|
|
} from '@vben/icons';
|
|
|
|
import { $t, useI18n } from '@vben/locales';
|
2024-07-05 23:15:46 +08:00
|
|
|
import {
|
|
|
|
storeToRefs,
|
|
|
|
useCoreAccessStore,
|
|
|
|
useCoreTabbarStore,
|
2024-07-23 00:03:59 +08:00
|
|
|
} from '@vben/stores';
|
|
|
|
import { filterTree } from '@vben/utils';
|
2024-07-12 23:43:47 +08:00
|
|
|
|
2024-07-20 08:31:05 +08:00
|
|
|
export function useTabbar() {
|
2024-05-19 21:20:42 +08:00
|
|
|
const router = useRouter();
|
|
|
|
const route = useRoute();
|
2024-07-05 23:15:46 +08:00
|
|
|
const accessStore = useCoreAccessStore();
|
2024-07-10 00:50:41 +08:00
|
|
|
const coreTabbarStore = useCoreTabbarStore();
|
2024-05-19 21:20:42 +08:00
|
|
|
const { accessMenus } = storeToRefs(accessStore);
|
2024-07-20 08:31:05 +08:00
|
|
|
const { contentIsMaximize, toggleMaximize } = useContentMaximize();
|
|
|
|
const {
|
|
|
|
closeAllTabs,
|
|
|
|
closeCurrentTab,
|
|
|
|
closeLeftTabs,
|
|
|
|
closeOtherTabs,
|
|
|
|
closeRightTabs,
|
|
|
|
closeTabByKey,
|
|
|
|
getTabDisableState,
|
|
|
|
openTabInNewWindow,
|
|
|
|
refreshTab,
|
|
|
|
toggleTabPin,
|
|
|
|
} = useTabs();
|
2024-07-29 22:53:04 +08:00
|
|
|
|
2024-05-19 21:20:42 +08:00
|
|
|
const currentActive = computed(() => {
|
2024-07-20 11:14:32 +08:00
|
|
|
return route.fullPath;
|
2024-05-19 21:20:42 +08:00
|
|
|
});
|
|
|
|
|
2024-07-05 10:04:16 +08:00
|
|
|
const { locale } = useI18n();
|
2024-07-05 11:12:38 +08:00
|
|
|
const currentTabs = ref<RouteLocationNormalizedGeneric[]>();
|
2024-07-20 09:36:10 +08:00
|
|
|
watch(
|
|
|
|
[
|
|
|
|
() => coreTabbarStore.getTabs,
|
|
|
|
() => coreTabbarStore.updateTime,
|
|
|
|
() => locale.value,
|
|
|
|
],
|
|
|
|
([tabs]) => {
|
|
|
|
currentTabs.value = tabs.map((item) => wrapperTabLocale(item));
|
|
|
|
},
|
|
|
|
);
|
2024-05-19 21:20:42 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 初始化固定标签页
|
|
|
|
*/
|
|
|
|
const initAffixTabs = () => {
|
|
|
|
const affixTabs = filterTree(router.getRoutes(), (route) => {
|
|
|
|
return !!route.meta?.affixTab;
|
|
|
|
});
|
2024-07-10 00:50:41 +08:00
|
|
|
coreTabbarStore.setAffixTabs(affixTabs);
|
2024-05-19 21:20:42 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
// 点击tab,跳转路由
|
|
|
|
const handleClick = (key: string) => {
|
|
|
|
router.push(key);
|
|
|
|
};
|
|
|
|
|
|
|
|
// 关闭tab
|
|
|
|
const handleClose = async (key: string) => {
|
2024-07-20 08:31:05 +08:00
|
|
|
await closeTabByKey(key);
|
2024-05-19 21:20:42 +08:00
|
|
|
};
|
|
|
|
|
2024-07-05 11:12:38 +08:00
|
|
|
function wrapperTabLocale(tab: RouteLocationNormalizedGeneric) {
|
2024-05-21 21:45:48 +08:00
|
|
|
return {
|
|
|
|
...tab,
|
|
|
|
meta: {
|
2024-07-14 15:18:02 +08:00
|
|
|
...tab?.meta,
|
|
|
|
title: $t(tab?.meta?.title as string),
|
2024-05-21 21:45:48 +08:00
|
|
|
},
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2024-05-19 21:20:42 +08:00
|
|
|
watch(
|
|
|
|
() => accessMenus.value,
|
|
|
|
() => {
|
|
|
|
initAffixTabs();
|
|
|
|
},
|
|
|
|
{ immediate: true },
|
|
|
|
);
|
|
|
|
|
|
|
|
watch(
|
|
|
|
() => route.path,
|
|
|
|
() => {
|
2024-07-10 00:50:41 +08:00
|
|
|
coreTabbarStore.addTab(route as RouteLocationNormalized);
|
2024-05-19 21:20:42 +08:00
|
|
|
},
|
|
|
|
{ immediate: true },
|
|
|
|
);
|
|
|
|
|
2024-07-14 16:28:56 +08:00
|
|
|
const createContextMenus = (tab: TabDefinition) => {
|
2024-07-20 08:31:05 +08:00
|
|
|
const {
|
|
|
|
disabledCloseAll,
|
|
|
|
disabledCloseCurrent,
|
|
|
|
disabledCloseLeft,
|
|
|
|
disabledCloseOther,
|
|
|
|
disabledCloseRight,
|
|
|
|
disabledRefresh,
|
|
|
|
} = getTabDisableState(tab);
|
2024-05-19 21:20:42 +08:00
|
|
|
|
2024-07-20 08:31:05 +08:00
|
|
|
const affixTab = tab?.meta?.affixTab ?? false;
|
2024-05-19 21:20:42 +08:00
|
|
|
|
|
|
|
const menus: IContextMenuItem[] = [
|
2024-07-14 15:18:02 +08:00
|
|
|
{
|
2024-07-20 08:31:05 +08:00
|
|
|
disabled: disabledCloseCurrent,
|
2024-07-14 15:18:02 +08:00
|
|
|
handler: async () => {
|
2024-07-20 08:31:05 +08:00
|
|
|
await closeCurrentTab(tab);
|
2024-07-14 15:18:02 +08:00
|
|
|
},
|
2024-07-17 22:25:27 +08:00
|
|
|
icon: X,
|
2024-07-14 15:18:02 +08:00
|
|
|
key: 'close',
|
|
|
|
text: $t('preferences.tabbar.contextMenu.close'),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
handler: async () => {
|
2024-07-20 08:31:05 +08:00
|
|
|
await toggleTabPin(tab);
|
2024-07-14 15:18:02 +08:00
|
|
|
},
|
|
|
|
icon: affixTab ? MdiPinOff : MdiPin,
|
|
|
|
key: 'affix',
|
|
|
|
text: affixTab
|
|
|
|
? $t('preferences.tabbar.contextMenu.unpin')
|
|
|
|
: $t('preferences.tabbar.contextMenu.pin'),
|
|
|
|
},
|
2024-07-13 16:35:47 +08:00
|
|
|
{
|
|
|
|
handler: async () => {
|
|
|
|
if (!contentIsMaximize.value) {
|
|
|
|
await router.push(tab.fullPath);
|
|
|
|
}
|
2024-07-20 08:31:05 +08:00
|
|
|
toggleMaximize();
|
2024-07-13 16:35:47 +08:00
|
|
|
},
|
2024-07-17 22:25:27 +08:00
|
|
|
icon: contentIsMaximize.value ? Minimize2 : Fullscreen,
|
2024-07-13 16:35:47 +08:00
|
|
|
key: contentIsMaximize.value ? 'restore-maximize' : 'maximize',
|
|
|
|
text: contentIsMaximize.value
|
|
|
|
? $t('preferences.tabbar.contextMenu.restoreMaximize')
|
|
|
|
: $t('preferences.tabbar.contextMenu.maximize'),
|
|
|
|
},
|
2024-05-19 21:20:42 +08:00
|
|
|
{
|
2024-07-20 08:31:05 +08:00
|
|
|
disabled: disabledRefresh,
|
|
|
|
handler: refreshTab,
|
2024-07-17 22:25:27 +08:00
|
|
|
icon: RotateCw,
|
2024-05-19 21:20:42 +08:00
|
|
|
key: 'reload',
|
2024-07-10 21:55:16 +08:00
|
|
|
text: $t('preferences.tabbar.contextMenu.reload'),
|
2024-05-19 21:20:42 +08:00
|
|
|
},
|
2024-07-12 23:43:47 +08:00
|
|
|
{
|
|
|
|
handler: async () => {
|
2024-07-20 08:31:05 +08:00
|
|
|
await openTabInNewWindow(tab);
|
2024-07-12 23:43:47 +08:00
|
|
|
},
|
2024-07-17 22:25:27 +08:00
|
|
|
icon: ExternalLink,
|
2024-07-12 23:43:47 +08:00
|
|
|
key: 'open-in-new-window',
|
|
|
|
separator: true,
|
2024-07-13 16:35:47 +08:00
|
|
|
text: $t('preferences.tabbar.contextMenu.openInNewWindow'),
|
2024-07-12 23:43:47 +08:00
|
|
|
},
|
2024-07-13 16:35:47 +08:00
|
|
|
|
2024-05-19 21:20:42 +08:00
|
|
|
{
|
2024-07-20 08:31:05 +08:00
|
|
|
disabled: disabledCloseLeft,
|
2024-05-19 21:20:42 +08:00
|
|
|
handler: async () => {
|
2024-07-20 08:31:05 +08:00
|
|
|
await closeLeftTabs(tab);
|
2024-05-19 21:20:42 +08:00
|
|
|
},
|
2024-07-17 22:25:27 +08:00
|
|
|
icon: ArrowLeftToLine,
|
2024-05-19 21:20:42 +08:00
|
|
|
key: 'close-left',
|
2024-07-10 21:55:16 +08:00
|
|
|
text: $t('preferences.tabbar.contextMenu.closeLeft'),
|
2024-05-19 21:20:42 +08:00
|
|
|
},
|
|
|
|
{
|
2024-07-20 08:31:05 +08:00
|
|
|
disabled: disabledCloseRight,
|
2024-05-19 21:20:42 +08:00
|
|
|
handler: async () => {
|
2024-07-20 08:31:05 +08:00
|
|
|
await closeRightTabs(tab);
|
2024-05-19 21:20:42 +08:00
|
|
|
},
|
2024-07-17 22:25:27 +08:00
|
|
|
icon: ArrowRightToLine,
|
2024-05-19 21:20:42 +08:00
|
|
|
key: 'close-right',
|
|
|
|
separator: true,
|
2024-07-10 21:55:16 +08:00
|
|
|
text: $t('preferences.tabbar.contextMenu.closeRight'),
|
2024-05-19 21:20:42 +08:00
|
|
|
},
|
|
|
|
{
|
2024-07-20 08:31:05 +08:00
|
|
|
disabled: disabledCloseOther,
|
2024-05-19 21:20:42 +08:00
|
|
|
handler: async () => {
|
2024-07-20 08:31:05 +08:00
|
|
|
await closeOtherTabs(tab);
|
2024-05-19 21:20:42 +08:00
|
|
|
},
|
2024-07-17 22:25:27 +08:00
|
|
|
icon: FoldHorizontal,
|
2024-05-19 21:20:42 +08:00
|
|
|
key: 'close-other',
|
2024-07-10 21:55:16 +08:00
|
|
|
text: $t('preferences.tabbar.contextMenu.closeOther'),
|
2024-05-19 21:20:42 +08:00
|
|
|
},
|
|
|
|
{
|
2024-07-20 08:31:05 +08:00
|
|
|
disabled: disabledCloseAll,
|
|
|
|
handler: closeAllTabs,
|
2024-07-17 22:25:27 +08:00
|
|
|
icon: ArrowRightLeft,
|
2024-05-19 21:20:42 +08:00
|
|
|
key: 'close-all',
|
2024-07-10 21:55:16 +08:00
|
|
|
text: $t('preferences.tabbar.contextMenu.closeAll'),
|
2024-05-19 21:20:42 +08:00
|
|
|
},
|
|
|
|
];
|
|
|
|
return menus;
|
|
|
|
};
|
|
|
|
|
|
|
|
return {
|
|
|
|
createContextMenus,
|
|
|
|
currentActive,
|
|
|
|
currentTabs,
|
|
|
|
handleClick,
|
|
|
|
handleClose,
|
|
|
|
};
|
|
|
|
}
|