mirror of
https://github.com/vbenjs/vue-vben-admin.git
synced 2025-08-27 14:49:43 +08:00
feat(breadcrumb): add breadcrumb demo #143
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<div :class="[prefixCls, `${prefixCls}--${theme}`]">
|
||||
<a-breadcrumb :routes="routes">
|
||||
<template #itemRender="{ route, routes }">
|
||||
<template #itemRender="{ route, routes, paths }">
|
||||
<Icon :icon="route.meta.icon" v-if="getShowBreadCrumbIcon && route.meta.icon" />
|
||||
<span v-if="routes.indexOf(route) === routes.length - 1">
|
||||
<span v-if="!hasRedirect(routes, route)">
|
||||
{{ t(route.meta.title) }}
|
||||
</span>
|
||||
<router-link v-else :to="route.path">
|
||||
<router-link v-else to="" @click="handleClick(route, paths, $event)">
|
||||
{{ t(route.meta.title) }}
|
||||
</router-link>
|
||||
</template>
|
||||
@@ -30,6 +30,8 @@
|
||||
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
|
||||
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
import { useGo } from '/@/hooks/web/usePage';
|
||||
import { isString } from '/@/utils/is';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'LayoutBreadcrumb',
|
||||
@@ -45,22 +47,12 @@
|
||||
|
||||
const { t } = useI18n();
|
||||
watchEffect(() => {
|
||||
if (currentRoute.value.name === REDIRECT_NAME) {
|
||||
return;
|
||||
}
|
||||
if (currentRoute.value.name === REDIRECT_NAME) return;
|
||||
|
||||
const matched = currentRoute.value?.matched;
|
||||
if (!matched || matched.length === 0) return;
|
||||
|
||||
let breadcrumbList = filter(toRaw(matched), (item) => {
|
||||
if (!item.meta) {
|
||||
return false;
|
||||
}
|
||||
const { title, hideBreadcrumb } = item.meta;
|
||||
if (!title || hideBreadcrumb) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
let breadcrumbList = filterItem(toRaw(matched));
|
||||
|
||||
const filterBreadcrumbList = breadcrumbList.filter(
|
||||
(item) => item.path !== PageEnum.BASE_HOME
|
||||
@@ -71,13 +63,86 @@
|
||||
path: PageEnum.BASE_HOME,
|
||||
meta: {
|
||||
title: t('layout.header.home'),
|
||||
isLink: true,
|
||||
},
|
||||
} as unknown) as RouteLocationMatched);
|
||||
}
|
||||
routes.value = filterBreadcrumbList.length === 1 ? [] : filterBreadcrumbList;
|
||||
|
||||
if (currentRoute.value.meta?.currentActiveMenu) {
|
||||
filterBreadcrumbList.push((currentRoute.value as unknown) as RouteLocationMatched);
|
||||
}
|
||||
// routes.value = filterBreadcrumbList.length === 1 ? [] : filterBreadcrumbList;
|
||||
routes.value = filterBreadcrumbList;
|
||||
});
|
||||
|
||||
return { routes, t, prefixCls, getShowBreadCrumbIcon };
|
||||
function filterItem(list: RouteLocationMatched[]) {
|
||||
let resultList = filter(list, (item) => {
|
||||
const { meta } = item;
|
||||
|
||||
if (!meta) {
|
||||
return false;
|
||||
}
|
||||
const { title, hideBreadcrumb, hideMenu } = meta;
|
||||
if (!title || hideBreadcrumb || hideMenu) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}).filter((item) => !item.meta?.hideBreadcrumb || !item.meta?.hideMenu);
|
||||
|
||||
resultList = resultList.filter((item) => item.path !== PageEnum.BASE_HOME);
|
||||
return resultList;
|
||||
}
|
||||
|
||||
function handleClick(route: RouteLocationMatched, paths: string[], e: Event) {
|
||||
e?.preventDefault();
|
||||
const {
|
||||
children,
|
||||
redirect,
|
||||
meta,
|
||||
// components
|
||||
} = route;
|
||||
|
||||
// const isParent =
|
||||
// components?.default?.name === 'DefaultLayout' || (components?.default as any)?.parentView;
|
||||
|
||||
if (
|
||||
children?.length &&
|
||||
!redirect
|
||||
// && !isParent
|
||||
) {
|
||||
e?.stopPropagation();
|
||||
return;
|
||||
}
|
||||
if (meta?.carryParam) {
|
||||
return;
|
||||
}
|
||||
|
||||
const go = useGo();
|
||||
if (redirect && isString(redirect)) {
|
||||
go(redirect);
|
||||
} else {
|
||||
const ps = paths.slice(1);
|
||||
const lastPath = ps.pop() || '';
|
||||
const parentPath = ps.pop() || '';
|
||||
let path = `${parentPath}/${lastPath}`;
|
||||
path = /^\//.test(path) ? path : `/${path}`;
|
||||
go(path);
|
||||
}
|
||||
}
|
||||
|
||||
function hasRedirect(routes: RouteLocationMatched[], route: RouteLocationMatched) {
|
||||
if (route?.meta?.isLink) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (routes.indexOf(route) === routes.length - 1) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return { routes, t, prefixCls, getShowBreadCrumbIcon, handleClick, hasRedirect };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
@@ -59,7 +59,7 @@ export function handler(event: HandlerEnum, value: any): DeepPartial<ProjectConf
|
||||
return { menuSetting: { bgColor: value } };
|
||||
|
||||
case HandlerEnum.MENU_SPLIT:
|
||||
return { menuSetting: { split: value, collapsedShowTitle: true } };
|
||||
return { menuSetting: { split: value } };
|
||||
|
||||
case HandlerEnum.MENU_CLOSE_MIX_SIDEBAR_ON_CHANGE:
|
||||
return { menuSetting: { closeMixSidebarOnChange: value } };
|
||||
|
@@ -38,6 +38,7 @@
|
||||
|
||||
<div :class="`${prefixCls}-menu-list`" ref="sideRef" :style="getMenuStyle">
|
||||
<div
|
||||
v-show="openMenu"
|
||||
:class="[
|
||||
`${prefixCls}-menu-list__title`,
|
||||
{
|
||||
|
@@ -30,6 +30,7 @@
|
||||
|
||||
import { Tabs } from 'ant-design-vue';
|
||||
import TabContent from './components/TabContent.vue';
|
||||
import type { RouteLocationNormalized } from 'vue-router';
|
||||
|
||||
import { useGo } from '/@/hooks/web/usePage';
|
||||
|
||||
@@ -43,6 +44,8 @@
|
||||
import { listenerLastChangeTab } from '/@/logics/mitt/tabChange';
|
||||
import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';
|
||||
|
||||
import router from '/@/router';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'MultipleTabs',
|
||||
components: {
|
||||
@@ -61,7 +64,9 @@
|
||||
const go = useGo();
|
||||
const { getShowQuick, getShowRedo } = useMultipleTabSetting();
|
||||
|
||||
const getTabsState = computed(() => tabStore.getTabsState);
|
||||
const getTabsState = computed(() => {
|
||||
return tabStore.getTabsState.filter((item) => !item.meta?.hideTab);
|
||||
});
|
||||
|
||||
const unClose = computed(() => unref(getTabsState).length === 1);
|
||||
|
||||
@@ -78,13 +83,24 @@
|
||||
const { name } = route;
|
||||
if (name === REDIRECT_NAME || !route || !userStore.getTokenState) return;
|
||||
|
||||
const { path, fullPath } = route;
|
||||
const p = fullPath || path;
|
||||
const { path, fullPath, meta = {} } = route;
|
||||
|
||||
const { currentActiveMenu, hideTab } = meta;
|
||||
const isHide = !hideTab ? null : currentActiveMenu;
|
||||
const p = isHide || fullPath || path;
|
||||
if (activeKeyRef.value !== p) {
|
||||
activeKeyRef.value = p;
|
||||
}
|
||||
tabStore.addTabAction(unref(route));
|
||||
|
||||
if (isHide) {
|
||||
const findParentRoute = router
|
||||
.getRoutes()
|
||||
.find((item) => item.path === currentActiveMenu);
|
||||
findParentRoute &&
|
||||
tabStore.addTabAction((findParentRoute as unknown) as RouteLocationNormalized);
|
||||
} else {
|
||||
tabStore.addTabAction(unref(route));
|
||||
}
|
||||
});
|
||||
|
||||
function handleChange(activeKey: any) {
|
||||
|
Reference in New Issue
Block a user