2025-07-11 18:01:23 +08:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace app\common\logic;
|
|
|
|
|
|
|
|
|
|
use app\common\model\User;
|
2025-07-14 14:24:03 +08:00
|
|
|
use app\common\model\Resource;
|
2025-07-11 18:01:23 +08:00
|
|
|
|
|
|
|
|
class PermLogic
|
|
|
|
|
{
|
|
|
|
|
/**
|
|
|
|
|
* 获取用户所有资源(合并角色+直接分配)
|
|
|
|
|
*/
|
2025-07-14 14:24:03 +08:00
|
|
|
// public function getUserResources(int $userId)
|
|
|
|
|
// {
|
|
|
|
|
// $user = User::with(['roles.resources', 'resources'])->find($userId);
|
|
|
|
|
// if (!$user) {
|
|
|
|
|
// return collect();
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// $all = collect();
|
|
|
|
|
// foreach ($user->roles as $role) {
|
|
|
|
|
// $all = $all->merge($role->resources);
|
|
|
|
|
// }
|
|
|
|
|
// $all = $all->merge($user->resources);
|
|
|
|
|
// return $all->unique('id')->values();
|
|
|
|
|
// }
|
|
|
|
|
/**
|
|
|
|
|
* 获取用户所有资源(合并角色+直接分配),并加入公共菜单
|
|
|
|
|
*/
|
2025-07-11 18:01:23 +08:00
|
|
|
public function getUserResources(int $userId)
|
|
|
|
|
{
|
2025-07-14 14:24:03 +08:00
|
|
|
// 获取用户及其关联角色资源和直接分配的资源
|
2025-07-11 18:01:23 +08:00
|
|
|
$user = User::with(['roles.resources', 'resources'])->find($userId);
|
2025-07-14 14:24:03 +08:00
|
|
|
|
2025-07-11 18:01:23 +08:00
|
|
|
if (!$user) {
|
|
|
|
|
return collect();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$all = collect();
|
2025-07-14 14:24:03 +08:00
|
|
|
|
|
|
|
|
// 合并角色资源,排除不需要权限认证的资源
|
2025-07-11 18:01:23 +08:00
|
|
|
foreach ($user->roles as $role) {
|
2025-07-14 14:24:03 +08:00
|
|
|
$all = $all->merge(
|
|
|
|
|
$role->resources->filter(function ($resource) {
|
|
|
|
|
// 只保留需要权限认证的资源(或公共资源)
|
|
|
|
|
return !$resource->no_auth;
|
|
|
|
|
})
|
|
|
|
|
);
|
2025-07-11 18:01:23 +08:00
|
|
|
}
|
2025-07-14 14:24:03 +08:00
|
|
|
|
|
|
|
|
// 合并用户直接分配的资源,排除不需要权限认证的资源
|
|
|
|
|
$all = $all->merge(
|
|
|
|
|
$user->resources->filter(function ($resource) {
|
|
|
|
|
// 只保留需要权限认证的资源(或公共资源)
|
|
|
|
|
return !$resource->no_auth;
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// 加入公共菜单,公共菜单不管是否授权,所有人都能访问
|
|
|
|
|
$publicResources = Resource::where('no_auth', 1)->get(); // 获取所有公共菜单
|
|
|
|
|
$all = $all->merge($publicResources);
|
|
|
|
|
|
|
|
|
|
// 返回唯一的资源列表,并按 id 排序
|
2025-07-11 18:01:23 +08:00
|
|
|
return $all->unique('id')->values();
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-14 14:24:03 +08:00
|
|
|
|
2025-07-11 18:01:23 +08:00
|
|
|
/**
|
|
|
|
|
* 构建目录/菜单树,节点包含权限与打开方式,拼接完整路径,并对子级菜单component处理
|
|
|
|
|
* @param \Illuminate\Support\Collection $resources
|
|
|
|
|
* @param int $parentId
|
|
|
|
|
* @param string $parentPath
|
|
|
|
|
* @return array
|
|
|
|
|
*/
|
|
|
|
|
public function buildTree($resources, int $parentId = 0, string $parentPath = ''): array
|
|
|
|
|
{
|
|
|
|
|
$tree = [];
|
|
|
|
|
foreach ($resources as $node) {
|
|
|
|
|
if ($node->parent_id !== $parentId) continue;
|
|
|
|
|
|
|
|
|
|
// 拼接完整路径
|
|
|
|
|
$currentPath = $parentPath;
|
|
|
|
|
if ($currentPath && substr($currentPath, -1) === '/') {
|
|
|
|
|
$currentPath = rtrim($currentPath, '/');
|
|
|
|
|
}
|
|
|
|
|
if (!empty($node->url)) {
|
|
|
|
|
if (!$currentPath) {
|
|
|
|
|
$currentPath = $node->url;
|
|
|
|
|
} else {
|
|
|
|
|
$url = ltrim($node->url, '/');
|
|
|
|
|
$currentPath = $currentPath . '/' . $url;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 子节点递归
|
|
|
|
|
$children = [];
|
|
|
|
|
if ($node->type === 'directory') {
|
|
|
|
|
$children = $this->buildTree($resources, $node->id, $currentPath);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 权限
|
|
|
|
|
$authList = $resources
|
|
|
|
|
->filter(fn($r) => $r->type === 'permission' && $r->parent_id === $node->id)
|
|
|
|
|
->map(fn($r) => [
|
|
|
|
|
'id' => $r->id,
|
|
|
|
|
'title' => $r->name,
|
|
|
|
|
'auth_mark' => $r->code,
|
|
|
|
|
])->values()->all();
|
|
|
|
|
|
|
|
|
|
// 判断是否有子级菜单(非权限)
|
|
|
|
|
$hasChildrenMenu = collect($resources)->where('parent_id', $node->id)
|
|
|
|
|
->whereIn('type', ['directory', 'menu'])->isNotEmpty();
|
|
|
|
|
|
|
|
|
|
// component 字段规则:
|
|
|
|
|
// 1. 存在子菜单,固定 '/index/index'
|
|
|
|
|
// 2. 否则为当前完整路径(或其它你想要的)
|
|
|
|
|
$componentValue = $hasChildrenMenu ? '/index/index' : $currentPath;
|
|
|
|
|
|
|
|
|
|
$tree[] = [
|
|
|
|
|
'id' => $node->id,
|
|
|
|
|
'name' => $node->name,
|
|
|
|
|
'path' => $node->url,
|
|
|
|
|
'component' => $componentValue,
|
|
|
|
|
'meta' => [
|
|
|
|
|
'title' => $node->name,
|
|
|
|
|
'icon' => $node->icon,
|
|
|
|
|
'keepAlive' => true,
|
|
|
|
|
'authList' => $authList,
|
|
|
|
|
'openType' => $node->open_type,
|
|
|
|
|
],
|
|
|
|
|
'children' => $children,
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
return $tree;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取用户所有权限code
|
|
|
|
|
*/
|
|
|
|
|
public function getPermissionCodes(int $userId): array
|
|
|
|
|
{
|
|
|
|
|
$resources = $this->getUserResources($userId);
|
|
|
|
|
return $resources
|
|
|
|
|
->filter(fn($res) => $res->type === 'permission')
|
|
|
|
|
->pluck('code')
|
|
|
|
|
->unique()
|
|
|
|
|
->values()
|
|
|
|
|
->all();
|
|
|
|
|
}
|
|
|
|
|
}
|