453 lines
9.9 KiB
Markdown
453 lines
9.9 KiB
Markdown
# 移除硬编码首页说明
|
||
|
||
## 🎯 修改目标
|
||
|
||
移除代码中硬编码的首页路由,完全依赖后端接口返回的菜单配置(包括首页)。
|
||
|
||
## 📋 修改原因
|
||
|
||
### 之前的问题
|
||
|
||
**硬编码首页**:
|
||
```javascript
|
||
// 在代码中创建默认首页
|
||
const defaultHomeRoute = {
|
||
path: '/home',
|
||
name: 'home',
|
||
meta: { title: '首页', notCache: true },
|
||
component: HomePage
|
||
}
|
||
```
|
||
|
||
**问题**:
|
||
- ❌ 首页配置写死在代码中
|
||
- ❌ 无法通过后端动态配置首页
|
||
- ❌ 首页和其他菜单的处理逻辑不一致
|
||
- ❌ 增加了代码复杂度
|
||
|
||
### 新的设计
|
||
|
||
**完全依赖后端**:
|
||
- ✅ 首页配置由后端返回
|
||
- ✅ 首页和其他菜单统一处理
|
||
- ✅ 代码更简洁
|
||
- ✅ 配置更灵活
|
||
|
||
## 📝 修改内容
|
||
|
||
### 1. 修改 `src/utils/uiTool.js` 的 `getRoutes` 方法
|
||
|
||
**修改前**:
|
||
```javascript
|
||
static getRoutes(Main, ParentView, Page404, HomePage) {
|
||
// 创建默认的首页路由
|
||
const defaultHomeRoute = {
|
||
path: '/home',
|
||
name: 'home',
|
||
meta: { title: '首页', notCache: true },
|
||
component: HomePage || {
|
||
render: h => h('div', { style: { padding: '20px' } }, '欢迎使用管理系统')
|
||
}
|
||
}
|
||
|
||
let mainRoute = {
|
||
path: '/',
|
||
name: '主视图',
|
||
redirect: '/home',
|
||
component: Main,
|
||
meta: { title: '首页', notCache: true },
|
||
children: [defaultHomeRoute] // ❌ 硬编码首页
|
||
}
|
||
|
||
// 从 localStorage 读取权限菜单
|
||
if (localStorage.authorityMenus && localStorage.authorityMenus !== 'undefined') {
|
||
let authorityMenus = JSON.parse(localStorage.authorityMenus) || []
|
||
|
||
if (authorityMenus && authorityMenus.length > 0) {
|
||
let menus = uiTool.transformTree(authorityMenus)
|
||
let curRoutes = uiTool.menuToRoute(menus, ParentView, Page404)
|
||
|
||
// 检查权限路由中是否有 home
|
||
const hasHome = curRoutes.some(r => r.name === 'home')
|
||
|
||
if (hasHome) {
|
||
mainRoute.children = curRoutes
|
||
} else {
|
||
mainRoute.children = [defaultHomeRoute, ...curRoutes] // ❌ 复杂的合并逻辑
|
||
}
|
||
}
|
||
}
|
||
|
||
return mainRoute
|
||
}
|
||
```
|
||
|
||
**修改后**:
|
||
```javascript
|
||
static getRoutes(Main, ParentView, Page404) {
|
||
let mainRoute = {
|
||
path: '/',
|
||
name: '主视图',
|
||
redirect: '/home',
|
||
component: Main,
|
||
meta: { title: '首页', notCache: true },
|
||
children: [] // ✅ 初始为空
|
||
}
|
||
|
||
// 从 localStorage 读取权限菜单
|
||
if (localStorage.authorityMenus && localStorage.authorityMenus !== 'undefined') {
|
||
let authorityMenus = JSON.parse(localStorage.authorityMenus) || []
|
||
|
||
if (authorityMenus && authorityMenus.length > 0) {
|
||
let menus = uiTool.transformTree(authorityMenus)
|
||
let curRoutes = uiTool.menuToRoute(menus, ParentView, Page404)
|
||
|
||
// ✅ 直接使用后端返回的路由(包括首页)
|
||
mainRoute.children = curRoutes
|
||
}
|
||
}
|
||
|
||
return mainRoute
|
||
}
|
||
```
|
||
|
||
**改进点**:
|
||
- ✅ 移除了 `HomePage` 参数
|
||
- ✅ 移除了 `defaultHomeRoute` 的创建
|
||
- ✅ 移除了复杂的首页合并逻辑
|
||
- ✅ 代码更简洁,逻辑更清晰
|
||
|
||
### 2. 更新 `src/index.js` 中的调用
|
||
|
||
**修改前**:
|
||
```javascript
|
||
// 获取主路由配置(包含 home)
|
||
const mainRoute = this.getRoutes({ Main, ParentView, Page404, HomePage })
|
||
|
||
// getRoutes 方法
|
||
getRoutes(components = {}) {
|
||
const { Main, ParentView, Page404, HomePage } = components
|
||
|
||
if (!Main || !ParentView || !Page404) {
|
||
console.error('Missing required layout components')
|
||
return null
|
||
}
|
||
|
||
return uiTool.getRoutes(Main, ParentView, Page404, HomePage)
|
||
}
|
||
```
|
||
|
||
**修改后**:
|
||
```javascript
|
||
// 获取主路由配置(从后端权限菜单生成)
|
||
const mainRoute = this.getRoutes({ Main, ParentView, Page404 })
|
||
|
||
// getRoutes 方法
|
||
getRoutes(components = {}) {
|
||
const { Main, ParentView, Page404 } = components
|
||
|
||
if (!Main || !ParentView || !Page404) {
|
||
console.error('Missing required layout components')
|
||
return null
|
||
}
|
||
|
||
return uiTool.getRoutes(Main, ParentView, Page404)
|
||
}
|
||
```
|
||
|
||
**改进点**:
|
||
- ✅ 移除了 `HomePage` 参数
|
||
- ✅ 注释更准确
|
||
|
||
### 3. 确保默认菜单配置包含首页
|
||
|
||
**`src/config/menuConfig.js`**:
|
||
```javascript
|
||
export const defaultMenus = [
|
||
{
|
||
id: 1,
|
||
name: '首页',
|
||
path: '/home',
|
||
component: 'home/index',
|
||
parent_id: 0,
|
||
type: '页面',
|
||
is_show_menu: 1,
|
||
icon: 'md-home',
|
||
sort: 1
|
||
},
|
||
// ... 其他菜单
|
||
]
|
||
```
|
||
|
||
**说明**:
|
||
- ✅ 默认菜单配置中包含首页(id: 1)
|
||
- ✅ 当 `authorityMenus` 接口失败时,会使用这个默认配置
|
||
- ✅ 确保即使接口失败,也能显示首页
|
||
|
||
## 📊 新的路由生成流程
|
||
|
||
### 应用启动时
|
||
|
||
```
|
||
应用启动
|
||
↓
|
||
框架初始化
|
||
↓
|
||
调用 getRoutes
|
||
↓
|
||
从 localStorage 读取 authorityMenus
|
||
↓
|
||
authorityMenus 存在?
|
||
├─ 是 → 解析菜单数据
|
||
│ ↓
|
||
│ transformTree (构建树形结构)
|
||
│ ↓
|
||
│ menuToRoute (转换为路由配置)
|
||
│ ↓
|
||
│ 生成路由(包括首页)✅
|
||
│
|
||
└─ 否 → children = [] (空路由)
|
||
↓
|
||
显示登录页面
|
||
```
|
||
|
||
### 登录后
|
||
|
||
```
|
||
用户登录
|
||
↓
|
||
调用登录接口
|
||
↓
|
||
保存 token 和用户信息
|
||
↓
|
||
调用 setAuthorityMenus
|
||
├─ 尝试调用 authorityMenus 接口
|
||
│ ├─ 成功 → 使用后端返回的菜单(包括首页)
|
||
│ └─ 失败 → 使用默认菜单配置(包括首页)
|
||
↓
|
||
保存到 localStorage
|
||
↓
|
||
刷新页面
|
||
↓
|
||
重新执行应用启动流程
|
||
↓
|
||
从 localStorage 读取菜单
|
||
↓
|
||
生成路由(包括首页)✅
|
||
```
|
||
|
||
## 🎯 后端接口要求
|
||
|
||
### authorityMenus 接口返回格式
|
||
|
||
**必须包含首页配置**:
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"message": "请求成功",
|
||
"data": [
|
||
{
|
||
"id": 1,
|
||
"name": "首页",
|
||
"path": "/home",
|
||
"component": "home/index",
|
||
"parent_id": 0,
|
||
"type": "页面",
|
||
"is_show_menu": 1,
|
||
"icon": "md-home",
|
||
"sort": 1
|
||
},
|
||
{
|
||
"id": 5,
|
||
"name": "系统管理",
|
||
"path": "/system",
|
||
"component": "",
|
||
"parent_id": 0,
|
||
"type": "菜单",
|
||
"is_show_menu": 1,
|
||
"icon": "md-settings",
|
||
"sort": 2,
|
||
"children": [
|
||
{
|
||
"id": 11,
|
||
"name": "用户管理",
|
||
"path": "/system/user",
|
||
"component": "system/sys_user",
|
||
"parent_id": 5,
|
||
"type": "页面",
|
||
"is_show_menu": 1
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### 首页配置说明
|
||
|
||
**必需字段**:
|
||
- `id`: 菜单 ID(建议使用 1)
|
||
- `name`: 菜单名称(如 "首页")
|
||
- `path`: 路由路径(必须是 `/home`)
|
||
- `component`: 组件路径(如 `home/index`)
|
||
- `parent_id`: 父菜单 ID(0 表示顶级菜单)
|
||
- `type`: 类型("页面")
|
||
- `is_show_menu`: 是否显示在菜单中(1=显示,0=隐藏)
|
||
|
||
**可选字段**:
|
||
- `icon`: 图标名称(如 `md-home`)
|
||
- `sort`: 排序(建议设为 1,让首页排在第一位)
|
||
|
||
## ✅ 优势
|
||
|
||
### 1. 代码更简洁
|
||
|
||
**代码行数减少**:
|
||
- 移除了 `defaultHomeRoute` 的创建
|
||
- 移除了首页合并逻辑
|
||
- 移除了 `HomePage` 参数传递
|
||
|
||
**复杂度降低**:
|
||
- 不需要判断是否有首页
|
||
- 不需要合并首页和其他路由
|
||
- 逻辑更直观
|
||
|
||
### 2. 配置更灵活
|
||
|
||
**后端控制**:
|
||
- ✅ 首页路径可以动态配置
|
||
- ✅ 首页组件可以动态指定
|
||
- ✅ 首页标题可以动态设置
|
||
- ✅ 首页图标可以动态配置
|
||
|
||
**统一管理**:
|
||
- ✅ 所有菜单(包括首页)都由后端管理
|
||
- ✅ 权限控制统一
|
||
- ✅ 配置方式统一
|
||
|
||
### 3. 维护更容易
|
||
|
||
**单一数据源**:
|
||
- ✅ 菜单配置只来自后端
|
||
- ✅ 不需要维护前端的默认首页
|
||
- ✅ 修改首页只需要修改后端配置
|
||
|
||
**降级方案**:
|
||
- ✅ 如果 `authorityMenus` 接口失败
|
||
- ✅ 使用 `defaultMenus` 配置(包含首页)
|
||
- ✅ 确保系统可用
|
||
|
||
## ⚠️ 注意事项
|
||
|
||
### 1. 后端必须返回首页配置
|
||
|
||
如果后端返回的菜单数据中没有首页,用户登录后会看不到首页。
|
||
|
||
**解决方案**:
|
||
- 确保后端 `authorityMenus` 接口返回包含首页的菜单数据
|
||
- 或者在 `defaultMenus` 中包含首页作为兜底
|
||
|
||
### 2. 首页路径必须是 `/home`
|
||
|
||
因为主路由的 `redirect` 设置为 `/home`:
|
||
```javascript
|
||
let mainRoute = {
|
||
path: '/',
|
||
redirect: '/home', // ← 重定向到 /home
|
||
// ...
|
||
}
|
||
```
|
||
|
||
**要求**:
|
||
- 后端返回的首页配置中,`path` 必须是 `/home`
|
||
- 或者修改主路由的 `redirect` 配置
|
||
|
||
### 3. 组件路径映射
|
||
|
||
后端返回的 `component` 字段(如 `home/index`)会被映射到:
|
||
```
|
||
src/views/home/index.vue
|
||
```
|
||
|
||
**要求**:
|
||
- 确保组件文件存在
|
||
- 组件路径正确
|
||
|
||
## 🧪 测试验证
|
||
|
||
### 测试场景 1:正常登录
|
||
|
||
```
|
||
1. 启动项目
|
||
2. 访问登录页面
|
||
3. 输入用户名密码
|
||
4. 点击登录
|
||
5. 登录成功
|
||
6. 页面刷新
|
||
7. 进入系统首页 ✅
|
||
```
|
||
|
||
**验证点**:
|
||
- ✅ 首页正确显示
|
||
- ✅ 首页路由是 `/home`
|
||
- ✅ 首页组件正确加载
|
||
|
||
### 测试场景 2:authorityMenus 接口失败
|
||
|
||
```
|
||
1. 启动项目
|
||
2. 登录(authorityMenus 接口失败)
|
||
3. 使用默认菜单配置
|
||
4. 页面刷新
|
||
5. 进入系统首页 ✅
|
||
```
|
||
|
||
**验证点**:
|
||
- ✅ 使用默认菜单配置
|
||
- ✅ 首页正确显示
|
||
- ✅ 控制台有警告信息
|
||
|
||
### 测试场景 3:刷新页面
|
||
|
||
```
|
||
1. 已登录状态
|
||
2. 刷新页面
|
||
3. 从 localStorage 读取菜单
|
||
4. 重新生成路由
|
||
5. 首页正确显示 ✅
|
||
```
|
||
|
||
**验证点**:
|
||
- ✅ 首页路由正确
|
||
- ✅ 菜单正确显示
|
||
- ✅ 用户状态保持
|
||
|
||
## 📝 总结
|
||
|
||
### 修改内容
|
||
|
||
- ✅ 移除了硬编码的首页路由
|
||
- ✅ 移除了 `HomePage` 参数
|
||
- ✅ 简化了路由生成逻辑
|
||
- ✅ 统一了菜单处理方式
|
||
|
||
### 优势
|
||
|
||
- ✅ 代码更简洁(减少约 20 行代码)
|
||
- ✅ 逻辑更清晰
|
||
- ✅ 配置更灵活
|
||
- ✅ 维护更容易
|
||
|
||
### 要求
|
||
|
||
- ⚠️ 后端必须返回首页配置
|
||
- ⚠️ 首页路径必须是 `/home`
|
||
- ⚠️ 组件文件必须存在
|
||
|
||
---
|
||
|
||
**硬编码首页已移除!** 🎉
|
||
|
||
现在首页完全由后端配置控制,代码更简洁、更灵活。
|
||
|