OL-LearnPlatform-Frontend/docs/dynamic-menu-routes.md

198 lines
4.3 KiB
Markdown
Raw Normal View History

# 动态菜单路由系统
## 概述
本系统实现了基于后端接口的动态菜单路由加载功能,支持从后端获取菜单配置并自动生成前端路由。
## 接口说明
### 获取首页菜单
- **接口**: `/aiol/aiolMenu/getIndexMenus`
- **方法**: GET
- **返回格式**:
```json
{
"success": true,
"message": "",
"code": 200,
"result": [
{
"id": "1",
"name": "首页",
"path": "/",
"type": "index",
"icon": null,
"parentId": null,
"sortOrder": 99,
"izVisible": 1,
"permissionKey": null
}
],
"timestamp": 1759134778382
}
```
### 获取学生菜单
- **接口**: `/aiol/aiolMenu/getStudentMenus`
- **方法**: GET
- **返回格式**: 同上type为"student"
## 核心文件
### 1. API模块 (`src/api/modules/menu.ts`)
```typescript
export interface MenuItem {
id: string
name: string
path: string
type: string
icon: string | null
parentId: string | null
sortOrder: number
izVisible: number
permissionKey: string | null
}
export class MenuApi {
static async getIndexMenus(): Promise<ApiResponse<MenuItem[]>>
static async getStudentMenus(): Promise<ApiResponse<MenuItem[]>>
}
```
### 2. 路由工具 (`src/utils/routeUtils.ts`)
```typescript
// 根据菜单数据生成路由配置
export function generateRoutesFromMenus(menus: MenuItem[]): RouteRecordRaw[]
// 生成导航菜单数据
export function generateNavMenus(menus: MenuItem[])
// 检查路由是否存在于菜单中
export function isRouteInMenus(path: string, menus: MenuItem[]): boolean
```
### 3. 状态管理 (`src/stores/menu.ts`)
```typescript
export const useMenuStore = defineStore('menu', () => {
// 状态
const indexMenus = ref<MenuItem[]>([])
const studentMenus = ref<MenuItem[]>([])
const loading = ref(false)
const error = ref<string | null>(null)
// 计算属性
const navMenus = computed(() => generateNavMenus(indexMenus.value))
const visibleIndexMenus = computed(() => ...)
// 方法
const fetchIndexMenus = async () => { ... }
const fetchStudentMenus = async () => { ... }
})
```
### 4. 路由配置 (`src/router/index.ts`)
在路由守卫中自动加载动态菜单:
```typescript
router.beforeEach(async (to, from, next) => {
// 加载动态菜单路由(仅在首次访问时)
if (!isMenuLoaded) {
await loadMenuRoutes()
}
// ...
})
```
## 使用方法
### 1. 在组件中使用菜单状态
```vue
<script setup lang="ts">
import { useMenuStore } from '@/stores/menu'
const menuStore = useMenuStore()
// 获取菜单数据
await menuStore.fetchIndexMenus()
// 使用菜单数据
console.log(menuStore.navMenus)
</script>
```
### 2. 使用动态导航组件
```vue
<template>
<DynamicNavigation />
</template>
<script setup lang="ts">
import DynamicNavigation from '@/components/layout/DynamicNavigation.vue'
</script>
```
### 3. 检查路由权限
```typescript
import { useMenuStore } from '@/stores/menu'
const menuStore = useMenuStore()
// 检查路由是否可见
const isVisible = menuStore.isRouteVisible('/courses', 'index')
```
## 路径映射
当前支持的路径映射:
| 菜单名称 | 路径 | 组件 |
|---------|------|------|
| 首页 | / | Home |
| 热门好课 | /courses | Courses |
| 专题训练 | /special-training | SpecialTraining |
| 师资力量 | /faculty | Faculty |
| 精选资源 | /resources | Resources |
| 活动 | /activities | Activities |
| AI体验 | /ai/app | AiAppList |
## 测试页面
访问 `/menu-test` 可以查看动态菜单系统的测试页面,包含:
- 菜单状态监控
- 菜单数据展示
- 路由跳转测试
- 动态导航组件演示
## 响应式设计
动态导航组件支持响应式设计:
- 桌面端:垂直菜单布局
- 移动端:水平滚动菜单布局
## 错误处理
系统包含完整的错误处理机制:
- 网络请求失败重试
- 加载状态显示
- 错误信息提示
- 手动重试功能
## 扩展说明
### 添加新的路径映射
`src/utils/routeUtils.ts` 中的 `componentMap` 添加新的路径映射:
```typescript
const componentMap: Record<string, () => Promise<any>> = {
'/new-path': () => import('@/views/NewComponent.vue'),
// ...
}
```
### 自定义菜单图标
`DynamicNavigation.vue` 中的 `iconMap` 添加新的图标映射:
```typescript
const iconMap: Record<string, any> = {
'new-icon': NewIconComponent,
// ...
}
```