MenuService.php 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. <?php
  2. declare (strict_types=1);
  3. namespace app\service;
  4. use app\model\UserRoleModel;
  5. use think\facade\Config;
  6. class MenuService
  7. {
  8. /**
  9. * 获取用户菜单列表
  10. */
  11. public static function getUserMenus(int $userId): array
  12. {
  13. $roleId = getUserRoleId($userId);
  14. if (!$roleId) {
  15. return [];
  16. }
  17. // 超级管理员返回所有菜单
  18. if (self::isSuperAdmin($roleId)) {
  19. return Config::get('menu.menus', []);
  20. }
  21. // 获取用户权限
  22. $permissions = self::getUserPermissions($roleId);
  23. // 过滤菜单
  24. $allMenus = Config::get('menu.menus', []);
  25. return self::filterMenus($allMenus, $permissions);
  26. }
  27. /**
  28. * 过滤菜单 - 根据权限返回可见菜单
  29. */
  30. private static function filterMenus(array $menus, array $permissions): array
  31. {
  32. $filtered = [];
  33. foreach ($menus as $menu) {
  34. // 检查菜单权限
  35. if (self::hasMenuPermission($menu, $permissions)) {
  36. $filteredMenu = $menu;
  37. // 递归过滤子菜单
  38. if (!empty($menu['children'])) {
  39. $filteredMenu['children'] = self::filterMenus($menu['children'], $permissions);
  40. // 如果没有子菜单,则不显示父菜单
  41. if (empty($filteredMenu['children'])) {
  42. continue;
  43. }
  44. }
  45. $filtered[] = $filteredMenu;
  46. }
  47. }
  48. return $filtered;
  49. }
  50. /**
  51. * 检查菜单权限
  52. */
  53. private static function hasMenuPermission(array $menu, array $permissions): bool
  54. {
  55. // 如果没有控制器,说明是父菜单,需要检查子菜单
  56. if (empty($menu['controller'])) {
  57. return true;
  58. }
  59. // 如果没有actions配置,则默认有权限
  60. if (empty($menu['actions'])) {
  61. return true;
  62. }
  63. // 检查是否有任一action的权限
  64. foreach (array_keys($menu['actions']) as $action) {
  65. $permission = strtolower($menu['controller'] . '.' . $action);
  66. if (in_array($permission, $permissions)) {
  67. return true;
  68. }
  69. }
  70. return false;
  71. }
  72. /**
  73. * 获取用户权限列表
  74. */
  75. private static function getUserPermissions(int $roleId): array
  76. {
  77. $role = UserRoleModel::find($roleId);
  78. if (!$role || empty($role->privileges)) {
  79. return [];
  80. }
  81. $privileges = json_decode($role->privileges, true);
  82. if (!is_array($privileges)) {
  83. return [];
  84. }
  85. // 转换为权限数组格式: controller.action
  86. $permissions = [];
  87. foreach ($privileges as $controller => $actions) {
  88. if (is_array($actions)) {
  89. foreach ($actions as $action) {
  90. $permissions[] = strtolower($controller . '.' . $action);
  91. }
  92. }
  93. }
  94. return $permissions;
  95. }
  96. /**
  97. * 检查是否超级管理员
  98. */
  99. private static function isSuperAdmin(int $roleId): bool
  100. {
  101. $superAdminIds = Config::get('menu.super_admin_role_ids', []);
  102. return in_array($roleId, $superAdminIds);
  103. }
  104. /**
  105. * 从菜单配置中提取所有权限
  106. */
  107. public static function getAllPermissions(): array
  108. {
  109. $permissions = [];
  110. $menus = Config::get('menu.menus', []);
  111. self::extractPermissions($menus, $permissions);
  112. return $permissions;
  113. }
  114. /**
  115. * 递归提取权限
  116. */
  117. private static function extractPermissions(array $menus, array &$permissions): void
  118. {
  119. foreach ($menus as $menu) {
  120. if (!empty($menu['controller']) && !empty($menu['actions'])) {
  121. $controller = $menu['controller'];
  122. if (!isset($permissions[$controller])) {
  123. $permissions[$controller] = [
  124. 'name' => $menu['title'],
  125. 'actions' => []
  126. ];
  127. }
  128. foreach ($menu['actions'] as $action => $desc) {
  129. $permissions[$controller]['actions'][$action] = $desc;
  130. }
  131. }
  132. if (!empty($menu['children'])) {
  133. self::extractPermissions($menu['children'], $permissions);
  134. }
  135. }
  136. }
  137. /**
  138. * 检查用户权限
  139. */
  140. public static function checkPermission(int $userId, string $controller, string $action): bool
  141. {
  142. // 检查是否在白名单中
  143. if (self::isWhitelisted($controller, $action)) {
  144. return true;
  145. }
  146. $roleId = getUserRoleId($userId);
  147. if (!$roleId) {
  148. return false;
  149. }
  150. // 超级管理员拥有所有权限
  151. if (self::isSuperAdmin($roleId)) {
  152. return true;
  153. }
  154. // 获取用户权限
  155. $permissions = self::getUserPermissions($roleId);
  156. $permission = strtolower($controller . '.' . $action);
  157. return in_array($permission, $permissions);
  158. }
  159. /**
  160. * 检查是否在白名单中
  161. */
  162. private static function isWhitelisted(string $controller, string $action): bool
  163. {
  164. $whitelist = Config::get('menu.permission_whitelist', []);
  165. // 检查控制器级别白名单
  166. $controllers = $whitelist['controllers'] ?? [];
  167. if (in_array($controller, $controllers)) {
  168. return true;
  169. }
  170. // 检查具体方法白名单
  171. $actions = $whitelist['actions'] ?? [];
  172. $current = $controller . '/' . $action;
  173. if (in_array($current, $actions)) {
  174. return true;
  175. }
  176. return false;
  177. }
  178. /**
  179. * 获取权限组配置
  180. */
  181. public static function getPermissionGroups(): array
  182. {
  183. return Config::get('menu.permission_groups', []);
  184. }
  185. /**
  186. * 根据权限组获取权限
  187. */
  188. public static function getPermissionsByGroup(string $groupName): array
  189. {
  190. $groups = self::getPermissionGroups();
  191. return $groups[$groupName]['permissions'] ?? [];
  192. }
  193. }