goods
parent
bb3937cd4d
commit
86208dd0dd
33
README.md
33
README.md
|
|
@ -7,10 +7,39 @@ Dcat-admin 商品管理
|
|||
- 进入项目目录
|
||||
- `mkdir packages && cd packages`
|
||||
- `git clone https://gitea.peidikeji.cn/pdkj/dcat-admin-goods.git`
|
||||
- `composer config repositories.peidikeji/dcat-admin-user path ./packages/dcat-admin-goods`
|
||||
- `composer require peidikeji/dcat-admin-goods:dev-develop`
|
||||
- `composer config repositories.peidikeji/dcat-admin-goods path ./packages/dcat-admin-goods`
|
||||
- `composer require peidikeji/dcat-admin-goods`
|
||||
- `php artisan migrate`
|
||||
- `php artisan vendor:publish --provider=Peidikeji\Goods\GoodsServiceProvider`
|
||||
|
||||
## 测试数据
|
||||
|
||||
- 复制文件 `database/seeders/GoodsCategorySeeder`, ``database/seeders/GoodsSeeder``
|
||||
|
||||
## 后台权限
|
||||
|
||||
```php
|
||||
$permissions = [
|
||||
'goods' => ['name' => '商品管理', 'curd' => true],
|
||||
'goods_category' => ['name' => '商品分类', 'curd' => true],
|
||||
'goods_brand' => ['name' => '商品品牌', 'curd' => true],
|
||||
'goods_type' => ['name' => '商品类别', 'curd' => true],
|
||||
];
|
||||
```
|
||||
|
||||
## 后台菜单
|
||||
|
||||
```php
|
||||
$menus = [
|
||||
['title' => '商品模块', 'icon' => 'feather icon-layers', 'uri' => '', 'permission' => ['goods', 'goods_category', 'goods_brand', 'goods_type'], 'children' => [
|
||||
['title' => '商品分类', 'icon' => '', 'uri' => '/goods-category', 'permission' => 'goods_category'],
|
||||
['title' => '商品品牌', 'icon' => '', 'uri' => '/goods-brand', 'permission' => 'goods_brand'],
|
||||
['title' => '商品类别', 'icon' => '', 'uri' => '/goods-type', 'permission' => 'goods_type'],
|
||||
['title' => '商品管理', 'icon' => '', 'uri' => '/goods', 'permission' => 'goods'],
|
||||
]],
|
||||
];
|
||||
```
|
||||
|
||||
## 数据表
|
||||
|
||||
### 商品分类: goods_category
|
||||
|
|
|
|||
|
|
@ -15,14 +15,14 @@
|
|||
"require": {
|
||||
"php": ">=8.1.0",
|
||||
"peidikeji/dcat-admin": "*",
|
||||
"tucker-eric/eloquentfilter": "^3.1",
|
||||
"laravel/framework": "^9.0"
|
||||
"tucker-eric/eloquentfilter": "^3.1"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Peidikeji\\Goods\\": "src/"
|
||||
}
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
|
|
|
|||
|
|
@ -0,0 +1,103 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Peidikeji\Goods\Models\GoodsCategory;
|
||||
|
||||
class GoodsCategorySeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
DB::statement('SET FOREIGN_KEY_CHECKS = 0;');
|
||||
GoodsCategory::truncate();
|
||||
$categoryList = [
|
||||
['name' => '男装', 'children' => [
|
||||
['name' => 'T恤', 'children' => [
|
||||
['name' => '纯色T恤'],
|
||||
['name' => '联名T恤'],
|
||||
['name' => '纯色POLO'],
|
||||
]],
|
||||
['name' => '裤装','children' => [
|
||||
['name' => '直筒牛仔裤'],
|
||||
['name' => '休闲裤'],
|
||||
['name' => '卫裤'],
|
||||
]],
|
||||
['name' => '衬衫', 'children' => [
|
||||
['name' => '正装衬衫'],
|
||||
['name' => '纯色衬衫'],
|
||||
['name' => '牛仔衬衫'],
|
||||
]],
|
||||
]],
|
||||
['name' => '女装', 'children' => [
|
||||
['name' => '外套', 'children' => [
|
||||
['name' => '休闲西装'],
|
||||
['name' => '牛仔外套'],
|
||||
['name' => '风衣'],
|
||||
]],
|
||||
['name' => '裙装', 'children' => [
|
||||
['name' => '连衣裙'],
|
||||
['name' => '衬衫裙'],
|
||||
['name' => '半身裙'],
|
||||
]],
|
||||
['name' => '裤装', 'children' => [
|
||||
['name' => '牛仔'],
|
||||
['name' => '工装裤'],
|
||||
['name' => '休闲裤'],
|
||||
]],
|
||||
]],
|
||||
['name' => '手机', 'children' => [
|
||||
['name' => '手机', 'children' => [
|
||||
['name' => '5G手机'],
|
||||
['name' => '游戏手机'],
|
||||
['name' => '长续航手机'],
|
||||
]],
|
||||
['name' => '运营商', 'children' => [
|
||||
['name' => '中国移动'],
|
||||
['name' => '中国联通'],
|
||||
['name' => '中国电信'],
|
||||
]],
|
||||
['name' => '手机配件', 'children' => [
|
||||
['name' => '充电宝'],
|
||||
['name' => '数据线'],
|
||||
['name' => '手机耳机'],
|
||||
]],
|
||||
]],
|
||||
];
|
||||
|
||||
foreach ($categoryList as $index => $item) {
|
||||
$attributes = Arr::except($item, ['children']);
|
||||
$category = GoodsCategory::create(array_merge([
|
||||
'parent_id' => 0,
|
||||
'sort' => $index + 1,
|
||||
], $attributes));
|
||||
}
|
||||
|
||||
foreach ($categoryList as $index => $item) {
|
||||
if ($children = data_get($item, 'children')) {
|
||||
$this->createCategory($children, $item['id'] ?? 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function createCategory($list, $pid = 0)
|
||||
{
|
||||
foreach ($list as $index => $item) {
|
||||
$attributes = Arr::except($item, ['children']);
|
||||
$category = GoodsCategory::create(array_merge([
|
||||
'parent_id' => $pid,
|
||||
'sort' => $index + 1,
|
||||
], $attributes));
|
||||
if ($children = data_get($item, 'children')) {
|
||||
$this->createCategory($children, $category->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Peidikeji\Goods\GoodsService;
|
||||
use Peidikeji\Goods\Models\Goods;
|
||||
use Peidikeji\Goods\Models\GoodsBrand;
|
||||
use Peidikeji\Goods\Models\GoodsSku;
|
||||
use Peidikeji\Goods\Models\GoodsType;
|
||||
use Peidikeji\Goods\Models\GoodsCategory;
|
||||
|
||||
class GoodsSeeder extends Seeder
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
DB::statement('SET FOREIGN_KEY_CHECKS = 0;');
|
||||
|
||||
$category_id = GoodsCategory::orderBy('level', 'desc')->value('id');
|
||||
if (!$category_id) {
|
||||
$this->call(GoodsCategorySeeder::class);
|
||||
$category_id = GoodsCategory::orderBy('level', 'desc')->value('id');
|
||||
}
|
||||
|
||||
GoodsType::truncate();
|
||||
$types = [
|
||||
[
|
||||
'name' => '手机',
|
||||
'attr' => [
|
||||
['name' => '主体', 'values' => ['入网型号', '上市年份', '品牌']],
|
||||
['name' => '显示器', 'values' => ['屏幕类型', '物理分辨率']],
|
||||
],
|
||||
'spec' => [
|
||||
['name' => '颜色', 'values' => ['白色', '红色', '黑色']],
|
||||
['name' => '内存', 'values' => ['32G', '64G', '128G']],
|
||||
],
|
||||
'part' => [
|
||||
['name' => '套餐', 'values' => ['套餐1', '套餐2', '套餐3']],
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => '笔记本电脑',
|
||||
'attr' => [
|
||||
['name' => '显示器', 'values' => ['屏幕类型', '物理分辨率']],
|
||||
],
|
||||
'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' => $category_id,
|
||||
'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' => '主体', 'values' => [
|
||||
['name' => '入网型号', 'value' => '5G'],
|
||||
['name' => '品牌', 'value' => '三星Galaxy'],
|
||||
['name' => '上市年份', 'value' => '2020'],
|
||||
]],
|
||||
],
|
||||
'spec' => [
|
||||
['name' => '颜色', 'values' => [
|
||||
['name' => '白色', 'value' => 0],
|
||||
['name' => '红色', 'value' => 800],
|
||||
['name' => '黑色', 'value' => 0],
|
||||
]],
|
||||
['name' => '内存', 'values' => [
|
||||
['name' => '32G', 'value' => 0],
|
||||
['name' => '64G', 'value' => 1000],
|
||||
['name' => '128G', 'value' => 2000],
|
||||
]],
|
||||
],
|
||||
'part' => [
|
||||
['name' => '套餐', 'values' => [
|
||||
['name' => '套餐1', 'value' => 850],
|
||||
['name' => '套餐2', 'value' => 1200],
|
||||
['name' => '套餐3', 'value' => 1800],
|
||||
]],
|
||||
],
|
||||
],
|
||||
[
|
||||
'category_id' => $category_id,
|
||||
'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' => '显示器', 'values' => [
|
||||
['name' => '屏幕类型', 'value' => 'LED 背光显示屏'],
|
||||
['name' => '物理分辨率', 'value' => '3072 x 1920 (226 ppi)'],
|
||||
]],
|
||||
],
|
||||
'spec' => [
|
||||
['name' => '颜色', 'values' => [
|
||||
['name' => '白色', 'value' => 0],
|
||||
['name' => '灰色', 'value' => 0],
|
||||
]],
|
||||
['name' => '内存', 'values' => [
|
||||
['name' => '16G', 'value' => 0],
|
||||
['name' => '32G', 'value' => 3000],
|
||||
['name' => '64G', 'value' => 6000],
|
||||
]],
|
||||
],
|
||||
'part' => [
|
||||
['name' => '套餐', 'values' => [
|
||||
['name' => '优惠套装1', 'value' => 850],
|
||||
['name' => '优惠套装2', 'value' => 650],
|
||||
['name' => '优惠套装3', 'value' => 1000],
|
||||
]],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$service = GoodsService::make();
|
||||
foreach ($goodsList as $item) {
|
||||
$goods = Goods::create($item);
|
||||
$service->generateSku($goods);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Peidikeji\Goods\Action\Check;
|
||||
|
||||
use Dcat\Admin\Grid\RowAction;
|
||||
use Dcat\Admin\Widgets\Modal;
|
||||
use Peidikeji\Goods\Form\Check\HandleCheckForm;
|
||||
|
||||
class RowHandleCheck extends RowAction
|
||||
{
|
||||
protected $title = '审核';
|
||||
|
||||
protected function html()
|
||||
{
|
||||
$form = HandleCheckForm::make()->payload(['id' => $this->row('id')]);
|
||||
|
||||
return Modal::make()->lg()->body($form)->title($this->title())->button($this->title);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Peidikeji\Goods\Action\Check;
|
||||
|
||||
use Dcat\Admin\Grid\RowAction;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Peidikeji\Goods\GoodsService;
|
||||
use Peidikeji\Goods\Models\Goods;
|
||||
|
||||
class RowSubmitCheck extends RowAction
|
||||
{
|
||||
protected $title = '提交审核';
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$goods = Goods::findOrFail($this->getKey());
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
GoodsService::make()->submitCheck($goods);
|
||||
DB::commit();
|
||||
|
||||
return $this->response()->success('操作成功')->refresh();
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
|
||||
return $this->response()->error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function confirm()
|
||||
{
|
||||
return ['是否确定?'];
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Peidikeji\Goods\Action\Goods;
|
||||
namespace Peidikeji\Goods\Action;
|
||||
|
||||
use Dcat\Admin\Grid\RowAction;
|
||||
use Peidikeji\Goods\Models\Goods;
|
||||
|
|
@ -2,15 +2,10 @@
|
|||
|
||||
namespace Peidikeji\Goods;
|
||||
|
||||
use App\Exceptions\BizException;
|
||||
use Dcat\Admin\Admin;
|
||||
use Dcat\Admin\Models\Administrator;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
use Peidikeji\Goods\Models\Goods;
|
||||
use Peidikeji\Goods\Models\GoodsCheck;
|
||||
use Peidikeji\Goods\Models\GoodsSku;
|
||||
use Peidikeji\Merchant\Enums\CheckStatus;
|
||||
|
||||
class GoodsService
|
||||
{
|
||||
|
|
@ -39,11 +34,6 @@ class GoodsService
|
|||
{
|
||||
$spec = data_get($options, 'spec', $goods->spec);
|
||||
$price = data_get($options, 'price', $goods->price);
|
||||
$vipPrice = data_get($options, 'vip_price', $goods->vip_price);
|
||||
|
||||
$weight = $goods->weight;
|
||||
$volume = $goods->volume;
|
||||
$shippingTmpId = data_get($options, 'shipping_tmp_id', $goods->shipping_tmp_id);
|
||||
|
||||
$name = data_get($options, 'name', $goods->name);
|
||||
$stock = data_get($options, 'stock', $goods->stock);
|
||||
|
|
@ -65,18 +55,13 @@ class GoodsService
|
|||
$cartesianList = Arr::crossJoin(...$specList);
|
||||
foreach ($cartesianList as $items) {
|
||||
$specPrice = $priceAdd ? $price + array_sum(array_column($items, 'price')) : $price;
|
||||
$specVipPrice = $priceAdd ? $vipPrice + array_sum(array_column($items, 'price')) : $vipPrice;
|
||||
$specName = $nameAdd ? $name.' '.implode(' ', array_column($items, 'value')) : $name;
|
||||
$exists = $goods->skus()->jsonArray($items)->exists();
|
||||
$attributes = [
|
||||
'name' => $specName,
|
||||
'price' => $specPrice,
|
||||
'vip_price' => $specVipPrice,
|
||||
'stock' => $stock,
|
||||
'spec' => $items,
|
||||
'weight' => $weight,
|
||||
'volume' => $volume,
|
||||
'shipping_tmp_id' => $shippingTmpId,
|
||||
];
|
||||
if ($exists) {
|
||||
$goods->skus()->jsonArray($items)->update($attributes);
|
||||
|
|
@ -87,60 +72,4 @@ class GoodsService
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 申请审核
|
||||
*
|
||||
* @param Goods $goods
|
||||
* @param Administrator $user
|
||||
* @return GoodsCheck
|
||||
*/
|
||||
public function submitCheck(Goods $goods, Administrator $user = null)
|
||||
{
|
||||
$goods->update([
|
||||
'check_status' => CheckStatus::Processing,
|
||||
]);
|
||||
|
||||
$attributes = Arr::except($goods->toArray(), ['check_status', 'check_remarks', 'check_at', 'check_user_id']);
|
||||
$attributes['check_status'] = CheckStatus::Processing;
|
||||
|
||||
$check = $goods->checkLogs()->create($attributes);
|
||||
|
||||
// 如果当前用户拥有审核权限, 则自动通过审核
|
||||
$user = $user ?: Admin::user();
|
||||
if ($user->can('dcat.admin.goods.check')) {
|
||||
$this->handleCheck($check, $user, true, '自动通过审核');
|
||||
}
|
||||
|
||||
return $check;
|
||||
}
|
||||
|
||||
/**
|
||||
* 审核商品
|
||||
*
|
||||
* @param GoodsCheck $check
|
||||
* @param Administrator $admin
|
||||
* @param bool $status true: 通过, false: 不通过
|
||||
* @param string $remarks 审核备注
|
||||
*/
|
||||
public function handleCheck(GoodsCheck $check, Administrator $admin, bool $status, string $remarks = null)
|
||||
{
|
||||
if ($check->check_status === CheckStatus::Success || $check->check_status === CheckStatus::Fail) {
|
||||
throw new BizException('已经审核过了');
|
||||
}
|
||||
$goods = $check->goods;
|
||||
if ($goods->check_status !== CheckStatus::Processing) {
|
||||
throw new BizException('商品未申请审核');
|
||||
}
|
||||
|
||||
$attributes = [
|
||||
'check_status' => $status ? CheckStatus::Success : CheckStatus::Fail,
|
||||
'check_at' => now(),
|
||||
'check_remarks' => $remarks,
|
||||
'check_user_id' => $admin->id,
|
||||
];
|
||||
$check->update($attributes);
|
||||
|
||||
$goods->update(array_merge($attributes, ['on_sale' => 1]));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ class GoodsServiceProvider extends ServiceProvider
|
|||
$this->loadRoutesFrom(__DIR__.'/../routes/admin.php');
|
||||
$this->loadRoutesFrom(__DIR__.'/../routes/api.php');
|
||||
|
||||
// $this->loadMigrationsFrom(__DIR__.'/../database/');
|
||||
$this->loadMigrationsFrom(__DIR__.'/../database/migrations');
|
||||
|
||||
$this->loadViewsFrom(__DIR__.'/../views', 'dcat-admin-goods');
|
||||
|
||||
|
|
@ -23,9 +23,9 @@ class GoodsServiceProvider extends ServiceProvider
|
|||
__DIR__.'/../assets' => public_path('vendor/dcat-admin-goods'),
|
||||
], 'dcat-admin-goods-assets');
|
||||
|
||||
$this->publishes([
|
||||
__DIR__.'/../database/' => database_path('migrations'),
|
||||
], 'dcat-admin-goods-migrations');
|
||||
// $this->publishes([
|
||||
// __DIR__.'/../database/migrations' => database_path('migrations'),
|
||||
// ], 'dcat-admin-goods-migrations');
|
||||
|
||||
$this->loadTranslationsFrom(__DIR__.'/../lang', 'dcat-admin-goods');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace Peidikeji\Goods\Http\Admin;
|
||||
|
||||
use App\Models\ShippingTmp;
|
||||
use Dcat\Admin\Admin;
|
||||
use Dcat\Admin\Form;
|
||||
use Dcat\Admin\Grid;
|
||||
|
|
@ -13,8 +12,7 @@ use Dcat\Admin\Layout\Content;
|
|||
use Dcat\Admin\Show;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Peidikeji\Goods\Action\Check\RowSubmitCheck;
|
||||
use Peidikeji\Goods\Action\Goods\RowGoodsSale;
|
||||
use Peidikeji\Goods\Action\RowGoodsSale;
|
||||
use Peidikeji\Goods\Form\Goods\AttrForm;
|
||||
use Peidikeji\Goods\Form\Goods\PartForm;
|
||||
use Peidikeji\Goods\Form\Goods\SpecForm;
|
||||
|
|
@ -24,9 +22,6 @@ use Peidikeji\Goods\Models\GoodsBrand;
|
|||
use Peidikeji\Goods\Models\GoodsCategory;
|
||||
use Peidikeji\Goods\Models\GoodsSku;
|
||||
use Peidikeji\Goods\Models\GoodsType;
|
||||
use Peidikeji\Merchant\Enums\CheckStatus;
|
||||
use Peidikeji\Merchant\Models\Merchant;
|
||||
use Peidikeji\Setting\Models\Setting;
|
||||
|
||||
class GoodsController extends AdminController
|
||||
{
|
||||
|
|
@ -94,7 +89,7 @@ class GoodsController extends AdminController
|
|||
|
||||
protected function grid()
|
||||
{
|
||||
return Grid::make(Goods::with(['category', 'brand', 'type', 'merchant', 'skus']), function (Grid $grid) {
|
||||
return Grid::make(Goods::with(['category', 'brand', 'type', 'skus']), function (Grid $grid) {
|
||||
$grid->model()->sort();
|
||||
|
||||
$grid->selector(function (Selector $selector) {
|
||||
|
|
@ -102,8 +97,6 @@ class GoodsController extends AdminController
|
|||
$types = GoodsType::get();
|
||||
$categories = GoodsCategory::where('level', 3)->where('path', 'like', '-1-%')->get();
|
||||
$prices = ['0-999', '1000-1999', '2000-4999', '5000+'];
|
||||
$merchants = Merchant::checked()->sort()->get();
|
||||
$selector->selectOne('merchant_id', __('dcat-admin-goods::goods.fields.merchant_id'), $merchants->pluck('name', 'id'));
|
||||
$selector->selectOne('category_id', __('dcat-admin-goods::goods.fields.category_id'), $categories->pluck('name', 'id'));
|
||||
$selector->selectOne('brand_id', __('dcat-admin-goods::goods.fields.brand_id'), $brands->pluck('name', 'id'));
|
||||
$selector->selectOne('type_id', __('dcat-admin-goods::goods.fields.type_id'), $types->pluck('name', 'id'));
|
||||
|
|
@ -121,7 +114,6 @@ class GoodsController extends AdminController
|
|||
});
|
||||
});
|
||||
|
||||
$grid->column('merchant.name');
|
||||
$grid->column('goods_sn');
|
||||
$grid->column('category.name');
|
||||
$grid->column('brand.name');
|
||||
|
|
@ -132,7 +124,6 @@ class GoodsController extends AdminController
|
|||
).'">'.$this->name.'</a>';
|
||||
});
|
||||
$grid->column('price');
|
||||
$grid->column('vip_price');
|
||||
$grid->column('stock')
|
||||
->if(fn () => $this->skus->count() > 0)
|
||||
->display(fn () => $this->skus->sum('stock'))
|
||||
|
|
@ -140,7 +131,6 @@ class GoodsController extends AdminController
|
|||
->editable();
|
||||
$grid->column('on_sale')->bool();
|
||||
$grid->column('is_recommend')->switch();
|
||||
$grid->column('check_status')->display(fn () => $this->check_status->dot());
|
||||
$grid->column('sold_count');
|
||||
|
||||
$grid->disableRowSelector();
|
||||
|
|
@ -155,7 +145,7 @@ class GoodsController extends AdminController
|
|||
|
||||
$actions->view($user->can('dcat.admin.goods.show'));
|
||||
|
||||
if ($user->can('dcat.admin.goods.edit') && ! $row->on_sale && $row->check_status !== CheckStatus::Processing) {
|
||||
if ($user->can('dcat.admin.goods.edit') && ! $row->on_sale) {
|
||||
$actions->edit();
|
||||
$actions->append('<a href="'.admin_route('goods.attr', ['goods' => $row->id]).'" class="">属性介绍</a>');
|
||||
$actions->append('<a href="'.admin_route('goods.spec', ['goods' => $row->id]).'" class="">商品规格</a>');
|
||||
|
|
@ -166,15 +156,11 @@ class GoodsController extends AdminController
|
|||
$actions->append('<a href="'.admin_route('goods_sku.index', ['goods' => $row->id]).'" class="">货品列表</a>');
|
||||
}
|
||||
|
||||
if ($user->can('dcat.admin.goods.edit') && $row->check_status === CheckStatus::Success) {
|
||||
if ($user->can('dcat.admin.goods.edit')) {
|
||||
$actions->append(new RowGoodsSale());
|
||||
}
|
||||
|
||||
$actions->delete($user->can('dcat.admin.goods.destroy') && ! $row->on_sale);
|
||||
|
||||
if (! $row->on_sale && $row->check_status !== CheckStatus::Success && $row->check_status !== CheckStatus::Processing) {
|
||||
$actions->append(new RowSubmitCheck());
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -184,17 +170,14 @@ class GoodsController extends AdminController
|
|||
Admin::css([
|
||||
'vendor/dcat-admin-goods/goods.css',
|
||||
]);
|
||||
$info = Goods::with(['category', 'merchant', 'brand', 'type', 'checkUser'])->findOrFail($id);
|
||||
$info = Goods::with(['category', 'brand', 'type'])->findOrFail($id);
|
||||
$show = Show::make($info);
|
||||
$show->field('merchant.name');
|
||||
$show->field('goods_sn');
|
||||
$show->field('category.name');
|
||||
$show->field('brand.name');
|
||||
$show->field('type.name');
|
||||
$show->field('name');
|
||||
$show->field('price');
|
||||
$show->field('vip_price');
|
||||
$show->field('score_max_amount');
|
||||
$show->field('cover_image')->image('', 100);
|
||||
$show->field('images')->image('', 100);
|
||||
$show->field('content')->image('');
|
||||
|
|
@ -204,30 +187,25 @@ class GoodsController extends AdminController
|
|||
$show->field('on_sale')->bool();
|
||||
$show->field('is_recommend')->bool();
|
||||
$show->field('sold_count');
|
||||
$show->field('check_status')->unescape()->as(fn () => $this->check_status->label());
|
||||
$show->field('check_at');
|
||||
$show->field('check_remarks');
|
||||
$show->field('check_user.name');
|
||||
$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'));
|
||||
$show->field('created_at');
|
||||
$show->field('updated_at');
|
||||
|
||||
return $show;
|
||||
}
|
||||
|
||||
protected function form()
|
||||
{
|
||||
return Form::make(Goods::with(['merchant']), function (Form $form) {
|
||||
return Form::make(Goods::with([]), function (Form $form) {
|
||||
$model = $form->model();
|
||||
$isCreating = $form->isCreating();
|
||||
$unique = Rule::unique('goods', 'goods_sn');
|
||||
|
||||
if ($isCreating) {
|
||||
// $form->select('type_id')->options(GoodsType::pluck('name', 'id'));
|
||||
$form->select('type_id')->options(GoodsType::pluck('name', 'id'));
|
||||
$form->select('merchant_id')->ajax('api/merchants?_paginate=1');
|
||||
} else {
|
||||
// $type = $model->type_id ? GoodsType::find($model->type_id) : null;
|
||||
// $form->display('type_id')->with(fn () => $model->type_id ? $type->name : '');
|
||||
$form->display('merchant.name', __('dcat-admin-goods::goods.fields.merchant_id'));
|
||||
$type = $model->type_id ? GoodsType::find($model->type_id) : null;
|
||||
$form->display('type_id')->with(fn () => $model->type_id ? $type->name : '');
|
||||
$unique->ignore($model->id);
|
||||
}
|
||||
$form->select('category_id')->options(GoodsCategory::selectOptions(null, false))->required();
|
||||
|
|
@ -253,14 +231,6 @@ class GoodsController extends AdminController
|
|||
if ($isCreating || !$model->spec) {
|
||||
$form->number('price')->min(0)->attribute('step', 0.01);
|
||||
$form->number('vip_price')->min(0)->attribute('step', 0.01);
|
||||
|
||||
$discountRatio = Setting::where('slug', 'discount_profit_ratio')->value('value');
|
||||
$form->number('score_max_amount')->min(0)->help('购买商品时, 允许使用多少积分, 积分抵扣比例: 1 积分 = '.$discountRatio.' 元');
|
||||
|
||||
$form->currency('weight')->default(0)->symbol('克');
|
||||
$form->currency('volume')->default(0)->symbol('立方');
|
||||
|
||||
$form->select('shipping_tmp_id')->options(ShippingTmp::all()->pluck('name', 'id'))->help('运费模板,不选择默认免邮');
|
||||
} else {
|
||||
$form->display('help', '提示')->value('商品其他信息, 请到 <a href="'.admin_route('goods_sku.index', ['goods' => $model->id]).'" target="_blank">货品列表<a/> 去修改');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,8 @@
|
|||
|
||||
namespace Peidikeji\Goods\Http\Admin;
|
||||
|
||||
use App\Models\ShippingTmp;
|
||||
use Dcat\Admin\Admin;
|
||||
use Dcat\Admin\Form;
|
||||
use Dcat\Admin\Form\EmbeddedForm;
|
||||
use Dcat\Admin\Grid;
|
||||
use Dcat\Admin\Grid\Tools\Selector;
|
||||
use Dcat\Admin\Layout\Content;
|
||||
|
|
@ -16,7 +14,6 @@ use Illuminate\Validation\Rule;
|
|||
use Peidikeji\Goods\GoodsService;
|
||||
use Peidikeji\Goods\Models\Goods;
|
||||
use Peidikeji\Goods\Models\GoodsSku;
|
||||
use Peidikeji\Setting\Models\Setting;
|
||||
|
||||
class GoodsSkuController extends Controller
|
||||
{
|
||||
|
|
@ -46,7 +43,6 @@ class GoodsSkuController extends Controller
|
|||
$grid->column('id');
|
||||
$grid->column('sn');
|
||||
$grid->column('name');
|
||||
// $grid->column('reset')->display(fn() => $goods->price);
|
||||
$grid->column('price');
|
||||
$grid->column('stock');
|
||||
if ($goods->spec) {
|
||||
|
|
@ -77,15 +73,17 @@ class GoodsSkuController extends Controller
|
|||
|
||||
public function show($goods, $id, Content $content)
|
||||
{
|
||||
Admin::css([
|
||||
'vendor/dcat-admin-goods/goods.css',
|
||||
]);
|
||||
$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('vip_price');
|
||||
$show->field('stock');
|
||||
$show->field('spec')->view('dcat-admin-goods::grid.spec');
|
||||
$show->field('spec')->view('dcat-admin-goods::goods.grid-spec');
|
||||
});
|
||||
|
||||
return $content
|
||||
|
|
@ -102,13 +100,6 @@ class GoodsSkuController extends Controller
|
|||
$form->text('sn')->rules([$unqiue], ['unique' => '货号已经存在'])->required();
|
||||
$form->text('name')->default($goods->name);
|
||||
$form->number('price')->min(0)->attribute('step', 0.01)->default($goods->price);
|
||||
$form->number('vip_price')->min(0)->attribute('step', 0.01)->default($goods->vip_price);
|
||||
$discountRatio = Setting::where('slug', 'discount_profit_ratio')->value('value');
|
||||
$form->number('score_max_amount')->min(0)->help('购买商品时, 允许使用多少积分, 积分抵扣比例: 1 积分 = '.$discountRatio.' 元');
|
||||
|
||||
$form->currency('weight')->default(0)->symbol('克')->saving(fn ($v) => ! empty($v) ?? null);
|
||||
$form->currency('volume')->default(0)->symbol('立方')->saving(fn ($v) => ! empty($v) ?? null);
|
||||
$form->select('shipping_tmp_id')->options(ShippingTmp::all()->pluck('name', 'id'))->help('运费模板,不选择默认免邮');
|
||||
|
||||
$form->number('stock')->min(0)->default($goods->stock);
|
||||
$form->hidden('spec')->customFormat(fn ($v) => json_encode($v));
|
||||
|
|
@ -187,11 +178,6 @@ class GoodsSkuController extends Controller
|
|||
$form->checkbox('price_append', '')->options([1 => '是否在价格上面追加属性的加价'])->default([1]);
|
||||
}
|
||||
|
||||
$discountRatio = Setting::where('slug', 'discount_profit_ratio')->value('value');
|
||||
$form->number('score_max_amount')->min(0)->help('购买商品时, 允许使用多少积分, 积分抵扣比例: 1 积分 = '.$discountRatio.' 元');
|
||||
|
||||
$form->select('shipping_tmp_id')->default($goods->shipping_tmp_id ?? 0)->options(ShippingTmp::all()->pluck('name', 'id'))->help('运费模板,不选择默认免邮');
|
||||
|
||||
$form->number('stock')->min(0)->default($goods->stock);
|
||||
|
||||
if ($goods->spec) {
|
||||
|
|
@ -252,7 +238,6 @@ class GoodsSkuController extends Controller
|
|||
'name_add' => (bool) data_get($form->name_append, 0),
|
||||
'price_add' => (bool) data_get($form->price_append, 0),
|
||||
'stock' => $form->stock,
|
||||
'shipping_tmp_id' => $form->shipping_tmp_id ?? null,
|
||||
]);
|
||||
|
||||
return $form->response()->success('添加成功')->redirect(admin_route('goods_sku.index', ['goods' => $goods->id]));
|
||||
|
|
|
|||
|
|
@ -8,8 +8,6 @@ use EloquentFilter\Filterable;
|
|||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Str;
|
||||
use Peidikeji\Goods\Filters\GoodsFilter;
|
||||
use Peidikeji\Merchant\Enums\CheckStatus;
|
||||
use Peidikeji\Merchant\Models\Merchant;
|
||||
|
||||
class Goods extends Model
|
||||
{
|
||||
|
|
@ -18,12 +16,10 @@ class Goods extends Model
|
|||
protected $table = 'goods';
|
||||
|
||||
protected $fillable = [
|
||||
'merchant_id', 'category_id', 'type_id', 'brand_id',
|
||||
'category_id', 'type_id', 'brand_id',
|
||||
'goods_sn', 'name', 'cover_image', 'description', 'content',
|
||||
'price', 'vip_price', 'score_max_amount', 'on_sale', 'is_recommend', 'sold_count', 'stock',
|
||||
'weight', 'volume', 'shipping_tmp_id',
|
||||
'price', 'on_sale', 'is_recommend', 'sold_count', 'stock',
|
||||
'attr', 'part', 'spec',
|
||||
'check_user_id', 'check_at', 'check_remarks', 'check_status',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
|
|
@ -32,7 +28,6 @@ class Goods extends Model
|
|||
'part' => 'array',
|
||||
'content' => 'array',
|
||||
'images' => 'array',
|
||||
'check_status' => CheckStatus::class,
|
||||
];
|
||||
|
||||
protected $dates = ['check_at'];
|
||||
|
|
@ -44,14 +39,6 @@ class Goods extends Model
|
|||
$model->goods_sn = Str::uuid();
|
||||
}
|
||||
});
|
||||
static::updating(function (Goods $model) {
|
||||
if ($model->isDirty(['merchant_id', 'category_id', 'brand_id', 'goods_sn', 'name', 'cover_image', 'description', 'content', 'price', 'vip_price']) && $model->check_status === CheckStatus::Success) {
|
||||
$model->check_status = CheckStatus::None;
|
||||
$model->check_at = null;
|
||||
$model->check_user_id = null;
|
||||
$model->check_remarks = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function modelFilter()
|
||||
|
|
@ -64,11 +51,6 @@ class Goods extends Model
|
|||
return $this->belongsTo(GoodsCategory::class, 'category_id');
|
||||
}
|
||||
|
||||
public function merchant()
|
||||
{
|
||||
return $this->belongsTo(Merchant::class, 'merchant_id');
|
||||
}
|
||||
|
||||
public function type()
|
||||
{
|
||||
return $this->belongsTo(GoodsType::class, 'type_id');
|
||||
|
|
@ -79,21 +61,11 @@ class Goods extends Model
|
|||
return $this->belongsTo(GoodsBrand::class, 'brand_id');
|
||||
}
|
||||
|
||||
public function checkUser()
|
||||
{
|
||||
return $this->belongsTo(Administrator::class, 'check_user_id');
|
||||
}
|
||||
|
||||
public function skus()
|
||||
{
|
||||
return $this->hasMany(GoodsSku::class, 'goods_id');
|
||||
}
|
||||
|
||||
public function checkLogs()
|
||||
{
|
||||
return $this->hasMany(GoodsCheck::class, 'goods_id');
|
||||
}
|
||||
|
||||
public function scopeSort($q)
|
||||
{
|
||||
return $q->orderBy('created_at', 'desc');
|
||||
|
|
@ -101,6 +73,6 @@ class Goods extends Model
|
|||
|
||||
public function scopeShow($q)
|
||||
{
|
||||
return $q->where('on_sale', 1)->where('check_status', CheckStatus::Success);
|
||||
return $q->where('on_sale', 1);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
<!-- $model 当前行数据 -->
|
||||
<!-- $name 字段名称 -->
|
||||
<!-- $value 为当前列的值 -->
|
||||
@if($value)
|
||||
<div class="grid-attr">
|
||||
@foreach($value as $item)
|
||||
<div class="group">
|
||||
<span class="label bg-info">{{ $item['name'] }}</span>
|
||||
<span class="text-danger">{{ $item['value'] }}</span>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
Loading…
Reference in New Issue