Compare commits
2 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
478dbe1531 | |
|
|
77a017298a |
|
|
@ -35,7 +35,7 @@ class Components extends BaseRenderer {
|
|||
* 2位小数输入框
|
||||
*/
|
||||
public function decimalControl($name ='decimal', $label = null){
|
||||
return amisMake()->NumberControl()
|
||||
return amisMake()->NumberControl()->size('sm')
|
||||
->name($name)->label($label ?? __('admin.components.decimal'))
|
||||
->kilobitSeparator(true)
|
||||
->percision(2)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ namespace App\Admin\Controllers;
|
|||
|
||||
use Slowlyo\OwlAdmin\Renderers\Page;
|
||||
use Slowlyo\OwlAdmin\Renderers\Form;
|
||||
use Slowlyo\OwlAdmin\Renderers\TableColumn;
|
||||
use Slowlyo\OwlAdmin\Renderers\TextControl;
|
||||
use Slowlyo\OwlAdmin\Controllers\AdminController;
|
||||
use App\Services\Admin\KeywordService;
|
||||
|
|
@ -23,7 +22,7 @@ class KeywordController extends AdminController
|
|||
->footerToolbar([])
|
||||
//去掉分页-end
|
||||
->headerToolbar([
|
||||
$this->createButton(true),
|
||||
$this->createButton(true, 'md'),
|
||||
amis('reload')->align('right'),
|
||||
amis('filter-toggler')->align('right'),
|
||||
])
|
||||
|
|
@ -38,13 +37,13 @@ class KeywordController extends AdminController
|
|||
))
|
||||
->columns([
|
||||
// TableColumn::make()->name('id')->label('ID')->sortable(true),
|
||||
TableColumn::make()->name('name')->label('名称'),
|
||||
TableColumn::make()->name('key')->label('KEY')->copyable(true),
|
||||
TableColumn::make()->name('value')->label('值'),
|
||||
TableColumn::make()->name('sort')->label('排序'),
|
||||
TableColumn::make()->name('created_at')->label('创建时间')->type('datetime')->sortable(true),
|
||||
amis()->TableColumn('name', __('admin.keywords.name')),
|
||||
amis()->TableColumn('key', __('admin.keywords.key'))->copyable(true),
|
||||
amis()->TableColumn('value', __('admin.keywords.value')),
|
||||
amis()->TableColumn('sort', __('admin.keywords.sort')),
|
||||
amis()->TableColumn('created_at', __('admin.created_at'))->type('datetime')->sortable(true),
|
||||
amisMake()->Operation()->label(__('admin.actions'))->buttons([
|
||||
$this->rowEditButton(true),
|
||||
$this->rowEditButton(true, 'md'),
|
||||
$this->rowDeleteButton(),
|
||||
]),
|
||||
]);
|
||||
|
|
@ -56,10 +55,10 @@ class KeywordController extends AdminController
|
|||
{
|
||||
return $this->baseForm()->body([
|
||||
Components::make()->parentControl(admin_url('api/keywords/tree-list')),
|
||||
TextControl::make()->name('name')->label('名称')->required(true),
|
||||
TextControl::make()->name('key')->label('KEY')->required(true),
|
||||
TextControl::make()->name('value')->label('值'),
|
||||
amisMake()->NumberControl()->name('sort')->value(0)->min()->label('排序'),
|
||||
amis()->TextControl('name', __('admin.keywords.name'))->required(true),
|
||||
amis()->TextControl('key', __('admin.keywords.key'))->required(true),
|
||||
amis()->TextControl('value', __('admin.keywords.value')),
|
||||
Components::make()->sortControl('sort', __('admin.keywords.sort')),
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
|
||||
namespace App\Admin\Controllers;
|
||||
|
||||
use Slowlyo\OwlAdmin\Renderers\Page;
|
||||
use Slowlyo\OwlAdmin\Renderers\Form;
|
||||
use Slowlyo\OwlAdmin\Controllers\AdminController;
|
||||
use App\Services\Admin\ProductCategoryService;
|
||||
use App\Admin\Components;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ProductCategoryController extends AdminController
|
||||
{
|
||||
protected string $serviceName = ProductCategoryService::class;
|
||||
|
||||
public function list(): Page
|
||||
{
|
||||
$crud = $this->baseCRUD()
|
||||
//去掉分页-start
|
||||
->loadDataOnce(true)
|
||||
->footerToolbar([])
|
||||
//去掉分页-end
|
||||
->headerToolbar([
|
||||
$this->createButton(true, 'md'),
|
||||
amis('reload')->align('right'),
|
||||
amis('filter-toggler')->align('right'),
|
||||
])
|
||||
->filter($this->baseFilter()->body([
|
||||
|
||||
]
|
||||
))
|
||||
->columns([
|
||||
amis()->TableColumn()->make()->name('id')->label('ID')->sortable(true),
|
||||
amis()->TableColumn('name', __('admin.product_categories.name')),
|
||||
amis()->TableColumn('key', __('admin.product_categories.key'))->copyable(true),
|
||||
amis()->TableColumn('cover', __('admin.product_categories.cover'))->type('image')->height('50px')->width('150px')->enlargeAble(true),
|
||||
amis()->TableColumn('is_enable', __('admin.product_categories.is_enable'))->type('switch'),
|
||||
amis()->TableColumn('is_show', __('admin.product_categories.is_show'))->type('switch'),
|
||||
amis()->TableColumn('is_recommend', __('admin.product_categories.is_recommend'))->type('switch'),
|
||||
amis()->TableColumn('created_at', __('admin.created_at'))->type('datetime')->sortable(true),
|
||||
amisMake()->Operation()->label(__('admin.actions'))->buttons([
|
||||
$this->rowEditButton(true, 'md'),
|
||||
$this->rowDeleteButton(),
|
||||
]),
|
||||
]);
|
||||
|
||||
return $this->baseList($crud);
|
||||
}
|
||||
|
||||
public function form(): Form
|
||||
{
|
||||
return $this->baseForm()->body([
|
||||
Components::make()->parentControl(admin_url('api/product_categories/tree-list')),
|
||||
amis()->TextControl('name', __('admin.product_categories.name'))->required(true),
|
||||
amis()->TextControl('key', __('admin.product_categories.key'))->required(true),
|
||||
Components::make()->cropImageControl('cover', __('admin.product_categories.cover')),
|
||||
Components::make()->sortControl('sort', __('admin.product_categories.sort')),
|
||||
amis()->SwitchControl('is_enable', __('admin.product_categories.is_enable'))->value(false),
|
||||
amis()->SwitchControl('is_show', __('admin.product_categories.is_show'))->value(false),
|
||||
amis()->SwitchControl('is_recommend', __('admin.product_categories.is_recommend'))->value(false),
|
||||
]);
|
||||
}
|
||||
|
||||
public function getTreeList(Request $request){
|
||||
return $this->service->getTree();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
<?php
|
||||
|
||||
namespace App\Admin\Controllers;
|
||||
|
||||
use Slowlyo\OwlAdmin\Admin;
|
||||
use Slowlyo\OwlAdmin\Renderers\Page;
|
||||
use Slowlyo\OwlAdmin\Renderers\Form;
|
||||
use Slowlyo\OwlAdmin\Controllers\AdminController;
|
||||
use App\Services\Admin\ProductService;
|
||||
use App\Admin\Components;
|
||||
use App\Models\Keyword;
|
||||
|
||||
class ProductController extends AdminController
|
||||
{
|
||||
protected string $serviceName = ProductService::class;
|
||||
|
||||
public function list():Page
|
||||
{
|
||||
$crud = $this->baseCRUD()->tableLayout('fixed')
|
||||
->headerToolbar([
|
||||
$this->createButton(),
|
||||
...$this->baseHeaderToolBar(),
|
||||
])
|
||||
->filter($this->baseFilter()->body([
|
||||
amis()->GroupControl()->mode('horizontal')->body([
|
||||
amis()->TextControl('sku', __('admin.products.sku'))
|
||||
->placeholder(__('admin.products.sku')),
|
||||
amis()->TextControl('name', __('admin.products.name'))
|
||||
->placeholder(__('admin.products.name')),
|
||||
]),
|
||||
]))
|
||||
->columns([
|
||||
amis()->TableColumn('name', __('admin.products.name'))->width('300px'),
|
||||
amis()->TableColumn('sku', __('admin.sku'))->sortable(true),
|
||||
amis()->TableColumn('category.name', __('admin.products.category')),
|
||||
amis()->TableColumn('cover', __('admin.products.cover'))->type('image')->height('50px')->width('50px')->enlargeAble(true),
|
||||
amis()->TableColumn('is_sale', __('admin.products.is_sale'))->type('switch'),
|
||||
amis()->TableColumn('is_recommend', __('admin.products.is_recommend'))->type('switch'),
|
||||
amis()->Operation()->label(__('admin.actions'))->buttons([
|
||||
$this->rowEditButton(),
|
||||
$this->rowDeleteButton(),
|
||||
])
|
||||
]);
|
||||
|
||||
return $this->baseList($crud);
|
||||
}
|
||||
|
||||
public function form(): Form
|
||||
{
|
||||
return $this->baseForm()->panelClassName('px-0')->body([
|
||||
amis()->Tabs()->tabsMode('line')->tabs([
|
||||
//基础信息
|
||||
amis()->Tab()->title(__('admin.products.tab1'))->body([
|
||||
amis()->Grid()->columns([
|
||||
amis()->Wrapper()->body([
|
||||
amis()->TextControl('name', __('admin.products.name'))->required(true),
|
||||
Components::make()->parentControl(admin_url('api/product_categories/tree-list'), 'category_id', __('admin.products.category')),
|
||||
|
||||
amis()->TextControl('spu', __('admin.products.spu'))->description('*未填写则自动生成唯一spu'),
|
||||
amis()->TextareaControl('sub_title', __('admin.products.sub_title'))->minRows(5),
|
||||
|
||||
Components::make()->sortControl('virtual_sales', __('admin.products.virtual_sales')),
|
||||
Components::make()->sortControl('stocks', __('admin.products.stocks'))->description('*已销售过的商品无法直接编辑库存,需前往商品库存中操作。'),
|
||||
|
||||
Components::make()->decimalControl('price', __('admin.products.price')),
|
||||
|
||||
amis()->SwitchControl('is_sale', __('admin.products.is_sale'))->value(false),
|
||||
amis()->SwitchControl('is_show', __('admin.products.is_show'))->value(false),
|
||||
|
||||
])->md(4),
|
||||
amis()->Wrapper()->body([
|
||||
Components::make()->imageControl('photos', __('admin.products.photos'))->multiple(true)->draggable(true)->required(true),
|
||||
Components::make()->cropImageControl('cover', __('admin.products.cover'))->description('*若不选择上传,则默认为相册第一张'),
|
||||
|
||||
Components::make()->sortControl('sort', __('admin.products.sort')),
|
||||
|
||||
amis()->SwitchControl('is_recommend', __('admin.products.is_recommend'))->value(false),
|
||||
amis()->SwitchControl('is_hot', __('admin.products.is_hot'))->value(false),
|
||||
amis()->SwitchControl('is_new', __('admin.products.is_new'))->value(false),
|
||||
|
||||
])->md(8)
|
||||
]),
|
||||
]),
|
||||
//详情,信息
|
||||
amis()->Tab()->title(__('admin.products.tab2'))->body([
|
||||
//详情,基础信息,运费模板,属性标签,
|
||||
amis()->Grid()->columns([
|
||||
amis()->Wrapper()->body([
|
||||
Components::make()->keywordsTagControl('t_ids', __('admin.products.tags'), 'product_tag'),
|
||||
amis()->SelectControl('shipping_tmp_id', __('admin.products.shipping_tmp_id'))->required(true),
|
||||
amis()->InputKV()->name('base_info')->label('参数信息')->keyPlaceholder('属性')->valuePlaceholder('值'),
|
||||
])->md(4),
|
||||
amis()->Wrapper()->body([
|
||||
Components::make()->fuEditorControl('description', __('admin.products.description')),
|
||||
])->md(8),
|
||||
]),
|
||||
]),
|
||||
//多属性商品
|
||||
amis()->Tab()->title(__('admin.products.tab3'))->body([
|
||||
|
||||
])
|
||||
])
|
||||
]);
|
||||
}
|
||||
|
||||
public function detail(): Form
|
||||
{
|
||||
return $this->baseDetail()->body([]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -13,6 +13,8 @@ Route::group([
|
|||
'prefix' => 'api',
|
||||
], function (Router $router) {
|
||||
$router->get('keywords/tree-list', '\App\Admin\Controllers\KeywordController@getTreeList')->name('api.keywords.tree-list');
|
||||
|
||||
$router->get('product_categories/tree-list', '\App\Admin\Controllers\ProductCategoryController@getTreeList')->name('api.product_categories.tree-list');
|
||||
});
|
||||
|
||||
$router->resource('index', \App\Admin\Controllers\HomeController::class);
|
||||
|
|
@ -32,6 +34,10 @@ Route::group([
|
|||
|
||||
$router->resource('ads', \App\Admin\Controllers\AdController::class);
|
||||
|
||||
$router->resource('product_categories', \App\Admin\Controllers\ProductCategoryController::class);
|
||||
|
||||
$router->resource('products', \App\Admin\Controllers\ProductController::class);
|
||||
|
||||
//修改上传
|
||||
$router->post('upload_file', [\App\Admin\Controllers\IndexController::class, 'uploadFile']);
|
||||
$router->post('upload_image', [\App\Admin\Controllers\IndexController::class, 'uploadImage']);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models\Filters;
|
||||
|
||||
use EloquentFilter\ModelFilter;
|
||||
use App\Models\ProductCategory;
|
||||
|
||||
class ProductCategoryFilter extends ModelFilter
|
||||
{
|
||||
/**
|
||||
* 关键字
|
||||
*/
|
||||
public function name($name)
|
||||
{
|
||||
return $this->where('name','like', '%'.$name.'%')
|
||||
->orWhere('key','like', '%'.$name.'%');
|
||||
}
|
||||
|
||||
public function parentName($parent_name)
|
||||
{
|
||||
if(request('has_owner', 1)){
|
||||
$this->where(function($q) use ($parent_name){
|
||||
$q->where('name','like', '%'.$parent_name.'%')
|
||||
->orWhere('key','like', '%'.$parent_name.'%');
|
||||
});
|
||||
}
|
||||
return $this->orWhere('path','like', '%-'.
|
||||
ProductCategory::where('name','like', '%'.$parent_name.'%')->orWhere('key','like', '%'.$parent_name.'%')->value('id')
|
||||
. '-%' ?? '');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models\Filters;
|
||||
|
||||
use EloquentFilter\ModelFilter;
|
||||
|
||||
class ProductFilter extends ModelFilter
|
||||
{
|
||||
/**
|
||||
* 关键字
|
||||
*/
|
||||
public function name($name)
|
||||
{
|
||||
return $this->where('name','like', '%'.$name.'%');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use EloquentFilter\Filterable;
|
||||
|
||||
class Product extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use Filterable;
|
||||
|
||||
protected function serializeDate(\DateTimeInterface $date)
|
||||
{
|
||||
return $date->format('Y-m-d H:i:s');
|
||||
}
|
||||
|
||||
protected $fillable = [
|
||||
'name', 'sub_title', 'cover', 'photos', 'base_info', 'description',
|
||||
'spu', 'sku', 'parent_id', 'category_id', 't_ids',
|
||||
];
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use EloquentFilter\Filterable;
|
||||
|
||||
class ProductCategory extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use Filterable;
|
||||
|
||||
protected function serializeDate(\DateTimeInterface $date)
|
||||
{
|
||||
return $date->format('Y-m-d H:i:s');
|
||||
}
|
||||
|
||||
protected $fillable = [
|
||||
'name', 'key', 'cover',
|
||||
'parent_id', 'parent_key', 'lv', 'path',
|
||||
'is_enable', 'is_show', 'is_recommend',
|
||||
'sort',
|
||||
];
|
||||
|
||||
protected static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
// 监听 Keyword 的创建事件,用于初始化 path 和 lv 字段值
|
||||
static::saving(function ($keyword) {
|
||||
// 如果创建的是一个根类目
|
||||
if (! $keyword->parent_id) {
|
||||
// 将层级设为 1
|
||||
$keyword->lv = 1;
|
||||
// 将 path 设为 -
|
||||
$keyword->path = '-';
|
||||
} else {
|
||||
// 将层级设为父类目的层级 + 1
|
||||
$keyword->lv = $keyword->parent->lv ++;
|
||||
$keyword->parent_key = $keyword->parent->key;
|
||||
// 将 path 值设为父类目的 path 追加父类目 ID 以及最后跟上一个 - 分隔符
|
||||
$keyword->path = $keyword->parent->path.$keyword->parent_id.'-';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function parent()
|
||||
{
|
||||
return $this->belongsTo(static::class, 'parent_id');
|
||||
}
|
||||
|
||||
public function children()
|
||||
{
|
||||
return $this->hasMany(static::class, 'parent_id');
|
||||
}
|
||||
}
|
||||
|
|
@ -74,7 +74,7 @@ class KeywordService extends BaseService
|
|||
$pid = Arr::get($data, 'parent_id');
|
||||
if ($pid != 0) {
|
||||
if ($this->parentIsChild($primaryKey, $pid)) {
|
||||
$this->setError('父级不允许设置为当前子权限');
|
||||
$this->setError('父级不允许设置为当前子级');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,125 @@
|
|||
<?php
|
||||
|
||||
namespace App\Services\Admin;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use App\Models\ProductCategory;
|
||||
use App\Models\Filters\ProductCategoryFilter;
|
||||
use App\Traits\UploadTrait;
|
||||
|
||||
/**
|
||||
* @method ProductCategory getModel()
|
||||
* @method ProductCategory|\Illuminate\Database\Query\Builder query()
|
||||
*/
|
||||
class ProductCategoryService extends BaseService
|
||||
{
|
||||
protected string $modelName = ProductCategory::class;
|
||||
protected string $modelFilterName = ProductCategoryFilter::class;
|
||||
|
||||
use UploadTrait;
|
||||
|
||||
public function getTree()
|
||||
{
|
||||
$list = $this->query()->filter(request()->all(), $this->modelFilterName)->orderByDesc('sort')->get();
|
||||
$minNum = $list->min('parent_id');
|
||||
return !$list->isEmpty() ? array2tree($list->toArray(), $minNum) :[];
|
||||
}
|
||||
|
||||
public function parentIsChild($id, $pid): bool
|
||||
{
|
||||
$parent = $this->query()->find($pid);
|
||||
|
||||
do {
|
||||
if ($parent->parent_id == $id) {
|
||||
return true;
|
||||
}
|
||||
// 如果没有parent 则为顶级 退出循环
|
||||
$parent = $parent->parent;
|
||||
} while ($parent);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function list()
|
||||
{
|
||||
return ['items' => $this->getTree()];
|
||||
}
|
||||
|
||||
public function store($data): bool
|
||||
{
|
||||
if ($this->hasRepeated($data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$columns = $this->getTableColumns();
|
||||
|
||||
$model = $this->getModel();
|
||||
|
||||
$data['cover'] = $this->saveImage('cover', 'product_category/cover')[0] ?? '';
|
||||
foreach ($data as $k => $v) {
|
||||
if (!in_array($k, $columns)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$model->setAttribute($k, $v);
|
||||
}
|
||||
|
||||
return $model->save();
|
||||
}
|
||||
|
||||
public function update($primaryKey, $data): bool
|
||||
{
|
||||
if ($this->hasRepeated($data, $primaryKey)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$columns = $this->getTableColumns();
|
||||
|
||||
$pid = Arr::get($data, 'parent_id');
|
||||
if ($pid != 0) {
|
||||
if ($this->parentIsChild($primaryKey, $pid)) {
|
||||
$this->setError('父级不允许设置为当前子级');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$model = $this->query()->whereKey($primaryKey)->first();
|
||||
|
||||
if(isset($data['cover'])){
|
||||
$data['cover'] = $this->saveImage('cover', 'articles/cover')[0] ?? '';
|
||||
}
|
||||
foreach ($data as $k => $v) {
|
||||
if (!in_array($k, $columns)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$model->setAttribute($k, $v);
|
||||
}
|
||||
|
||||
return $model->save();
|
||||
}
|
||||
|
||||
|
||||
public function hasRepeated($data, $id = 0): bool
|
||||
{
|
||||
$query = $this->query()->when($id, fn($query) => $query->where('id', '<>', $id));
|
||||
|
||||
if (isset($data['key']) && (clone $query)->where('key', $data['key'])->exists()) {
|
||||
$this->setError('KEY重复');
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public function delete(string $ids): mixed
|
||||
{
|
||||
$ids = explode(',', $ids);
|
||||
if(count($ids) == 1){
|
||||
$this->query()->where('path', 'like', '%-'.$ids[0].'-%')->delete();
|
||||
}
|
||||
|
||||
return $this->query()->whereIn('id', $ids)->delete();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
namespace App\Services\Admin;
|
||||
|
||||
use App\Models\Product;
|
||||
use App\Models\Filters\ProductFilter;
|
||||
use App\Traits\UploadTrait;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
/**
|
||||
* @method Product getModel()
|
||||
* @method Product|\Illuminate\Database\Query\Builder query()
|
||||
*/
|
||||
class ProductService extends BaseService
|
||||
{
|
||||
use UploadTrait;
|
||||
|
||||
protected string $modelName = Product::class;
|
||||
|
||||
protected string $modelFilterName = ProductFilter::class;
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('product_categories', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name')->comment('名称');
|
||||
$table->string('key')->nullable()->unique();
|
||||
$table->string('cover')->nullable()->comment('封面');
|
||||
|
||||
$table->unsignedBigInteger('parent_id')->default(0)->comment('上级ID');
|
||||
$table->string('parent_key')->nullable('上级key');
|
||||
$table->unsignedInteger('lv')->default(1)->comment('层级');
|
||||
$table->string('path')->default('-')->comment('所有的父级ID');
|
||||
|
||||
$table->unsignedTinyInteger('is_enable')->default(1)->comment('启用开关');
|
||||
$table->unsignedTinyInteger('is_show')->default(0)->comment('显示开关');
|
||||
$table->unsignedTinyInteger('is_recommend')->default(0)->comment('推荐开关');
|
||||
|
||||
$table->unsignedInteger('sort')->default(0)->comment('排序');
|
||||
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('product_categories');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('products', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name')->comment('名称');
|
||||
$table->string('spu')->nullable()->comment('spu');
|
||||
$table->string('sku')->nullable()->unique()->comment('sku');
|
||||
$table->unsignedBigInteger('parent_id')->nullable()->comment('父级');
|
||||
$table->unsignedBigInteger('category_id')->nullable()->comment('分类');
|
||||
$table->string('t_ids')->nullable()->comment('标签');
|
||||
|
||||
$table->text('sub_title')->nullable()->comment('副标题');
|
||||
$table->string('cover')->nullable()->comment('封面');
|
||||
$table->text('photos')->nullable()->comment('图片');
|
||||
$table->text('base_info')->nullable()->comment('基础信息');
|
||||
$table->text('description')->nullable()->comment('详情');
|
||||
|
||||
$table->text('attr_config')->nullable()->comment('属性');
|
||||
$table->text('attr_values')->nullable()->comment('属性值');//sku才有属性值
|
||||
|
||||
$table->unsignedInteger('virtual_sales')->default(0)->comment('虚拟销量');
|
||||
$table->unsignedInteger('sales')->default(0)->comment('销量');
|
||||
|
||||
$table->unsignedTinyInteger('is_sale')->default(0)->comment('上架开关');
|
||||
$table->unsignedTinyInteger('is_show')->default(0)->comment('显示开关');
|
||||
$table->unsignedTinyInteger('is_recommend')->default(0)->comment('推荐开关');
|
||||
$table->unsignedTinyInteger('is_hot')->default(0)->comment('热销开关');
|
||||
$table->unsignedTinyInteger('is_new')->default(0)->comment('上新开关');
|
||||
|
||||
$table->unsignedDecimal('sale_price', 10, 2)->default(0.00)->comment('售价');
|
||||
$table->unsignedBigInteger('shipping_tmp_id')->nullable()->comment('运费模板');
|
||||
$table->unsignedInteger('stocks')->default(0)->comment('库存');
|
||||
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('products');
|
||||
}
|
||||
};
|
||||
|
|
@ -30,12 +30,23 @@ class AdminMenuSeeder extends Seeder
|
|||
['title' => 'keywords', 'icon' => 'ph:codesandbox-logo-light', 'url' => '/system/keywords', 'order'=>6]
|
||||
],
|
||||
],
|
||||
['title' => 'web_content', 'icon' => 'ic:outline-collections-bookmark', 'url' => '', 'order'=>3,
|
||||
['title' => 'web_content', 'icon' => 'ic:outline-collections-bookmark', 'url' => '/web_content', 'order'=>3,
|
||||
'children' =>[
|
||||
['title'=>'articles', 'icon'=>'ic:outline-article','url'=>'/articles', 'order'=>1],
|
||||
['title'=>'ads', 'icon'=>'lets-icons:img-box','url'=>'/ads', 'order'=>2],
|
||||
]
|
||||
]
|
||||
],
|
||||
['title' => 'mall', 'icon' => 'uil:shop', 'url' => '/mall', 'order'=> 4,
|
||||
'children' => [
|
||||
['title'=>'product_categories', 'icon'=>'tabler:category-2', 'url'=>'/product_categories', 'order'=>1],
|
||||
['title'=>'products', 'icon'=>'ep:goods', 'url'=>'/products', 'order'=>2],
|
||||
['title'=>'shipping_tmps', 'icon'=>'streamline:shipping-truck', 'url'=>'/shipping_tmps', 'order'=>3],
|
||||
['title'=>'orders', 'icon'=>'icon-park-outline:transaction-order', 'url'=>'/orders', 'order'=>4],
|
||||
['title'=>'shipping_orders', 'icon'=>'akar-icons:shipping-box-02', 'url'=>'/shipping_orders', 'order'=>5],
|
||||
['title'=>'after_orders', 'icon'=>'material-symbols-light:inactive-order-outline-sharp', 'url'=>'/after_orders', 'order'=>6],
|
||||
['title'=>'product_stocks', 'icon'=>'material-symbols:warehouse-outline-rounded', 'url'=>'/product_stocks', 'order'=>7],
|
||||
]
|
||||
],
|
||||
];
|
||||
DB::table('admin_menus')->truncate();
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -270,6 +270,10 @@ return [
|
|||
'please_install_laravel_excel' => '请先安装 laravel-excel 扩展',
|
||||
],
|
||||
'keywords' => [
|
||||
'name' => '名称',
|
||||
'key' => 'KEY',
|
||||
'value' => '值',
|
||||
'sort' => '排序',
|
||||
'search_name' => '名称/KEY',
|
||||
'parent_keyword' => '父级关键字',
|
||||
],
|
||||
|
|
@ -307,5 +311,43 @@ return [
|
|||
'mini_id' => '小程序ID',
|
||||
'mini_link'=> '小程序路径'
|
||||
],
|
||||
],
|
||||
'product_categories' => [
|
||||
'name' => '名称',
|
||||
'key' => 'KEY',
|
||||
'cover'=>'分类图',
|
||||
'sort'=>'排序',
|
||||
'is_enable' => '启用',
|
||||
'is_show' => '展示',
|
||||
'is_recommend' => '推荐'
|
||||
],
|
||||
'products' => [
|
||||
'name' => '名称',
|
||||
'spu' => 'SPU',
|
||||
'sku' => 'SKU',
|
||||
'category' => '分类',
|
||||
'sub_title'=> '副标题',
|
||||
'cover' => '封面',
|
||||
'photos' => '相册',
|
||||
'base_info' => '基础信息',
|
||||
'description' => '详情',
|
||||
'price' => '售价',
|
||||
'virtual_sales' => '虚拟销量',
|
||||
'stocks' => '库存',
|
||||
'tags' => '标签',
|
||||
'shipping_tmp_id' => '运费模板',
|
||||
|
||||
'sort' => '排序',
|
||||
|
||||
'is_sale' => '上架',
|
||||
'is_show' => '展示',
|
||||
|
||||
'is_recommend' => '推荐',
|
||||
'is_hot' => '热销',
|
||||
'is_new' => '新品',
|
||||
|
||||
'tab1' => '基础信息',
|
||||
'tab2' => '详细信息',
|
||||
'tab3' => '规格属性',
|
||||
]
|
||||
];
|
||||
|
|
|
|||
|
|
@ -12,5 +12,13 @@ return [
|
|||
'keywords' => '数据字典',
|
||||
'web_content' => '内容管理',
|
||||
'articles' => '文章管理',
|
||||
'ads' => '广告管理',
|
||||
'ads' => '广告管理',
|
||||
'mall' => '商城管理',
|
||||
'product_categories'=> '商品分类',
|
||||
'products' => '商品管理',
|
||||
'shipping_tmps' => '运费模板',
|
||||
'orders' => '订单管理',
|
||||
'shipping_orders' => '发货管理',
|
||||
'after_orders' => '售后管理',
|
||||
'product_stocks' => '商品库存',
|
||||
];
|
||||
|
|
|
|||
Loading…
Reference in New Issue