4
0
Fork 0
master
panliang 2022-08-08 18:03:19 +08:00
parent 52ef9567cf
commit 182bd8b06f
15 changed files with 450 additions and 194 deletions

View File

@ -4,7 +4,8 @@ return [
'labels' => [
'GoodsSku' => '货品管理',
'goods' => '商品管理',
'sku' => '商品管理',
'sku' => '货品管理',
'create' => '添加',
],
'fields' => [
'sn' => '货号',

View File

@ -1,22 +1,29 @@
<div class="table-responsive p-1" id="spec-{{$name}}">
<input type="hidden" name="{{$name}}" value="{{ json_encode($value, JSON_UNESCAPED_UNICODE) }}">
<table class="table table-bordered table-hover">
<thead>
<tr>
@foreach($headers as $item)
<td>{{ $item }}</td>
@endforeach
<td></td>
<td>
@if($type)
<button type="button" class="btn btn-sm btn-outline-primary generate-button">
<i class="fa fa-plus-square"></i>
</button>
@endif
</td>
</tr>
</thead>
<tbody>
@foreach($value as $item)
@foreach($formatValue as $item)
<tr data-id="{{ $item['name'] }}">
<td rowspan="{{count($headers) + 2}}" class="editable">{{ $item['name'] }}</td>
<td rowspan="{{count($item['values']) + 2}}" class="editable">{{ $item['name'] }}</td>
</tr>
@foreach($item['values'] as $subItem)
<tr data-pid="{{ $item['name'] }}">
@foreach($subItem as $value)
<td class="editable">{{ $value }}</td>
@foreach($keys as $key)
<td class="editable" data-{{$key}}="{{ data_get($subItem, $key) }}">{{ data_get($subItem, $key) }}</td>
@endforeach
<td>
<button type="button" class="btn btn-sm btn-outline-danger delete-item-button">
@ -26,12 +33,10 @@
</tr>
@endforeach
<tr data-pid="{{$item['name']}}">
@foreach($headers as $index => $subItem)
@if($index > 0)
<td>
<input type="text" class="form-control add-item-input" placeholder="填写 {{ $item['name'] }} {{ $subItem }}">
</td>
@endif
@foreach($keys as $index => $key)
<td>
<input type="text" class="form-control add-item-input" placeholder="填写 {{ $headers[$index + 1] }}">
</td>
@endforeach
<td>
<button type="button" class="btn btn-sm btn-outline-primary add-item-button">
@ -45,7 +50,7 @@
<input type="text" class="form-control add-attr-input" placeholder="添加 {{ $headers[0] }}">
</td>
<td>
<button type="button" class="btn btn-sm btn-outline-warning add-attr-button" rowspan="{{count($headers) + 2}}">
<button type="button" class="btn btn-sm btn-outline-warning add-attr-button">
<i class="fa fa-plus"></i>
</button>
</td>
@ -66,89 +71,170 @@
}
</style>
<script>
Dcat.ready(function () {
// 添加父级属性
$('#spec-{{$name}}').on('click', '.add-attr-button', function () {
var tr = $(this).parents('tr')
var rowspan = tr.find('td').length
var value = $('.add-attr-input').val()
if (!value) {
return Dcat.swal.warning('请填写{{$headers[0]}}')
}
var html = `<tr data-id="${value}">`
html += `<td rowspan="${rowspan}" class="editable">${value}</td>`
// for (let i = 0; i < rowspan; i++) {
// html += `<td></td>`
// }
// html += '<td><button type="button" class="btn btn-sm btn-outline-danger delete-item-button"><i class="fa fa-trash"></i></button></td>'
html += '</tr>'
html += `<tr data-pid="${value}">`
for (let i = 0; i < rowspan; i++) {
html += `<td><input type="text" class="form-control add-item-input" placeholder="填写"></td>`
}
html += '<td><button type="button" class="btn btn-sm btn-outline-primary add-item-button"><i class="fa fa-plus"></i></button></td>'
html += '</tr>'
tr.before(html)
$('.add-attr-input').val('')
var type = JSON.parse('{!! json_encode($type) !!}')
var keys = JSON.parse('{!! json_encode($keys) !!}')
var headers = JSON.parse('{!! json_encode($headers) !!}')
var element = $('#spec-{{$name}}')
// 添加父级属性
element.on('click', '.add-attr-button', function () {
var value = $('.add-attr-input').val()
if (!value) {
return Dcat.swal.warning(`请填写 ${headers.name}`)
}
addGroup(value)
$('.add-attr-input').val('')
updateInputValue()
})
// 添加子属性
.on('click', '.add-item-button', function () {
var tr = $(this).parents('tr')
var pid = tr.data('pid')
var values = {}
var inputs = tr.find('input.add-item-input')
for(let i = 0; i < keys.length; i++) {
let item = inputs.eq(i)[0]
let key = keys[i]
values[key] = inputs.eq(i).val()
}
addItem(pid, values)
// 清空输入框
inputs.each((key, item) => {
item.value = ''
})
// 添加子属性
.on('click', '.add-item-button', function () {
var tr = $(this).parents('tr')
var pid = tr.data('pid')
var parent = $('tr[data-id="'+pid+'"]')
var values = []
var inputs = tr.find('input.add-item-input')
var html = '<tr data-pid="'+pid+'">'
for(let i = 0; i < inputs.length; i++) {
let item = inputs.eq(i)[0]
// if (!item.value) {
// return Dcat.swal.warning('请' + item.placeholder)
// }
values.push(item.value)
html += '<td class="editable">' + item.value + '</td>'
}
html += '<td><button type="button" class="btn btn-sm btn-outline-danger delete-item-button"><i class="fa fa-trash"></i></button></td></tr>'
if (values.length === inputs.length) {
tr.before(html)
var parentTd = parent.find('td').first()
parentTd.attr('rowspan', parseInt(parentTd.attr('rowspan')) + 1)
// 清空输入框
inputs.each((key, item) => {
item.value = ''
})
}
})
// 删除子属性
.on('click', '.delete-item-button', function () {
var tr = $(this).parents('tr')
var pid = tr.data('pid')
var parent = $('tr[data-id="'+pid+'"]')
var parentTd = parent.find('td').first()
parentTd.attr('rowspan', parseInt(parentTd.attr('rowspan')) - 1)
tr.remove()
})
// 修改
.on('click', '.editable', function () {
var td = $(this)
var tr = td.parents('tr')
var value = td.html()
Dcat.swal.fire({
input: 'text',
inputValue: value,
showCancelButton: true,
cancelButtonText: '取消',
confirmButtonText: '确定',
}).then(result => {
if (result.value !== undefined && result.value) {
// 修改父级属性
if (tr.attr('data-id')) {
var pid = tr.attr('data-id')
$('tr[data-pid="'+pid+'"]').attr('data-pid', result.value)
tr.attr('data-id', result.value)
}
td.html(result.value)
updateInputValue()
})
// 删除子属性
.on('click', '.delete-item-button', function () {
var tr = $(this).parents('tr')
var pid = tr.data('pid')
var parent = $('tr[data-id="'+pid+'"]')
var parentTd = parent.find('td').first()
parentTd.attr('rowspan', parseInt(parentTd.attr('rowspan')) - 1)
tr.remove()
// 子属性全部删除, 删除父级属性
if (element.find(`tr[data-pid="${pid}"]`).length <= 1) {
element.find(`tr[data-pid="${pid}"]`).remove()
element.find(`tr[data-id="${pid}"]`).remove()
}
updateInputValue()
})
// 修改
.on('click', '.editable', function () {
var td = $(this)
var tr = td.parents('tr')
var value = td.html()
Dcat.swal.fire({
input: 'text',
inputValue: value,
showCancelButton: true,
cancelButtonText: '取消',
confirmButtonText: '确定',
}).then(result => {
if (result.value !== undefined && result.value) {
// 修改父级属性
if (tr.attr('data-id')) {
var pid = tr.attr('data-id')
$('tr[data-pid="'+pid+'"]').attr('data-pid', result.value)
tr.attr('data-id', result.value)
}
})
td.html(result.value)
updateInputValue()
}
})
})
// 重新生成
.on('click', '.generate-button', function () {
var trs = $(this).parents('table').find('tr[data-id]')
for (let i = 0; i < type.length; i++) {
let item = type[i]
// 生成父级属性
if (element.find(`tr[data-id="${item.name}"]`).length === 0) {
addGroup(item.name)
}
// 生成子级属性
for (let k = 0; k < item.values.length; k++) {
let subItem = item.values[k]
let baseKey = keys[0]
if (element.find(`tr[data-pid="${item.name}"]`).find(`td[data-name="${subItem[baseKey]}"]`).length == 0) {
let values = {}
for(let j = 0; j < keys.length; j++) {
let key = keys[j]
values[key] = subItem[key] ?? ''
}
addItem(item.name, values)
}
}
}
updateInputValue()
})
function addGroup(id) {
var tr = element.find('.add-attr-button').parents('tr')
var html = `<tr data-id="${id}">`
html += `<td rowspan="${keys.length}" class="editable">${id}</td>`
html += '</tr>'
html += `<tr data-pid="${id}">`
for (let i = 1; i < headers.length; i++) {
html += `<td><input type="text" class="form-control add-item-input" placeholder="填写 ${headers[i]}"></td>`
}
html += '<td><button type="button" class="btn btn-sm btn-outline-primary add-item-button"><i class="fa fa-plus"></i></button></td>'
html += '</tr>'
tr.before(html)
}
function addItem(id, values) {
var tr = element.find(`tr[data-id="${id}"]`)
// 构造 html
var html = `<tr data-pid="${id}">`;
Object.keys(values).forEach(key => {
let value = values[key]
html += `<td class="editable" data-${key}="${value}">${value}</td>`
})
for(let i = 0; i < values.length; i++) {
html += `<td class="editable">${values[i]}</td>`
}
html += '<td><button type="button" class="btn btn-sm btn-outline-danger delete-item-button"><i class="fa fa-trash"></i></button></td></tr>'
// 修改 rowspan
var parentTd = tr.find('td').first()
parentTd.attr('rowspan', parseInt(parentTd.attr('rowspan')) + 1)
// 追加 html
$(`tr[data-pid="${id}"]:last`).before(html)
}
// 整合表格里面的值
function formatValue() {
var values = []
var tr = element.find('tr[data-id]')
for (let i = 0; i < tr.length; i++) {
var item = tr.eq(i)
var id = item.data('id')
var subTr = element.find(`[data-pid="${id}"]:not(:last)`)
var subValues = []
subTr.each((key, item) => {
var subValue = {}
for (let k = 0; k < keys.length; k++) {
subValue[keys[k]] = $(item).find('td').eq(k).html()
}
subValues.push(subValue)
})
values.push({name: id, values: subValues})
}
return values
}
function updateInputValue() {
element.find('input[name="{{$name}}"]').val(JSON.stringify(formatValue()))
}
</script>

View File

@ -5,7 +5,7 @@
@foreach($value as $item)
<div class="mt-1">
<span class="label bg-info">{{ $item['name'] }}</span>
<span>{{ $item['value'] }} {{ isset($item['price']) ? '(+'.$item['price'].')' : '' }}</span>
<span>{{ $item['name'] }}({{ $item['value'] }})</span>
</div>
@endforeach
@endif

View File

@ -0,0 +1,15 @@
<!-- $model 当前行数据 -->
<!-- $name 字段名称 -->
<!-- $value 为当前列的值 -->
@if($value)
@foreach($value as $item)
<div class="mt-1">
<span class="label bg-info">{{ $item['name'] }}</span>
@if($item['values'])
@foreach($item['values'] as $subItem)
<span>{{ $subItem['name'] }}({{ $subItem['value'] }})</span>
@endforeach
@endif
</div>
@endforeach
@endif

View File

@ -0,0 +1,15 @@
<!-- $model 当前行数据 -->
<!-- $name 字段名称 -->
<!-- $value 为当前列的值 -->
@if($value)
@foreach($value as $item)
<div class="mt-1">
<span class="label bg-info">{{ $item['name'] }}</span>
@if($item['values'])
@foreach($item['values'] as $subItem)
<span>{{ $subItem['value'] }}({{ $subItem['price'] }})</span>
@endforeach
@endif
</div>
@endforeach
@endif

View File

@ -5,11 +5,7 @@
@foreach($value as $item)
<div class="mt-1">
<span class="label bg-info">{{ $item['name'] }}</span>
@if($item['values'])
@foreach($item['values'] as $subItem)
<span>{{ $subItem['value'] }}({{ $subItem['price'] }})</span>
@endforeach
@endif
<span>{{ $item['value'] }}({{ $item['price'] }})</span>
</div>
@endforeach
@endif

View File

@ -0,0 +1,15 @@
<!-- $model 当前行数据 -->
<!-- $name 字段名称 -->
<!-- $value 为当前列的值 -->
@if($value)
@foreach($value as $item)
<div class="mt-1">
<span class="label bg-info">{{ $item['name'] }}</span>
@if($item['values'])
@foreach($item['values'] as $subItem)
<span>{{ $subItem['value'] }}({{ $subItem['price'] }})</span>
@endforeach
@endif
</div>
@endforeach
@endif

View File

@ -5,7 +5,6 @@ namespace Peidikeji\Goods\Form;
use Dcat\Admin\Contracts\LazyRenderable;
use Dcat\Admin\Traits\LazyWidget;
use Dcat\Admin\Widgets\Form;
use Illuminate\Support\Arr;
use Peidikeji\Goods\Models\Goods;
class GoodsAttrForm extends Form implements LazyRenderable
@ -14,20 +13,16 @@ class GoodsAttrForm extends Form implements LazyRenderable
public function handle(array $input)
{
dd($input);
$goods = Goods::findOrFail($input['goods_id']);
$goods->update(['attr' => $input['attr']]);
$goods = Goods::findOrFail($this->payload['goods_id']);
$goods->update(['attr' => json_decode($input['attr'])]);
return $this->response()->success('保存成功');
}
public function form()
{
$this->fill(Arr::only($this->payload, ['type_id', 'goods_id', 'attr']));
$this->hidden('type_id');
$this->hidden('goods_id');
$this->spec('attr')->header(['分组', '名称', '属性值']);
$attr = $this->model()->type?->attr;
$this->spec('attr')->header(['分组', '名称', '属性值'])->keys(['name', 'value'])->type($attr);
}
protected function renderResetButton()

View File

@ -2,12 +2,9 @@
namespace Peidikeji\Goods\Form;
use Dcat\Admin\Admin;
use Dcat\Admin\Contracts\LazyRenderable;
use Dcat\Admin\Form\NestedForm;
use Dcat\Admin\Traits\LazyWidget;
use Dcat\Admin\Widgets\Form;
use Illuminate\Support\Arr;
use Peidikeji\Goods\Models\Goods;
class GoodsSpecForm extends Form implements LazyRenderable
@ -16,28 +13,21 @@ class GoodsSpecForm extends Form implements LazyRenderable
public function handle(array $input)
{
$goods = Goods::findOrFail($input['goods_id']);
$goods->update(['spec' => $input['spec']]);
$goods = Goods::findOrFail($this->payload['goods_id']);
$spec = json_decode($input['spec'], true);
foreach($spec as &$item) {
foreach($item['values'] as &$subItem) {}
$subItem['price'] = floatval($subItem['price']);
}
$goods->update(['spec' => $spec]);
return $this->response()->success('保存成功');
}
public function form()
{
$this->spec('spec')->customFormat(function ($v) {
$list = [];
foreach($v as $item) {
$listItem = ['name' => $item['name'], 'values' => []];
foreach($item['values'] as $subItem) {
array_push($listItem['values'], [
'name' => $subItem['value'],
'value' => $subItem['price']
]);
}
array_push($list, $listItem);
}
return $list;
})->header(['名称', '可选值', '价格']);
$spec = $this->model()->type?->spec;
$this->spec('spec')->header(['名称', '可选值', '价格'])->keys(['value', 'price'])->type($spec);
}
protected function renderResetButton()

View File

@ -3,19 +3,68 @@
namespace Peidikeji\Goods\Form;
use Dcat\Admin\Form\Field;
use Illuminate\Support\Arr;
class Spec extends Field
{
protected $view = 'peidikeji.dcat-admin-extension-goods::form.spec';
protected $variables = [
'headers' => []
'headers' => [],
'keys' => [],
'type' => null,
'formatValue' => [],
];
public function header(array $headers)
{
$this->addVariables(['headers' => $headers]);
$this->addVariables([
'headers' => $headers,
]);
return $this;
}
public function keys($keys)
{
$this->addVariables([
'keys' => $keys,
]);
return $this;
}
public function type($type)
{
$this->addVariables(['type' => $type]);
return $this;
}
public function render()
{
$value = $this->value;
$type = $this->variables['type'];
$newValue = [];
if ($type && !$value) {
foreach($type as $item) {
$itemValue = $value ? Arr::first($value, fn($i) => $i['name'] === $item['name']) : [];
$values = data_get($itemValue, 'values', []);
foreach($values as &$items) {
$subItem = Arr::first($item['values'], fn($i) => $i['name'] === $items['name']);
$items['options'] = data_get($subItem, 'values');
}
array_push($newValue, [
'name' => $item['name'],
'values' => $values
]);
}
} else {
$newValue = $value ?: [];
}
$this->addVariables([
'formatValue' => $newValue
]);
return parent::render();
}
}

View File

@ -22,14 +22,22 @@ class GoodsService
GoodsSku::where('goods_id', $goods->id)->delete();
}
public function generateSku(Goods $goods)
/**
* 根据规格生成SKU
*
* @param Goods $goods 商品
* @param array $options {spec: 指定规格, price: 基础价格, name: 基础名称, stock: 默认库存, name_add: 是否在名称上面追加属性值, price_add: 是否在价格上面追加属性的加价, force: 是否覆盖原有的货品}
*/
public function generateSku(Goods $goods, $options = [])
{
$this->clearSku($goods);
if ($goods->spec) {
$spec = $goods->spec;
$price = $goods->price;
$name = $goods->name;
$spec = data_get($options, 'spec', $goods->spec);
$price = data_get($options, 'price', $goods->price);
$name = data_get($options, 'name', $goods->name);
$stock = data_get($options, 'stock', $goods->stock);
$nameAdd = !!data_get($options, 'name_add', false);
$priceAdd = !!data_get($options, 'price_add', false);
$force = !!data_get($options, 'force', false);
if ($spec) {
$specList = [];
foreach ($spec as $item) {
$items = [];
@ -37,21 +45,30 @@ class GoodsService
array_push($items, [
'name' => $item['name'],
'value' => $value['value'],
'price' => $value['price'],
'price' => floatval($value['price']),
]);
}
array_push($specList, $items);
}
$cartesianList = $this->cartesianProduct($specList);
foreach($cartesianList as $items) {
$specPrice = array_sum(array_column($items, 'price'));
$goods->skus()->create([
'sn' => $this->generateSn(),
'name' => $name,
'price' => $price + $specPrice,
'stock' => $goods->stock,
$specPrice = $priceAdd ? $price + array_sum(array_column($items, 'price')) : $price;
$specName = $nameAdd ? $name . ' ' . implode(' ', array_column($items, 'value')) : $name;
$exists = $goods->skus()->jsonArray($items)->exists();
$attributes = [
'name' => $specName,
'price' => $specPrice,
'stock' => $stock,
'spec' => $items,
]);
];
if ($exists) {
if ($force) {
$goods->skus()->jsonArray($items)->update($attributes);
}
} else {
$attributes['sn'] = $this->generateSn();
$goods->skus()->create($attributes);
}
}
}
}

View File

@ -10,11 +10,13 @@ use Dcat\Admin\Http\Controllers\AdminController;
use Dcat\Admin\Layout\Content;
use Dcat\Admin\Show;
use Dcat\Admin\Widgets\Card;
use Illuminate\Validation\Rule;
use Peidikeji\Goods\Form\GoodsAttrForm;
use Peidikeji\Goods\Form\GoodsSpecForm;
use Peidikeji\Goods\Models\Goods;
use Peidikeji\Goods\Models\GoodsBrand;
use Peidikeji\Goods\Models\GoodsCategory;
use Peidikeji\Goods\Models\GoodsSku;
use Peidikeji\Goods\Models\GoodsType;
class GoodsController extends AdminController
@ -25,8 +27,9 @@ class GoodsController extends AdminController
{
$goods = Goods::with(['type'])->findOrFail($goods);
$form = GoodsAttrForm::make([
'type' => $goods->type
])->payload(['attr' => $goods->attr, 'type_id' => $goods->type?->id, 'goods_id' => $goods->id])->appendHtmlAttribute('class', 'bg-white');
'type' => $goods->type,
'attr' => $goods->attr
])->payload(['type_id' => $goods->type?->id, 'goods_id' => $goods->id])->appendHtmlAttribute('class', 'bg-white');
return $content
->translation($this->translation())
->title($goods->name)
@ -83,7 +86,7 @@ class GoodsController extends AdminController
return ($this->cover_image ? '<img src="'.$this->cover_image.'" width="60" class="img-thumbnail"/>&nbsp;' : '') . '<a href="'.admin_url('goods/' . $this->id).'">'.$this->name.'</a>';
});
$grid->column('price')->editable();
$grid->column('spec')->view('peidikeji.dcat-admin-extension-goods::grid.spec');
$grid->column('spec')->view('peidikeji.dcat-admin-extension-goods::grid.specs');
$grid->column('on_sale')->switch();
$grid->column('sold_count');
@ -111,9 +114,9 @@ class GoodsController extends AdminController
$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('spec')->view('peidikeji.dcat-admin-extension-goods::grid.specs');
$show->field('attr')->view('peidikeji.dcat-admin-extension-goods::grid.attrs');
$show->field('part')->view('peidikeji.dcat-admin-extension-goods::grid.parts');
$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'));
@ -127,17 +130,21 @@ class GoodsController extends AdminController
return Form::make(new Goods(), 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'));
} else {
$type = $model->type_id ? GoodsType::find($form->model()->type_id) : null;
$form->display('type_id')->with(fn() => $type->name);
$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();
$form->select('brand_id')->options(GoodsBrand::pluck('name', 'id'));
$form->text('name')->required();
$form->text('goods_sn');
$form->text('goods_sn')->required()->rules([$unique], [
'unique' => '商品编号已经存在'
]);
$form->image('cover_image')
->autoUpload()
->saveFullUrl()
@ -159,6 +166,12 @@ class GoodsController extends AdminController
$form->disableCreatingCheck();
$form->disableViewCheck();
$form->disableEditingCheck();
$form->deleting(function (Form $form) {
$data = $form->model()->toArray();
// 删除 SKU
GoodsSku::whereIn('goods_id', array_column($data, 'id'))->delete();
});
});
}
}

View File

@ -11,6 +11,7 @@ use Dcat\Admin\Show;
use Illuminate\Routing\Controller;
use Illuminate\Support\Arr;
use Illuminate\Validation\Rule;
use Peidikeji\Goods\GoodsService;
use Peidikeji\Goods\Models\Goods;
use Peidikeji\Goods\Models\GoodsSku;
@ -26,14 +27,16 @@ class GoodsSkuController extends Controller
$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]]]);
}
});
if ($specs) {
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]]]);
}
});
}
}
});
@ -43,13 +46,15 @@ class GoodsSkuController extends Controller
$grid->column('origin_price')->display(fn() => $goods->price);
$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 '<span class="label bg-info">'.$value.'</span>';
});
if ($goods->spec) {
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 '<span class="label bg-info">'.$value.'</span>';
});
}
}
// $grid->column('spec')->view('peidikeji.dcat-admin-extension-goods::grid.attr');
});
@ -69,7 +74,7 @@ class GoodsSkuController extends Controller
$show->field('name');
$show->field('price');
$show->field('stock');
$show->field('spec')->view('peidikeji.dcat-admin-extension-goods::grid.attr');
$show->field('spec')->view('peidikeji.dcat-admin-extension-goods::grid.spec');
// $goods = $show->model()->goods;
// foreach($goods->spec as $key => $item) {
// $show->field('spec_' . $key, $item['name'])->as(function () use ($item) {
@ -90,11 +95,8 @@ class GoodsSkuController extends Controller
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();
$unqiue = Rule::unique('goods_sku', 'sn')->ignore($form->model()->id);
$form->text('sn')->rules([$unqiue], ['unique' => '货号已经存在'])->required();
$form->text('name')->default($goods->name);
$form->number('price')->min(0)->default($goods->price);
$form->number('stock')->min(0)->default($goods->stock);
@ -102,22 +104,26 @@ class GoodsSkuController extends Controller
$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);
if ($goods->spec) {
foreach($goods->spec as $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->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']);
if ($goods->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);
@ -148,11 +154,67 @@ class GoodsSkuController extends Controller
public function create($goods, Content $content)
{
$goods = Goods::findOrFail($goods);
return $content
->translation($this->translation)
->title(admin_trans_label())
->description(trans('admin.create'))
->body($this->form(Goods::findOrFail($goods)));
->title(__('peidikeji.dcat-admin-extension-goods::goods-sku.labels.sku'))
->description(__('peidikeji.dcat-admin-extension-goods::goods-sku.labels.create'))
->body($this->createForm($goods));
}
protected function createForm($goods)
{
return Form::make(new GoodsSku(), function (Form $form) use ($goods) {
$form->text('name')->default($goods->name);
if ($goods->spec) {
$form->checkbox('name_append', '')->options([1 => '是否在名称上面追加属性值']);
}
$form->number('price')->min(0)->default($goods->price);
if ($goods->spec) {
$form->checkbox('price_append', '')->options([1 => '是否在价格上面追加属性的加价'])->default([1]);
}
if ($goods->spec) {
foreach($goods->spec as $item) {
$values = array_column($item['values'], 'value', 'value');
$form->checkbox($item['name'], $item['name'])->options($values);
}
$form->checkbox('force', '')->options([1 => '覆盖已经存在的货品'])->default(1);
}
$form->disableCreatingCheck();
$form->disableEditingCheck();
$form->disableViewCheck();
$form->disableResetButton();
$form->saving(function (Form $form) use ($goods) {
$price = $form->price;
$name = $form->name;
$spec = [];
if ($goods->spec) {
foreach($goods->spec as $index => $item) {
$values = $form->input($item['name']);
$values = array_filter($values, fn($v) => $v);
if (count($values) === 0) {
return $form->response()->error('请勾选 ' . $item['name']);
}
array_push($spec, ['name' => $item['name'], 'values' => array_filter($item['values'], fn($v) => in_array($v['value'], $values))]);
$form->deleteInput($item['name']);
}
}
GoodsService::make()->generateSku($goods, [
'spec' => $spec,
'price' => $price,
'name' => $name,
'name_add' => !!data_get($form->name_append, 0),
'price_add' => !!data_get($form->price_append, 0),
'force' => !!$form->force
]);
return $form->response()->success('添加成功')->redirect(admin_route('goods_sku.index', ['goods' => $goods->id]));
});
});
}
public function update($goods, $id)
@ -162,7 +224,7 @@ class GoodsSkuController extends Controller
public function store($goods)
{
return $this->form(Goods::findOrFail($goods))->store();
return $this->createForm(Goods::findOrFail($goods))->store();
}
public function destroy($goods, $id)

View File

@ -53,8 +53,10 @@ class GoodsTableSeeder extends Seeder
[
'name' => '笔记本电脑',
'attr' => [
['group' => '显示器', 'name' => '屏幕类型', 'values' => ['LED 背光显示屏']],
['group' => '显示器','name' => '物理分辨率', 'values' => ['3072 x 1920 (226 ppi)']],
['name' => '显示器', 'values' => [
['name' => '屏幕类型', 'values' => ['LED 背光显示屏']],
['name' => '物理分辨率', 'values' => ['3072 x 1920 (226 ppi)']]
]],
],
'spec' => [
['name' => '颜色', 'values' => ['白色', '灰色']],

View File

@ -1,6 +1,6 @@
<div class="{{$viewClass['form-group']}}" >
<label class="{{$viewClass['label']}} control-label pt-0">{!! $label !!}</label>
<label class="{{$viewClass['label']}} control-label">{!! $label !!}</label>
<div class="{{$viewClass['field']}}">
@ -55,4 +55,4 @@
});
$(selector+':checked').trigger('change')
</script>
@endif
@endif