5.3 KiB
5.3 KiB
6.2 角色管理
:::tip 概述
角色管理是 RBAC 权限体系的核心,通过角色关联菜单实现权限分配。RoleService 继承 BaseTenantService(角色按租户隔离),并提供菜单授权、权限缓存清理等专用能力。
:::
模块特点
| 特性 | 说明 |
|---|---|
| 基类 | BaseTenantService(租户隔离,角色含 tenant_id) |
| 关联 | 与 Menu 多对多(通过 RoleMenu 中间表) |
| 唯一校验 | code 按租户分组唯一(['code','tenant_id']) |
| 数据权限 | 范围由 HasDataScope 解析(当前表无 data_scope 字段,默认全部数据) |
| 缓存联动 | 菜单授权后 clearRolePermissions() 清除该角色权限缓存(配合 RoleMenuObserver) |
套餐化角色预置
系统内置三套租户角色模板,用于按套餐等级快速授权:
| 角色名称 | 定位 | 菜单范围 |
|---|---|---|
| 租户-标准版 | 基础功能 | 核心业务模块 |
| 租户-专业版 | 进阶功能 | 核心 + 高级模块 |
| 租户-旗舰版 | 全功能 | 全部菜单(最全) |
创建租户后,通过「角色管理 → 授权菜单」为对应角色分配菜单权限。详见 6.13 租户管理。
API 接口
| 方法 | 路径 | 权限码 | 说明 |
|---|---|---|---|
| GET | /api/role/page |
sys:role:page | 分页列表 |
| GET | /api/role/list |
sys:role:list | 全量列表 |
| GET | /api/role/detail/{id} |
sys:role:detail | 详情 |
| POST | /api/role/add |
sys:role:add | 新增 |
| PUT | /api/role/update |
sys:role:update | 修改 |
| DELETE | /api/role/delete/{id} |
sys:role:delete | 删除 |
| DELETE | /api/role/batchDelete |
sys:role:batchDelete | 批量删除 |
| GET | /api/role/menu/list/{id} |
— | 获取角色菜单(含选中状态) |
| POST | /api/role/menu/save |
sys:role:savePermission | 保存角色菜单 |
Service 属性配置
// app/Services/RoleService.php(来自项目实际代码)
class RoleService extends BaseTenantService
{
// HasDataScope(数据权限 + 租户隔离)由 BaseTenantService 继承提供
use HasCrudOperations, HasQueryScopes, HasUniqueCheck;
protected string $modelClass = Role::class;
protected array $pageLikeFields = ['name', 'code'];
protected array $pageEqFields = [];
protected array $pageOrderBy = ['field' => 'sort', 'type' => 'asc'];
// code 在同一租户内唯一
protected array $uniqueFields = [['code', 'tenant_id']];
}
菜单权限分配
专用方法
| 方法 | 说明 |
|---|---|
getMenuListWithChecked($roleId) |
获取平铺菜单列表(id / name / parent_id / checked),供前端授权弹窗回显 |
saveMenus($roleId, $menuIds) |
全量覆盖式保存角色菜单(事务保护) |
getMenuIds($roleId) |
获取角色已有菜单 ID 数组 |
clearRolePermissions($roleId) |
清除该角色的权限缓存(授权即时生效) |
保存流程(saveMenus)
saveMenus($roleId, $menuIds)
│
▼
DB::transaction {
1. 删除该角色原有全部 role_menu 关联(全量覆盖)
2. 遍历新菜单 ID,组装关联记录(含审计字段)
3. 批量写入 role_menu
4. clearRolePermissions() 清除该角色权限缓存
}
│ 任一步骤异常 → 自动回滚
▼
返回成功
:::tip 授权即时生效
保存成功即清除该角色在 Redis(perms:{uid})与 Laravel Cache 中的权限缓存,拥有该角色的用户下一次请求即按新权限校验,无需重新登录。
:::
控制器(menuSave)
// app/Http/Controllers/Api/RoleController.php(行为说明)
#[OperationLog('角色管理-保存菜单权限', OperationLog::TYPE_AUTHORIZE, '保存角色ID:{roleId}的菜单权限')]
#[Permission('sys:role:savePermission', '授权角色菜单')]
public function menuSave(): JsonResponse
{
$data = $this->getJsonBody();
$roleId = $data['roleId'] ?? 0;
$menuIds = $data['menuIds'] ?? [];
if (empty($roleId)) {
return $this->fail('缺少roleId参数');
}
$this->roleService->saveMenus($roleId, $menuIds);
return $this->success(null, '保存成功');
}
请求参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
roleId |
int | 是 | 角色 ID |
menuIds |
array | 是 | 菜单 ID 数组(含目录/菜单/按钮) |
删除保护(beforeDelete / afterDelete 钩子)
// 删除前:校验业务约束(如角色已被用户使用时阻止删除)
protected function beforeDelete(int $id): void
{
// 检查 user_role 是否存在关联 → 存在则抛 BizException 阻止删除
}
// 删除后:清理 role_menu 关联 + 清除权限缓存
protected function afterDelete(int $id): void
{
RoleMenu::where('role_id', $id)->delete();
$this->clearRolePermissions($id);
}
数据权限
数据范围语义由 HasDataScope 解析(详见 5.9 数据权限):
| 值 | 范围 |
|---|---|
| 1 | 全部数据(当前默认) |
| 2 | 本部门数据 |
| 3 | 仅本人数据(无角色用户默认) |
:::info 当前版本现状
laravel_role 表不包含 data_scope 字段(按当前表设计),getRoleDataScope() 读取缺省为 1——角色一律按全部数据处理。
:::