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-25 18:10:11 +08:00
|
|
|
use app\common\model\Systems;
|
2025-07-11 18:01:23 +08:00
|
|
|
|
|
|
|
|
class PermLogic
|
|
|
|
|
{
|
|
|
|
|
/**
|
2025-07-14 18:55:59 +08:00
|
|
|
* 获取用户所有资源(合并角色+直接分配),并加入公共菜单,排序按sort字段
|
2025-07-14 14:24:03 +08:00
|
|
|
*/
|
2025-07-25 18:10:11 +08:00
|
|
|
public function getUserResources(int $userId, string $systemCode)
|
2025-07-11 18:01:23 +08:00
|
|
|
{
|
2025-07-25 18:10:11 +08:00
|
|
|
$system = Systems::where('code', $systemCode)->first();
|
|
|
|
|
|
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-08-14 20:08:57 +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(
|
2025-08-14 20:08:57 +08:00
|
|
|
// 过滤当前角色的资源列表
|
2025-07-25 18:10:11 +08:00
|
|
|
$role->resources->filter(function ($resource) use($system) {
|
2025-08-14 20:08:57 +08:00
|
|
|
// 资源过滤条件:
|
|
|
|
|
// 1. !$resource->no_auth:资源需要权限认证(排除公共资源)
|
|
|
|
|
// 2. 系统匹配条件:
|
|
|
|
|
// - $system->id == $resource->system_id:资源属于当前系统
|
|
|
|
|
// - $resource->system_id == 0:资源为全局公共资源(所有系统可用)
|
2025-07-29 11:12:47 +08:00
|
|
|
return !$resource->no_auth && ($system->id == $resource->system_id || $resource->system_id == 0);
|
2025-07-14 14:24:03 +08:00
|
|
|
})
|
|
|
|
|
);
|
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;
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// 加入公共菜单,公共菜单不管是否授权,所有人都能访问
|
2025-07-14 18:55:59 +08:00
|
|
|
$publicResources = Resource::where('no_auth', 1)
|
|
|
|
|
->orderBy('sort', 'asc') // 按 sort 字段升序排序
|
|
|
|
|
->get();
|
|
|
|
|
|
2025-07-14 19:01:42 +08:00
|
|
|
// 合并所有公共资源
|
2025-07-14 14:24:03 +08:00
|
|
|
$all = $all->merge($publicResources);
|
|
|
|
|
|
|
|
|
|
// 返回唯一的资源列表,并按 id 排序
|
2025-07-14 19:01:42 +08:00
|
|
|
// 使用 sortBy('sort') 来确保最终结果根据 'sort' 字段排序
|
|
|
|
|
return $all->unique('id')->values()->sortBy('sort');
|
2025-07-11 18:01:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2025-07-22 15:29:54 +08:00
|
|
|
* 构建目录/菜单树
|
2025-07-22 10:21:41 +08:00
|
|
|
*
|
|
|
|
|
* @param \Illuminate\Support\Collection $resources 全部资源集合
|
|
|
|
|
* @param int $parentId 当前父级资源 ID
|
|
|
|
|
* @param string $parentPath 父级完整路径(用于递归)
|
2025-07-11 18:01:23 +08:00
|
|
|
* @return array
|
|
|
|
|
*/
|
2025-07-22 15:29:54 +08:00
|
|
|
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);
|
|
|
|
|
}
|
2025-07-21 16:43:43 +08:00
|
|
|
|
2025-07-22 15:29:54 +08:00
|
|
|
// 权限
|
|
|
|
|
$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();
|
|
|
|
|
|
|
|
|
|
$componentValue = $hasChildrenMenu ? '/index/index' : $currentPath;
|
|
|
|
|
|
|
|
|
|
$tree[] = [
|
|
|
|
|
'id' => $node->id,
|
|
|
|
|
'name' => $node->name,
|
|
|
|
|
'path' => $node->url,
|
|
|
|
|
'component' => $componentValue,
|
|
|
|
|
'meta' => [
|
|
|
|
|
'title' => $node->name,
|
|
|
|
|
'icon' => $node->icon,
|
2025-08-14 20:08:57 +08:00
|
|
|
'keepAlive' => $node->keep_alive == 1 ? true : false,
|
2025-07-22 15:29:54 +08:00
|
|
|
'authList' => $authList,
|
|
|
|
|
'openType' => $node->open_type,
|
2025-07-25 16:10:59 +08:00
|
|
|
'isHide' => $node->is_hide == 0 ? false : true,
|
|
|
|
|
'isHideTab' => $node->is_hide_tab == 0 ? false : true
|
2025-07-22 15:29:54 +08:00
|
|
|
],
|
|
|
|
|
'children' => $children,
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
return $tree;
|
|
|
|
|
}
|
2025-07-11 18:01:23 +08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取用户所有权限code
|
|
|
|
|
*/
|
2025-07-25 18:10:11 +08:00
|
|
|
public function getPermissionCodes(int $userId, string $systemCode): array
|
2025-07-11 18:01:23 +08:00
|
|
|
{
|
2025-07-25 18:10:11 +08:00
|
|
|
$resources = $this->getUserResources($userId, $systemCode);
|
2025-07-11 18:01:23 +08:00
|
|
|
return $resources
|
|
|
|
|
->filter(fn($res) => $res->type === 'permission')
|
|
|
|
|
->pluck('code')
|
|
|
|
|
->unique()
|
|
|
|
|
->values()
|
|
|
|
|
->all();
|
|
|
|
|
}
|
|
|
|
|
}
|