feat: add menu type

This commit is contained in:
chansee97 2024-04-05 14:46:54 +08:00
parent ec28d4e53d
commit 446d67e6d8
8 changed files with 33 additions and 36 deletions

2
.env
View File

@ -5,7 +5,7 @@ VITE_APP_NAME=Nova - Admin
# 路由模式
VITE_ROUTE_MODE = web
# 权限路由模式: static dynamic
VITE_AUTH_ROUTE_MODE=static
VITE_AUTH_ROUTE_MODE=dynamic
# 设置登陆后跳转地址
VITE_HOME_PATH = /dashboard/workbench

View File

@ -5,6 +5,7 @@ export const staticRoutes: AppRoute.RowRoute[] = [
'meta.title': '仪表盘',
'meta.requiresAuth': true,
'meta.icon': 'icon-park-outline:analysis',
'meta.menuType': 'dir',
'componentPath': null,
'id': 1,
'pid': null,
@ -16,6 +17,7 @@ export const staticRoutes: AppRoute.RowRoute[] = [
'meta.requiresAuth': true,
'meta.icon': 'icon-park-outline:alarm',
'meta.pinTab': true,
'meta.menuType': 'page',
'componentPath': '/dashboard/workbench/index.vue',
'id': 2,
'pid': 1,
@ -26,6 +28,7 @@ export const staticRoutes: AppRoute.RowRoute[] = [
'meta.title': '监控页',
'meta.requiresAuth': true,
'meta.icon': 'icon-park-outline:anchor',
'meta.menuType': 'page',
'componentPath': '/dashboard/monitor/index.vue',
'id': 3,
'pid': 1,
@ -36,6 +39,7 @@ export const staticRoutes: AppRoute.RowRoute[] = [
'meta.title': '多级菜单演示',
'meta.requiresAuth': true,
'meta.icon': 'icon-park-outline:list',
'meta.menuType': 'dir',
'componentPath': null,
'id': 4,
'pid': null,
@ -46,6 +50,7 @@ export const staticRoutes: AppRoute.RowRoute[] = [
'meta.title': '多级菜单子页',
'meta.requiresAuth': true,
'meta.icon': 'icon-park-outline:list',
'meta.menuType': 'page',
'componentPath': '/test/test2/index.vue',
'id': 6,
'pid': 4,
@ -58,6 +63,7 @@ export const staticRoutes: AppRoute.RowRoute[] = [
'meta.icon': 'icon-park-outline:list',
'meta.hide': true,
'meta.activeMenu': '/test/test2',
'meta.menuType': 'page',
'componentPath': '/test/test2/detail/index.vue',
'id': 7,
'pid': 4,
@ -68,6 +74,7 @@ export const staticRoutes: AppRoute.RowRoute[] = [
'meta.title': '多级菜单',
'meta.requiresAuth': true,
'meta.icon': 'icon-park-outline:list',
'meta.menuType': 'dir',
'componentPath': null,
'id': 8,
'pid': 4,
@ -88,6 +95,7 @@ export const staticRoutes: AppRoute.RowRoute[] = [
'meta.title': '列表页',
'meta.requiresAuth': true,
'meta.icon': 'icon-park-outline:list-two',
'meta.menuType': 'dir',
'componentPath': null,
'id': 10,
'pid': null,
@ -118,6 +126,7 @@ export const staticRoutes: AppRoute.RowRoute[] = [
'meta.title': '功能示例',
'meta.requiresAuth': true,
'meta.icon': 'icon-park-outline:application-one',
'meta.menuType': 'dir',
'componentPath': null,
'id': 13,
'pid': null,
@ -159,6 +168,7 @@ export const staticRoutes: AppRoute.RowRoute[] = [
'meta.title': '编辑器',
'meta.requiresAuth': true,
'meta.icon': 'icon-park-outline:editor',
'meta.menuType': 'dir',
'componentPath': null,
'id': 18,
'pid': 13,
@ -219,6 +229,7 @@ export const staticRoutes: AppRoute.RowRoute[] = [
'meta.title': '外链文档',
'meta.requiresAuth': true,
'meta.icon': 'icon-park-outline:file-doc',
'meta.menuType': 'dir',
'componentPath': null,
'id': 24,
'pid': null,
@ -260,6 +271,7 @@ export const staticRoutes: AppRoute.RowRoute[] = [
'meta.title': '权限',
'meta.requiresAuth': true,
'meta.icon': 'icon-park-outline:people-safe',
'meta.menuType': 'dir',
'componentPath': null,
'id': 28,
'pid': null,
@ -293,6 +305,7 @@ export const staticRoutes: AppRoute.RowRoute[] = [
'meta.title': '异常页',
'meta.requiresAuth': true,
'meta.icon': 'icon-park-outline:error-computer',
'meta.menuType': 'dir',
'componentPath': null,
'id': 31,
'pid': null,
@ -336,6 +349,7 @@ export const staticRoutes: AppRoute.RowRoute[] = [
'meta.title': '系统设置',
'meta.requiresAuth': true,
'meta.icon': 'icon-park-outline:setting',
'meta.menuType': 'dir',
'componentPath': null,
'id': 35,
'pid': null,

View File

@ -1,7 +1,7 @@
import { request } from '../http'
interface Ilogin {
username: string
userName: string
password: string
}

View File

@ -52,8 +52,8 @@ export const useAuthStore = defineStore('auth-store', {
},
/* 用户登录 */
async login(username: string, password: string) {
const { isSuccess, data } = await fetchLogin({ username, password })
async login(userName: string, password: string) {
const { isSuccess, data } = await fetchLogin({ userName, password })
if (!isSuccess) {
window.$message.error('登录失败,请检查用户名和密码')
return

View File

@ -72,7 +72,7 @@ export const useRouteStore = defineStore('route-store', {
id: item.id,
pid: item.pid,
label:
(!item.children || item.children.length === 0)
(!item.meta.menuType || item.meta.menuType === 'page')
? () =>
h(
RouterLink,
@ -83,36 +83,13 @@ export const useRouteStore = defineStore('route-store', {
},
{ default: () => $t(`route.${String(item.name)}`, item.meta.title) },
)
: $t(`route.${String(item.name)}`, item.meta.title),
: () => $t(`route.${String(item.name)}`, item.meta.title),
key: item.path,
icon: item.meta.icon ? renderIcon(item.meta.icon) : undefined,
}
return target
})
},
setRedirect(routes: AppRoute.Route[]) {
routes.forEach((route) => {
if (route.children) {
if (!route.redirect) {
// 过滤出没有隐藏的子元素集
const visibleChilds = route.children.filter(child => !child.meta.hide)
// 过滤出含有order属性的页面
const orderChilds = visibleChilds.filter(child => child.meta.order)
// 重定向页默认第一个子元素的路径
let target = route.children[0]
if (orderChilds.length > 0)
// 有order则取最小者重定向
target = min(orderChilds, i => i.meta.order as number) as AppRoute.Route
route.redirect = target.path
}
this.setRedirect(route.children)
}
})
},
createRoutes(routes: AppRoute.RowRoute[]) {
const { hasPermission } = usePermission()
// 结构化meta字段
@ -128,14 +105,19 @@ export const useRouteStore = defineStore('route-store', {
// 生成路由有redirect的不需要引入文件
const modules = import.meta.glob('@/views/**/*.vue')
resultRouter = resultRouter.map((item: any) => {
resultRouter = resultRouter.map((item: AppRoute.Route) => {
if (item.componentPath && !item.redirect)
item.component = modules[`/src/views${item.componentPath}`]
// 判断是否是目录,代表目录的路由没有实际页面
if (item.meta.menuType === 'dir')
item.redirect = '/404'
return item
})
// 生成路由表
resultRouter = arrayToTree(resultRouter) as AppRoute.Route[]
this.setRedirect(resultRouter)
const appRootRoute: RouteRecordRaw = {
path: '/appRoot',
name: 'appRoot',

View File

@ -7,7 +7,7 @@ declare namespace ApiAuth {
/** 用户id */
id: number
/** 用户名 */
username: string
userName: string
/* 用户头像 */
avatar?: string
/* 用户邮箱 */

View File

@ -23,10 +23,10 @@ declare namespace AppRoute {
withoutTab?: boolean
/** 当前路由是否会被固定在Tab中,用于一些常驻页面 */
pinTab?: boolean
/** 当前路由i18n标识 */
i18nKey?: string
/** 当前路由在左侧菜单是目录还是页面,不设置默认为page */
menuType?: 'dir' | 'page'
}
/** 单个路由的类型结构(动态路由模式:后端返回此类型结构的路由) */
interface baseRoute {
/** 路由名称(路由唯一标识) */
name: string
@ -42,6 +42,7 @@ declare namespace AppRoute {
pid: number | null
}
/** 单个路由的类型结构(动态路由模式:后端返回此类型结构的路由) */
type RowRoute = {
[K in keyof RouteMeta as `meta.${K}`]?: RouteMeta[K]
} & baseRoute

View File

@ -52,7 +52,7 @@ function handleValidateClick() {
{{ userInfo?.id }}
</n-descriptions-item>
<n-descriptions-item label="用户名">
{{ userInfo?.username }}
{{ userInfo?.userName }}
</n-descriptions-item>
<n-descriptions-item label="真实名称">
{{ userInfo?.nickname }}