From db489a842965102978109ac667a1a027c44f429a Mon Sep 17 00:00:00 2001 From: jsasg <735273025@qq.com> Date: Fri, 24 Jan 2025 17:54:04 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BA=A7=E5=93=81=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/admin/controller/v1/Product.php | 157 ++++++++++++++++++ app/admin/model/v1/ProductCategoryModel.php | 15 ++ app/admin/model/v1/ProductModel.php | 81 +++++++++ app/admin/route/v1.php | 24 +++ app/admin/validate/v1/ProductValidate.php | 115 +++++++++++++ app/common/model/BaseModel.php | 31 ++++ app/common/model/ProductAttrBaseModel.php | 28 ++++ app/common/model/ProductAttrPropBaseModel.php | 26 +++ app/common/model/ProductBaseModel.php | 43 +++++ app/common/model/ProductCategoryBaseModel.php | 38 +++++ app/common/model/ProductInquiryBaseModel.php | 32 ++++ app/common/model/ProductParamsBaseModel.php | 27 +++ .../model/ProductPurchaseLinkBaseModel.php | 28 ++++ .../ProductPurchasePlatformBaseModel.php | 27 +++ app/common/model/ProductRelatedBaseModel.php | 28 ++++ app/common/model/ProductSkuAttrBaseModel.php | 23 +++ app/common/model/ProductSkuBaseModel.php | 29 ++++ .../model/ProductTcoCategoryBaseModel.php | 35 ++++ 18 files changed, 787 insertions(+) create mode 100644 app/admin/controller/v1/Product.php create mode 100644 app/admin/model/v1/ProductCategoryModel.php create mode 100644 app/admin/model/v1/ProductModel.php create mode 100644 app/admin/validate/v1/ProductValidate.php create mode 100644 app/common/model/BaseModel.php create mode 100644 app/common/model/ProductAttrBaseModel.php create mode 100644 app/common/model/ProductAttrPropBaseModel.php create mode 100644 app/common/model/ProductBaseModel.php create mode 100644 app/common/model/ProductCategoryBaseModel.php create mode 100644 app/common/model/ProductInquiryBaseModel.php create mode 100644 app/common/model/ProductParamsBaseModel.php create mode 100644 app/common/model/ProductPurchaseLinkBaseModel.php create mode 100644 app/common/model/ProductPurchasePlatformBaseModel.php create mode 100644 app/common/model/ProductRelatedBaseModel.php create mode 100644 app/common/model/ProductSkuAttrBaseModel.php create mode 100644 app/common/model/ProductSkuBaseModel.php create mode 100644 app/common/model/ProductTcoCategoryBaseModel.php diff --git a/app/admin/controller/v1/Product.php b/app/admin/controller/v1/Product.php new file mode 100644 index 00000000..c12cb1b8 --- /dev/null +++ b/app/admin/controller/v1/Product.php @@ -0,0 +1,157 @@ +get([ + 'name', + 'spu', + 'category_id', + 'created_at', + 'is_sale', + 'page/d' => 1, + 'size/d' => 10 + ]); + + $validate = new ProductValidate(); + if (!$validate->scene('index')->check($param)) { + return error($validate->getError()); + } + + $products = ProductModel::field([ + 'id', + 'name', + 'cover_image', + 'spu', + 'category_id', + 'sort', + 'is_new', + 'is_hot', + 'is_sale', + 'status', + 'created_at' + ]) + ->with('category') + ->language(request()->lang_id) + ->withSearch(['name_nullable', 'spu_nullable', 'created_at_nullable'], [ + 'name_nullable' => $param['name']??null, + 'spu_nullable' => $param['spu']??null, + 'created_at_nullable' => $param['created_at']??null, + ]) + ->categoryNullable($param['category_id']??null) + ->isSaleNullable(isset($param['is_sale']) ? (bool)$param['is_sale'] : null) + ->order(['sort' => 'asc', 'id' => 'desc']) + ->paginate([ + 'list_rows' => $param['size'], + 'page' => $param['page'], + ]) + ->bindAttr('category', ['category_name' => 'name']) + ->hidden(['category_id', 'category']); + + return success('获取成功', $products); + } + + // 产品详情 + public function read() + { + $product = ProductModel::withoutField([ + 'language_id', + 'created_at', + 'updated_at', + 'deleted_at' + ]) + ->bypk(request()->param('id')) + ->find(); + if (empty($product)) { + return error('产品不存在'); + } + + return success('获取成功', $product); + } + + // 更新 + public function update() + { + $id = request()->param('id'); + $put = request()->put([ + 'category_id', + 'spu', + 'name', + 'short_name', + 'cover_image', + 'desc', + 'video_img', + 'video_url', + 'is_sale', + 'is_new', + 'is_hot', + 'sort', + 'detail', + 'status' => 1, + 'seo_title', + 'seo_keywords', + 'seo_desc' + ]); + + $validate = new ProductValidate(); + $check_data = array_merge($put, [ + 'id' => $id, + 'language_id' => request()->lang_id + ]); + if (!$validate->scene('update')->check($check_data)) { + return error($validate->getError()); + } + + $product = ProductModel::bypk($id)->find(); + if (is_null($product)) { + return error('请确认操作对象是否存在'); + } + + if (!$product->save($put)) { + return error('操作失败'); + } + + return success('操作成功'); + } + + // 上下架操作 + public function updownShelves() + { + $id = request()->param('id'); + $product = ProductModel::bypk($id )->find(); + if (empty($product)) { + return error('请确认操作对象是否存在'); + } + + $product->is_sale = (int)!$product->is_sale; + if (!$product->save()) { + return error('操作失败'); + } + + return success('操作成功'); + } + + // 删除 + public function delete() + { + $product = ProductModel::bypk(request()->param('id'))->find(); + if (empty($product)) { + return error('请确认操作对象是否存在'); + } + + // 软删除 + if (!$product->delete()) { + return error('操作失败'); + } + + return success('操作成功'); + } +} diff --git a/app/admin/model/v1/ProductCategoryModel.php b/app/admin/model/v1/ProductCategoryModel.php new file mode 100644 index 00000000..6c83fe51 --- /dev/null +++ b/app/admin/model/v1/ProductCategoryModel.php @@ -0,0 +1,15 @@ +belongsTo('ProductCategoryModel', 'category_id', 'id'); + } + + // 搜索器名称 + public function searchNameNullableAttr($query, $value, $data) + { + if (is_null($value)) { + return; + } + $query->where('name', 'like', '%' . $value . '%'); + } + + // 搜索spu + public function searchSpuNullableAttr($query, $value, $data) + { + if (is_null($value)) { + return; + } + $query->where('spu', 'like', '%' . $value . '%'); + } + + // 搜索发布时间 + public function searchCreatedAtNullableAttr($query, $value, $data) + { + if (is_array($value)) { + if (count($value) == 2) { + $query->whereBetweenTime('created_at', $value[0], $value[1]); + } else { + $query->whereTime('created_at', '>=', $value[0]); + } + } + } + + // 所属语言查询 + public function scopeLanguage($query, $value) + { + $query->where('language_id', '=', $value); + } + + // 产品分类查询 + public function scopeCategoryNullable($query, $value) + { + if (is_null($value)) { + return; + } + $query->where('category_id', '=', $value); + } + + // 上架状态查询 + public function scopeIsSaleNullable($query, bool|null $value) + { + if (is_null($value)) { + return; + } + $query->where('is_sale', '=', (int)$value); + } +} diff --git a/app/admin/route/v1.php b/app/admin/route/v1.php index c35dd630..68b7dd3c 100644 --- a/app/admin/route/v1.php +++ b/app/admin/route/v1.php @@ -109,6 +109,30 @@ Route::group('v1', function () { Route::delete('delete/:id', 'ArticleTrash/delete'); }); }); + + // 产品模块 + Route::group('product', function () { + // 产品分页列表 + Route::get('index', 'Product/index'); + + // 产品详情 + Route::get('read/:id', 'Product/read'); + + // 产品新增 + Route::post('save', 'Product/save'); + + // 产品更新 + Route::put('update/:id', 'Product/update'); + + // 上/下架操作 + Route::get('updown_shelves/:id', 'Product/updownShelves'); + + // 产品删除 + Route::delete('delete/:id', 'Product/delete'); + + // 产品导出 + Route::get('export', 'Product/export'); + }); })->prefix('v1.'); Route::miss(function() { diff --git a/app/admin/validate/v1/ProductValidate.php b/app/admin/validate/v1/ProductValidate.php new file mode 100644 index 00000000..2530f05c --- /dev/null +++ b/app/admin/validate/v1/ProductValidate.php @@ -0,0 +1,115 @@ + ['规则1','规则2'...] + * + * @var array + */ + protected $rule = [ + 'category_id' => 'integer', + 'spu' => 'require|max:255', + 'name' => 'require|max:125', + 'short_name' => 'max:64', + 'cover_image' => 'max:255', + 'desc' => 'max:255', + 'video_img' => 'max:255', + 'video_url' => 'max:255', + 'is_sale' => 'in:0,1', + 'is_new' => 'in:0,1', + 'is_hot' => 'in:0,1', + 'sort' => 'integer', + 'detail' => 'max:65535', + 'status' => 'in:-1,1', + 'seo_title' => 'max:255', + 'seo_keywords' => 'max:255', + 'seo_desc' => 'max:255', + 'created_at' => 'checkFormatDatetimeRange' + ]; + + /** + * 定义错误信息 + * 格式:'字段名.规则名' => '错误信息' + * + * @var array + */ + protected $message = [ + 'category_id.integer' => '分类ID必须为整数', + 'spu.require' => 'spu不能为空', + 'spu.max' => 'spu不能超过255个字符', + 'name.require' => '名称不能为空', + 'name.max' => '名称不能超过125个字符', + 'short_name.max' => '短标题不能超过64个字符', + 'cover_image.max' => '封面图不能超过255个字符', + 'desc.max' => '描述不能超过255个字符', + 'video_img.max' => '视频封面图不能超过255个字符', + 'video_url.max' => '视频地址不能超过255个字符', + 'is_sale.in' => '上架状态值错误', + 'is_new.in' => '新品状态值错误', + 'is_hot.in' => '热门状态值错误', + 'sort.integer' => '排序值类型错误', + 'detail.max' => '详情不能超过65535个字符', + 'status.in' => '状态值错误', + 'seo_title.max' => 'seo标题不能超过255个字符', + 'seo_keywords.max' => 'seo关键字不能超过255个字符', + 'seo_desc.max' => 'seo描述不能超过255个字符', + 'created_at.checkFormatDatetimeRange' => '添加时间格式错误' + ]; + + /** + * 分页列表验证场景 + */ + public function sceneIndex() + { + return $this->only(['created_id', 'is_sale', 'created_at']); + } + + /** + * 数据更新验证场景 + */ + public function sceneUpdate() + { + return $this->only([ + 'category_id', + 'spu', + 'name', + 'short_name', + 'cover_image', + 'desc', + 'video_img', + 'video_url', + 'is_sale', + 'is_new', + 'is_hot', + 'sort', + 'detail', + 'status', + 'seo_title', + 'seo_keywords', + 'seo_desc', + ]); + } + + protected function checkFormatDatetimeRange($value, $rule, $data) + { + $val = explode(',', $value); + if (empty($val)) return '时间错误'; + $v1 = strtotime($val[0]); + if (!$v1) return '时间错误'; + if (count($val) == 2) { + $v2 = strtotime($val[1]); + if (!$v2) { + return '时间错误'; + } + } + + return true; + } +} diff --git a/app/common/model/BaseModel.php b/app/common/model/BaseModel.php new file mode 100644 index 00000000..e5f9ad86 --- /dev/null +++ b/app/common/model/BaseModel.php @@ -0,0 +1,31 @@ +where((new static)->pk, '=', $pk); + } + + /** + * 根据多主键查询 + */ + public function scopeBypks($query, $pks) + { + if (!is_array($pks) && (is_string($pks) && false === strpos($pks, ','))) { + throw new \Exception('pks参数为级数或逗号分隔字符串'); + } + $query->where((new static)->pk, 'in', $pks); + } +} diff --git a/app/common/model/ProductAttrBaseModel.php b/app/common/model/ProductAttrBaseModel.php new file mode 100644 index 00000000..9b83d4f9 --- /dev/null +++ b/app/common/model/ProductAttrBaseModel.php @@ -0,0 +1,28 @@ + 'int', + 'language_id' => 'int', + 'attr_name' => 'string', + 'is_system' => 'string', + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + ]; +} diff --git a/app/common/model/ProductAttrPropBaseModel.php b/app/common/model/ProductAttrPropBaseModel.php new file mode 100644 index 00000000..552d0a2b --- /dev/null +++ b/app/common/model/ProductAttrPropBaseModel.php @@ -0,0 +1,26 @@ + 'int', + 'prop_name' => 'string', + 'prop_value' => 'string', + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + ]; +} diff --git a/app/common/model/ProductBaseModel.php b/app/common/model/ProductBaseModel.php new file mode 100644 index 00000000..c5dc8ca6 --- /dev/null +++ b/app/common/model/ProductBaseModel.php @@ -0,0 +1,43 @@ + 'int', + 'language_id' => 'int', + 'category_id' => 'int', + 'spu' => 'string', + 'name' => 'string', + 'short_name' => 'string', + 'cover_image' => 'string', + 'desc' => 'string', + 'video_img' => 'string', + 'video_url' => 'string', + 'is_sale' => 'int', + 'is_new' => 'int', + 'is_hot' => 'int', + 'sort' => 'int', + 'detail' => 'string', + 'status' => 'int', + 'seo_title' => 'string', + 'seo_keywords' => 'string', + 'seo_desc' => 'string', + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime' + ]; +} diff --git a/app/common/model/ProductCategoryBaseModel.php b/app/common/model/ProductCategoryBaseModel.php new file mode 100644 index 00000000..3ea5614d --- /dev/null +++ b/app/common/model/ProductCategoryBaseModel.php @@ -0,0 +1,38 @@ + 'int', + 'language_id' => 'int', + 'unique_id' => 'string', + 'pid' => 'int', + 'name' => 'string', + 'icon' => 'string', + 'desc' => 'string', + 'related_tco_category' => 'string', + 'sort' => 'int', + 'level' => 'int', + 'is_show' => 'int', + 'seo_title' => 'string', + 'seo_keywords' => 'string', + 'seo_desc' => 'string', + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + ]; +} diff --git a/app/common/model/ProductInquiryBaseModel.php b/app/common/model/ProductInquiryBaseModel.php new file mode 100644 index 00000000..512663b0 --- /dev/null +++ b/app/common/model/ProductInquiryBaseModel.php @@ -0,0 +1,32 @@ + 'int', + 'language_id' => 'int', + 'corp_name' => 'string', + 'fisrt_name' => 'string', + 'last_name' => 'string', + 'email' => 'string', + 'phone' => 'string', + 'country_name' => 'string', + 'industry' => 'string', + 'message' => 'string', + 'created_at' => 'datetime' + ]; +} diff --git a/app/common/model/ProductParamsBaseModel.php b/app/common/model/ProductParamsBaseModel.php new file mode 100644 index 00000000..cb30fc50 --- /dev/null +++ b/app/common/model/ProductParamsBaseModel.php @@ -0,0 +1,27 @@ + 'int', + 'product_id' => 'int', + 'name' => 'string', + 'value' => 'string', + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + ]; +} diff --git a/app/common/model/ProductPurchaseLinkBaseModel.php b/app/common/model/ProductPurchaseLinkBaseModel.php new file mode 100644 index 00000000..bfe4a704 --- /dev/null +++ b/app/common/model/ProductPurchaseLinkBaseModel.php @@ -0,0 +1,28 @@ + 'int', + 'language_id' => 'int', + 'product_id' => 'int', + 'platform_id' => 'int', + 'link' => 'string', + 'sort' => 'int', + 'created_at' => 'datetime', + ]; +} diff --git a/app/common/model/ProductPurchasePlatformBaseModel.php b/app/common/model/ProductPurchasePlatformBaseModel.php new file mode 100644 index 00000000..9ba03a66 --- /dev/null +++ b/app/common/model/ProductPurchasePlatformBaseModel.php @@ -0,0 +1,27 @@ + 'int', + 'language_id' => 'int', + 'platform' => 'string', + 'desc' => 'string', + 'sort' => 'int', + 'created_at' => 'datetime' + ]; +} diff --git a/app/common/model/ProductRelatedBaseModel.php b/app/common/model/ProductRelatedBaseModel.php new file mode 100644 index 00000000..eec802f1 --- /dev/null +++ b/app/common/model/ProductRelatedBaseModel.php @@ -0,0 +1,28 @@ + 'int', + 'product_id' => 'int', + 'related_product_id' => 'int', + 'desc' => 'string', + 'sort' => 'int', + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + ]; +} diff --git a/app/common/model/ProductSkuAttrBaseModel.php b/app/common/model/ProductSkuAttrBaseModel.php new file mode 100644 index 00000000..751f9641 --- /dev/null +++ b/app/common/model/ProductSkuAttrBaseModel.php @@ -0,0 +1,23 @@ + 'int', + 'attr_id' => 'int', + 'prop_id' => 'int', + ]; +} diff --git a/app/common/model/ProductSkuBaseModel.php b/app/common/model/ProductSkuBaseModel.php new file mode 100644 index 00000000..fba8df29 --- /dev/null +++ b/app/common/model/ProductSkuBaseModel.php @@ -0,0 +1,29 @@ + 'int', + 'product_id' => 'int', + 'sku' => 'string', + 'main_image' => 'string', + 'photo_album' => 'string', + 'sort' => 'int', + 'created_at' => 'datetime', + 'updated_at' => 'datetime' + ]; +} diff --git a/app/common/model/ProductTcoCategoryBaseModel.php b/app/common/model/ProductTcoCategoryBaseModel.php new file mode 100644 index 00000000..59c8aeab --- /dev/null +++ b/app/common/model/ProductTcoCategoryBaseModel.php @@ -0,0 +1,35 @@ + 'int', + 'language_id' => 'int', + 'name' => 'int', + 'tco_id' => 'int', + 'tco_pid' => 'int', + 'tco_path' => 'string', + 'erp_id' => 'int', + 'erp_pid' => 'int', + 'erp_path' => 'string', + 'disabled' => 'int', + 'sync_time' => 'int', + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + ]; +}