From 18e466f6822f97b0035660b7d09deed8dce81a89 Mon Sep 17 00:00:00 2001 From: zds <49744633+zds-s@users.noreply.github.com> Date: Mon, 3 Mar 2025 03:13:15 +0800 Subject: [PATCH 01/91] feat(migration): create department, position, and user association tables --- ..._02_24_195620_create_department_tables.php | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 databases/migrations/2025_02_24_195620_create_department_tables.php diff --git a/databases/migrations/2025_02_24_195620_create_department_tables.php b/databases/migrations/2025_02_24_195620_create_department_tables.php new file mode 100644 index 000000000..ade3c6731 --- /dev/null +++ b/databases/migrations/2025_02_24_195620_create_department_tables.php @@ -0,0 +1,83 @@ +comment('部门表'); + $table->bigIncrements('id'); + $table->string('name', 50); + $table->bigInteger('parent_id')->default(0); + $table->datetimes(); + $table->softDeletes(); + }); + Schema::create('position', function (Blueprint $table) { + $table->comment('岗位表'); + $table->bigIncrements('id'); + $table->string('name', 50); + $table->bigInteger('dept_id'); + $table->datetimes(); + $table->softDeletes(); + }); + Schema::create('user_dept', function (Blueprint $table) { + $table->comment('用户-部门关联表'); + $table->bigInteger('user_id'); + $table->bigInteger('dept_id'); + $table->datetimes(); + $table->softDeletes(); + }); + Schema::create('user_position', function (Blueprint $table) { + $table->comment('用户-岗位关联表'); + $table->bigInteger('user_id'); + $table->bigInteger('position_id'); + $table->datetimes(); + $table->softDeletes(); + }); + Schema::create('dept_leader', function (Blueprint $table) { + $table->comment('部门领导表'); + $table->bigInteger('dept_id'); + $table->bigInteger('user_id'); + $table->datetimes(); + $table->softDeletes(); + }); + Schema::create('data_permission_policy', function (Blueprint $table) { + $table->comment('数据权限策略'); + $table->bigIncrements('id'); + $table->bigInteger('user_id')->comment('用户ID(与角色二选一)'); + $table->bigInteger('role_id')->comment('角色ID(与用户二选一)'); + $table->string('policy_type', 20)->comment('策略类型(DEPT_SELF, DEPT_TREE, ALL, SELF, CUSTOM_DEPT, CUSTOM_FUNC)'); + $table->boolean('is_default')->default(true)->comment('是否默认策略(默认值:true)'); + $table->datetimes(); + $table->softDeletes(); + }); + Schema::create('data_permission_custom_func', function (Blueprint $table) { + $table->comment('自定义回调函数表'); + $table->bigInteger('policy_id'); + $table->string('func_key', 50); + $table->datetimes(); + $table->softDeletes(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('department'); + Schema::dropIfExists('position'); + Schema::dropIfExists('user_dept'); + Schema::dropIfExists('user_position'); + Schema::dropIfExists('dept_leader'); + Schema::dropIfExists('data_permission_policy'); + Schema::dropIfExists('data_permission_custom_func'); + } +}; From 0c6a843aac8c33c9ea4edd8671818caa260e3850 Mon Sep 17 00:00:00 2001 From: zds <49744633+zds-s@users.noreply.github.com> Date: Mon, 3 Mar 2025 03:47:13 +0800 Subject: [PATCH 02/91] feat(database): enhance department and position tables with comments and defaults; add PolicyType enum for data permission policies --- .../Enums/DataPermissionPolicy/PolicyType.php | 81 +++++++++++++++++++ app/Model/Permission/DataPermissionPolicy.php | 38 +++++++++ app/Model/Permission/Department.php | 58 +++++++++++++ app/Model/Permission/Position.php | 51 ++++++++++++ ..._02_24_195620_create_department_tables.php | 16 ++-- 5 files changed, 236 insertions(+), 8 deletions(-) create mode 100644 app/Model/Enums/DataPermissionPolicy/PolicyType.php create mode 100644 app/Model/Permission/DataPermissionPolicy.php create mode 100644 app/Model/Permission/Department.php create mode 100644 app/Model/Permission/Position.php diff --git a/app/Model/Enums/DataPermissionPolicy/PolicyType.php b/app/Model/Enums/DataPermissionPolicy/PolicyType.php new file mode 100644 index 000000000..f7e0f9ad6 --- /dev/null +++ b/app/Model/Enums/DataPermissionPolicy/PolicyType.php @@ -0,0 +1,81 @@ +isDeptSelf(); + } + + public function isNotDeptTree(): bool + { + return !$this->isDeptTree(); + } + + public function isNotAll(): bool + { + return !$this->isAll(); + } + + public function isNotSelf(): bool + { + return !$this->isSelf(); + } + + public function isNotCustomDept(): bool + { + return !$this->isCustomDept(); + } + + public function isNotCustomFunc(): bool + { + return !$this->isCustomFunc(); + } +} diff --git a/app/Model/Permission/DataPermissionPolicy.php b/app/Model/Permission/DataPermissionPolicy.php new file mode 100644 index 000000000..5e9b9bea3 --- /dev/null +++ b/app/Model/Permission/DataPermissionPolicy.php @@ -0,0 +1,38 @@ + 'integer', 'user_id' => 'integer', 'role_id' => 'integer', 'is_default' => 'bool', 'created_at' => 'datetime', 'updated_at' => 'datetime', 'deleted_at' => 'datetime']; +} diff --git a/app/Model/Permission/Department.php b/app/Model/Permission/Department.php new file mode 100644 index 000000000..d42146a7f --- /dev/null +++ b/app/Model/Permission/Department.php @@ -0,0 +1,58 @@ + $positions 岗位 + * @property-read User[]|Collection $department_users 部门用户 + * @property-read User[]|Collection $leader 部门领导 + */ +class Department extends Model +{ + use SoftDeletes; + /** + * The table associated with the model. + */ + protected ?string $table = 'department'; + + /** + * The attributes that are mass assignable. + */ + protected array $fillable = ['id', 'name', 'parent_id', 'created_at', 'updated_at', 'deleted_at']; + + /** + * The attributes that should be cast to native types. + */ + protected array $casts = ['id' => 'integer', 'parent_id' => 'integer', 'created_at' => 'datetime', 'updated_at' => 'datetime', 'deleted_at' => 'datetime']; + + public function positions(): HasMany + { + return $this->hasMany(Position::class, 'dept_id', 'id'); + } + + public function department_users(): BelongsToMany + { + return $this->belongsToMany(User::class, 'user_dept', 'dept_id', 'user_id'); + } + + public function leaders(): BelongsToMany + { + return $this->belongsToMany(User::class, 'user_leader', 'dept_id', 'user_id'); + } + +} diff --git a/app/Model/Permission/Position.php b/app/Model/Permission/Position.php new file mode 100644 index 000000000..3742b68ef --- /dev/null +++ b/app/Model/Permission/Position.php @@ -0,0 +1,51 @@ + $users + */ +class Position extends Model +{ + use SoftDeletes; + /** + * The table associated with the model. + */ + protected ?string $table = 'position'; + + /** + * The attributes that are mass assignable. + */ + protected array $fillable = ['id', 'name', 'dept_id', 'created_at', 'updated_at', 'deleted_at']; + + /** + * The attributes that should be cast to native types. + */ + protected array $casts = ['id' => 'integer', 'dept_id' => 'integer', 'created_at' => 'datetime', 'updated_at' => 'datetime', 'deleted_at' => 'datetime']; + + public function department(): BelongsTo + { + return $this->belongsTo(Department::class, 'dept_id', 'id'); + } + + public function users(): BelongsToMany + { + return $this->belongsToMany(User::class, 'user_position', 'position_id', 'user_id'); + } +} diff --git a/databases/migrations/2025_02_24_195620_create_department_tables.php b/databases/migrations/2025_02_24_195620_create_department_tables.php index ade3c6731..00eefdd73 100644 --- a/databases/migrations/2025_02_24_195620_create_department_tables.php +++ b/databases/migrations/2025_02_24_195620_create_department_tables.php @@ -14,16 +14,16 @@ public function up(): void Schema::create('department', function (Blueprint $table) { $table->comment('部门表'); $table->bigIncrements('id'); - $table->string('name', 50); - $table->bigInteger('parent_id')->default(0); + $table->string('name', 50)->comment('部门名称'); + $table->bigInteger('parent_id')->default(0)->comment('父级部门ID'); $table->datetimes(); $table->softDeletes(); }); Schema::create('position', function (Blueprint $table) { $table->comment('岗位表'); $table->bigIncrements('id'); - $table->string('name', 50); - $table->bigInteger('dept_id'); + $table->string('name', 50)->comment('岗位名称'); + $table->bigInteger('dept_id')->comment('部门ID'); $table->datetimes(); $table->softDeletes(); }); @@ -51,8 +51,8 @@ public function up(): void Schema::create('data_permission_policy', function (Blueprint $table) { $table->comment('数据权限策略'); $table->bigIncrements('id'); - $table->bigInteger('user_id')->comment('用户ID(与角色二选一)'); - $table->bigInteger('role_id')->comment('角色ID(与用户二选一)'); + $table->bigInteger('user_id')->default(0)->comment('用户ID(与角色二选一)'); + $table->bigInteger('role_id')->default(0)->comment('角色ID(与用户二选一)'); $table->string('policy_type', 20)->comment('策略类型(DEPT_SELF, DEPT_TREE, ALL, SELF, CUSTOM_DEPT, CUSTOM_FUNC)'); $table->boolean('is_default')->default(true)->comment('是否默认策略(默认值:true)'); $table->datetimes(); @@ -60,8 +60,8 @@ public function up(): void }); Schema::create('data_permission_custom_func', function (Blueprint $table) { $table->comment('自定义回调函数表'); - $table->bigInteger('policy_id'); - $table->string('func_key', 50); + $table->bigInteger('policy_id')->comment('数据权限策略ID'); + $table->string('func_key', 50)->comment('回调函数KEY'); $table->datetimes(); $table->softDeletes(); }); From 299ec61ff359c429a58d7e5325aaeb0a9af2bc90 Mon Sep 17 00:00:00 2001 From: zds <49744633+zds-s@users.noreply.github.com> Date: Mon, 3 Mar 2025 03:49:39 +0800 Subject: [PATCH 03/91] feat(model): update DataPermissionPolicy to use PolicyType enum for policy_type property --- app/Model/Permission/DataPermissionPolicy.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/app/Model/Permission/DataPermissionPolicy.php b/app/Model/Permission/DataPermissionPolicy.php index 5e9b9bea3..8fed74f0d 100644 --- a/app/Model/Permission/DataPermissionPolicy.php +++ b/app/Model/Permission/DataPermissionPolicy.php @@ -4,6 +4,7 @@ namespace App\Model\Permission; +use App\Model\Enums\DataPermissionPolicy\PolicyType; use Carbon\Carbon; use Hyperf\Database\Model\SoftDeletes; use Hyperf\DbConnection\Model\Model; @@ -12,7 +13,7 @@ * @property int $id * @property int $user_id 用户ID(与角色二选一) * @property int $role_id 角色ID(与用户二选一) - * @property string $policy_type 策略类型(DEPT_SELF, DEPT_TREE, ALL, SELF, CUSTOM_DEPT, CUSTOM_FUNC) + * @property PolicyType $policy_type 策略类型(DEPT_SELF, DEPT_TREE, ALL, SELF, CUSTOM_DEPT, CUSTOM_FUNC) * @property bool $is_default 是否默认策略(默认值:true) * @property Carbon $created_at * @property Carbon $updated_at @@ -34,5 +35,10 @@ class DataPermissionPolicy extends Model /** * The attributes that should be cast to native types. */ - protected array $casts = ['id' => 'integer', 'user_id' => 'integer', 'role_id' => 'integer', 'is_default' => 'bool', 'created_at' => 'datetime', 'updated_at' => 'datetime', 'deleted_at' => 'datetime']; + protected array $casts = [ + 'id' => 'integer', 'user_id' => 'integer', 'role_id' => 'integer', + 'is_default' => 'bool', 'created_at' => 'datetime', + 'updated_at' => 'datetime', 'deleted_at' => 'datetime', + 'policy_type' => PolicyType::class + ]; } From 8d195745c9e0f14f873f778e755ba83d1af123f8 Mon Sep 17 00:00:00 2001 From: zds <49744633+zds-s@users.noreply.github.com> Date: Mon, 3 Mar 2025 03:54:53 +0800 Subject: [PATCH 04/91] feat: refactor DataPermissionPolicy and PolicyType to improve namespace structure and enhance role/user associations --- .../Policy.php} | 6 +++--- .../PolicyType.php | 2 +- app/Model/Permission/Role.php | 9 +++++++++ app/Model/Permission/User.php | 9 +++++++++ 4 files changed, 22 insertions(+), 4 deletions(-) rename app/Model/{Permission/DataPermissionPolicy.php => DataPermission/Policy.php} (90%) rename app/Model/Enums/{DataPermissionPolicy => DataPermission}/PolicyType.php (96%) diff --git a/app/Model/Permission/DataPermissionPolicy.php b/app/Model/DataPermission/Policy.php similarity index 90% rename from app/Model/Permission/DataPermissionPolicy.php rename to app/Model/DataPermission/Policy.php index 8fed74f0d..fdc818821 100644 --- a/app/Model/Permission/DataPermissionPolicy.php +++ b/app/Model/DataPermission/Policy.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace App\Model\Permission; +namespace App\Model\DataPermission; -use App\Model\Enums\DataPermissionPolicy\PolicyType; +use App\Model\Enums\DataPermission\PolicyType; use Carbon\Carbon; use Hyperf\Database\Model\SoftDeletes; use Hyperf\DbConnection\Model\Model; @@ -19,7 +19,7 @@ * @property Carbon $updated_at * @property Carbon $deleted_at */ -class DataPermissionPolicy extends Model +class Policy extends Model { use SoftDeletes; /** diff --git a/app/Model/Enums/DataPermissionPolicy/PolicyType.php b/app/Model/Enums/DataPermission/PolicyType.php similarity index 96% rename from app/Model/Enums/DataPermissionPolicy/PolicyType.php rename to app/Model/Enums/DataPermission/PolicyType.php index f7e0f9ad6..cbaaffb99 100644 --- a/app/Model/Enums/DataPermissionPolicy/PolicyType.php +++ b/app/Model/Enums/DataPermission/PolicyType.php @@ -1,6 +1,6 @@ users()->detach(); $this->menus()->detach(); } + + + public function policy(): BelongsTo + { + return $this->belongsTo(Policy::class, 'policy_id', 'id'); + } } diff --git a/app/Model/Permission/User.php b/app/Model/Permission/User.php index 313b47282..215281271 100644 --- a/app/Model/Permission/User.php +++ b/app/Model/Permission/User.php @@ -12,12 +12,14 @@ namespace App\Model\Permission; +use App\Model\DataPermission\Policy; use App\Model\Enums\User\Status; use App\Model\Enums\User\Type; use Carbon\Carbon; use Hyperf\Collection\Collection; use Hyperf\Database\Model\Events\Creating; use Hyperf\Database\Model\Events\Deleted; +use Hyperf\Database\Model\Relations\BelongsTo; use Hyperf\Database\Model\Relations\BelongsToMany; use Hyperf\DbConnection\Model\Model; @@ -41,6 +43,7 @@ * @property string $remark 备注 * @property null|Collection|Role[] $roles * @property mixed $password 密码 + * @property Policy|null $policy 数据权限策略 */ final class User extends Model { @@ -136,4 +139,10 @@ public function hasPermission(string $permission): bool { return $this->roles()->whereRelation('menus', 'name', $permission)->exists(); } + + + public function policy(): BelongsTo + { + return $this->belongsTo(Policy::class, 'id', 'id'); + } } From ccd5355e140242ef9d05c315935f46262863d8d5 Mon Sep 17 00:00:00 2001 From: zds <49744633+zds-s@users.noreply.github.com> Date: Thu, 6 Mar 2025 00:16:23 +0800 Subject: [PATCH 05/91] feat: enhance role and policy management with new schema and properties --- .../Admin/Request/Permission/RoleRequest.php | 21 ++++++++- app/Model/DataPermission/Policy.php | 16 +++++-- app/Model/Enums/DataPermission/PolicyType.php | 29 +++++++----- app/Model/Permission/Department.php | 18 +++++--- app/Model/Permission/Position.php | 17 +++++-- app/Model/Permission/Role.php | 3 +- app/Model/Permission/User.php | 3 +- app/Repository/Permission/RoleRepository.php | 23 ++++++---- app/Schema/PolicySchema.php | 45 +++++++++++++++++++ app/Schema/RoleSchema.php | 6 ++- app/Service/Permission/RoleService.php | 33 ++++++++++++++ ..._02_24_195620_create_department_tables.php | 8 +--- 12 files changed, 176 insertions(+), 46 deletions(-) create mode 100644 app/Schema/PolicySchema.php diff --git a/app/Http/Admin/Request/Permission/RoleRequest.php b/app/Http/Admin/Request/Permission/RoleRequest.php index ab9d96fa8..b1188d2e9 100644 --- a/app/Http/Admin/Request/Permission/RoleRequest.php +++ b/app/Http/Admin/Request/Permission/RoleRequest.php @@ -14,13 +14,15 @@ use App\Http\Common\Request\Traits\HttpMethodTrait; use App\Http\Common\Request\Traits\NoAuthorizeTrait; +use App\Model\Enums\DataPermission\PolicyType; use App\Schema\RoleSchema; use Hyperf\Validation\Request\FormRequest; +use Hyperf\Validation\Rule; #[\Mine\Swagger\Attributes\FormRequest( schema: RoleSchema::class, only: [ - 'name', 'code', 'status', 'sort', 'remark', + 'name', 'code', 'status', 'sort', 'remark', 'policy', ] )] class RoleRequest extends FormRequest @@ -41,6 +43,23 @@ public function rules(): array 'status' => 'sometimes|integer|in:1,2', 'sort' => 'required|integer', 'remark' => 'nullable|string|max:255', + 'policy' => 'nullable|array', + 'policy.*.policy_type' => [ + 'required_with:policy', + 'string', + 'max:10', + Rule::enum(PolicyType::class), + ], + 'policy.*.value' => [ + 'required_with:policy', + 'array', + 'min:1', + ], + 'policy.*.is_default' => [ + 'required_with:policy', + 'integer', + 'in:0,1', + ], ]; if ($this->isCreate()) { $rules['code'][] = 'unique:role,code'; diff --git a/app/Model/DataPermission/Policy.php b/app/Model/DataPermission/Policy.php index fdc818821..48e62a4cd 100644 --- a/app/Model/DataPermission/Policy.php +++ b/app/Model/DataPermission/Policy.php @@ -1,6 +1,14 @@ 'integer', 'user_id' => 'integer', 'role_id' => 'integer', 'is_default' => 'bool', 'created_at' => 'datetime', 'updated_at' => 'datetime', 'deleted_at' => 'datetime', - 'policy_type' => PolicyType::class + 'policy_type' => PolicyType::class, 'value' => 'array', ]; } diff --git a/app/Model/Enums/DataPermission/PolicyType.php b/app/Model/Enums/DataPermission/PolicyType.php index cbaaffb99..167d3f93f 100644 --- a/app/Model/Enums/DataPermission/PolicyType.php +++ b/app/Model/Enums/DataPermission/PolicyType.php @@ -1,22 +1,27 @@ isDeptSelf(); + return ! $this->isDeptSelf(); } public function isNotDeptTree(): bool { - return !$this->isDeptTree(); + return ! $this->isDeptTree(); } public function isNotAll(): bool { - return !$this->isAll(); + return ! $this->isAll(); } public function isNotSelf(): bool { - return !$this->isSelf(); + return ! $this->isSelf(); } public function isNotCustomDept(): bool { - return !$this->isCustomDept(); + return ! $this->isCustomDept(); } public function isNotCustomFunc(): bool { - return !$this->isCustomFunc(); + return ! $this->isCustomFunc(); } } diff --git a/app/Model/Permission/Department.php b/app/Model/Permission/Department.php index d42146a7f..e4ae3d4d3 100644 --- a/app/Model/Permission/Department.php +++ b/app/Model/Permission/Department.php @@ -1,6 +1,14 @@ $positions 岗位 - * @property-read User[]|Collection $department_users 部门用户 - * @property-read User[]|Collection $leader 部门领导 + * @property Collection|Position[] $positions 岗位 + * @property Collection|User[] $department_users 部门用户 + * @property Collection|User[] $leader 部门领导 */ class Department extends Model { use SoftDeletes; + /** * The table associated with the model. */ @@ -54,5 +63,4 @@ public function leaders(): BelongsToMany { return $this->belongsToMany(User::class, 'user_leader', 'dept_id', 'user_id'); } - } diff --git a/app/Model/Permission/Position.php b/app/Model/Permission/Position.php index 3742b68ef..1f7d4e12a 100644 --- a/app/Model/Permission/Position.php +++ b/app/Model/Permission/Position.php @@ -1,29 +1,38 @@ $users + * @property null|Department $department + * @property Collection|User[] $users */ class Position extends Model { use SoftDeletes; + /** * The table associated with the model. */ diff --git a/app/Model/Permission/Role.php b/app/Model/Permission/Role.php index d0ad80364..852316258 100644 --- a/app/Model/Permission/Role.php +++ b/app/Model/Permission/Role.php @@ -35,7 +35,7 @@ * @property string $remark 备注 * @property Collection|Menu[] $menus * @property Collection|User[] $users - * @property Policy|null $policy 数据权限策略 + * @property null|Policy $policy 数据权限策略 */ final class Role extends MineModel { @@ -94,7 +94,6 @@ public function deleting(Deleting $event) $this->menus()->detach(); } - public function policy(): BelongsTo { return $this->belongsTo(Policy::class, 'policy_id', 'id'); diff --git a/app/Model/Permission/User.php b/app/Model/Permission/User.php index 215281271..0f301a672 100644 --- a/app/Model/Permission/User.php +++ b/app/Model/Permission/User.php @@ -43,7 +43,7 @@ * @property string $remark 备注 * @property null|Collection|Role[] $roles * @property mixed $password 密码 - * @property Policy|null $policy 数据权限策略 + * @property null|Policy $policy 数据权限策略 */ final class User extends Model { @@ -140,7 +140,6 @@ public function hasPermission(string $permission): bool return $this->roles()->whereRelation('menus', 'name', $permission)->exists(); } - public function policy(): BelongsTo { return $this->belongsTo(Policy::class, 'id', 'id'); diff --git a/app/Repository/Permission/RoleRepository.php b/app/Repository/Permission/RoleRepository.php index da1a9be20..91d240802 100644 --- a/app/Repository/Permission/RoleRepository.php +++ b/app/Repository/Permission/RoleRepository.php @@ -25,14 +25,19 @@ public function __construct( public function handleSearch(Builder $query, array $params): Builder { - return $query->when(Arr::get($params, 'name'), static function (Builder $query, $name) { - $query->where('name', 'like', '%' . $name . '%'); - })->when(Arr::get($params, 'code'), static function (Builder $query, $code) { - $query->whereIn('code', Arr::wrap($code)); - })->when(Arr::has($params, 'status'), static function (Builder $query) use ($params) { - $query->where('status', $params['status']); - })->when(Arr::get($params, 'created_at'), static function (Builder $query, $createdAt) { - $query->whereBetween('created_at', $createdAt); - }); + return $query + ->when(Arr::get($params, 'name'), static function (Builder $query, $name) { + $query->where('name', 'like', '%' . $name . '%'); + }) + ->when(Arr::get($params, 'code'), static function (Builder $query, $code) { + $query->whereIn('code', Arr::wrap($code)); + }) + ->when(Arr::has($params, 'status'), static function (Builder $query) use ($params) { + $query->where('status', $params['status']); + }) + ->when(Arr::get($params, 'created_at'), static function (Builder $query, $createdAt) { + $query->whereBetween('created_at', $createdAt); + }) + ->with(['policy']); } } diff --git a/app/Schema/PolicySchema.php b/app/Schema/PolicySchema.php new file mode 100644 index 000000000..f31abcd5a --- /dev/null +++ b/app/Schema/PolicySchema.php @@ -0,0 +1,45 @@ + $this->policyType->value, + 'is_default' => $this->isDefault, + 'value' => $this->value, + ]; + } +} diff --git a/app/Schema/RoleSchema.php b/app/Schema/RoleSchema.php index c1ce4bad3..98f7169a4 100644 --- a/app/Schema/RoleSchema.php +++ b/app/Schema/RoleSchema.php @@ -53,6 +53,9 @@ final class RoleSchema implements \JsonSerializable #[Property(property: 'remark', title: '备注', type: 'string')] public ?string $remark; + #[Property(property: 'policy', ref: '#/components/schemas/PolicySchema', title: '权限')] + public ?PolicySchema $policy; + public function __construct(Role $model) { $this->id = $model->id; @@ -66,10 +69,11 @@ public function __construct(Role $model) $this->createdAt = $model->created_at; $this->updatedAt = $model->updated_at->format(CarbonInterface::DEFAULT_TO_STRING_FORMAT); $this->remark = $model->remark; + $this->policy = isset($model->policy) ? new PolicySchema($model->policy) : null; } public function jsonSerialize(): mixed { - return ['id' => $this->id, 'name' => $this->name, 'code' => $this->code, 'data_scope' => $this->dataScope, 'status' => $this->status, 'sort' => $this->sort, 'created_by' => $this->createdBy, 'updated_by' => $this->updatedBy, 'created_at' => $this->createdAt, 'updated_at' => $this->updatedAt, 'remark' => $this->remark]; + return ['id' => $this->id, 'name' => $this->name, 'code' => $this->code, 'data_scope' => $this->dataScope, 'status' => $this->status, 'sort' => $this->sort, 'created_by' => $this->createdBy, 'updated_by' => $this->updatedBy, 'created_at' => $this->createdAt, 'updated_at' => $this->updatedAt, 'remark' => $this->remark, 'policy' => $this->policy->jsonSerialize()]; } } diff --git a/app/Service/Permission/RoleService.php b/app/Service/Permission/RoleService.php index fc92da29c..092693a29 100644 --- a/app/Service/Permission/RoleService.php +++ b/app/Service/Permission/RoleService.php @@ -12,11 +12,14 @@ namespace App\Service\Permission; +use App\Exception\BusinessException; +use App\Http\Common\ResultCode; use App\Model\Permission\Role; use App\Repository\Permission\MenuRepository; use App\Repository\Permission\RoleRepository; use App\Service\IService; use Hyperf\Collection\Collection; +use Hyperf\DbConnection\Db; /** * @extends IService @@ -53,4 +56,34 @@ public function batchGrantPermissionsForRole(int $id, array $permissionsCode): v ->toArray() ); } + + public function create(array $data): mixed + { + return Db::transaction(function () use ($data) { + /** + * @var Role $entity + */ + $entity = parent::create($data); + if (isset($data['policy'])) { + $entity->policy()->create($data['policy']); + } + }); + } + + public function updateById(mixed $id, array $data): mixed + { + return Db::transaction(function () use ($id, $data) { + /** + * @var Role $entity + */ + $entity = $this->repository->findById($id); + if (empty($entity)) { + throw new BusinessException(code: ResultCode::NOT_FOUND); + } + $entity->update($data); + if (isset($data['policy'])) { + $entity->policy()->update($data['policy']); + } + }); + } } diff --git a/databases/migrations/2025_02_24_195620_create_department_tables.php b/databases/migrations/2025_02_24_195620_create_department_tables.php index 00eefdd73..236c9346c 100644 --- a/databases/migrations/2025_02_24_195620_create_department_tables.php +++ b/databases/migrations/2025_02_24_195620_create_department_tables.php @@ -55,13 +55,7 @@ public function up(): void $table->bigInteger('role_id')->default(0)->comment('角色ID(与用户二选一)'); $table->string('policy_type', 20)->comment('策略类型(DEPT_SELF, DEPT_TREE, ALL, SELF, CUSTOM_DEPT, CUSTOM_FUNC)'); $table->boolean('is_default')->default(true)->comment('是否默认策略(默认值:true)'); - $table->datetimes(); - $table->softDeletes(); - }); - Schema::create('data_permission_custom_func', function (Blueprint $table) { - $table->comment('自定义回调函数表'); - $table->bigInteger('policy_id')->comment('数据权限策略ID'); - $table->string('func_key', 50)->comment('回调函数KEY'); + $table->json('value')->nullable()->comment('策略值'); $table->datetimes(); $table->softDeletes(); }); From 7a4d7c1d431190ae0d95011750ae03c27f00a106 Mon Sep 17 00:00:00 2001 From: zds <49744633+zds-s@users.noreply.github.com> Date: Thu, 6 Mar 2025 00:27:15 +0800 Subject: [PATCH 06/91] feat: enhance user management with policy handling in requests and services --- .../Admin/Request/Permission/RoleRequest.php | 4 +-- .../Admin/Request/Permission/UserRequest.php | 20 +++++++++++++ app/Repository/Permission/UserRepository.php | 3 +- app/Schema/UserSchema.php | 4 +++ app/Service/Permission/UserService.php | 29 +++++++++++++++++++ 5 files changed, 57 insertions(+), 3 deletions(-) diff --git a/app/Http/Admin/Request/Permission/RoleRequest.php b/app/Http/Admin/Request/Permission/RoleRequest.php index b1188d2e9..3e8ae9e7f 100644 --- a/app/Http/Admin/Request/Permission/RoleRequest.php +++ b/app/Http/Admin/Request/Permission/RoleRequest.php @@ -51,12 +51,12 @@ public function rules(): array Rule::enum(PolicyType::class), ], 'policy.*.value' => [ - 'required_with:policy', + 'sometimes', 'array', 'min:1', ], 'policy.*.is_default' => [ - 'required_with:policy', + 'sometimes', 'integer', 'in:0,1', ], diff --git a/app/Http/Admin/Request/Permission/UserRequest.php b/app/Http/Admin/Request/Permission/UserRequest.php index 33c1af077..201332ce8 100644 --- a/app/Http/Admin/Request/Permission/UserRequest.php +++ b/app/Http/Admin/Request/Permission/UserRequest.php @@ -13,8 +13,10 @@ namespace App\Http\Admin\Request\Permission; use App\Http\Common\Request\Traits\NoAuthorizeTrait; +use App\Model\Enums\DataPermission\PolicyType; use App\Schema\UserSchema; use Hyperf\Validation\Request\FormRequest; +use Hyperf\Validation\Rule; use Mine\Swagger\Attributes\FormRequest as FormRequestAnnotation; #[FormRequestAnnotation( @@ -43,6 +45,7 @@ 'status', 'backend_setting', 'remark', + 'policy', ] )] class UserRequest extends FormRequest @@ -62,6 +65,23 @@ public function rules(): array 'status' => 'sometimes|integer', 'backend_setting' => 'sometimes|array|max:255', 'remark' => 'sometimes|string|max:255', + 'policy' => 'sometimes|array', + 'policy.*.policy_type' => [ + 'required_with:policy', + 'string', + 'max:10', + Rule::enum(PolicyType::class), + ], + 'policy.*.value' => [ + 'sometimes', + 'array', + 'min:1', + ], + 'policy.*.is_default' => [ + 'sometimes', + 'integer', + 'in:0,1', + ], ]; } diff --git a/app/Repository/Permission/UserRepository.php b/app/Repository/Permission/UserRepository.php index 000858318..ce37714ea 100644 --- a/app/Repository/Permission/UserRepository.php +++ b/app/Repository/Permission/UserRepository.php @@ -72,6 +72,7 @@ public function handleSearch(Builder $query, array $params): Builder $query->whereHas('roles', static function (Builder $query) use ($roleId) { $query->where('role_id', $roleId); }); - }); + }) + ->with(['policy']); } } diff --git a/app/Schema/UserSchema.php b/app/Schema/UserSchema.php index c51e59385..1e5e00aad 100644 --- a/app/Schema/UserSchema.php +++ b/app/Schema/UserSchema.php @@ -72,6 +72,9 @@ final class UserSchema implements \JsonSerializable #[Property(property: 'remark', title: '备注', type: 'string')] public ?string $remark; + #[Property(property: 'policy', ref: '#/components/schemas/PolicySchema', title: '权限')] + public ?PolicySchema $policy; + public function __construct(User $model) { $this->id = $model->id; @@ -91,6 +94,7 @@ public function __construct(User $model) $this->createdAt = $model->created_at; $this->updatedAt = $model->updated_at; $this->remark = $model->remark; + $this->policy = isset($model->policy) ? new PolicySchema($model->policy) : null; } public function jsonSerialize(): mixed diff --git a/app/Service/Permission/UserService.php b/app/Service/Permission/UserService.php index 211c3cb1d..cd345f5ee 100644 --- a/app/Service/Permission/UserService.php +++ b/app/Service/Permission/UserService.php @@ -12,12 +12,15 @@ namespace App\Service\Permission; +use App\Exception\BusinessException; +use App\Http\Common\ResultCode; use App\Model\Permission\Role; use App\Model\Permission\User; use App\Repository\Permission\RoleRepository; use App\Repository\Permission\UserRepository; use App\Service\IService; use Hyperf\Collection\Collection; +use Hyperf\DbConnection\Db; /** * @extends IService @@ -69,4 +72,30 @@ public function batchGrantRoleForUser(int $id, array $roleCodes): void }) ); } + + public function create(array $data): mixed + { + return Db::transaction(function () use ($data) { + /** @var User $entity */ + $entity = parent::create($data); + if (! empty($data['policy'])) { + $entity->policy()->create($data['policy']); + } + }); + } + + public function updateById(mixed $id, array $data): mixed + { + return Db::transaction(function () use ($id, $data) { + /** @var User $entity */ + $entity = $this->repository->findById($id); + if (empty($entity)) { + throw new BusinessException(ResultCode::NOT_FOUND); + } + $entity->fill($data)->save(); + if (! empty($data['policy'])) { + $entity->policy()->update($data['policy']); + } + }); + } } From dc92609e582177d075d73c118e87bb0693e84893 Mon Sep 17 00:00:00 2001 From: zds <49744633+zds-s@users.noreply.github.com> Date: Thu, 6 Mar 2025 00:27:56 +0800 Subject: [PATCH 07/91] feat: ensure policy deletion on role and user removal --- app/Model/Permission/Role.php | 1 + app/Model/Permission/User.php | 1 + 2 files changed, 2 insertions(+) diff --git a/app/Model/Permission/Role.php b/app/Model/Permission/Role.php index 852316258..ed2d207dc 100644 --- a/app/Model/Permission/Role.php +++ b/app/Model/Permission/Role.php @@ -92,6 +92,7 @@ public function deleting(Deleting $event) { $this->users()->detach(); $this->menus()->detach(); + $this->policy()->delete(); } public function policy(): BelongsTo diff --git a/app/Model/Permission/User.php b/app/Model/Permission/User.php index 0f301a672..14c40b61c 100644 --- a/app/Model/Permission/User.php +++ b/app/Model/Permission/User.php @@ -90,6 +90,7 @@ public function roles(): BelongsToMany public function deleted(Deleted $event) { $this->roles()->detach(); + $this->policy()->delete(); } public function setPasswordAttribute($value): void From 8befc9cf3bfd02286c1b64dfb114178483c6b570 Mon Sep 17 00:00:00 2001 From: zds <49744633+zds-s@users.noreply.github.com> Date: Thu, 6 Mar 2025 01:04:27 +0800 Subject: [PATCH 08/91] feat: add Department management functionality with controller, service, repository, request, and schema --- .../Permission/DepartmentController.php | 121 ++++++++++++++++++ .../Request/Permission/DepartmentRequest.php | 64 +++++++++ .../Permission/DepartmentRepository.php | 52 ++++++++ app/Schema/DepartmentSchema.php | 59 +++++++++ app/Service/Permission/DepartmentService.php | 27 ++++ ..._02_24_195620_create_department_tables.php | 50 +++++++- 6 files changed, 372 insertions(+), 1 deletion(-) create mode 100644 app/Http/Admin/Controller/Permission/DepartmentController.php create mode 100644 app/Http/Admin/Request/Permission/DepartmentRequest.php create mode 100644 app/Repository/Permission/DepartmentRepository.php create mode 100644 app/Schema/DepartmentSchema.php create mode 100644 app/Service/Permission/DepartmentService.php diff --git a/app/Http/Admin/Controller/Permission/DepartmentController.php b/app/Http/Admin/Controller/Permission/DepartmentController.php new file mode 100644 index 000000000..b4eb40480 --- /dev/null +++ b/app/Http/Admin/Controller/Permission/DepartmentController.php @@ -0,0 +1,121 @@ + [], 'ApiKey' => []]], + tags: ['岗位管理'], + )] + #[PageResponse(instance: DepartmentSchema::class)] + #[Permission(code: 'permission:department:index')] + public function pageList(): Result + { + return $this->success( + $this->service->page( + $this->getRequestData(), + $this->getCurrentPage(), + $this->getPageSize() + ) + ); + } + + #[Post( + path: '/admin/department', + operationId: 'roleCreate', + summary: '创建岗位', + security: [['Bearer' => [], 'ApiKey' => []]], + tags: ['岗位管理'], + )] + #[RequestBody( + content: new JsonContent(ref: DepartmentRequest::class) + )] + #[Permission(code: 'permission:department:save')] + #[ResultResponse(instance: new Result())] + public function create(DepartmentRequest $request): Result + { + $this->service->create(array_merge($request->validated(), [ + 'created_by' => $this->currentUser->id(), + ])); + return $this->success(); + } + + #[Put( + path: '/admin/department/{id}', + operationId: 'roleSave', + summary: '保存岗位', + security: [['Bearer' => [], 'ApiKey' => []]], + tags: ['岗位管理'], + )] + #[RequestBody( + content: new JsonContent(ref: DepartmentRequest::class) + )] + #[Permission(code: 'permission:department:update')] + #[ResultResponse(instance: new Result())] + public function save(int $id, DepartmentRequest $request): Result + { + $this->service->updateById($id, array_merge($request->validated(), [ + 'updated_by' => $this->currentUser->id(), + ])); + return $this->success(); + } + + #[Delete( + path: '/admin/department', + operationId: 'roleDelete', + summary: '删除岗位', + security: [['Bearer' => [], 'ApiKey' => []]], + tags: ['岗位管理'], + )] + #[ResultResponse(instance: new Result())] + #[Permission(code: 'permission:department:delete')] + public function delete(): Result + { + $this->service->deleteById($this->getRequestData()); + return $this->success(); + } +} diff --git a/app/Http/Admin/Request/Permission/DepartmentRequest.php b/app/Http/Admin/Request/Permission/DepartmentRequest.php new file mode 100644 index 000000000..e50b983ca --- /dev/null +++ b/app/Http/Admin/Request/Permission/DepartmentRequest.php @@ -0,0 +1,64 @@ + 'required|string|max:60', + 'parent_id' => 'sometimes|integer', + ]; + if ($this->isCreate()) { + $rules['name'] = 'required|string|max:60|unique:department,name'; + } + if ($this->isUpdate()) { + $rules['name'] = 'required|string|max:60|unique:department,name,' . $this->route('id'); + } + $rules['positions'] = 'sometimes|array'; + $rules['positions.*.id'] = 'sometimes|integer'; + $rules['department_users'] = 'sometimes|array'; + $rules['department_users.*.id'] = 'sometimes|integer'; + $rules['leader'] = 'sometimes|array'; + $rules['leader.*.id'] = 'sometimes|integer'; + return $rules; + } + + public function attributes(): array + { + return [ + 'name' => '部门名称', + 'parent_id' => '上级部门', + ]; + } +} diff --git a/app/Repository/Permission/DepartmentRepository.php b/app/Repository/Permission/DepartmentRepository.php new file mode 100644 index 000000000..ee4ddb875 --- /dev/null +++ b/app/Repository/Permission/DepartmentRepository.php @@ -0,0 +1,52 @@ + + */ +final class DepartmentRepository extends IRepository +{ + public function __construct( + protected readonly Department $model + ) {} + + public function handleSearch(Builder $query, array $params): Builder + { + return $query + ->when(isset($params['name']), static function (Builder $query) use ($params) { + $query->where('name', 'like', '%' . $params['name'] . '%'); + }) + ->when(isset($params['parent_id']), static function (Builder $query) use ($params) { + $query->where('parent_id', $params['parent_id']); + }) + ->when(isset($params['created_at']), static function (Builder $query) use ($params) { + $query->whereBetween('created_at', $params['created_at']); + }) + ->when(isset($params['updated_at']), static function (Builder $query) use ($params) { + $query->whereBetween('updated_at', $params['updated_at']); + }) + ->when(isset($params['level']), static function (Builder $query) use ($params) { + if ($params['level'] === 1) { + $query->where('parent_id', 0); + } + + // todo 指定层级查询 + }) + ->with(['positions', 'department_users:id,nickname,username,avatar', 'leader:id,nickname,username,avatar']); + } +} diff --git a/app/Schema/DepartmentSchema.php b/app/Schema/DepartmentSchema.php new file mode 100644 index 000000000..d8dffd557 --- /dev/null +++ b/app/Schema/DepartmentSchema.php @@ -0,0 +1,59 @@ + + */ +class DepartmentService extends IService +{ + public function __construct( + protected readonly DepartmentRepository $repository + ) {} +} diff --git a/databases/migrations/2025_02_24_195620_create_department_tables.php b/databases/migrations/2025_02_24_195620_create_department_tables.php index 236c9346c..1ea76d03b 100644 --- a/databases/migrations/2025_02_24_195620_create_department_tables.php +++ b/databases/migrations/2025_02_24_195620_create_department_tables.php @@ -1,5 +1,6 @@ comment('部门表'); $table->bigIncrements('id'); @@ -59,6 +66,48 @@ public function up(): void $table->datetimes(); $table->softDeletes(); }); + $parent = Menu::where('name','permission')->firstOrFail(); + $now = Menu::create([ + 'name' => 'permission:department', + 'path' => '/permission/departments', + 'parent_id' => $parent->id, + 'meta' => [ + 'title' => '部门管理', + 'icon' => 'ri:git-repository-private-line', + 'type' => 'M', + 'hidden' => 0, + 'componentPath' => 'modules/', + 'componentSuffix' => '.vue', + 'breadcrumbEnable' => 1, + 'copyright' => 1, + 'cache' => 1, + 'affix' => 0, + ] + ]); + $children = [ + 'permission:department:index' => '部门列表', + 'permission:department:save' => '部门新增', + 'permission:department:update' => '部门编辑', + 'permission:department:delete' => '部门删除', + ]; + foreach ($children as $child => $title) { + Menu::create([ + 'name' => $child, + 'path' => '/permission/departments', + 'meta' => [ + 'title' => $title, + 'icon' => 'ri:git-repository-private-line', + 'type' => 'M', + 'hidden' => 1, + 'componentPath' => 'modules/', + 'componentSuffix' => '.vue', + 'breadcrumbEnable' => 1, + 'cache' => 1, + 'affix' => 0, + ], + 'parent_id' => $now->id + ]); + } } /** @@ -72,6 +121,5 @@ public function down(): void Schema::dropIfExists('user_position'); Schema::dropIfExists('dept_leader'); Schema::dropIfExists('data_permission_policy'); - Schema::dropIfExists('data_permission_custom_func'); } }; From 7372b18b5e0302377f415a209788dc4bd28765b1 Mon Sep 17 00:00:00 2001 From: "X.Mo" Date: Mon, 10 Mar 2025 10:40:29 +0800 Subject: [PATCH 09/91] =?UTF-8?q?fix:(data=20seeder)=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E5=A1=AB=E5=85=85=E9=83=A8=E9=97=A8=E8=8F=9C=E5=8D=95=E6=95=B0?= =?UTF-8?q?=E6=8D=AEbug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ..._02_24_195620_create_department_tables.php | 43 ------------ databases/seeders/user_dept_20250310.php | 66 +++++++++++++++++++ 2 files changed, 66 insertions(+), 43 deletions(-) create mode 100644 databases/seeders/user_dept_20250310.php diff --git a/databases/migrations/2025_02_24_195620_create_department_tables.php b/databases/migrations/2025_02_24_195620_create_department_tables.php index 1ea76d03b..2f9477ddb 100644 --- a/databases/migrations/2025_02_24_195620_create_department_tables.php +++ b/databases/migrations/2025_02_24_195620_create_department_tables.php @@ -1,6 +1,5 @@ datetimes(); $table->softDeletes(); }); - $parent = Menu::where('name','permission')->firstOrFail(); - $now = Menu::create([ - 'name' => 'permission:department', - 'path' => '/permission/departments', - 'parent_id' => $parent->id, - 'meta' => [ - 'title' => '部门管理', - 'icon' => 'ri:git-repository-private-line', - 'type' => 'M', - 'hidden' => 0, - 'componentPath' => 'modules/', - 'componentSuffix' => '.vue', - 'breadcrumbEnable' => 1, - 'copyright' => 1, - 'cache' => 1, - 'affix' => 0, - ] - ]); - $children = [ - 'permission:department:index' => '部门列表', - 'permission:department:save' => '部门新增', - 'permission:department:update' => '部门编辑', - 'permission:department:delete' => '部门删除', - ]; - foreach ($children as $child => $title) { - Menu::create([ - 'name' => $child, - 'path' => '/permission/departments', - 'meta' => [ - 'title' => $title, - 'icon' => 'ri:git-repository-private-line', - 'type' => 'M', - 'hidden' => 1, - 'componentPath' => 'modules/', - 'componentSuffix' => '.vue', - 'breadcrumbEnable' => 1, - 'cache' => 1, - 'affix' => 0, - ], - 'parent_id' => $now->id - ]); - } } /** diff --git a/databases/seeders/user_dept_20250310.php b/databases/seeders/user_dept_20250310.php new file mode 100644 index 000000000..f5d475e23 --- /dev/null +++ b/databases/seeders/user_dept_20250310.php @@ -0,0 +1,66 @@ +firstOrFail(); + $now = Menu::create([ + 'name' => 'permission:department', + 'path' => '/permission/departments', + 'parent_id' => $parent->id, + 'meta' => [ + 'title' => '部门管理', + 'icon' => 'ri:git-repository-private-line', + 'type' => 'M', + 'hidden' => 0, + 'componentPath' => 'modules/', + 'componentSuffix' => '.vue', + 'breadcrumbEnable' => 1, + 'copyright' => 1, + 'cache' => 1, + 'affix' => 0, + ] + ]); + $children = [ + 'permission:department:index' => '部门列表', + 'permission:department:save' => '部门新增', + 'permission:department:update' => '部门编辑', + 'permission:department:delete' => '部门删除', + ]; + foreach ($children as $child => $title) { + Menu::create([ + 'name' => $child, + 'path' => '/permission/departments', + 'meta' => [ + 'title' => $title, + 'icon' => 'ri:git-repository-private-line', + 'type' => 'M', + 'hidden' => 1, + 'componentPath' => 'modules/', + 'componentSuffix' => '.vue', + 'breadcrumbEnable' => 1, + 'cache' => 1, + 'affix' => 0, + ], + 'parent_id' => $now->id + ]); + } + } +} From d895cc55414947db6509845e22632cd9e96531de Mon Sep 17 00:00:00 2001 From: "X.Mo" Date: Mon, 10 Mar 2025 15:10:51 +0800 Subject: [PATCH 10/91] =?UTF-8?q?feat:=20=E9=83=A8=E9=97=A8=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E5=89=8D=E7=AB=AF=E9=A1=B5=E9=9D=A2.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Model/Permission/Department.php | 4 +- databases/seeders/user_dept_20250310.php | 27 ++- web/src/modules/base/api/department.ts | 36 ++++ ...344\275\223\344\270\255\346\226\207].yaml" | 17 ++ .../department/data/getFormItems.tsx | 46 ++++ .../department/data/getSearchItems.tsx | 21 ++ .../department/data/getTableColumns.tsx | 87 ++++++++ .../base/views/permission/department/form.vue | 76 +++++++ .../views/permission/department/index.vue | 197 ++++++++++++++++++ .../views/permission/department/setLeader.vue | 111 ++++++++++ .../base/views/permission/menu/index.vue | 3 +- web/types/components.d.ts | 3 + 12 files changed, 615 insertions(+), 13 deletions(-) create mode 100644 web/src/modules/base/api/department.ts create mode 100644 web/src/modules/base/views/permission/department/data/getFormItems.tsx create mode 100644 web/src/modules/base/views/permission/department/data/getSearchItems.tsx create mode 100644 web/src/modules/base/views/permission/department/data/getTableColumns.tsx create mode 100644 web/src/modules/base/views/permission/department/form.vue create mode 100644 web/src/modules/base/views/permission/department/index.vue create mode 100644 web/src/modules/base/views/permission/department/setLeader.vue diff --git a/app/Model/Permission/Department.php b/app/Model/Permission/Department.php index e4ae3d4d3..4bbc3bb3f 100644 --- a/app/Model/Permission/Department.php +++ b/app/Model/Permission/Department.php @@ -59,8 +59,8 @@ public function department_users(): BelongsToMany return $this->belongsToMany(User::class, 'user_dept', 'dept_id', 'user_id'); } - public function leaders(): BelongsToMany + public function leader(): BelongsToMany { - return $this->belongsToMany(User::class, 'user_leader', 'dept_id', 'user_id'); + return $this->belongsToMany(User::class, 'dept_leader', 'dept_id', 'user_id'); } } diff --git a/databases/seeders/user_dept_20250310.php b/databases/seeders/user_dept_20250310.php index f5d475e23..d233e8c94 100644 --- a/databases/seeders/user_dept_20250310.php +++ b/databases/seeders/user_dept_20250310.php @@ -25,9 +25,11 @@ public function run() 'name' => 'permission:department', 'path' => '/permission/departments', 'parent_id' => $parent->id, + 'component' => 'base/views/permission/department/index', 'meta' => [ 'title' => '部门管理', - 'icon' => 'ri:git-repository-private-line', + 'icon' => 'mingcute:department-line', + 'i18n' => 'baseMenu.permission.department', 'type' => 'M', 'hidden' => 0, 'componentPath' => 'modules/', @@ -39,28 +41,33 @@ public function run() ] ]); $children = [ - 'permission:department:index' => '部门列表', - 'permission:department:save' => '部门新增', - 'permission:department:update' => '部门编辑', - 'permission:department:delete' => '部门删除', + 'permission:department:index' => '部门列表', + 'permission:department:save' => '部门新增', + 'permission:department:update' => '部门编辑', + 'permission:department:delete' => '部门删除', ]; + $i18n = [ + 'baseMenu.permission.departmentList', + 'baseMenu.permission.departmentCreate', + 'baseMenu.permission.departmentSave', + 'baseMenu.permission.departmentDelete', + ]; + $i = 0; foreach ($children as $child => $title) { Menu::create([ 'name' => $child, 'path' => '/permission/departments', 'meta' => [ 'title' => $title, - 'icon' => 'ri:git-repository-private-line', - 'type' => 'M', + 'type' => 'B', + 'i18n' => $i18n[$i], 'hidden' => 1, - 'componentPath' => 'modules/', - 'componentSuffix' => '.vue', - 'breadcrumbEnable' => 1, 'cache' => 1, 'affix' => 0, ], 'parent_id' => $now->id ]); + $i++; } } } diff --git a/web/src/modules/base/api/department.ts b/web/src/modules/base/api/department.ts new file mode 100644 index 000000000..b16af828f --- /dev/null +++ b/web/src/modules/base/api/department.ts @@ -0,0 +1,36 @@ +/** + * MineAdmin is committed to providing solutions for quickly building web applications + * Please view the LICENSE file that was distributed with this source code, + * For the full copyright and license information. + * Thank you very much for using MineAdmin. + * + * @Author X.Mo + * @Link https://github.com/mineadmin + */ +import type { PageList, ResponseStruct } from '#/global' + +export interface DepartmentVo { + id?: number + name?: string +} + +export interface DepartmentSearchVo { + name?: string + [key: string]: any +} + +export function page(data: DepartmentSearchVo): Promise>> { + return useHttp().get('/admin/department/list', { params: data }) +} + +export function create(data: DepartmentVo): Promise> { + return useHttp().post('/admin/department', data) +} + +export function save(id: number, data: DepartmentVo): Promise> { + return useHttp().put(`/admin/department/${id}`, data) +} + +export function deleteByIds(ids: number[]): Promise> { + return useHttp().delete('/admin/department', { data: ids }) +} diff --git "a/web/src/modules/base/locales/zh_CN[\347\256\200\344\275\223\344\270\255\346\226\207].yaml" "b/web/src/modules/base/locales/zh_CN[\347\256\200\344\275\223\344\270\255\346\226\207].yaml" index b5698cf03..156329d82 100644 --- "a/web/src/modules/base/locales/zh_CN[\347\256\200\344\275\223\344\270\255\346\226\207].yaml" +++ "b/web/src/modules/base/locales/zh_CN[\347\256\200\344\275\223\344\270\255\346\226\207].yaml" @@ -124,6 +124,18 @@ baseOperationLog: ip: 请求IP created_at: 创建时间 updated_at: 更新时间 +baseDepartment: + name: 部门名称 + created_at: 创建时间 + updated_at: 更新时间 + parentDepartment: 上级部门 + page: + mainTitle: 部门管理 + subTitle: 提供公司、机构的人员部门管理、以及部门负责人。 + setLeader: 设置负责人 + placeholder: + name: 请输入部门名称 + parentDepartment: 请选择上级部门 baseMenu: permission: index: 权限管理 @@ -147,6 +159,11 @@ baseMenu: menuSave: 菜单保存 menuUpdate: 菜单更新 menuDelete: 菜单删除 + department: 部门管理 + departmentList: 部门列表 + departmentCreate: 新增部门 + departmentSave: 编辑部门 + departmentDelete: 删除部门 log: index: 日志管理 userLoginLog: 登录日志 diff --git a/web/src/modules/base/views/permission/department/data/getFormItems.tsx b/web/src/modules/base/views/permission/department/data/getFormItems.tsx new file mode 100644 index 000000000..aa1659b8d --- /dev/null +++ b/web/src/modules/base/views/permission/department/data/getFormItems.tsx @@ -0,0 +1,46 @@ +/** + * MineAdmin is committed to providing solutions for quickly building web applications + * Please view the LICENSE file that was distributed with this source code, + * For the full copyright and license information. + * Thank you very much for using MineAdmin. + * + * @Author X.Mo + * @Link https://github.com/mineadmin + */ +import type { MaFormItem } from '@mineadmin/form' + +export default function getFormItems(formType: 'add' | 'edit' = 'add', t: any): MaFormItem[] { + const treeSelectRef = ref() + const deptList = ref([]) + + return [ + { + label: () => t('baseDepartment.parentDepartment'), prop: 'parent_id', render: () => ( + + + ), + renderProps: { + class: 'w-full', + placeholder: t('baseDepartment.placeholder.parentDepartment'), + }, + }, + { + label: () => t('baseDepartment.name'), + prop: 'name', + render: 'input', + renderProps: { + placeholder: t('form.pleaseInput', { msg: t('baseDepartment.name') }), + }, + itemProps: { + rules: [{ required: true, message: t('form.requiredInput', { msg: t('baseDepartment.placeholder.name') }) }], + }, + }, + ] +} diff --git a/web/src/modules/base/views/permission/department/data/getSearchItems.tsx b/web/src/modules/base/views/permission/department/data/getSearchItems.tsx new file mode 100644 index 000000000..2e5151200 --- /dev/null +++ b/web/src/modules/base/views/permission/department/data/getSearchItems.tsx @@ -0,0 +1,21 @@ +/** + * MineAdmin is committed to providing solutions for quickly building web applications + * Please view the LICENSE file that was distributed with this source code, + * For the full copyright and license information. + * Thank you very much for using MineAdmin. + * + * @Author X.Mo + * @Link https://github.com/mineadmin + */ + +import type { MaSearchItem } from '@mineadmin/search' + +export default function getSearchItems(t: any): MaSearchItem[] { + return [ + { + label: () => t('baseDepartment.name'), + prop: 'name', + render: 'input', + }, + ] +} diff --git a/web/src/modules/base/views/permission/department/data/getTableColumns.tsx b/web/src/modules/base/views/permission/department/data/getTableColumns.tsx new file mode 100644 index 000000000..a3a9950c0 --- /dev/null +++ b/web/src/modules/base/views/permission/department/data/getTableColumns.tsx @@ -0,0 +1,87 @@ +/** + * MineAdmin is committed to providing solutions for quickly building web applications + * Please view the LICENSE file that was distributed with this source code, + * For the full copyright and license information. + * Thank you very much for using MineAdmin. + * + * @Author X.Mo + * @Link https://github.com/mineadmin + */ +import type { MaProTableColumns, MaProTableExpose } from '@mineadmin/pro-table' +import type { RoleVo } from '~/base/api/role.ts' +import type { UseDialogExpose } from '@/hooks/useDialog.ts' + +import { useMessage } from '@/hooks/useMessage.ts' +import { deleteByIds } from '~/base/api/role.ts' +import { ResultCode } from '@/utils/ResultCode.ts' +import hasAuth from '@/utils/permission/hasAuth.ts' + +export default function getTableColumns(dialog: UseDialogExpose, formRef: any, t: any): MaProTableColumns[] { + const dictStore = useDictStore() + const msg = useMessage() + + const showBtn = (auth: string | string[], row: RoleVo) => { + return hasAuth(auth) && row.id !== 1 + } + + return [ + // 多选列 + { type: 'selection', showOverflowTooltip: false, label: () => t('crud.selection'), + cellRender: ({ row }): any => row.id === 1 ? '-' : undefined, + selectable: (row: RoleVo) => ![1].includes(row.id as number), + }, + // 索引序号列 + { type: 'index' }, + // 普通列 + { label: () => t('baseDepartment.name'), prop: 'name' }, + { label: () => t('baseDepartment.created_at'), prop: 'created_at' }, + { label: () => t('baseDepartment.updated_at'), prop: 'updated_at' }, + + // 操作列 + { + type: 'operation', + label: () => t('crud.operation'), + width: '260px', + operationConfigure: { + type: 'tile', + actions: [ + { + name: 'setLeader', + show: ({ row }) => showBtn(['permission:department:save'], row), + icon: 'material-symbols:checklist-rounded', + text: () => t('baseDepartment.page.setLeader'), + onClick: ({ row }) => { + dialog.setTitle(t('baseDepartment.page.setLeader')) + dialog.open({ formType: 'setLeader', data: row }) + }, + }, + { + name: 'edit', + icon: 'material-symbols:person-edit', + show: ({ row }) => showBtn('permission:department:save', row), + text: () => t('crud.edit'), + onClick: ({ row }) => { + dialog.setTitle(t('crud.edit')) + dialog.open({ formType: 'edit', data: row }) + }, + }, + { + name: 'del', + show: ({ row }) => showBtn('permission:department:delete', row), + icon: 'mdi:delete', + text: () => t('crud.delete'), + onClick: ({ row }, proxy: MaProTableExpose) => { + msg.delConfirm(t('crud.delDataMessage')).then(async () => { + const response = await deleteByIds([row.id]) + if (response.code === ResultCode.SUCCESS) { + msg.success(t('crud.delSuccess')) + await proxy.refresh() + } + }) + }, + }, + ], + }, + }, + ] +} diff --git a/web/src/modules/base/views/permission/department/form.vue b/web/src/modules/base/views/permission/department/form.vue new file mode 100644 index 000000000..4a6bc900c --- /dev/null +++ b/web/src/modules/base/views/permission/department/form.vue @@ -0,0 +1,76 @@ + + + + + + diff --git a/web/src/modules/base/views/permission/department/index.vue b/web/src/modules/base/views/permission/department/index.vue new file mode 100644 index 000000000..be7f2cdcf --- /dev/null +++ b/web/src/modules/base/views/permission/department/index.vue @@ -0,0 +1,197 @@ + + + + + + diff --git a/web/src/modules/base/views/permission/department/setLeader.vue b/web/src/modules/base/views/permission/department/setLeader.vue new file mode 100644 index 000000000..cae37eb79 --- /dev/null +++ b/web/src/modules/base/views/permission/department/setLeader.vue @@ -0,0 +1,111 @@ + + + + + + + diff --git a/web/src/modules/base/views/permission/menu/index.vue b/web/src/modules/base/views/permission/menu/index.vue index 2a8da12c6..4733b35e8 100644 --- a/web/src/modules/base/views/permission/menu/index.vue +++ b/web/src/modules/base/views/permission/menu/index.vue @@ -11,7 +11,8 @@ import type { ElForm } from 'element-plus' import { useMessage } from '@/hooks/useMessage.ts' import getOnlyWorkAreaHeight from '@/utils/getOnlyWorkAreaHeight.ts' -import { create, type MenuVo, page, save } from '~/base/api/menu.ts' +import { create, page, save } from '~/base/api/menu.ts' +import type { MenuVo } from '~/base/api/menu.ts' import MenuTree from './menu-tree.vue' import MenuForm from './menu-form.vue' diff --git a/web/types/components.d.ts b/web/types/components.d.ts index c275c2151..e20d9e3f2 100644 --- a/web/types/components.d.ts +++ b/web/types/components.d.ts @@ -2,6 +2,7 @@ // @ts-nocheck // Generated by unplugin-vue-components // Read more: https://github.com/vuejs/core/pull/3399 +// biome-ignore lint: disable export {} /* prettier-ignore */ @@ -10,6 +11,8 @@ declare module 'vue' { Form: typeof import('./../src/components/ma-key-value/components/form.vue')['default'] MaAuth: typeof import('./../src/components/ma-auth/index.vue')['default'] MaCitySelect: typeof import('./../src/components/ma-city-select/index.vue')['default'] + MaColCard: typeof import('./../src/components/ma-col-card/index.vue')['default'] + MaColsCard: typeof import('./../src/components/ma-cols-card/index.vue')['default'] MaDialog: typeof import('./../src/components/ma-dialog/index.vue')['default'] MaDictCheckbox: typeof import('./../src/components/ma-dict-picker/ma-dict-checkbox.vue')['default'] MaDictRadio: typeof import('./../src/components/ma-dict-picker/ma-dict-radio.vue')['default'] From 55a9a07405834eadaed57316ba680fe7f069b597 Mon Sep 17 00:00:00 2001 From: zds <49744633+zds-s@users.noreply.github.com> Date: Mon, 10 Mar 2025 15:11:19 +0800 Subject: [PATCH 11/91] fix --- app/Model/Permission/Department.php | 5 +++++ app/Repository/Permission/DepartmentRepository.php | 1 + 2 files changed, 6 insertions(+) diff --git a/app/Model/Permission/Department.php b/app/Model/Permission/Department.php index 4bbc3bb3f..8bb57ea69 100644 --- a/app/Model/Permission/Department.php +++ b/app/Model/Permission/Department.php @@ -63,4 +63,9 @@ public function leader(): BelongsToMany { return $this->belongsToMany(User::class, 'dept_leader', 'dept_id', 'user_id'); } + + public function children(): HasMany + { + return $this->hasMany(Department::class, 'parent_id', 'id'); + } } diff --git a/app/Repository/Permission/DepartmentRepository.php b/app/Repository/Permission/DepartmentRepository.php index ee4ddb875..bdf303027 100644 --- a/app/Repository/Permission/DepartmentRepository.php +++ b/app/Repository/Permission/DepartmentRepository.php @@ -43,6 +43,7 @@ public function handleSearch(Builder $query, array $params): Builder ->when(isset($params['level']), static function (Builder $query) use ($params) { if ($params['level'] === 1) { $query->where('parent_id', 0); + $query->with('children'); } // todo 指定层级查询 From 1ab2925245975f2711815d678158cb1c43960d73 Mon Sep 17 00:00:00 2001 From: zds <49744633+zds-s@users.noreply.github.com> Date: Mon, 10 Mar 2025 15:17:07 +0800 Subject: [PATCH 12/91] feat: enhance Department management with transaction handling and validation improvements --- .../Request/Permission/DepartmentRequest.php | 6 ++-- app/Service/Permission/DepartmentService.php | 33 +++++++++++++++++++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/app/Http/Admin/Request/Permission/DepartmentRequest.php b/app/Http/Admin/Request/Permission/DepartmentRequest.php index e50b983ca..715e2e57a 100644 --- a/app/Http/Admin/Request/Permission/DepartmentRequest.php +++ b/app/Http/Admin/Request/Permission/DepartmentRequest.php @@ -45,12 +45,10 @@ public function rules(): array if ($this->isUpdate()) { $rules['name'] = 'required|string|max:60|unique:department,name,' . $this->route('id'); } - $rules['positions'] = 'sometimes|array'; - $rules['positions.*.id'] = 'sometimes|integer'; $rules['department_users'] = 'sometimes|array'; - $rules['department_users.*.id'] = 'sometimes|integer'; + $rules['department_users.*'] = 'sometimes|integer'; $rules['leader'] = 'sometimes|array'; - $rules['leader.*.id'] = 'sometimes|integer'; + $rules['leader.*'] = 'sometimes|integer'; return $rules; } diff --git a/app/Service/Permission/DepartmentService.php b/app/Service/Permission/DepartmentService.php index 62f8ce358..402f2e10e 100644 --- a/app/Service/Permission/DepartmentService.php +++ b/app/Service/Permission/DepartmentService.php @@ -12,9 +12,12 @@ namespace App\Service\Permission; +use App\Exception\BusinessException; +use App\Http\Common\ResultCode; use App\Model\Permission\Department; use App\Repository\Permission\DepartmentRepository; use App\Service\IService; +use Hyperf\DbConnection\Db; /** * @extends IService @@ -24,4 +27,34 @@ class DepartmentService extends IService public function __construct( protected readonly DepartmentRepository $repository ) {} + + public function create(array $data): mixed + { + return Db::transaction(function () use ($data) { + $entity = $this->repository->create($data); + $this->handleEntity($entity,$data); + return $entity; + }); + } + + public function updateById(mixed $id, array $data): mixed + { + return Db::transaction(function () use ($id, $data) { + $entity = $this->repository->findById($id); + if (empty($entity)){ + throw new BusinessException(ResultCode::NOT_FOUND); + } + $this->handleEntity($entity,$data); + }); + } + + protected function handleEntity(Department $entity,array $data): void + { + if (!empty($data['department_users'])){ + $entity->department_users()->sync($data['department_users']); + } + if (!empty($data['leader'])){ + $entity->leader()->sync($data['leader']); + } + } } From e49cfd5d318f6b6d8b49f32c868dda4d7b995b2f Mon Sep 17 00:00:00 2001 From: zds <49744633+zds-s@users.noreply.github.com> Date: Mon, 10 Mar 2025 15:17:44 +0800 Subject: [PATCH 13/91] feat: update operation IDs in DepartmentController for clarity and consistency --- .../Admin/Controller/Permission/DepartmentController.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/Http/Admin/Controller/Permission/DepartmentController.php b/app/Http/Admin/Controller/Permission/DepartmentController.php index b4eb40480..73722f4a8 100644 --- a/app/Http/Admin/Controller/Permission/DepartmentController.php +++ b/app/Http/Admin/Controller/Permission/DepartmentController.php @@ -46,7 +46,7 @@ public function __construct( #[Get( path: '/admin/department/list', - operationId: 'roleList', + operationId: 'departmentList', summary: '岗位列表', security: [['Bearer' => [], 'ApiKey' => []]], tags: ['岗位管理'], @@ -66,7 +66,7 @@ public function pageList(): Result #[Post( path: '/admin/department', - operationId: 'roleCreate', + operationId: 'departmentCreate', summary: '创建岗位', security: [['Bearer' => [], 'ApiKey' => []]], tags: ['岗位管理'], @@ -86,7 +86,7 @@ public function create(DepartmentRequest $request): Result #[Put( path: '/admin/department/{id}', - operationId: 'roleSave', + operationId: 'departmentSave', summary: '保存岗位', security: [['Bearer' => [], 'ApiKey' => []]], tags: ['岗位管理'], @@ -106,7 +106,7 @@ public function save(int $id, DepartmentRequest $request): Result #[Delete( path: '/admin/department', - operationId: 'roleDelete', + operationId: 'departmentDelete', summary: '删除岗位', security: [['Bearer' => [], 'ApiKey' => []]], tags: ['岗位管理'], From b6ed70fa54e6ed4f7cf2f3677215793156b323b0 Mon Sep 17 00:00:00 2001 From: "X.Mo" Date: Mon, 10 Mar 2025 15:18:18 +0800 Subject: [PATCH 14/91] =?UTF-8?q?feat:=20=E9=83=A8=E9=97=A8=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E5=89=8D=E7=AB=AF=E9=A1=B5=E9=9D=A2.=20-=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Permission/DepartmentController.php | 16 +++++++------- .../department/data/getTableColumns.tsx | 21 +++++++------------ .../views/permission/department/index.vue | 4 ++-- 3 files changed, 17 insertions(+), 24 deletions(-) diff --git a/app/Http/Admin/Controller/Permission/DepartmentController.php b/app/Http/Admin/Controller/Permission/DepartmentController.php index b4eb40480..c12e22510 100644 --- a/app/Http/Admin/Controller/Permission/DepartmentController.php +++ b/app/Http/Admin/Controller/Permission/DepartmentController.php @@ -47,9 +47,9 @@ public function __construct( #[Get( path: '/admin/department/list', operationId: 'roleList', - summary: '岗位列表', + summary: '部门列表', security: [['Bearer' => [], 'ApiKey' => []]], - tags: ['岗位管理'], + tags: ['部门管理'], )] #[PageResponse(instance: DepartmentSchema::class)] #[Permission(code: 'permission:department:index')] @@ -67,9 +67,9 @@ public function pageList(): Result #[Post( path: '/admin/department', operationId: 'roleCreate', - summary: '创建岗位', + summary: '创建部门', security: [['Bearer' => [], 'ApiKey' => []]], - tags: ['岗位管理'], + tags: ['部门管理'], )] #[RequestBody( content: new JsonContent(ref: DepartmentRequest::class) @@ -87,9 +87,9 @@ public function create(DepartmentRequest $request): Result #[Put( path: '/admin/department/{id}', operationId: 'roleSave', - summary: '保存岗位', + summary: '保存部门', security: [['Bearer' => [], 'ApiKey' => []]], - tags: ['岗位管理'], + tags: ['部门管理'], )] #[RequestBody( content: new JsonContent(ref: DepartmentRequest::class) @@ -107,9 +107,9 @@ public function save(int $id, DepartmentRequest $request): Result #[Delete( path: '/admin/department', operationId: 'roleDelete', - summary: '删除岗位', + summary: '删除部门', security: [['Bearer' => [], 'ApiKey' => []]], - tags: ['岗位管理'], + tags: ['部门管理'], )] #[ResultResponse(instance: new Result())] #[Permission(code: 'permission:department:delete')] diff --git a/web/src/modules/base/views/permission/department/data/getTableColumns.tsx b/web/src/modules/base/views/permission/department/data/getTableColumns.tsx index a3a9950c0..65e02732e 100644 --- a/web/src/modules/base/views/permission/department/data/getTableColumns.tsx +++ b/web/src/modules/base/views/permission/department/data/getTableColumns.tsx @@ -8,30 +8,23 @@ * @Link https://github.com/mineadmin */ import type { MaProTableColumns, MaProTableExpose } from '@mineadmin/pro-table' -import type { RoleVo } from '~/base/api/role.ts' import type { UseDialogExpose } from '@/hooks/useDialog.ts' import { useMessage } from '@/hooks/useMessage.ts' -import { deleteByIds } from '~/base/api/role.ts' +import { deleteByIds } from '~/base/api/department.ts' import { ResultCode } from '@/utils/ResultCode.ts' import hasAuth from '@/utils/permission/hasAuth.ts' export default function getTableColumns(dialog: UseDialogExpose, formRef: any, t: any): MaProTableColumns[] { - const dictStore = useDictStore() const msg = useMessage() - const showBtn = (auth: string | string[], row: RoleVo) => { - return hasAuth(auth) && row.id !== 1 + const showBtn = (auth: string | string[]) => { + return hasAuth(auth) } return [ // 多选列 - { type: 'selection', showOverflowTooltip: false, label: () => t('crud.selection'), - cellRender: ({ row }): any => row.id === 1 ? '-' : undefined, - selectable: (row: RoleVo) => ![1].includes(row.id as number), - }, - // 索引序号列 - { type: 'index' }, + { type: 'selection', showOverflowTooltip: false, label: () => t('crud.selection') }, // 普通列 { label: () => t('baseDepartment.name'), prop: 'name' }, { label: () => t('baseDepartment.created_at'), prop: 'created_at' }, @@ -47,7 +40,7 @@ export default function getTableColumns(dialog: UseDialogExpose, formRef: any, t actions: [ { name: 'setLeader', - show: ({ row }) => showBtn(['permission:department:save'], row), + show: () => showBtn('permission:department:update'), icon: 'material-symbols:checklist-rounded', text: () => t('baseDepartment.page.setLeader'), onClick: ({ row }) => { @@ -58,7 +51,7 @@ export default function getTableColumns(dialog: UseDialogExpose, formRef: any, t { name: 'edit', icon: 'material-symbols:person-edit', - show: ({ row }) => showBtn('permission:department:save', row), + show: () => showBtn('permission:department:update'), text: () => t('crud.edit'), onClick: ({ row }) => { dialog.setTitle(t('crud.edit')) @@ -67,7 +60,7 @@ export default function getTableColumns(dialog: UseDialogExpose, formRef: any, t }, { name: 'del', - show: ({ row }) => showBtn('permission:department:delete', row), + show: () => showBtn('permission:department:delete'), icon: 'mdi:delete', text: () => t('crud.delete'), onClick: ({ row }, proxy: MaProTableExpose) => { diff --git a/web/src/modules/base/views/permission/department/index.vue b/web/src/modules/base/views/permission/department/index.vue index be7f2cdcf..4dc559359 100644 --- a/web/src/modules/base/views/permission/department/index.vue +++ b/web/src/modules/base/views/permission/department/index.vue @@ -142,7 +142,7 @@ function handleDelete() {