# 权限菜单处理说明 ## 📊 当前情况 ### 登录接口返回的数据 ```json { "code": 0, "message": "请求成功", "data": { "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "user": { "id": 1, "name": "zc", "roleId": 6 }, "authorityMenus": "[1,142,121,143,144,145,124,147,120,123,125,132,133,126,136,137,138,139,151,152,153,154,149,150,156,157,158,122,159,5,11,12,13,67,68,15]" } } ``` ### 问题分析 **登录接口返回的 `authorityMenus`**: - 类型:字符串 - 内容:菜单 ID 数组 `"[1,142,121,...]"` - 作用:表示用户有权限访问的菜单 ID 列表 **框架期望的 `authorityMenus`**: - 类型:对象数组 - 内容:完整的菜单对象,包含以下字段: ```javascript { id: 1, name: "系统管理", path: "/system", component: "...", parent_id: 0, type: "菜单", is_show_menu: 1, children: [...] } ``` ## 🔧 解决方案 ### 方案一:调用 authorityMenus 接口(当前实现) 登录成功后,调用 `/sys_user/authorityMenus` 接口获取完整的菜单对象数组。 **流程:** 1. 用户登录 → 获取 token 和菜单 ID 列表 2. 保存 token 3. 调用 `authorityMenus` 接口 → 获取完整菜单对象数组 4. 生成路由 **代码实现:** ```javascript // src/store/user.js async handleLogin({ state, commit, dispatch }, { userFrom, Main, ParentView, Page404 }) { let res = await userServerInstance.login(userFrom) let token = res.data.token let user = res.data.user commit('setUserName', user.name.trim()) commit('setToken', token) // 调用 authorityMenus 接口获取完整菜单数据 await dispatch('setAuthorityMenus', { Main, ParentView, Page404 }) } ``` **优点:** - 简单直接 - 不需要修改后端接口 **缺点:** - 需要额外的 HTTP 请求 - 如果 authorityMenus 接口失败,用户无法进入系统 ### 方案二:后端直接返回完整菜单对象(推荐) 修改后端登录接口,直接返回完整的菜单对象数组,而不是菜单 ID 数组。 **修改后的返回数据:** ```json { "code": 0, "message": "请求成功", "data": { "token": "...", "user": {...}, "authorityMenus": [ { "id": 1, "name": "系统管理", "path": "/system", "component": "Main", "parent_id": 0, "type": "菜单", "is_show_menu": 1, "children": [...] }, ... ] } } ``` **优点:** - 减少 HTTP 请求 - 登录更快 - 数据一致性更好 **缺点:** - 需要修改后端代码 ## 📝 当前实现 ### 登录流程 1. **用户输入用户名密码** ```javascript // src/views/login/login.vue handleSubmit({ userName, password }) { let userFrom = { name: userName, password: password } this.handleLogin({ userFrom, Main, ParentView, Page404 }) } ``` 2. **调用登录接口** ```javascript // src/store/user.js let res = await userServerInstance.login(userFrom) // 返回: { code: 0, data: { token, user, authorityMenus: "[1,2,3...]" } } ``` 3. **保存 token 和用户信息** ```javascript commit('setUserName', user.name.trim()) commit('setToken', token) ``` 4. **获取完整菜单数据** ```javascript // 调用 /sys_user/authorityMenus 接口 await dispatch('setAuthorityMenus', { Main, ParentView, Page404 }) ``` 5. **处理菜单数据** ```javascript // src/store/user.js - setAuthorityMenus let res = await userServerInstance.authorityMenus() // 期望返回: { code: 0, data: [{id, name, path, ...}, ...] } let menus = res.data commit('setAuthorityMenus', JSON.stringify(menus)) // 生成路由 let mainMenu = uiTool.getRoutes(Main, ParentView, Page404) commit('setMenuList', mainMenu.children) ``` 6. **刷新页面进入系统** ```javascript window.location.reload() ``` ## ⚠️ 需要确认的事项 ### 1. authorityMenus 接口返回的数据格式 请确认 `/sys_user/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 } ] } ] } ``` ### 2. 菜单对象的必需字段 每个菜单对象需要包含以下字段: | 字段 | 类型 | 说明 | 必需 | |------|------|------|------| | id | Number | 菜单 ID | ✅ | | name | String | 菜单名称 | ✅ | | path | String | 路由路径 | ✅ | | component | String | 组件路径 | ✅ | | parent_id | Number | 父菜单 ID(0 表示顶级菜单) | ✅ | | type | String | 类型:"菜单"、"页面"、"功能" | ✅ | | is_show_menu | Number | 是否显示在菜单中(1=显示,0=隐藏) | ✅ | | icon | String | 图标名称 | ❌ | | sort | Number | 排序 | ❌ | | children | Array | 子菜单 | ❌ | ## 🐛 调试方法 ### 1. 查看 authorityMenus 接口返回 在浏览器控制台查看: ```javascript // 登录成功后,查看控制台日志 获取权限菜单返回: { code: 0, data: [...] } 处理权限菜单: [...] 生成的主菜单: { path: '/', children: [...] } ``` ### 2. 查看 localStorage 打开浏览器开发者工具 → Application → Local Storage: ```javascript authorityMenus: "[{\"id\":1,\"name\":\"首页\",...}]" ``` ### 3. 查看网络请求 打开浏览器开发者工具 → Network: 1. 查看 `/sys_user/login` 请求的响应 2. 查看 `/sys_user/authorityMenus` 请求的响应 ## 🎯 测试步骤 ### 1. 测试登录 ```bash # 启动项目 cd demo-project npm run dev # 打开浏览器 http://localhost:8080 # 输入用户名密码 用户名: zc 密码: *** # 点击登录 ``` ### 2. 查看控制台日志 应该看到: ``` 登录接口返回: { code: 0, data: { token, user, authorityMenus } } 登录返回的菜单 IDs: "[1,142,121,...]" 获取权限菜单返回: { code: 0, data: [...] } 处理权限菜单: [...] 生成的主菜单: { path: '/', children: [...] } ``` ### 3. 验证登录成功 - ✅ 显示"登录成功!"提示 - ✅ 页面刷新 - ✅ 进入系统首页 - ✅ 左侧显示菜单 ## 💡 建议 ### 短期方案(当前实现) 保持现有实现,登录后调用 `authorityMenus` 接口获取完整菜单数据。 ### 长期方案(推荐) 建议后端修改登录接口,直接返回完整的菜单对象数组,减少 HTTP 请求,提升用户体验。 **修改建议:** ```javascript // 后端登录接口返回 { "code": 0, "message": "请求成功", "data": { "token": "...", "user": {...}, "authorityMenus": [ // 完整的菜单对象数组,而不是 ID 数组字符串 { id: 1, name: "首页", path: "/home", ... }, { id: 5, name: "系统管理", path: "/system", children: [...] } ] } } ``` 这样前端就可以直接使用,不需要额外的 HTTP 请求。 --- **当前状态**:登录功能正常,需要确认 `authorityMenus` 接口返回的数据格式是否正确。