82 lines
2.1 KiB
TypeScript
82 lines
2.1 KiB
TypeScript
import request from '@/utils/request'
|
||
import type { ApiResult } from '@/api/auth'
|
||
|
||
/**
|
||
* 路由菜单项 — 后端 /route/menu 接口返回的数据结构
|
||
*/
|
||
export interface RouteMenuVo {
|
||
/** 主键 */
|
||
id: string
|
||
/** 根节点ID */
|
||
rootId: string
|
||
/** 父级路由ID */
|
||
parentId: string
|
||
/** 路由名称(用于侧边栏显示) */
|
||
routeName: string
|
||
/** 前端路径 */
|
||
routePath: string
|
||
/** 前端组件路径(对应 componentMap 的 key) */
|
||
component: string
|
||
/** 图标 key */
|
||
icon: string
|
||
/** 排序 */
|
||
sortOrder: number
|
||
/** 是否有使用权限:true=可用 false=无权限(需会员) */
|
||
accessible: boolean
|
||
/** 递归子菜单 */
|
||
children?: RouteMenuVo[]
|
||
}
|
||
|
||
/**
|
||
* 兼容旧版 MenuItemRaw 类型(供 SideNav 和 store 使用)
|
||
* 在新接口基础上补充原有字段映射
|
||
*/
|
||
export interface MenuItemRaw {
|
||
path: string
|
||
name: string
|
||
component: string
|
||
meta?: {
|
||
label?: string
|
||
icon?: string
|
||
badge?: string
|
||
/** 'footer' 表示该菜单项显示在底部区域而非主导航 */
|
||
position?: string
|
||
}
|
||
/** 排序字段 */
|
||
sortOrder: number
|
||
/** 是否有使用权限 */
|
||
accessible: boolean
|
||
}
|
||
|
||
/**
|
||
* 将后端返回的 RouteMenuVo 转换为前端使用的 MenuItemRaw
|
||
*/
|
||
function mapRouteMenuToMenuItem(item: RouteMenuVo): MenuItemRaw {
|
||
return {
|
||
path: item.routePath,
|
||
name: item.component, // component 作为路由 name(与 componentMap 对应)
|
||
component: item.component,
|
||
meta: {
|
||
label: item.routeName,
|
||
icon: item.icon,
|
||
},
|
||
sortOrder: item.sortOrder,
|
||
accessible: item.accessible,
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取当前用户有权限的路由菜单列表
|
||
* GET /route/menu
|
||
* Cookie 自动携带 Token
|
||
*/
|
||
export async function fetchUserRoutes(): Promise<MenuItemRaw[]> {
|
||
const res = await request.get<any, ApiResult<RouteMenuVo[]>>('/route/menu')
|
||
if (res.code === '0' && res.data) {
|
||
// 按 sortOrder 排序后转换格式
|
||
const sorted = [...res.data].sort((a, b) => a.sortOrder - b.sortOrder)
|
||
return sorted.map(mapRouteMenuToMenuItem)
|
||
}
|
||
return []
|
||
}
|