mirror of
https://github.com/WeBankFinTech/fes.js.git
synced 2025-04-06 03:59:53 +08:00
feat(plugin-layout): 支持配置 403、404 的 navigation
This commit is contained in:
parent
2bb6903bb3
commit
426cc13d7c
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<f-layout class="main-layout">
|
||||
<FLayout class="main-layout">
|
||||
<template v-if="currentNavigation === 'side'">
|
||||
<f-aside
|
||||
<FAside
|
||||
v-model:collapsed="collapsedRef"
|
||||
:fixed="isFixedSidebar"
|
||||
:width="`${sideWidth}px`"
|
||||
@ -10,41 +10,43 @@
|
||||
:inverted="theme === 'dark'"
|
||||
>
|
||||
<div class="layout-logo">
|
||||
<img v-if="logo" :src="logo" class="logo-img" />
|
||||
<div v-if="title" class="logo-name">{{ title }}</div>
|
||||
<img v-if="logo" :src="logo" class="logo-img">
|
||||
<div v-if="title" class="logo-name">
|
||||
{{ title }}
|
||||
</div>
|
||||
</div>
|
||||
<Menu
|
||||
<LayoutMenu
|
||||
class="layout-menu"
|
||||
:menus="menus"
|
||||
:collapsed="collapsedRef"
|
||||
mode="vertical"
|
||||
:inverted="theme === 'dark'"
|
||||
:expandedKeys="menuProps?.expandedKeys"
|
||||
:defaultExpandAll="menuProps?.defaultExpandAll"
|
||||
:expanded-keys="menuProps?.expandedKeys"
|
||||
:default-expand-all="menuProps?.defaultExpandAll"
|
||||
:accordion="menuProps?.accordion"
|
||||
/>
|
||||
</f-aside>
|
||||
<f-layout :fixed="isFixedSidebar" :style="sideStyleRef">
|
||||
<f-header ref="headerRef" class="layout-header" :fixed="currentFixedHeaderRef">
|
||||
</FAside>
|
||||
<FLayout :fixed="isFixedSidebar" :style="sideStyleRef">
|
||||
<FHeader ref="headerRef" class="layout-header" :fixed="currentFixedHeaderRef">
|
||||
<div class="layout-header-custom">
|
||||
<slot name="renderCustom" :menus="menus"></slot>
|
||||
<slot name="renderCustom" :menus="menus" />
|
||||
</div>
|
||||
<template v-if="locale">
|
||||
<slot name="locale"></slot>
|
||||
<slot name="locale" />
|
||||
</template>
|
||||
</f-header>
|
||||
<f-layout :embedded="!multiTabs" :fixed="currentFixedHeaderRef" :style="headerStyleRef">
|
||||
<f-main class="layout-main">
|
||||
<MultiTabProvider :multiTabs="multiTabs" />
|
||||
</f-main>
|
||||
<f-footer v-if="footer" class="layout-footer">
|
||||
</FHeader>
|
||||
<FLayout :embedded="!multiTabs" :fixed="currentFixedHeaderRef" :style="headerStyleRef">
|
||||
<FMain class="layout-main">
|
||||
<MultiTabProvider :multi-tabs="multiTabs" />
|
||||
</FMain>
|
||||
<FFooter v-if="footer" class="layout-footer">
|
||||
{{ footer }}
|
||||
</f-footer>
|
||||
</f-layout>
|
||||
</f-layout>
|
||||
</FFooter>
|
||||
</FLayout>
|
||||
</FLayout>
|
||||
</template>
|
||||
<template v-else-if="currentNavigation === 'left-right'">
|
||||
<f-aside
|
||||
<FAside
|
||||
v-model:collapsed="collapsedRef"
|
||||
:fixed="isFixedSidebar"
|
||||
:width="`${sideWidth}px`"
|
||||
@ -55,121 +57,127 @@
|
||||
<div class="flex-between">
|
||||
<div>
|
||||
<div class="layout-logo">
|
||||
<img v-if="logo" :src="logo" class="logo-img" />
|
||||
<div v-if="title" class="logo-name">{{ title }}</div>
|
||||
<img v-if="logo" :src="logo" class="logo-img">
|
||||
<div v-if="title" class="logo-name">
|
||||
{{ title }}
|
||||
</div>
|
||||
</div>
|
||||
<Menu
|
||||
<LayoutMenu
|
||||
class="layout-menu"
|
||||
:menus="menus"
|
||||
:collapsed="collapsedRef"
|
||||
mode="vertical"
|
||||
:inverted="theme === 'dark'"
|
||||
:expandedKeys="menuProps?.expandedKeys"
|
||||
:defaultExpandAll="menuProps?.defaultExpandAll"
|
||||
:expanded-keys="menuProps?.expandedKeys"
|
||||
:default-expand-all="menuProps?.defaultExpandAll"
|
||||
:accordion="menuProps?.accordion"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div class="layout-aside-custom">
|
||||
<slot name="renderCustom" :menus="menus"></slot>
|
||||
<slot name="renderCustom" :menus="menus" />
|
||||
</div>
|
||||
<div v-if="locale" class="layout-aside-locale">
|
||||
<slot name="locale"></slot>
|
||||
<slot name="locale" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</f-aside>
|
||||
<f-layout :fixed="isFixedSidebar" :style="sideStyleRef">
|
||||
<f-layout :embedded="!multiTabs">
|
||||
<f-main class="layout-main">
|
||||
<MultiTabProvider :multiTabs="multiTabs" />
|
||||
</f-main>
|
||||
<f-footer v-if="footer" class="layout-footer">
|
||||
</FAside>
|
||||
<FLayout :fixed="isFixedSidebar" :style="sideStyleRef">
|
||||
<FLayout :embedded="!multiTabs">
|
||||
<FMain class="layout-main">
|
||||
<MultiTabProvider :multi-tabs="multiTabs" />
|
||||
</FMain>
|
||||
<FFooter v-if="footer" class="layout-footer">
|
||||
{{ footer }}
|
||||
</f-footer>
|
||||
</f-layout>
|
||||
</f-layout>
|
||||
</FFooter>
|
||||
</FLayout>
|
||||
</FLayout>
|
||||
</template>
|
||||
<template v-else-if="currentNavigation === 'top'">
|
||||
<f-header 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">
|
||||
<img v-if="logo" :src="logo" class="logo-img" />
|
||||
<div v-if="title" class="logo-name">{{ title }}</div>
|
||||
<img v-if="logo" :src="logo" class="logo-img">
|
||||
<div v-if="title" class="logo-name">
|
||||
{{ title }}
|
||||
</div>
|
||||
</div>
|
||||
<Menu
|
||||
<LayoutMenu
|
||||
class="layout-menu"
|
||||
:menus="menus"
|
||||
mode="horizontal"
|
||||
:inverted="theme === 'dark'"
|
||||
:expandedKeys="menuProps?.expandedKeys"
|
||||
:defaultExpandAll="menuProps?.defaultExpandAll"
|
||||
:expanded-keys="menuProps?.expandedKeys"
|
||||
:default-expand-all="menuProps?.defaultExpandAll"
|
||||
:accordion="menuProps?.accordion"
|
||||
/>
|
||||
<div class="layout-header-custom">
|
||||
<slot name="renderCustom" :menus="menus"></slot>
|
||||
<slot name="renderCustom" :menus="menus" />
|
||||
</div>
|
||||
<template v-if="locale">
|
||||
<slot name="locale"></slot>
|
||||
<slot name="locale" />
|
||||
</template>
|
||||
</f-header>
|
||||
<f-layout :embedded="!multiTabs" :fixed="currentFixedHeaderRef" :style="headerStyleRef">
|
||||
<f-main class="layout-main">
|
||||
<MultiTabProvider :multiTabs="multiTabs" />
|
||||
</f-main>
|
||||
<f-footer v-if="footer" class="layout-footer">
|
||||
</FHeader>
|
||||
<FLayout :embedded="!multiTabs" :fixed="currentFixedHeaderRef" :style="headerStyleRef">
|
||||
<FMain class="layout-main">
|
||||
<MultiTabProvider :multi-tabs="multiTabs" />
|
||||
</FMain>
|
||||
<FFooter v-if="footer" class="layout-footer">
|
||||
{{ footer }}
|
||||
</f-footer>
|
||||
</f-layout>
|
||||
</FFooter>
|
||||
</FLayout>
|
||||
</template>
|
||||
<template v-else-if="currentNavigation === 'mixin'">
|
||||
<f-header ref="headerRef" class="layout-header" :fixed="currentFixedHeaderRef" :inverted="theme === 'dark'">
|
||||
<FHeader ref="headerRef" class="layout-header" :fixed="currentFixedHeaderRef" :inverted="theme === 'dark'">
|
||||
<div class="layout-logo">
|
||||
<img v-if="logo" :src="logo" class="logo-img" />
|
||||
<div v-if="title" class="logo-name">{{ title }}</div>
|
||||
<img v-if="logo" :src="logo" class="logo-img">
|
||||
<div v-if="title" class="logo-name">
|
||||
{{ title }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-header-custom">
|
||||
<slot name="renderCustom" :menus="menus"></slot>
|
||||
<slot name="renderCustom" :menus="menus" />
|
||||
</div>
|
||||
<template v-if="locale">
|
||||
<slot name="locale"></slot>
|
||||
<slot name="locale" />
|
||||
</template>
|
||||
</f-header>
|
||||
<f-layout :fixed="currentFixedHeaderRef" :style="headerStyleRef">
|
||||
<f-aside v-model:collapsed="collapsedRef" :fixed="isFixedSidebar" :width="`${sideWidth}px`" collapsible class="layout-aside">
|
||||
<Menu
|
||||
</FHeader>
|
||||
<FLayout :fixed="currentFixedHeaderRef" :style="headerStyleRef">
|
||||
<FAside v-model:collapsed="collapsedRef" :fixed="isFixedSidebar" :width="`${sideWidth}px`" collapsible class="layout-aside">
|
||||
<LayoutMenu
|
||||
class="layout-menu"
|
||||
:menus="menus"
|
||||
:collapsed="collapsedRef"
|
||||
mode="vertical"
|
||||
:expandedKeys="menuProps?.expandedKeys"
|
||||
:defaultExpandAll="menuProps?.defaultExpandAll"
|
||||
:expanded-keys="menuProps?.expandedKeys"
|
||||
:default-expand-all="menuProps?.defaultExpandAll"
|
||||
:accordion="menuProps?.accordion"
|
||||
/>
|
||||
</f-aside>
|
||||
<f-layout :embedded="!multiTabs" :fixed="isFixedSidebar" :style="sideStyleRef">
|
||||
<f-main class="layout-main">
|
||||
<MultiTabProvider :multiTabs="multiTabs" />
|
||||
</f-main>
|
||||
<f-footer v-if="footer" class="layout-footer">
|
||||
</FAside>
|
||||
<FLayout :embedded="!multiTabs" :fixed="isFixedSidebar" :style="sideStyleRef">
|
||||
<FMain class="layout-main">
|
||||
<MultiTabProvider :multi-tabs="multiTabs" />
|
||||
</FMain>
|
||||
<FFooter v-if="footer" class="layout-footer">
|
||||
{{ footer }}
|
||||
</f-footer>
|
||||
</f-layout>
|
||||
</f-layout>
|
||||
</FFooter>
|
||||
</FLayout>
|
||||
</FLayout>
|
||||
</template>
|
||||
<template v-else>
|
||||
<f-main class="layout-main">
|
||||
<router-view></router-view>
|
||||
</f-main>
|
||||
<FMain class="layout-main">
|
||||
<router-view />
|
||||
</FMain>
|
||||
</template>
|
||||
</f-layout>
|
||||
</FLayout>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref, computed, watch, nextTick } from 'vue';
|
||||
import { useRoute, useRouter } from '@@/core/coreExports';
|
||||
import { FLayout, FAside, FMain, FFooter, FHeader } from '@fesjs/fes-design';
|
||||
import { FAside, FFooter, FHeader, FLayout, FMain } from '@fesjs/fes-design';
|
||||
import { computed, nextTick, ref, watch } from 'vue';
|
||||
import defaultLogo from '../assets/logo.png';
|
||||
import Menu from './Menu.vue';
|
||||
import LayoutMenu from './Menu.vue';
|
||||
import MultiTabProvider from './MultiTabProvider.vue';
|
||||
|
||||
export default {
|
||||
@ -179,7 +187,7 @@ export default {
|
||||
FMain,
|
||||
FFooter,
|
||||
FHeader,
|
||||
Menu,
|
||||
LayoutMenu,
|
||||
MultiTabProvider,
|
||||
},
|
||||
props: {
|
||||
@ -209,6 +217,9 @@ export default {
|
||||
type: String,
|
||||
default: 'side', // side 左右(上/下)、 top 上/下、 mixin 上/下(左/右)
|
||||
},
|
||||
navigationOnError: {
|
||||
type: String, // 403, 404 时的 navigation
|
||||
},
|
||||
isFixedHeader: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
@ -241,6 +252,12 @@ export default {
|
||||
if (route.meta.layout && route.meta.layout.navigation !== undefined) {
|
||||
return route.meta.layout.navigation;
|
||||
}
|
||||
if (props.navigationOnError !== undefined && ['/403', '/404'].includes(route.path)) {
|
||||
if (typeof props.navigationOnError === 'function') {
|
||||
return props.navigationOnError(route);
|
||||
}
|
||||
return props.navigationOnError;
|
||||
}
|
||||
return props.navigation;
|
||||
});
|
||||
|
||||
@ -278,6 +295,7 @@ export default {
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.main-layout {
|
||||
height: 100vh;
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { unref, defineComponent, computed } from 'vue';
|
||||
import { plugin } from '@@/core/coreExports';
|
||||
import { getRoutes } from '@@/core/routes/routes';
|
||||
// eslint-disable-next-line import/extensions
|
||||
import getConfig from '../helpers/getConfig';
|
||||
import { computed, defineComponent, unref } from 'vue';
|
||||
|
||||
import fillMenu from '../helpers/fillMenu';
|
||||
import getConfig from '../helpers/getConfig';
|
||||
import BaseLayout from './BaseLayout.vue';
|
||||
|
||||
const Layout = defineComponent({
|
||||
@ -33,11 +33,12 @@ const Layout = defineComponent({
|
||||
return (
|
||||
<BaseLayout
|
||||
menus={filledMenuRef.value}
|
||||
locale={localeShared ? true : false}
|
||||
locale={!!localeShared}
|
||||
title={config.title}
|
||||
logo={config.logo}
|
||||
theme={config.theme}
|
||||
navigation={config.navigation}
|
||||
navigationOnError={config.navigationOnError}
|
||||
isFixedHeader={config.isFixedHeader}
|
||||
isFixedSidebar={config.isFixedSidebar}
|
||||
multiTabs={config.multiTabs}
|
||||
@ -45,7 +46,7 @@ const Layout = defineComponent({
|
||||
footer={config.footer}
|
||||
menuProps={config.menuProps}
|
||||
v-slots={slots}
|
||||
></BaseLayout>
|
||||
/>
|
||||
);
|
||||
};
|
||||
},
|
||||
|
46
packages/fes-plugin-layout/types.d.ts
vendored
46
packages/fes-plugin-layout/types.d.ts
vendored
@ -1,6 +1,6 @@
|
||||
import { Component, VNode, Ref } from 'vue';
|
||||
import { Router, RouteLocationNormalized, NavigationGuardNext, NavigationGuard } from 'vue-router';
|
||||
import { MenuOption } from '@fesjs/fes-design/es/menu/interface';
|
||||
import type { MenuOption } from '@fesjs/fes-design/es/menu/interface';
|
||||
import type { Component, Ref, VNode } from 'vue';
|
||||
import type { NavigationGuard, NavigationGuardNext, RouteLocationNormalized, Router } from 'vue-router';
|
||||
|
||||
interface CustomNavigationGuardOption {
|
||||
router: Router;
|
||||
@ -22,6 +22,8 @@ interface Menu {
|
||||
children?: Menu[];
|
||||
}
|
||||
|
||||
type Navigation = 'side' | 'mixin' | 'top' | 'left-right';
|
||||
|
||||
export const Page: Component;
|
||||
|
||||
export function useTabTitle(title: string | Ref<string>): void;
|
||||
@ -29,7 +31,8 @@ export function useTabTitle(title: string | Ref<string>): void;
|
||||
interface LayoutRuntimeConfig {
|
||||
footer?: string;
|
||||
theme?: 'dark' | 'light';
|
||||
navigation?: 'side' | 'top' | 'mixin' | 'left-right';
|
||||
navigation?: Navigation;
|
||||
navigationOnError?: Navigation | ((route: RouteLocationNormalized) => Navigation | null);
|
||||
title?: string;
|
||||
isFixedHeader?: boolean;
|
||||
isFixedSidebar?: boolean;
|
||||
@ -51,28 +54,29 @@ declare module '@fesjs/fes' {
|
||||
interface RouteMeta {
|
||||
'keep-alive'?: boolean;
|
||||
layout?: {
|
||||
navigation?: 'side' | 'mixin' | 'top' | 'left-right' | null;
|
||||
navigation?: Navigation | null;
|
||||
};
|
||||
}
|
||||
interface PluginBuildConfig {
|
||||
layout?:
|
||||
| {
|
||||
footer: string;
|
||||
theme: 'dark' | 'light';
|
||||
navigation: 'side' | 'top' | 'mixin' | 'left-right';
|
||||
title: string;
|
||||
isFixedHeader: boolean;
|
||||
isFixedSidebar: boolean;
|
||||
logo: string;
|
||||
multiTabs: boolean;
|
||||
sideWidth: number;
|
||||
menus: Menu[];
|
||||
menuProps: {
|
||||
expandedKeys: string[];
|
||||
defaultExpandAll: boolean;
|
||||
accordion: boolean;
|
||||
};
|
||||
}
|
||||
footer: string;
|
||||
theme: 'dark' | 'light';
|
||||
navigation: Navigation;
|
||||
navigationOnError: Navigation;
|
||||
title: string;
|
||||
isFixedHeader: boolean;
|
||||
isFixedSidebar: boolean;
|
||||
logo: string;
|
||||
multiTabs: boolean;
|
||||
sideWidth: number;
|
||||
menus: Menu[];
|
||||
menuProps: {
|
||||
expandedKeys: string[];
|
||||
defaultExpandAll: boolean;
|
||||
accordion: boolean;
|
||||
};
|
||||
}
|
||||
| false;
|
||||
}
|
||||
interface PluginRuntimeConfig {
|
||||
|
Loading…
x
Reference in New Issue
Block a user