diff --git a/README.md b/README.md index 6b31293..81b33d1 100644 --- a/README.md +++ b/README.md @@ -51,3 +51,7 @@ public function filteredResults() return \Slowlyo\OwlAdmin\Support\Cores\AdminPipeline::handle(static::class, $this->amisSchema); } ``` + +## TODO + +- 表单验证: 服务端返回 `errors` 不生效, https://aisuda.bce.baidu.com/amis/zh-CN/components/form/formitem#%E6%9C%8D%E5%8A%A1%E7%AB%AF%E6%A0%A1%E9%AA%8C \ No newline at end of file diff --git a/app/Admin/Controllers/UserController.php b/app/Admin/Controllers/UserController.php index f46426e..b83a9fc 100644 --- a/app/Admin/Controllers/UserController.php +++ b/app/Admin/Controllers/UserController.php @@ -22,13 +22,15 @@ class UserController extends AdminController ->headerToolbar([ $this->createButton('drawer', 'lg')->permission('admin.users.create'), ...$this->baseHeaderToolBar(), + $this->exportAction(), ]) ->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(), + amis()->TextControl()->name('search')->label(__('admin.search'))->placeholder(__('users.phone').'/'.__('users.name'))->columnRatio(3)->clearable(), + amis()->DateRangeControl()->name('created_range')->label(__('users.created_at'))->columnRatio(3)->clearable(), ]) ])) ->columns([ @@ -65,4 +67,15 @@ class UserController extends AdminController ['label' => __('users.created_at'), 'content' => '${created_at}'], ])); } + + protected function exportMap($row) + { + return [ + __('admin.id') => $row['id'], + __('users.avatar') => $row['avatar'], + __('users.phone') => $row['phone'], + __('users.name') => $row['name'], + __('users.created_at') => $row['created_at'], + ]; + } } \ No newline at end of file diff --git a/app/Exceptions/AdminValidationException.php b/app/Exceptions/AdminValidationException.php new file mode 100644 index 0000000..e5d8126 --- /dev/null +++ b/app/Exceptions/AdminValidationException.php @@ -0,0 +1,29 @@ +first()); + $errors = []; + foreach($error->messages() as $key => $messages) { + $errors[$key] = Arr::first($messages); + } + $this->errors = $errors; + } + + public function render() + { + return Admin::response()->additional(['errors' => $this->errors])->fail($this->getMessage()); + } + +} diff --git a/app/ModelFilters/UserFilter.php b/app/ModelFilters/UserFilter.php index ee89630..e2c0292 100644 --- a/app/ModelFilters/UserFilter.php +++ b/app/ModelFilters/UserFilter.php @@ -2,6 +2,7 @@ namespace App\ModelFilters; +use Carbon\Carbon; use EloquentFilter\ModelFilter; class UserFilter extends ModelFilter @@ -19,4 +20,16 @@ class UserFilter extends ModelFilter $str = '%'.$key.'%'; return $this->where(fn($q) => $q->where('phone', 'like', $str)->orWhere('name', 'like', $str)); } + + public function createdRange($key) + { + $keys = explode(',', $key); + $start = data_get($keys, 0); + $end = data_get($keys, 1); + if ($start && $end) { + $start = Carbon::createFromTimestamp($start); + $end = Carbon::createFromTimestamp($end); + return $this->whereBetween('created_at', [$start, $end]); + } + } } diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 452e6b6..363ea21 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -2,6 +2,7 @@ namespace App\Providers; +use Illuminate\Support\Facades\Validator; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider @@ -19,6 +20,8 @@ class AppServiceProvider extends ServiceProvider */ public function boot(): void { - // + Validator::extend('phone', function ($attribute, $value, $parameters, $validator) { + return preg_match('/^1[\d]{10}$/', $value); + }); } } diff --git a/app/Services/UserService.php b/app/Services/UserService.php index 95a6bcc..ca2093c 100644 --- a/app/Services/UserService.php +++ b/app/Services/UserService.php @@ -2,7 +2,10 @@ namespace App\Services; +use App\Exceptions\AdminValidationException; use App\Models\User; +use Illuminate\Support\Facades\Validator; +use Illuminate\Validation\Rule; use Slowlyo\OwlAdmin\Services\AdminService; /** @@ -12,6 +15,23 @@ class UserService extends AdminService { protected string $modelName = User::class; + public function saving(&$data, $primaryKey = '') + { + $unique = Rule::unique('users', 'phone'); + $createRules = [ + 'phone' => ['required', $unique, 'phone'] + ]; + $updateRules = [ + 'phone' => ['phone', $unique->ignore($primaryKey)] + ]; + + $validator = Validator::make($data, $primaryKey ? $updateRules : $createRules); + + if ($validator->fails()) { + throw new AdminValidationException($validator->errors()); + } + } + public function sortable($query) { $query->orderByDesc('id'); diff --git a/lang/zh_CN/validation.php b/lang/zh_CN/validation.php index e914746..1dd12bb 100644 --- a/lang/zh_CN/validation.php +++ b/lang/zh_CN/validation.php @@ -134,7 +134,7 @@ return [ 'string' => ':Attribute 必须是一个字符串。', 'timezone' => ':Attribute 必须是一个合法的时区值。', 'ulid' => ':Attribute 必须是有效的 ULID。', - 'unique' => ':Attribute 已经存在。', + 'unique' => ':Attribute :input 已经存在。', 'uploaded' => ':Attribute 上传失败。', 'uppercase' => ':Attribute 必须大写', 'url' => ':Attribute 格式不正确。', @@ -182,7 +182,7 @@ return [ 'number' => '数字', 'password' => '密码', 'password_confirmation' => '确认密码', - 'phone' => '电话', + 'phone' => '手机号', 'photo' => '照片', 'postal_code' => '邮政编码', 'price' => '价格', @@ -213,5 +213,5 @@ return [ 'year' => '年', 'money' => '金额', ], - 'phone' => '不是一个有效的手机号', + 'phone' => ':input 不是一个有效的手机号', ]; diff --git a/tests/Feature/ExampleTest.php b/tests/Feature/ExampleTest.php index 3d548dd..db9eea7 100644 --- a/tests/Feature/ExampleTest.php +++ b/tests/Feature/ExampleTest.php @@ -3,7 +3,6 @@ namespace Tests\Feature; // use Illuminate\Foundation\Testing\RefreshDatabase; - use Tests\TestCase; class ExampleTest extends TestCase @@ -13,6 +12,5 @@ class ExampleTest extends TestCase */ public function test_the_application_returns_a_successful_response(): void { - dump(now()); } }