From b4d8d98d8ed8cc9cd35031b352c1bb348c06254a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=9D=99?= Date: Tue, 7 Dec 2021 14:06:24 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9C=B0=E5=9D=80=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Http/Controllers/AddressController.php | 119 ++++++++++++++++++ .../Api/Http/Resources/AddressResource.php | 27 ++++ app/Endpoint/Api/routes.php | 3 + app/Models/Address.php | 35 ++++++ app/Models/User.php | 8 ++ app/Models/Zone.php | 60 +++++++++ ...21_12_07_131430_create_addresses_table.php | 38 ++++++ resources/lang/zh_CN/models.php | 2 + 8 files changed, 292 insertions(+) create mode 100644 app/Endpoint/Api/Http/Controllers/AddressController.php create mode 100644 app/Endpoint/Api/Http/Resources/AddressResource.php create mode 100644 app/Models/Address.php create mode 100644 database/migrations/2021_12_07_131430_create_addresses_table.php diff --git a/app/Endpoint/Api/Http/Controllers/AddressController.php b/app/Endpoint/Api/Http/Controllers/AddressController.php new file mode 100644 index 00000000..d5a2e9ee --- /dev/null +++ b/app/Endpoint/Api/Http/Controllers/AddressController.php @@ -0,0 +1,119 @@ +user()->addresses()->latest('id')->get(); + + return AddressResource::collection($addresses->sortByDesc('is_default')); + } + + /** + * 添加地址 + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\JsonResponse + */ + public function store(Request $request) + { + $input = $request->validate([ + 'zone_id' => ['bail', 'required', 'int'], + 'consignee' => ['bail', 'required', 'max:255'], + 'telephone' => ['bail', 'required', new PhoneNumber()], + 'address' => ['bail', 'required', 'string', 'max:255'], + 'is_default' => ['bail', 'required', 'bool'], + ]); + + $zone = Zone::areas()->findOrFail($input['zone_id']); + + $user = $request->user(); + + $address = $user->addresses()->create( + array_merge($input, ['zone' => $zone->full_name]) + ); + + if ($address->is_default) { + $user->addresses()->where('id', '!=', $address->id)->update(['is_default' => false]); + } + + return AddressResource::make($address); + } + + /** + * 查看地址 + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\JsonResponse + */ + public function show($id, Request $request) + { + $address = $request->user()->addresses()->findOrFail($id); + + return AddressResource::make($address); + } + + /** + * 编辑地址 + * + * @param int $id + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\JsonResponse + */ + public function update($id, Request $request) + { + $input = $request->validate([ + 'zone_id' => ['bail', 'required', 'int'], + 'consignee' => ['bail', 'required', 'max:255'], + 'telephone' => ['bail', 'required', new PhoneNumber()], + 'address' => ['bail', 'required', 'string', 'max:255'], + 'is_default' => ['bail', 'required', 'bool'], + ]); + + $user = $request->user(); + + $address = $user->addresses()->findOrFail($id); + $address->fill($input); + + if ($address->isDirty('zone_id')) { + $zone = Zone::areas()->findOrFail($input['zone_id']); + + $address->zone = $zone->full_name; + } + + $address->save(); + + if ($address->is_default && $address->wasChanged('is_default')) { + $user->addresses()->where('id', '!=', $address->id)->update(['is_default' => false]); + } + + return AddressResource::make($address); + } + + /** + * 删除地址 + * + * @param int $id + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\Response + */ + public function destroy($id, Request $request) + { + $request->user()->addresses()->where('id', $id)->delete(); + + return response()->noContent(); + } +} diff --git a/app/Endpoint/Api/Http/Resources/AddressResource.php b/app/Endpoint/Api/Http/Resources/AddressResource.php new file mode 100644 index 00000000..c8e553e8 --- /dev/null +++ b/app/Endpoint/Api/Http/Resources/AddressResource.php @@ -0,0 +1,27 @@ + $this->id, + 'zone_id' => $this->zone_id, + 'consignee' => $this->consignee, + 'telephone' => $this->telephone, + 'zone' => $this->zone, + 'address' => $this->address, + 'is_default' => $this->is_default, + ]; + } +} diff --git a/app/Endpoint/Api/routes.php b/app/Endpoint/Api/routes.php index e4d11e1d..57b57b2c 100644 --- a/app/Endpoint/Api/routes.php +++ b/app/Endpoint/Api/routes.php @@ -3,6 +3,7 @@ use App\Endpoint\Api\Http\Controllers\Account\ChangePasswordController; use App\Endpoint\Api\Http\Controllers\Account\UserController; use App\Endpoint\Api\Http\Controllers\AdController; +use App\Endpoint\Api\Http\Controllers\AddressController; use App\Endpoint\Api\Http\Controllers\Auth\LoginController; use App\Endpoint\Api\Http\Controllers\Auth\LogoutController; use App\Endpoint\Api\Http\Controllers\Auth\RegisterController; @@ -65,5 +66,7 @@ Route::group([ Route::post('shopping-cart-items', [ShoppingCartItemController::class, 'store']); Route::delete('shopping-cart-items', [ShoppingCartItemController::class, 'delete']); Route::put('shopping-cart-items/{shopping_cart_item}', [ShoppingCartItemController::class, 'update']); + + Route::apiResource('addresses', AddressController::class); }); }); diff --git a/app/Models/Address.php b/app/Models/Address.php new file mode 100644 index 00000000..dc029fd5 --- /dev/null +++ b/app/Models/Address.php @@ -0,0 +1,35 @@ + false, + ]; + + /** + * @var array + */ + protected $casts = [ + 'is_default' => 'bool', + ]; + + /** + * @var array + */ + protected $fillable = [ + 'user_id', + 'zone_id', + 'consignee', + 'telephone', + 'zone', + 'address', + 'is_default', + ]; +} diff --git a/app/Models/User.php b/app/Models/User.php index 109e391e..4b3e7a17 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -86,6 +86,14 @@ class User extends Model implements AuthorizableContract, AuthenticatableContrac return $this->hasMany(ShoppingCartItem::class); } + /** + * 属于此用户的地址 + */ + public function addresses() + { + return $this->hasMany(Address::class); + } + /** * 禁用用户 * diff --git a/app/Models/Zone.php b/app/Models/Zone.php index 76d94667..5ad80b7b 100644 --- a/app/Models/Zone.php +++ b/app/Models/Zone.php @@ -18,4 +18,64 @@ class Zone extends Model 'parent_id', 'type', ]; + + /** + * 仅查询区级地区 + */ + public function scopeAreas($query) + { + return $query->where('type', static::TYPE_AREA); + } + + /** + * 此地区的上级地区 + */ + public function parent() + { + return $this->belongsTo(static::class, 'parent_id'); + } + + /** + * 确认此地区是否是省 + * + * @return bool + */ + public function isProvince(): bool + { + return $this->type === static::TYPE_PROVINCE; + } + + /** + * 确认此地区是否是市 + * + * @return bool + */ + public function isCity(): bool + { + return $this->type === static::TYPE_CITY; + } + + /** + * 确认此地区是否是区 + * + * @return bool + */ + public function isArea(): bool + { + return $this->type === static::TYPE_AREA; + } + + /** + * 获取当前地区的完整名称 + * + * @return string + */ + public function getFullNameAttribute() + { + if ($this->parent_id === null) { + return $this->name; + } + + return $this->parent->full_name . ' ' . $this->name; + } } diff --git a/database/migrations/2021_12_07_131430_create_addresses_table.php b/database/migrations/2021_12_07_131430_create_addresses_table.php new file mode 100644 index 00000000..54276b8e --- /dev/null +++ b/database/migrations/2021_12_07_131430_create_addresses_table.php @@ -0,0 +1,38 @@ +id(); + $table->unsignedBigInteger('user_id')->comment('地区ID'); + $table->unsignedBigInteger('zone_id')->comment('地区ID'); + $table->string('consignee')->comment('收件人'); + $table->string('telephone')->comment('联系电话'); + $table->string('zone')->comment('所在地区'); + $table->string('address')->comment('详细地址'); + $table->boolean('is_default')->default(false)->comment('是否默认'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('addresses'); + } +} diff --git a/resources/lang/zh_CN/models.php b/resources/lang/zh_CN/models.php index cb2303fa..acb910e2 100644 --- a/resources/lang/zh_CN/models.php +++ b/resources/lang/zh_CN/models.php @@ -4,10 +4,12 @@ use App\Models\Address; use App\Models\ProductSku; use App\Models\ProductSpu; use App\Models\ShoppingCartItem; +use App\Models\Zone; return [ Address::class => '地址', ProductSpu::class => '商品', ProductSku::class => '商品', ShoppingCartItem::class => '商品', + Zone::class => '地区', ];