From 43b4332d5797cafbe64a4b4c1e15990a095961ee Mon Sep 17 00:00:00 2001 From: jsasg <735273025@qq.com> Date: Tue, 25 Feb 2025 18:14:52 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E8=A7=92=E8=89=B2?= =?UTF-8?q?=E5=88=86=E9=A1=B5/=E8=AF=A6=E6=83=85/=E6=96=B0=E5=A2=9E/?= =?UTF-8?q?=E6=9B=B4=E6=96=B0/=E5=88=A0=E9=99=A4=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/admin/controller/v1/Role.php | 194 ++++++++++++++++++ .../exception/InvalidOperateException.php | 10 + app/admin/model/v1/SysRoleAuthorityModel.php | 12 +- app/admin/model/v1/SysRoleModel.php | 18 +- app/admin/route/v1.php | 19 ++ app/admin/validate/v1/SysRoleValidate.php | 46 +++++ .../model/SysRoleAuthorityBaseModel.php | 23 +++ app/common/model/SysRoleBaseModel.php | 1 - .../20241230062221_create_sys_role.php | 2 +- 9 files changed, 321 insertions(+), 4 deletions(-) create mode 100644 app/admin/controller/v1/Role.php create mode 100644 app/admin/exception/InvalidOperateException.php create mode 100644 app/admin/validate/v1/SysRoleValidate.php create mode 100644 app/common/model/SysRoleAuthorityBaseModel.php diff --git a/app/admin/controller/v1/Role.php b/app/admin/controller/v1/Role.php new file mode 100644 index 00000000..8b4163a8 --- /dev/null +++ b/app/admin/controller/v1/Role.php @@ -0,0 +1,194 @@ +get([ + 'name', + 'page/d' => 1, + 'size/d' => 10 + ]); + + $roles = SysRoleModel::withoutField([ + 'pid', + 'created_at', + 'updated_at', + 'deleted_at' + ]) + ->withSearch(['name'], [ + 'name' => $params['name']??null + ]) + ->order('id', 'desc'); + if (!request()->has('scene')) { + $roles = $roles->paginate([ + 'list_rows' => $params['size'], + 'page' => $params['page'] + ]); + } else if ('all' == request()->get('scene')) { + $roles = $roles->select(); + } + + return success('获取成功', $roles); + } + + // 角色详情 + public function read() + { + $id = request()->param('id'); + + $role = SysRoleModel::withoutField([ + 'pid', + 'created_at', + 'updated_at', + 'deleted_at' + ]) + ->bypk($id) + ->find(); + if (empty($role)) { + return error('角色不存在'); + } + + return success('获取成功', $role); + } + + // 角色新增 + public function save() + { + $post = request()->post([ + 'name', + 'desc', + // $[*].menu_id + // $[*].permissions + 'menu_permission' + ]); + $post['menu_permission'] = json_decode($post['menu_permission'], true); + + $validate = new SysRoleValidate; + if (!$validate->scene('create')->check($post)) { + return error($validate->getError()); + } + + SysRoleModel::startTrans(); + try { + $role = SysRoleModel::create($post, ['name', 'desc']); + if ($role->isEmpty()) { + throw new InvalidOperateException('角色新增失败'); + } + + $permissions = []; + foreach ($post['menu_permission'] as $menu) { + $permissions[] = [ + 'role_id' => $role->id, + 'menu_id' => $menu['menu_id'], + 'permission' => array_reduce($menu['permission'], function($v1, $v2) { + return $v1 | $v2; + }) + ]; + } + $authority = (new SysRoleAuthorityModel)->saveAll($permissions); + if ($authority->isEmpty()) { + throw new InvalidOperateException('角色权限新增失败'); + } + + SysRoleModel::commit(); + } catch (InvalidOperateException $e) { + SysRoleModel::rollback(); + return error($e->getMessage()); + } catch (\Throwable $th) { + SysRoleModel::rollback(); + return error('操作失败'); + } + + return success('操作成功'); + } + + // 角色更新 + public function update() + { + $id = request()->param('id'); + $put = request()->put([ + 'name', + 'desc', + // $[*].menu_id + // $[*].permissions + 'menu_permission' + ]); + $put['menu_permission'] = json_decode($put['menu_permission'], true); + + $validate = new SysRoleValidate; + if (!$validate->scene('update')->check($put)) { + return error($validate->getError()); + } + + SysRoleModel::startTrans(); + try { + $role = SysRoleModel::bypk($id)->find(); + if (empty($rule)) { + throw new InvalidOperateException('角色不存在'); + } + + if (!$role->allowField(['name', 'desc'])->save($put)) { + throw new InvalidOperateException('角色更新失败'); + } + + $permissions = []; + foreach ($put['menu_permission'] as $menu) { + $permissions[] = [ + 'role_id' => $role->id, + 'menu_id' => $menu['menu_id'], + 'permission' => array_reduce($menu['permission'], function($v1, $v2) { + return $v1 | $v2; + }) + ]; + } + + SysRoleAuthorityModel::destroy(function($query) use ($role) { + $query->roleId($role->id); + }); + $authority = (new SysRoleAuthorityModel)->saveAll($permissions); + if ($authority->isEmpty()) { + throw new InvalidOperateException('角色权限更新失败'); + } + + SysRoleModel::commit(); + } catch (InvalidOperateException $e) { + SysRoleModel::rollback(); + return error($e->getMessage()); + } catch (\Throwable $th) { + SysRoleModel::rollback(); + return error('操作失败'); + } + + return success('操作成功'); + } + + // 角色删除 + public function delete() + { + $id = request()->param('id'); + + $role = SysRoleModel::bypk($id)->find(); + if (empty($role)) { + return error('请确认要操作对象是否存在'); + } + + if (!$role->delete()) { + return error('操作失败'); + } + + return success('操作成功'); + } +} diff --git a/app/admin/exception/InvalidOperateException.php b/app/admin/exception/InvalidOperateException.php new file mode 100644 index 00000000..44677bfd --- /dev/null +++ b/app/admin/exception/InvalidOperateException.php @@ -0,0 +1,10 @@ +where('role_id', $value); + } + + // menu_id查询 + public function scopeMenuId($query, $value) + { + return $query->where('menu_id', $value); + } } diff --git a/app/admin/model/v1/SysRoleModel.php b/app/admin/model/v1/SysRoleModel.php index 521b8651..9a82697b 100644 --- a/app/admin/model/v1/SysRoleModel.php +++ b/app/admin/model/v1/SysRoleModel.php @@ -4,11 +4,27 @@ declare (strict_types = 1); namespace app\admin\model\v1; use app\common\model\SysRoleBaseModel; +use think\model\concern\SoftDelete; /** + * 角色模型 * @mixin \think\Model */ class SysRoleModel extends SysRoleBaseModel { - // + // 启用软件删除 + use SoftDelete; + // 软件删除字段 + protected $deleteTime = 'deleted_at'; + // 自动写入时间格式 + protected $autoWriteTimestamp = 'datetime'; + + // 角色名称搜索 + public function searchNameAttr($query, $value, $data) + { + if (empty($value)) { + return; + } + $query->where('name', 'like', "%$value%"); + } } diff --git a/app/admin/route/v1.php b/app/admin/route/v1.php index 8e8bfd2a..ea56e1d9 100644 --- a/app/admin/route/v1.php +++ b/app/admin/route/v1.php @@ -349,6 +349,25 @@ Route::group('v1', function () { // 用户删除 Route::delete('delete/:id', 'User/delete'); }); + + // 角色管理 + Route::get('roles', 'Role/index')->append(['scene' => 'all']); // 角色列表 + Route::group('role', function() { + // 角色分页 + Route::get('index', 'Role/index'); + + // 角色详情 + Route::get('read/:id', 'Role/read'); + + // 角色新增 + Route::post('save', 'Role/save'); + + // 角色更新 + Route::put('update/:id', 'Role/update'); + + // 角色删除 + Route::delete('delete/:id', 'Role/delete'); + }); })->prefix('v1.'); Route::miss(function() { diff --git a/app/admin/validate/v1/SysRoleValidate.php b/app/admin/validate/v1/SysRoleValidate.php new file mode 100644 index 00000000..3b4def68 --- /dev/null +++ b/app/admin/validate/v1/SysRoleValidate.php @@ -0,0 +1,46 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'id' => 'require|integer', + 'pid' => 'integer', + 'name' => 'max:64', + 'desc' => 'max:255', + 'menu_permission.*.menu_id' => 'integer', + 'menu_permission.*.permission' => 'array', + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = [ + 'id.require' => '角色ID不能为空', + 'id.integer' => '角色ID必须为整数', + 'pid.integer' => '父级角色ID必须为整数', + 'name.max' => '角色名称最多64个字符', + 'desc.max' => '角色描述最多255个字符', + 'menu_permission.*.menu_id.integer' => '菜单ID必须为整数', + 'menu_permission.*.permission.array' => '权限必须为数组', + ]; + + // 新增场景校验 + public function sceneCreate() + { + return $this->remove('id', 'require|integer'); + } +} diff --git a/app/common/model/SysRoleAuthorityBaseModel.php b/app/common/model/SysRoleAuthorityBaseModel.php new file mode 100644 index 00000000..b7cf723b --- /dev/null +++ b/app/common/model/SysRoleAuthorityBaseModel.php @@ -0,0 +1,23 @@ + 'int', + 'menu_id' => 'int', + 'permission' => 'int', + ]; +} diff --git a/app/common/model/SysRoleBaseModel.php b/app/common/model/SysRoleBaseModel.php index b01b6bd5..43e8179c 100644 --- a/app/common/model/SysRoleBaseModel.php +++ b/app/common/model/SysRoleBaseModel.php @@ -21,7 +21,6 @@ class SysRoleBaseModel extends BaseModel 'pid' => 'int', 'name' => 'string', 'desc' => 'string', - 'status' => 'int', 'created_at' => 'datetime', 'updated_at' => 'datetime', 'deleted_at' => 'datetime', diff --git a/database/migrations/20241230062221_create_sys_role.php b/database/migrations/20241230062221_create_sys_role.php index 9ddc97cc..603120fd 100644 --- a/database/migrations/20241230062221_create_sys_role.php +++ b/database/migrations/20241230062221_create_sys_role.php @@ -31,9 +31,9 @@ class CreateSysRole extends Migrator $table->addColumn('pid', 'integer', ['null' => false, 'default' => 0, 'comment' => '父级ID']) ->addColumn('name', 'string', ['limit' => 64, 'null' => false, 'comment' => '角色名称']) ->addColumn('desc', 'string', ['limit' => 255, 'null' => false, 'comment' => '角色描述']) - ->addColumn('status', 'boolean', ['null' => false, 'default' => 1, 'comment' => '-1为禁用, 1为启用']) ->addColumn('created_at', 'timestamp', ['null' => false, 'default' => 'CURRENT_TIMESTAMP', 'comment' => '创建时间']) ->addColumn('updated_at', 'timestamp', ['null' => false, 'default' => 'CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP', 'comment' => '更新时间']) + ->addColumn('deleted_at', 'timestamp', ['null' => true, 'default' => null, 'comment' => '删除时间']) ->create(); } }