fix: 精简路由,重新规范路径

This commit is contained in:
chansee97 2025-08-18 23:53:25 +08:00
parent 03a7891ed4
commit 501b64e884
31 changed files with 222 additions and 334 deletions

View File

@ -108,9 +108,6 @@
"QRCode": "QR code",
"about": "About",
"clipboard": "Clipboard",
"demo403": "403",
"demo404": "404",
"demo500": "500",
"dictionarySetting": "Dictionary settings",
"documents": "Document",
"documentsVite": "Vite",
@ -122,7 +119,6 @@
"editor": "Editor",
"editorMd": "MarkDown editor",
"editorRich": "Rich text editor",
"error": "Exception page",
"icons": "Icon",
"justSuper": "Supervisible",
"map": "Map",

View File

@ -151,10 +151,6 @@
"permission": "权限",
"permissionDemo": "权限示例",
"justSuper": "super可见",
"error": "异常页",
"demo403": "403",
"demo404": "404",
"demo500": "500",
"setting": "系统设置",
"accountSetting": "用户设置",
"dictionarySetting": "字典设置",

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 60 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 41 KiB

View File

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 71 KiB

View File

@ -1,36 +0,0 @@
<script setup lang="ts">
defineProps<{
/** 异常类型 403 404 500 */
type: '403' | '404' | '500'
}>()
const router = useRouter()
</script>
<template>
<div class="flex-col-center h-full">
<img
v-if="type === '403'"
src="@/assets/svg/error-403.svg"
alt=""
class="w-1/3"
>
<img
v-if="type === '404'"
src="@/assets/svg/error-404.svg"
alt=""
class="w-1/3"
>
<img
v-if="type === '500'"
src="@/assets/svg/error-500.svg"
alt=""
class="w-1/3"
>
<n-button
type="primary"
@click="router.push('/')"
>
{{ $t('app.backHome') }}
</n-button>
</div>
</template>

View File

@ -61,7 +61,7 @@ function handleSelect(key: string | number) {
})
}
if (key === 'userCenter')
router.push('/userCenter')
router.push('/user-center')
if (key === 'guthub')
window.open('https://github.com/chansee97/nova-admin')

View File

@ -47,7 +47,7 @@ export function setupRouterGuard(router: Router) {
}
// 如果路由设置了requiresAuth为true且用户未登录重定向到登录页
else if (to.meta.requiresAuth === true && !isLogin) {
const redirect = to.name === '404' ? undefined : to.fullPath
const redirect = to.name === 'not-found' ? undefined : to.fullPath
next({ path: '/login', query: { redirect } })
return
}
@ -57,7 +57,7 @@ export function setupRouterGuard(router: Router) {
try {
await routeStore.initAuthRoute()
// 动态路由加载完回到根路由
if (to.name === '404') {
if (to.name === 'not-found') {
// 等待权限路由加载好了,回到之前的路由,否则404
next({
path: to.fullPath,

View File

@ -11,7 +11,7 @@ export const routes: RouteRecordRaw[] = [
{
path: '/login',
name: 'login',
component: () => import('@/views/login/index.vue'), // 注意这里要带上 文件后缀.vue
component: () => import('@/views/build-in/login/index.vue'), // 注意这里要带上 文件后缀.vue
meta: {
title: '登录',
withoutTab: true,
@ -20,7 +20,7 @@ export const routes: RouteRecordRaw[] = [
{
path: '/public',
name: 'publicAccess',
component: () => import('@/views/demo/publicAccess/index.vue'),
component: () => import('@/views/build-in/public-access/index.vue'),
meta: {
title: '公共访问示例',
requiresAuth: false,
@ -28,38 +28,19 @@ export const routes: RouteRecordRaw[] = [
},
},
{
path: '/403',
name: '403',
component: () => import('@/views/error/403/index.vue'),
meta: {
title: '用户无权限',
withoutTab: true,
},
},
{
path: '/404',
name: '404',
component: () => import('@/views/error/404/index.vue'),
path: '/not-found',
name: 'not-found',
component: () => import('@/views/build-in/not-found/index.vue'),
meta: {
title: '找不到页面',
icon: 'icon-park-outline:ghost',
withoutTab: true,
},
},
{
path: '/500',
name: '500',
component: () => import('@/views/error/500/index.vue'),
meta: {
title: '服务器错误',
icon: 'icon-park-outline:close-wifi',
withoutTab: true,
},
},
{
path: '/:pathMatch(.*)*',
component: () => import('@/views/error/404/index.vue'),
name: '404',
component: () => import('@/views/build-in/not-found/index.vue'),
name: 'not-found',
meta: {
title: '找不到页面',
icon: 'icon-park-outline:ghost',

View File

@ -19,7 +19,7 @@ export const staticRoutes: AppRoute.RowRoute[] = [
pinTab: true,
menuType: 'page',
componentPath: '/dashboard/workbench/index.vue',
id: 2,
id: 101,
pid: 1,
},
{
@ -30,7 +30,7 @@ export const staticRoutes: AppRoute.RowRoute[] = [
icon: 'icon-park-outline:anchor',
menuType: 'page',
componentPath: '/dashboard/monitor/index.vue',
id: 3,
id: 102,
pid: 1,
},
{
@ -41,53 +41,53 @@ export const staticRoutes: AppRoute.RowRoute[] = [
icon: 'icon-park-outline:list',
menuType: 'dir',
componentPath: null,
id: 4,
id: 2,
pid: null,
},
{
name: 'multi2',
path: '/multi/multi2',
path: '/multi/multi-2',
title: '多级菜单子页',
requiresAuth: true,
icon: 'icon-park-outline:list',
menuType: 'page',
componentPath: '/demo/multi/multi2/index.vue',
id: 6,
pid: 4,
componentPath: '/demo/multi/multi-2/index.vue',
id: 201,
pid: 2,
},
{
name: 'multi2Detail',
path: '/multi/multi2/detail',
name: 'multi2-detail',
path: '/multi/multi-2/detail',
title: '菜单详情页',
requiresAuth: false,
icon: 'icon-park-outline:list',
hide: true,
activeMenu: '/multi/multi2',
activeMenu: '/multi/multi-2',
menuType: 'page',
componentPath: '/demo/multi/multi2/detail/index.vue',
id: 7,
pid: 4,
componentPath: '/demo/multi/multi-2/detail/index.vue',
id: 20101,
pid: 2,
},
{
name: 'multi3',
path: '/multi/multi3',
path: '/multi/multi-3',
title: '多级菜单',
requiresAuth: true,
icon: 'icon-park-outline:list',
menuType: 'dir',
componentPath: null,
id: 8,
pid: 4,
id: 202,
pid: 2,
},
{
name: 'multi4',
path: '/multi/multi3/multi4',
path: '/multi/multi-3/multi-4',
title: '多级菜单3-1',
requiresAuth: true,
icon: 'icon-park-outline:list',
componentPath: '/demo/multi/multi3/multi4/index.vue',
id: 9,
pid: 8,
componentPath: '/demo/multi/multi-3/multi-4/index.vue',
id: 20201,
pid: 202,
},
{
name: 'list',
@ -97,28 +97,38 @@ export const staticRoutes: AppRoute.RowRoute[] = [
icon: 'icon-park-outline:list-two',
menuType: 'dir',
componentPath: null,
id: 10,
id: 3,
pid: null,
},
{
name: 'commonList',
path: '/list/commonList',
path: '/list/common-list',
title: '常用列表',
requiresAuth: true,
icon: 'icon-park-outline:list-view',
componentPath: '/demo/list/commonList/index.vue',
id: 11,
pid: 10,
componentPath: '/demo/list/common-list/index.vue',
id: 301,
pid: 3,
},
{
name: 'cardList',
path: '/list/cardList',
path: '/list/card-list',
title: '卡片列表',
requiresAuth: true,
icon: 'icon-park-outline:view-grid-list',
componentPath: '/demo/list/cardList/index.vue',
id: 12,
pid: 10,
componentPath: '/demo/list/card-list/index.vue',
id: 302,
pid: 3,
},
{
name: 'draggableList',
path: '/list/draggable-list',
title: '拖拽列表',
requiresAuth: true,
icon: 'icon-park-outline:menu-fold',
componentPath: '/demo/list/draggable-list/index.vue',
id: 303,
pid: 3,
},
{
name: 'demo',
@ -128,7 +138,7 @@ export const staticRoutes: AppRoute.RowRoute[] = [
icon: 'icon-park-outline:application-one',
menuType: 'dir',
componentPath: null,
id: 13,
id: 4,
pid: null,
},
{
@ -138,8 +148,8 @@ export const staticRoutes: AppRoute.RowRoute[] = [
requiresAuth: true,
icon: 'icon-park-outline:international',
componentPath: '/demo/fetch/index.vue',
id: 5,
pid: 13,
id: 401,
pid: 4,
},
{
name: 'echarts',
@ -148,8 +158,8 @@ export const staticRoutes: AppRoute.RowRoute[] = [
requiresAuth: true,
icon: 'icon-park-outline:chart-proportion',
componentPath: '/demo/echarts/index.vue',
id: 15,
pid: 13,
id: 402,
pid: 4,
},
{
name: 'map',
@ -159,8 +169,8 @@ export const staticRoutes: AppRoute.RowRoute[] = [
icon: 'carbon:map',
keepAlive: true,
componentPath: '/demo/map/index.vue',
id: 17,
pid: 13,
id: 403,
pid: 4,
},
{
name: 'editor',
@ -170,8 +180,8 @@ export const staticRoutes: AppRoute.RowRoute[] = [
icon: 'icon-park-outline:editor',
menuType: 'dir',
componentPath: null,
id: 18,
pid: 13,
id: 404,
pid: 4,
},
{
name: 'editorMd',
@ -180,8 +190,8 @@ export const staticRoutes: AppRoute.RowRoute[] = [
requiresAuth: true,
icon: 'ri:markdown-line',
componentPath: '/demo/editor/md/index.vue',
id: 19,
pid: 18,
id: 40401,
pid: 404,
},
{
name: 'editorRich',
@ -190,8 +200,8 @@ export const staticRoutes: AppRoute.RowRoute[] = [
requiresAuth: true,
icon: 'icon-park-outline:edit-one',
componentPath: '/demo/editor/rich/index.vue',
id: 20,
pid: 18,
id: 40402,
pid: 404,
},
{
name: 'clipboard',
@ -200,8 +210,8 @@ export const staticRoutes: AppRoute.RowRoute[] = [
requiresAuth: true,
icon: 'icon-park-outline:clipboard',
componentPath: '/demo/clipboard/index.vue',
id: 21,
pid: 13,
id: 405,
pid: 4,
},
{
name: 'icons',
@ -210,18 +220,38 @@ export const staticRoutes: AppRoute.RowRoute[] = [
requiresAuth: true,
icon: 'local:cool',
componentPath: '/demo/icons/index.vue',
id: 22,
pid: 13,
id: 406,
pid: 4,
},
{
name: 'QRCode',
path: '/demo/QRCode',
path: '/demo/qr-code',
title: '二维码',
requiresAuth: true,
icon: 'icon-park-outline:two-dimensional-code',
componentPath: '/demo/QRCode/index.vue',
id: 23,
pid: 13,
componentPath: '/demo/qr-code/index.vue',
id: 407,
pid: 4,
},
{
name: 'cascader',
path: '/demo/cascader',
title: '省市区联动',
requiresAuth: true,
icon: 'icon-park-outline:add-subset',
componentPath: '/demo/cascader/index.vue',
id: 408,
pid: 4,
},
{
name: 'dict',
path: '/demo/dict',
title: '字典示例',
requiresAuth: true,
icon: 'icon-park-outline:book-one',
componentPath: '/demo/dict/index.vue',
id: 409,
pid: 4,
},
{
name: 'documents',
@ -231,7 +261,7 @@ export const staticRoutes: AppRoute.RowRoute[] = [
icon: 'icon-park-outline:file-doc',
menuType: 'dir',
componentPath: null,
id: 24,
id: 5,
pid: null,
},
{
@ -241,8 +271,8 @@ export const staticRoutes: AppRoute.RowRoute[] = [
requiresAuth: true,
icon: 'logos:vue',
componentPath: '/demo/documents/vue/index.vue',
id: 25,
pid: 24,
id: 501,
pid: 5,
},
{
name: 'documentsVite',
@ -251,169 +281,21 @@ export const staticRoutes: AppRoute.RowRoute[] = [
requiresAuth: true,
icon: 'logos:vitejs',
componentPath: '/demo/documents/vite/index.vue',
id: 26,
pid: 24,
id: 502,
pid: 5,
},
{
name: 'documentsVueuse',
path: '/documents/vueuse',
path: '/documents/vue-use',
title: 'VueUse外链',
requiresAuth: true,
icon: 'logos:vueuse',
href: 'https://vueuse.org/guide/',
componentPath: 'null',
id: 27,
pid: 24,
},
{
name: 'permission',
path: '/permission',
title: '权限',
requiresAuth: true,
icon: 'icon-park-outline:people-safe',
menuType: 'dir',
componentPath: null,
id: 28,
pid: null,
},
{
name: 'permissionDemo',
path: '/permission/permission',
title: '权限示例',
requiresAuth: true,
icon: 'icon-park-outline:right-user',
componentPath: '/demo/permission/permission/index.vue',
id: 29,
pid: 28,
},
{
name: 'justSuper',
path: '/permission/justSuper',
title: 'super可见',
requiresAuth: true,
roles: [
'super',
],
icon: 'icon-park-outline:wrong-user',
componentPath: '/demo/permission/justSuper/index.vue',
id: 30,
pid: 28,
},
{
name: 'error',
path: '/error',
title: '异常页',
requiresAuth: true,
icon: 'icon-park-outline:error-computer',
menuType: 'dir',
componentPath: null,
id: 31,
pid: null,
},
{
name: 'demo403',
path: '/error/403',
title: '403',
requiresAuth: true,
icon: 'carbon:error',
order: 3,
componentPath: '/error/403/index.vue',
id: 32,
pid: 31,
},
{
name: 'demo404',
path: '/error/404',
title: '404',
requiresAuth: true,
icon: 'icon-park-outline:error',
order: 2,
componentPath: '/error/404/index.vue',
id: 33,
pid: 31,
},
{
name: 'demo500',
path: '/error/500',
title: '500',
requiresAuth: true,
icon: 'carbon:data-error',
order: 1,
componentPath: '/error/500/index.vue',
id: 34,
pid: 31,
},
{
name: 'setting',
path: '/setting',
title: '系统设置',
requiresAuth: true,
icon: 'icon-park-outline:setting',
menuType: 'dir',
componentPath: null,
id: 35,
pid: null,
},
{
name: 'accountSetting',
path: '/setting/account',
title: '用户设置',
requiresAuth: true,
icon: 'icon-park-outline:every-user',
componentPath: '/setting/account/index.vue',
id: 36,
pid: 35,
},
{
name: 'dictionarySetting',
path: '/setting/dictionary',
title: '字典设置',
requiresAuth: true,
icon: 'icon-park-outline:book-one',
componentPath: '/setting/dictionary/index.vue',
id: 37,
pid: 35,
},
{
name: 'menuSetting',
path: '/setting/menu',
title: '菜单设置',
requiresAuth: true,
icon: 'icon-park-outline:application-menu',
componentPath: '/setting/menu/index.vue',
id: 38,
pid: 35,
},
{
name: 'userCenter',
path: '/userCenter',
title: '个人中心',
requiresAuth: true,
icon: 'carbon:user-avatar-filled-alt',
componentPath: '/demo/userCenter/index.vue',
id: 39,
pid: null,
},
{
name: 'about',
path: '/about',
title: '关于',
requiresAuth: true,
icon: 'icon-park-outline:info',
componentPath: '/demo/about/index.vue',
id: 40,
pid: null,
},
{
name: 'cascader',
path: '/demo/cascader',
title: '省市区联动',
requiresAuth: true,
icon: 'icon-park-outline:add-subset',
componentPath: '/demo/cascader/index.vue',
id: 41,
pid: 13,
id: 503,
pid: 5,
},
{
name: 'documentsNova',
path: '/documents/nova',
@ -422,28 +304,8 @@ export const staticRoutes: AppRoute.RowRoute[] = [
icon: 'local:logo',
href: 'https://nova-admin-docs.netlify.app/',
componentPath: '2333333',
id: 42,
pid: 24,
},
{
name: 'dict',
path: '/demo/dict',
title: '字典示例',
requiresAuth: true,
icon: 'icon-park-outline:book-one',
componentPath: '/demo/dict/index.vue',
id: 43,
pid: 13,
},
{
name: 'draggableList',
path: '/list/draggableList',
title: '拖拽列表',
requiresAuth: true,
icon: 'icon-park-outline:menu-fold',
componentPath: '/demo/list/draggableList/index.vue',
id: 44,
pid: 10,
id: 504,
pid: 5,
},
{
name: 'documentsPublic',
@ -453,7 +315,104 @@ export const staticRoutes: AppRoute.RowRoute[] = [
icon: 'local:logo',
href: '/public',
componentPath: 'null',
id: 45,
pid: 24,
id: 505,
pid: 5,
},
{
name: 'permission',
path: '/permission',
title: '权限',
requiresAuth: true,
icon: 'icon-park-outline:people-safe',
menuType: 'dir',
componentPath: null,
id: 6,
pid: null,
},
{
name: 'permissionDemo',
path: '/permission/permission',
title: '权限示例',
requiresAuth: true,
icon: 'icon-park-outline:right-user',
componentPath: '/demo/permission/permission/index.vue',
id: 601,
pid: 6,
},
{
name: 'justSuper',
path: '/permission/just-super',
title: 'super可见',
requiresAuth: true,
roles: [
'super',
],
icon: 'icon-park-outline:wrong-user',
componentPath: '/demo/permission/just-super/index.vue',
id: 602,
pid: 6,
},
{
name: 'setting',
path: '/setting',
title: '系统设置',
requiresAuth: true,
icon: 'icon-park-outline:setting',
menuType: 'dir',
componentPath: null,
id: 7,
pid: null,
},
{
name: 'accountSetting',
path: '/setting/account',
title: '用户设置',
requiresAuth: true,
icon: 'icon-park-outline:every-user',
componentPath: '/setting/account/index.vue',
id: 701,
pid: 7,
},
{
name: 'dictionarySetting',
path: '/setting/dictionary',
title: '字典设置',
requiresAuth: true,
icon: 'icon-park-outline:book-one',
componentPath: '/setting/dictionary/index.vue',
id: 702,
pid: 7,
},
{
name: 'menuSetting',
path: '/setting/menu',
title: '菜单设置',
requiresAuth: true,
icon: 'icon-park-outline:application-menu',
componentPath: '/setting/menu/index.vue',
id: 703,
pid: 7,
},
{
name: 'about',
path: '/about',
title: '关于',
requiresAuth: true,
icon: 'icon-park-outline:info',
componentPath: '/demo/about/index.vue',
id: 8,
pid: null,
},
{
name: 'userCenter',
path: '/user-center',
title: '个人中心',
requiresAuth: true,
hide: true,
icon: 'carbon:user-avatar-filled-alt',
componentPath: '/build-in/user-center/index.vue',
id: 999,
pid: null,
},
]

View File

@ -0,0 +1,19 @@
<script setup lang="ts">
const router = useRouter()
</script>
<template>
<div class="flex-col-center h-full">
<img
src="@/assets/svg/error-not-found.svg"
alt=""
class="w-1/3"
>
<n-button
type="primary"
@click="router.push('/')"
>
{{ $t('app.backHome') }}
</n-button>
</div>
</template>

View File

@ -122,7 +122,7 @@ function handleResetSearch() {
model.value = { ...initialModel }
}
type ModalType = 'add' | 'edit'
type ModalType = 'add' | 'edit'
const modalType = ref<ModalType>('add')
function setModalType(type: ModalType) {
modalType.value = type

View File

@ -1,7 +0,0 @@
<script setup lang="ts"></script>
<template>
<ErrorTip type="403" />
</template>
<style lang="scss" scoped></style>

View File

@ -1,7 +0,0 @@
<script setup lang="ts"></script>
<template>
<ErrorTip type="404" />
</template>
<style lang="scss" scoped></style>

View File

@ -1,7 +0,0 @@
<script setup lang="ts"></script>
<template>
<ErrorTip type="500" />
</template>
<style lang="scss" scoped></style>

View File

@ -1,10 +1,10 @@
<script setup lang="tsx">
import type { DataTableColumns } from 'naive-ui'
import CopyText from '@/components/custom/CopyText.vue'
import { useBoolean } from '@/hooks'
import { fetchAllRoutes } from '@/service'
import { arrayToTree, createIcon } from '@/utils'
import { NButton, NPopconfirm, NSpace, NTag } from 'naive-ui'
import { renderProCopyableText } from 'pro-naive-ui'
import TableModal from './components/TableModal.vue'
const { bool: loading, setTrue: startLoading, setFalse: endLoading } = useBoolean(false)
@ -45,11 +45,7 @@ const columns: DataTableColumns<AppRoute.RowRoute> = [
{
title: '路径',
key: 'path',
render: (row) => {
return (
<CopyText value={row.path} />
)
},
render: row => renderProCopyableText(row.path),
},
{
title: '组件路径',