Files
MrleeAdmin/backend/app/service/admin/system/RoleMenuService.php
T
2026-08-31 11:33:59 +08:00

181 lines
6.6 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
/**
*+------------------
* madong
*+------------------
* Copyright (c) https://gitee.com/motion-code All rights reserved.
*+------------------
* Author: Mr. April (405784684@qq.com)
*+------------------
* Official Website: http://www.madong.tech
*/
namespace app\service\admin\system;
use app\dao\system\RoleMenuDao;
use core\base\BaseService;
use core\exception\handler\AdminException;
use support\Container;
/**
* @method getColumn(int[]|string[] $array, string $string)
*/
class RoleMenuService extends BaseService
{
public function __construct(RoleMenuDao $dao)
{
$this->dao = $dao;
}
/**
* 更新设置角色权限
*
* @param $data
*
* @throws \core\exception\handler\AdminException
*/
// public function save($data): void
// {
// try {
// $this->transaction(function () use ($data) {
// $roleId = $data['role_id'] ?? '';
// $newPermissions = $data['menu_id'] ?? [];
// if (empty($roleId)) {
// throw new AdminException('参数错误缺少role_id', ['errorCode' => -1]);
// }
//
// // 1. 获取角色模型(确保角色存在)
// /** @var SysRoleService $roleService */
// $roleService = Container::make(SysRoleService::class);
// $roleModel = $roleService->get($roleId);
// if (!$roleModel) {
// throw new AdminException('角色不存在', ['errorCode' => -1]);
// }
//
// // 2. 同步 role_menu 关联关系(自动处理新增/删除,无需手动计算差异)
// // 假设 SysRole 模型定义了 roleMenus 关联(hasMany: SysRoleMenu)
// $roleModel->menus()->sync($newPermissions);
//
// // 3. 获取同步后的菜单ID(从关联关系中直接获取,确保数据一致性)
// $syncedMenuIds = $roleModel->menus()->pluck('menu_id')->toArray();
//
// // 4. 构建 Casbin 策略(基于同步后的最新菜单权限)
// $casbinRoleId = PolicyPrefix::ROLE->value . $roleId;
// $domain = '*';
//
// // 4.1 获取菜单详情(用于构建策略)
// /** @var SysMenuService $menuService */
// $menuService = Container::make(SysMenuService::class);
// $menuDetails = $menuService->selectList(['id' => $syncedMenuIds], '*', 0, 0, 'sort', [], true)->toArray();
//
// $incomingPolicies = [];
// foreach ($menuDetails as $menu) {
// if (empty($menu['code'])) continue;
// $incomingPolicies[] = [
// $casbinRoleId, // sub (角色标识)
// $domain, // dom (租户域)
// $menu['code'], // obj (权限码)
// '*', // act (操作类型)
// $menu['methods'], // method (HTTP方法)
// PolicyPrefix::MENU->value . $menu['id'], // trace_id
// ];
// }
//
// // 4.2 更新 Casbin 策略
// $currentCasbinPolicies = Permission::getImplicitResourcesForUser($casbinRoleId, $domain);
// /** @var SysCasbinService $casbinService */
// $casbinService = Container::make(SysCasbinService::class);
// $casbinService->updateCasbinPolicies($currentCasbinPolicies, $incomingPolicies);
//
// });
// } catch (\Throwable $e) {
// throw new AdminException($e->getMessage());
// }
// }
/**
* 更新设置角色权限(含事务封装)
*
* @param $data
*
* @throws \core\exception\handler\AdminException
*/
public function save($data): void
{
try {
$this->transaction(function () use ($data) {
$this->saveWithoutTransaction($data);
});
} catch (\Throwable $e) {
throw new AdminException($e->getMessage());
}
}
/**
* 无事务版本:核心业务逻辑(供内部/外部事务复用)
*
* @param array $data
*
* @throws \core\exception\handler\AdminException
*/
public function saveWithoutTransaction(array $data): void
{
try {
$roleId = $data['role_id'] ?? '';
$newPermissions = $data['menu_id'] ?? [];
if (empty($roleId)) {
throw new AdminException('参数错误缺少role_id');
}
// 1. 获取角色模型(确保角色存在)
/** @var RoleService $roleService */
$roleService = Container::make(RoleService::class);
$roleModel = $roleService->get($roleId);
if (!$roleModel) {
throw new AdminException('角色不存在');
}
// 2. 同步 role_menu 关联关系(自动处理新增/删除,无需手动计算差异)
$roleModel->menus()->sync($newPermissions);
// 3. 清理相关用户的权限缓存
$this->clearUserPermissionCacheByRole($roleId);
} catch (\Throwable $e) {
throw new AdminException($e->getMessage());
}
}
/**
* 清理拥有此角色的用户的权限缓存
*
* @param string|int $roleId 角色ID
*/
private function clearUserPermissionCacheByRole(string|int $roleId): void
{
try {
// 获取拥有此角色的所有用户
/** @var \app\service\admin\system\AdminRoleService $adminRoleService */
$adminRoleService = Container::make(\app\service\admin\system\AdminRoleService::class);
// 获取拥有此角色的用户ID列表
$userIds = \app\model\system\AdminRole::where('role_id', $roleId)
->pluck('admin_id')
->toArray();
if (!empty($userIds)) {
// 清理这些用户的权限缓存
$currentUser = Container::make(\app\adminapi\CurrentUser::class);
foreach ($userIds as $userId) {
$currentUser->clearCache($userId);
}
}
} catch (\Throwable $e) {
// 缓存清理失败不影响主要业务,记录日志即可
\core\logger\Logger::error("清理角色{$roleId}的用户权限缓存失败: " . $e->getMessage());
}
}
}