getAttributes())->id; } /** * @throws ApiException */ public function updateMenu($params) { // 校验更新的菜单是否存在 !self::isExistMenu($params['id']) && self::error('MENU_NOT_EXISTS', Response::HTTP_UNPROCESSABLE_ENTITY); // 校验父菜单存在 self::validateParentMenu($params['parentId'], $params['id']); // 校验菜单(自己) self::validateMenu($params['parentId'], $params['name'], $params['id']); // 更新到数据库 $menu = self::toModel($params, Menu::class); self::initMenuProperty($menu); $menu->update($menu->getAttributes()); } /** * @throws ApiException */ public function deleteMenu($id) { // 校验是否还有子菜单 self::validateChildrenMenu($id); // 校验删除的菜单是否存在 !self::isExistMenu($id) && self::error('MENU_NOT_EXISTS',Response::HTTP_UNPROCESSABLE_ENTITY); $menu = self::toModel(['id' => $id], Menu::class); // 标记删除 return $menu->delete(); } public function getMenu($id) { $menu = Menu::query(); $select = ['id','name','permission','type','sort','parent_id as parentId','path','icon','component','component_name as componentName','status','visible','keep_alive as keepAlive','always_show as alwaysShow']; return $menu->select($select)->find($id)->toArray(); } public function getMenuList($params = []): array { $menu = Menu::query(); $select = ['id','name','type','sort','parent_id as parentId','path','icon','component','component_name as componentName','status','visible','keep_alive as keepAlive','always_show as alwaysShow']; !empty($params['name']) && $menu->whereLike('name', "%{$params['name']}%"); !is_null($params['status']) && $menu->where('status', $params['status']); return $menu->orderBy('sort')->select($select)->get()->toArray(); } public function getSimpleMenuList(): array { $menus = $this->getMenuList(['status' => 0]); $list = self::filterDisableMenus($menus); // list.sort(Comparator . comparing(MenuDO::getSort)); return $list; } protected static function isExistMenu(int|array $condition): bool { $menu = Menu::query(); is_array($condition) && $menu->where($condition); is_numeric($condition) && $menu->where('id', $condition); return $menu->exists(); } /** * @throws ApiException */ protected static function validateChildrenMenu($parentId): void { Menu::query()->where('parent_id', $parentId)->count() && self::error('MENU_EXISTS_CHILDREN', Response::HTTP_UNPROCESSABLE_ENTITY); } /** * @throws ApiException */ protected static function validateParentMenu($parentId, $childId): void { if (!$parentId) return; // 不能设置自己为父菜单 $parentId === $childId && self::error('MENU_PARENT_ERROR',Response::HTTP_UNPROCESSABLE_ENTITY); $menu = Menu::query()->select('type')->find($parentId); // 父菜单不存在 !$menu && self::error('MENU_PARENT_NOT_EXISTS', Response::HTTP_UNPROCESSABLE_ENTITY); // 父菜单必须是目录或者菜单类型 $menu->type != MenuType::DIR && $menu->type != MenuType::MENU && self::error('MENU_PARENT_NOT_DIR_OR_MENU', Response::HTTP_UNPROCESSABLE_ENTITY); } /** * @throws ApiException */ protected static function validateMenu($parentId, $name, $id): void { $where = ['parent_id' => $parentId, 'name' => $name]; $menu = Menu::query()->where($where)->first(); if (is_null($menu)) return; // 如果 id 为空,说明不用比较是否为相同 id 的菜单 !$id && self::error('MENU_NAME_DUPLICATE', Response::HTTP_UNPROCESSABLE_ENTITY); $menu->id !== $id && self::error('MENU_NAME_DUPLICATE', Response::HTTP_UNPROCESSABLE_ENTITY); } /** * 初始化菜单的通用属性。 *
* 例如说,只有目录或者菜单类型的菜单,才设置 icon * */ private static function initMenuProperty(&$menu): void { // 菜单为按钮类型时,无需 component、icon、path 属性,进行置空 if ($menu->type === MenuType::BUTTON) { $menu->component = null; $menu->componentName = null; $menu->icon = null; $menu->path = null; } (isset($menu->permission) && empty($menu->permission) || !isset($menu->permission)) && ($menu->permission = null); } private static function filterDisableMenus($menus): array { if (empty($menus)) return []; // $menuMap = convertMap($menus,'id'); // $menuMap = collect($menus)->mapWithKeys(function ($menu) { // return [$menu['id'] => $menu]; // })->all(); // 遍历 menu 菜单,查找不是禁用的菜单,添加到 enabledMenus 结果 $enabledMenus = []; $disabledMenuCache = []; // 存下递归搜索过被禁用的菜单,防止重复的搜索 foreach ($menus as $menu) { if($menu['status'] !== 0) continue; // if($menu['type'] === 3) continue; // if (isMenuDisabled($menu, $menuMap, $disabledMenuCache)) { // continue; // } $enabledMenus[] = ['id' => $menu['id'],'status' => $menu['status'], 'name' => $menu['name'], 'parentId' => $menu['parentId'], 'type' => $menu['type']]; } return $enabledMenus; } }