|
|
@@ -3,206 +3,203 @@ declare (strict_types=1);
|
|
|
|
|
|
namespace app\service;
|
|
|
|
|
|
+use app\model\UserRoleModel;
|
|
|
use think\facade\Config;
|
|
|
|
|
|
class MenuService
|
|
|
{
|
|
|
/**
|
|
|
- * 获取所有菜单配置
|
|
|
+ * 获取用户菜单列表
|
|
|
*/
|
|
|
- public static function getAllMenus(): array
|
|
|
+ public static function getUserMenus(int $userId): array
|
|
|
{
|
|
|
- return Config::get('menu.menus', []);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 根据用户权限过滤菜单
|
|
|
- */
|
|
|
- public static function getMenusByPermission($userInfo): array
|
|
|
- {
|
|
|
- $allMenus = self::getAllMenus();
|
|
|
- return self::filterMenusByPermission($allMenus, $userInfo);
|
|
|
+ $roleId = getUserRoleId($userId);
|
|
|
+ if (!$roleId) {
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 超级管理员返回所有菜单
|
|
|
+ if (self::isSuperAdmin($roleId)) {
|
|
|
+ return Config::get('menu.menus', []);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取用户权限
|
|
|
+ $permissions = self::getUserPermissions($roleId);
|
|
|
+
|
|
|
+ // 过滤菜单
|
|
|
+ $allMenus = Config::get('menu.menus', []);
|
|
|
+ return self::filterMenus($allMenus, $permissions);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
/**
|
|
|
- * 递归过滤菜单权限
|
|
|
+ * 过滤菜单 - 根据权限返回可见菜单
|
|
|
*/
|
|
|
- private static function filterMenusByPermission($menus, $userInfo): array
|
|
|
+ private static function filterMenus(array $menus, array $permissions): array
|
|
|
{
|
|
|
- $filteredMenus = [];
|
|
|
+ $filtered = [];
|
|
|
|
|
|
foreach ($menus as $menu) {
|
|
|
- // 如果菜单指定了控制器,需要检查权限
|
|
|
- if (!empty($menu['controller'])) {
|
|
|
- if (!self::hasControllerPermission($userInfo, $menu['controller'])) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 处理子菜单
|
|
|
- if (isset($menu['children']) && is_array($menu['children'])) {
|
|
|
- $children = self::filterMenusByPermission($menu['children'], $userInfo);
|
|
|
- // 如果有子菜单权限,才显示父菜单
|
|
|
- if (!empty($children)) {
|
|
|
- $menu['children'] = $children;
|
|
|
- $filteredMenus[] = $menu;
|
|
|
- }
|
|
|
- } else {
|
|
|
- // 没有子菜单的情况
|
|
|
- if (empty($menu['controller']) || self::hasControllerPermission($userInfo, $menu['controller'])) {
|
|
|
- $filteredMenus[] = $menu;
|
|
|
+ // 检查菜单权限
|
|
|
+ if (self::hasMenuPermission($menu, $permissions)) {
|
|
|
+ $filteredMenu = $menu;
|
|
|
+
|
|
|
+ // 递归过滤子菜单
|
|
|
+ if (!empty($menu['children'])) {
|
|
|
+ $filteredMenu['children'] = self::filterMenus($menu['children'], $permissions);
|
|
|
+
|
|
|
+ // 如果没有子菜单,则不显示父菜单
|
|
|
+ if (empty($filteredMenu['children'])) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
+ $filtered[] = $filteredMenu;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- return $filteredMenus;
|
|
|
+ return $filtered;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
/**
|
|
|
- * 检查用户是否有控制器权限
|
|
|
+ * 检查菜单权限
|
|
|
*/
|
|
|
- private static function hasControllerPermission($userInfo, $controller): bool
|
|
|
+ private static function hasMenuPermission(array $menu, array $permissions): bool
|
|
|
{
|
|
|
- // 超级管理员拥有所有权限
|
|
|
- $superAdminRoleId = Config::get('permission.super_admin_role_id', 1);
|
|
|
- if ($userInfo['user_role'] == $superAdminRoleId) {
|
|
|
+ // 如果没有控制器,说明是父菜单,需要检查子菜单
|
|
|
+ if (empty($menu['controller'])) {
|
|
|
return true;
|
|
|
}
|
|
|
-
|
|
|
- // 获取用户角色权限
|
|
|
- $role = \app\model\UserRoleModel::getRoleById($userInfo['user_role'], $userInfo['merchant_id']);
|
|
|
- if (!$role) {
|
|
|
- return false;
|
|
|
+
|
|
|
+ // 如果没有actions配置,则默认有权限
|
|
|
+ if (empty($menu['actions'])) {
|
|
|
+ return true;
|
|
|
}
|
|
|
-
|
|
|
- $privileges = $role->privileges;
|
|
|
|
|
|
- // 检查是否有对应控制器的权限
|
|
|
- return isset($privileges[$controller]) && is_array($privileges[$controller]) && !empty($privileges[$controller]);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取菜单树形结构(用于前端显示)
|
|
|
- */
|
|
|
- public static function getMenuTree($userInfo): array
|
|
|
- {
|
|
|
- $menus = self::getMenusByPermission($userInfo);
|
|
|
- return self::buildMenuTree($menus);
|
|
|
+ // 检查是否有任一action的权限
|
|
|
+ foreach (array_keys($menu['actions']) as $action) {
|
|
|
+ $permission = strtolower($menu['controller'] . '.' . $action);
|
|
|
+ if (in_array($permission, $permissions)) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
/**
|
|
|
- * 构建菜单树形结构
|
|
|
+ * 获取用户权限列表
|
|
|
*/
|
|
|
- private static function buildMenuTree($menus): array
|
|
|
+ private static function getUserPermissions(int $roleId): array
|
|
|
{
|
|
|
- $tree = [];
|
|
|
+ $role = UserRoleModel::find($roleId);
|
|
|
+ if (!$role || empty($role->privileges)) {
|
|
|
+ return [];
|
|
|
+ }
|
|
|
|
|
|
- foreach ($menus as $menu) {
|
|
|
- $item = [
|
|
|
- 'id' => $menu['id'],
|
|
|
- 'title' => $menu['title'],
|
|
|
- 'icon' => $menu['icon'] ?? '',
|
|
|
- 'url' => $menu['url'] ?? '',
|
|
|
- 'controller' => $menu['controller'] ?? '',
|
|
|
- 'level' => $menu['level'],
|
|
|
- 'sort' => $menu['sort'] ?? 0,
|
|
|
- ];
|
|
|
-
|
|
|
- if (isset($menu['children']) && is_array($menu['children'])) {
|
|
|
- $item['children'] = self::buildMenuTree($menu['children']);
|
|
|
- $item['spread'] = false; // 默认不展开
|
|
|
- }
|
|
|
-
|
|
|
- $tree[] = $item;
|
|
|
+ $privileges = json_decode($role->privileges, true);
|
|
|
+ if (!is_array($privileges)) {
|
|
|
+ return [];
|
|
|
}
|
|
|
|
|
|
- // 按sort字段排序
|
|
|
- usort($tree, function($a, $b) {
|
|
|
- return ($a['sort'] ?? 0) - ($b['sort'] ?? 0);
|
|
|
- });
|
|
|
+ // 转换为权限数组格式: controller.action
|
|
|
+ $permissions = [];
|
|
|
+ foreach ($privileges as $controller => $actions) {
|
|
|
+ if (is_array($actions)) {
|
|
|
+ foreach ($actions as $action) {
|
|
|
+ $permissions[] = strtolower($controller . '.' . $action);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- return $tree;
|
|
|
+ return $permissions;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
/**
|
|
|
- * 获取所有控制器权限配置
|
|
|
+ * 检查是否超级管理员
|
|
|
*/
|
|
|
- public static function getControllerPermissions(): array
|
|
|
+ private static function isSuperAdmin(int $roleId): bool
|
|
|
{
|
|
|
- return Config::get('menu.controller_permissions', []);
|
|
|
+ $superAdminIds = Config::get('menu.super_admin_role_ids', []);
|
|
|
+ return in_array($roleId, $superAdminIds);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
/**
|
|
|
- * 根据菜单ID获取菜单信息
|
|
|
+ * 从菜单配置中提取所有权限
|
|
|
*/
|
|
|
- public static function getMenuById($menuId): ?array
|
|
|
+ public static function getAllPermissions(): array
|
|
|
{
|
|
|
- $allMenus = self::getAllMenus();
|
|
|
- return self::findMenuById($allMenus, $menuId);
|
|
|
+ $permissions = [];
|
|
|
+ $menus = Config::get('menu.menus', []);
|
|
|
+
|
|
|
+ self::extractPermissions($menus, $permissions);
|
|
|
+
|
|
|
+ return $permissions;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
/**
|
|
|
- * 递归查找菜单
|
|
|
+ * 递归提取权限
|
|
|
*/
|
|
|
- private static function findMenuById($menus, $menuId): ?array
|
|
|
+ private static function extractPermissions(array $menus, array &$permissions): void
|
|
|
{
|
|
|
foreach ($menus as $menu) {
|
|
|
- if ($menu['id'] == $menuId) {
|
|
|
- return $menu;
|
|
|
+ if (!empty($menu['controller']) && !empty($menu['actions'])) {
|
|
|
+ $controller = $menu['controller'];
|
|
|
+
|
|
|
+ if (!isset($permissions[$controller])) {
|
|
|
+ $permissions[$controller] = [
|
|
|
+ 'name' => $menu['title'],
|
|
|
+ 'actions' => []
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach ($menu['actions'] as $action => $desc) {
|
|
|
+ $permissions[$controller]['actions'][$action] = $desc;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- if (isset($menu['children']) && is_array($menu['children'])) {
|
|
|
- $found = self::findMenuById($menu['children'], $menuId);
|
|
|
- if ($found) {
|
|
|
- return $found;
|
|
|
- }
|
|
|
+ if (!empty($menu['children'])) {
|
|
|
+ self::extractPermissions($menu['children'], $permissions);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- return null;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
/**
|
|
|
- * 获取面包屑导航
|
|
|
+ * 检查用户权限
|
|
|
*/
|
|
|
- public static function getBreadcrumb($menuId): array
|
|
|
+ public static function checkPermission(int $userId, string $controller, string $action): bool
|
|
|
{
|
|
|
- $breadcrumb = [];
|
|
|
- $allMenus = self::getAllMenus();
|
|
|
-
|
|
|
- $path = self::getMenuPath($allMenus, $menuId);
|
|
|
+ $roleId = getUserRoleId($userId);
|
|
|
+ if (!$roleId) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
|
|
|
- foreach ($path as $menu) {
|
|
|
- $breadcrumb[] = [
|
|
|
- 'id' => $menu['id'],
|
|
|
- 'title' => $menu['title'],
|
|
|
- 'url' => $menu['url'] ?? ''
|
|
|
- ];
|
|
|
+ // 超级管理员拥有所有权限
|
|
|
+ if (self::isSuperAdmin($roleId)) {
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
- return $breadcrumb;
|
|
|
+ // 获取用户权限
|
|
|
+ $permissions = self::getUserPermissions($roleId);
|
|
|
+ $permission = strtolower($controller . '.' . $action);
|
|
|
+
|
|
|
+ return in_array($permission, $permissions);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
/**
|
|
|
- * 获取菜单路径
|
|
|
+ * 获取权限组配置
|
|
|
*/
|
|
|
- private static function getMenuPath($menus, $menuId, $path = []): array
|
|
|
+ public static function getPermissionGroups(): array
|
|
|
{
|
|
|
- foreach ($menus as $menu) {
|
|
|
- $currentPath = array_merge($path, [$menu]);
|
|
|
-
|
|
|
- if ($menu['id'] == $menuId) {
|
|
|
- return $currentPath;
|
|
|
- }
|
|
|
-
|
|
|
- if (isset($menu['children']) && is_array($menu['children'])) {
|
|
|
- $found = self::getMenuPath($menu['children'], $menuId, $currentPath);
|
|
|
- if (!empty($found)) {
|
|
|
- return $found;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return [];
|
|
|
+ return Config::get('menu.permission_groups', []);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据权限组获取权限
|
|
|
+ */
|
|
|
+ public static function getPermissionsByGroup(string $groupName): array
|
|
|
+ {
|
|
|
+ $groups = self::getPermissionGroups();
|
|
|
+ return $groups[$groupName]['permissions'] ?? [];
|
|
|
}
|
|
|
}
|