1
This commit is contained in:
452
demo-project/移除硬编码首页说明.md
Normal file
452
demo-project/移除硬编码首页说明.md
Normal file
@@ -0,0 +1,452 @@
|
||||
# 移除硬编码首页说明
|
||||
|
||||
## 🎯 修改目标
|
||||
|
||||
移除代码中硬编码的首页路由,完全依赖后端接口返回的菜单配置(包括首页)。
|
||||
|
||||
## 📋 修改原因
|
||||
|
||||
### 之前的问题
|
||||
|
||||
**硬编码首页**:
|
||||
```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`
|
||||
- ⚠️ 组件文件必须存在
|
||||
|
||||
---
|
||||
|
||||
**硬编码首页已移除!** 🎉
|
||||
|
||||
现在首页完全由后端配置控制,代码更简洁、更灵活。
|
||||
|
||||
Reference in New Issue
Block a user