30 KiB
菜单管理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. 安全考虑
- 权限验证: 前后端都要进行权限验证
- 敏感操作: 重要操作需要二次确认
- 日志记录: 记录权限变更操作日志
- 最小权限: 遵循最小权限原则
注意事项
- 菜单删除: 删除菜单前需要检查是否有子菜单和角色关联
- 权限继承: 子菜单的权限依赖于父菜单
- 缓存更新: 菜单权限变更后需要清理相关缓存
- 前端同步: 菜单结构变更后前端需要同步更新
- 权限验证: 前后端都需要进行权限验证
- 状态管理: 菜单状态变更会影响用户访问
- 排序规则: 菜单按照sorted字段升序排列
- 数据完整性: 保证菜单数据的完整性和一致性