coder-common-thin-frontend/doc/api/permission/菜单管理API.md
Leo d09a400ad0 feat(user-management): 实现用户管理导入导出功能
- 新增用户数据导出功能:
  * 支持导出当前查询条件下的数据
  * 支持导出全部用户数据
  * 支持下载用户导入模板
  * 自动生成带时间戳的文件名

- 新增用户数据导入功能:
  * 拖拽上传Excel文件支持
  * 文件类型和大小验证(.xlsx/.xls, 最大10MB)
  * 覆盖已存在数据选项
  * 实时上传进度显示
  * 详细的导入结果反馈

- 完善API接口:
  * downloadExcelTemplate: 下载Excel模板
  * exportExcelData: 导出用户数据(支持查询参数)
  * importUserData: 导入用户数据(支持覆盖选项)

- UI/UX优化:
  * 下拉菜单式导出按钮设计
  * 专业的导入模态框界面
  * 完善的错误处理和用户反馈
  * 导入说明和操作指导

技术实现:
- 使用Blob处理文件下载
- FormData处理文件上传
- Naive UI组件深度集成
- TypeScript类型安全保障
2025-07-06 00:58:26 +08:00

30 KiB
Raw Blame History

菜单管理API

概述

菜单管理模块是权限系统的核心组成部分,负责管理系统菜单、权限配置和路由生成。支持无限级菜单嵌套,提供目录、菜单、按钮三种类型的权限控制。

权限说明

菜单管理接口需要相应的权限才能访问:

操作 权限码 说明
查询菜单列表 system:menu:list 查看菜单列表权限
新增菜单 system:menu:add 新增菜单权限
修改菜单 system:menu:edit 修改菜单信息权限
删除菜单 system:menu:remove 删除菜单权限
分配权限 system:menu:assign 分配菜单权限

菜单类型说明

类型 说明 用途
目录 1 菜单目录 用于菜单分组,不对应具体页面
菜单 2 菜单项 对应具体的页面路由
按钮 3 按钮权限 用于控制页面内的按钮显示

接口列表

1. 分页查询菜单列表

接口地址: GET /coder/sysMenu/listPage

接口描述: 分页查询系统菜单列表

是否需要认证: 是

权限要求: system:menu:list

请求头:

Authorization: your-token-value

请求参数:

参数名 类型 必填 说明 示例
pageNo Integer 页码 1
pageSize Integer 每页大小 10
menuName String 菜单名称 用户管理
menuStatus String 菜单状态 0
auth String 权限标识 system:user:list

响应示例:

{
    "code": 1,
    "success": true,
    "msg": "操作成功",
    "data": [
        {
            "menuId": 1,
            "menuName": "系统管理",
            "enName": "System Manage",
            "parentId": 0,
            "menuType": "1",
            "name": "systemPage",
            "path": "/system",
            "component": "",
            "icon": "Tools",
            "isHide": "1",
            "isLink": "",
            "isKeepAlive": "0",
            "isFull": "1",
            "isAffix": "1",
            "redirect": "/system/user",
            "activeMenu": null
        },
        {
            "menuId": 2,
            "menuName": "用户管理",
            "enName": "User Manage",
            "parentId": 1,
            "menuType": "2",
            "name": "userPage",
            "path": "/system/user",
            "component": "system/user/index",
            "icon": "UserFilled",
            "isHide": "1",
            "isLink": "",
            "isKeepAlive": "1",
            "isFull": "1",
            "isAffix": "1",
            "redirect": "",
            "activeMenu": null
        },
        {
            "menuId": 12,
            "menuName": "角色管理",
            "enName": "Role Manage",
            "parentId": 1,
            "menuType": "2",
            "name": "rolePage",
            "path": "/system/role",
            "component": "system/role/index",
            "icon": "Avatar",
            "isHide": "1",
            "isLink": "",
            "isKeepAlive": "0",
            "isFull": "1",
            "isAffix": "1",
            "redirect": "",
            "activeMenu": null
        },
        {
            "menuId": 72,
            "menuName": "文件管理",
            "enName": "Files Manage",
            "parentId": 70,
            "menuType": "2",
            "name": "filePage",
            "path": "/tools/file",
            "component": "system/file/index",
            "icon": "FolderOpened",
            "isHide": "1",
            "isLink": "",
            "isKeepAlive": "0",
            "isFull": "1",
            "isAffix": "1",
            "redirect": "",
            "activeMenu": ""
        },
        {
            "menuId": 19,
            "menuName": "菜单管理",
            "enName": "Menu Manage",
            "parentId": 1,
            "menuType": "2",
            "name": "menuPage",
            "path": "/system/menu",
            "component": "system/menu/index",
            "icon": "Grid",
            "isHide": "1",
            "isLink": "",
            "isKeepAlive": "0",
            "isFull": "1",
            "isAffix": "1",
            "redirect": "",
            "activeMenu": null
        },
        {
            "menuId": 77,
            "menuName": "图库管理",
            "enName": "Pictures Manage",
            "parentId": 70,
            "menuType": "2",
            "name": "picturePage",
            "path": "/tools/picture",
            "component": "system/picture/index",
            "icon": "Picture",
            "isHide": "1",
            "isLink": "",
            "isKeepAlive": "0",
            "isFull": "1",
            "isAffix": "1",
            "redirect": "",
            "activeMenu": ""
        },
        {
            "menuId": 39,
            "menuName": "登录日志",
            "enName": "Login Logs",
            "parentId": 1,
            "menuType": "2",
            "name": "loginlogPage",
            "path": "/system/loginlog",
            "component": "system/loginlog/index",
            "icon": "Calendar",
            "isHide": "1",
            "isLink": "",
            "isKeepAlive": "0",
            "isFull": "1",
            "isAffix": "1",
            "redirect": "",
            "activeMenu": null
        },
        {
            "menuId": 42,
            "menuName": "操作日志",
            "enName": "Operate Logs",
            "parentId": 1,
            "menuType": "2",
            "name": "operlogPage",
            "path": "/system/operlog",
            "component": "system/operlog/index",
            "icon": "Notebook",
            "isHide": "1",
            "isLink": "",
            "isKeepAlive": "0",
            "isFull": "1",
            "isAffix": "1",
            "redirect": "",
            "activeMenu": null
        },
        {
            "menuId": 50,
            "menuName": "个人中心",
            "enName": "Personage Center",
            "parentId": 1,
            "menuType": "2",
            "name": "personagePage",
            "path": "/system/personage",
            "component": "system/personage/index",
            "icon": "User",
            "isHide": "0",
            "isLink": "",
            "isKeepAlive": "0",
            "isFull": "1",
            "isAffix": "1",
            "redirect": null,
            "activeMenu": null
        },
        {
            "menuId": 166,
            "menuName": "外部链接",
            "enName": "External Link",
            "parentId": 0,
            "menuType": "1",
            "name": "linkPage",
            "path": "/link",
            "component": "",
            "icon": "Link",
            "isHide": "0",
            "isLink": "",
            "isKeepAlive": "0",
            "isFull": "1",
            "isAffix": "1",
            "redirect": null,
            "activeMenu": null
        }
    ]
}

调用示例:

curl -X GET \
  "http://localhost:18099/coder/sysMenu/listPage?pageNo=1&pageSize=10&menuName=系统管理" \
  -H "Authorization: your-token-value"

2. 查询菜单列表

接口地址: GET /coder/sysMenu/list

接口描述: 查询系统菜单列表(树形结构,不分页)

是否需要认证: 是

权限要求: system:menu:list

请求参数: 同分页查询除pageNo、pageSize外

响应示例:

{
  "status": 200,
  "msg": "SUCCESS",
  "data": [
    {
      "menuId": 1,
      "menuName": "系统管理",
      "enName": "System",
      "parentId": 0,
      "menuType": "1",
      "path": "/system",
      "name": "system",
      "component": "Layout",
      "icon": "system",
      "auth": "",
      "menuStatus": "0",
      "activeMenu": "",
      "isHide": "1",
      "isLink": "1",
      "isKeepAlive": "0",
      "isFull": "1",
      "isAffix": "1",
      "isSpread": "0",
      "sorted": 1,
      "createBy": "admin",
      "createTime": "2024-01-01 10:00:00",
      "updateBy": "admin",
      "updateTime": "2024-01-01 10:00:00",
      "children": [
        // 子菜单...
      ]
    }
  ],
  "traceId": "trace-123456"
}

调用示例:

curl -X GET \
  "http://localhost:18099/coder/sysMenu/list" \
  -H "Authorization: your-token-value"

3. 根据ID查询菜单

接口地址: GET /coder/sysMenu/getById/{id}

接口描述: 根据菜单ID查询菜单详细信息

是否需要认证: 是

权限要求: system:menu:list

路径参数:

参数名 类型 必填 说明
id Long 菜单ID

响应示例:

{
  "status": 200,
  "msg": "SUCCESS",
  "data": {
    "menuId": 1,
    "menuName": "系统管理",
    "enName": "System",
    "parentId": 0,
    "menuType": "1",
    "path": "/system",
    "name": "system",
    "component": "Layout",
    "icon": "system",
    "auth": "",
    "menuStatus": "0",
    "activeMenu": "",
    "isHide": "1",
    "isLink": "1",
    "isKeepAlive": "0",
    "isFull": "1",
    "isAffix": "1",
    "isSpread": "0",
    "sorted": 1,
    "createBy": "admin",
    "createTime": "2024-01-01 10:00:00",
    "updateBy": "admin",
    "updateTime": "2024-01-01 10:00:00"
  },
  "traceId": "trace-123456"
}

调用示例:

curl -X GET \
  http://localhost:18099/coder/sysMenu/getById/1 \
  -H "Authorization: your-token-value"

4. 新增菜单

接口地址: POST /coder/sysMenu/add

接口描述: 新增系统菜单

是否需要认证: 是

权限要求: system:menu:add

请求参数:

{
  "menuName": "用户管理",
  "enName": "User Management",
  "parentId": 1,
  "menuType": "2",
  "path": "/system/user",
  "name": "user",
  "component": "/system/user/index",
  "icon": "user",
  "auth": "system:user:list",
  "menuStatus": "0",
  "activeMenu": "",
  "isHide": "1",
  "isLink": "1",
  "isKeepAlive": "0",
  "isFull": "1",
  "isAffix": "1",
  "isSpread": "0",
  "sorted": 1
}

请求参数说明:

参数名 类型 必填 说明 校验规则
menuName String 菜单名称 不能为空
enName String 英文名称 可为空
parentId Long 父菜单ID 不能为空0表示根菜单
menuType String 菜单类型 1-目录 2-菜单 3-按钮
path String 路由地址 菜单类型为2时必填
name String 路由名称 菜单类型为2时必填
component String 组件路径 菜单类型为2时必填
icon String 菜单图标 可为空
auth String 权限标识 按钮类型时必填
menuStatus String 菜单状态 0-启用 1-停用
activeMenu String 选中路由 可为空
isHide String 是否隐藏 0-隐藏 1-显示
isLink String 是否外链 0-是 1-否
isKeepAlive String 是否缓存 0-是 1-否
isFull String 是否全屏 0-是 1-否
isAffix String 是否固定 0-是 1-否
isSpread String 是否展开 0-是 1-否
sorted Integer 显示顺序 不能为空

响应示例:

{
  "status": 200,
  "msg": "SUCCESS",
  "data": "新增成功",
  "traceId": "trace-123456"
}

调用示例:

curl -X POST \
  http://localhost:18099/coder/sysMenu/add \
  -H "Content-Type: application/json" \
  -H "Authorization: your-token-value" \
  -d '{
    "menuName": "用户管理",
    "enName": "User Management",
    "parentId": 1,
    "menuType": "2",
    "path": "/system/user",
    "name": "user",
    "component": "/system/user/index",
    "icon": "user",
    "auth": "system:user:list",
    "menuStatus": "0",
    "activeMenu": "",
    "isHide": "1",
    "isLink": "1",
    "isKeepAlive": "0",
    "isFull": "1",
    "isAffix": "1",
    "isSpread": "0",
    "sorted": 1
  }'

5. 修改菜单信息

接口地址: POST /coder/sysMenu/update

接口描述: 修改系统菜单信息

是否需要认证: 是

权限要求: system:menu:edit

请求参数:

{
  "menuId": 1,
  "menuName": "用户管理",
  "enName": "User Management",
  "parentId": 1,
  "menuType": "2",
  "path": "/system/user",
  "name": "user",
  "component": "/system/user/index",
  "icon": "user",
  "auth": "system:user:list",
  "menuStatus": "0",
  "activeMenu": "",
  "isHide": "1",
  "isLink": "1",
  "isKeepAlive": "0",
  "isFull": "1",
  "isAffix": "1",
  "isSpread": "0",
  "sorted": 1
}

请求参数说明:

参数名 类型 必填 说明 校验规则
menuId Long 菜单ID 必须是有效的菜单ID
其他参数 - - 同新增菜单 -

响应示例:

{
  "status": 200,
  "msg": "SUCCESS",
  "data": "修改成功",
  "traceId": "trace-123456"
}

调用示例:

curl -X POST \
  http://localhost:18099/coder/sysMenu/update \
  -H "Content-Type: application/json" \
  -H "Authorization: your-token-value" \
  -d '{
    "menuId": 1,
    "menuName": "用户管理",
    "parentId": 1,
    "menuType": "2",
    "menuStatus": "0",
    "sorted": 1
  }'

6. 删除菜单

接口地址: POST /coder/sysMenu/deleteById/{id}

接口描述: 根据ID删除菜单

是否需要认证: 是

权限要求: system:menu:remove

路径参数:

参数名 类型 必填 说明
id Long 菜单ID

响应示例:

{
  "status": 200,
  "msg": "SUCCESS",
  "data": "删除成功",
  "traceId": "trace-123456"
}

调用示例:

curl -X POST \
  http://localhost:18099/coder/sysMenu/deleteById/1 \
  -H "Authorization: your-token-value"

7. 批量删除菜单

接口地址: POST /coder/sysMenu/batchDelete

接口描述: 批量删除菜单

是否需要认证: 是

权限要求: system:menu:remove

请求参数:

{
  "ids": [1, 2, 3]
}

请求参数说明:

参数名 类型 必填 说明
ids Long[] 菜单ID数组

响应示例:

{
  "status": 200,
  "msg": "SUCCESS",
  "data": "删除成功",
  "traceId": "trace-123456"
}

调用示例:

curl -X POST \
  http://localhost:18099/coder/sysMenu/batchDelete \
  -H "Content-Type: application/json" \
  -H "Authorization: your-token-value" \
  -d '{
    "ids": [1, 2, 3]
  }'

8. 修改菜单状态

接口地址: POST /coder/sysMenu/updateStatus/{id}/{menuStatus}

接口描述: 修改菜单状态(启用/停用)

是否需要认证: 是

权限要求: system:menu:edit

路径参数:

参数名 类型 必填 说明
id Long 菜单ID
menuStatus String 菜单状态0-启用 1-停用)

响应示例:

{
  "status": 200,
  "msg": "SUCCESS",
  "data": "修改成功",
  "traceId": "trace-123456"
}

调用示例:

curl -X POST \
  http://localhost:18099/coder/sysMenu/updateStatus/1/0 \
  -H "Authorization: your-token-value"

9. 修改菜单展开状态

接口地址: POST /coder/sysMenu/updateSpread/{id}/{isSpread}

接口描述: 修改菜单展开状态

是否需要认证: 是

权限要求: system:menu:edit

路径参数:

参数名 类型 必填 说明
id Long 菜单ID
isSpread String 展开状态0-是 1-否)

响应示例:

{
  "status": 200,
  "msg": "SUCCESS",
  "data": "修改成功",
  "traceId": "trace-123456"
}

调用示例:

curl -X POST \
  http://localhost:18099/coder/sysMenu/updateSpread/1/0 \
  -H "Authorization: your-token-value"

10. 菜单级联下拉框

接口地址: GET /coder/sysMenu/cascaderList

接口描述: 获取菜单级联下拉框数据

是否需要认证: 是

权限要求: system:menu:list

请求参数: 无

响应示例:

{
  "status": 200,
  "msg": "SUCCESS",
  "data": [
    {
      "label": "系统管理",
      "value": 1,
      "parentId": "0",
      "children": [
        {
          "label": "用户管理",
          "value": 2,
          "parentId": "1"
        },
        {
          "label": "角色管理",
          "value": 3,
          "parentId": "1"
        }
      ]
    }
  ],
  "traceId": "trace-123456"
}

调用示例:

curl -X GET \
  http://localhost:18099/coder/sysMenu/cascaderList \
  -H "Authorization: your-token-value"

11. 生成用户菜单路由

接口地址: GET /coder/sysMenu/listRouters

接口描述: 根据当前用户权限生成前端菜单路由

是否需要认证: 是

权限要求: 无(已登录用户可访问)

请求参数: 无

响应示例:

{
    "code": 1,
    "success": true,
    "msg": "操作成功",
    "data": [
        {
            "menuId": 1,
            "menuName": "系统管理",
            "enName": "System Manage",
            "parentId": 0,
            "menuType": "1",
            "name": "systemPage",
            "path": "/system",
            "component": "",
            "icon": "Tools",
            "isHide": "1",
            "isLink": "",
            "isKeepAlive": "0",
            "isFull": "1",
            "isAffix": "1",
            "redirect": "/system/user",
            "activeMenu": null
        },
        {
            "menuId": 2,
            "menuName": "用户管理",
            "enName": "User Manage",
            "parentId": 1,
            "menuType": "2",
            "name": "userPage",
            "path": "/system/user",
            "component": "system/user/index",
            "icon": "UserFilled",
            "isHide": "1",
            "isLink": "",
            "isKeepAlive": "1",
            "isFull": "1",
            "isAffix": "1",
            "redirect": "",
            "activeMenu": null
        },
        {
            "menuId": 70,
            "menuName": "系统工具",
            "enName": "System Tools",
            "parentId": 0,
            "menuType": "1",
            "name": "toolsPage",
            "path": "/tools",
            "component": "",
            "icon": "Tools",
            "isHide": "1",
            "isLink": "",
            "isKeepAlive": "0",
            "isFull": "1",
            "isAffix": "1",
            "redirect": "/tools/file",
            "activeMenu": null
        },
        {
            "menuId": 12,
            "menuName": "角色管理",
            "enName": "Role Manage",
            "parentId": 1,
            "menuType": "2",
            "name": "rolePage",
            "path": "/system/role",
            "component": "system/role/index",
            "icon": "Avatar",
            "isHide": "1",
            "isLink": "",
            "isKeepAlive": "0",
            "isFull": "1",
            "isAffix": "1",
            "redirect": "",
            "activeMenu": null
        },
        {
            "menuId": 72,
            "menuName": "文件管理",
            "enName": "Files Manage",
            "parentId": 70,
            "menuType": "2",
            "name": "filePage",
            "path": "/tools/file",
            "component": "system/file/index",
            "icon": "FolderOpened",
            "isHide": "1",
            "isLink": "",
            "isKeepAlive": "0",
            "isFull": "1",
            "isAffix": "1",
            "redirect": "",
            "activeMenu": ""
        },
        {
            "menuId": 19,
            "menuName": "菜单管理",
            "enName": "Menu Manage",
            "parentId": 1,
            "menuType": "2",
            "name": "menuPage",
            "path": "/system/menu",
            "component": "system/menu/index",
            "icon": "Grid",
            "isHide": "1",
            "isLink": "",
            "isKeepAlive": "0",
            "isFull": "1",
            "isAffix": "1",
            "redirect": "",
            "activeMenu": null
        },
        {
            "menuId": 77,
            "menuName": "图库管理",
            "enName": "Pictures Manage",
            "parentId": 70,
            "menuType": "2",
            "name": "picturePage",
            "path": "/tools/picture",
            "component": "system/picture/index",
            "icon": "Picture",
            "isHide": "1",
            "isLink": "",
            "isKeepAlive": "0",
            "isFull": "1",
            "isAffix": "1",
            "redirect": "",
            "activeMenu": ""
        },
        {
            "menuId": 39,
            "menuName": "登录日志",
            "enName": "Login Logs",
            "parentId": 1,
            "menuType": "2",
            "name": "loginlogPage",
            "path": "/system/loginlog",
            "component": "system/loginlog/index",
            "icon": "Calendar",
            "isHide": "1",
            "isLink": "",
            "isKeepAlive": "0",
            "isFull": "1",
            "isAffix": "1",
            "redirect": "",
            "activeMenu": null
        },
        {
            "menuId": 42,
            "menuName": "操作日志",
            "enName": "Operate Logs",
            "parentId": 1,
            "menuType": "2",
            "name": "operlogPage",
            "path": "/system/operlog",
            "component": "system/operlog/index",
            "icon": "Notebook",
            "isHide": "1",
            "isLink": "",
            "isKeepAlive": "0",
            "isFull": "1",
            "isAffix": "1",
            "redirect": "",
            "activeMenu": null
        },
        {
            "menuId": 50,
            "menuName": "个人中心",
            "enName": "Personage Center",
            "parentId": 1,
            "menuType": "2",
            "name": "personagePage",
            "path": "/system/personage",
            "component": "system/personage/index",
            "icon": "User",
            "isHide": "0",
            "isLink": "",
            "isKeepAlive": "0",
            "isFull": "1",
            "isAffix": "1",
            "redirect": null,
            "activeMenu": null
        },
        {
            "menuId": 166,
            "menuName": "外部链接",
            "enName": "External Link",
            "parentId": 0,
            "menuType": "1",
            "name": "linkPage",
            "path": "/link",
            "component": "",
            "icon": "Link",
            "isHide": "0",
            "isLink": "",
            "isKeepAlive": "0",
            "isFull": "1",
            "isAffix": "1",
            "redirect": null,
            "activeMenu": null
        }
    ]
}

调用示例:

curl -X GET \
  http://localhost:18099/coder/sysMenu/listRouters \
  -H "Authorization: your-token-value"

12. 查询正常菜单列表

接口地址: GET /coder/sysMenu/listMenuNormal

接口描述: 查询状态正常的菜单列表

是否需要认证: 是

权限要求: system:menu:list

请求参数: 无

响应示例:

{
  "status": 200,
  "msg": "SUCCESS",
  "data": [
    {
      "menuId": 1,
      "menuName": "系统管理",
      "enName": "System",
      "parentId": 0,
      "menuType": "1",
      "path": "/system",
      "name": "system",
      "component": "Layout",
      "icon": "system",
      "auth": "",
      "menuStatus": "0",
      "activeMenu": "",
      "isHide": "1",
      "isLink": "1",
      "isKeepAlive": "0",
      "isFull": "1",
      "isAffix": "1",
      "isSpread": "0",
      "sorted": 1,
      "children": [
        // 子菜单...
      ]
    }
  ],
  "traceId": "trace-123456"
}

调用示例:

curl -X GET \
  http://localhost:18099/coder/sysMenu/listMenuNormal \
  -H "Authorization: your-token-value"

13. 根据角色ID查询菜单

接口地址: GET /coder/sysMenu/listMenuIdsByRoleId/{roleId}

接口描述: 根据角色ID查询该角色拥有的菜单ID列表

是否需要认证: 是

权限要求: system:menu:list

路径参数:

参数名 类型 必填 说明
roleId Long 角色ID

响应示例:

{
  "status": 200,
  "msg": "SUCCESS",
  "data": [1, 2, 3, 4, 5],
  "traceId": "trace-123456"
}

调用示例:

curl -X GET \
  http://localhost:18099/coder/sysMenu/listMenuIdsByRoleId/1 \
  -H "Authorization: your-token-value"

14. 保存角色菜单权限

接口地址: POST /coder/sysMenu/saveRoleMenu/{roleId}/{menuIds}

接口描述: 保存角色的菜单权限

是否需要认证: 是

权限要求: system:menu:assign

路径参数:

参数名 类型 必填 说明
roleId Long 角色ID
menuIds String 菜单ID列表逗号分隔

响应示例:

{
  "status": 200,
  "msg": "SUCCESS",
  "data": "保存成功",
  "traceId": "trace-123456"
}

调用示例:

curl -X POST \
  http://localhost:18099/coder/sysMenu/saveRoleMenu/1/1,2,3,4,5 \
  -H "Authorization: your-token-value"

菜单字段说明

基础字段

字段名 类型 说明 示例
menuId Long 菜单ID 1
menuName String 菜单名称 系统管理
enName String 英文名称 System
parentId Long 父菜单ID 0根菜单
menuType String 菜单类型 1-目录 2-菜单 3-按钮
sorted Integer 显示顺序 1

路由字段

字段名 类型 说明 示例
path String 路由地址 /system/user
name String 路由名称 user
component String 组件路径 /system/user/index
redirect String 重定向地址 /system/user
activeMenu String 选中路由 /system/user

权限字段

字段名 类型 说明 示例
auth String 权限标识 system:user:list
menuStatus String 菜单状态 0-启用 1-停用

显示字段

字段名 类型 说明 示例
icon String 菜单图标 user
isHide String 是否隐藏 0-隐藏 1-显示
isLink String 是否外链 0-是 1-否
isKeepAlive String 是否缓存 0-是 1-否
isFull String 是否全屏 0-是 1-否
isAffix String 是否固定 0-是 1-否
isSpread String 是否展开 0-是 1-否

前端路由配置

Vue Router 配置

// 根据后端返回的菜单数据生成路由
function generateRoutes(menuData) {
  const routes = [];
  
  menuData.forEach(menu => {
    const route = {
      path: menu.path,
      name: menu.name,
      component: () => import(`@/views${menu.component}.vue`),
      meta: {
        title: menu.menuName,
        icon: menu.icon,
        isHide: menu.isHide === '0',
        isLink: menu.isLink === '0',
        isKeepAlive: menu.isKeepAlive === '0',
        isFull: menu.isFull === '0',
        isAffix: menu.isAffix === '0',
        activeMenu: menu.activeMenu
      }
    };
    
    if (menu.children && menu.children.length > 0) {
      route.children = generateRoutes(menu.children);
    }
    
    if (menu.redirect) {
      route.redirect = menu.redirect;
    }
    
    routes.push(route);
  });
  
  return routes;
}

权限控制

// 页面权限控制
router.beforeEach((to, from, next) => {
  const userPermissions = store.getters.permissions;
  
  if (to.meta.auth) {
    if (userPermissions.includes(to.meta.auth) || userPermissions.includes('*:*:*')) {
      next();
    } else {
      next('/403');
    }
  } else {
    next();
  }
});

// 按钮权限控制
Vue.directive('permission', {
  inserted(el, binding) {
    const { value } = binding;
    const permissions = store.getters.permissions;
    
    if (value) {
      const hasPermission = permissions.includes(value) || permissions.includes('*:*:*');
      if (!hasPermission) {
        el.parentNode && el.parentNode.removeChild(el);
      }
    }
  }
});

错误码说明

错误码 错误信息 说明
400 菜单名称不能为空 菜单名称为空
400 上级菜单不能为空 父菜单ID为空
400 菜单类型不能为空 菜单类型为空
400 菜单状态不能为空 菜单状态为空
400 是否隐藏菜单不能为空 隐藏状态为空
400 显示顺序不能为空 排序值为空
400 菜单不存在 菜单ID不存在
400 存在子菜单,不允许删除 菜单有子菜单时不能删除
400 菜单已分配,不允许删除 菜单已分配给角色时不能删除
400 不能选择自己作为父菜单 父菜单不能是自己
400 路由地址不能为空 菜单类型为菜单时路由地址必填
400 组件路径不能为空 菜单类型为菜单时组件路径必填
400 权限标识不能为空 菜单类型为按钮时权限标识必填
401 当前会话未登录 未登录或Token无效
403 权限不足 没有相应的操作权限
500 系统异常 服务器内部错误

使用建议

1. 菜单设计规范

  • 层级结构: 建议不超过3级菜单
  • 命名规范: 使用有意义的英文名称作为路由名称
  • 权限标识: 使用模块:功能:操作的格式
  • 图标使用: 统一使用Element UI或其他图标库

2. 权限设计

  • 粒度控制: 按钮级别的权限控制
  • 角色分离: 不同角色分配不同的菜单权限
  • 继承关系: 子菜单权限依赖于父菜单权限
  • 缓存策略: 用户权限信息缓存到前端

3. 性能优化

  • 懒加载: 菜单组件使用懒加载
  • 缓存机制: 菜单数据缓存到本地存储
  • 权限缓存: 权限信息缓存到内存中
  • 树形结构: 使用高效的树形数据结构

4. 安全考虑

  • 权限验证: 前后端都要进行权限验证
  • 敏感操作: 重要操作需要二次确认
  • 日志记录: 记录权限变更操作日志
  • 最小权限: 遵循最小权限原则

注意事项

  1. 菜单删除: 删除菜单前需要检查是否有子菜单和角色关联
  2. 权限继承: 子菜单的权限依赖于父菜单
  3. 缓存更新: 菜单权限变更后需要清理相关缓存
  4. 前端同步: 菜单结构变更后前端需要同步更新
  5. 权限验证: 前后端都需要进行权限验证
  6. 状态管理: 菜单状态变更会影响用户访问
  7. 排序规则: 菜单按照sorted字段升序排列
  8. 数据完整性: 保证菜单数据的完整性和一致性