mirror of
https://gitee.com/WeBank/fes.js.git
synced 2024-11-29 18:28:09 +08:00
feat(plugin-layout): 支持配置 403、404 的 navigation (#224)
* feat: 升级 eslint 配置及版本 * feat(plugin-layout): 支持配置 403、404 的 navigation * docs: 补充文档
This commit is contained in:
parent
14d7f6eaad
commit
74fa0ba122
71
.vscode/settings.json
vendored
71
.vscode/settings.json
vendored
@ -1,48 +1,35 @@
|
|||||||
{
|
{
|
||||||
// Enable the ESlint flat config support
|
// Enable the ESlint flat config support
|
||||||
"eslint.experimental.useFlatConfig": true,
|
"eslint.experimental.useFlatConfig": true,
|
||||||
|
|
||||||
// Disable the default formatter, use eslint instead
|
// Disable the default formatter, use eslint instead
|
||||||
"prettier.enable": false,
|
"prettier.enable": false,
|
||||||
"editor.formatOnSave": false,
|
"editor.formatOnSave": false,
|
||||||
|
|
||||||
// Auto fix
|
// Auto fix
|
||||||
"editor.codeActionsOnSave": {
|
"editor.codeActionsOnSave": {
|
||||||
"source.fixAll.eslint": "explicit",
|
"source.fixAll.eslint": "explicit",
|
||||||
"source.organizeImports": "never"
|
"source.organizeImports": "never"
|
||||||
},
|
},
|
||||||
|
|
||||||
// Silent the stylistic rules in you IDE, but still auto fix them
|
// Enable eslint for all supported languages
|
||||||
"eslint.rules.customizations": [
|
"eslint.validate": [
|
||||||
{ "rule": "style/*", "severity": "off" },
|
"javascript",
|
||||||
{ "rule": "*-indent", "severity": "off" },
|
"javascriptreact",
|
||||||
{ "rule": "*-spacing", "severity": "off" },
|
"typescript",
|
||||||
{ "rule": "*-spaces", "severity": "off" },
|
"typescriptreact",
|
||||||
{ "rule": "*-order", "severity": "off" },
|
"vue",
|
||||||
{ "rule": "*-dangle", "severity": "off" },
|
"html",
|
||||||
{ "rule": "*-newline", "severity": "off" },
|
"markdown",
|
||||||
{ "rule": "*quotes", "severity": "off" },
|
"json",
|
||||||
{ "rule": "*semi", "severity": "off" }
|
"jsonc",
|
||||||
],
|
"yaml"
|
||||||
|
],
|
||||||
|
|
||||||
// Enable eslint for all supported languages
|
"pair-diff.patterns": [
|
||||||
"eslint.validate": [
|
{
|
||||||
"javascript",
|
"source": "./fixtures/output/**/*.*",
|
||||||
"javascriptreact",
|
"target": "./fixtures/input/<base>"
|
||||||
"typescript",
|
}
|
||||||
"typescriptreact",
|
]
|
||||||
"vue",
|
|
||||||
"html",
|
|
||||||
"markdown",
|
|
||||||
"json",
|
|
||||||
"jsonc",
|
|
||||||
"yaml"
|
|
||||||
],
|
|
||||||
|
|
||||||
"pair-diff.patterns": [
|
|
||||||
{
|
|
||||||
"source": "./fixtures/output/**/*.*",
|
|
||||||
"target": "./fixtures/input/<base>"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
@ -90,8 +90,9 @@ Fes.js 里约定目录下有 `layout.vue` 时会生成嵌套路由,以 `layout
|
|||||||
|
|
||||||
```vue
|
```vue
|
||||||
<template>
|
<template>
|
||||||
<Page></Page>
|
<Page />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { Page } from '@fesjs/fes';
|
import { Page } from '@fesjs/fes';
|
||||||
export default {
|
export default {
|
||||||
@ -112,7 +113,7 @@ export default {
|
|||||||
export default {
|
export default {
|
||||||
layout: {
|
layout: {
|
||||||
// 标题
|
// 标题
|
||||||
title: "Fes.js",
|
title: 'Fes.js',
|
||||||
// 底部文字
|
// 底部文字
|
||||||
footer: 'Created by MumbleFE',
|
footer: 'Created by MumbleFE',
|
||||||
// 主题light
|
// 主题light
|
||||||
@ -128,6 +129,7 @@ export default {
|
|||||||
}],
|
}],
|
||||||
|
|
||||||
},
|
},
|
||||||
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 运行时配置方式
|
#### 运行时配置方式
|
||||||
@ -146,27 +148,29 @@ export const layout = {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
在`fes.js`中,运行时配置有定义对象和函数两种方式,当使用函数配置`layout`时,`layoutConfig`是编译时配置结果,`initialState`是 `beforeRender.action`执行后创建的应用初始状态数据。
|
在`fes.js`中,运行时配置有定义对象和函数两种方式,当使用函数配置`layout`时,`layoutConfig`是编译时配置结果,`initialState`是 `beforeRender.action`执行后创建的应用初始状态数据。
|
||||||
。
|
。
|
||||||
|
|
||||||
```js
|
```js
|
||||||
export const layout = (layoutConfig, { initialState }) => ({
|
export function layout(layoutConfig, { initialState }) {
|
||||||
renderCustom: () => <UserCenter />,
|
return {
|
||||||
menus: () => {
|
renderCustom: () => <UserCenter />,
|
||||||
const menusRef = ref(layoutConfig.menus);
|
menus: () => {
|
||||||
watch(
|
const menusRef = ref(layoutConfig.menus);
|
||||||
() => initialState.userName,
|
watch(
|
||||||
() => {
|
() => initialState.userName,
|
||||||
menusRef.value = [
|
() => {
|
||||||
{
|
menusRef.value = [
|
||||||
name: 'store',
|
{
|
||||||
},
|
name: 'store',
|
||||||
];
|
},
|
||||||
},
|
];
|
||||||
);
|
},
|
||||||
return menusRef;
|
);
|
||||||
},
|
return menusRef;
|
||||||
});
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
最终配置结果是运行时配置跟编译时配置合并的结果,运行时配置优先于编译时配置。
|
最终配置结果是运行时配置跟编译时配置合并的结果,运行时配置优先于编译时配置。
|
||||||
@ -194,6 +198,12 @@ export const layout = (layoutConfig, { initialState }) => ({
|
|||||||
|
|
||||||
- **详情**:页面布局类型,可选有 `side`、 `top`、 `mixin`
|
- **详情**:页面布局类型,可选有 `side`、 `top`、 `mixin`
|
||||||
|
|
||||||
|
### navigationOnError
|
||||||
|
|
||||||
|
- **类型**:`String`、`Function`
|
||||||
|
|
||||||
|
- **详情**:指定 `403`、`404` 时,页面的布局类型。值同 `navigation`。也支持函数返回。
|
||||||
|
|
||||||
### isFixedHeader
|
### isFixedHeader
|
||||||
|
|
||||||
- **类型**:`Boolean`
|
- **类型**:`Boolean`
|
||||||
@ -382,7 +392,7 @@ import { useRoute, useTabTitle } from '@fesjs/fes';
|
|||||||
|
|
||||||
const titleRef = useTabTitle(`详情-${route.params?.id}`);
|
const titleRef = useTabTitle(`详情-${route.params?.id}`);
|
||||||
|
|
||||||
//如果要更新
|
// 如果要更新
|
||||||
titleRef.value = 'changed';
|
titleRef.value = 'changed';
|
||||||
</script>
|
</script>
|
||||||
```
|
```
|
||||||
|
@ -2,19 +2,36 @@
|
|||||||
import antfu from '@antfu/eslint-config';
|
import antfu from '@antfu/eslint-config';
|
||||||
|
|
||||||
export default await antfu({
|
export default await antfu({
|
||||||
|
files: ['**/*.js', '**/*.jsx', '**/*.vue', '**/*.ts'],
|
||||||
|
// TODO: 使用 ignore 代替 cli 命令中的配置
|
||||||
stylistic: {
|
stylistic: {
|
||||||
indent: 4, // 4, or 'tab'
|
indent: 4,
|
||||||
quotes: 'single', // or 'double'
|
quotes: 'single',
|
||||||
semi: 'always',
|
semi: 'always',
|
||||||
},
|
},
|
||||||
typescript: true,
|
typescript: true,
|
||||||
vue: true,
|
vue: true,
|
||||||
rules: {
|
rules: {
|
||||||
|
'curly': ['error', 'multi-line'],
|
||||||
'vue/block-order': [
|
'vue/block-order': [
|
||||||
'error',
|
'error',
|
||||||
{
|
{
|
||||||
order: ['template', 'script', 'style'],
|
order: ['template', 'script', 'style'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
'style/member-delimiter-style': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
multiline: {
|
||||||
|
delimiter: 'semi',
|
||||||
|
requireLast: true,
|
||||||
|
},
|
||||||
|
singleline: {
|
||||||
|
delimiter: 'semi',
|
||||||
|
requireLast: false,
|
||||||
|
},
|
||||||
|
multilineDetection: 'brackets',
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
37
package.json
37
package.json
@ -1,13 +1,21 @@
|
|||||||
{
|
{
|
||||||
"name": "fes.js",
|
"name": "fes.js",
|
||||||
|
"type": "module",
|
||||||
"version": "3.1.1",
|
"version": "3.1.1",
|
||||||
|
"private": true,
|
||||||
"description": "一个好用的前端管理台快速开发框架",
|
"description": "一个好用的前端管理台快速开发框架",
|
||||||
"preferGlobal": true,
|
"preferGlobal": true,
|
||||||
"private": true,
|
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
],
|
],
|
||||||
"type": "module",
|
"license": "MIT",
|
||||||
|
"keywords": [
|
||||||
|
"管理端",
|
||||||
|
"fes",
|
||||||
|
"fast",
|
||||||
|
"easy",
|
||||||
|
"strong"
|
||||||
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"bootstrap": "pnpm i",
|
"bootstrap": "pnpm i",
|
||||||
"dev": "node scripts/build.mjs --watch",
|
"dev": "node scripts/build.mjs --watch",
|
||||||
@ -18,17 +26,10 @@
|
|||||||
"docs:build": "vitepress build docs",
|
"docs:build": "vitepress build docs",
|
||||||
"docs:build-pages": "BASE=fes.js vitepress build docs",
|
"docs:build-pages": "BASE=fes.js vitepress build docs",
|
||||||
"test": "fes test",
|
"test": "fes test",
|
||||||
"lint": "eslint -c ./.eslintrc.js --ignore-pattern='templates' --ext .js,.jsx,.vue,.ts",
|
"lint": "eslint --ignore-pattern='templates'",
|
||||||
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s"
|
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
|
||||||
|
"hooks:sync": "simple-git-hooks"
|
||||||
},
|
},
|
||||||
"license": "MIT",
|
|
||||||
"keywords": [
|
|
||||||
"管理端",
|
|
||||||
"fes",
|
|
||||||
"fast",
|
|
||||||
"easy",
|
|
||||||
"strong"
|
|
||||||
],
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chalk": "^5.0.1",
|
"chalk": "^5.0.1",
|
||||||
"conventional-changelog-cli": "^4.1.0",
|
"conventional-changelog-cli": "^4.1.0",
|
||||||
@ -38,14 +39,14 @@
|
|||||||
"semver": "^7.3.6"
|
"semver": "^7.3.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@antfu/eslint-config": "^2.1.1",
|
"@antfu/eslint-config": "^2.6.2",
|
||||||
"@commitlint/cli": "^11.0.0",
|
"@commitlint/cli": "^11.0.0",
|
||||||
"@commitlint/config-conventional": "^11.0.0",
|
"@commitlint/config-conventional": "^11.0.0",
|
||||||
"chokidar": "^3.5.3",
|
"chokidar": "^3.5.3",
|
||||||
"commitizen": "^4.3.0",
|
"commitizen": "^4.3.0",
|
||||||
"cz-conventional-changelog": "^3.3.0",
|
"cz-conventional-changelog": "^3.3.0",
|
||||||
"deepmerge": "^4.2.2",
|
"deepmerge": "^4.2.2",
|
||||||
"eslint": "^8.54.0",
|
"eslint": "^8.56.0",
|
||||||
"fs-extra": "^11.1.1",
|
"fs-extra": "^11.1.1",
|
||||||
"lint-staged": "^13.2.0",
|
"lint-staged": "^13.2.0",
|
||||||
"simple-git-hooks": "^2.9.0",
|
"simple-git-hooks": "^2.9.0",
|
||||||
@ -54,15 +55,15 @@
|
|||||||
"vue": "^3.3.4",
|
"vue": "^3.3.4",
|
||||||
"yargs-parser": "^21.1.1"
|
"yargs-parser": "^21.1.1"
|
||||||
},
|
},
|
||||||
|
"simple-git-hooks": {
|
||||||
|
"pre-commit": "lint-staged",
|
||||||
|
"commit-msg": "commitlint"
|
||||||
|
},
|
||||||
"lint-staged": {
|
"lint-staged": {
|
||||||
"*.{js,jsx,vue,ts}": [
|
"*.{js,jsx,vue,ts}": [
|
||||||
"npm run lint"
|
"npm run lint"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"simple-git-hooks": {
|
|
||||||
"pre-commit": "lint-staged",
|
|
||||||
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
|
|
||||||
},
|
|
||||||
"config": {
|
"config": {
|
||||||
"commitizen": {
|
"commitizen": {
|
||||||
"path": "./node_modules/cz-conventional-changelog"
|
"path": "./node_modules/cz-conventional-changelog"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<f-layout class="main-layout">
|
<FLayout class="main-layout">
|
||||||
<template v-if="currentNavigation === 'side'">
|
<template v-if="currentNavigation === 'side'">
|
||||||
<f-aside
|
<FAside
|
||||||
v-model:collapsed="collapsedRef"
|
v-model:collapsed="collapsedRef"
|
||||||
:fixed="isFixedSidebar"
|
:fixed="isFixedSidebar"
|
||||||
:width="`${sideWidth}px`"
|
:width="`${sideWidth}px`"
|
||||||
@ -10,41 +10,43 @@
|
|||||||
:inverted="theme === 'dark'"
|
:inverted="theme === 'dark'"
|
||||||
>
|
>
|
||||||
<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">
|
||||||
<div v-if="title" class="logo-name">{{ title }}</div>
|
<div v-if="title" class="logo-name">
|
||||||
|
{{ title }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Menu
|
<LayoutMenu
|
||||||
class="layout-menu"
|
class="layout-menu"
|
||||||
:menus="menus"
|
:menus="menus"
|
||||||
:collapsed="collapsedRef"
|
:collapsed="collapsedRef"
|
||||||
mode="vertical"
|
mode="vertical"
|
||||||
:inverted="theme === 'dark'"
|
:inverted="theme === 'dark'"
|
||||||
:expandedKeys="menuProps?.expandedKeys"
|
:expanded-keys="menuProps?.expandedKeys"
|
||||||
:defaultExpandAll="menuProps?.defaultExpandAll"
|
:default-expand-all="menuProps?.defaultExpandAll"
|
||||||
:accordion="menuProps?.accordion"
|
:accordion="menuProps?.accordion"
|
||||||
/>
|
/>
|
||||||
</f-aside>
|
</FAside>
|
||||||
<f-layout :fixed="isFixedSidebar" :style="sideStyleRef">
|
<FLayout :fixed="isFixedSidebar" :style="sideStyleRef">
|
||||||
<f-header ref="headerRef" class="layout-header" :fixed="currentFixedHeaderRef">
|
<FHeader ref="headerRef" class="layout-header" :fixed="currentFixedHeaderRef">
|
||||||
<div class="layout-header-custom">
|
<div class="layout-header-custom">
|
||||||
<slot name="renderCustom" :menus="menus"></slot>
|
<slot name="renderCustom" :menus="menus" />
|
||||||
</div>
|
</div>
|
||||||
<template v-if="locale">
|
<template v-if="locale">
|
||||||
<slot name="locale"></slot>
|
<slot name="locale" />
|
||||||
</template>
|
</template>
|
||||||
</f-header>
|
</FHeader>
|
||||||
<f-layout :embedded="!multiTabs" :fixed="currentFixedHeaderRef" :style="headerStyleRef">
|
<FLayout :embedded="!multiTabs" :fixed="currentFixedHeaderRef" :style="headerStyleRef">
|
||||||
<f-main class="layout-main">
|
<FMain class="layout-main">
|
||||||
<MultiTabProvider :multiTabs="multiTabs" />
|
<MultiTabProvider :multi-tabs="multiTabs" />
|
||||||
</f-main>
|
</FMain>
|
||||||
<f-footer v-if="footer" class="layout-footer">
|
<FFooter v-if="footer" class="layout-footer">
|
||||||
{{ footer }}
|
{{ footer }}
|
||||||
</f-footer>
|
</FFooter>
|
||||||
</f-layout>
|
</FLayout>
|
||||||
</f-layout>
|
</FLayout>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="currentNavigation === 'left-right'">
|
<template v-else-if="currentNavigation === 'left-right'">
|
||||||
<f-aside
|
<FAside
|
||||||
v-model:collapsed="collapsedRef"
|
v-model:collapsed="collapsedRef"
|
||||||
:fixed="isFixedSidebar"
|
:fixed="isFixedSidebar"
|
||||||
:width="`${sideWidth}px`"
|
:width="`${sideWidth}px`"
|
||||||
@ -55,121 +57,127 @@
|
|||||||
<div class="flex-between">
|
<div class="flex-between">
|
||||||
<div>
|
<div>
|
||||||
<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">
|
||||||
<div v-if="title" class="logo-name">{{ title }}</div>
|
<div v-if="title" class="logo-name">
|
||||||
|
{{ title }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Menu
|
<LayoutMenu
|
||||||
class="layout-menu"
|
class="layout-menu"
|
||||||
:menus="menus"
|
:menus="menus"
|
||||||
:collapsed="collapsedRef"
|
:collapsed="collapsedRef"
|
||||||
mode="vertical"
|
mode="vertical"
|
||||||
:inverted="theme === 'dark'"
|
:inverted="theme === 'dark'"
|
||||||
:expandedKeys="menuProps?.expandedKeys"
|
:expanded-keys="menuProps?.expandedKeys"
|
||||||
:defaultExpandAll="menuProps?.defaultExpandAll"
|
:default-expand-all="menuProps?.defaultExpandAll"
|
||||||
:accordion="menuProps?.accordion"
|
:accordion="menuProps?.accordion"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="layout-aside-custom">
|
<div class="layout-aside-custom">
|
||||||
<slot name="renderCustom" :menus="menus"></slot>
|
<slot name="renderCustom" :menus="menus" />
|
||||||
</div>
|
</div>
|
||||||
<div v-if="locale" class="layout-aside-locale">
|
<div v-if="locale" class="layout-aside-locale">
|
||||||
<slot name="locale"></slot>
|
<slot name="locale" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</f-aside>
|
</FAside>
|
||||||
<f-layout :fixed="isFixedSidebar" :style="sideStyleRef">
|
<FLayout :fixed="isFixedSidebar" :style="sideStyleRef">
|
||||||
<f-layout :embedded="!multiTabs">
|
<FLayout :embedded="!multiTabs">
|
||||||
<f-main class="layout-main">
|
<FMain class="layout-main">
|
||||||
<MultiTabProvider :multiTabs="multiTabs" />
|
<MultiTabProvider :multi-tabs="multiTabs" />
|
||||||
</f-main>
|
</FMain>
|
||||||
<f-footer v-if="footer" class="layout-footer">
|
<FFooter v-if="footer" class="layout-footer">
|
||||||
{{ footer }}
|
{{ footer }}
|
||||||
</f-footer>
|
</FFooter>
|
||||||
</f-layout>
|
</FLayout>
|
||||||
</f-layout>
|
</FLayout>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="currentNavigation === 'top'">
|
<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">
|
<div class="layout-logo">
|
||||||
<img v-if="logo" :src="logo" class="logo-img" />
|
<img v-if="logo" :src="logo" class="logo-img">
|
||||||
<div v-if="title" class="logo-name">{{ title }}</div>
|
<div v-if="title" class="logo-name">
|
||||||
|
{{ title }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Menu
|
<LayoutMenu
|
||||||
class="layout-menu"
|
class="layout-menu"
|
||||||
:menus="menus"
|
:menus="menus"
|
||||||
mode="horizontal"
|
mode="horizontal"
|
||||||
:inverted="theme === 'dark'"
|
:inverted="theme === 'dark'"
|
||||||
:expandedKeys="menuProps?.expandedKeys"
|
:expanded-keys="menuProps?.expandedKeys"
|
||||||
:defaultExpandAll="menuProps?.defaultExpandAll"
|
:default-expand-all="menuProps?.defaultExpandAll"
|
||||||
:accordion="menuProps?.accordion"
|
:accordion="menuProps?.accordion"
|
||||||
/>
|
/>
|
||||||
<div class="layout-header-custom">
|
<div class="layout-header-custom">
|
||||||
<slot name="renderCustom" :menus="menus"></slot>
|
<slot name="renderCustom" :menus="menus" />
|
||||||
</div>
|
</div>
|
||||||
<template v-if="locale">
|
<template v-if="locale">
|
||||||
<slot name="locale"></slot>
|
<slot name="locale" />
|
||||||
</template>
|
</template>
|
||||||
</f-header>
|
</FHeader>
|
||||||
<f-layout :embedded="!multiTabs" :fixed="currentFixedHeaderRef" :style="headerStyleRef">
|
<FLayout :embedded="!multiTabs" :fixed="currentFixedHeaderRef" :style="headerStyleRef">
|
||||||
<f-main class="layout-main">
|
<FMain class="layout-main">
|
||||||
<MultiTabProvider :multiTabs="multiTabs" />
|
<MultiTabProvider :multi-tabs="multiTabs" />
|
||||||
</f-main>
|
</FMain>
|
||||||
<f-footer v-if="footer" class="layout-footer">
|
<FFooter v-if="footer" class="layout-footer">
|
||||||
{{ footer }}
|
{{ footer }}
|
||||||
</f-footer>
|
</FFooter>
|
||||||
</f-layout>
|
</FLayout>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="currentNavigation === 'mixin'">
|
<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">
|
<div class="layout-logo">
|
||||||
<img v-if="logo" :src="logo" class="logo-img" />
|
<img v-if="logo" :src="logo" class="logo-img">
|
||||||
<div v-if="title" class="logo-name">{{ title }}</div>
|
<div v-if="title" class="logo-name">
|
||||||
|
{{ title }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout-header-custom">
|
<div class="layout-header-custom">
|
||||||
<slot name="renderCustom" :menus="menus"></slot>
|
<slot name="renderCustom" :menus="menus" />
|
||||||
</div>
|
</div>
|
||||||
<template v-if="locale">
|
<template v-if="locale">
|
||||||
<slot name="locale"></slot>
|
<slot name="locale" />
|
||||||
</template>
|
</template>
|
||||||
</f-header>
|
</FHeader>
|
||||||
<f-layout :fixed="currentFixedHeaderRef" :style="headerStyleRef">
|
<FLayout :fixed="currentFixedHeaderRef" :style="headerStyleRef">
|
||||||
<f-aside v-model:collapsed="collapsedRef" :fixed="isFixedSidebar" :width="`${sideWidth}px`" collapsible class="layout-aside">
|
<FAside v-model:collapsed="collapsedRef" :fixed="isFixedSidebar" :width="`${sideWidth}px`" collapsible class="layout-aside">
|
||||||
<Menu
|
<LayoutMenu
|
||||||
class="layout-menu"
|
class="layout-menu"
|
||||||
:menus="menus"
|
:menus="menus"
|
||||||
:collapsed="collapsedRef"
|
:collapsed="collapsedRef"
|
||||||
mode="vertical"
|
mode="vertical"
|
||||||
:expandedKeys="menuProps?.expandedKeys"
|
:expanded-keys="menuProps?.expandedKeys"
|
||||||
:defaultExpandAll="menuProps?.defaultExpandAll"
|
:default-expand-all="menuProps?.defaultExpandAll"
|
||||||
:accordion="menuProps?.accordion"
|
:accordion="menuProps?.accordion"
|
||||||
/>
|
/>
|
||||||
</f-aside>
|
</FAside>
|
||||||
<f-layout :embedded="!multiTabs" :fixed="isFixedSidebar" :style="sideStyleRef">
|
<FLayout :embedded="!multiTabs" :fixed="isFixedSidebar" :style="sideStyleRef">
|
||||||
<f-main class="layout-main">
|
<FMain class="layout-main">
|
||||||
<MultiTabProvider :multiTabs="multiTabs" />
|
<MultiTabProvider :multi-tabs="multiTabs" />
|
||||||
</f-main>
|
</FMain>
|
||||||
<f-footer v-if="footer" class="layout-footer">
|
<FFooter v-if="footer" class="layout-footer">
|
||||||
{{ footer }}
|
{{ footer }}
|
||||||
</f-footer>
|
</FFooter>
|
||||||
</f-layout>
|
</FLayout>
|
||||||
</f-layout>
|
</FLayout>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<f-main class="layout-main">
|
<FMain class="layout-main">
|
||||||
<router-view></router-view>
|
<router-view />
|
||||||
</f-main>
|
</FMain>
|
||||||
</template>
|
</template>
|
||||||
</f-layout>
|
</FLayout>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { ref, computed, watch, nextTick } from 'vue';
|
|
||||||
import { useRoute, useRouter } from '@@/core/coreExports';
|
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 defaultLogo from '../assets/logo.png';
|
||||||
import Menu from './Menu.vue';
|
import LayoutMenu from './Menu.vue';
|
||||||
import MultiTabProvider from './MultiTabProvider.vue';
|
import MultiTabProvider from './MultiTabProvider.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -179,7 +187,7 @@ export default {
|
|||||||
FMain,
|
FMain,
|
||||||
FFooter,
|
FFooter,
|
||||||
FHeader,
|
FHeader,
|
||||||
Menu,
|
LayoutMenu,
|
||||||
MultiTabProvider,
|
MultiTabProvider,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
@ -209,6 +217,9 @@ export default {
|
|||||||
type: String,
|
type: String,
|
||||||
default: 'side', // side 左右(上/下)、 top 上/下、 mixin 上/下(左/右)
|
default: 'side', // side 左右(上/下)、 top 上/下、 mixin 上/下(左/右)
|
||||||
},
|
},
|
||||||
|
navigationOnError: {
|
||||||
|
type: [String, Function], // 403, 404 时的 navigation
|
||||||
|
},
|
||||||
isFixedHeader: {
|
isFixedHeader: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
@ -241,6 +252,12 @@ export default {
|
|||||||
if (route.meta.layout && route.meta.layout.navigation !== undefined) {
|
if (route.meta.layout && route.meta.layout.navigation !== undefined) {
|
||||||
return route.meta.layout.navigation;
|
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;
|
return props.navigation;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -278,6 +295,7 @@ export default {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.main-layout {
|
.main-layout {
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { unref, defineComponent, computed } from 'vue';
|
|
||||||
import { plugin } from '@@/core/coreExports';
|
import { plugin } from '@@/core/coreExports';
|
||||||
import { getRoutes } from '@@/core/routes/routes';
|
import { getRoutes } from '@@/core/routes/routes';
|
||||||
// eslint-disable-next-line import/extensions
|
import { computed, defineComponent, unref } from 'vue';
|
||||||
import getConfig from '../helpers/getConfig';
|
|
||||||
import fillMenu from '../helpers/fillMenu';
|
import fillMenu from '../helpers/fillMenu';
|
||||||
|
import getConfig from '../helpers/getConfig';
|
||||||
import BaseLayout from './BaseLayout.vue';
|
import BaseLayout from './BaseLayout.vue';
|
||||||
|
|
||||||
const Layout = defineComponent({
|
const Layout = defineComponent({
|
||||||
@ -33,11 +33,12 @@ const Layout = defineComponent({
|
|||||||
return (
|
return (
|
||||||
<BaseLayout
|
<BaseLayout
|
||||||
menus={filledMenuRef.value}
|
menus={filledMenuRef.value}
|
||||||
locale={localeShared ? true : false}
|
locale={!!localeShared}
|
||||||
title={config.title}
|
title={config.title}
|
||||||
logo={config.logo}
|
logo={config.logo}
|
||||||
theme={config.theme}
|
theme={config.theme}
|
||||||
navigation={config.navigation}
|
navigation={config.navigation}
|
||||||
|
navigationOnError={config.navigationOnError}
|
||||||
isFixedHeader={config.isFixedHeader}
|
isFixedHeader={config.isFixedHeader}
|
||||||
isFixedSidebar={config.isFixedSidebar}
|
isFixedSidebar={config.isFixedSidebar}
|
||||||
multiTabs={config.multiTabs}
|
multiTabs={config.multiTabs}
|
||||||
@ -45,7 +46,7 @@ const Layout = defineComponent({
|
|||||||
footer={config.footer}
|
footer={config.footer}
|
||||||
menuProps={config.menuProps}
|
menuProps={config.menuProps}
|
||||||
v-slots={slots}
|
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 type { MenuOption } from '@fesjs/fes-design/es/menu/interface';
|
||||||
import { Router, RouteLocationNormalized, NavigationGuardNext, NavigationGuard } from 'vue-router';
|
import type { Component, Ref, VNode } from 'vue';
|
||||||
import { MenuOption } from '@fesjs/fes-design/es/menu/interface';
|
import type { NavigationGuard, NavigationGuardNext, RouteLocationNormalized, Router } from 'vue-router';
|
||||||
|
|
||||||
interface CustomNavigationGuardOption {
|
interface CustomNavigationGuardOption {
|
||||||
router: Router;
|
router: Router;
|
||||||
@ -22,6 +22,8 @@ interface Menu {
|
|||||||
children?: Menu[];
|
children?: Menu[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Navigation = 'side' | 'mixin' | 'top' | 'left-right';
|
||||||
|
|
||||||
export const Page: Component;
|
export const Page: Component;
|
||||||
|
|
||||||
export function useTabTitle(title: string | Ref<string>): void;
|
export function useTabTitle(title: string | Ref<string>): void;
|
||||||
@ -29,7 +31,8 @@ export function useTabTitle(title: string | Ref<string>): void;
|
|||||||
interface LayoutRuntimeConfig {
|
interface LayoutRuntimeConfig {
|
||||||
footer?: string;
|
footer?: string;
|
||||||
theme?: 'dark' | 'light';
|
theme?: 'dark' | 'light';
|
||||||
navigation?: 'side' | 'top' | 'mixin' | 'left-right';
|
navigation?: Navigation;
|
||||||
|
navigationOnError?: Navigation | ((route: RouteLocationNormalized) => Navigation | null);
|
||||||
title?: string;
|
title?: string;
|
||||||
isFixedHeader?: boolean;
|
isFixedHeader?: boolean;
|
||||||
isFixedSidebar?: boolean;
|
isFixedSidebar?: boolean;
|
||||||
@ -51,28 +54,29 @@ declare module '@fesjs/fes' {
|
|||||||
interface RouteMeta {
|
interface RouteMeta {
|
||||||
'keep-alive'?: boolean;
|
'keep-alive'?: boolean;
|
||||||
layout?: {
|
layout?: {
|
||||||
navigation?: 'side' | 'mixin' | 'top' | 'left-right' | null;
|
navigation?: Navigation | null;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
interface PluginBuildConfig {
|
interface PluginBuildConfig {
|
||||||
layout?:
|
layout?:
|
||||||
| {
|
| {
|
||||||
footer: string;
|
footer: string;
|
||||||
theme: 'dark' | 'light';
|
theme: 'dark' | 'light';
|
||||||
navigation: 'side' | 'top' | 'mixin' | 'left-right';
|
navigation: Navigation;
|
||||||
title: string;
|
navigationOnError: Navigation;
|
||||||
isFixedHeader: boolean;
|
title: string;
|
||||||
isFixedSidebar: boolean;
|
isFixedHeader: boolean;
|
||||||
logo: string;
|
isFixedSidebar: boolean;
|
||||||
multiTabs: boolean;
|
logo: string;
|
||||||
sideWidth: number;
|
multiTabs: boolean;
|
||||||
menus: Menu[];
|
sideWidth: number;
|
||||||
menuProps: {
|
menus: Menu[];
|
||||||
expandedKeys: string[];
|
menuProps: {
|
||||||
defaultExpandAll: boolean;
|
expandedKeys: string[];
|
||||||
accordion: boolean;
|
defaultExpandAll: boolean;
|
||||||
};
|
accordion: boolean;
|
||||||
}
|
};
|
||||||
|
}
|
||||||
| false;
|
| false;
|
||||||
}
|
}
|
||||||
interface PluginRuntimeConfig {
|
interface PluginRuntimeConfig {
|
||||||
|
583
pnpm-lock.yaml
583
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user