mirror of
https://gitee.com/fantastic-admin/basic.git
synced 2024-12-05 05:27:39 +08:00
优化路由配置
This commit is contained in:
parent
2ff29a7321
commit
0d9ebc5599
@ -35,13 +35,6 @@ const switchMenu = inject('switchMenu')
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
// 头部动画
|
||||
.header-enter-active {
|
||||
transition: 0.2s;
|
||||
}
|
||||
.header-enter-from {
|
||||
transform: translateY(-#{$g-header-height});
|
||||
}
|
||||
header {
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
@ -135,4 +128,13 @@ header {
|
||||
}
|
||||
}
|
||||
}
|
||||
// 头部动画
|
||||
.header-enter-active,
|
||||
.header-leave-active {
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
.header-enter-from,
|
||||
.header-leave-to {
|
||||
transform: translateY(-#{$g-header-height});
|
||||
}
|
||||
</style>
|
||||
|
@ -34,13 +34,6 @@ const switchMenu = inject('switchMenu')
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
// 主侧边栏动画
|
||||
.main-sidebar-enter-active {
|
||||
transition: 0.3s;
|
||||
}
|
||||
.main-sidebar-enter-from {
|
||||
transform: translateX(calc(var(--g-main-sidebar-width) * -1));
|
||||
}
|
||||
.main-sidebar-container {
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
@ -97,4 +90,13 @@ const switchMenu = inject('switchMenu')
|
||||
}
|
||||
}
|
||||
}
|
||||
// 主侧边栏动画
|
||||
.main-sidebar-enter-active,
|
||||
.main-sidebar-leave-active {
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
.main-sidebar-enter-from,
|
||||
.main-sidebar-leave-to {
|
||||
transform: translateX(calc(var(--g-main-sidebar-width) * -1));
|
||||
}
|
||||
</style>
|
||||
|
@ -39,18 +39,6 @@ function onSidebarScroll(e) {
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
// 次侧边栏动画
|
||||
.sub-sidebar-enter-active {
|
||||
transition: 0.3s;
|
||||
}
|
||||
.sub-sidebar-enter-from,
|
||||
.sub-sidebar-leave-active {
|
||||
opacity: 0;
|
||||
transform: translateY(30px) skewY(10deg);
|
||||
}
|
||||
.sub-sidebar-leave-active {
|
||||
position: absolute;
|
||||
}
|
||||
.sub-sidebar-container {
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
@ -67,9 +55,9 @@ function onSidebarScroll(e) {
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
transition: 0.3s;
|
||||
background-color: var(--g-sub-sidebar-bg);
|
||||
box-shadow: 10px 0 10px -10px var(--g-box-shadow-color);
|
||||
transition: background-color 0.3s, var(--el-transition-box-shadow), left 0.3s;
|
||||
&.is-collapse {
|
||||
width: 64px;
|
||||
.sidebar-logo {
|
||||
@ -99,7 +87,7 @@ function onSidebarScroll(e) {
|
||||
.el-menu {
|
||||
border-right: 0;
|
||||
padding-top: $g-sidebar-logo-height;
|
||||
transition: border-color 0.3s, background-color 0.3s, color 0.3s;
|
||||
transition: border-color 0.3s, background-color 0.3s, color 0.3s, padding-top 0.3s;
|
||||
background-color: var(--g-sub-sidebar-bg);
|
||||
&:not(.el-menu--collapse) {
|
||||
width: inherit;
|
||||
@ -137,4 +125,16 @@ function onSidebarScroll(e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
// 次侧边栏动画
|
||||
.sub-sidebar-enter-active {
|
||||
transition: opacity 0.3s, transform 0.3s;
|
||||
}
|
||||
.sub-sidebar-enter-from,
|
||||
.sub-sidebar-leave-active {
|
||||
opacity: 0;
|
||||
transform: translateY(30px) skewY(10deg);
|
||||
}
|
||||
.sub-sidebar-leave-active {
|
||||
position: absolute;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,6 +1,5 @@
|
||||
<script setup name="Topbar">
|
||||
import { compile } from 'path-to-regexp'
|
||||
import { deepClone } from '@/util'
|
||||
import Tools from '../Tools/index.vue'
|
||||
|
||||
const route = useRoute()
|
||||
@ -24,7 +23,7 @@ const breadcrumbList = computed(() => {
|
||||
})
|
||||
}
|
||||
if (route.meta.breadcrumbNeste) {
|
||||
breadcrumbList.push(...deepClone(route.meta.breadcrumbNeste))
|
||||
breadcrumbList.push(...route.meta.breadcrumbNeste.filter(item => item.hide === false))
|
||||
}
|
||||
return breadcrumbList
|
||||
})
|
||||
|
@ -135,13 +135,14 @@ function switchMenu(index) {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-shadow: -1px 0 0 0 var(--g-box-shadow-color);
|
||||
transition: padding-top 0.3s;
|
||||
.sidebar-container {
|
||||
position: fixed;
|
||||
z-index: 1010;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
transition: transform 0.3s;
|
||||
transition: transform 0.3s, top 0.3s;
|
||||
width: calc(var(--g-main-sidebar-actual-width) + var(--g-sub-sidebar-actual-width));
|
||||
}
|
||||
.sidebar-mask {
|
||||
@ -162,7 +163,7 @@ function switchMenu(index) {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
.main-sidebar-container + .sub-sidebar-container {
|
||||
.main-sidebar-container:not(.main-sidebar-leave-active) + .sub-sidebar-container {
|
||||
left: var(--g-main-sidebar-width);
|
||||
}
|
||||
.main-container {
|
||||
@ -188,7 +189,7 @@ function switchMenu(index) {
|
||||
}
|
||||
}
|
||||
}
|
||||
header + .wrapper {
|
||||
header:not(.header-leave-active) + .wrapper {
|
||||
padding-top: $g-header-height;
|
||||
.sidebar-container {
|
||||
top: $g-header-height;
|
||||
|
@ -9,145 +9,10 @@ import '@/assets/styles/nprogress.scss'
|
||||
import { useNProgress } from '@vueuse/integrations/useNProgress'
|
||||
const { isLoading } = useNProgress()
|
||||
|
||||
// 固定路由
|
||||
let constantRoutes = [
|
||||
{
|
||||
path: '/login',
|
||||
name: 'login',
|
||||
component: () => import('@/views/login.vue'),
|
||||
meta: {
|
||||
title: '登录'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/',
|
||||
component: () => import('@/layout/index.vue'),
|
||||
redirect: '/dashboard',
|
||||
children: [
|
||||
{
|
||||
path: 'dashboard',
|
||||
name: 'dashboard',
|
||||
component: () => import('@/views/index.vue'),
|
||||
meta: {
|
||||
title: () => {
|
||||
const settingsStore = useSettingsStore()
|
||||
return settingsStore.dashboard.title
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'personal/setting',
|
||||
name: 'personalSetting',
|
||||
component: () => import('@/views/personal/setting.vue'),
|
||||
meta: {
|
||||
title: '个人设置',
|
||||
cache: 'personalEditPassword',
|
||||
breadcrumbNeste: [
|
||||
{ title: '个人设置', path: '/personal/setting' }
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'personal/edit/password',
|
||||
name: 'personalEditPassword',
|
||||
component: () => import('@/views/personal/edit.password.vue'),
|
||||
meta: {
|
||||
title: '修改密码',
|
||||
breadcrumbNeste: [
|
||||
{ title: '修改密码', path: '/personal/edit/password' }
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'reload',
|
||||
name: 'reload',
|
||||
component: () => import('@/views/reload.vue')
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
import MultilevelMenuExample from './modules/multilevel.menu.example'
|
||||
import BreadcrumbExample from './modules/breadcrumb.example'
|
||||
import KeepAliveExample from './modules/keep.alive.example'
|
||||
import ComponentBasicExample from './modules/component.basic.example'
|
||||
import ComponentExtendExample from './modules/component.extend.example'
|
||||
import PermissionExample from './modules/permission.example'
|
||||
import MockExample from './modules/mock.example'
|
||||
import JsxExample from './modules/jsx.example'
|
||||
import ExternalLinkExample from './modules/external.link.example'
|
||||
// import VideosExample from './modules/videos.example'
|
||||
import EcologyExample from './modules/ecology.example'
|
||||
import CooperationExample from './modules/cooperation.example'
|
||||
|
||||
// 动态路由(异步路由、导航栏路由)
|
||||
let asyncRoutes = [
|
||||
{
|
||||
meta: {
|
||||
title: '演示',
|
||||
icon: 'sidebar-default'
|
||||
},
|
||||
children: [
|
||||
MultilevelMenuExample,
|
||||
BreadcrumbExample,
|
||||
KeepAliveExample,
|
||||
ComponentBasicExample,
|
||||
ComponentExtendExample,
|
||||
PermissionExample,
|
||||
MockExample,
|
||||
JsxExample,
|
||||
ExternalLinkExample
|
||||
]
|
||||
},
|
||||
// {
|
||||
// meta: {
|
||||
// title: '教程',
|
||||
// icon: 'sidebar-videos'
|
||||
// },
|
||||
// children: [
|
||||
// ...VideosExample
|
||||
// ]
|
||||
// },
|
||||
{
|
||||
meta: {
|
||||
title: '生态',
|
||||
icon: 'sidebar-ecology'
|
||||
},
|
||||
children: [
|
||||
...EcologyExample
|
||||
]
|
||||
},
|
||||
{
|
||||
meta: {
|
||||
title: '战略合作',
|
||||
icon: 'sidebar-cooperation'
|
||||
},
|
||||
children: [
|
||||
...CooperationExample
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
const lastRoute = {
|
||||
path: '/:all(.*)*',
|
||||
name: 'notFound',
|
||||
component: () => import('@/views/[...all].vue'),
|
||||
meta: {
|
||||
title: '找不到页面'
|
||||
}
|
||||
}
|
||||
|
||||
import { setupLayouts } from 'virtual:generated-layouts'
|
||||
import generatedRoutes from 'virtual:generated-pages'
|
||||
|
||||
if (useSettingsStore(createPinia()).app.routeBaseOn === 'filesystem') {
|
||||
constantRoutes = generatedRoutes.filter(item => {
|
||||
return item.meta?.enabled !== false && item.meta?.constant === true
|
||||
})
|
||||
asyncRoutes = setupLayouts(generatedRoutes.filter(item => {
|
||||
return item.meta?.enabled !== false && item.meta?.constant !== true && item.meta?.layout !== false
|
||||
}))
|
||||
}
|
||||
// 路由相关数据
|
||||
import { constantRoutes, asyncRoutes, notFoundRoute } from './routes'
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHashHistory(),
|
||||
@ -226,7 +91,10 @@ router.beforeEach(async(to, from, next) => {
|
||||
const otherRoutes = generatedRoutes.filter(item => item.meta?.constant !== true && item.meta?.layout === false)
|
||||
otherRoutes.length && removeRoutes.push(router.addRoute(...otherRoutes))
|
||||
} else {
|
||||
removeRoutes.push(router.addRoute(lastRoute))
|
||||
routeStore.flatSystemRoutes.forEach(route => {
|
||||
removeRoutes.push(router.addRoute(route))
|
||||
})
|
||||
removeRoutes.push(router.addRoute(notFoundRoute))
|
||||
}
|
||||
// 记录的 accessRoutes 路由数据,在登出时会使用到,不使用 router.removeRoute 是考虑配置的路由可能不一定有设置 name ,则通过调用 router.addRoute() 返回的回调进行删除
|
||||
routeStore.setCurrentRemoveRoutes(removeRoutes)
|
||||
|
169
src/router/routes.js
Normal file
169
src/router/routes.js
Normal file
@ -0,0 +1,169 @@
|
||||
import useSettingsStore from '@/store/modules/settings'
|
||||
|
||||
// 固定路由(默认路由)
|
||||
let constantRoutes = [
|
||||
{
|
||||
path: '/',
|
||||
redirect: '/dashboard'
|
||||
},
|
||||
{
|
||||
path: '/login',
|
||||
name: 'login',
|
||||
component: () => import('@/views/login.vue'),
|
||||
meta: {
|
||||
title: '登录'
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
// 系统路由
|
||||
let systemRoutes = [
|
||||
{
|
||||
path: '/dashboard',
|
||||
component: () => import('@/layout/index.vue'),
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'dashboard',
|
||||
component: () => import('@/views/index.vue'),
|
||||
meta: {
|
||||
title: () => {
|
||||
return useSettingsStore().dashboard.title
|
||||
},
|
||||
breadcrumb: false
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/personal',
|
||||
component: () => import('@/layout/index.vue'),
|
||||
redirect: '/personal/setting',
|
||||
children: [
|
||||
{
|
||||
path: 'setting',
|
||||
name: 'personalSetting',
|
||||
component: () => import('@/views/personal/setting.vue'),
|
||||
meta: {
|
||||
title: '个人设置',
|
||||
i18n: 'route.personal.setting',
|
||||
cache: 'personalEditPassword'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'edit/password',
|
||||
name: 'personalEditPassword',
|
||||
component: () => import('@/views/personal/edit.password.vue'),
|
||||
meta: {
|
||||
title: '修改密码',
|
||||
i18n: 'route.personal.editpassword'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/reload',
|
||||
component: () => import('@/layout/index.vue'),
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'reload',
|
||||
component: () => import('@/views/reload.vue'),
|
||||
meta: {
|
||||
title: '重新加载',
|
||||
breadcrumb: false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
import MultilevelMenuExample from './modules/multilevel.menu.example'
|
||||
import BreadcrumbExample from './modules/breadcrumb.example'
|
||||
import KeepAliveExample from './modules/keep.alive.example'
|
||||
import ComponentBasicExample from './modules/component.basic.example'
|
||||
import ComponentExtendExample from './modules/component.extend.example'
|
||||
import PermissionExample from './modules/permission.example'
|
||||
import MockExample from './modules/mock.example'
|
||||
import JsxExample from './modules/jsx.example'
|
||||
import ExternalLinkExample from './modules/external.link.example'
|
||||
// import VideosExample from './modules/videos.example'
|
||||
import EcologyExample from './modules/ecology.example'
|
||||
import CooperationExample from './modules/cooperation.example'
|
||||
|
||||
// 动态路由(异步路由、导航栏路由)
|
||||
let asyncRoutes = [
|
||||
{
|
||||
meta: {
|
||||
title: '演示',
|
||||
icon: 'sidebar-default'
|
||||
},
|
||||
children: [
|
||||
MultilevelMenuExample,
|
||||
BreadcrumbExample,
|
||||
KeepAliveExample,
|
||||
ComponentBasicExample,
|
||||
ComponentExtendExample,
|
||||
PermissionExample,
|
||||
MockExample,
|
||||
JsxExample,
|
||||
ExternalLinkExample
|
||||
]
|
||||
},
|
||||
// {
|
||||
// meta: {
|
||||
// title: '教程',
|
||||
// icon: 'sidebar-videos'
|
||||
// },
|
||||
// children: [
|
||||
// ...VideosExample
|
||||
// ]
|
||||
// },
|
||||
{
|
||||
meta: {
|
||||
title: '生态',
|
||||
icon: 'sidebar-ecology'
|
||||
},
|
||||
children: [
|
||||
...EcologyExample
|
||||
]
|
||||
},
|
||||
{
|
||||
meta: {
|
||||
title: '战略合作',
|
||||
icon: 'sidebar-cooperation'
|
||||
},
|
||||
children: [
|
||||
...CooperationExample
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
import { setupLayouts } from 'virtual:generated-layouts'
|
||||
import generatedRoutes from 'virtual:generated-pages'
|
||||
|
||||
if (useSettingsStore(createPinia()).app.routeBaseOn === 'filesystem') {
|
||||
constantRoutes = generatedRoutes.filter(item => {
|
||||
return item.meta?.enabled !== false && item.meta?.constant === true
|
||||
})
|
||||
asyncRoutes = setupLayouts(generatedRoutes.filter(item => {
|
||||
return item.meta?.enabled !== false && item.meta?.constant !== true && item.meta?.layout !== false
|
||||
}))
|
||||
}
|
||||
|
||||
// 404路由
|
||||
const notFoundRoute = {
|
||||
path: '/:all(.*)*',
|
||||
name: 'notFound',
|
||||
component: () => import('@/views/[...all].vue'),
|
||||
meta: {
|
||||
title: '找不到页面'
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
constantRoutes,
|
||||
systemRoutes,
|
||||
asyncRoutes,
|
||||
notFoundRoute
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
import { deepClone, isExternalLink } from '@/util'
|
||||
import api from '@/api'
|
||||
import { systemRoutes } from '@/router/routes'
|
||||
|
||||
import useSettingsStore from './settings'
|
||||
import useUserStore from './user'
|
||||
@ -57,7 +58,7 @@ function formatBackRoutes(routes, views = import.meta.glob('../../views/**/*.vue
|
||||
}
|
||||
|
||||
// 将多层嵌套路由处理成平级
|
||||
function flatAsyncRoutes(routes, breadcrumb, baseUrl = '') {
|
||||
function flatAsyncRoutes(routes, breadcrumb = [], baseUrl = '') {
|
||||
let res = []
|
||||
routes.forEach(route => {
|
||||
if (route.children) {
|
||||
@ -71,7 +72,8 @@ function flatAsyncRoutes(routes, breadcrumb, baseUrl = '') {
|
||||
if (route.meta.breadcrumb !== false) {
|
||||
childrenBreadcrumb.push({
|
||||
path: childrenBaseUrl,
|
||||
title: route.meta.title
|
||||
title: route.meta.title,
|
||||
hide: !route.meta.breadcrumb && route.meta.breadcrumb === false
|
||||
})
|
||||
}
|
||||
let tmpRoute = deepClone(route)
|
||||
@ -103,12 +105,11 @@ function flatAsyncRoutes(routes, breadcrumb, baseUrl = '') {
|
||||
}
|
||||
// 处理面包屑导航
|
||||
let tmpBreadcrumb = deepClone(breadcrumb)
|
||||
if (tmpRoute.meta.breadcrumb !== false) {
|
||||
tmpBreadcrumb.push({
|
||||
path: tmpRoute.path,
|
||||
title: tmpRoute.meta.title
|
||||
})
|
||||
}
|
||||
tmpBreadcrumb.push({
|
||||
path: tmpRoute.path,
|
||||
title: tmpRoute.meta.title,
|
||||
hide: !tmpRoute.meta.breadcrumb && tmpRoute.meta.breadcrumb === false
|
||||
})
|
||||
tmpRoute.meta.breadcrumbNeste = tmpBreadcrumb
|
||||
res.push(tmpRoute)
|
||||
}
|
||||
@ -137,10 +138,7 @@ const useRouteStore = defineStore(
|
||||
})
|
||||
routes.map(item => {
|
||||
if (item.children) {
|
||||
item.children = flatAsyncRoutes(item.children, [{
|
||||
path: item.path,
|
||||
title: item.meta.title
|
||||
}], item.path)
|
||||
item.children = flatAsyncRoutes(item.children, [], item.path)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
@ -150,6 +148,18 @@ const useRouteStore = defineStore(
|
||||
}
|
||||
}
|
||||
return routes
|
||||
},
|
||||
flatSystemRoutes: () => {
|
||||
let routes = []
|
||||
systemRoutes.map(item => {
|
||||
routes.push(deepClone(item))
|
||||
})
|
||||
routes.map(item => {
|
||||
if (item.children) {
|
||||
item.children = flatAsyncRoutes(item.children, [], item.path)
|
||||
}
|
||||
})
|
||||
return routes
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
|
Loading…
Reference in New Issue
Block a user