Files
lgp-admin-plus-api/app/Service/RoleService.php
LQ bcf54c2727 初始化
缺陷:主题配色需要优化整体的同风格
2026-08-14 23:21:21 +08:00

222 lines
6.3 KiB
PHP
Executable File
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
namespace App\Service;
use App\BaseApp\BaseService;
use App\Models\RoleMenuRelationModel;
use App\Models\RoleModel;
use App\Service\common\RedisService;
use Exception;
use Illuminate\Support\Facades\DB;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
/**
* 角色服务类
*/
class RoleService extends BaseService
{
public function __construct()
{
parent::__construct();
$this->model = RoleModel::class;
$this->selectField = ['id', 'name', 'value', 'pid', 'desc', 'status', 'color', 'created_at'];
$this->queryField = ['name' => 'like', 'value' => 'like', 'pid' => '=', 'status' => '='];
$this->orderBy = ['name' => 'id', 'sort' => 'asc'];
}
/**
* 获取列表
* @return array
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function list(): array
{
return $this->getPageList();
}
/**
* 获取下拉列表
* @return mixed
*/
public function option(): mixed
{
return $this->getOption();
}
/**
* 根据角色ID获取菜单ID
* @param $roleId
* @return mixed
* @throws Exception
*/
public function getMenuIdsByRoleIds($roleId): mixed
{
if (empty($roleId)) $this->utils->errorThrow('请选择角色');
return RoleMenuRelationModel::where('role_id', $roleId)->pluck('menu_id');
}
/**
* 保存角色菜单关系
* @param $roleId
* @param $menuIds
* @return true
* @throws Exception
*/
public function saveRoleMenu($roleId, $menuIds): true
{
$menus = array_unique($menuIds);
// 查询角色当前绑定的菜单
$bindResources = RoleMenuRelationModel::where('role_id', $roleId)->pluck('menu_id');
// 开启事务
DB::beginTransaction();
try {
// 提取查询到的菜单ID
$existingResourceIds = $bindResources->toArray();
// 传值中不存在的菜单ID从数据库中删除
$menusToDelete = array_diff($existingResourceIds, $menus);
if (!empty($menusToDelete)) {
$delBindResources = RoleMenuRelationModel::where('role_id', $roleId)->whereIn('menu_id', array_values($menusToDelete))->delete();
if (!$delBindResources) {
$this->utils->errorThrow('更新失败!');
}
}
// 传值中存在但数据库中不存在的菜单ID新增到数据库
$menusToAdd = array_diff($menus, $existingResourceIds);
$insertData = [];
foreach ($menusToAdd as $menusId) {
$insertData[] = [
'role_id' => $roleId,
'menu_id' => $menusId,
'created_at' => time()
];
}
// 只取消勾选、没有新增时 $insertData 为空insert([]) 返回 false 会误判成失败
if (!empty($insertData) && !RoleMenuRelationModel::insert($insertData)) {
$this->utils->errorThrow('更新失败!');
}
DB::commit();
$this->flushRoleCache((int) $roleId);
} catch (\Exception $e) {
DB::rollBack();
$this->utils->errorThrow($e->getMessage());
}
return true;
}
/**
* 接口授权树
*/
public function endpointTree(): array
{
return PermissionService::getInstance()->endpointTree();
}
/**
* 角色已授权的接口 id
* @throws Exception
*/
public function getEndpointIdsByRoleId($roleId): array
{
if (empty($roleId)) $this->utils->errorThrow('请选择角色');
return PermissionService::getInstance()->grantedIds((int) $roleId);
}
/**
* 保存角色接口授权
* @throws Exception
*/
public function saveRoleEndpoint(int $roleId, array $endpointIds): bool
{
if ($roleId <= 0) $this->utils->errorThrow('请选择角色');
if ($roleId === 1) $this->utils->errorThrow('超级管理员默认拥有全部接口权限,无需授权');
return PermissionService::getInstance()->grant($roleId, $endpointIds);
}
/**
* 启用 / 停用角色
*
* 停用后该角色下的账号仍能登录但权限为空,所以要顺手清掉权限与菜单缓存
* @throws Exception
*/
public function status($id, $status): mixed
{
$id = (int) $id;
if ($id === 1) $this->utils->errorThrow('超级管理员角色禁止停用');
$result = $this->save($id, ['status' => (int) $status]);
$this->flushRoleCache($id);
return $result;
}
/**
* 获取数据详情
* @param $id
* @return mixed
* @throws Exception
*/
public function detail($id): mixed
{
return $this->getDetail($id);
}
/**
* 新增数据
* @param $params
* @return mixed
*/
public function create($params): mixed
{
return $this->insert($params);
}
/**
* 编辑数据
* @param $id
* @param $params
* @return mixed
* @throws Exception
*/
public function update($id, $params): mixed
{
return $this->save($id, $params);
}
/**
* 删除数据
* @param $id
* @return mixed|true
* @throws Exception
*/
public function delete($id): mixed
{
// BaseController::delete 传入的是 ids 数组,直接 in_array($id,[1,2]) 会因「数组与标量比较恒 false」绕过保护
// 这里统一归一为数组后用 array_intersect 判断是否命中内置角色1超管 / 2默认
$ids = is_array($id) ? $id : [$id];
if (array_intersect(array_map('intval', $ids), [1, 2])) {
$this->utils->errorThrow('管理员角色禁止删除');
}
$result = $this->del($id);
foreach ($ids as $roleId) {
$this->flushRoleCache((int) $roleId);
}
return $result;
}
/**
* 角色的菜单与权限都按角色缓存,改动后必须一起清,否则要等 1 小时才生效
*/
private function flushRoleCache(int $roleId): void
{
RedisService::getInstance()->init(config('nl.redis.menu_key'))->del($roleId);
PermissionService::getInstance()->clear($roleId);
}
}