refactor: refactor async routes

This commit is contained in:
张传龙 2022-08-07 22:25:28 +08:00
parent 869a68812c
commit ef3aaa5be5
10 changed files with 159 additions and 182 deletions

View File

@ -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()

View File

@ -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 }

View File

@ -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'],
},
},
],
},
],
},
]

View File

@ -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))
} }

View File

@ -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']

View 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',
},
},
],
}

View 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',
},
},
],
}

View 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,
},
},
],
},
],
}

View File

@ -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>

View 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,
},
},
],
}