提交 819bcbe5 编写于 作者: V vben

feat(breadcrumb): add breadcrumb demo #143

上级 930383f9
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
- 新增左侧菜单混合模式 - 新增左侧菜单混合模式
- 新增 markdown 嵌入表单内示例 - 新增 markdown 嵌入表单内示例
- 新增主框架外页面示例 - 新增主框架外页面示例
- `route.meta` 新增`currentActiveMenu`,`hideTab`,`hideMenu`参数 用于控制详情页面包屑级菜单显示隐藏。
- 新增面包屑导航示例
### 🐛 Bug Fixes ### 🐛 Bug Fixes
...@@ -14,6 +16,7 @@ ...@@ -14,6 +16,7 @@
- 修复图表库切换页面导致宽高计算错误 - 修复图表库切换页面导致宽高计算错误
- 修复多语言配置 `Locale.show`导致配置不生效 - 修复多语言配置 `Locale.show`导致配置不生效
- 修复路由类型错误 - 修复路由类型错误
- 修复菜单分割时权限失效问题
## 2.0.0-rc.14 (2020-12-15) ## 2.0.0-rc.14 (2020-12-15)
......
...@@ -118,16 +118,21 @@ ...@@ -118,16 +118,21 @@
listenerLastChangeTab((route) => { listenerLastChangeTab((route) => {
if (route.name === REDIRECT_NAME) return; if (route.name === REDIRECT_NAME) return;
handleMenuChange(route); handleMenuChange(route);
}, false); const currentActiveMenu = route.meta?.currentActiveMenu;
if (currentActiveMenu) {
menuState.selectedKeys = [currentActiveMenu];
setOpenKeys(currentActiveMenu);
}
});
watch( watch(
() => props.items, () => props.items,
() => { () => {
handleMenuChange(); handleMenuChange();
},
{
immediate: true,
} }
// {
// immediate: true,
// }
); );
async function handleMenuClick({ key, keyPath }: { key: string; keyPath: string[] }) { async function handleMenuClick({ key, keyPath }: { key: string; keyPath: string[] }) {
...@@ -149,9 +154,7 @@ ...@@ -149,9 +154,7 @@
return; return;
} }
const path = (route || unref(currentRoute)).path; const path = (route || unref(currentRoute)).path;
if (props.mode !== MenuModeEnum.HORIZONTAL) { setOpenKeys(path);
setOpenKeys(path);
}
if (props.isHorizontal && unref(getSplit)) { if (props.isHorizontal && unref(getSplit)) {
const parentPath = await getCurrentParentPath(path); const parentPath = await getCurrentParentPath(path);
menuState.selectedKeys = [parentPath]; menuState.selectedKeys = [parentPath];
......
<template> <template>
<BasicMenuItem v-if="!menuHasChildren(item)" v-bind="$props" /> <BasicMenuItem v-if="!menuHasChildren(item) && getShowMenu" v-bind="$props" />
<SubMenu v-else :class="[`${prefixCls}__level${level}`, theme]"> <SubMenu
v-if="menuHasChildren(item) && getShowMenu"
:class="[`${prefixCls}__level${level}`, theme]"
>
<template #title> <template #title>
<MenuItemContent v-bind="$props" :item="item" /> <MenuItemContent v-bind="$props" :item="item" />
</template> </template>
...@@ -16,7 +19,7 @@ ...@@ -16,7 +19,7 @@
<script lang="ts"> <script lang="ts">
import type { Menu as MenuType } from '/@/router/types'; import type { Menu as MenuType } from '/@/router/types';
import { defineComponent } from 'vue'; import { defineComponent, computed } from 'vue';
import { Menu } from 'ant-design-vue'; import { Menu } from 'ant-design-vue';
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
import { itemProps } from '../props'; import { itemProps } from '../props';
...@@ -35,8 +38,12 @@ ...@@ -35,8 +38,12 @@
// ExpandIcon: createAsyncComponent(() => import('./ExpandIcon.vue')), // ExpandIcon: createAsyncComponent(() => import('./ExpandIcon.vue')),
}, },
props: itemProps, props: itemProps,
setup() { setup(props) {
const { prefixCls } = useDesign('basic-menu-item'); const { prefixCls } = useDesign('basic-menu-item');
const getShowMenu = computed(() => {
return !props.item.meta?.hideMenu;
});
function menuHasChildren(menuTreeItem: MenuType): boolean { function menuHasChildren(menuTreeItem: MenuType): boolean {
return ( return (
Reflect.has(menuTreeItem, 'children') && Reflect.has(menuTreeItem, 'children') &&
...@@ -47,6 +54,7 @@ ...@@ -47,6 +54,7 @@
return { return {
prefixCls, prefixCls,
menuHasChildren, menuHasChildren,
getShowMenu,
}; };
}, },
}); });
......
...@@ -18,6 +18,9 @@ export function useOpenKeys( ...@@ -18,6 +18,9 @@ export function useOpenKeys(
const { getCollapsed } = useMenuSetting(); const { getCollapsed } = useMenuSetting();
function setOpenKeys(path: string) { function setOpenKeys(path: string) {
if (mode.value === MenuModeEnum.HORIZONTAL) {
return;
}
const menuList = toRaw(menus.value); const menuList = toRaw(menus.value);
if (!unref(accordion)) { if (!unref(accordion)) {
menuState.openKeys = es6Unique([...menuState.openKeys, ...getAllParentPath(menuList, path)]); menuState.openKeys = es6Unique([...menuState.openKeys, ...getAllParentPath(menuList, path)]);
......
<template> <template>
<div :class="[prefixCls, `${prefixCls}--${theme}`]"> <div :class="[prefixCls, `${prefixCls}--${theme}`]">
<a-breadcrumb :routes="routes"> <a-breadcrumb :routes="routes">
<template #itemRender="{ route, routes }"> <template #itemRender="{ route, routes, paths }">
<Icon :icon="route.meta.icon" v-if="getShowBreadCrumbIcon && route.meta.icon" /> <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) }} {{ t(route.meta.title) }}
</span> </span>
<router-link v-else :to="route.path"> <router-link v-else to="" @click="handleClick(route, paths, $event)">
{{ t(route.meta.title) }} {{ t(route.meta.title) }}
</router-link> </router-link>
</template> </template>
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
import { useRootSetting } from '/@/hooks/setting/useRootSetting'; import { useRootSetting } from '/@/hooks/setting/useRootSetting';
import { propTypes } from '/@/utils/propTypes'; import { propTypes } from '/@/utils/propTypes';
import { useGo } from '/@/hooks/web/usePage';
import { isString } from '/@/utils/is';
export default defineComponent({ export default defineComponent({
name: 'LayoutBreadcrumb', name: 'LayoutBreadcrumb',
...@@ -45,22 +47,12 @@ ...@@ -45,22 +47,12 @@
const { t } = useI18n(); const { t } = useI18n();
watchEffect(() => { watchEffect(() => {
if (currentRoute.value.name === REDIRECT_NAME) { if (currentRoute.value.name === REDIRECT_NAME) return;
return;
}
const matched = currentRoute.value?.matched; const matched = currentRoute.value?.matched;
if (!matched || matched.length === 0) return; if (!matched || matched.length === 0) return;
let breadcrumbList = filter(toRaw(matched), (item) => { let breadcrumbList = filterItem(toRaw(matched));
if (!item.meta) {
return false;
}
const { title, hideBreadcrumb } = item.meta;
if (!title || hideBreadcrumb) {
return false;
}
return true;
});
const filterBreadcrumbList = breadcrumbList.filter( const filterBreadcrumbList = breadcrumbList.filter(
(item) => item.path !== PageEnum.BASE_HOME (item) => item.path !== PageEnum.BASE_HOME
...@@ -71,13 +63,86 @@ ...@@ -71,13 +63,86 @@
path: PageEnum.BASE_HOME, path: PageEnum.BASE_HOME,
meta: { meta: {
title: t('layout.header.home'), title: t('layout.header.home'),
isLink: true,
}, },
} as unknown) as RouteLocationMatched); } 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> </script>
......
...@@ -59,7 +59,7 @@ export function handler(event: HandlerEnum, value: any): DeepPartial<ProjectConf ...@@ -59,7 +59,7 @@ export function handler(event: HandlerEnum, value: any): DeepPartial<ProjectConf
return { menuSetting: { bgColor: value } }; return { menuSetting: { bgColor: value } };
case HandlerEnum.MENU_SPLIT: case HandlerEnum.MENU_SPLIT:
return { menuSetting: { split: value, collapsedShowTitle: true } }; return { menuSetting: { split: value } };
case HandlerEnum.MENU_CLOSE_MIX_SIDEBAR_ON_CHANGE: case HandlerEnum.MENU_CLOSE_MIX_SIDEBAR_ON_CHANGE:
return { menuSetting: { closeMixSidebarOnChange: value } }; return { menuSetting: { closeMixSidebarOnChange: value } };
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
<div :class="`${prefixCls}-menu-list`" ref="sideRef" :style="getMenuStyle"> <div :class="`${prefixCls}-menu-list`" ref="sideRef" :style="getMenuStyle">
<div <div
v-show="openMenu"
:class="[ :class="[
`${prefixCls}-menu-list__title`, `${prefixCls}-menu-list__title`,
{ {
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
import { Tabs } from 'ant-design-vue'; import { Tabs } from 'ant-design-vue';
import TabContent from './components/TabContent.vue'; import TabContent from './components/TabContent.vue';
import type { RouteLocationNormalized } from 'vue-router';
import { useGo } from '/@/hooks/web/usePage'; import { useGo } from '/@/hooks/web/usePage';
...@@ -43,6 +44,8 @@ ...@@ -43,6 +44,8 @@
import { listenerLastChangeTab } from '/@/logics/mitt/tabChange'; import { listenerLastChangeTab } from '/@/logics/mitt/tabChange';
import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting'; import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';
import router from '/@/router';
export default defineComponent({ export default defineComponent({
name: 'MultipleTabs', name: 'MultipleTabs',
components: { components: {
...@@ -61,7 +64,9 @@ ...@@ -61,7 +64,9 @@
const go = useGo(); const go = useGo();
const { getShowQuick, getShowRedo } = useMultipleTabSetting(); 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); const unClose = computed(() => unref(getTabsState).length === 1);
...@@ -78,13 +83,24 @@ ...@@ -78,13 +83,24 @@
const { name } = route; const { name } = route;
if (name === REDIRECT_NAME || !route || !userStore.getTokenState) return; if (name === REDIRECT_NAME || !route || !userStore.getTokenState) return;
const { path, fullPath } = route; const { path, fullPath, meta = {} } = route;
const p = fullPath || path;
const { currentActiveMenu, hideTab } = meta;
const isHide = !hideTab ? null : currentActiveMenu;
const p = isHide || fullPath || path;
if (activeKeyRef.value !== p) { if (activeKeyRef.value !== p) {
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) { function handleChange(activeKey: any) {
......
...@@ -15,4 +15,11 @@ export default { ...@@ -15,4 +15,11 @@ export default {
tab: 'Tab with parameters', tab: 'Tab with parameters',
tab1: 'Tab with parameter 1', tab1: 'Tab with parameter 1',
tab2: 'Tab with parameter 2', tab2: 'Tab with parameter 2',
breadcrumb: 'Breadcrumbs',
breadcrumbFlat: 'Flat Mode',
breadcrumbFlatDetail: 'Flat mode details',
breadcrumbChildren: 'Level mode',
breadcrumbChildrenDetail: 'Level mode detail',
}; };
...@@ -15,4 +15,11 @@ export default { ...@@ -15,4 +15,11 @@ export default {
tab: 'Tab带参', tab: 'Tab带参',
tab1: 'Tab带参1', tab1: 'Tab带参1',
tab2: 'Tab带参2', tab2: 'Tab带参2',
breadcrumb: '面包屑导航',
breadcrumbFlat: '平级模式',
breadcrumbFlatDetail: '平级详情',
breadcrumbChildren: '层级模式',
breadcrumbChildrenDetail: '层级详情',
}; };
...@@ -16,7 +16,7 @@ function asyncImportRoute(routes: AppRouteRecordRaw[] | undefined) { ...@@ -16,7 +16,7 @@ function asyncImportRoute(routes: AppRouteRecordRaw[] | undefined) {
const { component, name } = item; const { component, name } = item;
const { children } = item; const { children } = item;
if (component) { if (component) {
item.component = dynamicImport(component); item.component = dynamicImport(component as string);
} else if (name) { } else if (name) {
item.component = getParentLayout(name); item.component = getParentLayout(name);
} }
...@@ -31,7 +31,7 @@ export function transformObjToRoute<T = AppRouteModule>(routeList: AppRouteModul ...@@ -31,7 +31,7 @@ export function transformObjToRoute<T = AppRouteModule>(routeList: AppRouteModul
routeList.forEach((route) => { routeList.forEach((route) => {
if (route.component) { if (route.component) {
if ((route.component as string).toUpperCase() === 'LAYOUT') { if ((route.component as string).toUpperCase() === 'LAYOUT') {
route.component = LayoutMap.get(route.component); route.component = LayoutMap.get(route.component as LayoutMapKey);
} else { } else {
route.children = [cloneDeep(route)]; route.children = [cloneDeep(route)];
route.component = LAYOUT; route.component = LAYOUT;
......
...@@ -71,8 +71,10 @@ export async function getShallowMenus(): Promise<Menu[]> { ...@@ -71,8 +71,10 @@ export async function getShallowMenus(): Promise<Menu[]> {
export async function getChildrenMenus(parentPath: string) { export async function getChildrenMenus(parentPath: string) {
const menus = await getAsyncMenus(); const menus = await getAsyncMenus();
const parent = menus.find((item) => item.path === parentPath); const parent = menus.find((item) => item.path === parentPath);
if (!parent) return [] as Menu[]; if (!parent || !parent.children) return [] as Menu[];
return parent.children; const routes = router.getRoutes();
return !isBackMode() ? filter(parent.children, basicFilter(routes)) : parent.children;
} }
// 通用过滤方法 // 通用过滤方法
......
...@@ -151,9 +151,6 @@ const menu: MenuModule = { ...@@ -151,9 +151,6 @@ const menu: MenuModule = {
{ {
path: 'loading', path: 'loading',
name: t('routes.demo.comp.loading'), name: t('routes.demo.comp.loading'),
tag: {
content: 'new',
},
}, },
{ {
path: 'tree', path: 'tree',
...@@ -176,6 +173,9 @@ const menu: MenuModule = { ...@@ -176,6 +173,9 @@ const menu: MenuModule = {
{ {
name: t('routes.demo.editor.editor'), name: t('routes.demo.editor.editor'),
path: 'editor', path: 'editor',
tag: {
content: 'new',
},
children: [ children: [
{ {
path: 'markdown', path: 'markdown',
......
...@@ -19,6 +19,7 @@ const menu: MenuModule = { ...@@ -19,6 +19,7 @@ const menu: MenuModule = {
path: 'tabs', path: 'tabs',
name: t('routes.demo.feat.tabs'), name: t('routes.demo.feat.tabs'),
}, },
{ {
path: 'context-menu', path: 'context-menu',
name: t('routes.demo.feat.contextMenu'), name: t('routes.demo.feat.contextMenu'),
...@@ -85,6 +86,27 @@ const menu: MenuModule = { ...@@ -85,6 +86,27 @@ const menu: MenuModule = {
}, },
], ],
}, },
{
name: t('routes.demo.feat.breadcrumb'),
path: 'breadcrumb',
tag: {
content: 'new',
},
children: [
{
path: 'flat',
name: t('routes.demo.feat.breadcrumbFlat'),
},
{
path: 'flatDetail',
name: t('routes.demo.feat.breadcrumbFlatDetail'),
},
{
path: 'children',
name: t('routes.demo.feat.breadcrumbChildrenDetail'),
},
],
},
{ {
path: 'testTab', path: 'testTab',
name: t('routes.demo.feat.tab'), name: t('routes.demo.feat.tab'),
......
...@@ -7,14 +7,14 @@ const menu: MenuModule = { ...@@ -7,14 +7,14 @@ const menu: MenuModule = {
name: t('routes.demo.iframe.frame'), name: t('routes.demo.iframe.frame'),
path: '/frame', path: '/frame',
children: [ children: [
{
path: 'antv',
name: t('routes.demo.iframe.antv'),
},
{ {
path: 'doc', path: 'doc',
name: t('routes.demo.iframe.doc'), name: t('routes.demo.iframe.doc'),
}, },
{
path: 'antv',
name: t('routes.demo.iframe.antv'),
},
{ {
path: 'https://vvbin.cn/doc-next/', path: 'https://vvbin.cn/doc-next/',
name: t('routes.demo.iframe.docExternal'), name: t('routes.demo.iframe.docExternal'),
......
...@@ -6,9 +6,6 @@ const menu: MenuModule = { ...@@ -6,9 +6,6 @@ const menu: MenuModule = {
menu: { menu: {
name: t('routes.demo.level.level'), name: t('routes.demo.level.level'),
path: '/level', path: '/level',
tag: {
dot: true,
},
children: [ children: [
{ {
path: 'menu1', path: 'menu1',
......
...@@ -6,9 +6,7 @@ const menu: MenuModule = { ...@@ -6,9 +6,7 @@ const menu: MenuModule = {
menu: { menu: {
name: t('routes.demo.page.page'), name: t('routes.demo.page.page'),
path: '/page-demo', path: '/page-demo',
tag: {
dot: true,
},
children: [ children: [
{ {
path: 'form', path: 'form',
...@@ -102,9 +100,6 @@ const menu: MenuModule = { ...@@ -102,9 +100,6 @@ const menu: MenuModule = {
{ {
path: 'list', path: 'list',
name: t('routes.demo.page.list'), name: t('routes.demo.page.list'),
tag: {
content: 'new',
},
children: [ children: [
{ {
path: 'basic', path: 'basic',
......
...@@ -13,6 +13,14 @@ const charts: AppRouteModule = { ...@@ -13,6 +13,14 @@ const charts: AppRouteModule = {
title: t('routes.demo.charts.charts'), title: t('routes.demo.charts.charts'),
}, },
children: [ children: [
{
path: 'apexChart',
name: 'ApexChart',
meta: {
title: t('routes.demo.charts.apexChart'),
},
component: () => import('/@/views/demo/echarts/apex/index.vue'),
},
{ {
path: 'echarts', path: 'echarts',
name: 'Echarts', name: 'Echarts',
...@@ -20,6 +28,7 @@ const charts: AppRouteModule = { ...@@ -20,6 +28,7 @@ const charts: AppRouteModule = {
meta: { meta: {
title: 'Echarts', title: 'Echarts',
}, },
redirect: '/charts/echarts/map',
children: [ children: [
{ {
path: 'map', path: 'map',
...@@ -47,14 +56,6 @@ const charts: AppRouteModule = { ...@@ -47,14 +56,6 @@ const charts: AppRouteModule = {
}, },
], ],
}, },
{
path: 'apexChart',
name: 'ApexChart',
meta: {
title: t('routes.demo.charts.apexChart'),
},
component: () => import('/@/views/demo/echarts/apex/index.vue'),
},
], ],
}; };
......
...@@ -29,6 +29,68 @@ const feat: AppRouteModule = { ...@@ -29,6 +29,68 @@ const feat: AppRouteModule = {
title: t('routes.demo.feat.tabs'), title: t('routes.demo.feat.tabs'),
}, },
}, },
{
path: 'breadcrumb',
name: 'BreadcrumbDemo',
redirect: '/feat/breadcrumb/flat',
component: getParentLayout('BreadcrumbDemo'),
meta: {
title: t('routes.demo.feat.breadcrumb'),
},
children: [
{
path: 'flat',
name: 'BreadcrumbFlatDemo',
component: () => import('/@/views/demo/feat/breadcrumb/FlatList.vue'),
meta: {
title: t('routes.demo.feat.breadcrumbFlat'),
},
},
{
path: 'flatDetail',
name: 'BreadcrumbFlatDetailDemo',
component: () => import('/@/views/demo/feat/breadcrumb/FlatListDetail.vue'),
meta: {
title: t('routes.demo.feat.breadcrumbFlatDetail'),
hideMenu: true,
hideTab: true,
currentActiveMenu: '/feat/breadcrumb/flat',
},
},
{
path: 'children',
name: 'BreadcrumbChildrenDemo',
component: getParentLayout('BreadcrumbChildrenDemo'),
redirect: '/feat/breadcrumb/children',
meta: {
title: t('routes.demo.feat.breadcrumbFlat'),
},
children: [
{
path: '',
name: 'BreadcrumbChildren',
component: () => import('/@/views/demo/feat/breadcrumb/ChildrenList.vue'),
meta: {
title: t('routes.demo.feat.breadcrumbChildren'),
hideBreadcrumb: true,
},
},
{
path: 'childrenDetail',
name: 'BreadcrumbChildrenDetailDemo',
component: () => import('/@/views/demo/feat/breadcrumb/ChildrenListDetail.vue'),
meta: {
currentActiveMenu: '/feat/breadcrumb/children',
title: t('routes.demo.feat.breadcrumbChildrenDetail'),
hideTab: true,
hideMenu: true,
},
},
],
},
],
},
{ {
path: 'context-menu', path: 'context-menu',
......
...@@ -8,7 +8,7 @@ const iframe: AppRouteModule = { ...@@ -8,7 +8,7 @@ const iframe: AppRouteModule = {
path: '/frame', path: '/frame',
name: 'Frame', name: 'Frame',
component: LAYOUT, component: LAYOUT,
redirect: '/frame/antv', redirect: '/frame/doc',
meta: { meta: {
icon: 'mdi:page-next-outline', icon: 'mdi:page-next-outline',
title: t('routes.demo.iframe.frame'), title: t('routes.demo.iframe.frame'),
...@@ -16,21 +16,21 @@ const iframe: AppRouteModule = { ...@@ -16,21 +16,21 @@ const iframe: AppRouteModule = {
children: [ children: [
{ {
path: 'antv', path: 'doc',
name: 'Antv', name: 'Doc',
component: IFrame, component: IFrame,
meta: { meta: {
frameSrc: 'https://2x.antdv.com/docs/vue/introduce-cn/', frameSrc: 'https://vvbin.cn/doc-next/',
title: t('routes.demo.iframe.antv'), title: t('routes.demo.iframe.doc'),
}, },
}, },
{ {
path: 'doc', path: 'antv',
name: 'Doc', name: 'Antv',
component: IFrame, component: IFrame,
meta: { meta: {
frameSrc: 'https://vvbin.cn/doc-next/', frameSrc: 'https://2x.antdv.com/docs/vue/introduce-cn/',
title: t('routes.demo.iframe.doc'), title: t('routes.demo.iframe.antv'),
}, },
}, },
{ {
......
...@@ -7,7 +7,7 @@ const permission: AppRouteModule = { ...@@ -7,7 +7,7 @@ const permission: AppRouteModule = {
path: '/level', path: '/level',
name: 'Level', name: 'Level',
component: LAYOUT, component: LAYOUT,
redirect: '/level/menu1/menu1-1', redirect: '/level/menu1/menu1-1/menu1-1-1',
meta: { meta: {
icon: 'carbon:user-role', icon: 'carbon:user-role',
title: t('routes.demo.level.level'), title: t('routes.demo.level.level'),
...@@ -21,6 +21,7 @@ const permission: AppRouteModule = { ...@@ -21,6 +21,7 @@ const permission: AppRouteModule = {
meta: { meta: {
title: 'Menu1', title: 'Menu1',
}, },
redirect: '/level/menu1/menu1-1/menu1-1-1',
children: [ children: [
{ {
path: 'menu1-1', path: 'menu1-1',
...@@ -29,6 +30,7 @@ const permission: AppRouteModule = { ...@@ -29,6 +30,7 @@ const permission: AppRouteModule = {
meta: { meta: {
title: 'Menu1-1', title: 'Menu1-1',
}, },
redirect: '/level/menu1/menu1-1/menu1-1-1',
children: [ children: [
{ {
path: 'menu1-1-1', path: 'menu1-1-1',
......
...@@ -30,13 +30,22 @@ export interface RouteMeta { ...@@ -30,13 +30,22 @@ export interface RouteMeta {
// Used internally to mark single-level menus // Used internally to mark single-level menus
single?: boolean; single?: boolean;
// Currently active menu
currentActiveMenu?: string;
// Never show in tab
hideTab?: boolean;
// Never show in menu
hideMenu?: boolean;
} }
// @ts-ignore // @ts-ignore
export interface AppRouteRecordRaw extends Omit<RouteRecordRaw, 'meta'> { export interface AppRouteRecordRaw extends Omit<RouteRecordRaw, 'meta'> {
name: string; name: string;
meta: RouteMeta; meta: RouteMeta;
component?: Component; component?: Component | string;
components?: Component; components?: Component;
children?: AppRouteRecordRaw[]; children?: AppRouteRecordRaw[];
props?: Record<string, any>; props?: Record<string, any>;
......
<template>
<div class="p-5">
<router-link to="/feat/breadcrumb/children/childrenDetail">进入子级详情页</router-link>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({});
</script>
<template>
<div> 子级详情页 </div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({});
</script>
<template>
<div class="p-5">
<router-link to="/feat/breadcrumb/flatDetail">进入平级详情页</router-link>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({});
</script>
<template>
<div> 平级详情页 </div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({});
</script>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册