16 KiB
16 KiB
权限管理功能使用说明
📋 功能概述
本次开发完成了完整的权限管理系统,包括:
- 菜单权限管理 - 管理系统菜单树和菜单项
- 操作权限管理 - 为不同角色分配菜单和按钮操作权限
- 超级管理员 - 15900000000 账号拥有所有权限
🗂️ 部署步骤
第一步:执行数据库初始化脚本
在数据库中执行 权限管理功能初始化SQL.sql 文件,该脚本会:
- ✅ 创建"权限管理"父菜单
- ✅ 创建"菜单权限管理"子菜单
- ✅ 创建"操作权限管理"子菜单
- ✅ 为这些菜单添加对应的按钮权限
- ✅ 创建或更新超级管理员角色(ID=1)
- ✅ 设置 15900000000 为超级管理员账号
- ✅ 为超级管理员分配所有菜单权限
- ✅ 为运送清单功能添加完整的权限点
执行方式:
-- 在MySQL客户端或管理工具中执行
source /path/to/权限管理功能初始化SQL.sql;
-- 或直接复制粘贴SQL内容执行
第二步:重新编译并启动后端
# 进入后端项目根目录
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
第三步:启动前端
# 进入前端项目目录
cd c:\cattleTransport\pc-cattle-transportation
# 安装依赖(首次或有新依赖时)
npm install
# 启动开发服务器
npm run dev
前端访问地址:http://localhost:8080
👤 超级管理员账号
登录信息
- 账号:
15900000000 - 密码:
123456(如果是SQL脚本新创建的账号) - 角色:超级管理员(roleId=1)
- 权限:拥有系统所有权限(::*)
特权说明
超级管理员具有以下特权:
- ✅ 绕过所有权限检查 - 自动拥有所有操作权限
- ✅ 查看所有数据 - 不受数据权限限制,可以看到所有用户创建的数据
- ✅ 管理权限 - 可以为其他角色分配权限
- ✅ 管理菜单 - 可以增删改菜单和按钮权限
🎯 功能使用指南
1. 菜单权限管理
访问路径:系统主菜单 → 权限管理 → 菜单权限管理
功能列表:
- ✅ 查看菜单树 - 以树形结构展示所有系统菜单
- ✅ 新增菜单 - 添加新的菜单或按钮权限
- ✅ 编辑菜单 - 修改菜单信息
- ✅ 删除菜单 - 软删除菜单(is_delete=1)
字段说明:
| 字段 | 说明 | 示例 |
|---|---|---|
| 菜单名称 | 显示在系统中的菜单名称 | 权限管理 |
| 菜单类型 | 1=菜单(页面),2=按钮(操作) | 1 |
| 路由地址 | 前端路由路径 | /permission/menu |
| 组件路径 | Vue组件路径 | permission/menuPermission |
| 权限标识 | 后端权限检查标识 | permission:menu:view |
| 图标 | Element Plus图标名称 | el-icon-lock |
| 排序 | 菜单显示顺序 | 1 |
操作步骤:
- 点击"新增菜单"按钮
- 选择上级菜单(可选,默认为顶级菜单)
- 选择菜单类型(菜单/按钮)
- 填写必填信息:菜单名称、权限标识
- 如果是菜单类型,还需填写路由地址和组件路径
- 设置排序号
- 点击"确定"保存
2. 操作权限管理
访问路径:系统主菜单 → 权限管理 → 操作权限管理
功能列表:
- ✅ 角色管理 - 新增、编辑、删除角色
- ✅ 权限分配 - 为角色分配菜单和按钮权限
- ✅ 查看权限 - 查看角色当前拥有的权限
左侧:角色列表
- 显示所有系统角色
- 点击角色行可查看和编辑该角色的权限
- 可以新增、编辑、删除角色(超级管理员角色不可删除)
右侧:权限树
- 以树形结构显示所有菜单和按钮权限
- 勾选表示该角色拥有该权限
- 支持级联选择(选中父菜单会自动选中子项)
操作步骤:
新增角色
- 点击左侧"新增角色"按钮
- 输入角色名称和描述
- 点击"确定"保存
为角色分配权限
- 在左侧角色列表中点击选中某个角色
- 右侧会显示权限树
- 勾选该角色需要的菜单和按钮权限
- 点击右上角"保存权限"按钮
🔐 权限标识规范
系统采用统一的权限标识命名规范:模块:资源:操作
示例
| 权限标识 | 说明 | 对应功能 |
|---|---|---|
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 指令控制按钮的显示/隐藏:
<!-- 单个权限 -->
<el-button v-hasPermi="['delivery:add']" @click="handleAdd">
新增
</el-button>
<!-- 多个权限(满足其一即可) -->
<el-button v-hasPermi="['delivery:edit', 'delivery:view']" @click="handleEdit">
编辑
</el-button>
角色级权限指令
使用 v-hasRole 指令控制基于角色的显示:
<el-button v-hasRole="['admin']" @click="handleAdmin">
管理员功能
</el-button>
编程式权限判断
import { useUserStore } from '@/store/user';
const userStore = useUserStore();
// 判断是否有某个权限
if (userStore.hasPermission('delivery:add')) {
// 有权限,执行操作
}
// 判断是否有某个角色
if (userStore.hasRole('admin')) {
// 有角色,执行操作
}
🛡️ 后端权限控制
接口级权限注解
在Controller方法上使用 @SaCheckPermission 注解:
@RestController
@RequestMapping("/delivery")
public class DeliveryController {
// 单个权限
@SaCheckPermission("delivery:list")
@PostMapping("/pageQuery")
public PageResultResponse<Delivery> pageQuery(@RequestBody DeliveryQueryDto dto) {
// ...
}
// 多个权限(满足其一即可)
@SaCheckPermission(value = {"delivery:add", "delivery:create"}, mode = SaMode.OR)
@PostMapping("/create")
public AjaxResult create(@RequestBody DeliveryCreateDto dto) {
// ...
}
}
数据权限控制
使用 DataScopeUtil 工具类进行数据权限过滤:
// 普通用户只能看自己创建的数据,超级管理员可以看所有数据
LambdaQueryWrapper<Delivery> wrapper = new LambdaQueryWrapper<>();
DataScopeUtil.applyDataScope(wrapper, Delivery::getCreatedBy);
List<Delivery> list = this.list(wrapper);
// 用户可以看到自己创建或自己核验的数据
LambdaQueryWrapper<Delivery> wrapper = new LambdaQueryWrapper<>();
DataScopeUtil.applyDataScopeWithChecker(wrapper, Delivery::getCreatedBy, Delivery::getCheckBy);
List<Delivery> list = this.list(wrapper);
编程式权限判断
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<String> 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. 普通角色测试
步骤:
- 使用超级管理员登录
- 进入"操作权限管理"
- 新增一个测试角色(如"运输管理员")
- 为该角色分配部分权限(如只分配运送清单相关权限)
- 在用户管理中创建或修改一个测试用户,指定其角色为"运输管理员"
- 退出超级管理员,使用测试用户登录
验证点:
- ✅ 登录后只能看到被分配的菜单
- ✅ 只能看到被分配的按钮(其他按钮被v-hasPermi隐藏)
- ✅ 只能看到自己创建的数据(数据权限)
- ✅ 无权限的操作会被后端拦截(返回403)
3. 权限管理功能测试
菜单权限管理
- 进入"菜单权限管理"页面
- 测试新增一个测试菜单
- 测试编辑菜单信息
- 测试删除菜单(软删除)
- 验证菜单树的显示是否正确
操作权限管理
- 进入"操作权限管理"页面
- 左侧新增一个测试角色
- 点击该角色,右侧显示权限树
- 勾选部分菜单和按钮权限
- 点击"保存权限"
- 刷新页面,验证权限是否保存成功
- 测试编辑和删除角色
❗ 常见问题
Q1: 执行SQL脚本后,菜单没有出现?
解决方案:
- 检查SQL脚本是否执行成功,查看数据库是否有数据
- 检查用户的角色是否被分配了相应菜单权限
- 退出重新登录,刷新权限缓存
Q2: 按钮被v-hasPermi隐藏了,但我应该有权限?
解决方案:
- 检查登录接口返回的permissions字段是否包含该权限
- 检查Pinia store中是否正确保存了permissions
- 退出重新登录,刷新权限
- 如果是超级管理员,检查permissions是否包含"::*"
Q3: 后端接口返回403,提示无权限?
解决方案:
- 检查Controller方法上的@SaCheckPermission注解
- 检查用户的角色是否被分配了该权限
- 检查Sa-Token配置是否正确
- 查看后端日志,确认权限检查的详细信息
Q4: 超级管理员看不到其他用户的数据?
解决方案:
- 检查Service层是否正确使用了DataScopeUtil
- 检查SecurityUtil.isSuperAdmin()方法是否正确判断
- 检查用户的roleId是否为1
Q5: 菜单树显示不正常,层级错乱?
解决方案:
- 检查sys_menu表的parent_id字段是否正确
- 检查sort字段,调整排序
- 检查is_delete字段,确认菜单未被软删除
📝 开发文档
新增模块权限的步骤
如果要为一个新功能模块添加权限控制:
1. 数据库添加菜单和权限
-- 添加父菜单
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添加权限注解
@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. 前端按钮添加权限指令
<el-button v-hasPermi="['newmodule:function:add']" @click="handleAdd">
新增
</el-button>
🎉 功能清单
本次开发完成的文件清单:
后端文件
- ✅
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- 本使用说明文档
📞 技术支持
如有问题,请检查:
- 后端日志:查看权限验证相关错误
- 浏览器控制台:查看前端请求和权限判断
- 数据库数据:确认菜单、角色、权限数据是否正确
- Sa-Token文档:https://sa-token.cc/
祝使用愉快! 🎊