Files
fdesk/app/common/logic/PermLogic.php
T

282 lines
10 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
namespace app\common\logic;
use app\common\model\User;
use app\common\model\Resource;
class PermLogic
{
/**
* 获取用户所有资源(合并角色+直接分配),并加入公共菜单,排序按sort字段
*/
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->filter(function ($resource) {
// 只保留需要权限认证的资源(或公共资源)
return !$resource->no_auth;
})
);
}
// 合并用户直接分配的资源,排除不需要权限认证的资源
$all = $all->merge(
$user->resources->filter(function ($resource) {
// 只保留需要权限认证的资源(或公共资源)
return !$resource->no_auth;
})
);
// 加入公共菜单,公共菜单不管是否授权,所有人都能访问
$publicResources = Resource::where('no_auth', 1)
->orderBy('sort', 'asc') // 按 sort 字段升序排序
->get();
// 合并所有公共资源
$all = $all->merge($publicResources);
// 返回唯一的资源列表,并按 id 排序
// 使用 sortBy('sort') 来确保最终结果根据 'sort' 字段排序
return $all->unique('id')->values()->sortBy('sort');
}
/**
* 构建目录/菜单树
*
* @param \Illuminate\Support\Collection $resources 全部资源集合
* @param int $parentId 当前父级资源 ID
* @param string $parentPath 父级完整路径(用于递归)
* @return array
*/
public function buildTree_bak($resources, int $parentId = 0, string $parentPath = ''): array
{
$tree = [];
foreach ($resources as $node) {
// 只处理目录和菜单,不把 permission 当作菜单节点
if ($node->parent_id !== $parentId || $node->type === 'permission') {
continue;
}
// —— 拼接当前节点的完整路径 ——
$currentPath = rtrim($parentPath, '/');
if (!empty($node->url)) {
$urlSegment = ltrim($node->url, '/');
$currentPath = $currentPath === ''
? $urlSegment
: "{$currentPath}/{$urlSegment}";
}
// —— 递归构建子节点 ——
// 这里只会继续收目录和菜单,permission 永远不会进入此方法
$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 = ! empty($children);
// —— 计算 component 字段 ——
if ($hasChildrenMenu) {
if ($node->type === 'menu' && !empty($node->url)) {
// menu 类型且自身有 url,用自身 url(加前导 slash)
$componentValue = '/' . ltrim($node->url, '/');
} else {
// 其它含子项的节点,固定 Layout 组件
$componentValue = '/index/index';
}
} else {
// 叶子节点:拼接路径,确保以 slash 开头
$componentValue = $currentPath !== ''
? '/' . ltrim($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,
'isHide' => $node->is_hide == 0 ? false : true,
'isHideTab' => $node->is_hide_tab == 0 ? false : true
],
'children' => $children
];
}
return $tree;
}
public function buildTree_bak2($resources, int $parentId = 0, string $parentPath = ''): array
{
$tree = [];
foreach ($resources as $node) {
if ($node->parent_id !== $parentId) {
continue;
}
// —— 拼接当前节点的完整路径 ——
$currentPath = $parentPath;
// 去掉末尾多余 slash
$currentPath = rtrim($currentPath, '/');
if (!empty($node->url)) {
// 如果当前节点有 url,则拼接
$urlSegment = ltrim($node->url, '/');
$currentPath = $currentPath === ''
? $urlSegment
: "{$currentPath}/{$urlSegment}";
}
// —— 递归构建子节点 ——
$children = [];
if ($node->type === 'directory') {
$children = $this->buildTree($resources, $node->id, $currentPath);
}
// —— 收集本级的 permission 权限列表 ——
$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 = $resources
->where('parent_id', $node->id)
->whereIn('type', ['directory', 'menu'])
->isNotEmpty();
// —— 计算 component 字段 ——
if ($hasChildrenMenu) {
// 只要有子项,就一律显示顶层 Layout 组件
$componentValue = '/index/index';
} else {
// 叶子节点:如果定义了 url,就使用拼接后的路径;否则用占位符(这里用空串,你可替换)
$componentValue = $currentPath !== '' ? $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;
}
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();
$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,
'isHide' => $node->is_hide == 0 ? false : true,
'isHideTab' => $node->is_hide_tab == 0 ? false : true
],
'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();
}
}