From 54bd8cc1a398f272e90701ee037d9cc083a4105e Mon Sep 17 00:00:00 2001
From: panliang <1163816051@qq.com>
Date: Mon, 1 Aug 2022 14:50:37 +0800
Subject: [PATCH 1/8] goods list
---
packages/goods/resources/lang/en/goods.php | 3 +
packages/goods/resources/lang/zh_CN/goods.php | 36 ++++
.../goods/resources/views/grid/attr.blade.php | 11 ++
.../goods/resources/views/grid/spec.blade.php | 13 ++
packages/goods/src/GoodsService.php | 109 +++++++++++
packages/goods/src/GoodsServiceProvider.php | 1 +
.../Controllers/Admin/GoodsController.php | 83 ++++++++
packages/goods/src/Http/routes.php | 2 +
packages/goods/src/Models/Goods.php | 35 +++-
packages/goods/src/Models/GoodsBrand.php | 14 ++
packages/goods/src/Models/GoodsSku.php | 23 +++
packages/goods/src/Models/GoodsType.php | 20 ++
packages/goods/updates/CreateGoodsTable.php | 26 ++-
packages/goods/updates/GoodsTableSeeder.php | 179 ++++++++++++++++++
packages/goods/version.php | 1 +
15 files changed, 553 insertions(+), 3 deletions(-)
create mode 100644 packages/goods/resources/lang/en/goods.php
create mode 100644 packages/goods/resources/lang/zh_CN/goods.php
create mode 100644 packages/goods/resources/views/grid/attr.blade.php
create mode 100644 packages/goods/resources/views/grid/spec.blade.php
create mode 100644 packages/goods/src/GoodsService.php
create mode 100644 packages/goods/src/Http/Controllers/Admin/GoodsController.php
create mode 100644 packages/goods/src/Models/GoodsBrand.php
create mode 100644 packages/goods/src/Models/GoodsSku.php
create mode 100644 packages/goods/src/Models/GoodsType.php
create mode 100644 packages/goods/updates/GoodsTableSeeder.php
diff --git a/packages/goods/resources/lang/en/goods.php b/packages/goods/resources/lang/en/goods.php
new file mode 100644
index 0000000..0b67a5f
--- /dev/null
+++ b/packages/goods/resources/lang/en/goods.php
@@ -0,0 +1,3 @@
+ [
+ 'Goods' => '商品信息',
+ 'goods' => '商品信息',
+ ],
+ 'fields' => [
+ 'category_id' => '分类',
+ 'category' => [
+ 'name' => '分类'
+ ],
+ 'brand_id' => '品牌',
+ 'brand' => [
+ 'name' => '品牌'
+ ],
+ 'type_id' => '类别',
+ 'type' => [
+ 'name' => '类别'
+ ],
+ 'name' => '名称',
+ 'goods_sn' => '编号',
+ 'cover_image' => '封面图',
+ 'price' => '售价',
+ 'spec' => '规格',
+ 'attr' => '属性',
+ 'part' => '配件',
+ 'on_sale' => '上架',
+ 'stock' => '库存',
+ 'sold_count' => '销量',
+ 'images' => '详细图',
+ 'content' => '内容',
+ 'created_at' => '创建时间',
+ 'updated_at' => '更新时间',
+ ]
+];
diff --git a/packages/goods/resources/views/grid/attr.blade.php b/packages/goods/resources/views/grid/attr.blade.php
new file mode 100644
index 0000000..e630876
--- /dev/null
+++ b/packages/goods/resources/views/grid/attr.blade.php
@@ -0,0 +1,11 @@
+
+
+
+@if($value)
+@foreach($value as $item)
+
+ {{ $item['name'] }}
+ {{ $item['value'] }}
+
+@endforeach
+@endif
diff --git a/packages/goods/resources/views/grid/spec.blade.php b/packages/goods/resources/views/grid/spec.blade.php
new file mode 100644
index 0000000..697e800
--- /dev/null
+++ b/packages/goods/resources/views/grid/spec.blade.php
@@ -0,0 +1,13 @@
+
+
+
+@if($value)
+@foreach($value as $item)
+
+ {{ $item['name'] }}
+ @foreach($item['values'] as $value)
+ {{ $value['value'] }}({{ $value['price'] }})
+ @endforeach
+
+@endforeach
+@endif
diff --git a/packages/goods/src/GoodsService.php b/packages/goods/src/GoodsService.php
new file mode 100644
index 0000000..9276ccc
--- /dev/null
+++ b/packages/goods/src/GoodsService.php
@@ -0,0 +1,109 @@
+id)->delete();
+ }
+
+ public function generateSku(Goods $goods)
+ {
+ $this->clearSku($goods);
+ if ($goods->spec) {
+ $spec = $goods->spec;
+ $goods_price = $goods->price;
+ $goods_name = $goods->name;
+
+ $specList = [];
+ foreach ($spec as $item) {
+ $items = [];
+ foreach($item['values'] as $value) {
+ array_push($items, [
+ 'name' => $item['name'],
+ 'value' => $value['value'],
+ 'price' => $value['price'],
+ ]);
+ }
+ array_push($specList, $items);
+ }
+ $cartesianList = $this->cartesianProduct($specList);
+ foreach($cartesianList as $items) {
+ $sub_goods_name = $goods_name;
+ $sub_price = $goods_price;
+
+ $goods->skus()->create([
+ 'sn' => $this->generateSn(),
+ 'name' => $sub_goods_name,
+ 'price' => $sub_price,
+ 'stock' => $goods->stock,
+ 'spec' => $items,
+ ]);
+ }
+ }
+ }
+
+ protected function cartesianProduct($sets)
+ {
+ // 保存结果
+ $result = [];
+ if (count($sets) === 1) {
+ // 保存临时数据
+ $tmp = array();
+ // 结果与下一个集合计算笛卡尔积
+ foreach($sets[0] as $set) {
+ $item = [];
+ if (isset($set['value'])) {
+ array_push($item, $set);
+ } else {
+ $item = $set;
+ }
+ array_push($item, $set);
+ $tmp[] = $item;
+ }
+ // 将笛卡尔积写入结果
+ $result = $tmp;
+ return $result;
+ }
+ // 循环遍历集合数据
+ for($i = 0; $i < count($sets) -1 ; $i++) {
+ // 初始化
+ if($i==0){
+ $result = $sets[$i];
+ }
+ // 保存临时数据
+ $tmp = array();
+ // 结果与下一个集合计算笛卡尔积
+ foreach($result as $res) {
+ foreach($sets[$i+1] as $set) {
+ $item = [];
+ if (isset($res['value'])) {
+ array_push($item, $res);
+ } else {
+ $item = $res;
+ }
+ array_push($item, $set);
+ $tmp[] = $item;
+ }
+ }
+ // 将笛卡尔积写入结果
+ $result = $tmp;
+ }
+ return $result;
+ }
+}
diff --git a/packages/goods/src/GoodsServiceProvider.php b/packages/goods/src/GoodsServiceProvider.php
index 8e6b5a1..5d0f646 100644
--- a/packages/goods/src/GoodsServiceProvider.php
+++ b/packages/goods/src/GoodsServiceProvider.php
@@ -10,5 +10,6 @@ class GoodsServiceProvider extends ServiceProvider
protected $menu = [
['title' => '商品管理', 'uri' => '', 'icon' => ''],
['title' => '商品分类', 'uri' => 'goods/category', 'icon' => '', 'parent' => '商品管理'],
+ ['title' => '商品信息', 'uri' => 'goods', 'icon' => '', 'parent' => '商品管理'],
];
}
diff --git a/packages/goods/src/Http/Controllers/Admin/GoodsController.php b/packages/goods/src/Http/Controllers/Admin/GoodsController.php
new file mode 100644
index 0000000..3e18af5
--- /dev/null
+++ b/packages/goods/src/Http/Controllers/Admin/GoodsController.php
@@ -0,0 +1,83 @@
+model()->sort();
+
+ $grid->selector(function (Selector $selector) {
+ $brands = GoodsBrand::get();
+ $types = GoodsType::get();
+ $categories = GoodsCategory::where('level', 3)->get();
+ $prices = ['0-999', '1000-1999', '2000-4999', '5000+'];
+ $selector->selectOne('category_id', __('peidikeji.dcat-admin-extension-goods::goods.fields.category_id'), $categories->pluck('name', 'id'));
+ $selector->selectOne('brand_id', __('peidikeji.dcat-admin-extension-goods::goods.fields.brand_id'), $brands->pluck('name', 'id'));
+ $selector->selectOne('type_id', __('peidikeji.dcat-admin-extension-goods::goods.fields.type_id'), $types->pluck('name', 'id'));
+ $selector->selectOne('price', __('peidikeji.dcat-admin-extension-goods::goods.fields.price'), $prices, function ($q, $value) use ($prices) {
+ $parsePrice = data_get($prices, $value);
+ if ($parsePrice) {
+ $parts = explode('-', $parsePrice);
+ $parts = array_map(fn($v) => (int)$v, $parts);
+ if (count($parts) > 1) {
+ $q->whereBetween('price', $parts);
+ } else {
+ $q->where('price', '>', $parts[0]);
+ }
+ }
+ });
+ });
+
+ $grid->column('goods_sn');
+ $grid->column('category.name');
+ $grid->column('brand.name');
+ $grid->column('type.name')->label();
+ $grid->column('name')->display(function () {
+ return ($this->cover_image ? '
' : '') . ''.$this->name.'';
+ });
+ $grid->column('price');
+ $grid->column('spec')->view('peidikeji.dcat-admin-extension-goods::grid.spec');
+ $grid->column('on_sale')->switch();
+ $grid->column('sold_count');
+
+ $grid->disableRowSelector();
+ });
+ }
+
+ protected function detail($id)
+ {
+ $info = Goods::with(['category', 'brand', 'type'])->findOrFail($id);
+ $show = Show::make($info);
+ $show->field('goods_sn');
+ $show->field('category.name');
+ $show->field('brand.name');
+ $show->field('type.name');
+ $show->field('name');
+ $show->field('price');
+ $show->field('cover_image')->image('', 100);
+ $show->field('images')->image('', 100);
+ $show->field('content')->image('');
+ $show->field('spec')->view('peidikeji.dcat-admin-extension-goods::grid.spec');
+ $show->field('attr')->view('peidikeji.dcat-admin-extension-goods::grid.attr');
+ $show->field('part')->view('peidikeji.dcat-admin-extension-goods::grid.spec');
+ $show->field('on_sale')->bool();
+ $show->field('sold_count');
+ $show->field('created_at')->as(fn($v) => $this->created_at->format('Y-m-d H:i:s'));
+ $show->field('updated_at')->as(fn($v) => $this->updated_at->format('Y-m-d H:i:s'));
+ return $show;
+ }
+}
diff --git a/packages/goods/src/Http/routes.php b/packages/goods/src/Http/routes.php
index 6e9220b..4f98c7c 100644
--- a/packages/goods/src/Http/routes.php
+++ b/packages/goods/src/Http/routes.php
@@ -5,3 +5,5 @@ namespace Peidikeji\Goods\Http\Controllers\Admin;
use Illuminate\Support\Facades\Route;
Route::resource('goods/category', GoodsCategoryController::class);
+
+Route::resource('goods', GoodsController::class);
diff --git a/packages/goods/src/Models/Goods.php b/packages/goods/src/Models/Goods.php
index ed4609f..6ee0993 100644
--- a/packages/goods/src/Models/Goods.php
+++ b/packages/goods/src/Models/Goods.php
@@ -11,5 +11,38 @@ class Goods extends Model
protected $table = 'goods';
- protected $fillable = ['attr', 'category_id', 'content', 'cover_image', 'deleted_at', 'description', 'goods_sn', 'images', 'name', 'on_sale', 'part', 'price', 'sold_count', 'spec', 'stock'];
+ protected $fillable = ['attr', 'category_id', 'type_id', 'brand_id', 'content', 'cover_image', 'deleted_at', 'description', 'goods_sn', 'images', 'name', 'on_sale', 'part', 'price', 'sold_count', 'spec', 'stock'];
+
+ protected $casts = [
+ 'attr' => 'array',
+ 'spec' => 'array',
+ 'part' => 'array',
+ 'content' => 'array',
+ 'images' => 'array',
+ ];
+
+ public function category()
+ {
+ return $this->belongsTo(GoodsCategory::class, 'category_id');
+ }
+
+ public function type()
+ {
+ return $this->belongsTo(GoodsType::class, 'type_id');
+ }
+
+ public function brand()
+ {
+ return $this->belongsTo(GoodsBrand::class, 'brand_id');
+ }
+
+ public function skus()
+ {
+ return $this->hasMany(GoodsSku::class, 'goods_id');
+ }
+
+ public function scopeSort($q)
+ {
+ return $q->orderBy('created_at', 'desc');
+ }
}
diff --git a/packages/goods/src/Models/GoodsBrand.php b/packages/goods/src/Models/GoodsBrand.php
new file mode 100644
index 0000000..367562c
--- /dev/null
+++ b/packages/goods/src/Models/GoodsBrand.php
@@ -0,0 +1,14 @@
+ 'array',
+ ];
+
+ public $timestamps = false;
+
+ public function goods()
+ {
+ return $this->belongsTo(Goods::class, 'goods_id');
+ }
+}
diff --git a/packages/goods/src/Models/GoodsType.php b/packages/goods/src/Models/GoodsType.php
new file mode 100644
index 0000000..a2d1f22
--- /dev/null
+++ b/packages/goods/src/Models/GoodsType.php
@@ -0,0 +1,20 @@
+ 'array',
+ 'spec' => 'array',
+ 'part' => 'array',
+ ];
+
+ public $timestamps = false;
+}
diff --git a/packages/goods/updates/CreateGoodsTable.php b/packages/goods/updates/CreateGoodsTable.php
index 020696a..5ab70e6 100644
--- a/packages/goods/updates/CreateGoodsTable.php
+++ b/packages/goods/updates/CreateGoodsTable.php
@@ -25,18 +25,36 @@ class CreateGoodsTable extends Migration
$table->unsignedTinyInteger('is_enable')->default(1)->comment('状态');
$table->string('path')->default('-')->comment('所有的父级ID');
- $table->comment('商品分类');
+ $table->comment('商品-分类');
+ });
+
+ Schema::create('goods_type', function (Blueprint $table) {
+ $table->id();
+ $table->string('name');
+ $table->json('attr')->nullable()->comment('属性[{name: "属性名", values: [可选值]}]');
+ $table->json('spec')->nullable()->comment('规格[{name: "属性名", values: [可选值]}]');
+ $table->json('part')->nullable()->comment('配件[{name: "属性名", values: [可选值]}]');
+ $table->comment('商品-类型');
+ });
+
+ Schema::create('goods_brand', function (Blueprint $table) {
+ $table->id();
+ $table->string('name')->comment('名称');
+ $table->string('image')->nullable()->comment('图标');
+ $table->comment('商品-品牌');
});
Schema::create('goods', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('category_id')->comment('所属分类, 关联 goods_category.id');
+ $table->unsignedBigInteger('type_id')->nullable()->comment('所属类别');
+ $table->unsignedBigInteger('brand_id')->nullable()->comment('所属品牌');
$table->string('name')->comment('商品名称');
$table->string('goods_sn')->unique()->comment('编号');
$table->string('cover_image')->nullable()->comment('封面图');
$table->json('images')->nullable()->comment('图片集');
$table->string('description')->nullable()->comment('描述');
- $table->text('content')->nullable()->comment('详细');
+ $table->json('content')->nullable()->comment('详细');
$table->unsignedInteger('on_sale')->default(0)->comment('是否上架');
$table->unsignedInteger('stock')->default(0)->comment('库存');
$table->unsignedInteger('sold_count')->default(0)->comment('销量');
@@ -48,6 +66,8 @@ class CreateGoodsTable extends Migration
$table->softDeletes();
$table->foreign('category_id')->references('id')->on('goods_category');
+ $table->foreign('type_id')->references('id')->on('goods_type');
+ $table->foreign('brand_id')->references('id')->on('goods_brand');
$table->comment('商品');
});
@@ -77,5 +97,7 @@ class CreateGoodsTable extends Migration
Schema::dropIfExists('goods_sku');
Schema::dropIfExists('goods');
Schema::dropIfExists('goods_category');
+ Schema::dropIfExists('goods_type');
+ Schema::dropIfExists('goods_brand');
}
};
diff --git a/packages/goods/updates/GoodsTableSeeder.php b/packages/goods/updates/GoodsTableSeeder.php
new file mode 100644
index 0000000..f52eadf
--- /dev/null
+++ b/packages/goods/updates/GoodsTableSeeder.php
@@ -0,0 +1,179 @@
+ '1', 'children' => [
+ ['name' => '1-1', 'children' => [
+ ['name' => '1-1-1']
+ ]]
+ ]],
+ ['name' => '2', 'children' => [
+ ['name' => '2-2', 'children' => [
+ ['name' => '2-2-2']
+ ]]
+ ]],
+ ];
+
+ $this->createCategory($categoryList);
+
+ GoodsType::truncate();
+ $types = [
+ [
+ 'name' => '手机',
+ 'attr' => [
+ ['name' => '入网型号', 'values' => ['5G', '4G']],
+ ['name' => '上市年份', 'values' => null],
+ ['name' => '品牌', 'values' => null]
+ ],
+ 'spec' => [
+ ['name' => '颜色', 'values' => ['白色', '红色', '黑色']],
+ ['name' => '内存', 'values' => ['32G', '64G', '128G']],
+ ],
+ 'part' => [
+ ['name' => '套餐', 'values' => ['套餐1', '套餐2', '套餐3']]
+ ]
+ ],
+ [
+ 'name' => '笔记本电脑',
+ 'attr' => [
+ ['name' => '屏幕类型', 'values' => ['LED 背光显示屏']],
+ ['name' => '物理分辨率', 'values' => ['3072 x 1920 (226 ppi)']],
+ ],
+ 'spec' => [
+ ['name' => '颜色', 'values' => ['白色', '灰色']],
+ ['name' => '内存', 'values' => ['16G', '32G', '64G']],
+ ],
+ 'part' => [
+ ['name' => '套餐', 'values' => ['优惠套装1', '优惠套装2', '优惠套装3']]
+ ]
+ ],
+ ];
+ foreach($types as $item) {
+ GoodsType::create($item);
+ }
+
+ GoodsBrand::truncate();
+ GoodsBrand::insert([
+ ['name' => '三星', 'image' => 'https://img20.360buyimg.com/popshop/jfs/t1/1534/38/9873/3556/5bc93df2E73c40121/74dc92d16e483509.jpg'],
+ ['name' => 'Apple', 'image' => 'https://img20.360buyimg.com/popshop/jfs/t2989/240/151377693/3895/30ad9044/574d36dbN262ef26d.jpg'],
+ ]);
+
+ Goods::truncate();
+ GoodsSku::truncate();
+ $goodsList = [
+ [
+ 'category_id' => 3,
+ 'type_id' => 1,
+ 'brand_id' => 1,
+ 'goods_sn' => '1016',
+ 'name' => '三星Galaxy Noet10+ 5G(SM-N9760)',
+ 'cover_image' => 'https://img14.360buyimg.com/n5/s54x54_jfs/t1/85701/3/3164/116271/5ddcffaeEd7924f35/013d69c48b507982.jpg',
+ 'content' => ['https://img30.360buyimg.com/sku/jfs/t1/91355/34/4028/288919/5de4c653Ed267b5d0/b67ac088ded04947.jpg'],
+ 'images' => [
+ 'https://img14.360buyimg.com/n0/jfs/t1/138249/34/51/266266/5edaed2fE2d4d4050/297b76afaff928bb.jpg',
+ 'https://img14.360buyimg.com/n0/jfs/t1/85701/3/3164/116271/5ddcffaeEd7924f35/013d69c48b507982.jpg',
+ 'https://img14.360buyimg.com/n0/jfs/t1/43997/21/12754/274595/5d5f87f1Ec419d2f9/358032d0a7a2ccd7.jpg'
+ ],
+ 'stock' => 100,
+ 'price' => 6499.00,
+ 'attr' => [
+ ['name' => '入网型号', 'value' => '5G'],
+ ['name' => '品牌', 'value' => '三星Galaxy'],
+ ['name' => '上市年份', 'value' => '2020'],
+ ],
+ 'spec' => [
+ ['name' => '颜色', 'values' => [
+ ['value' => '白色', 'price' => 0],
+ ['value' => '红色', 'price' => 800],
+ ['value' => '黑色', 'price' => 0],
+ ]],
+ ['name' => '内存', 'values' => [
+ ['value' => '32G', 'price' => 0],
+ ['value' => '64G', 'price' => 1000],
+ ['value' => '128G', 'price' => 2000],
+ ]]
+ ],
+ 'part' => [
+ ['name' => '套餐', 'values' => [
+ ['value' => '套餐1', 'price' => 850],
+ ['value' => '套餐2', 'price' => 1200],
+ ['value' => '套餐3', 'price' => 1800],
+ ]]
+ ],
+ ],
+ [
+ 'category_id' => 6,
+ 'type_id' => 2,
+ 'brand_id' => 2,
+ 'goods_sn' => '1017',
+ 'name' => 'MacBook Pro 16英寸',
+ 'cover_image' => 'https://img14.360buyimg.com/n0/jfs/t1/64979/31/15492/115459/5dd3d4f2E75b0a9a6/95c273eda00e67c0.jpg',
+ 'description' => '',
+ 'content' => ['https://img11.360buyimg.com/cms/jfs/t1/77779/20/15834/638477/5dd3d469Eca9fa4a7/26ff2bd661580a86.jpg'],
+ 'images' => [
+ 'https://img14.360buyimg.com/n0/jfs/t1/64979/31/15492/115459/5dd3d4f2E75b0a9a6/95c273eda00e67c0.jpg',
+ 'https://img14.360buyimg.com/n0/jfs/t1/50902/13/16242/169086/5dd3d4f2E19e1994f/ff8ecd5a61c1bebb.jpg',
+ 'https://img14.360buyimg.com/n0/jfs/t1/104429/27/2676/303491/5dd3d4f3E6fd2b80a/b7213eaf5be44b49.jpg'
+ ],
+ 'stock' => 150,
+ 'price' => 17999.00,
+ 'attr' => [
+ ['name' => '屏幕类型', 'value' => 'LED 背光显示屏'],
+ ['name' => '物理分辨率', 'value' => '3072 x 1920 (226 ppi)'],
+ ],
+ 'spec' => [
+ ['name' => '颜色', 'values' => [
+ ['value' => '白色', 'price' => 0],
+ ['value' => '灰色', 'price' => 0]
+ ]],
+ ['name' => '内存', 'values' => [
+ ['value' => '16G', 'price' => 0],
+ ['value' => '32G', 'price' => 3000],
+ ['value' => '64G', 'price' => 6000],
+ ]]
+ ],
+ 'part' => [
+ ['name' => '套餐', 'values' => [
+ ['value' => '优惠套装1', 'price' => 850],
+ ['value' => '优惠套装2', 'price' => 650],
+ ['value' => '优惠套装3', 'price' => 1000],
+ ]]
+ ],
+ ]
+ ];
+
+ $service = GoodsService::make();
+ foreach($goodsList as $item) {
+ $goods = Goods::create($item);
+ $service->generateSku($goods);
+ }
+ }
+
+ protected function createCategory($list, $pid = 0)
+ {
+ foreach($list as $key => $item) {
+ $attributes = Arr::except($item, ['children']);
+ $attributes['parent_id'] = $pid;
+ $attributes['sort'] = $key + 1;
+ $category = GoodsCategory::create($attributes);
+ if ($children = data_get($item, 'children')) {
+ $this->createCategory($children, $category->id);
+ }
+ }
+ }
+}
diff --git a/packages/goods/version.php b/packages/goods/version.php
index bfc02ed..cb0a8b4 100644
--- a/packages/goods/version.php
+++ b/packages/goods/version.php
@@ -3,5 +3,6 @@
return [
'1.0.0' => [
'CreateGoodsTable.php',
+ 'GoodsTableSeeder.php',
],
];
From a08604bf82f867b18fb811846ff956441150b5ae Mon Sep 17 00:00:00 2001
From: panliang <1163816051@qq.com>
Date: Mon, 1 Aug 2022 15:07:32 +0800
Subject: [PATCH 2/8] goods
---
.../Controllers/Admin/GoodsController.php | 33 +++++++++++++++++++
packages/goods/src/Models/GoodsCategory.php | 14 ++++++++
2 files changed, 47 insertions(+)
diff --git a/packages/goods/src/Http/Controllers/Admin/GoodsController.php b/packages/goods/src/Http/Controllers/Admin/GoodsController.php
index 3e18af5..c5ab3c6 100644
--- a/packages/goods/src/Http/Controllers/Admin/GoodsController.php
+++ b/packages/goods/src/Http/Controllers/Admin/GoodsController.php
@@ -2,6 +2,7 @@
namespace Peidikeji\Goods\Http\Controllers\Admin;
+use Dcat\Admin\Form;
use Dcat\Admin\Grid;
use Dcat\Admin\Grid\Tools\Selector;
use Dcat\Admin\Http\Controllers\AdminController;
@@ -80,4 +81,36 @@ class GoodsController extends AdminController
$show->field('updated_at')->as(fn($v) => $this->updated_at->format('Y-m-d H:i:s'));
return $show;
}
+
+ protected function form()
+ {
+ return Form::make(new Goods(), function (Form $form) {
+ $form->select('category_id')->options(GoodsCategory::selectOptions(null, false))->required();
+ $form->select('brand_id')->options(GoodsBrand::pluck('name', 'id'));
+ $form->select('type_id')->options(GoodsType::pluck('name', 'id'));
+ $form->text('name')->required();
+ $form->text('goods_sn');
+ $form->image('cover_image')
+ ->autoUpload()
+ ->saveFullUrl()
+ ->move('goods')
+ ->required();
+ $form->multipleImage('images')
+ ->autoUpload()
+ ->saveFullUrl()
+ ->move('goods');
+ $form->multipleImage('content')
+ ->autoUpload()
+ ->saveFullUrl()
+ ->move('goods');
+
+ $form->number('price')->min(0)->attribute('step', 0.01);
+ $form->switch('on_sale');
+
+ $form->disableResetButton();
+ $form->disableCreatingCheck();
+ $form->disableViewCheck();
+ $form->disableEditingCheck();
+ });
+ }
}
diff --git a/packages/goods/src/Models/GoodsCategory.php b/packages/goods/src/Models/GoodsCategory.php
index a18c8dd..dda29e3 100644
--- a/packages/goods/src/Models/GoodsCategory.php
+++ b/packages/goods/src/Models/GoodsCategory.php
@@ -49,6 +49,20 @@ class GoodsCategory extends Model
});
}
+ public static function selectOptions(\Closure $closure = null, $rootText = null)
+ {
+ $options = (new static())->withQuery($closure)->buildSelectOptions();
+
+ $list = collect($options);
+
+ if ($rootText !== false) {
+ $rootText = $rootText ?: admin_trans_label('root');
+ $list->prepend($rootText, 0);
+ }
+
+ return $list->all();
+ }
+
public function parent()
{
return $this->belongsTo(self::class, 'parent_id');
From 9fcd37b6464870c58ae57521f51b068cf31e9d9a Mon Sep 17 00:00:00 2001
From: panliang <1163816051@qq.com>
Date: Mon, 1 Aug 2022 15:52:00 +0800
Subject: [PATCH 3/8] goods-brand
---
.../goods/resources/lang/en/goods-brand.php | 3 +
.../goods/resources/lang/en/goods-type.php | 3 +
.../resources/lang/zh_CN/goods-brand.php | 13 ++++
.../goods/resources/lang/zh_CN/goods-type.php | 16 +++++
.../goods/resources/views/grid/part.blade.php | 15 +++++
.../goods/resources/views/grid/spec.blade.php | 6 +-
packages/goods/src/GoodsServiceProvider.php | 2 +
.../Admin/GoodsBrandController.php | 50 +++++++++++++++
.../Admin/GoodsCategoryController.php | 2 +-
.../Controllers/Admin/GoodsController.php | 6 +-
.../Controllers/Admin/GoodsTypeController.php | 64 +++++++++++++++++++
packages/goods/src/Http/routes.php | 2 +
packages/goods/src/Models/GoodsBrand.php | 5 ++
packages/goods/updates/CreateGoodsTable.php | 8 +--
14 files changed, 185 insertions(+), 10 deletions(-)
create mode 100644 packages/goods/resources/lang/en/goods-brand.php
create mode 100644 packages/goods/resources/lang/en/goods-type.php
create mode 100644 packages/goods/resources/lang/zh_CN/goods-brand.php
create mode 100644 packages/goods/resources/lang/zh_CN/goods-type.php
create mode 100644 packages/goods/resources/views/grid/part.blade.php
create mode 100644 packages/goods/src/Http/Controllers/Admin/GoodsBrandController.php
create mode 100644 packages/goods/src/Http/Controllers/Admin/GoodsTypeController.php
diff --git a/packages/goods/resources/lang/en/goods-brand.php b/packages/goods/resources/lang/en/goods-brand.php
new file mode 100644
index 0000000..0b67a5f
--- /dev/null
+++ b/packages/goods/resources/lang/en/goods-brand.php
@@ -0,0 +1,3 @@
+ [
+ 'GoodsBrand' => '品牌管理',
+ 'goods' => '商品管理',
+ 'brand' => '品牌',
+ ],
+ 'fields' => [
+ 'name' => '名称',
+ 'image' => '图片',
+ ]
+];
diff --git a/packages/goods/resources/lang/zh_CN/goods-type.php b/packages/goods/resources/lang/zh_CN/goods-type.php
new file mode 100644
index 0000000..e653e2f
--- /dev/null
+++ b/packages/goods/resources/lang/zh_CN/goods-type.php
@@ -0,0 +1,16 @@
+ [
+ 'GoodsType' => '商品类别',
+ 'goods' => '商品管理',
+ 'brand' => '类别',
+ ],
+ 'fields' => [
+ 'name' => '名称',
+ 'spec' => '规格',
+ 'attr' => '属性',
+ 'part' => '配件',
+ 'values' => '可选值',
+ ]
+];
diff --git a/packages/goods/resources/views/grid/part.blade.php b/packages/goods/resources/views/grid/part.blade.php
new file mode 100644
index 0000000..69a636a
--- /dev/null
+++ b/packages/goods/resources/views/grid/part.blade.php
@@ -0,0 +1,15 @@
+
+
+
+@if($value)
+@foreach($value as $item)
+
+ {{ $item['name'] }}
+ @if($item['values'])
+ @foreach($item['values'] as $subItem)
+ {{ $subItem }}
+ @endforeach
+ @endif
+
+@endforeach
+@endif
diff --git a/packages/goods/resources/views/grid/spec.blade.php b/packages/goods/resources/views/grid/spec.blade.php
index 697e800..e5aa0a5 100644
--- a/packages/goods/resources/views/grid/spec.blade.php
+++ b/packages/goods/resources/views/grid/spec.blade.php
@@ -5,9 +5,11 @@
@foreach($value as $item)
{{ $item['name'] }}
- @foreach($item['values'] as $value)
- {{ $value['value'] }}({{ $value['price'] }})
+ @if($item['values'])
+ @foreach($item['values'] as $subItem)
+ {{ $subItem['value'] }}({{ $subItem['price'] }})
@endforeach
+ @endif
@endforeach
@endif
diff --git a/packages/goods/src/GoodsServiceProvider.php b/packages/goods/src/GoodsServiceProvider.php
index 5d0f646..6dac8d7 100644
--- a/packages/goods/src/GoodsServiceProvider.php
+++ b/packages/goods/src/GoodsServiceProvider.php
@@ -10,6 +10,8 @@ class GoodsServiceProvider extends ServiceProvider
protected $menu = [
['title' => '商品管理', 'uri' => '', 'icon' => ''],
['title' => '商品分类', 'uri' => 'goods/category', 'icon' => '', 'parent' => '商品管理'],
+ ['title' => '品牌管理', 'uri' => 'goods/brand', 'icon' => '', 'parent' => '商品管理'],
+ ['title' => '商品类别', 'uri' => 'goods/type', 'icon' => '', 'parent' => '商品管理'],
['title' => '商品信息', 'uri' => 'goods', 'icon' => '', 'parent' => '商品管理'],
];
}
diff --git a/packages/goods/src/Http/Controllers/Admin/GoodsBrandController.php b/packages/goods/src/Http/Controllers/Admin/GoodsBrandController.php
new file mode 100644
index 0000000..65df6eb
--- /dev/null
+++ b/packages/goods/src/Http/Controllers/Admin/GoodsBrandController.php
@@ -0,0 +1,50 @@
+disableRowSelector();
+
+ $grid->disableViewButton();
+
+ $grid->column('name');
+ $grid->column('image')->image('', 120);
+ });
+ }
+
+ protected function form()
+ {
+ return Form::make(new GoodsBrand(), function (Form $form) {
+ $form->text('name');
+ $form->image('image')->autoUpload()->saveFullUrl()->move('goods/brand');
+
+ $form->disableResetButton();
+ $form->disableCreatingCheck();
+ $form->disableViewCheck();
+ $form->disableEditingCheck();
+
+ $form->deleting(function (Form $form) {
+ $data = $form->model()->toArray();
+ foreach($data as $item) {
+ $id = data_get($item, 'id');
+ // 品牌下面包含商品, 阻止删除
+ if (Goods::where('brand_id', $id)->exists()) {
+ return $form->response()->error('请先删除关联的商品');
+ }
+ }
+ });
+ });
+ }
+}
diff --git a/packages/goods/src/Http/Controllers/Admin/GoodsCategoryController.php b/packages/goods/src/Http/Controllers/Admin/GoodsCategoryController.php
index 6223aef..c71c529 100644
--- a/packages/goods/src/Http/Controllers/Admin/GoodsCategoryController.php
+++ b/packages/goods/src/Http/Controllers/Admin/GoodsCategoryController.php
@@ -35,7 +35,7 @@ class GoodsCategoryController extends AdminController
$form->text('name')->required();
$form->image('image')
->uniqueName()
- ->move('article-category')
+ ->move('goods/category')
->autoUpload();
$form->number('sort')
->min(0)
diff --git a/packages/goods/src/Http/Controllers/Admin/GoodsController.php b/packages/goods/src/Http/Controllers/Admin/GoodsController.php
index c5ab3c6..4263b2d 100644
--- a/packages/goods/src/Http/Controllers/Admin/GoodsController.php
+++ b/packages/goods/src/Http/Controllers/Admin/GoodsController.php
@@ -93,16 +93,16 @@ class GoodsController extends AdminController
$form->image('cover_image')
->autoUpload()
->saveFullUrl()
- ->move('goods')
+ ->move('goods/goods')
->required();
$form->multipleImage('images')
->autoUpload()
->saveFullUrl()
- ->move('goods');
+ ->move('goods/goods');
$form->multipleImage('content')
->autoUpload()
->saveFullUrl()
- ->move('goods');
+ ->move('goods/goods');
$form->number('price')->min(0)->attribute('step', 0.01);
$form->switch('on_sale');
diff --git a/packages/goods/src/Http/Controllers/Admin/GoodsTypeController.php b/packages/goods/src/Http/Controllers/Admin/GoodsTypeController.php
new file mode 100644
index 0000000..87a9f1f
--- /dev/null
+++ b/packages/goods/src/Http/Controllers/Admin/GoodsTypeController.php
@@ -0,0 +1,64 @@
+disableRowSelector();
+ $grid->disableViewButton();
+
+ $grid->column('name');
+ $grid->column('attr')->view('peidikeji.dcat-admin-extension-goods::grid.part');
+ $grid->column('spec')->view('peidikeji.dcat-admin-extension-goods::grid.part');
+ $grid->column('part')->view('peidikeji.dcat-admin-extension-goods::grid.part');
+ });
+ }
+
+ protected function form()
+ {
+ return Form::make(new GoodsType(), function (Form $form) {
+ $form->text('name');
+
+ $form->array('attr', function (NestedForm $table) {
+ $table->text('name')->required();
+ $table->list('values');
+ });
+ $form->array('spec', function (NestedForm $table) {
+ $table->text('name')->required();
+ $table->list('values');
+ });
+ $form->array('part', function (NestedForm $table) {
+ $table->text('name')->required();
+ $table->list('values');
+ });
+
+ $form->disableResetButton();
+ $form->disableCreatingCheck();
+ $form->disableViewCheck();
+ $form->disableEditingCheck();
+
+ $form->deleting(function (Form $form) {
+ $data = $form->model()->toArray();
+ foreach($data as $item) {
+ $id = data_get($item, 'id');
+ // 下面包含商品, 阻止删除
+ if (Goods::where('type_id', $id)->exists()) {
+ return $form->response()->error('请先删除关联的商品');
+ }
+ }
+ });
+ });
+ }
+}
diff --git a/packages/goods/src/Http/routes.php b/packages/goods/src/Http/routes.php
index 4f98c7c..8337ee7 100644
--- a/packages/goods/src/Http/routes.php
+++ b/packages/goods/src/Http/routes.php
@@ -5,5 +5,7 @@ namespace Peidikeji\Goods\Http\Controllers\Admin;
use Illuminate\Support\Facades\Route;
Route::resource('goods/category', GoodsCategoryController::class);
+Route::resource('goods/brand', GoodsBrandController::class);
+Route::resource('goods/type', GoodsTypeController::class);
Route::resource('goods', GoodsController::class);
diff --git a/packages/goods/src/Models/GoodsBrand.php b/packages/goods/src/Models/GoodsBrand.php
index 367562c..c0a6b58 100644
--- a/packages/goods/src/Models/GoodsBrand.php
+++ b/packages/goods/src/Models/GoodsBrand.php
@@ -11,4 +11,9 @@ class GoodsBrand extends Model
protected $fillable = ['name', 'image'];
public $timestamps = false;
+
+ public function goods()
+ {
+ return $this->hasMany(Goods::class, 'brand_id');
+ }
}
diff --git a/packages/goods/updates/CreateGoodsTable.php b/packages/goods/updates/CreateGoodsTable.php
index 5ab70e6..0e81261 100644
--- a/packages/goods/updates/CreateGoodsTable.php
+++ b/packages/goods/updates/CreateGoodsTable.php
@@ -59,9 +59,9 @@ class CreateGoodsTable extends Migration
$table->unsignedInteger('stock')->default(0)->comment('库存');
$table->unsignedInteger('sold_count')->default(0)->comment('销量');
$table->decimal('price', 12, 2)->comment('售价');
- $table->json('attr')->nullable()->comment('属性');
- $table->json('spec')->nullable()->comment('规格');
- $table->json('part')->nullable()->comment('配件');
+ $table->json('attr')->nullable()->comment('属性[{name, value}]');
+ $table->json('spec')->nullable()->comment('规格[{name, values: [{value, price}]}]');
+ $table->json('part')->nullable()->comment('配件[{name, values: [{value, price}]}]');
$table->timestamps();
$table->softDeletes();
@@ -79,7 +79,7 @@ class CreateGoodsTable extends Migration
$table->string('name')->comment('名称');
$table->decimal('price', 12, 2)->comment('价格');
$table->unsignedInteger('stock')->comment('库存');
- $table->json('spec')->nullable()->comment('规格');
+ $table->json('spec')->nullable()->comment('规格[{name, value, price}]');
$table->foreign('goods_id')->references('id')->on('goods');
From c923c50abe567a824b24b2d02b9f51a60d96c52e Mon Sep 17 00:00:00 2001
From: panliang <1163816051@qq.com>
Date: Tue, 2 Aug 2022 15:32:47 +0800
Subject: [PATCH 4/8] goods
---
.../goods/resources/lang/en/goods-sku.php | 3 +
.../goods/resources/lang/zh_CN/goods-sku.php | 16 ++
.../goods/src/Actions/RowGoodsSkuList.php | 16 ++
packages/goods/src/GoodsService.php | 12 +-
.../Admin/GoodsBrandController.php | 6 +-
.../Controllers/Admin/GoodsController.php | 6 +
.../Controllers/Admin/GoodsSkuController.php | 170 ++++++++++++++++++
packages/goods/src/Http/routes.php | 2 +
packages/goods/src/Models/GoodsSku.php | 19 ++
9 files changed, 242 insertions(+), 8 deletions(-)
create mode 100644 packages/goods/resources/lang/en/goods-sku.php
create mode 100644 packages/goods/resources/lang/zh_CN/goods-sku.php
create mode 100644 packages/goods/src/Actions/RowGoodsSkuList.php
create mode 100644 packages/goods/src/Http/Controllers/Admin/GoodsSkuController.php
diff --git a/packages/goods/resources/lang/en/goods-sku.php b/packages/goods/resources/lang/en/goods-sku.php
new file mode 100644
index 0000000..0b67a5f
--- /dev/null
+++ b/packages/goods/resources/lang/en/goods-sku.php
@@ -0,0 +1,3 @@
+ [
+ 'GoodsSku' => '货品管理',
+ 'goods' => '商品管理',
+ 'sku' => '商品管理',
+ ],
+ 'fields' => [
+ 'sn' => '货号',
+ 'name' => '名称',
+ 'price' => '价格',
+ 'stock' => '库存',
+ 'spec' => '规格',
+ ]
+];
diff --git a/packages/goods/src/Actions/RowGoodsSkuList.php b/packages/goods/src/Actions/RowGoodsSkuList.php
new file mode 100644
index 0000000..5e6641a
--- /dev/null
+++ b/packages/goods/src/Actions/RowGoodsSkuList.php
@@ -0,0 +1,16 @@
+response()->redirect(admin_route('goods-sku.index', ['goods' => $this->getKey()]));
+ }
+}
diff --git a/packages/goods/src/GoodsService.php b/packages/goods/src/GoodsService.php
index 9276ccc..6bc81ec 100644
--- a/packages/goods/src/GoodsService.php
+++ b/packages/goods/src/GoodsService.php
@@ -27,8 +27,8 @@ class GoodsService
$this->clearSku($goods);
if ($goods->spec) {
$spec = $goods->spec;
- $goods_price = $goods->price;
- $goods_name = $goods->name;
+ $price = $goods->price;
+ $name = $goods->name;
$specList = [];
foreach ($spec as $item) {
@@ -44,13 +44,11 @@ class GoodsService
}
$cartesianList = $this->cartesianProduct($specList);
foreach($cartesianList as $items) {
- $sub_goods_name = $goods_name;
- $sub_price = $goods_price;
-
+ $specPrice = array_sum(array_column($items, 'price'));
$goods->skus()->create([
'sn' => $this->generateSn(),
- 'name' => $sub_goods_name,
- 'price' => $sub_price,
+ 'name' => $name,
+ 'price' => $price + $specPrice,
'stock' => $goods->stock,
'spec' => $items,
]);
diff --git a/packages/goods/src/Http/Controllers/Admin/GoodsBrandController.php b/packages/goods/src/Http/Controllers/Admin/GoodsBrandController.php
index 65df6eb..89c4864 100644
--- a/packages/goods/src/Http/Controllers/Admin/GoodsBrandController.php
+++ b/packages/goods/src/Http/Controllers/Admin/GoodsBrandController.php
@@ -28,7 +28,11 @@ class GoodsBrandController extends AdminController
{
return Form::make(new GoodsBrand(), function (Form $form) {
$form->text('name');
- $form->image('image')->autoUpload()->saveFullUrl()->move('goods/brand');
+ $form->image('image')
+ ->autoUpload()
+ ->saveFullUrl()
+ ->move('goods/brand');
+ // $form->oss('file')->dir('mv');
$form->disableResetButton();
$form->disableCreatingCheck();
diff --git a/packages/goods/src/Http/Controllers/Admin/GoodsController.php b/packages/goods/src/Http/Controllers/Admin/GoodsController.php
index 4263b2d..4c9f517 100644
--- a/packages/goods/src/Http/Controllers/Admin/GoodsController.php
+++ b/packages/goods/src/Http/Controllers/Admin/GoodsController.php
@@ -4,9 +4,11 @@ namespace Peidikeji\Goods\Http\Controllers\Admin;
use Dcat\Admin\Form;
use Dcat\Admin\Grid;
+use Dcat\Admin\Grid\Displayers\Actions;
use Dcat\Admin\Grid\Tools\Selector;
use Dcat\Admin\Http\Controllers\AdminController;
use Dcat\Admin\Show;
+use Peidikeji\Goods\Actions\RowGoodsSkuList;
use Peidikeji\Goods\Models\Goods;
use Peidikeji\Goods\Models\GoodsBrand;
use Peidikeji\Goods\Models\GoodsCategory;
@@ -56,6 +58,10 @@ class GoodsController extends AdminController
$grid->column('sold_count');
$grid->disableRowSelector();
+
+ $grid->actions(function (Actions $actions) {
+ $actions->append(new RowGoodsSkuList());
+ });
});
}
diff --git a/packages/goods/src/Http/Controllers/Admin/GoodsSkuController.php b/packages/goods/src/Http/Controllers/Admin/GoodsSkuController.php
new file mode 100644
index 0000000..8584747
--- /dev/null
+++ b/packages/goods/src/Http/Controllers/Admin/GoodsSkuController.php
@@ -0,0 +1,170 @@
+model()->where('goods_id', $goods->id);
+
+ $grid->selector(function (Selector $selector) use ($goods) {
+ $specs = $goods->spec;
+ foreach($specs as $key => $item) {
+ $values = array_column($item['values'], 'value');
+ $selector->selectOne('spec_' . $key, $item['name'], array_column($item['values'], 'value'), function ($q, $value) use ($values, $item) {
+ $selected = array_values(Arr::only($values, $value));
+ if (count($selected) > 0) {
+ $q->jsonArray([['name' => $item['name'], 'value' => $selected[0]]]);
+ }
+ });
+ }
+ });
+
+ $grid->column('id');
+ $grid->column('sn');
+ $grid->column('name');
+ $grid->column('price');
+ $grid->column('stock');
+ foreach($goods->spec as $key => $item) {
+ $grid->column('spec_' . $key, $item['name'])->display(function () use ($item) {
+ $filtered = current(array_filter($this->spec, fn($subItem) => $subItem['name'] === $item['name']));
+ $value = data_get($filtered, 'value');
+ $price = data_get($filtered, 'price');
+ return ''.$value.'';
+ });
+ }
+ // $grid->column('spec')->view('peidikeji.dcat-admin-extension-goods::grid.attr');
+ });
+ return $content
+ ->translation($this->translation)
+ ->title(admin_trans_label())
+ ->description(trans('admin.list'))
+ ->body($grid);
+ }
+
+ public function show($id, Content $content)
+ {
+ $info = GoodsSku::with(['goods'])->findOrFail($id);
+ $show = Show::make($info, function (Show $show) {
+ $show->field('sn');
+ $show->field('name');
+ $show->field('price');
+ $show->field('stock');
+ // $show->field('spec')->view('peidikeji.dcat-admin-extension-goods::grid.attr');
+ $goods = $show->model()->goods;
+ foreach($goods->spec as $key => $item) {
+ $show->field('spec_' . $key, $item['name'])->as(function () use ($item) {
+ $filtered = current(array_filter($this->spec, fn($subItem) => $subItem['name'] === $item['name']));
+ $value = data_get($filtered, 'value');
+ $price = data_get($filtered, 'price');
+ return ''.$value.'';
+ })->unescape();
+ }
+ });
+ return $content
+ ->translation($this->translation)
+ ->title(admin_trans_label())
+ ->description(trans('admin.show'))
+ ->body($show);
+ }
+
+ protected function form($goods)
+ {
+ return Form::make(new GoodsSku(), function (Form $form) use ($goods) {
+ $unqiue = Rule::unique('goods_sku', 'sn');
+ if ($form->isEditing()) {
+ $unqiue->ignore($form->model()->id);
+ }
+ $form->text('sn')->rules([$unqiue])->required();
+ $form->text('name')->default($goods->name);
+ $form->number('price')->min(0)->default($goods->price);
+ $form->number('stock')->min(0)->default($goods->stock);
+ $form->hidden('spec')->customFormat(fn($v) => json_encode($v));
+ $form->hidden('goods_id')->default($goods->id);
+
+ $spec = $form->model()->spec;
+ foreach($goods->spec as $key => $item) {
+ $values = array_column($item['values'], 'value', 'value');
+ $value = null;
+ if ($spec) {
+ $filtered = current(array_filter($spec, fn($subItem) => $subItem['name'] === $item['name']));
+ $value = array_search($filtered['value'], $values);
+ }
+ $form->radio($item['name'], $item['name'])->options($values)->value($value);
+ }
+
+ $form->saving(function (Form $form) use ($goods) {
+ $info = $form->model();
+ $spec = [];
+ foreach($goods->spec as $item) {
+ array_push($spec, ['name' => $item['name'], 'value' => $form->input($item['name'])]);
+ $form->deleteInput($item['name']);
+ }
+ $form->input('spec', $spec);
+ $query = GoodsSku::where('goods_id', $goods->id)->jsonArray($spec);
+ if ($form->isEditing()) {
+ $query->where('id', '!=', $info->id);
+ }
+ if ($query->exists()) {
+ return $form->response()->error('该规格已经存在');
+ }
+ });
+
+ $form->disableCreatingCheck();
+ $form->disableEditingCheck();
+ $form->disableViewCheck();
+ $form->disableResetButton();
+ });
+ }
+
+ public function edit($goods, $id, Content $content)
+ {
+ $goods = Goods::findOrFail($goods);
+ return $content
+ ->translation($this->translation)
+ ->title(admin_trans_label())
+ ->description(trans('admin.edit'))
+ ->body($this->form($goods)->edit($id));
+ }
+
+ public function create($goods, Content $content)
+ {
+ return $content
+ ->translation($this->translation)
+ ->title(admin_trans_label())
+ ->description(trans('admin.create'))
+ ->body($this->form(Goods::findOrFail($goods)));
+ }
+
+ public function update($goods, $id)
+ {
+ return $this->form(Goods::findOrFail($goods))->update($id);
+ }
+
+ public function store($goods)
+ {
+ return $this->form(Goods::findOrFail($goods))->store();
+ }
+
+ public function destroy($goods, $id)
+ {
+ return $this->form(Goods::findOrFail($goods))->destroy($id);
+ }
+}
diff --git a/packages/goods/src/Http/routes.php b/packages/goods/src/Http/routes.php
index 8337ee7..40d661d 100644
--- a/packages/goods/src/Http/routes.php
+++ b/packages/goods/src/Http/routes.php
@@ -8,4 +8,6 @@ Route::resource('goods/category', GoodsCategoryController::class);
Route::resource('goods/brand', GoodsBrandController::class);
Route::resource('goods/type', GoodsTypeController::class);
+Route::resource('goods/{goods}/sku', GoodsSkuController::class)->names('goods-sku');
+
Route::resource('goods', GoodsController::class);
diff --git a/packages/goods/src/Models/GoodsSku.php b/packages/goods/src/Models/GoodsSku.php
index 994e9c9..2468221 100644
--- a/packages/goods/src/Models/GoodsSku.php
+++ b/packages/goods/src/Models/GoodsSku.php
@@ -3,6 +3,7 @@
namespace Peidikeji\Goods\Models;
use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Query\Builder;
class GoodsSku extends Model
{
@@ -20,4 +21,22 @@ class GoodsSku extends Model
{
return $this->belongsTo(Goods::class, 'goods_id');
}
+
+ /**
+ * Mysql Json 查询
+ * 数据库存储格式: [{"name": "颜色", "price": 0, "value": "白色"}, {"name": "内存", "price": 0, "value": "32G"}]
+ *
+ * @param Builder $q
+ * @param array $params [{"name": "颜色", "value": "白色"}, {"name": "内存", "value": "32G"}]
+ */
+ public function scopeJsonArray($q, $params)
+ {
+ foreach($params as $item) {
+ foreach($item as $key => $value) {
+ $value = is_string($value) ? '"'.$value.'"' : $value;
+ $q->whereRaw("json_contains(spec->>\"$[*].".$key."\", '".$value."')");
+ }
+ }
+ return $q;
+ }
}
From 41eafd3cdd7649152e8cefbc03ee4f2429f7e21d Mon Sep 17 00:00:00 2001
From: panliang <1163816051@qq.com>
Date: Tue, 2 Aug 2022 15:38:39 +0800
Subject: [PATCH 5/8] sku detaul
---
.../goods/resources/views/grid/attr.blade.php | 2 +-
.../Controllers/Admin/GoodsSkuController.php | 25 ++++++++++---------
2 files changed, 14 insertions(+), 13 deletions(-)
diff --git a/packages/goods/resources/views/grid/attr.blade.php b/packages/goods/resources/views/grid/attr.blade.php
index e630876..643a91d 100644
--- a/packages/goods/resources/views/grid/attr.blade.php
+++ b/packages/goods/resources/views/grid/attr.blade.php
@@ -5,7 +5,7 @@
@foreach($value as $item)
{{ $item['name'] }}
- {{ $item['value'] }}
+ {{ $item['value'] }} {{ isset($item['price']) ? '(+'.$item['price'].')' : '' }}
@endforeach
@endif
diff --git a/packages/goods/src/Http/Controllers/Admin/GoodsSkuController.php b/packages/goods/src/Http/Controllers/Admin/GoodsSkuController.php
index 8584747..d61019d 100644
--- a/packages/goods/src/Http/Controllers/Admin/GoodsSkuController.php
+++ b/packages/goods/src/Http/Controllers/Admin/GoodsSkuController.php
@@ -59,24 +59,25 @@ class GoodsSkuController extends Controller
->body($grid);
}
- public function show($id, Content $content)
+ public function show($goods, $id, Content $content)
{
- $info = GoodsSku::with(['goods'])->findOrFail($id);
+ $goods = Goods::findOrFail($goods);
+ $info = GoodsSku::findOrFail($id);
$show = Show::make($info, function (Show $show) {
$show->field('sn');
$show->field('name');
$show->field('price');
$show->field('stock');
- // $show->field('spec')->view('peidikeji.dcat-admin-extension-goods::grid.attr');
- $goods = $show->model()->goods;
- foreach($goods->spec as $key => $item) {
- $show->field('spec_' . $key, $item['name'])->as(function () use ($item) {
- $filtered = current(array_filter($this->spec, fn($subItem) => $subItem['name'] === $item['name']));
- $value = data_get($filtered, 'value');
- $price = data_get($filtered, 'price');
- return ''.$value.'';
- })->unescape();
- }
+ $show->field('spec')->view('peidikeji.dcat-admin-extension-goods::grid.attr');
+ // $goods = $show->model()->goods;
+ // foreach($goods->spec as $key => $item) {
+ // $show->field('spec_' . $key, $item['name'])->as(function () use ($item) {
+ // $filtered = current(array_filter($this->spec, fn($subItem) => $subItem['name'] === $item['name']));
+ // $value = data_get($filtered, 'value');
+ // $price = data_get($filtered, 'price');
+ // return ''.$value.'';
+ // })->unescape();
+ // }
});
return $content
->translation($this->translation)
From f050bbf5b5f5a629143c64421c47ad483e36ae2d Mon Sep 17 00:00:00 2001
From: panliang <1163816051@qq.com>
Date: Wed, 3 Aug 2022 15:00:58 +0800
Subject: [PATCH 6/8] goods create
---
.../goods/resources/lang/zh_CN/goods-sku.php | 3 +-
.../goods/resources/lang/zh_CN/goods-type.php | 3 +-
packages/goods/resources/lang/zh_CN/goods.php | 2 +
.../Admin/GoodsBrandController.php | 7 +-
.../Controllers/Admin/GoodsController.php | 125 +++++++++++++++---
.../Controllers/Admin/GoodsSkuController.php | 1 +
.../Controllers/Admin/GoodsTypeController.php | 1 +
packages/goods/updates/GoodsTableSeeder.php | 20 +--
src/Form.php | 3 +-
9 files changed, 131 insertions(+), 34 deletions(-)
diff --git a/packages/goods/resources/lang/zh_CN/goods-sku.php b/packages/goods/resources/lang/zh_CN/goods-sku.php
index 3edc557..5c8f5bc 100644
--- a/packages/goods/resources/lang/zh_CN/goods-sku.php
+++ b/packages/goods/resources/lang/zh_CN/goods-sku.php
@@ -9,8 +9,9 @@ return [
'fields' => [
'sn' => '货号',
'name' => '名称',
- 'price' => '价格',
+ 'price' => '售价',
'stock' => '库存',
'spec' => '规格',
+ 'origin_price' => '原价',
]
];
diff --git a/packages/goods/resources/lang/zh_CN/goods-type.php b/packages/goods/resources/lang/zh_CN/goods-type.php
index e653e2f..c2c16dc 100644
--- a/packages/goods/resources/lang/zh_CN/goods-type.php
+++ b/packages/goods/resources/lang/zh_CN/goods-type.php
@@ -4,7 +4,7 @@ return [
'labels' => [
'GoodsType' => '商品类别',
'goods' => '商品管理',
- 'brand' => '类别',
+ 'type' => '商品类别',
],
'fields' => [
'name' => '名称',
@@ -12,5 +12,6 @@ return [
'attr' => '属性',
'part' => '配件',
'values' => '可选值',
+ 'group' => '分组',
]
];
diff --git a/packages/goods/resources/lang/zh_CN/goods.php b/packages/goods/resources/lang/zh_CN/goods.php
index 23838e5..f314135 100644
--- a/packages/goods/resources/lang/zh_CN/goods.php
+++ b/packages/goods/resources/lang/zh_CN/goods.php
@@ -4,6 +4,8 @@ return [
'labels' => [
'Goods' => '商品信息',
'goods' => '商品信息',
+ 'create' => '创建',
+ 'edit' => '修改',
],
'fields' => [
'category_id' => '分类',
diff --git a/packages/goods/src/Http/Controllers/Admin/GoodsBrandController.php b/packages/goods/src/Http/Controllers/Admin/GoodsBrandController.php
index 89c4864..946956e 100644
--- a/packages/goods/src/Http/Controllers/Admin/GoodsBrandController.php
+++ b/packages/goods/src/Http/Controllers/Admin/GoodsBrandController.php
@@ -32,7 +32,12 @@ class GoodsBrandController extends AdminController
->autoUpload()
->saveFullUrl()
->move('goods/brand');
- // $form->oss('file')->dir('mv');
+ $form->oss('file')->config([
+ 'accessId' => 'LTAI5tFMaynxgZ9aDMNLxpU9',
+ 'accessKey' => 'pecJA3LX2sQyWxWDMUUb5NhsMe4Czu',
+ 'host' => 'https://zcs-test.oss-cn-chengdu.aliyuncs.com',
+ 'dir' => 'mv',
+ ]);
$form->disableResetButton();
$form->disableCreatingCheck();
diff --git a/packages/goods/src/Http/Controllers/Admin/GoodsController.php b/packages/goods/src/Http/Controllers/Admin/GoodsController.php
index 4c9f517..10f80a0 100644
--- a/packages/goods/src/Http/Controllers/Admin/GoodsController.php
+++ b/packages/goods/src/Http/Controllers/Admin/GoodsController.php
@@ -2,7 +2,11 @@
namespace Peidikeji\Goods\Http\Controllers\Admin;
+use Dcat\Admin\Admin;
use Dcat\Admin\Form;
+use Dcat\Admin\Form\BlockForm;
+use Dcat\Admin\Form\NestedForm;
+use Dcat\Admin\Form\Row;
use Dcat\Admin\Grid;
use Dcat\Admin\Grid\Displayers\Actions;
use Dcat\Admin\Grid\Tools\Selector;
@@ -91,32 +95,113 @@ class GoodsController extends AdminController
protected function form()
{
return Form::make(new Goods(), function (Form $form) {
- $form->select('category_id')->options(GoodsCategory::selectOptions(null, false))->required();
- $form->select('brand_id')->options(GoodsBrand::pluck('name', 'id'));
- $form->select('type_id')->options(GoodsType::pluck('name', 'id'));
- $form->text('name')->required();
- $form->text('goods_sn');
- $form->image('cover_image')
- ->autoUpload()
- ->saveFullUrl()
- ->move('goods/goods')
- ->required();
- $form->multipleImage('images')
- ->autoUpload()
- ->saveFullUrl()
- ->move('goods/goods');
- $form->multipleImage('content')
- ->autoUpload()
- ->saveFullUrl()
- ->move('goods/goods');
+ $model = $form->model();
+ $isCreating = $form->isCreating();
+ $type = null;
- $form->number('price')->min(0)->attribute('step', 0.01);
- $form->switch('on_sale');
+ if (request('type_id') && $isCreating) {
+ $typeId = request('type_id');
+ $type = GoodsType::find($typeId);
+ if ($type) {
+ $attrbutes = [
+ 'type_id' => $type->id,
+ 'attr' => $type->attr,
+ 'spec' => $type->spec,
+ 'part' => $type->part,
+ ];
+ $form->model($attrbutes);
+ }
+ }
+ $model = $form->model();
+ if (!$type) {
+ $type = $model && $model->type_id ? GoodsType::find($form->model()->type_id) : null;
+ }
+
+ $form->disableHeader();
+ $form->tab('基本设置', function (Form $form) use ($isCreating, $type) {
+ if ($isCreating) {
+ $form->select('type_id')->options(GoodsType::pluck('name', 'id'));
+ } else {
+ $form->display('type_id')->with(fn() => $type->name);
+ }
+ $form->select('category_id')->options(GoodsCategory::selectOptions(null, false))->required();
+ $form->select('brand_id')->options(GoodsBrand::pluck('name', 'id'));
+ $form->text('name')->required();
+ $form->text('goods_sn');
+ $form->image('cover_image')
+ ->autoUpload()
+ ->saveFullUrl()
+ ->move('goods/goods')
+ ->required();
+ $form->multipleImage('images')
+ ->autoUpload()
+ ->saveFullUrl()
+ ->move('goods/goods');
+ $form->multipleImage('content')
+ ->autoUpload()
+ ->saveFullUrl()
+ ->move('goods/goods');
+
+ $form->number('price')->min(0)->attribute('step', 0.01);
+ $form->switch('on_sale');
+ });
+
+ $form->tab('属性', function (Form $form) use ($type) {
+ $form->array('attr', null, function (NestedForm $table) use ($type) {
+ $values = data_get($type, 'attr.' . $table->getKey() . '.values') ?: [];
+ $table->text('group', '分组');
+ $table->text('name', '属性名')->required();
+ $table->autocomplete('value', '属性值')->options($values)->configs(['minChars' => 0]);
+ });
+ });
+ $form->tab('规格', function (Form $form) use ($type) {
+ $form->array('spec', null, function (NestedForm $table) use ($type) {
+ $table->text('name', '名称')->required();
+ $values = data_get($type, 'spec.' . $table->getKey() . '.values') ?: [];
+ $table->array('values', null, function (NestedForm $table) use ($values) {
+ $index = $table->getKey();
+ $table->autocomplete('value', '可选值')
+ ->default($index === null ? '' : data_get($values, $index, ''))
+ ->options($values)
+ ->configs(['minChars' => 0]);
+ $table->number('price', '加价')->min(0)->default();
+ });
+ });
+ });
+ $form->tab('配件', function (Form $form) use ($type) {
+ $form->array('part', null, function (NestedForm $table) use ($type) {
+ $table->text('name', '名称')->required();
+ $values = data_get($type, 'part.' . $table->getKey() . '.values') ?: [];
+ $table->array('values', null, function (NestedForm $table) use ($values) {
+ $index = $table->getKey();
+ $table->autocomplete('value', '可选值')
+ ->default($index === null ? '' : data_get($values, $index, ''))
+ ->options($values)
+ ->configs(['minChars' => 0]);
+ $table->number('price', '加价')->min(0)->default();
+ });
+ });
+ });
$form->disableResetButton();
$form->disableCreatingCheck();
$form->disableViewCheck();
$form->disableEditingCheck();
+
+ $admin_url = request()->url();
+ Admin::script(
+ <<column('id');
$grid->column('sn');
$grid->column('name');
+ $grid->column('origin_price')->display(fn() => $goods->price);
$grid->column('price');
$grid->column('stock');
foreach($goods->spec as $key => $item) {
diff --git a/packages/goods/src/Http/Controllers/Admin/GoodsTypeController.php b/packages/goods/src/Http/Controllers/Admin/GoodsTypeController.php
index 87a9f1f..950b5c4 100644
--- a/packages/goods/src/Http/Controllers/Admin/GoodsTypeController.php
+++ b/packages/goods/src/Http/Controllers/Admin/GoodsTypeController.php
@@ -33,6 +33,7 @@ class GoodsTypeController extends AdminController
$form->array('attr', function (NestedForm $table) {
$table->text('name')->required();
+ $table->text('group');
$table->list('values');
});
$form->array('spec', function (NestedForm $table) {
diff --git a/packages/goods/updates/GoodsTableSeeder.php b/packages/goods/updates/GoodsTableSeeder.php
index f52eadf..bf0f38f 100644
--- a/packages/goods/updates/GoodsTableSeeder.php
+++ b/packages/goods/updates/GoodsTableSeeder.php
@@ -36,9 +36,9 @@ class GoodsTableSeeder extends Seeder
[
'name' => '手机',
'attr' => [
- ['name' => '入网型号', 'values' => ['5G', '4G']],
- ['name' => '上市年份', 'values' => null],
- ['name' => '品牌', 'values' => null]
+ ['group' => '主体', 'name' => '入网型号', 'values' => ['5G', '4G']],
+ ['group' => '主体', 'name' => '上市年份', 'values' => null],
+ ['group' => '主体', 'name' => '品牌', 'values' => null]
],
'spec' => [
['name' => '颜色', 'values' => ['白色', '红色', '黑色']],
@@ -51,8 +51,8 @@ class GoodsTableSeeder extends Seeder
[
'name' => '笔记本电脑',
'attr' => [
- ['name' => '屏幕类型', 'values' => ['LED 背光显示屏']],
- ['name' => '物理分辨率', 'values' => ['3072 x 1920 (226 ppi)']],
+ ['group' => '显示器', 'name' => '屏幕类型', 'values' => ['LED 背光显示屏']],
+ ['group' => '显示器','name' => '物理分辨率', 'values' => ['3072 x 1920 (226 ppi)']],
],
'spec' => [
['name' => '颜色', 'values' => ['白色', '灰色']],
@@ -92,9 +92,9 @@ class GoodsTableSeeder extends Seeder
'stock' => 100,
'price' => 6499.00,
'attr' => [
- ['name' => '入网型号', 'value' => '5G'],
- ['name' => '品牌', 'value' => '三星Galaxy'],
- ['name' => '上市年份', 'value' => '2020'],
+ ['group' => '主体', 'name' => '入网型号', 'value' => '5G'],
+ ['group' => '主体', 'name' => '品牌', 'value' => '三星Galaxy'],
+ ['group' => '主体', 'name' => '上市年份', 'value' => '2020'],
],
'spec' => [
['name' => '颜色', 'values' => [
@@ -133,8 +133,8 @@ class GoodsTableSeeder extends Seeder
'stock' => 150,
'price' => 17999.00,
'attr' => [
- ['name' => '屏幕类型', 'value' => 'LED 背光显示屏'],
- ['name' => '物理分辨率', 'value' => '3072 x 1920 (226 ppi)'],
+ ['group' => '显示器','name' => '屏幕类型', 'value' => 'LED 背光显示屏'],
+ ['group' => '显示器','name' => '物理分辨率', 'value' => '3072 x 1920 (226 ppi)'],
],
'spec' => [
['name' => '颜色', 'values' => [
diff --git a/src/Form.php b/src/Form.php
index b6cb6cb..0592589 100755
--- a/src/Form.php
+++ b/src/Form.php
@@ -1183,13 +1183,14 @@ class Form implements Renderable
{
$this->build();
+ $this->fillFields($this->model()->toArray());
+
if ($this->isCreating()) {
$this->callCreating();
return;
}
- $this->fillFields($this->model()->toArray());
$this->callEditing();
}
From 4b4a79fde747000b0ba24395d54ce8fafc56ef48 Mon Sep 17 00:00:00 2001
From: panliang <1163816051@qq.com>
Date: Wed, 3 Aug 2022 15:02:13 +0800
Subject: [PATCH 7/8] 1
---
.../Http/Controllers/Admin/GoodsBrandController.php | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/packages/goods/src/Http/Controllers/Admin/GoodsBrandController.php b/packages/goods/src/Http/Controllers/Admin/GoodsBrandController.php
index 946956e..79618c6 100644
--- a/packages/goods/src/Http/Controllers/Admin/GoodsBrandController.php
+++ b/packages/goods/src/Http/Controllers/Admin/GoodsBrandController.php
@@ -32,12 +32,12 @@ class GoodsBrandController extends AdminController
->autoUpload()
->saveFullUrl()
->move('goods/brand');
- $form->oss('file')->config([
- 'accessId' => 'LTAI5tFMaynxgZ9aDMNLxpU9',
- 'accessKey' => 'pecJA3LX2sQyWxWDMUUb5NhsMe4Czu',
- 'host' => 'https://zcs-test.oss-cn-chengdu.aliyuncs.com',
- 'dir' => 'mv',
- ]);
+ // $form->oss('file')->config([
+ // 'accessId' => 'LTAI5tFMaynxgZ9aDMNLxpU9',
+ // 'accessKey' => 'pecJA3LX2sQyWxWDMUUb5NhsMe4Czu',
+ // 'host' => 'https://zcs-test.oss-cn-chengdu.aliyuncs.com',
+ // 'dir' => 'mv',
+ // ]);
$form->disableResetButton();
$form->disableCreatingCheck();
From 5066df4dfe80f2d63d4d2134634f021d8764c6a0 Mon Sep 17 00:00:00 2001
From: panliang <1163816051@qq.com>
Date: Wed, 3 Aug 2022 15:02:32 +0800
Subject: [PATCH 8/8] 1
---
packages/goods/src/Http/Controllers/Admin/GoodsController.php | 2 --
1 file changed, 2 deletions(-)
diff --git a/packages/goods/src/Http/Controllers/Admin/GoodsController.php b/packages/goods/src/Http/Controllers/Admin/GoodsController.php
index 10f80a0..24e41a1 100644
--- a/packages/goods/src/Http/Controllers/Admin/GoodsController.php
+++ b/packages/goods/src/Http/Controllers/Admin/GoodsController.php
@@ -193,8 +193,6 @@ class GoodsController extends AdminController
<<