|
@@ -8,35 +8,57 @@
|
|
|
|
|
|
namespace App\Http\Services\Backend\Server\System;
|
|
|
|
|
|
+use App\Enums\Common\Status;
|
|
|
use App\Enums\System\MenuType;
|
|
|
use App\Exceptions\ApiException;
|
|
|
use App\Http\Services\Service;
|
|
|
use App\Models\System\Menu;
|
|
|
-use Illuminate\Support\Arr;
|
|
|
+use Exception;
|
|
|
+use Illuminate\Support\Facades\DB;
|
|
|
+use Spatie\Permission\Guard;
|
|
|
+use Spatie\Permission\Models\Permission;
|
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
|
|
|
|
class MenuService extends Service
|
|
|
{
|
|
|
+ protected array $selectColumn = ['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'];
|
|
|
+// protected array $selectAppendColumn = ['created_at as createTime'];
|
|
|
|
|
|
/**
|
|
|
* @throws ApiException
|
|
|
*/
|
|
|
- public function createMenu($data)
|
|
|
+ public function createMenu(array $data, array $permissions)
|
|
|
{
|
|
|
// 校验父菜单存在
|
|
|
self::validateParentMenu($data['parentId'], null);
|
|
|
// 校验菜单(自己)
|
|
|
self::validateMenu($data['parentId'], $data['name'], null);
|
|
|
+
|
|
|
+ // 校验权限标识
|
|
|
+ $this->validatePermissions($permissions);
|
|
|
+
|
|
|
// 插入数据库
|
|
|
$menu = self::toModel($data, Menu::class);
|
|
|
+
|
|
|
self::initMenuProperty($menu);
|
|
|
- return Menu::create($menu->getAttributes())->id;
|
|
|
+
|
|
|
+ DB::beginTransaction();
|
|
|
+ try {
|
|
|
+ $menu_id = $menu->create($menu->getAttributes())->id;
|
|
|
+ $this->createPermissions($permissions, $menu_id);
|
|
|
+ DB::commit();
|
|
|
+ }
|
|
|
+ catch (Exception){
|
|
|
+ DB::rollBack();
|
|
|
+ self::error('添加失败');
|
|
|
+ }
|
|
|
+ return $menu_id;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @throws ApiException
|
|
|
*/
|
|
|
- public function updateMenu($params)
|
|
|
+ public function updateMenu($params): void
|
|
|
{
|
|
|
// 校验更新的菜单是否存在
|
|
|
!self::isExistMenu($params['id']) && self::error('MENU_NOT_EXISTS', Response::HTTP_UNPROCESSABLE_ENTITY);
|
|
@@ -61,7 +83,7 @@ class MenuService extends Service
|
|
|
self::validateChildrenMenu($id);
|
|
|
|
|
|
// 校验删除的菜单是否存在
|
|
|
- !self::isExistMenu($id) && self::error('MENU_NOT_EXISTS',Response::HTTP_UNPROCESSABLE_ENTITY);
|
|
|
+ !self::isExistMenu($id) && self::error('MENU_NOT_EXISTS', Response::HTTP_UNPROCESSABLE_ENTITY);
|
|
|
|
|
|
$menu = self::toModel(['id' => $id], Menu::class);
|
|
|
|
|
@@ -69,27 +91,25 @@ class MenuService extends Service
|
|
|
return $menu->delete();
|
|
|
}
|
|
|
|
|
|
- public function getMenu($id)
|
|
|
+ public function getMenu($id): array
|
|
|
{
|
|
|
$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();
|
|
|
+ return $menu->select($this->selectColumn)->find($id)->toArray();
|
|
|
}
|
|
|
+
|
|
|
public function getMenuList($params = []): array
|
|
|
{
|
|
|
$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'];
|
|
|
- !empty($params['name']) && $menu->whereLike('name', "%{$params['name']}%");
|
|
|
- !empty($params['status']) && $menu->where('status', $params['status']);
|
|
|
- return $menu->orderBy('sort')->select($select)->get()->toArray();
|
|
|
+ isset($params['name']) && filled($params['name']) && $menu->whereLike('name', "%{$params['name']}%");
|
|
|
+ isset($params['status']) && filled($params['status']) && $menu->where('status', $params['status']);
|
|
|
+ return $menu->orderBy('sort')->select($this->selectColumn)->get()->toArray();
|
|
|
}
|
|
|
|
|
|
public function getSimpleMenuList(): array
|
|
|
{
|
|
|
$menus = $this->getMenuList(['status' => 0]);
|
|
|
- $list = self::filterDisableMenus($menus);
|
|
|
-// list.sort(Comparator . comparing(MenuDO::getSort));
|
|
|
- return $list;
|
|
|
+ // list.sort(Comparator . comparing(MenuDO::getSort));
|
|
|
+ return self::filterDisableMenus($menus);
|
|
|
}
|
|
|
|
|
|
protected static function isExistMenu(int|array $condition): bool
|
|
@@ -115,7 +135,7 @@ class MenuService extends Service
|
|
|
{
|
|
|
if (!$parentId) return;
|
|
|
// 不能设置自己为父菜单
|
|
|
- $parentId === $childId && self::error('MENU_PARENT_ERROR',Response::HTTP_UNPROCESSABLE_ENTITY);
|
|
|
+ $parentId === $childId && self::error('MENU_PARENT_ERROR', Response::HTTP_UNPROCESSABLE_ENTITY);
|
|
|
|
|
|
$menu = Menu::query()->select('type')->find($parentId);
|
|
|
// 父菜单不存在
|
|
@@ -139,6 +159,46 @@ class MenuService extends Service
|
|
|
$menu->id !== $id && self::error('MENU_NAME_DUPLICATE', Response::HTTP_UNPROCESSABLE_ENTITY);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * @throws ApiException
|
|
|
+ */
|
|
|
+ protected function validatePermissions(array $permissions, int $menu_id = null): void
|
|
|
+ {
|
|
|
+ if (empty($permissions)) return;
|
|
|
+ $isExists = Permission::query()->whereIn('name', $permissions)->where('guard_name', Guard::getDefaultName(static::class))->exists();
|
|
|
+ $isExists && empty($menu_id) && self::error('权限标识重复');
|
|
|
+ }
|
|
|
+
|
|
|
+ protected function createPermissions(array $permissions, int $menu_id): void
|
|
|
+ {
|
|
|
+ if (empty($permissions)) return;
|
|
|
+ $permissionsData = [];
|
|
|
+ $guardName = Guard::getDefaultName(static::class);
|
|
|
+ $permissionQuery = Permission::query();
|
|
|
+ foreach ($permissions as $permission) {
|
|
|
+ $permissionsData[] = ['name' => $permission, 'guard_name' => $guardName];
|
|
|
+ }
|
|
|
+
|
|
|
+ $permissionQuery->insert($permissionsData);
|
|
|
+ $permissionIds = $permissionQuery->whereIn('name', $permissions)->pluck('id');
|
|
|
+
|
|
|
+ $this->createMenuHasPermissions($menu_id, $permissionIds->toArray());
|
|
|
+ }
|
|
|
+
|
|
|
+ protected function createMenuHasPermissions(int $menu_id, array $permission_ids): void
|
|
|
+ {
|
|
|
+ $tableNames = config('permission.table_names');
|
|
|
+ $menuHasPermissionsData = [];
|
|
|
+ $model_type = Menu::class;
|
|
|
+ foreach ($permission_ids as $permission_id) {
|
|
|
+ $menuHasPermissionsData[] = ['permission_id' => $permission_id, 'model_type' => $model_type, 'model_id' => $menu_id];
|
|
|
+ }
|
|
|
+ DB::table($tableNames['model_has_permissions'])->insert($menuHasPermissionsData);
|
|
|
+
|
|
|
+ // 存在权限并清空权限缓存
|
|
|
+// Cache::forget(config('permission.cache.key'));
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 初始化菜单的通用属性。
|
|
|
* <p>
|
|
@@ -148,34 +208,25 @@ class MenuService extends Service
|
|
|
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;
|
|
|
+ if ($menu['type'] === MenuType::BUTTON) {
|
|
|
+ $menu['component'] = null;
|
|
|
+ $menu['component_name'] = 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 = []; // 存下递归搜索过被禁用的菜单,防止重复的搜索
|
|
|
+// $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']];
|
|
|
+ if ($menu['status'] === Status::DISABLE) continue;
|
|
|
+ $enabledMenus[] = collect($menu)->only(['id', 'status', 'name', 'parentId', 'type']); //['id' => $menu['id'], 'status' => $menu['status'], 'name' => $menu['name'], 'parentId' => $menu['parentId'], 'type' => $menu['type']];
|
|
|
}
|
|
|
|
|
|
return $enabledMenus;
|