# 菜单管理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 | **响应示例**: ```json { "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 } ] } ``` **调用示例**: ```bash 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外) **响应示例**: ```json { "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" } ``` **调用示例**: ```bash 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 | **响应示例**: ```json { "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" } ``` **调用示例**: ```bash curl -X GET \ http://localhost:18099/coder/sysMenu/getById/1 \ -H "Authorization: your-token-value" ``` --- ### 4. 新增菜单 **接口地址**: `POST /coder/sysMenu/add` **接口描述**: 新增系统菜单 **是否需要认证**: 是 **权限要求**: `system:menu:add` **请求参数**: ```json { "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 | 是 | 显示顺序 | 不能为空 | **响应示例**: ```json { "status": 200, "msg": "SUCCESS", "data": "新增成功", "traceId": "trace-123456" } ``` **调用示例**: ```bash 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` **请求参数**: ```json { "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 | | 其他参数 | - | - | 同新增菜单 | - | **响应示例**: ```json { "status": 200, "msg": "SUCCESS", "data": "修改成功", "traceId": "trace-123456" } ``` **调用示例**: ```bash 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 | **响应示例**: ```json { "status": 200, "msg": "SUCCESS", "data": "删除成功", "traceId": "trace-123456" } ``` **调用示例**: ```bash curl -X POST \ http://localhost:18099/coder/sysMenu/deleteById/1 \ -H "Authorization: your-token-value" ``` --- ### 7. 批量删除菜单 **接口地址**: `POST /coder/sysMenu/batchDelete` **接口描述**: 批量删除菜单 **是否需要认证**: 是 **权限要求**: `system:menu:remove` **请求参数**: ```json { "ids": [1, 2, 3] } ``` **请求参数说明**: | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | ids | Long[] | 是 | 菜单ID数组 | **响应示例**: ```json { "status": 200, "msg": "SUCCESS", "data": "删除成功", "traceId": "trace-123456" } ``` **调用示例**: ```bash 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-停用) | **响应示例**: ```json { "status": 200, "msg": "SUCCESS", "data": "修改成功", "traceId": "trace-123456" } ``` **调用示例**: ```bash 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-否) | **响应示例**: ```json { "status": 200, "msg": "SUCCESS", "data": "修改成功", "traceId": "trace-123456" } ``` **调用示例**: ```bash curl -X POST \ http://localhost:18099/coder/sysMenu/updateSpread/1/0 \ -H "Authorization: your-token-value" ``` --- ### 10. 菜单级联下拉框 **接口地址**: `GET /coder/sysMenu/cascaderList` **接口描述**: 获取菜单级联下拉框数据 **是否需要认证**: 是 **权限要求**: `system:menu:list` **请求参数**: 无 **响应示例**: ```json { "status": 200, "msg": "SUCCESS", "data": [ { "label": "系统管理", "value": 1, "parentId": "0", "children": [ { "label": "用户管理", "value": 2, "parentId": "1" }, { "label": "角色管理", "value": 3, "parentId": "1" } ] } ], "traceId": "trace-123456" } ``` **调用示例**: ```bash curl -X GET \ http://localhost:18099/coder/sysMenu/cascaderList \ -H "Authorization: your-token-value" ``` --- ### 11. 生成用户菜单路由 **接口地址**: `GET /coder/sysMenu/listRouters` **接口描述**: 根据当前用户权限生成前端菜单路由 **是否需要认证**: 是 **权限要求**: 无(已登录用户可访问) **请求参数**: 无 **响应示例**: ```json { "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 } ] } ``` **调用示例**: ```bash curl -X GET \ http://localhost:18099/coder/sysMenu/listRouters \ -H "Authorization: your-token-value" ``` --- ### 12. 查询正常菜单列表 **接口地址**: `GET /coder/sysMenu/listMenuNormal` **接口描述**: 查询状态正常的菜单列表 **是否需要认证**: 是 **权限要求**: `system:menu:list` **请求参数**: 无 **响应示例**: ```json { "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" } ``` **调用示例**: ```bash 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 | **响应示例**: ```json { "status": 200, "msg": "SUCCESS", "data": [1, 2, 3, 4, 5], "traceId": "trace-123456" } ``` **调用示例**: ```bash 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列表(逗号分隔) | **响应示例**: ```json { "status": 200, "msg": "SUCCESS", "data": "保存成功", "traceId": "trace-123456" } ``` **调用示例**: ```bash 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 配置 ```javascript // 根据后端返回的菜单数据生成路由 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; } ``` ### 权限控制 ```javascript // 页面权限控制 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. **数据完整性**: 保证菜单数据的完整性和一致性