MenusService.php 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: qiuzijian
  5. * Date: 2021-04-15
  6. * Time: 11:08
  7. */
  8. namespace Modules\Admin\Services;
  9. use Illuminate\Support\Facades\Cache;
  10. use Illuminate\Support\Facades\Log;
  11. use Modules\Admin\Entities\Menu;
  12. class MenusService{
  13. /**
  14. * 添加菜单
  15. * @param $menuInfo
  16. * @param string $key
  17. * @return string
  18. */
  19. public function addMenu($menuInfo, $key = 'id')
  20. {
  21. return $this->addOrEditMenu($menuInfo, $key);
  22. }
  23. /**
  24. * 获取菜单列表
  25. * @param string $show
  26. * @param string $category
  27. * @return array|mixed|string
  28. */
  29. public function getMenusList($show = '', $category = 'admin')
  30. {
  31. // 判断并获取缓存
  32. if (empty($show)) {
  33. if (Cache::has($category . 'MenusList')) {
  34. return Cache::get($category . 'MenusList');
  35. }
  36. } else {
  37. if (Cache::has($category . 'MenusShowList')) {
  38. return Cache::get($category . 'MenusShowList');
  39. }
  40. }
  41. return $this->sortMenuAndCache($show, $category);
  42. }
  43. /**
  44. * 排序子菜单并缓存
  45. * ---------------------------------
  46. * array_column($array,$name)
  47. * $array => 要查询的数组
  48. * $name => 在数组中要返回的字段值
  49. *----------------------------------
  50. * array_multisort($array1,$rule,$array2)
  51. * $array1 => 规定数组(规定以这个数组来排序)
  52. * $rule => 规定排列顺序。
  53. * 可能的值:
  54. * SORT_ASC - 默认。按升序排列 (A-Z)。
  55. * SORT_DESC - 按降序排列 (Z-A)。
  56. * $array2 => 要规定的数组。(要排序的数组)
  57. */
  58. public function sortMenuAndCache($show = '', $category = 'admin')
  59. {
  60. $menus = Menu::where('category', $category);
  61. if (!empty($show)) {
  62. $menus = $menus->where('show', $show);
  63. }
  64. $menus = $menus->orderBy('sort', 'desc')->get()->toArray();
  65. if ($menus) {
  66. $menuList = $this->sortMenu($menus);
  67. foreach ($menuList as $key => $value) {
  68. if ($value['child']) {
  69. $sort = array_column($value['child'], 'sort');
  70. array_multisort($sort, SORT_DESC, $value['child']);
  71. }
  72. }
  73. //缓存菜单数据
  74. if (!empty($show)) {
  75. Cache::forever($category . 'MenusShowList', $menuList);
  76. } else {
  77. Cache::forever($category . 'MenusList', $menuList);
  78. }
  79. return $menuList;
  80. }
  81. return [];
  82. }
  83. /**
  84. * 递归菜单数据
  85. * @param $menus
  86. * @param int $pid
  87. * @return array|string
  88. */
  89. public function sortMenu($menus, $pid = 0)
  90. {
  91. $arr = [];
  92. if (empty($menus)) {
  93. return '';
  94. }
  95. $num = 0;
  96. foreach ($menus as $key => $value) {
  97. if ($value['parent_id'] == $pid) {
  98. $arr[$num] = $value;
  99. $arr[$num]['child'] = self::sortMenu($menus, $value['id']);
  100. $num += 1;
  101. }
  102. }
  103. return $arr;
  104. }
  105. /**
  106. * 递归删除菜单
  107. * @param $menuId
  108. * @return bool
  109. */
  110. public function delMenu($menuId, $category = 'admin')
  111. {
  112. $menu = Menu::find($menuId);
  113. $subMenus = Menu::where('parent_id', $menuId)->get()->toArray();
  114. if (count($subMenus) > 0) { // 如果有子菜单将子菜单删除
  115. foreach ($subMenus as $subMenu) {
  116. self::delMenu($subMenu['id']);
  117. }
  118. }
  119. // $permission = Permission::where('name', $menu['slug'])
  120. // ->where('route', $menu['path'])
  121. // ->where('guard_name', 'admin')->first();
  122. //
  123. // if ($permission) {
  124. // $permission->delete();
  125. // }
  126. if ($menu) {
  127. $menu->delete();
  128. }
  129. $this->sortMenuAndCache(1, $category);
  130. $this->sortMenuAndCache('', $category);
  131. return true;
  132. }
  133. /**
  134. * 获取单个菜单信息
  135. * @param $menuId
  136. * @return bool
  137. */
  138. public function getMenuInfo($menuId)
  139. {
  140. if (!isset($menuId)) {
  141. return false;
  142. }
  143. return Menu::find($menuId);
  144. }
  145. /**
  146. * 编辑菜单
  147. * @param $menuInfo
  148. * @return bool
  149. */
  150. public function editMenu($menuInfo)
  151. {
  152. if (!isset($menuInfo['id'])) {
  153. return false;
  154. }
  155. if ($menuInfo['id'] == $menuInfo['parent_id']) {
  156. return false;
  157. }
  158. return $this->addOrEditMenu($menuInfo);
  159. }
  160. protected function addOrEditMenu($menuInfo, $key = 'id')
  161. {
  162. // 判断层级
  163. if ($menuInfo['parent_id'] == 0) {
  164. $menuInfo['tier'] = 1;
  165. $degree = '';
  166. } else {
  167. $menuParent = Menu::find($menuInfo['parent_id']);
  168. $menuInfo['tier'] = $menuParent->tier + 1;
  169. $degree = $menuParent->degree . '|';
  170. }
  171. // 判断分类
  172. if (!isset($menuInfo['category'])) {
  173. $menuInfo['category'] = 'admin';
  174. }
  175. if (!isset($menuInfo['can_del'])) {
  176. $menuInfo['can_del'] = 1;
  177. }
  178. // 增加部门标识(如果为空则自动生成拼音)
  179. if (!isset($menuInfo['slug']) || empty($menuInfo['slug'])) {
  180. $cn = "/[\x{4e00}-\x{9fa5}a-zA-Z0-9\/]/u"; // 提取字母中文以及'/'
  181. preg_match_all($cn, $menuInfo['path'], $pathResult);
  182. $pathResult = implode('', $pathResult[0]);
  183. Log::info($pathResult);
  184. $menuInfo['slug'] = lcfirst(implode(array_map(function ($item) {
  185. return ucfirst($item);
  186. }, pinyin($pathResult))));
  187. }
  188. // 更新前数据
  189. if (isset($menuInfo[$key]) && !empty($menuInfo[$key])) {
  190. $oldMenu = Menu::where($key, $menuInfo[$key])->first();
  191. if ($oldMenu) {
  192. $permissionName = $oldMenu['slug'];
  193. }
  194. } else {
  195. $menuHas = Menu::where('slug', $menuInfo['slug'])->first();
  196. if ($menuHas) {
  197. return 'has';
  198. }
  199. $permissionName = $menuInfo['slug'];
  200. }
  201. $menu = Menu::updateOrCreate([$key => $menuInfo[$key] ?? ''], $menuInfo);
  202. $menu->degree = $degree . $menu->id;
  203. // 保存数据
  204. $menu->save();
  205. // 修改子树中数据,未改变层级不进行调整
  206. if (isset($menuInfo[$key]) && isset($oldMenu['degree']) && $oldMenu['degree'] != $menu['degree']) { // 如果改变父级,联动改变其下属所有子集
  207. // 层级
  208. $diffTier = $oldMenu['tier'] - $menuInfo['tier'];
  209. // 查找子数据数组(array)
  210. $childMenus = Menu::where('degree', 'like', $oldMenu['degree'] . '|%')->get();
  211. foreach ($childMenus as $childMenu) {
  212. // 第一条子数据
  213. // 修改树路径:修改的树|更新的树|子树
  214. $degree = str_replace($oldMenu['degree'] . '|', $menu['degree'] . '|', $childMenu['degree']);
  215. // 获取详情
  216. $_menu = Menu::where('id', $childMenu['id'])->first();
  217. // 路劲数据
  218. $_menu->degree = $degree;
  219. // 层级
  220. $_menu->tier = $_menu->tier - $diffTier;
  221. // 保存
  222. $_menu->save();
  223. }
  224. }
  225. // 权限
  226. $permissionInfo['title'] = $menuInfo['title'];
  227. $permissionInfo['name'] = $menuInfo['slug'];
  228. $permissionInfo['route'] = $menuInfo['path'];
  229. $permissionInfo['guard_name'] = $menuInfo['category'];
  230. // Permission::updateOrCreate(['name' => $permissionName ?? ''], $permissionInfo);
  231. $this->sortMenuAndCache(1, $menuInfo['category']);
  232. $this->sortMenuAndCache('', $menuInfo['category']);
  233. return $menu;
  234. }
  235. }