mirror of
https://github.com/WeBankFinTech/fes.js.git
synced 2025-06-28 09:29:22 +08:00
feat(plugin-layout): 代码逻辑优化
This commit is contained in:
parent
380bffe831
commit
791bdbbc59
BIN
docs/public/top-left-right.png
Normal file
BIN
docs/public/top-left-right.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 58 KiB |
@ -9,7 +9,7 @@ import { withBase } from 'vitepress'
|
|||||||
为了进一步降低研发成本,我们将布局利用 `fes.js` 插件的方式内置,只需通过简单的配置即可拥有布局,包括导航以及侧边栏。从而做到用户无需关心布局。
|
为了进一步降低研发成本,我们将布局利用 `fes.js` 插件的方式内置,只需通过简单的配置即可拥有布局,包括导航以及侧边栏。从而做到用户无需关心布局。
|
||||||
|
|
||||||
- 侧边栏菜单数据根据路由中的配置自动生成。
|
- 侧边栏菜单数据根据路由中的配置自动生成。
|
||||||
- 布局,提供 `side`、 `top`、`mixin`、`left-right` 四种布局。
|
- 布局,提供 `side`、 `top`、`mixin`、`left-right`、`top-left-right` 五种布局。
|
||||||
- 主题,提供 `light`、`dark` 两种主题。
|
- 主题,提供 `light`、`dark` 两种主题。
|
||||||
- 默认实现对路由的 404、403 处理。
|
- 默认实现对路由的 404、403 处理。
|
||||||
- 搭配 [@fesjs/plugin-access](./access.html) 插件使用,可以完成对路由的权限控制。
|
- 搭配 [@fesjs/plugin-access](./access.html) 插件使用,可以完成对路由的权限控制。
|
||||||
@ -34,7 +34,7 @@ import { withBase } from 'vitepress'
|
|||||||
|
|
||||||
## 布局类型
|
## 布局类型
|
||||||
|
|
||||||
配置参数是 `navigation`, 布局有三种类型 `side`、`mixin` 、`top` 和 `left-right`, 默认是 `side`。
|
配置参数是 `navigation`, 布局有五种类型 `side`、`mixin` 、`top` 、`left-right`、`top-left-right`, 默认是 `side`。
|
||||||
|
|
||||||
### side
|
### side
|
||||||
|
|
||||||
@ -53,9 +53,12 @@ import { withBase } from 'vitepress'
|
|||||||
|
|
||||||
### left-right
|
### left-right
|
||||||
|
|
||||||
<!--  -->
|
<!--  -->
|
||||||
<img :src="withBase('left-right.png')" alt="left-right">
|
<img :src="withBase('left-right.png')" alt="left-right">
|
||||||
|
|
||||||
|
<!--  -->
|
||||||
|
<img :src="withBase('top-left-right.png')" alt="top-left-right">
|
||||||
|
|
||||||
### 页面个性化
|
### 页面个性化
|
||||||
|
|
||||||
可以为页面单独设置布局类型:
|
可以为页面单独设置布局类型:
|
||||||
@ -258,6 +261,10 @@ export const layout = {
|
|||||||
|
|
||||||
- **path**:菜单的路径,可配置第三方地址。
|
- **path**:菜单的路径,可配置第三方地址。
|
||||||
|
|
||||||
|
- **query**:同 vue-router 的 query 参数。
|
||||||
|
|
||||||
|
- **params**:同 vue-router 的 params 参数。
|
||||||
|
|
||||||
- **match (v4.0.0+)**:额外匹配的路径,当前路由命中匹配规则时,此菜单高亮。
|
- **match (v4.0.0+)**:额外匹配的路径,当前路由命中匹配规则时,此菜单高亮。
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -127,7 +127,7 @@
|
|||||||
</FFooter>
|
</FFooter>
|
||||||
</FLayout>
|
</FLayout>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="currentNavigation === 'top-left'">
|
<template v-else-if="currentNavigation === 'top-left-right'">
|
||||||
<FHeader ref="headerRef" class="layout-header" :inverted="theme === 'dark'" :fixed="currentFixedHeaderRef">
|
<FHeader ref="headerRef" class="layout-header" :inverted="theme === 'dark'" :fixed="currentFixedHeaderRef">
|
||||||
<div class="layout-logo">
|
<div class="layout-logo">
|
||||||
<img v-if="logo" :src="logo" class="logo-img">
|
<img v-if="logo" :src="logo" class="logo-img">
|
||||||
@ -140,7 +140,6 @@
|
|||||||
:menus="rootMenus"
|
:menus="rootMenus"
|
||||||
mode="horizontal"
|
mode="horizontal"
|
||||||
:inverted="theme === 'dark'"
|
:inverted="theme === 'dark'"
|
||||||
:navigation="currentNavigation"
|
|
||||||
/>
|
/>
|
||||||
<div class="layout-header-custom">
|
<div class="layout-header-custom">
|
||||||
<slot name="renderCustom" :menus="menus" />
|
<slot name="renderCustom" :menus="menus" />
|
||||||
@ -150,7 +149,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</FHeader>
|
</FHeader>
|
||||||
<FLayout v-if="activeSubMenus.length" :embedded="!multiTabs" :fixed="currentFixedHeaderRef" :style="headerStyleRef">
|
<FLayout v-if="activeSubMenus.length" :embedded="!multiTabs" :fixed="currentFixedHeaderRef" :style="headerStyleRef">
|
||||||
<FAside v-model:collapsed="collapsedRef" :fixed="isFixedSidebar" :width="`${sideWidth}px`" collapsible class="layout-aside">
|
<FAside v-model:collapsed="collapsedRef" :inverted="theme === 'dark'" :fixed="isFixedSidebar" :width="`${sideWidth}px`" collapsible class="layout-aside">
|
||||||
<LayoutMenu
|
<LayoutMenu
|
||||||
class="layout-menu"
|
class="layout-menu"
|
||||||
:menus="activeSubMenus"
|
:menus="activeSubMenus"
|
||||||
@ -159,6 +158,7 @@
|
|||||||
:expanded-keys="menuProps?.expandedKeys"
|
:expanded-keys="menuProps?.expandedKeys"
|
||||||
:default-expand-all="menuProps?.defaultExpandAll"
|
:default-expand-all="menuProps?.defaultExpandAll"
|
||||||
:accordion="menuProps?.accordion"
|
:accordion="menuProps?.accordion"
|
||||||
|
:inverted="theme === 'dark'"
|
||||||
/>
|
/>
|
||||||
</FAside>
|
</FAside>
|
||||||
|
|
||||||
@ -269,7 +269,7 @@ export default {
|
|||||||
},
|
},
|
||||||
navigation: {
|
navigation: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'side', // side 左右(上/下)、 top 上/下、 mixin 上/下(左/右)
|
default: 'side', // side 左右(上/下)、 top 上/下、 mixin 上/下(左/右)、top-left-right 上/下(左/右)
|
||||||
},
|
},
|
||||||
navigationOnError: {
|
navigationOnError: {
|
||||||
type: [String, Function], // 403, 404 时的 navigation
|
type: [String, Function], // 403, 404 时的 navigation
|
||||||
@ -339,9 +339,21 @@ export default {
|
|||||||
const rootMenus = computed(() => {
|
const rootMenus = computed(() => {
|
||||||
return props.menus.map((menu) => {
|
return props.menus.map((menu) => {
|
||||||
const { children, match, ...others } = menu;
|
const { children, match, ...others } = menu;
|
||||||
|
let { path, query, params } = menu;
|
||||||
const flatChildren = flatNodes(children || []);
|
const flatChildren = flatNodes(children || []);
|
||||||
|
if (!menu.path) {
|
||||||
|
const firstChild = flatChildren.find(item => item.path);
|
||||||
|
if (firstChild) {
|
||||||
|
path = firstChild.path;
|
||||||
|
query = firstChild.query;
|
||||||
|
params = firstChild.params;
|
||||||
|
}
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
...others,
|
...others,
|
||||||
|
path,
|
||||||
|
query,
|
||||||
|
params,
|
||||||
match: (match || [])
|
match: (match || [])
|
||||||
.concat(...flatChildren.map(item => []
|
.concat(...flatChildren.map(item => []
|
||||||
.concat(item.match || [])
|
.concat(item.match || [])
|
||||||
|
@ -73,7 +73,6 @@ export default {
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
navigation: String,
|
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
@ -94,13 +93,7 @@ export default {
|
|||||||
if (matchMenus.length === 0) {
|
if (matchMenus.length === 0) {
|
||||||
return route.path;
|
return route.path;
|
||||||
}
|
}
|
||||||
// 兼容 top-left 布局情况下,匹配菜单可能没有 path 的情况
|
|
||||||
if (props.navigation === 'top-left') {
|
|
||||||
return matchMenus[0].value;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return matchMenus[0].path;
|
return matchMenus[0].path;
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const expandedKeysRef = ref(props.expandedKeys);
|
const expandedKeysRef = ref(props.expandedKeys);
|
||||||
@ -131,17 +124,8 @@ export default {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const onMenuClick = (e) => {
|
const onMenuClick = (e) => {
|
||||||
let path = e.value;
|
const path = e.value;
|
||||||
let currentMenu = menuArray.value.find(item => item.value === path);
|
const currentMenu = menuArray.value.find(item => item.value === path);
|
||||||
|
|
||||||
// 兼容 top-left 顶部导航没有链接的情况
|
|
||||||
if (props.navigation === 'top-left' && currentMenu && !currentMenu.path) {
|
|
||||||
// 判断当前菜单是否有子菜单
|
|
||||||
if (currentMenu._children && currentMenu._children.length > 0) {
|
|
||||||
path = currentMenu._children[0].path;
|
|
||||||
currentMenu = currentMenu._children[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (/^https?:\/\//.test(path)) {
|
if (/^https?:\/\//.test(path)) {
|
||||||
window.open(path, '_blank');
|
window.open(path, '_blank');
|
||||||
@ -149,8 +133,8 @@ export default {
|
|||||||
else if (/^\//.test(path)) {
|
else if (/^\//.test(path)) {
|
||||||
router.push({
|
router.push({
|
||||||
path,
|
path,
|
||||||
query: currentMenu.query || {},
|
query: currentMenu?.query || {},
|
||||||
params: currentMenu.params || {},
|
params: currentMenu?.params || {},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -54,6 +54,7 @@ export default defineBuildConfig({
|
|||||||
{
|
{
|
||||||
title: '子菜单',
|
title: '子菜单',
|
||||||
path: '/menuTest',
|
path: '/menuTest',
|
||||||
|
query: { id: 1 },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -23,8 +23,9 @@ export const beforeRender = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const layout = {
|
export const layout = {
|
||||||
logo: `${process.env.BASE_URL}wine-outline.svg`,
|
// eslint-disable-next-line node/prefer-global/process
|
||||||
renderCustom: (props) => {
|
logo: `${process.env.BASE_URL}logo.png`,
|
||||||
|
renderCustom: () => {
|
||||||
return <UserCenter />;
|
return <UserCenter />;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user