feat(plugin-layout): 菜单支持配置额外的匹配规则

This commit is contained in:
wanchun 2022-01-05 16:38:20 +08:00
parent ab949fb6a8
commit c998c39559
6 changed files with 62 additions and 17 deletions

View File

@ -56,21 +56,21 @@ export default {
}
</config>
```
如果只是不想展示`side`,则:
如果只是不想展示`sidebar`,则:
```
<config lang="json">
{
"layout": {
"side": false
"sidebar": false
}
}
</config>
```
`layout`的可选配置有:
- **side** 左侧区域
- **sidebar** 左侧区域从v4.0.0开始,之前名称叫`side`
- **top** 头部区域
- **header** 头部区域,从v4.0.0开始,之前名称叫`top`
- **logo**logo和标题区域。
@ -182,6 +182,15 @@ export default {
- **name**:菜单的名称。通过匹配 `name` 和路由元信息 [meta](../../../guide/route.md#扩展路由元信息) 中的 `name`,把菜单和路由关联起来,然后使用路由元信息补充菜单配置,比如 `title`、`path` 等。
- **path**:菜单的路径,可配置第三方地址。
- **match**:额外匹配的路径,当前路由命中匹配规则时,此菜单高亮。 (v4.0.0+
```
{
path: '/product',
match: ['/product/*', '/product/create']
}
```
- **title**:菜单的标题,如果同时使用[国际化插件](./locale.md),而且`title`的值以`$`开头,则使用`$`后面的内容去匹配语言设置。

View File

@ -56,21 +56,21 @@ export default {
}
</config>
```
如果只是不想展示`side`,则:
如果只是不想展示`sidebar`,则:
```
<config lang="json">
{
"layout": {
"side": false
"sidebar": false
}
}
</config>
```
`layout`的可选配置有:
- **side** 左侧区域
- **sidebar** 左侧区域从v4.0.0开始,之前名称叫`side`
- **top** 头部区域
- **header** 头部区域,从v4.0.0开始,之前名称叫`top`
- **logo**logo和标题区域。
@ -182,6 +182,15 @@ export default {
- **name**:菜单的名称。通过匹配 `name` 和路由元信息 [meta](../../../guide/route.md#扩展路由元信息) 中的 `name`,把菜单和路由关联起来,然后使用路由元信息补充菜单配置,比如 `title`、`path` 等。
- **path**:菜单的路径,可配置第三方地址。
- **match**:额外匹配的路径,当前路由命中匹配规则时,此菜单高亮。 (v4.0.0+
```
{
path: '/product',
match: ['/product/*', '/product/create']
}
```
- **title**:菜单的标题,如果同时使用[国际化插件](./locale.md),而且`title`的值以`$`开头,则使用`$`后面的内容去匹配语言设置。

View File

@ -0,0 +1,9 @@
export const flatNodes = (nodes = []) => nodes.reduce((res, node) => {
res.push(node);
if (node.children) {
res = res.concat(
flatNodes(node.children)
);
}
return res;
}, []);

View File

@ -2,7 +2,7 @@
<f-layout v-if="routeLayout" class="main-layout">
<template v-if="navigation === 'side'">
<f-aside
v-if="routeLayout.side"
v-if="routeLayout.sidebar"
v-model:collapsed="collapsed"
:fixed="fixedSideBar"
class="layout-aside"
@ -32,7 +32,7 @@
}"
>
<f-header
v-if="routeLayout.top"
v-if="routeLayout.header"
class="layout-header"
:fixed="currentFixedHeader"
>
@ -59,7 +59,7 @@
</template>
<template v-if="navigation === 'top'">
<f-header
v-if="routeLayout.top"
v-if="routeLayout.header"
class="layout-header"
:inverted="theme === 'dark'"
:fixed="currentFixedHeader"
@ -96,7 +96,7 @@
</template>
<template v-if="navigation === 'mixin'">
<f-header
v-if="routeLayout.top"
v-if="routeLayout.header"
class="layout-header"
:fixed="currentFixedHeader"
:inverted="theme === 'dark'"
@ -117,7 +117,7 @@
:style="{ top: currentFixedHeader ? '54px' : 'auto' }"
>
<f-aside
v-if="routeLayout.side"
v-if="routeLayout.sidebar"
v-model:collapsed="collapsed"
:fixed="fixedSideBar"
collapsible
@ -226,8 +226,8 @@ export default {
key: 'layout',
type: ApplyPluginsType.modify,
initialValue: {
side: true,
top: true,
sidebar: true,
header: true,
logo: true
}
});

View File

@ -1,6 +1,6 @@
<template>
<f-menu
:modelValue="route.path"
:modelValue="activePath"
:inverted="inverted"
:mode="mode"
:options="fixedMenus"
@ -15,6 +15,7 @@ import { useRoute, useRouter } from '@@/core/coreExports';
import MenuIcon from './MenuIcon';
import { transform as transformByAccess } from '../helpers/pluginAccess';
import { transform as transformByLocale } from '../helpers/pluginLocale';
import { flatNodes } from '../helpers/utils';
export default {
components: {
@ -56,6 +57,23 @@ export default {
return copy;
});
const fixedMenus = computed(() => transformByLocale(transformByAccess(transform(props.menus))));
const menus = computed(() => flatNodes(fixedMenus.value));
const activePath = computed(() => {
const matchMenus = menus.value.filter((menu) => {
const match = menu.match;
if (!match || !Array.isArray(match)) {
return false;
}
return match.some((str) => {
const reg = new RegExp(str);
return reg.test(route.path);
});
});
if (matchMenus.length === 0) {
return route.path;
}
return matchMenus[0].path;
});
const onMenuClick = (e) => {
const path = e.value;
if (/^https?:\/\//.test(path)) {
@ -69,7 +87,7 @@ export default {
}
};
return {
route,
activePath,
fixedMenus,
onMenuClick
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 50 KiB