fix: layout error

This commit is contained in:
vben
2024-06-09 15:39:11 +08:00
parent 35c3dd78ec
commit 640ad6d9e7
58 changed files with 678 additions and 679 deletions

View File

@@ -0,0 +1,3 @@
export { default as LayoutTabbar } from './tabbar.vue';
export { default as LayoutTabbarTools } from './tabbar-tools.vue';
export * from './use-tabs';

View File

@@ -0,0 +1,39 @@
<script lang="ts" setup>
import { computed } from 'vue';
import { useRoute } from 'vue-router';
import { preferences, updatePreferences } from '@vben-core/preferences';
import { TabsToolMore, TabsToolScreen } from '@vben-core/tabs-ui';
import { useTabs } from './use-tabs';
const route = useRoute();
const { createContextMenus } = useTabs();
const menus = computed(() => {
return createContextMenus(route);
});
function handleScreenChange(screen: boolean) {
updatePreferences({
header: {
hidden: !!screen,
},
sidebar: {
hidden: !!screen,
},
});
}
</script>
<template>
<div class="flex-center h-full">
<TabsToolMore :menus="menus" />
<TabsToolScreen
:screen="preferences.sidebar.hidden"
@change="handleScreenChange"
@update:screen="handleScreenChange"
/>
</div>
</template>

View File

@@ -0,0 +1,32 @@
<script lang="ts" setup>
import { TabsView } from '@vben-core/tabs-ui';
import { useTabs } from './use-tabs';
defineOptions({
name: 'LayoutTabbar',
});
defineProps<{ showIcon?: boolean }>();
const {
createContextMenus,
currentActive,
currentTabs,
handleClick,
handleClose,
handleUnPushPin,
} = useTabs();
</script>
<template>
<TabsView
:active="currentActive"
:menus="createContextMenus"
:show-icon="showIcon"
:tabs="currentTabs"
@close="handleClose"
@un-push-pin="handleUnPushPin"
@update:active="handleClick"
/>
</template>

View File

@@ -0,0 +1,204 @@
import type { IContextMenuItem } from '@vben-core/tabs-ui';
import type { TabItem } from '@vben-core/typings';
import type {
RouteLocationNormalized,
RouteRecordNormalized,
} from 'vue-router';
import { computed, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { $t } from '@vben/locales';
import {
IcRoundClose,
IcRoundMultipleStop,
IcRoundRefresh,
MdiArrowExpandHorizontal,
MdiFormatHorizontalAlignLeft,
MdiFormatHorizontalAlignRight,
MdiPin,
MdiPinOff,
} from '@vben-core/iconify';
import { storeToRefs, useAccessStore, useTabsStore } from '@vben-core/stores';
import { filterTree } from '@vben-core/toolkit';
function useTabs() {
const router = useRouter();
const route = useRoute();
const accessStore = useAccessStore();
const tabsStore = useTabsStore();
const { accessMenus } = storeToRefs(accessStore);
const currentActive = computed(() => {
return route.path;
});
const currentTabs = computed(() => {
return tabsStore.getTabs;
});
/**
* 初始化固定标签页
*/
const initAffixTabs = () => {
const affixTabs = filterTree(router.getRoutes(), (route) => {
return !!route.meta?.affixTab;
});
affixTabs.forEach((tab) => {
Object.assign(tab, wrapperTabLocale(tab));
});
tabsStore.setAffixTabs(affixTabs);
};
// 点击tab,跳转路由
const handleClick = (key: string) => {
router.push(key);
};
// 关闭tab
const handleClose = async (key: string) => {
await tabsStore.closeTabByKey(key, router);
};
function wrapperTabLocale(
tab: RouteLocationNormalized | RouteRecordNormalized,
) {
return {
...tab,
meta: {
...tab.meta,
title: $t(tab.meta.title as string),
},
};
}
watch(
() => accessMenus.value,
() => {
initAffixTabs();
},
{ immediate: true },
);
watch(
() => route.path,
() => {
tabsStore.addTab(wrapperTabLocale(route) as RouteLocationNormalized);
},
{ immediate: true },
);
const createContextMenus = (tab: TabItem) => {
const tabs = tabsStore.getTabs;
const affixTabs = tabsStore.affixTabs;
const index = tabs.findIndex((item) => item.path === tab.path);
const disabled = tabs.length <= 1;
const { meta } = tab;
const affixTab = meta?.affixTab ?? false;
const isCurrentTab = route.path === tab.path;
// 当前处于最左侧或者减去固定标签页的数量等于0
const closeLeftDisabled =
index === 0 || index - affixTabs.length <= 0 || !isCurrentTab;
const closeRightDisabled = !isCurrentTab || index === tabs.length - 1;
const closeOtherDisabled =
disabled || !isCurrentTab || tabs.length - affixTabs.length <= 1;
const menus: IContextMenuItem[] = [
{
disabled: !isCurrentTab,
handler: async () => {
await tabsStore.refreshTab(router);
},
icon: IcRoundRefresh,
key: 'reload',
text: '重新加载',
},
{
disabled: !!affixTab || disabled,
handler: async () => {
await tabsStore.closeTab(tab, router);
},
icon: IcRoundClose,
key: 'close',
text: '关闭标签页',
},
{
handler: async () => {
await (affixTab
? tabsStore.unPushPinTab(tab)
: tabsStore.pushPinTab(tab));
},
icon: affixTab ? MdiPinOff : MdiPin,
key: 'affix',
separator: true,
text: affixTab ? '取消固定标签页' : '固定标签页',
},
{
disabled: closeLeftDisabled,
handler: async () => {
await tabsStore.closeLeftTabs(tab);
},
icon: MdiFormatHorizontalAlignLeft,
key: 'close-left',
text: '关闭左侧标签页',
},
{
disabled: closeRightDisabled,
handler: async () => {
await tabsStore.closeRightTabs(tab);
},
icon: MdiFormatHorizontalAlignRight,
key: 'close-right',
separator: true,
text: '关闭右侧标签页',
},
{
disabled: closeOtherDisabled,
handler: async () => {
await tabsStore.closeOtherTabs(tab);
},
icon: MdiArrowExpandHorizontal,
key: 'close-other',
text: '关闭其他标签页',
},
{
disabled,
handler: async () => {
await tabsStore.closeAllTabs(router);
},
icon: IcRoundMultipleStop,
key: 'close-all',
text: '关闭全部标签页',
},
// {
// icon: 'icon-[material-symbols--back-to-tab-sharp]',
// key: 'close-all',
// text: '新窗口打开',
// },
];
return menus;
};
/**
* 取消固定标签页
*/
const handleUnPushPin = async (tab: TabItem) => {
await tabsStore.unPushPinTab(tab);
};
return {
createContextMenus,
currentActive,
currentTabs,
handleClick,
handleClose,
handleUnPushPin,
};
}
export { useTabs };