Files
admin_core/demo-project/_doc/权限菜单说明.md
张成 b27c047930 1
2025-10-08 20:01:26 +08:00

7.9 KiB
Raw Blame History

权限菜单处理说明

📊 当前情况

登录接口返回的数据

{
    "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

  • 类型:对象数组
  • 内容:完整的菜单对象,包含以下字段:
    {
      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. 生成路由

代码实现:

// 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 数组。

修改后的返回数据:

{
    "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. 用户输入用户名密码

    // src/views/login/login.vue
    handleSubmit({ userName, password }) {
      let userFrom = { name: userName, password: password }
      this.handleLogin({ userFrom, Main, ParentView, Page404 })
    }
    
  2. 调用登录接口

    // src/store/user.js
    let res = await userServerInstance.login(userFrom)
    // 返回: { code: 0, data: { token, user, authorityMenus: "[1,2,3...]" } }
    
  3. 保存 token 和用户信息

    commit('setUserName', user.name.trim())
    commit('setToken', token)
    
  4. 获取完整菜单数据

    // 调用 /sys_user/authorityMenus 接口
    await dispatch('setAuthorityMenus', { Main, ParentView, Page404 })
    
  5. 处理菜单数据

    // 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. 刷新页面进入系统

    window.location.reload()
    

⚠️ 需要确认的事项

1. authorityMenus 接口返回的数据格式

请确认 /sys_user/authorityMenus 接口返回的数据格式:

期望格式:

{
    "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 父菜单 ID0 表示顶级菜单)
type String 类型:"菜单"、"页面"、"功能"
is_show_menu Number 是否显示在菜单中1=显示0=隐藏)
icon String 图标名称
sort Number 排序
children Array 子菜单

🐛 调试方法

1. 查看 authorityMenus 接口返回

在浏览器控制台查看:

// 登录成功后,查看控制台日志
获取权限菜单返回: { code: 0, data: [...] }
处理权限菜单: [...]
生成的主菜单: { path: '/', children: [...] }

2. 查看 localStorage

打开浏览器开发者工具 → Application → Local Storage

authorityMenus: "[{\"id\":1,\"name\":\"首页\",...}]"

3. 查看网络请求

打开浏览器开发者工具 → Network

  1. 查看 /sys_user/login 请求的响应
  2. 查看 /sys_user/authorityMenus 请求的响应

🎯 测试步骤

1. 测试登录

# 启动项目
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 请求,提升用户体验。

修改建议:

// 后端登录接口返回
{
    "code": 0,
    "message": "请求成功",
    "data": {
        "token": "...",
        "user": {...},
        "authorityMenus": [
            // 完整的菜单对象数组,而不是 ID 数组字符串
            { id: 1, name: "首页", path: "/home", ... },
            { id: 5, name: "系统管理", path: "/system", children: [...] }
        ]
    }
}

这样前端就可以直接使用,不需要额外的 HTTP 请求。


当前状态:登录功能正常,需要确认 authorityMenus 接口返回的数据格式是否正确。