# 权限管理功能使用说明 ## 📋 功能概述 本次开发完成了完整的权限管理系统,包括: 1. **菜单权限管理** - 管理系统菜单树和菜单项 2. **操作权限管理** - 为不同角色分配菜单和按钮操作权限 3. **超级管理员** - 15900000000 账号拥有所有权限 --- ## 🗂️ 部署步骤 ### 第一步:执行数据库初始化脚本 在数据库中执行 `权限管理功能初始化SQL.sql` 文件,该脚本会: - ✅ 创建"权限管理"父菜单 - ✅ 创建"菜单权限管理"子菜单 - ✅ 创建"操作权限管理"子菜单 - ✅ 为这些菜单添加对应的按钮权限 - ✅ 创建或更新超级管理员角色(ID=1) - ✅ 设置 15900000000 为超级管理员账号 - ✅ 为超级管理员分配所有菜单权限 - ✅ 为运送清单功能添加完整的权限点 **执行方式**: ```sql -- 在MySQL客户端或管理工具中执行 source /path/to/权限管理功能初始化SQL.sql; -- 或直接复制粘贴SQL内容执行 ``` ### 第二步:重新编译并启动后端 ```bash # 进入后端项目根目录 cd c:\cattleTransport\tradeCattle # 清理并编译安装所有模块 mvn clean install -DskipTests # 进入业务模块 cd aiotagro-cattle-trade # 启动后端服务 mvn spring-boot:run # 或使用jar包启动 java -jar target/aiotagro-cattletrade-1.0.1.jar ``` **后端服务地址**:`http://127.0.0.1:16200` ### 第三步:启动前端 ```bash # 进入前端项目目录 cd c:\cattleTransport\pc-cattle-transportation # 安装依赖(首次或有新依赖时) npm install # 启动开发服务器 npm run dev ``` **前端访问地址**:`http://localhost:8080` --- ## 👤 超级管理员账号 ### 登录信息 - **账号**:`15900000000` - **密码**:`123456` (如果是SQL脚本新创建的账号) - **角色**:超级管理员(roleId=1) - **权限**:拥有系统所有权限(*:*:*) ### 特权说明 超级管理员具有以下特权: 1. ✅ **绕过所有权限检查** - 自动拥有所有操作权限 2. ✅ **查看所有数据** - 不受数据权限限制,可以看到所有用户创建的数据 3. ✅ **管理权限** - 可以为其他角色分配权限 4. ✅ **管理菜单** - 可以增删改菜单和按钮权限 --- ## 🎯 功能使用指南 ### 1. 菜单权限管理 **访问路径**:系统主菜单 → 权限管理 → 菜单权限管理 **功能列表**: - ✅ **查看菜单树** - 以树形结构展示所有系统菜单 - ✅ **新增菜单** - 添加新的菜单或按钮权限 - ✅ **编辑菜单** - 修改菜单信息 - ✅ **删除菜单** - 软删除菜单(is_delete=1) **字段说明**: | 字段 | 说明 | 示例 | |------|------|------| | 菜单名称 | 显示在系统中的菜单名称 | 权限管理 | | 菜单类型 | 1=菜单(页面),2=按钮(操作) | 1 | | 路由地址 | 前端路由路径 | /permission/menu | | 组件路径 | Vue组件路径 | permission/menuPermission | | 权限标识 | 后端权限检查标识 | permission:menu:view | | 图标 | Element Plus图标名称 | el-icon-lock | | 排序 | 菜单显示顺序 | 1 | **操作步骤**: 1. 点击"新增菜单"按钮 2. 选择上级菜单(可选,默认为顶级菜单) 3. 选择菜单类型(菜单/按钮) 4. 填写必填信息:菜单名称、权限标识 5. 如果是菜单类型,还需填写路由地址和组件路径 6. 设置排序号 7. 点击"确定"保存 --- ### 2. 操作权限管理 **访问路径**:系统主菜单 → 权限管理 → 操作权限管理 **功能列表**: - ✅ **角色管理** - 新增、编辑、删除角色 - ✅ **权限分配** - 为角色分配菜单和按钮权限 - ✅ **查看权限** - 查看角色当前拥有的权限 **左侧:角色列表** - 显示所有系统角色 - 点击角色行可查看和编辑该角色的权限 - 可以新增、编辑、删除角色(超级管理员角色不可删除) **右侧:权限树** - 以树形结构显示所有菜单和按钮权限 - 勾选表示该角色拥有该权限 - 支持级联选择(选中父菜单会自动选中子项) **操作步骤**: #### 新增角色 1. 点击左侧"新增角色"按钮 2. 输入角色名称和描述 3. 点击"确定"保存 #### 为角色分配权限 1. 在左侧角色列表中点击选中某个角色 2. 右侧会显示权限树 3. 勾选该角色需要的菜单和按钮权限 4. 点击右上角"保存权限"按钮 --- ## 🔐 权限标识规范 系统采用统一的权限标识命名规范:`模块:资源:操作` ### 示例 | 权限标识 | 说明 | 对应功能 | |---------|------|---------| | `permission:menu:view` | 权限-菜单-查看 | 查看菜单权限管理页面 | | `permission:menu:list` | 权限-菜单-列表 | 查询菜单列表 | | `permission:menu:add` | 权限-菜单-新增 | 新增菜单 | | `permission:menu:edit` | 权限-菜单-编辑 | 编辑菜单 | | `permission:menu:delete` | 权限-菜单-删除 | 删除菜单 | | `permission:menu:assign` | 权限-菜单-分配 | 分配菜单权限给角色 | | `permission:operation:view` | 权限-操作-查看 | 查看操作权限管理页面 | | `permission:operation:list` | 权限-操作-列表 | 查询角色和权限列表 | | `permission:operation:assign` | 权限-操作-分配 | 分配操作权限 | | `permission:operation:role` | 权限-操作-角色 | 管理角色(增删改) | | `delivery:list` | 运送-清单-列表 | 查看运送清单列表 | | `delivery:add` | 运送-清单-新增 | 新增运送清单 | | `delivery:edit` | 运送-清单-编辑 | 编辑运送清单 | | `delivery:delete` | 运送-清单-删除 | 删除运送清单 | | `delivery:view` | 运送-清单-查看 | 查看运送清单详情 | | `delivery:check` | 运送-清单-核验 | 核验运送清单 | | `delivery:assign` | 运送-清单-分配 | 分配设备 | | `delivery:load` | 运送-清单-装车 | 装车操作 | | `*:*:*` | 所有权限 | 超级管理员特有 | --- ## 🔧 前端权限控制 ### 按钮级权限指令 在前端使用 `v-hasPermi` 指令控制按钮的显示/隐藏: ```vue 新增 编辑 ``` ### 角色级权限指令 使用 `v-hasRole` 指令控制基于角色的显示: ```vue 管理员功能 ``` ### 编程式权限判断 ```javascript import { useUserStore } from '@/store/user'; const userStore = useUserStore(); // 判断是否有某个权限 if (userStore.hasPermission('delivery:add')) { // 有权限,执行操作 } // 判断是否有某个角色 if (userStore.hasRole('admin')) { // 有角色,执行操作 } ``` --- ## 🛡️ 后端权限控制 ### 接口级权限注解 在Controller方法上使用 `@SaCheckPermission` 注解: ```java @RestController @RequestMapping("/delivery") public class DeliveryController { // 单个权限 @SaCheckPermission("delivery:list") @PostMapping("/pageQuery") public PageResultResponse pageQuery(@RequestBody DeliveryQueryDto dto) { // ... } // 多个权限(满足其一即可) @SaCheckPermission(value = {"delivery:add", "delivery:create"}, mode = SaMode.OR) @PostMapping("/create") public AjaxResult create(@RequestBody DeliveryCreateDto dto) { // ... } } ``` ### 数据权限控制 使用 `DataScopeUtil` 工具类进行数据权限过滤: ```java // 普通用户只能看自己创建的数据,超级管理员可以看所有数据 LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); DataScopeUtil.applyDataScope(wrapper, Delivery::getCreatedBy); List list = this.list(wrapper); // 用户可以看到自己创建或自己核验的数据 LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); DataScopeUtil.applyDataScopeWithChecker(wrapper, Delivery::getCreatedBy, Delivery::getCheckBy); List list = this.list(wrapper); ``` ### 编程式权限判断 ```java import com.aiotagro.common.core.utils.SecurityUtil; // 判断是否超级管理员 if (SecurityUtil.isSuperAdmin()) { // 是超级管理员,执行特殊逻辑 } // 判断是否有某个权限 if (SecurityUtil.hasPermission("delivery:add")) { // 有权限,执行操作 } // 获取当前用户ID Integer userId = SecurityUtil.getCurrentUserId(); // 获取当前用户角色ID Integer roleId = SecurityUtil.getRoleId(); // 获取当前用户权限列表 List permissions = SecurityUtil.getPermissions(); ``` --- ## 📊 数据库表结构 ### sys_menu(菜单表) | 字段 | 类型 | 说明 | |------|------|------| | id | int | 主键 | | parent_id | int | 父菜单ID(0=顶级菜单) | | type | tinyint | 类型(1=菜单,2=按钮) | | name | varchar | 菜单名称 | | route_url | varchar | 路由地址 | | page_url | varchar | 组件路径 | | authority | varchar | 权限标识 | | icon | varchar | 图标 | | sort | int | 排序 | | is_delete | tinyint | 是否删除(0=否,1=是) | | create_time | datetime | 创建时间 | | update_time | datetime | 更新时间 | ### sys_role(角色表) | 字段 | 类型 | 说明 | |------|------|------| | id | int | 主键 | | name | varchar | 角色名称 | | description | varchar | 角色描述 | | is_delete | tinyint | 是否删除(0=否,1=是) | | create_time | datetime | 创建时间 | | update_time | datetime | 更新时间 | ### sys_role_menu(角色菜单关联表) | 字段 | 类型 | 说明 | |------|------|------| | id | int | 主键 | | role_id | int | 角色ID | | menu_id | int | 菜单ID | ### sys_user(用户表) | 字段 | 类型 | 说明 | |------|------|------| | id | int | 主键 | | mobile | varchar | 手机号 | | name | varchar | 用户名 | | password | varchar | 密码(MD5加密) | | role_id | int | 角色ID | | user_type | int | 用户类型 | | status | tinyint | 状态(1=启用) | | is_delete | tinyint | 是否删除 | | create_time | datetime | 创建时间 | --- ## 🧪 测试指南 ### 1. 超级管理员测试 **登录账号**:15900000000 / 123456 **验证点**: - ✅ 登录成功后,所有菜单都可见 - ✅ 所有按钮都可见(不受v-hasPermi限制) - ✅ 可以查看所有用户创建的数据 - ✅ 可以进入权限管理模块 - ✅ 可以新增、编辑、删除菜单 - ✅ 可以新增、编辑、删除角色 - ✅ 可以为角色分配权限 ### 2. 普通角色测试 **步骤**: 1. 使用超级管理员登录 2. 进入"操作权限管理" 3. 新增一个测试角色(如"运输管理员") 4. 为该角色分配部分权限(如只分配运送清单相关权限) 5. 在用户管理中创建或修改一个测试用户,指定其角色为"运输管理员" 6. 退出超级管理员,使用测试用户登录 **验证点**: - ✅ 登录后只能看到被分配的菜单 - ✅ 只能看到被分配的按钮(其他按钮被v-hasPermi隐藏) - ✅ 只能看到自己创建的数据(数据权限) - ✅ 无权限的操作会被后端拦截(返回403) ### 3. 权限管理功能测试 #### 菜单权限管理 1. 进入"菜单权限管理"页面 2. 测试新增一个测试菜单 3. 测试编辑菜单信息 4. 测试删除菜单(软删除) 5. 验证菜单树的显示是否正确 #### 操作权限管理 1. 进入"操作权限管理"页面 2. 左侧新增一个测试角色 3. 点击该角色,右侧显示权限树 4. 勾选部分菜单和按钮权限 5. 点击"保存权限" 6. 刷新页面,验证权限是否保存成功 7. 测试编辑和删除角色 --- ## ❗ 常见问题 ### Q1: 执行SQL脚本后,菜单没有出现? **解决方案**: 1. 检查SQL脚本是否执行成功,查看数据库是否有数据 2. 检查用户的角色是否被分配了相应菜单权限 3. 退出重新登录,刷新权限缓存 ### Q2: 按钮被v-hasPermi隐藏了,但我应该有权限? **解决方案**: 1. 检查登录接口返回的permissions字段是否包含该权限 2. 检查Pinia store中是否正确保存了permissions 3. 退出重新登录,刷新权限 4. 如果是超级管理员,检查permissions是否包含"*:*:*" ### Q3: 后端接口返回403,提示无权限? **解决方案**: 1. 检查Controller方法上的@SaCheckPermission注解 2. 检查用户的角色是否被分配了该权限 3. 检查Sa-Token配置是否正确 4. 查看后端日志,确认权限检查的详细信息 ### Q4: 超级管理员看不到其他用户的数据? **解决方案**: 1. 检查Service层是否正确使用了DataScopeUtil 2. 检查SecurityUtil.isSuperAdmin()方法是否正确判断 3. 检查用户的roleId是否为1 ### Q5: 菜单树显示不正常,层级错乱? **解决方案**: 1. 检查sys_menu表的parent_id字段是否正确 2. 检查sort字段,调整排序 3. 检查is_delete字段,确认菜单未被软删除 --- ## 📝 开发文档 ### 新增模块权限的步骤 如果要为一个新功能模块添加权限控制: #### 1. 数据库添加菜单和权限 ```sql -- 添加父菜单 INSERT INTO `sys_menu` (`parent_id`, `type`, `name`, `route_url`, `page_url`, `authority`, `icon`, `sort`, `is_delete`, `create_time`) VALUES (0, 1, '新模块', '/newmodule', null, 'newmodule:view', 'el-icon-setting', 30, 0, NOW()); SET @parent_id = LAST_INSERT_ID(); -- 添加子菜单 INSERT INTO `sys_menu` (`parent_id`, `type`, `name`, `route_url`, `page_url`, `authority`, `icon`, `sort`, `is_delete`, `create_time`) VALUES (@parent_id, 1, '功能页面', '/newmodule/function', 'newmodule/function', 'newmodule:function:view', null, 1, 0, NOW()); SET @function_id = LAST_INSERT_ID(); -- 添加按钮权限 INSERT INTO `sys_menu` (`parent_id`, `type`, `name`, `authority`, `sort`, `is_delete`, `create_time`) VALUES (@function_id, 2, '新增', 'newmodule:function:add', 1, 0, NOW()), (@function_id, 2, '编辑', 'newmodule:function:edit', 2, 0, NOW()), (@function_id, 2, '删除', 'newmodule:function:delete', 3, 0, NOW()); -- 为超级管理员分配新权限 INSERT INTO `sys_role_menu` (`role_id`, `menu_id`) SELECT 1, id FROM `sys_menu` WHERE `authority` LIKE 'newmodule:%' AND `is_delete` = 0; ``` #### 2. 后端Controller添加权限注解 ```java @RestController @RequestMapping("/newmodule") public class NewModuleController { @SaCheckPermission("newmodule:function:list") @PostMapping("/list") public AjaxResult list(@RequestBody QueryDto dto) { // ... } @SaCheckPermission("newmodule:function:add") @PostMapping("/add") public AjaxResult add(@RequestBody AddDto dto) { // ... } } ``` #### 3. 前端按钮添加权限指令 ```vue 新增 ``` --- ## 🎉 功能清单 本次开发完成的文件清单: ### 后端文件 - ✅ `RoleConstants.java` - 角色常量类 - ✅ `SecurityUtil.java` - 安全工具类(扩展) - ✅ `DataScopeUtil.java` - 数据权限工具类 - ✅ `SysMenuController.java` - 菜单权限管理Controller - ✅ `SysRoleController.java` - 角色管理Controller(扩展) - ✅ `LoginServiceImpl.java` - 登录Service(扩展,存储权限信息) - ✅ `DeliveryController.java` - 运送清单Controller(添加权限注解) - ✅ `DeliveryServiceImpl.java` - 运送清单Service(添加数据权限) - ✅ `DeliveryCreateDto.java` - 运送清单创建DTO ### 前端文件 - ✅ `permission.js` - 权限管理API接口 - ✅ `menuPermission.vue` - 菜单权限管理页面 - ✅ `operationPermission.vue` - 操作权限管理页面 - ✅ `createDeliveryDialog.vue` - 新增运送清单对话框 - ✅ `user.ts` - 用户Store(扩展,添加权限判断) - ✅ `login.vue` - 登录页(扩展,保存权限) - ✅ `loadingOrder.vue` - 运送清单列表(添加权限控制) - ✅ `shipping.js` - 运送清单API(扩展) ### 数据库文件 - ✅ `权限管理功能初始化SQL.sql` - 数据库初始化脚本 ### 文档文件 - ✅ `权限管理和运送清单新增功能实施计划.md` - 实施计划文档 - ✅ `权限管理功能使用说明.md` - 本使用说明文档 --- ## 📞 技术支持 如有问题,请检查: 1. 后端日志:查看权限验证相关错误 2. 浏览器控制台:查看前端请求和权限判断 3. 数据库数据:确认菜单、角色、权限数据是否正确 4. Sa-Token文档:https://sa-token.cc/ --- **祝使用愉快!** 🎊