refactor: refactor async routes
This commit is contained in:
parent
869a68812c
commit
ef3aaa5be5
@ -5,7 +5,7 @@ import { getToken, refreshAccessToken, removeToken } from '@/utils/token'
|
|||||||
import { toLogin } from '@/utils/auth'
|
import { toLogin } from '@/utils/auth'
|
||||||
import { isNullOrWhitespace } from '@/utils/is'
|
import { isNullOrWhitespace } from '@/utils/is'
|
||||||
|
|
||||||
const WHITE_LIST = ['/login', '/redirect']
|
const WHITE_LIST = ['/login']
|
||||||
export function createPermissionGuard(router) {
|
export function createPermissionGuard(router) {
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const permissionStore = usePermissionStore()
|
const permissionStore = usePermissionStore()
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import Layout from '@/layout/index.vue'
|
const Layout = () => import('@/layout/index.vue')
|
||||||
import Home from '@/views/dashboard/index.vue'
|
|
||||||
|
|
||||||
export const basicRoutes = [
|
export const basicRoutes = [
|
||||||
{
|
{
|
||||||
@ -8,19 +7,7 @@ export const basicRoutes = [
|
|||||||
component: () => import('@/views/error-page/404.vue'),
|
component: () => import('@/views/error-page/404.vue'),
|
||||||
isHidden: true,
|
isHidden: true,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'REDIRECT',
|
|
||||||
path: '/redirect',
|
|
||||||
component: Layout,
|
|
||||||
isHidden: true,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
name: 'REDIRECT_NAME',
|
|
||||||
path: '',
|
|
||||||
component: () => import('@/views/redirect/index.vue'),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'LOGIN',
|
name: 'LOGIN',
|
||||||
path: '/login',
|
path: '/login',
|
||||||
@ -31,97 +18,6 @@ export const basicRoutes = [
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
|
||||||
name: 'Dashboard',
|
|
||||||
path: '/',
|
|
||||||
component: Layout,
|
|
||||||
redirect: '/home',
|
|
||||||
meta: {
|
|
||||||
title: 'Dashboard',
|
|
||||||
icon: 'mdi:chart-bar',
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
name: 'Home',
|
|
||||||
path: 'home',
|
|
||||||
component: Home,
|
|
||||||
meta: {
|
|
||||||
title: '首页',
|
|
||||||
icon: 'mdi:home',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: 'ErrorPage',
|
|
||||||
path: '/error-page',
|
|
||||||
component: Layout,
|
|
||||||
redirect: '/error-page/404',
|
|
||||||
meta: {
|
|
||||||
title: '错误页',
|
|
||||||
icon: 'mdi:alert-circle-outline',
|
|
||||||
index: 4,
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
name: 'ERROR-404',
|
|
||||||
path: '404',
|
|
||||||
component: () => import('@/views/error-page/404.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '404',
|
|
||||||
icon: 'mdi:alert-circle-outline',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: 'Test',
|
|
||||||
path: '/test',
|
|
||||||
component: Layout,
|
|
||||||
redirect: '/test/unocss',
|
|
||||||
meta: {
|
|
||||||
title: '基础功能测试',
|
|
||||||
icon: 'mdi:menu',
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
name: 'Unocss',
|
|
||||||
path: 'unocss',
|
|
||||||
component: () => import('@/views/test-page/unocss/index.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '测试unocss',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Message',
|
|
||||||
path: 'message',
|
|
||||||
component: () => import('@/views/test-page/message/index.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '测试Message',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Dialog',
|
|
||||||
path: 'dialog',
|
|
||||||
component: () => import('@/views/test-page/dialog/index.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '测试Dialog',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'TestKeepAlive',
|
|
||||||
path: 'keep-alive',
|
|
||||||
component: () => import('@/views/test-page/keep-alive/index.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '测试Keep-Alive',
|
|
||||||
keepAlive: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
{
|
||||||
name: 'ExternalLink',
|
name: 'ExternalLink',
|
||||||
path: '/external-link',
|
path: '/external-link',
|
||||||
@ -129,6 +25,7 @@ export const basicRoutes = [
|
|||||||
meta: {
|
meta: {
|
||||||
title: '外部链接',
|
title: '外部链接',
|
||||||
icon: 'mdi:link-variant',
|
icon: 'mdi:link-variant',
|
||||||
|
index: 1,
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
@ -166,10 +63,10 @@ export const NOT_FOUND_ROUTE = {
|
|||||||
isHidden: true,
|
isHidden: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
const modules = import.meta.globEager('./modules/*.js')
|
const modules = import.meta.globEager('@/views/**/route.js')
|
||||||
const asyncRoutes = []
|
const asyncRoutes = []
|
||||||
Object.keys(modules).forEach((key) => {
|
Object.keys(modules).forEach((key) => {
|
||||||
asyncRoutes.push(...modules[key].default)
|
asyncRoutes.push(modules[key].default)
|
||||||
})
|
})
|
||||||
|
|
||||||
export { asyncRoutes }
|
export { asyncRoutes }
|
||||||
|
@ -1,48 +0,0 @@
|
|||||||
import Layout from '@/layout/index.vue'
|
|
||||||
|
|
||||||
export default [
|
|
||||||
{
|
|
||||||
name: 'Example',
|
|
||||||
path: '/example',
|
|
||||||
component: Layout,
|
|
||||||
redirect: '/example/table',
|
|
||||||
meta: {
|
|
||||||
title: '组件示例',
|
|
||||||
role: ['admin'],
|
|
||||||
icon: 'mdi:menu',
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
name: 'Table',
|
|
||||||
path: 'table',
|
|
||||||
component: () => import('@/views/examples/table/index.vue'),
|
|
||||||
redirect: '/example/table/post',
|
|
||||||
meta: {
|
|
||||||
title: '表格',
|
|
||||||
role: ['admin'],
|
|
||||||
icon: 'mdi:table',
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
name: 'PostList',
|
|
||||||
path: 'post',
|
|
||||||
component: () => import('@/views/examples/table/post/index.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '文章列表',
|
|
||||||
role: ['admin'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'PostCreate',
|
|
||||||
path: 'post-create',
|
|
||||||
component: () => import('@/views/examples/table/post/PostCreate.vue'),
|
|
||||||
meta: {
|
|
||||||
title: '创建文章',
|
|
||||||
role: ['admin'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]
|
|
@ -2,10 +2,15 @@ import { defineStore } from 'pinia'
|
|||||||
import { asyncRoutes, basicRoutes } from '@/router/routes'
|
import { asyncRoutes, basicRoutes } from '@/router/routes'
|
||||||
|
|
||||||
function hasPermission(route, role) {
|
function hasPermission(route, role) {
|
||||||
|
// * 不需要权限直接返回true
|
||||||
|
if (!route.meta?.requireAuth) return true
|
||||||
|
|
||||||
const routeRole = route.meta?.role ? route.meta.role : []
|
const routeRole = route.meta?.role ? route.meta.role : []
|
||||||
if (!role.length || !routeRole.length) {
|
|
||||||
return false
|
// * 登录用户没有角色或者路由没有设置角色判定为没有权限
|
||||||
}
|
if (!role.length || !routeRole.length) return false
|
||||||
|
|
||||||
|
// * 路由指定的角色包含任一登录用户角色则判定有权限
|
||||||
return role.some((item) => routeRole.includes(item))
|
return role.some((item) => routeRole.includes(item))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,4 +3,4 @@ import { sStorage } from '@/utils/cache'
|
|||||||
export const activeTag = sStorage.get('activeTag')
|
export const activeTag = sStorage.get('activeTag')
|
||||||
export const tags = sStorage.get('tags')
|
export const tags = sStorage.get('tags')
|
||||||
|
|
||||||
export const WITHOUT_TAG_PATHS = ['/404', '/login', '/redirect']
|
export const WITHOUT_TAG_PATHS = ['/404', '/login']
|
||||||
|
23
src/views/dashboard/route.js
Normal file
23
src/views/dashboard/route.js
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
const Layout = () => import('@/layout/index.vue')
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Dashboard',
|
||||||
|
path: '/',
|
||||||
|
component: Layout,
|
||||||
|
redirect: '/home',
|
||||||
|
meta: {
|
||||||
|
title: 'Dashboard',
|
||||||
|
icon: 'mdi:chart-bar',
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: 'Home',
|
||||||
|
path: 'home',
|
||||||
|
component: () => import('./index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '首页',
|
||||||
|
icon: 'mdi:home',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
24
src/views/error-page/route.js
Normal file
24
src/views/error-page/route.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
const Layout = () => import('@/layout/index.vue')
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ErrorPage',
|
||||||
|
path: '/error-page',
|
||||||
|
component: Layout,
|
||||||
|
redirect: '/error-page/404',
|
||||||
|
meta: {
|
||||||
|
title: '错误页',
|
||||||
|
icon: 'mdi:alert-circle-outline',
|
||||||
|
index: 4,
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: 'ERROR-404',
|
||||||
|
path: '404',
|
||||||
|
component: () => import('./404.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '404',
|
||||||
|
icon: 'mdi:alert-circle-outline',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
50
src/views/examples/table/route.js
Normal file
50
src/views/examples/table/route.js
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
const Layout = () => import('@/layout/index.vue')
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Example',
|
||||||
|
path: '/example',
|
||||||
|
component: Layout,
|
||||||
|
redirect: '/example/table',
|
||||||
|
meta: {
|
||||||
|
title: '组件示例',
|
||||||
|
icon: 'mdi:menu',
|
||||||
|
role: ['admin'],
|
||||||
|
requireAuth: true,
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: 'Table',
|
||||||
|
path: 'table',
|
||||||
|
component: () => import('./index.vue'),
|
||||||
|
redirect: '/example/table/post',
|
||||||
|
meta: {
|
||||||
|
title: '表格',
|
||||||
|
icon: 'mdi:table',
|
||||||
|
role: ['admin'],
|
||||||
|
requireAuth: true,
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: 'PostList',
|
||||||
|
path: 'post',
|
||||||
|
component: () => import('./post/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '文章列表',
|
||||||
|
role: ['admin'],
|
||||||
|
requireAuth: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'PostCreate',
|
||||||
|
path: 'post-create',
|
||||||
|
component: () => import('./post/PostCreate.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '创建文章',
|
||||||
|
role: ['admin'],
|
||||||
|
requireAuth: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
@ -1,21 +0,0 @@
|
|||||||
<template></template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
const { currentRoute, replace } = useRouter()
|
|
||||||
|
|
||||||
const { query } = currentRoute.value
|
|
||||||
let { redirect } = query
|
|
||||||
Reflect.deleteProperty(query, 'redirect')
|
|
||||||
|
|
||||||
if (Array.isArray(redirect)) {
|
|
||||||
redirect = redirect.join('/')
|
|
||||||
}
|
|
||||||
if (redirect.startsWith('/redirect')) {
|
|
||||||
redirect = '/'
|
|
||||||
}
|
|
||||||
|
|
||||||
replace({
|
|
||||||
path: redirect.startsWith('/') ? redirect : '/' + redirect,
|
|
||||||
query,
|
|
||||||
})
|
|
||||||
</script>
|
|
47
src/views/test-page/route.js
Normal file
47
src/views/test-page/route.js
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
const Layout = () => import('@/layout/index.vue')
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Test',
|
||||||
|
path: '/test',
|
||||||
|
component: Layout,
|
||||||
|
redirect: '/test/unocss',
|
||||||
|
meta: {
|
||||||
|
title: '基础功能测试',
|
||||||
|
icon: 'mdi:menu',
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: 'Unocss',
|
||||||
|
path: 'unocss',
|
||||||
|
component: () => import('@/views/test-page/unocss/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '测试unocss',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Message',
|
||||||
|
path: 'message',
|
||||||
|
component: () => import('@/views/test-page/message/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '测试Message',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Dialog',
|
||||||
|
path: 'dialog',
|
||||||
|
component: () => import('@/views/test-page/dialog/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '测试Dialog',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'TestKeepAlive',
|
||||||
|
path: 'keep-alive',
|
||||||
|
component: () => import('@/views/test-page/keep-alive/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '测试Keep-Alive',
|
||||||
|
keepAlive: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user