where(function ($q) use ($params) { $q->where('name', 'like', '%' . $params['keyword'] . '%') ->orWhere('path', 'like', '%' . $params['keyword'] . '%') ->orWhere('component', 'like', '%' . $params['keyword'] . '%'); }); } // 状态筛选 if (isset($params['status'])) { $query->where('status', $params['status']); } // 菜单类型筛选 if (isset($params['type'])) { $query->where('type', $params['type']); } // 父级菜单筛选 if (isset($params['parent_id'])) { $query->where('parent_id', $params['parent_id']); } // 显示状态筛选 if (isset($params['visible'])) { $query->where('visible', $params['visible']); } // 排序 $query->orderBy('sort', 'asc') ->orderBy('id', 'desc'); return $query->paginate($params['page_size'] ?? 15); } /** * 获取简单列表(用于下拉选择等) */ public function getSimpleList(): array { return SystemMenu::select('id', 'name', 'parent_id') ->where('status', 1) ->orderBy('sort', 'asc') ->get() ->toArray(); } /** * 获取树形菜单结构 */ public function getMenuTree(): array { $menus = SystemMenu::where('status', 0) ->orderBy('sort', 'asc') ->get() ->toArray(); return $this->buildTree($menus); } /** * 根据用户权限获取菜单树 * * @param \App\Models\User $user 用户对象 * @param bool $convertToCamelCase 是否转换为驼峰命名,默认true * @return array */ public function getMenuTreeByPermission(\App\Models\User $user, bool $convertToCamelCase = true, $isTree = true): array { // 获取用户角色 $userRoles = $user->roles()->where('status', 0)->get(); $roleCodes = $userRoles->pluck('code')->toArray(); // 判断是否为超级管理员(username为admin或角色编码包含admin相关) $isSuperAdmin = $user->username === 'admin' || in_array('admin', $roleCodes) || in_array('super_admin', $roleCodes); // 获取菜单权限 if ($isSuperAdmin) { // 超级管理员获取所有菜单 $menus = SystemMenu::where('status', 0) ->where('visible', 1) ->whereIn('type', [1, 2]) ->orderBy('sort', 'asc') ->orderBy('id', 'asc') ->get(); } else { // 普通用户根据角色权限获取菜单 $roleIds = $userRoles->pluck('id')->toArray(); if (empty($roleIds)) { $menus = collect([]); } else { $menuIds = \App\Models\System\SystemRoleMenu::whereIn('role_id', $roleIds) ->pluck('menu_id') ->unique() ->toArray(); $menus = SystemMenu::whereIn('id', $menuIds) ->where('status', 0) ->where('visible', 1) ->whereIn('type', [1, 2]) ->orderBy('sort', 'asc') ->orderBy('id', 'asc') ->get(); } } if($isTree){ // 构建菜单树形结构 return $this->buildPermissionMenuTree($menus->toArray(), 0, $convertToCamelCase); }else{ $menuItem = []; foreach($menus as $menu){ if ($convertToCamelCase) { $menuItem[] = [ 'id' => $menu['id'], 'parentId' => $menu['parent_id'], 'name' => $menu['name'], 'component' => $menu['component'], 'componentName' => $menu['component_name'], 'icon' => $menu['icon'], 'keepAlive' => $menu['keep_alive'], 'visible' => $menu['visible'], 'alwaysShow' => $menu['always_show'], 'path' => $menu['path'], ]; } else { // 使用表字段命名 $menuItem[] = [ 'id' => $menu['id'], 'parent_id' => $menu['parent_id'], 'name' => $menu['name'], 'component' => $menu['component'], 'component_name' => $menu['component_name'], 'icon' => $menu['icon'], 'keep_alive' => $menu['keep_alive'], 'visible' => $menu['visible'], 'always_show' => $menu['always_show'], 'path' => $menu['path'], ]; } } return $menuItem; } } /** * 构建权限菜单树形结构 * * @param array $menus 菜单数组 * @param int $parentId 父级菜单ID * @param bool $convertToCamelCase 是否转换为驼峰命名 * @return array */ private function buildPermissionMenuTree(array $menus, int $parentId = 0, bool $convertToCamelCase = true): array { $tree = []; foreach ($menus as $menu) { if ($menu['parent_id'] == $parentId) { // 根据参数决定字段命名格式 if ($convertToCamelCase) { $menuItem = [ 'id' => $menu['id'], 'parentId' => $menu['parent_id'], 'name' => $menu['name'], 'component' => $menu['component'], 'componentName' => $menu['component_name'], 'icon' => $menu['icon'], 'keepAlive' => $menu['keep_alive'], 'visible' => $menu['visible'], 'alwaysShow' => $menu['always_show'], 'path' => $menu['path'], ]; } else { // 使用表字段命名 $menuItem = [ 'id' => $menu['id'], 'parent_id' => $menu['parent_id'], 'name' => $menu['name'], 'component' => $menu['component'], 'component_name' => $menu['component_name'], 'icon' => $menu['icon'], 'keep_alive' => $menu['keep_alive'], 'visible' => $menu['visible'], 'always_show' => $menu['always_show'], 'path' => $menu['path'], ]; } // 递归获取子菜单 $children = $this->buildPermissionMenuTree($menus, $menu['id'], $convertToCamelCase); $menuItem['children'] = $children; $tree[] = $menuItem; } } return $tree; } /** * 检查用户是否为超级管理员 * * @param \App\Models\User $user * @return bool */ public function isSuperAdmin(\App\Models\User $user): bool { if ($user->username === 'admin') { return true; } $roleCodes = $user->roles()->where('status', 0)->pluck('code')->toArray(); return in_array('admin', $roleCodes) || in_array('superadmin', $roleCodes); } /** * 获取用户有权限的菜单ID列表 * * @param \App\Models\User $user * @return array */ public function getUserMenuIds(\App\Models\User $user): array { if ($this->isSuperAdmin($user)) { // 超级管理员返回所有菜单ID return SystemMenu::where('status', 0) ->where('visible', 1) ->whereIn('type', [1, 2]) ->pluck('id') ->toArray(); } // 普通用户根据角色权限获取菜单ID $roleIds = $user->roles()->where('status', 0)->pluck('id')->toArray(); if (empty($roleIds)) { return []; } return \App\Models\System\SystemRoleMenu::whereIn('role_id', $roleIds) ->pluck('menu_id') ->unique() ->toArray(); } /** * 获取父级菜单列表 */ public function getParentMenus(): array { return SystemMenu::where('type', '!=', 3) // 排除按钮类型 ->where('status', 0) ->select('id', 'name', 'parent_id') ->orderBy('sort', 'asc') ->get() ->toArray(); } /** * 构建树形结构 */ private function buildTree(array $menus, int $parentId = 0): array { $tree = []; foreach ($menus as $menu) { if ($menu['parent_id'] == $parentId) { $children = $this->buildTree($menus, $menu['id']); if (!empty($children)) { $menu['children'] = $children; } $tree[] = $menu; } } return $tree; } /** * 创建前的数据处理 */ protected function beforeCreate(array &$data): void { // 如果没有设置排序,则设置为最大值+1 if (!isset($data['sort'])) { $maxSort = SystemMenu::max('sort') ?? 0; $data['sort'] = $maxSort + 1; } // 如果没有设置状态,默认为启用 if (!isset($data['status'])) { $data['status'] = 1; } // 如果没有设置显示状态,默认为显示 if (!isset($data['visible'])) { $data['visible'] = 0; } // 如果没有设置父级ID,默认为0 if (!isset($data['parent_id'])) { $data['parent_id'] = 0; } } /** * 更新前的数据处理 */ protected function beforeUpdate(array &$data, $model): void { // 不能将自己设置为自己的父级 if (isset($data['parent_id']) && $data['parent_id'] == $model->id) { throw new \App\Exceptions\BusinessException( \App\Helpers\ResponseEnum::CLIENT_PARAMETER_ERROR, '不能将自己设置为父级菜单' ); } } }