From 26dc3dfa6f49cf2c31298ec719147e67c6c225e2 Mon Sep 17 00:00:00 2001 From: liutk <961510893@qq.com> Date: Mon, 23 Feb 2026 21:02:03 +0800 Subject: [PATCH] 0.85 --- .../Controllers/Api/ContactController.php | 40 +++++++++++++ app/Http/Requests/ContactRequest.php | 57 +++++++++++++++++++ app/Models/Contact.php | 27 +++++++++ app/Rules/CaptchaRule.php | 43 ++++++++++++++ app/Services/CaptchaService.php | 2 +- database/seeders/KeywordSeeder.php | 3 + routes/api.php | 3 + 7 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 app/Http/Controllers/Api/ContactController.php create mode 100644 app/Http/Requests/ContactRequest.php create mode 100644 app/Rules/CaptchaRule.php diff --git a/app/Http/Controllers/Api/ContactController.php b/app/Http/Controllers/Api/ContactController.php new file mode 100644 index 0000000..d83804b --- /dev/null +++ b/app/Http/Controllers/Api/ContactController.php @@ -0,0 +1,40 @@ +input(); + try { + DB::beginTransaction(); + Contact::create($inputParams); + DB::commit(); + } catch(\Throwable $th) { + DB::rollBack(); + report($th); + + return $this->error('提交失败,请稍后再试'); + } + + return $this->success('提交成功!'); + } + + /** + * 标签列表 + */ + public function types(Request $request){ + $query = Keyword::allChildrenOfKey('contact_types'); + $list = $query->sort()->get(); + return $this->json(KeywordResource::collection($list)); + } +} \ No newline at end of file diff --git a/app/Http/Requests/ContactRequest.php b/app/Http/Requests/ContactRequest.php new file mode 100644 index 0000000..fd98063 --- /dev/null +++ b/app/Http/Requests/ContactRequest.php @@ -0,0 +1,57 @@ + 'required|string|max:20', + 'phone' => 'required|string|regex:/^1[3-9]\d{9}$/|unique:contacts,phone', + 'captcha' => ['required', 'string', new CaptchaRule(request()->input('key'))], + 'company' => 'required|string|max:50', + 'type' => ['required', 'integer', Rule::exists('keywords', 'id')->where('parent_key', 'contact_types')], + 'content' => 'required|string|max:255', + 'key' => 'required|string|max:255', + ]; + } + + public function messages() + { + $messages = [ + 'name.required' => '姓名不能为空', + 'name.max' => '姓名最大不能超过20长度', + 'phone.required' => '手机号不能为空', + 'phone.regex' => '手机号格式不正确', + 'phone.unique' => '该手机号已提交过询价,请耐心等待工作人员联系', + 'company.required' => '公司不能为空', + 'company.max' => '公司名称最大不能超过50长度', + 'content.required' => '需求描述不能为空', + 'content.max' => '需求描述最大不能超过200长度', + 'captcha.required' => '请输入验证码', + 'type.required' => '请选择业务需求', + 'type.exists' => '业务需求类型不存在', + 'key.required' => '非法请求', + ]; + + return $messages; + } + + protected function failedValidation(Validator $validator) + { + $error = $validator->errors()->all(); + throw new HttpResponseException(response()->json(['data' => [], 'code' => 400, 'message' => $error[0]])); + } +} diff --git a/app/Models/Contact.php b/app/Models/Contact.php index c843206..8b76c47 100644 --- a/app/Models/Contact.php +++ b/app/Models/Contact.php @@ -4,8 +4,35 @@ namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use EloquentFilter\Filterable; class Contact extends Model { use HasFactory; + use Filterable; + + protected function serializeDate(\DateTimeInterface $date) + { + return $date->format('Y-m-d H:i:s'); + } + + protected $casts = [ + 'created_at' => 'datetime:Y-m-d H:i:s', + 'updated_at' => 'datetime:Y-m-d H:i:s', + 'status' => 'boolean', + ]; + + protected $fillable = [ + 'name', + 'phone', + 'company', + 'type', + 'content', + ]; + + + public function scopeSort($q) + { + $q->orderBy('created_at', 'desc'); + } } diff --git a/app/Rules/CaptchaRule.php b/app/Rules/CaptchaRule.php new file mode 100644 index 0000000..37375e1 --- /dev/null +++ b/app/Rules/CaptchaRule.php @@ -0,0 +1,43 @@ +key = $key; + } + + /** + * Run the validation rule. + * + * @param \Closure(string): \Illuminate\Translation\PotentiallyTranslatedString $fail + */ + public function validate(string $attribute, mixed $value, Closure $fail): void + { + // + // 从容器获取 Service(便于测试和依赖注入) + $captchaService = App::make(CaptchaService::class); + + if (!$captchaService->testPhrase($this->key, $value)) { + $fail('验证码错误,请重新输入'); + } + } +} diff --git a/app/Services/CaptchaService.php b/app/Services/CaptchaService.php index fa58a02..98ae33d 100644 --- a/app/Services/CaptchaService.php +++ b/app/Services/CaptchaService.php @@ -65,7 +65,7 @@ class CaptchaService public function validatePhrase(string $key, string $phrase): void { if (! $this->testPhrase($key, $phrase)) { - throw new BizException(__('Invalid captcha')); + throw new BizException(__('无效验证码')); } } diff --git a/database/seeders/KeywordSeeder.php b/database/seeders/KeywordSeeder.php index 07562a1..af99c95 100644 --- a/database/seeders/KeywordSeeder.php +++ b/database/seeders/KeywordSeeder.php @@ -26,6 +26,9 @@ class KeywordSeeder extends Seeder ]], ['key' => 'honors', 'name' => '资质荣誉', 'list' => [ 'honor1'=>'核心资质认证', 'honor2'=>'管理体系认证','honor3'=>'重要荣誉奖项' + ]], + ['key' => 'contact_types', 'name' => '业务需求类别', 'list' => [ + ]], ['key' => 'case_study_tag', 'name' => '服务案例标签', 'list' => [//标签value填写色号,指定标签颜色 'case_study_tag1'=>'全项目保洁', diff --git a/routes/api.php b/routes/api.php index 9af7f4d..a9bc28d 100644 --- a/routes/api.php +++ b/routes/api.php @@ -45,4 +45,7 @@ Route::middleware('api')->group(function () { Route::get('/honors', [HonorController::class, 'index']); //发展历程 Route::get('/timelines', [TimelineController::class, 'index']); + //联系我们 + Route::get('/contact_types', [ContactController::class, 'types']); + Route::post('/contacts', [ContactController::class, 'store']); }); \ No newline at end of file