From 67b7bf3f554474d4729315f0e24e027bedd63350 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=9D=99?= Date: Tue, 30 Nov 2021 09:49:54 +0800 Subject: [PATCH] =?UTF-8?q?=E8=BF=87=E6=BB=A4=E5=95=86=E5=93=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Endpoint/Api/Filters/ProductSkuFilter.php | 61 +++++++++++++ .../Http/Controllers/ProductController.php | 90 +++++++++++++++++++ .../ProductSku/ProductSkuSimpleResource.php | 26 ++++++ app/Endpoint/Api/routes.php | 2 + app/Models/ProductCategory.php | 23 ++++- 5 files changed, 201 insertions(+), 1 deletion(-) create mode 100644 app/Endpoint/Api/Filters/ProductSkuFilter.php create mode 100644 app/Endpoint/Api/Http/Controllers/ProductController.php create mode 100644 app/Endpoint/Api/Http/Resources/ProductSku/ProductSkuSimpleResource.php diff --git a/app/Endpoint/Api/Filters/ProductSkuFilter.php b/app/Endpoint/Api/Filters/ProductSkuFilter.php new file mode 100644 index 00000000..de019256 --- /dev/null +++ b/app/Endpoint/Api/Filters/ProductSkuFilter.php @@ -0,0 +1,61 @@ +find($id); + + if ($category === null) { + return $this->whereRaw('1=0'); + } + + $ids = $category->descendants()->showable()->pluck('id'); + + if ($ids->isEmpty()) { + $this->where('category_id', $id); + } else { + $this->whereIn('category_id', $ids); + } + } + + /** + * 关键字搜索商品 + * + * @param string $keyword + */ + public function keyword($keyword) + { + $this->whereLike('name', $keyword); + } + + /** + * 商品排序 + * + * @param string $sort + */ + public function sort($sort) + { + $column = str_ireplace('-', '', $sort); + + if (in_array($column, ['price', 'sales', 'release_at'])) { + if ($column === 'price') { + $column = 'sell_price'; + } + + return $this->orderBy($column, strpos($sort, '-') === 0 ? 'desc' : 'asc'); + } + + $this->orderBy('id', 'desc'); + } +} diff --git a/app/Endpoint/Api/Http/Controllers/ProductController.php b/app/Endpoint/Api/Http/Controllers/ProductController.php new file mode 100644 index 00000000..40bb1524 --- /dev/null +++ b/app/Endpoint/Api/Http/Controllers/ProductController.php @@ -0,0 +1,90 @@ +filled('part') + ? $this->filterProductsByPart($request) + : $this->filterProducts($request) + ); + } + + /** + * 过滤商品 + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Pagination\Paginator + */ + protected function filterProducts(Request $request): Paginator + { + $input = $request->input(); + + if ($request->isNotFilled('sort')) { + $input['sort'] = '-id'; + } + + return ProductSku::select(['id', 'name', 'cover', 'sell_price', 'vip_price', 'sales']) + ->filter($input) + ->isRelease() + ->whereRelation('category', 'is_show', true) + ->simplePaginate($this->getPerPage($request)); + } + + /** + * 按分区过滤商品 + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Pagination\Paginator + */ + protected function filterProductsByPart(Request $request): Paginator + { + $productPart = ProductPart::where('key', $request->input('part'))->first(); + + if ($productPart === null) { + return new Paginator([], $this->getPerPage($request), Paginator::resolveCurrentPage()); + } + + $paginator = ProductPartSku::with('sku:id,name,cover,sell_price,vip_price,sales') + ->whereHas('sku', function ($query) { + $query->isRelease()->whereRelation('category', 'is_show', true); + }) + ->where('part_id', $productPart->id) + ->latest('sort') + ->simplePaginate($this->getPerPage($request)); + + return $paginator->through(function ($item) { + return $item->sku; + }); + } + + /** + * @return int + */ + protected function getPerPage(Request $request): int + { + $perPage = (int) $request->input('per_page'); + + if ($perPage > 0) { + return $perPage > 50 ? 50 : $perPage; + } + + return 20; + } +} diff --git a/app/Endpoint/Api/Http/Resources/ProductSku/ProductSkuSimpleResource.php b/app/Endpoint/Api/Http/Resources/ProductSku/ProductSkuSimpleResource.php new file mode 100644 index 00000000..61a8ef67 --- /dev/null +++ b/app/Endpoint/Api/Http/Resources/ProductSku/ProductSkuSimpleResource.php @@ -0,0 +1,26 @@ + $this->id, + 'name' => $this->name, + 'cover' => (string) $this->cover, + 'sell_price' => (string) $this->sell_price, + 'vip_price' => (string) $this->vip_price, + 'sales' => (string) $this->sales, + ]; + } +} diff --git a/app/Endpoint/Api/routes.php b/app/Endpoint/Api/routes.php index 1601ffda..2048b83d 100644 --- a/app/Endpoint/Api/routes.php +++ b/app/Endpoint/Api/routes.php @@ -5,6 +5,7 @@ use App\Endpoint\Api\Http\Controllers\CaptchaController; use App\Endpoint\Api\Http\Controllers\LoginController; use App\Endpoint\Api\Http\Controllers\LogoutController; use App\Endpoint\Api\Http\Controllers\ProductCategoryController; +use App\Endpoint\Api\Http\Controllers\ProductController; use App\Endpoint\Api\Http\Controllers\RegisterController; use App\Endpoint\Api\Http\Controllers\SmsCodeController; use Illuminate\Support\Facades\Route; @@ -27,4 +28,5 @@ Route::group([ Route::get('ads', [AdController::class, 'index']); Route::get('product-categories', [ProductCategoryController::class, 'index']); + Route::get('products', [ProductController::class, 'index']); }); diff --git a/app/Models/ProductCategory.php b/app/Models/ProductCategory.php index e35eddb5..df2509fa 100644 --- a/app/Models/ProductCategory.php +++ b/app/Models/ProductCategory.php @@ -17,13 +17,34 @@ class ProductCategory extends Model use ModelTree; use HasDateTimeFormatter; - protected $table = 'product_categories'; + /** + * @var array + */ + protected $attributes = [ + 'is_show' => false, + 'is_recommend' => false, + 'sort' => 0, + ]; + /** + * @var array + */ protected $casts = [ 'is_show' => 'boolean', 'is_recommend' => 'boolean', ]; + /** + * @var array + */ + protected $fillable = [ + 'name', + 'icon', + 'is_show', + 'is_recommend', + 'sort', + ]; + // 排序字段名称,默认值为 order protected $orderColumn = 'sort';