diff --git a/app/Cache/Redis/Admin/MenuCache.php b/app/Cache/Redis/Admin/MenuCache.php index 3704e82..130cb72 100644 --- a/app/Cache/Redis/Admin/MenuCache.php +++ b/app/Cache/Redis/Admin/MenuCache.php @@ -5,6 +5,7 @@ namespace App\Cache\Redis\Admin; use App\Cache\Redis\RedisCache; use App\Constants\Admin\AuthCode; use App\Model\AdminMenu; +use App\Service\ServiceTrait\AdminRoleMenuTrait; use Hyperf\Di\Annotation\Inject; use Psr\Container\ContainerExceptionInterface; use Psr\Container\NotFoundExceptionInterface; @@ -12,6 +13,8 @@ use RedisException; class MenuCache { + use AdminRoleMenuTrait; + /** * @var RedisCache $redis */ @@ -30,6 +33,9 @@ class MenuCache */ protected string $menuKey; + /** + * 构造函数注入 key + */ public function __construct() { $this->menuKey = AdminRedisKey::adminMenuList(); @@ -51,7 +57,7 @@ class MenuCache $data = $this->getDbMenu($allMenuList); - $this->redis->set($this->menuKey,json_encode($data)); + $this->redis->set($this->menuKey,json_encode($data),'system'); return $data; } @@ -64,38 +70,6 @@ class MenuCache */ public function delMenu(): void { - $this->redis->delete($this->menuKey); - } - - /** - * 递归生成合适的数据 - * @param array $allMenuList - * @param int $parentId - * @return array - */ - private function getDbMenu(array $allMenuList, int $parentId = 0): array - { - $menuList = []; - foreach ($allMenuList as $menu) { - if ($menu['parent_id'] == $parentId) { - $children = $this->getDbMenu($allMenuList, (int)$menu['id']); - if (!empty($children)) { - //获取第一个 type 如何是菜单 - if ($children[0]['type'] == AuthCode::MENU_TYPE_LIST) { - $menu['children'] = $children; - } else { - foreach ($children as $child) { - $menu['permissionList'][] = [ - 'id' => $child['id'], - 'label' => $child['title'], - 'value' => $child['value'], - ]; - } - } - } - $menuList[] = $menu; - } - } - return $menuList; + $this->redis->delete($this->menuKey,'system'); } } \ No newline at end of file diff --git a/app/Cache/Redis/Admin/RoleCache.php b/app/Cache/Redis/Admin/RoleCache.php new file mode 100644 index 0000000..5386997 --- /dev/null +++ b/app/Cache/Redis/Admin/RoleCache.php @@ -0,0 +1,129 @@ +roleMenuArrKey = AdminRedisKey::adminMenuArrByRoleId($this->roleId); + $this->roleMenuListKey = AdminRedisKey::adminMenuListByRoleId($this->roleId); + } + + /** + * @param int $roleId + * @return array|array[] + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + * @throws \RedisException + */ + public function getRoleCache(int $roleId): array + { + $this->roleId = $roleId; + + $this->getKey(); + + if ($this->redis->exists($this->roleMenuArrKey,'system') && $this->redis->exists($this->roleMenuListKey,'system')) { + return [ + 'role_arr' => $this->redis->sMembers($this->roleMenuArrKey,'system'), + 'role_list' => json_decode($this->redis->get($this->roleMenuListKey,'system'),true), + ]; + } + + if ($this->roleId == AuthCode::SUPERADMIN) { + $menuIds = $this->adminMenuModel->getAllIds(); + $data = (new MenuCache)->getMenu(); +// $menuList = $this->adminMenuModel->getAllMenu(); + } else { + $menuIds = $this->adminRoleMenuModel->getMenuByRoleId($this->roleId); + $menuList = $this->adminMenuModel->getRoleMenu($menuIds); + $data = $this->getDbMenu($menuList); + } + + if (empty($menuIds) || empty($menuList)) { + return [ + 'role_arr' => [], + 'role_list' => [] + ]; + } + + $this->delRoleCache(); + + $this->redis->set($this->roleMenuListKey,json_encode($data),'system'); + $this->redis->sAddBatch($this->roleMenuArrKey,$menuIds,'system'); + + return [ + 'role_arr' => $menuIds, + 'role_list' => $data + ]; + } + + /** + * @param int $roleId + * @return void + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + * @throws \RedisException + */ + public function delRoleCache(int $roleId = 0): void + { + if ($roleId > 0) { + $this->roleId = $roleId; + $this->getKey(); + } + + $this->redis->delete($this->roleMenuArrKey,'system'); + $this->redis->delete($this->roleMenuListKey,'system'); + } +} \ No newline at end of file diff --git a/app/Cache/Redis/RedisCache.php b/app/Cache/Redis/RedisCache.php index ebe7fc8..eb01c87 100644 --- a/app/Cache/Redis/RedisCache.php +++ b/app/Cache/Redis/RedisCache.php @@ -272,6 +272,21 @@ class RedisCache return $this->getRedis($poolName)->sRem($key, $value); } + /** + * 集合批量添加 + * @param $key + * @param array $values + * @param string $poolName + * @return bool|int|Redis + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + * @throws RedisException + */ + public function sAddBatch($key, array $values, string $poolName = 'default') + { + return $this->getRedis($poolName)->sAddArray($key, $values); + } + // +-------------------------------------------------------------------------------------------------------------------------------------------- // | hash // +-------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/app/Constants/Admin/AuthCode.php b/app/Constants/Admin/AuthCode.php index a09be8f..efad9d4 100644 --- a/app/Constants/Admin/AuthCode.php +++ b/app/Constants/Admin/AuthCode.php @@ -23,4 +23,9 @@ class AuthCode * 按钮 */ const MENU_TYPE_BUTTON = 2; + + /** + * 超级管理员 + */ + const SUPERADMIN = 1; } \ No newline at end of file diff --git a/app/Controller/Admin/AuthController.php b/app/Controller/Admin/AuthController.php index 895823f..97cb9f4 100644 --- a/app/Controller/Admin/AuthController.php +++ b/app/Controller/Admin/AuthController.php @@ -9,6 +9,7 @@ use App\Middleware\Admin\JwtAuthMiddleware; use App\Request\Admin\AuthRequest; use App\Service\Admin\User\RoleMenuService; use App\Service\Admin\User\RoleService; +use Exception; use Hyperf\HttpServer\Annotation\Controller; use Hyperf\HttpServer\Annotation\Middlewares; use Hyperf\HttpServer\Annotation\RequestMapping; @@ -102,29 +103,63 @@ class AuthController extends AbstractController return (new RoleMenuService)->buildCache(); } + /** + * @param AuthRequest $request + * @return array + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + #[RequestMapping(path: "role_add", methods: "POST")] + #[Scene(scene: "role_add")] public function role_add(AuthRequest $request) { return (new RoleService)->add(); } - public function role_edit() + /** + * @return array + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + #[RequestMapping(path: "role_edit", methods: "POST")] + #[Scene(scene: "role_edit")] + public function roleEdit() { return (new RoleService)->edit(); } - public function role_status() + /** + * @param AuthRequest $request + * @return array + * @throws Exception + */ + #[RequestMapping(path: "role_change_status", methods: "POST")] + #[Scene(scene: "role_change_status")] + public function roleChangeStatus(AuthRequest $request) { return (new RoleService)->changeStatus(); } - public function role_list() + /** + * @return array + */ + #[RequestMapping(path: "role_list", methods: "GET")] + #[Scene(scene: "role_list")] + public function roleList(AuthRequest $request) { return (new RoleService)->handle(); } + /** + * @param AuthRequest $request + * @return array + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + * @throws \RedisException + */ #[RequestMapping(path: "role", methods: "GET")] #[Scene(scene: "role_info")] - public function role(AuthRequest $request) + public function role(AuthRequest $request): array { return (new RoleService)->details(); } diff --git a/app/Model/AdminMenu.php b/app/Model/AdminMenu.php index 13ee0c2..7963c18 100644 --- a/app/Model/AdminMenu.php +++ b/app/Model/AdminMenu.php @@ -59,10 +59,38 @@ class AdminMenu extends Model } /** - * @param int $url + * @return array + */ + public function getAllIds() + { + return $this + ->where('status', AuthCode::MENU_STATUS_ENABLE) + ->orderBy('sort', 'desc') + ->pluck('id') + ->toArray(); + } + + /** + * @param $ids + * @return array|false + */ + public function getRoleMenu($ids): array|false + { + $res = $this + ->where('status', AuthCode::MENU_STATUS_ENABLE) + ->whereIn('id',$ids) + ->orderBy('sort', 'desc') + ->get(); + if (empty($res)) return false; + + return $res->toArray(); + } + + /** + * @param string $url * @return Builder|\Hyperf\Database\Model\Model|null */ - public function getMenuByUrl(int $url): \Hyperf\Database\Model\Model|Builder|null + public function getMenuByUrl(string $url): \Hyperf\Database\Model\Model|Builder|null { return $this ->where('url', $url) @@ -73,7 +101,7 @@ class AdminMenu extends Model * @param int $id * @return HigherOrderTapProxy|mixed|null */ - public function getChildMenuType(int $id) + public function getChildMenuType(int $id): mixed { return $this->where('parent_id', $id)->value('type'); } diff --git a/app/Model/AdminRoleMenu.php b/app/Model/AdminRoleMenu.php new file mode 100644 index 0000000..05acf97 --- /dev/null +++ b/app/Model/AdminRoleMenu.php @@ -0,0 +1,39 @@ + 'integer', 'menu_id' => 'integer']; + + /** + * 获取角色菜单列表 + * @param int $roleId + * @return array + */ + public function getMenuByRoleId(int $roleId): array + { + return $this->where('role_id', $roleId)->pluck('menu_id')->toArray(); + } +} diff --git a/app/Request/Admin/AuthRequest.php b/app/Request/Admin/AuthRequest.php index 25e5b87..2874d81 100644 --- a/app/Request/Admin/AuthRequest.php +++ b/app/Request/Admin/AuthRequest.php @@ -26,10 +26,11 @@ class AuthRequest extends FormRequest 'menu_id' => 'required|integer', 'menu_name' => 'required|string', 'menu_url' =>'required|string', - 'menu_status' => 'required|string', + 'menu_status' => 'required|in:1,2', 'menu_parent_id' => 'integer|exists:admin_menu,id', - 'page' =>'required|integer', 'limit' => 'required|integer', + 'role_status' => 'required|in:1,2', + 'role_name' => 'required|string', ]; } @@ -41,14 +42,21 @@ class AuthRequest extends FormRequest 'menu_name.required' => '名称必填', 'menu_url.required' => 'url必填', 'menu_status.required' => '状态必填', + 'menu_status.in' => '状态值错误', 'menu_parent_id.exists' => 'parent_id不存在', 'page.required' => 'page必填', - 'limit.required' => 'limit必填' + 'limit.required' => 'limit必填', + 'role_status.required' => '状态必填', + 'role_status.in' => '状态值错误' ]; } protected array $scenes = [ 'role_info' => ['role_id'], + 'role_add' => ['role_name','role_status'], + 'role_edit' => ['role_id','role_name','role_status'], + 'role_change_status' => ['role_id','role_status'], + 'role_list' => ['limit'], 'menu_info' => ['menu_id'], 'menu_add' => ['menu_name','menu_url','menu_status','parent_id'], 'menu_edit' => ['menu_id','menu_name','menu_url','menu_status','parent_id'], diff --git a/app/Service/Admin/User/RoleMenuService.php b/app/Service/Admin/User/RoleMenuService.php index 27c7a56..7e2e715 100644 --- a/app/Service/Admin/User/RoleMenuService.php +++ b/app/Service/Admin/User/RoleMenuService.php @@ -118,7 +118,7 @@ class RoleMenuService extends BaseService */ public function edit(): array { - $menuId = $this->request->input('menu_id'); + $menuId = (int)$this->request->input('menu_id'); $url = $this->request->input('menu_url'); $oldUrlInfo = $this->adminMenuModel->getMenuByUrl($url); $menuInfo = $this->adminMenuModel->where('id',$menuId)->first(); @@ -213,32 +213,40 @@ class RoleMenuService extends BaseService if (!$res) throw new AdminException('路由不存在'); $res = $res->toArray(); - //闭包函数获取子集 - $res = function() use($res,$menuId) { - $children = $this->adminMenuModel->where('parent_id',$menuId)->select(['type','value','title','id'])->get(); - $res['permissionList'] = []; - if (!empty($children)) { - $children = $children->toArray(); - if ($children[0]['type'] == AuthCode::MENU_TYPE_LIST) { - return $res; - } - - foreach ($children as $one) - { - $res['permissionList'][] = [ - 'id' => $one['id'], - 'label' => $one['title'], - 'value' => $one['value'], - ]; - } - } - - return $res; - }; + //获取子集 + $res = $this->getChildren($res,$menuId); return $this->return->success('success',['info' => $res]); } + /** + * @param $res + * @param $menuId + * @return array + */ + private function getChildren(&$res,$menuId): array + { + $children = $this->adminMenuModel->where('parent_id',$menuId)->get(['type','value','title','id']); + $res['permission_list'] = []; + if (!empty($children)) { + $children = $children->toArray(); + if ($children[0]['type'] == AuthCode::MENU_TYPE_LIST) { + return $res; + } + + foreach ($children as $one) + { + $res['permission_list'][] = [ + 'id' => $one['id'], + 'label' => $one['title'], + 'value' => $one['value'], + ]; + } + } + + return $res; + } + /** * 构建缓存 * @return array diff --git a/app/Service/Admin/User/RoleService.php b/app/Service/Admin/User/RoleService.php index 44de9a9..8112559 100644 --- a/app/Service/Admin/User/RoleService.php +++ b/app/Service/Admin/User/RoleService.php @@ -10,12 +10,18 @@ declare(strict_types=1); namespace App\Service\Admin\User; +use App\Cache\Redis\Admin\MenuCache; +use App\Cache\Redis\Admin\RoleCache; +use App\Constants\Admin\AuthCode; use App\Exception\AdminException; use App\Model\AdminRole; +use App\Model\AdminRoleMenu; use App\Service\Admin\BaseService; use Exception; use Hyperf\DbConnection\Db; use Hyperf\Di\Annotation\Inject; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; class RoleService extends BaseService { @@ -25,6 +31,24 @@ class RoleService extends BaseService #[Inject] protected AdminRole $adminRoleModel; + /** + * @var AdminRoleMenu + */ + #[Inject] + protected AdminRoleMenu $adminRoleMenuModel; + + /** + * @var RoleCache + */ + #[Inject] + protected RoleCache $roleCache; + + /** + * @var MenuCache + */ + #[Inject] + protected MenuCache $menuCache; + /** * 查询字段 * @var array|string[] @@ -37,7 +61,7 @@ class RoleService extends BaseService */ public function handle(): array { - $limit = $this->request->input('limit', 10); + $limit = (int)$this->request->input('limit', 10); $list = $this->adminRoleModel->paginate($limit,$this->field)->toArray(); @@ -45,9 +69,15 @@ class RoleService extends BaseService } - public function add() + /** + * 添加角色 + * @return array + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function add(): array { - $name = $this->request->input('name'); + $name = $this->request->input('role_name'); if ($this->adminRoleModel->getInfoByName($name)) throw new AdminException('角色已存在'); @@ -56,17 +86,29 @@ class RoleService extends BaseService $model = new AdminRole(); $model->name = $name; - $model->status = $this->request->input('status', 1); - $model->remark = $this->request->input('remark', ''); + $model->status = $this->request->input('role_status', 1); + $model->remark = $this->request->input('role_remark', ''); - if (!$model->save()) throw new Exception('添加失败'); - - //todo 添加角色权限 - $menuIdArr = explode(',', $this->request->input('menu_ids')); + if (!$model->save()) throw new Exception('添加失败-角色错误'); + //添加角色权限 + if (!empty($this->request->input('menu_ids'))) + { + $menuIdArr = explode(',', $this->request->input('menu_ids')); + $insertArr = []; + foreach ($menuIdArr as $menuId) { + $insertArr[] = [ + 'role_id' => $model->id, + 'menu_id' => $menuId, + ]; + } + if (!(new AdminRoleMenu)->insert($insertArr)) throw new Exception('添加失败-权限组错误'); + } Db::commit(); + + $this->roleCache->getRoleCache($model->id); } catch (Exception $e) { Db::rollBack(); throw new AdminException($e->getMessage()); @@ -76,26 +118,50 @@ class RoleService extends BaseService } /** - * 修改 + * 修改角色 * @return array + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function edit(): array { - $id = $this->request->input('id'); + $id = (int)$this->request->input('role_id'); if (!$info = $this->adminRoleModel->getInfoById($id)) throw new AdminException('角色不存在'); + $name = $this->request->input('role_name'); + $oldInfo = $this->adminRoleModel->getInfoByName($name); + if ($oldInfo->id != $id) throw new AdminException('角色已存在'); + Db::beginTransaction(); try { - $info->name = $this->request->input('name'); - $info->status = $this->request->input('status', 1); - $info->remark = $this->request->input('remark', ''); + $info->name = $name; + $info->status = $this->request->input('role_status', 1); + $info->remark = $this->request->input('role_remark', ''); - if (!$info->save()) throw new Exception('修改失败'); + if (!$info->save()) throw new Exception('修改失败-角色错误'); - //todo 删除权限 添加角色权限 + //删除权限 添加角色权限 + if (!empty($this->request->input('menu_ids'))) { + //todo 判断数据一致 是否修改 + $this->adminRoleMenuModel->where('role_id', $info->id)->delete(); + + $menuIdArr = explode(',', $this->request->input('menu_ids')); + $insertArr = []; + foreach ($menuIdArr as $menuId) { + $insertArr[] = [ + 'role_id' => $info->id, + 'menu_id' => $menuId, + ]; + } + + if (!(new AdminRoleMenu)->insert($insertArr)) throw new Exception('修改失败-权限组错误'); + } Db::commit(); + + $this->roleCache->delRoleCache($info->id); + $this->roleCache->getRoleCache($info->id); } catch (Exception $e) { Db::rollBack(); throw new AdminException($e->getMessage()); @@ -111,20 +177,24 @@ class RoleService extends BaseService */ public function changeStatus(): array { - $id = $this->request->input('id'); + $id = (int)$this->request->input('role_id'); + if ($id == AuthCode::SUPERADMIN) throw new AdminException('超级管理员不可关闭'); if (!$info = $this->adminRoleModel->getInfoById($id)) throw new AdminException('角色不存在'); - $info->status = $this->request->input('status', 0); + $info->status = $this->request->input('role_status', 0); - if (!$info->save()) throw new Exception('修改失败'); + if (!$info->save()) throw new AdminException('修改失败'); return $this->return->success(); } /** - * 详情 + * 详情角色 * @return array + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + * @throws \RedisException */ public function details(): array { @@ -132,6 +202,14 @@ class RoleService extends BaseService $res = $this->adminRoleModel->where('id',$roleId)->first($this->field); if (!$res) throw new AdminException('角色不存在'); - return $this->return->success('success',['info' => $res->toArray()]); + $data = $this->roleCache->getRoleCache((int)$roleId); + + $menuList = $this->menuCache->getMenu(); + + return $this->return->success('success',[ + 'info' => $res->toArray(), + 'role_arr' => $data['role_arr'], + 'role_list' => $data['role_list'], + ]); } } \ No newline at end of file diff --git a/app/Service/ServiceTrait/AdminRoleMenuTrait.php b/app/Service/ServiceTrait/AdminRoleMenuTrait.php new file mode 100644 index 0000000..8b9bbc6 --- /dev/null +++ b/app/Service/ServiceTrait/AdminRoleMenuTrait.php @@ -0,0 +1,49 @@ +getDbMenu($allMenuList, (int)$menu['id']); + if (!empty($children)) { + //获取第一个 type 如何是菜单 + if ($children[0]['type'] == AuthCode::MENU_TYPE_LIST) { + $menu['children'] = $children; + } else { + foreach ($children as $child) { + $menu['permissionList'][] = [ + 'id' => $child['id'], + 'label' => $child['title'], + 'value' => $child['value'], + ]; + } + } + } + $menuList[] = $menu; + } + } + return $menuList; + } +} \ No newline at end of file diff --git a/sync/http/admin/auth.http b/sync/http/admin/auth.http index 576da56..26bd12e 100644 --- a/sync/http/admin/auth.http +++ b/sync/http/admin/auth.http @@ -18,18 +18,22 @@ POST {{host}}/admin/auth/menu_add Content-Type: application/x-www-form-urlencoded Authorization: Bearer {{admin_token}} +menu_name=第二页&menu_url=/admin/second&menu_icon=fa fa-user&menu_sort=2&menu_status=1&parent_id=0 + ### 权限修改 POST {{host}}/admin/auth/menu_edit Content-Type: application/x-www-form-urlencoded Authorization: Bearer {{admin_token}} +menu_id=11&menu_name=第二页1&menu_url=/admin/second&menu_icon=fa fa-user&menu_sort=2&menu_status=1&parent_id=0 + ### 权限删除 GET {{host}}/admin/auth/menu_del?menu_id=1 Content-Type: application/json Authorization: Bearer {{admin_token}} ### 权限详情 -GET {{host}}/admin/auth/menu?menu_id=1 +GET {{host}}/admin/auth/menu?menu_id=2 Content-Type: application/json Authorization: Bearer {{admin_token}} @@ -45,5 +49,28 @@ GET {{host}}/admin/auth/role?role_id=1 Content-Type: application/json Authorization: Bearer {{admin_token}} +### 角色列表 +GET {{host}}/admin/auth/role_list?limit=10 +Content-Type: application/json +Authorization: Bearer {{admin_token}} -### \ No newline at end of file +### 角色更改状态 +POST {{host}}/admin/auth/role_change_status +Content-Type: application/x-www-form-urlencoded +Authorization: Bearer {{admin_token}} + +role_id=1&role_status=2 + +### 角色添加 +POST {{host}}/admin/auth/role_add +Content-Type: application/x-www-form-urlencoded +Authorization: Bearer {{admin_token}} + +role_name=测试&role_status=1&menu_ids=1,2,3,4,5,6,7,8,9&role_remark=测试 + +### 角色修改 +POST {{host}}/admin/auth/role_edit +Content-Type: application/x-www-form-urlencoded +Authorization: Bearer {{admin_token}} + +role_id=3&role_name=测试&role_status=1&menu_ids=1,2,3,4,5,6,7&role_remark=测试 \ No newline at end of file