fix: 修改动态路由接口

This commit is contained in:
chansee97 2025-09-05 18:11:59 +08:00
parent f9ef71f0c7
commit ab72ff1bdd
5 changed files with 65 additions and 140 deletions

View File

@ -45,6 +45,6 @@ export function fetchRefreshToken(data: any) {
}) })
} }
export function fetchUserRoutes(params: { id: number }) { export function fetchUserMenus() {
return request.Get<Api.Response<AppRoute.RowRoute[]>>('/getUserRoutes', { params }) return request.Get<Api.Response<Entity.Menu[]>>('/userMenu')
} }

View File

@ -1,6 +1,5 @@
export const staticRoutes: AppRoute.RowRoute[] = [ export const staticRoutes: Entity.Menu[] = [
{ {
name: 'home',
path: '/home', path: '/home',
title: '概览', title: '概览',
icon: 'icon-park-outline:analysis', icon: 'icon-park-outline:analysis',
@ -11,21 +10,16 @@ export const staticRoutes: AppRoute.RowRoute[] = [
parentId: 0, parentId: 0,
}, },
{ {
name: 'multi',
path: '/multi', path: '/multi',
title: '多级菜单演示', title: '多级菜单演示',
requiresAuth: true,
icon: 'icon-park-outline:list', icon: 'icon-park-outline:list',
menuType: 'dir', menuType: 'directory',
component: null,
id: 2, id: 2,
parentId: null, parentId: 0,
}, },
{ {
name: 'multi2',
path: '/multi/multi-2', path: '/multi/multi-2',
title: '多级菜单子页', title: '多级菜单子页',
requiresAuth: true,
icon: 'icon-park-outline:list', icon: 'icon-park-outline:list',
menuType: 'page', menuType: 'page',
component: '/demo/multi/multi-2/index.vue', component: '/demo/multi/multi-2/index.vue',
@ -33,106 +27,83 @@ export const staticRoutes: AppRoute.RowRoute[] = [
parentId: 2, parentId: 2,
}, },
{ {
name: 'multi2-detail',
path: '/multi/multi-2/detail', path: '/multi/multi-2/detail',
title: '菜单详情页', title: '菜单详情页',
requiresAuth: false,
icon: 'icon-park-outline:list', icon: 'icon-park-outline:list',
hide: true, menuVisible: true,
activeMenu: '/multi/multi-2', activePath: '/multi/multi-2',
menuType: 'page', menuType: 'page',
component: '/demo/multi/multi-2/detail/index.vue', component: '/demo/multi/multi-2/detail/index.vue',
id: 20101, id: 20101,
parentId: 2, parentId: 2,
}, },
{ {
name: 'multi3',
path: '/multi/multi-3', path: '/multi/multi-3',
title: '多级菜单', title: '多级菜单',
requiresAuth: true,
icon: 'icon-park-outline:list', icon: 'icon-park-outline:list',
menuType: 'dir', menuType: 'directory',
component: null,
id: 202, id: 202,
parentId: 2, parentId: 2,
}, },
{ {
name: 'multi4',
path: '/multi/multi-3/multi-4', path: '/multi/multi-3/multi-4',
title: '多级菜单3-1', title: '多级菜单3-1',
requiresAuth: true,
icon: 'icon-park-outline:list', icon: 'icon-park-outline:list',
component: '/demo/multi/multi-3/multi-4/index.vue', component: '/demo/multi/multi-3/multi-4/index.vue',
id: 20201, id: 20201,
parentId: 202, parentId: 202,
}, },
{ {
name: 'list',
path: '/list', path: '/list',
title: '列表页', title: '列表页',
requiresAuth: true,
icon: 'icon-park-outline:list-two', icon: 'icon-park-outline:list-two',
menuType: 'dir', menuType: 'directory',
component: null,
id: 3, id: 3,
parentId: null, parentId: 0,
}, },
{ {
name: 'cardList',
path: '/list/card-list', path: '/list/card-list',
title: '卡片列表', title: '卡片列表',
requiresAuth: true,
icon: 'icon-park-outline:view-grid-list', icon: 'icon-park-outline:view-grid-list',
component: '/demo/list/card-list/index.vue', component: '/demo/list/card-list/index.vue',
id: 302, id: 302,
parentId: 3, parentId: 3,
}, },
{ {
name: 'draggableList',
path: '/list/draggable-list', path: '/list/draggable-list',
title: '拖拽列表', title: '拖拽列表',
requiresAuth: true,
icon: 'icon-park-outline:menu-fold', icon: 'icon-park-outline:menu-fold',
component: '/demo/list/draggable-list/index.vue', component: '/demo/list/draggable-list/index.vue',
id: 303, id: 303,
parentId: 3, parentId: 3,
}, },
{ {
name: 'demo',
path: '/demo', path: '/demo',
title: '功能示例', title: '功能示例',
requiresAuth: true,
icon: 'icon-park-outline:application-one', icon: 'icon-park-outline:application-one',
menuType: 'dir', menuType: 'directory',
component: null,
id: 4, id: 4,
parentId: null, parentId: 0,
}, },
{ {
name: 'fetch',
path: '/demo/fetch', path: '/demo/fetch',
title: '请求示例', title: '请求示例',
requiresAuth: true,
icon: 'icon-park-outline:international', icon: 'icon-park-outline:international',
component: '/demo/fetch/index.vue', component: '/demo/fetch/index.vue',
id: 401, id: 401,
parentId: 4, parentId: 4,
}, },
{ {
name: 'echarts',
path: '/demo/echarts', path: '/demo/echarts',
title: 'ECharts', title: 'ECharts',
requiresAuth: true,
icon: 'icon-park-outline:chart-proportion', icon: 'icon-park-outline:chart-proportion',
component: '/demo/echarts/index.vue', component: '/demo/echarts/index.vue',
id: 402, id: 402,
parentId: 4, parentId: 4,
}, },
{ {
name: 'map',
path: '/demo/map', path: '/demo/map',
title: '地图', title: '地图',
requiresAuth: true,
icon: 'carbon:map', icon: 'carbon:map',
keepAlive: true, keepAlive: true,
component: '/demo/map/index.vue', component: '/demo/map/index.vue',
@ -140,266 +111,206 @@ export const staticRoutes: AppRoute.RowRoute[] = [
parentId: 4, parentId: 4,
}, },
{ {
name: 'editor',
path: '/demo/editor', path: '/demo/editor',
title: '编辑器', title: '编辑器',
requiresAuth: true,
icon: 'icon-park-outline:editor', icon: 'icon-park-outline:editor',
menuType: 'dir', menuType: 'directory',
component: null,
id: 404, id: 404,
parentId: 4, parentId: 4,
}, },
{ {
name: 'editorMd',
path: '/demo/editor/md', path: '/demo/editor/md',
title: 'MarkDown', title: 'MarkDown',
requiresAuth: true,
icon: 'ri:markdown-line', icon: 'ri:markdown-line',
component: '/demo/editor/md/index.vue', component: '/demo/editor/md/index.vue',
id: 40401, id: 40401,
parentId: 404, parentId: 404,
}, },
{ {
name: 'editorRich',
path: '/demo/editor/rich', path: '/demo/editor/rich',
title: '富文本', title: '富文本',
requiresAuth: true,
icon: 'icon-park-outline:edit-one', icon: 'icon-park-outline:edit-one',
component: '/demo/editor/rich/index.vue', component: '/demo/editor/rich/index.vue',
id: 40402, id: 40402,
parentId: 404, parentId: 404,
}, },
{ {
name: 'clipboard',
path: '/demo/clipboard', path: '/demo/clipboard',
title: '剪贴板', title: '剪贴板',
requiresAuth: true,
icon: 'icon-park-outline:clipboard', icon: 'icon-park-outline:clipboard',
component: '/demo/clipboard/index.vue', component: '/demo/clipboard/index.vue',
id: 405, id: 405,
parentId: 4, parentId: 4,
}, },
{ {
name: 'icons',
path: '/demo/icons', path: '/demo/icons',
title: '图标', title: '图标',
requiresAuth: true,
icon: 'local:cool', icon: 'local:cool',
component: '/demo/icons/index.vue', component: '/demo/icons/index.vue',
id: 406, id: 406,
parentId: 4, parentId: 4,
}, },
{ {
name: 'QRCode',
path: '/demo/qr-code', path: '/demo/qr-code',
title: '二维码', title: '二维码',
requiresAuth: true,
icon: 'icon-park-outline:two-dimensional-code', icon: 'icon-park-outline:two-dimensional-code',
component: '/demo/qr-code/index.vue', component: '/demo/qr-code/index.vue',
id: 407, id: 407,
parentId: 4, parentId: 4,
}, },
{ {
name: 'cascader',
path: '/demo/cascader', path: '/demo/cascader',
title: '省市区联动', title: '省市区联动',
requiresAuth: true,
icon: 'icon-park-outline:add-subset', icon: 'icon-park-outline:add-subset',
component: '/demo/cascader/index.vue', component: '/demo/cascader/index.vue',
id: 408, id: 408,
parentId: 4, parentId: 4,
}, },
{ {
name: 'dict',
path: '/demo/dict', path: '/demo/dict',
title: '字典示例', title: '字典示例',
requiresAuth: true,
icon: 'icon-park-outline:book-one', icon: 'icon-park-outline:book-one',
component: '/demo/dict/index.vue', component: '/demo/dict/index.vue',
id: 409, id: 409,
parentId: 4, parentId: 4,
}, },
{ {
name: 'documents',
path: '/documents', path: '/documents',
title: '外链文档', title: '外链文档',
requiresAuth: true,
icon: 'icon-park-outline:file-doc', icon: 'icon-park-outline:file-doc',
menuType: 'dir', menuType: 'directory',
component: null,
id: 5, id: 5,
parentId: null, parentId: 0,
}, },
{ {
name: 'documentsVue',
path: '/documents/vue', path: '/documents/vue',
title: 'Vue', title: 'Vue',
requiresAuth: true,
icon: 'logos:vue', icon: 'logos:vue',
component: '/demo/documents/vue/index.vue', component: '/demo/documents/vue/index.vue',
id: 501, id: 501,
parentId: 5, parentId: 5,
}, },
{ {
name: 'documentsVite',
path: '/documents/vite', path: '/documents/vite',
title: 'Vite', title: 'Vite',
requiresAuth: true,
icon: 'logos:vitejs', icon: 'logos:vitejs',
component: '/demo/documents/vite/index.vue', component: '/demo/documents/vite/index.vue',
id: 502, id: 502,
parentId: 5, parentId: 5,
}, },
{ {
name: 'documentsVueuse', path: 'https://vueuse.org/guide/',
path: '/documents/vue-use',
title: 'VueUse外链', title: 'VueUse外链',
requiresAuth: true,
icon: 'logos:vueuse', icon: 'logos:vueuse',
href: 'https://vueuse.org/guide/', isLink: true,
component: 'null',
id: 503, id: 503,
parentId: 5, parentId: 5,
}, },
{ {
name: 'documentsNova', path: 'https://nova-admin-docs.netlify.app/',
path: '/documents/nova',
title: 'Nova docs', title: 'Nova docs',
requiresAuth: true,
icon: 'local:logo', icon: 'local:logo',
href: 'https://nova-admin-docs.netlify.app/', isLink: true,
component: '2333333',
id: 504, id: 504,
parentId: 5, parentId: 5,
}, },
{ {
name: 'documentsPublic', path: '/public',
path: '/documents/public',
title: '公共示例页(外链)', title: '公共示例页(外链)',
requiresAuth: true,
icon: 'local:logo', icon: 'local:logo',
href: '/public', isLink: true,
component: 'null',
id: 505, id: 505,
parentId: 5, parentId: 5,
}, },
{ {
name: 'permission',
path: '/permission', path: '/permission',
title: '权限', title: '权限',
requiresAuth: true,
icon: 'icon-park-outline:people-safe', icon: 'icon-park-outline:people-safe',
menuType: 'dir', menuType: 'directory',
component: null,
id: 6, id: 6,
parentId: null, parentId: 0,
}, },
{ {
name: 'permissionDemo',
path: '/permission/permission', path: '/permission/permission',
title: '权限示例', title: '权限示例',
requiresAuth: true,
icon: 'icon-park-outline:right-user', icon: 'icon-park-outline:right-user',
component: '/demo/permission/permission/index.vue', component: '/demo/permission/permission/index.vue',
id: 601, id: 601,
parentId: 6, parentId: 6,
}, },
{ {
name: 'justSuper',
path: '/permission/just-super', path: '/permission/just-super',
title: 'super可见', title: 'super可见',
requiresAuth: true,
roles: [
'super',
],
icon: 'icon-park-outline:wrong-user', icon: 'icon-park-outline:wrong-user',
component: '/demo/permission/just-super/index.vue', component: '/demo/permission/just-super/index.vue',
id: 602, id: 602,
parentId: 6, parentId: 6,
}, },
{ {
name: 'setting',
path: '/system', path: '/system',
title: '系统设置', title: '系统设置',
requiresAuth: true,
icon: 'icon-park-outline:setting', icon: 'icon-park-outline:setting',
menuType: 'dir', menuType: 'directory',
component: null,
id: 7, id: 7,
parentId: null, parentId: 0,
}, },
{ {
name: 'accountSetting',
path: '/system/user', path: '/system/user',
title: '用户设置', title: '用户设置',
requiresAuth: true,
icon: 'icon-park-outline:every-user', icon: 'icon-park-outline:every-user',
component: '/system/user/index.vue', component: '/system/user/index.vue',
id: 701, id: 701,
parentId: 7, parentId: 7,
}, },
{ {
name: 'roleSetting',
path: '/system/role', path: '/system/role',
title: '角色设置', title: '角色设置',
requiresAuth: true,
icon: 'icon-park-outline:every-user', icon: 'icon-park-outline:every-user',
component: '/system/role/index.vue', component: '/system/role/index.vue',
id: 702, id: 702,
parentId: 7, parentId: 7,
}, },
{ {
name: 'dictionarySetting',
path: '/system/dict', path: '/system/dict',
title: '字典设置', title: '字典设置',
requiresAuth: true,
icon: 'icon-park-outline:book-one', icon: 'icon-park-outline:book-one',
component: '/system/dict/index.vue', component: '/system/dict/index.vue',
id: 703, id: 703,
parentId: 7, parentId: 7,
}, },
{ {
name: 'menuSetting',
path: '/system/menu', path: '/system/menu',
title: '菜单设置', title: '菜单设置',
requiresAuth: true,
icon: 'icon-park-outline:application-menu', icon: 'icon-park-outline:application-menu',
component: '/system/menu/index.vue', component: '/system/menu/index.vue',
id: 704, id: 704,
parentId: 7, parentId: 7,
}, },
{ {
name: 'deptSetting',
path: '/system/dept', path: '/system/dept',
title: '部门管理', title: '部门管理',
requiresAuth: true,
icon: 'icon-park-outline:application-menu', icon: 'icon-park-outline:application-menu',
component: '/system/dept/index.vue', component: '/system/dept/index.vue',
id: 705, id: 705,
parentId: 7, parentId: 7,
}, },
{ {
name: 'about',
path: '/about', path: '/about',
title: '关于', title: '关于',
requiresAuth: true,
icon: 'icon-park-outline:info', icon: 'icon-park-outline:info',
component: '/demo/about/index.vue', component: '/demo/about/index.vue',
id: 8, id: 8,
parentId: null, parentId: 0,
}, },
{ {
name: 'userCenter',
path: '/user-center', path: '/user-center',
title: '个人中心', title: '个人中心',
requiresAuth: true, menuVisible: true,
hide: true,
icon: 'carbon:user-avatar-filled-alt', icon: 'carbon:user-avatar-filled-alt',
component: '/build-in/user-center/index.vue', component: '/build-in/user-center/index.vue',
id: 999, id: 999,
parentId: null, parentId: 0,
}, },
] ]

View File

@ -1,14 +1,14 @@
import type { MenuOption } from 'naive-ui' import type { MenuOption } from 'naive-ui'
import { router } from '@/router' import { router } from '@/router'
import { staticRoutes } from '@/router/routes.static' import { staticRoutes } from '@/router/routes.static'
import { fetchUserRoutes } from '@/api' import { fetchUserMenus } from '@/api'
import { $t } from '@/utils' import { $t } from '@/utils'
import { createMenus, createRoutes, generateCacheRoutes } from './helper' import { createMenus, createRoutes, generateCacheRoutes } from './helper'
interface RoutesStatus { interface RoutesStatus {
isInitAuthRoute: boolean isInitAuthRoute: boolean
menus: MenuOption[] menus: MenuOption[]
rowRoutes: AppRoute.RowRoute[] rowRoutes: Entity.Menu[]
activeMenu: string | null activeMenu: string | null
cacheRoutes: string[] cacheRoutes: string[]
} }
@ -40,9 +40,7 @@ export const useRouteStore = defineStore('route-store', {
if (import.meta.env.VITE_ROUTE_LOAD_MODE === 'dynamic') { if (import.meta.env.VITE_ROUTE_LOAD_MODE === 'dynamic') {
try { try {
// Get user's route // Get user's route
const { data } = await fetchUserRoutes({ const { data } = await fetchUserMenus()
id: 1,
})
if (!data) { if (!data) {
throw new Error('Failed to fetch user routes') throw new Error('Failed to fetch user routes')
} }

View File

@ -9,19 +9,19 @@ namespace Entity {
/** /**
* *
*/ */
component: string component?: string
/** /**
* *
*/ */
icon: string icon?: string
/** /**
* *
*/ */
keepAlive: boolean keepAlive?: boolean
/** /**
* *
*/ */
isLink: boolean isLink?: boolean
/** /**
* *
*/ */
@ -29,11 +29,11 @@ namespace Entity {
/** /**
* Key * Key
*/ */
i18nKey: string i18nKey?: string
/** /**
* *
*/ */
menuType: MenuType menuType?: MenuType
/** /**
* ID * ID
*/ */
@ -45,31 +45,35 @@ namespace Entity {
/** /**
* *
*/ */
activePath: string activePath?: string
/** /**
* *
*/ */
perms: string perms?: string
/** /**
* *
*/ */
remark: string remark?: string
/** /**
* *
*/ */
sort: number sort?: number
/** /**
* *
*/ */
status: number status?: number
/** /**
* *
*/ */
menuVisible: boolean menuVisible?: boolean
/** /**
* *
*/ */
tabVisible: boolean tabVisible?: boolean
/**
*
*/
pinTab?: boolean
/** /**
* *
*/ */

View File

@ -1,6 +1,6 @@
declare namespace AppRoute { declare namespace AppRoute {
type MenuType = 'dir' | 'page' type MenuType = 'directory' | 'page' | 'permission'
/** 单个路由所携带的meta标识 */ /** 单个路由所携带的meta标识 */
interface RouteMeta { interface RouteMeta {
/* 页面标题,通常必选。 */ /* 页面标题,通常必选。 */
@ -13,6 +13,22 @@ declare namespace AppRoute {
roles?: Entity.RoleType[] roles?: Entity.RoleType[]
/* 是否开启页面缓存 */ /* 是否开启页面缓存 */
keepAlive?: boolean keepAlive?: boolean
/* 菜单显示状态 - 适配新菜单实体 */
menuVisible?: boolean
/* 菜单排序 - 适配新菜单实体 */
sort?: number
/* 是否为外链 - 适配新菜单实体 */
isLink?: boolean
/* 高亮菜单路径 - 适配新菜单实体 */
activePath?: string
/* 标签栏显示状态 - 适配新菜单实体 */
tabVisible?: boolean
/** 当前路由是否会被固定在Tab中,用于一些常驻页面 */
pinTab?: boolean
/** 当前路由在左侧菜单是目录还是页面,不设置默认为page */
menuType?: MenuType
/* 以下字段保持向后兼容 */
/* 有些路由我们并不想在菜单中显示,比如某些编辑页面。 */ /* 有些路由我们并不想在菜单中显示,比如某些编辑页面。 */
hide?: boolean hide?: boolean
/* 菜单排序。 */ /* 菜单排序。 */
@ -23,10 +39,6 @@ declare namespace AppRoute {
activeMenu?: string activeMenu?: string
/** 当前路由是否会被添加到Tab中 */ /** 当前路由是否会被添加到Tab中 */
withoutTab?: boolean withoutTab?: boolean
/** 当前路由是否会被固定在Tab中,用于一些常驻页面 */
pinTab?: boolean
/** 当前路由在左侧菜单是目录还是页面,不设置默认为page */
menuType?: MenuType
} }
type MetaKeys = keyof RouteMeta type MetaKeys = keyof RouteMeta