|
1 | 1 | <template> |
2 | 2 | <div :class="[prefixCls, `${prefixCls}--${theme}`]"> |
3 | 3 | <a-breadcrumb :routes="routes"> |
4 | | - <template #itemRender="{ route, routes }"> |
| 4 | + <template #itemRender="{ route, routes, paths }"> |
5 | 5 | <Icon :icon="route.meta.icon" v-if="getShowBreadCrumbIcon && route.meta.icon" /> |
6 | | - <span v-if="routes.indexOf(route) === routes.length - 1"> |
| 6 | + <span v-if="!hasRedirect(routes, route)"> |
7 | 7 | {{ t(route.meta.title) }} |
8 | 8 | </span> |
9 | | - <router-link v-else :to="route.path"> |
| 9 | + <router-link v-else to="" @click="handleClick(route, paths, $event)"> |
10 | 10 | {{ t(route.meta.title) }} |
11 | 11 | </router-link> |
12 | 12 | </template> |
|
30 | 30 | import { useRootSetting } from '/@/hooks/setting/useRootSetting'; |
31 | 31 |
|
32 | 32 | import { propTypes } from '/@/utils/propTypes'; |
| 33 | + import { useGo } from '/@/hooks/web/usePage'; |
| 34 | + import { isString } from '/@/utils/is'; |
33 | 35 |
|
34 | 36 | export default defineComponent({ |
35 | 37 | name: 'LayoutBreadcrumb', |
|
45 | 47 |
|
46 | 48 | const { t } = useI18n(); |
47 | 49 | watchEffect(() => { |
48 | | - if (currentRoute.value.name === REDIRECT_NAME) { |
49 | | - return; |
50 | | - } |
| 50 | + if (currentRoute.value.name === REDIRECT_NAME) return; |
| 51 | +
|
51 | 52 | const matched = currentRoute.value?.matched; |
52 | 53 | if (!matched || matched.length === 0) return; |
53 | 54 |
|
54 | | - let breadcrumbList = filter(toRaw(matched), (item) => { |
55 | | - if (!item.meta) { |
56 | | - return false; |
57 | | - } |
58 | | - const { title, hideBreadcrumb } = item.meta; |
59 | | - if (!title || hideBreadcrumb) { |
60 | | - return false; |
61 | | - } |
62 | | - return true; |
63 | | - }); |
| 55 | + let breadcrumbList = filterItem(toRaw(matched)); |
64 | 56 |
|
65 | 57 | const filterBreadcrumbList = breadcrumbList.filter( |
66 | 58 | (item) => item.path !== PageEnum.BASE_HOME |
|
71 | 63 | path: PageEnum.BASE_HOME, |
72 | 64 | meta: { |
73 | 65 | title: t('layout.header.home'), |
| 66 | + isLink: true, |
74 | 67 | }, |
75 | 68 | } as unknown) as RouteLocationMatched); |
76 | 69 | } |
77 | | - routes.value = filterBreadcrumbList.length === 1 ? [] : filterBreadcrumbList; |
| 70 | +
|
| 71 | + if (currentRoute.value.meta?.currentActiveMenu) { |
| 72 | + filterBreadcrumbList.push((currentRoute.value as unknown) as RouteLocationMatched); |
| 73 | + } |
| 74 | + // routes.value = filterBreadcrumbList.length === 1 ? [] : filterBreadcrumbList; |
| 75 | + routes.value = filterBreadcrumbList; |
78 | 76 | }); |
79 | 77 |
|
80 | | - return { routes, t, prefixCls, getShowBreadCrumbIcon }; |
| 78 | + function filterItem(list: RouteLocationMatched[]) { |
| 79 | + let resultList = filter(list, (item) => { |
| 80 | + const { meta } = item; |
| 81 | +
|
| 82 | + if (!meta) { |
| 83 | + return false; |
| 84 | + } |
| 85 | + const { title, hideBreadcrumb, hideMenu } = meta; |
| 86 | + if (!title || hideBreadcrumb || hideMenu) { |
| 87 | + return false; |
| 88 | + } |
| 89 | +
|
| 90 | + return true; |
| 91 | + }).filter((item) => !item.meta?.hideBreadcrumb || !item.meta?.hideMenu); |
| 92 | +
|
| 93 | + resultList = resultList.filter((item) => item.path !== PageEnum.BASE_HOME); |
| 94 | + return resultList; |
| 95 | + } |
| 96 | +
|
| 97 | + function handleClick(route: RouteLocationMatched, paths: string[], e: Event) { |
| 98 | + e?.preventDefault(); |
| 99 | + const { |
| 100 | + children, |
| 101 | + redirect, |
| 102 | + meta, |
| 103 | + // components |
| 104 | + } = route; |
| 105 | +
|
| 106 | + // const isParent = |
| 107 | + // components?.default?.name === 'DefaultLayout' || (components?.default as any)?.parentView; |
| 108 | +
|
| 109 | + if ( |
| 110 | + children?.length && |
| 111 | + !redirect |
| 112 | + // && !isParent |
| 113 | + ) { |
| 114 | + e?.stopPropagation(); |
| 115 | + return; |
| 116 | + } |
| 117 | + if (meta?.carryParam) { |
| 118 | + return; |
| 119 | + } |
| 120 | +
|
| 121 | + const go = useGo(); |
| 122 | + if (redirect && isString(redirect)) { |
| 123 | + go(redirect); |
| 124 | + } else { |
| 125 | + const ps = paths.slice(1); |
| 126 | + const lastPath = ps.pop() || ''; |
| 127 | + const parentPath = ps.pop() || ''; |
| 128 | + let path = `${parentPath}/${lastPath}`; |
| 129 | + path = /^\//.test(path) ? path : `/${path}`; |
| 130 | + go(path); |
| 131 | + } |
| 132 | + } |
| 133 | +
|
| 134 | + function hasRedirect(routes: RouteLocationMatched[], route: RouteLocationMatched) { |
| 135 | + if (route?.meta?.isLink) { |
| 136 | + return true; |
| 137 | + } |
| 138 | +
|
| 139 | + if (routes.indexOf(route) === routes.length - 1) { |
| 140 | + return false; |
| 141 | + } |
| 142 | + return true; |
| 143 | + } |
| 144 | +
|
| 145 | + return { routes, t, prefixCls, getShowBreadCrumbIcon, handleClick, hasRedirect }; |
81 | 146 | }, |
82 | 147 | }); |
83 | 148 | </script> |
|
0 commit comments