diff --git a/README.md b/README.md index 9e50b31..1d56f95 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ 监听sql执行, 打印日志 - `app/Providers/QueryLogServiceProvider.php` +- `bootstrap\providers.php` ### 无限级分类 diff --git a/app/Admin/Controllers/KeywordController.php b/app/Admin/Controllers/KeywordController.php index f3faa96..59e662d 100644 --- a/app/Admin/Controllers/KeywordController.php +++ b/app/Admin/Controllers/KeywordController.php @@ -27,9 +27,12 @@ class KeywordController extends AdminController ->loadDataOnce(true) ->footerToolbar([]) ->headerToolbar([ - $this->createButton()->visible($user->can('keywords.create')), - $this->exportAction()->visible($user->can('keywords.export')), + $this->createButton()->permission('admin.keywords.create'), + $this->exportAction()->permission('admin.keywords.export'), ...$this->baseHeaderToolBar(), + ]) + ->bulkActions([ + $this->bulkDeleteButton()->permission('admin.keywords.delete') ]) ->filter($this->baseFilter()->body([ amis()->GroupControl()->mode('horizontal')->body([ @@ -44,9 +47,9 @@ class KeywordController extends AdminController 'saveImmediately' => true, ]), $this->rowActions([ - $this->rowShowButton()->visible($user->can('keywords.show')), - $this->rowEditButton()->visible($user->can('keywords.edit')), - $this->rowDeleteButton()->visible($user->can('keywords.delete')), + $this->rowShowButton()->permission('admin.keywords.show'), + $this->rowEditButton()->permission('admin.keywords.edit'), + $this->rowDeleteButton()->permission('admin.keywords.delete'), ]), ]); diff --git a/app/Admin/Controllers/UserController.php b/app/Admin/Controllers/UserController.php new file mode 100644 index 0000000..383f8c4 --- /dev/null +++ b/app/Admin/Controllers/UserController.php @@ -0,0 +1,67 @@ +baseCRUD() + ->filterTogglable(false) + ->columnsTogglable(false) + ->headerToolbar([ + $this->createButton('drawer', 'lg')->permission('admin.users.create'), + ...$this->baseHeaderToolBar(), + ]) + ->bulkActions([ + $this->bulkDeleteButton()->permission('admin.users.delete') + ]) + ->filter($this->baseFilter()->body([ + amis()->GroupControl()->mode('horizontal')->body([ + amis()->TextControl()->name('search')->label(__('admin.search'))->columnRatio(3)->clearable(), + ]) + ])) + ->columns([ + amis()->TableColumn()->name('id')->label(__('admin.id')), + amis()->TableColumn()->name('avatar')->label(__('users.avatar'))->type('avatar')->src('${avatar}'), + amis()->TableColumn()->name('phone')->label(__('users.phone')), + amis()->TableColumn()->name('name')->label(__('users.name')), + amis()->TableColumn()->name('created_at')->label(__('users.created_at')), + $this->rowActions([ + $this->rowShowButton('drawer', 'lg')->permission('admin.users.show'), + $this->rowEditButton('drawer', 'lg')->permission('admin.users.edit'), + $this->rowDeleteButton()->permission('admin.users.delete'), + ]), + ]); + + return $this->baseList($crud); + } + + public function form() + { + return $this->baseForm()->mode('horizontal')->body([ + amis()->ImageControl()->name('avatar')->label(__('users.avatar')), + amis()->TextControl()->name('phone')->label(__('users.phone'))->required(), + amis()->TextControl()->name('name')->label(__('users.name')), + ]); + } + + public function detail() + { + return $this->baseDetail()->body(amis()->Property()->items([ + ['label' => __('users.avatar'), 'content' => amis()->Avatar()->src('${avatar}')], + ['label' => __('users.phone'), 'content' => '${phone}'], + ['label' => __('users.name'), 'content' => '${name}'], + ])); + } +} \ No newline at end of file diff --git a/app/Admin/routes.php b/app/Admin/routes.php index b48b8ca..3bf8849 100644 --- a/app/Admin/routes.php +++ b/app/Admin/routes.php @@ -2,6 +2,7 @@ use App\Admin\Controllers\HomeController; use App\Admin\Controllers\KeywordController; +use App\Admin\Controllers\UserController; use Illuminate\Routing\Router; use Illuminate\Support\Facades\Route; @@ -25,5 +26,6 @@ Route::group([ $router->any('upload_image', [HomeController::class, 'uploadImage']); $router->any('upload_file', [HomeController::class, 'uploadFile']); + $router->resource('users', UserController::class); $router->resource('system/keywords', KeywordController::class); }); diff --git a/app/ModelFilters/UserFilter.php b/app/ModelFilters/UserFilter.php new file mode 100644 index 0000000..ee89630 --- /dev/null +++ b/app/ModelFilters/UserFilter.php @@ -0,0 +1,22 @@ + [input_key1, input_key2]]. + * + * @var array + */ + public $relations = []; + + public function search($key) + { + $str = '%'.$key.'%'; + return $this->where(fn($q) => $q->where('phone', 'like', $str)->orWhere('name', 'like', $str)); + } +} diff --git a/app/Models/User.php b/app/Models/User.php index def621f..4f3d8aa 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -6,42 +6,19 @@ namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; +use EloquentFilter\Filterable; +use Slowlyo\OwlAdmin\Traits\DatetimeFormatterTrait; +/** + * 用户 + */ class User extends Authenticatable { - use HasFactory, Notifiable; + use HasFactory, Filterable, DatetimeFormatterTrait; - /** - * The attributes that are mass assignable. - * - * @var array - */ - protected $fillable = [ - 'name', - 'email', - 'password', - ]; + protected $fillable = ['phone', 'name', 'avatar']; - /** - * The attributes that should be hidden for serialization. - * - * @var array - */ - protected $hidden = [ - 'password', - 'remember_token', - ]; - - /** - * Get the attributes that should be cast. - * - * @return array - */ - protected function casts(): array - { - return [ - 'email_verified_at' => 'datetime', - 'password' => 'hashed', - ]; - } + // protected $casts = [ + // 'created_at' => 'datetime:Y-m-d H:i:s', + // ]; } diff --git a/app/Services/UserService.php b/app/Services/UserService.php new file mode 100644 index 0000000..95a6bcc --- /dev/null +++ b/app/Services/UserService.php @@ -0,0 +1,35 @@ +orderByDesc('id'); + } + + public function searchable($query) + { + $query->filter(request()->all()); + } + + public function deleted($ids) + { + $ids = explode(',', $ids); + + $this->query()->where(function ($q) use ($ids) { + foreach ($ids as $id) { + $q->orWhere('path', 'like', '%-'.$id.'-%'); + } + })->delete(); + } +} \ No newline at end of file diff --git a/config/admin.php b/config/admin.php index cbcb536..ec87617 100644 --- a/config/admin.php +++ b/config/admin.php @@ -68,10 +68,10 @@ return [ 'https' => env('ADMIN_HTTPS', false), // 是否显示 [开发者工具] - 'show_development_tools' => env('ADMIN_SHOW_DEVELOPMENT_TOOLS', true), + 'show_development_tools' => env('ADMIN_SHOW_DEVELOPMENT_TOOLS', false), // 是否显示 [权限] 功能中的自动生成按钮 - 'show_auto_generate_permission_button' => env('ADMIN_SHOW_AUTO_GENERATE_PERMISSION_BUTTON', true), + 'show_auto_generate_permission_button' => env('ADMIN_SHOW_AUTO_GENERATE_PERMISSION_BUTTON', false), // 扩展 'extension' => [ diff --git a/database/migrations/2024_07_07_063654_create_users_table.php b/database/migrations/2024_07_07_063654_create_users_table.php index b3bb22f..15d787f 100644 --- a/database/migrations/2024_07_07_063654_create_users_table.php +++ b/database/migrations/2024_07_07_063654_create_users_table.php @@ -13,6 +13,9 @@ return new class extends Migration { Schema::create('users', function (Blueprint $table) { $table->id(); + $table->string('phone')->unique(); + $table->string('name')->nullable(); + $table->string('avatar')->nullable(); $table->timestamps(); }); } diff --git a/database/migrations/2024_08_25_111812_update_admin_permissions_table.php b/database/migrations/2024_08_25_111812_update_admin_permissions_table.php new file mode 100644 index 0000000..36452e1 --- /dev/null +++ b/database/migrations/2024_08_25_111812_update_admin_permissions_table.php @@ -0,0 +1,28 @@ +dropUnique('admin_permissions_name_unique'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('admin_permissions', function (Blueprint $table) { + $table->unique('name'); + }); + } +}; diff --git a/database/seeders/AdminPermissionSeeder.php b/database/seeders/AdminPermissionSeeder.php index 7f55b7d..a3780e5 100644 --- a/database/seeders/AdminPermissionSeeder.php +++ b/database/seeders/AdminPermissionSeeder.php @@ -23,6 +23,7 @@ class AdminPermissionSeeder extends Seeder // icon: https://icones.js.org/collection/mdi $list = [ ['name' => '首页', 'icon' => 'mdi:home', 'slug' => 'dashboard', 'url' => '/dashboard', 'is_home' => 1], + ['name' => '用户管理', 'icon' => 'mdi:account', 'slug' => 'users', 'url' => '/users', 'resource' => true], ['name' => '系统管理', 'icon' => 'mdi:cog-outline', 'slug' => 'system', 'url' => '/system', 'children' => [ ['name' => '管理员', 'icon' => 'mdi:account-cog-outline', 'slug' => 'admin_users', 'url' => '/system/admin_users'], ['name' => '角色', 'icon' => 'mdi:account-box-outline', 'slug' => 'roles', 'url' => '/system/admin_roles'], @@ -72,7 +73,7 @@ class AdminPermissionSeeder extends Seeder protected function createPermission($item, $pid = 0, $menu = null) { - $slug = data_get($item, 'slug'); + $slug = 'admin.'.data_get($item, 'slug'); $url = data_get($item, 'url'); $method = data_get($item, 'method'); $permission = AdminPermission::create([ @@ -109,13 +110,15 @@ class AdminPermissionSeeder extends Seeder 'show' => '详细', 'delete' => '删除' ]; - if ($resource == true) { - return $maps; + if ($resource) { + if ($resource === true) { + return $maps; + } + if (is_array($resource)) { + return Arr::only($maps, $resource); + } + return data_get($maps, $resource); } - if (is_array($resource)) { - return Arr::only($maps, $resource); - } - - return data_get($maps, $resource); + return []; } } diff --git a/lang/zh_CN/admin.php b/lang/zh_CN/admin.php index 8a2c7c2..36bb889 100644 --- a/lang/zh_CN/admin.php +++ b/lang/zh_CN/admin.php @@ -339,4 +339,5 @@ return [ 'data_delete' => '删除数据', 'data_detail' => '获取详情', ], + 'id' => 'ID', ]; diff --git a/lang/zh_CN/users.php b/lang/zh_CN/users.php new file mode 100644 index 0000000..4567cbf --- /dev/null +++ b/lang/zh_CN/users.php @@ -0,0 +1,8 @@ + '手机号', + 'name' => '姓名', + 'avatar' => '头像', + 'created_at' => '注册时间', +];