4
0
Fork 0

spec form

master
panliang 2022-08-05 17:51:33 +08:00
parent b5a22ce20e
commit 52ef9567cf
17 changed files with 529 additions and 151 deletions

View File

@ -4,17 +4,52 @@ Fork From [jqhph/dcat-admin](https://github.com/jqhph/dcat-admin)
## 改动
### Show
- 文件: `dcat-admin/src/Form/Footer.php`, 将 `reset` 按钮默认设置为 `false`
### 详细页-列表按钮点击跳转方式
```php
protected $buttons = ['reset' => false, 'submit' => true, 'back' => true];
- `packages/dcat-admin/src/Show/Tools.php` 254行
```html
<a href="{$this->getListPath()}" class="btn btn-sm btn-primary ">
public function disableBack(bool $disable = true)
{
$this->buttons['back'] = !$disable;
}
```
```html
<a href="javascript:window.history.back()" class="btn btn-sm btn-primary ">
- 添加 Form 表单的 `back` 按钮, 文件: `dcat-admin/resources/views/form/footer.blade.php`
```php
@if(! empty($buttons['back']))
<div class="btn-group pull-left">
<a href="javascript:window.history.back()" class="btn btn-white"><i class="feather icon-arrow-left"></i> {{ trans('admin.back') }}</a>
</div>
@endif
```
- 文件: `dcat-admin/src/Show/Tools.php`, 添加 `back` 按钮, `list` 默认设置为 `false`, 修改按钮的渲染方式(去掉外层的 `btn-group` 标签, 添加类名 `mr-1`)
```php
protected $tools = ['back', 'list', 'edit', 'delete'];
protected $showBack = true;
public function disableBack(bool $disable = true)
{
$this->showBack = !$disable;
return $this;
}
protected function renderBack()
{
if (! $this->showBack) {
return;
}
$back = trans('admin.back');
return <<<HTML
<a href="javascript:window.history.back()" class="btn btn-sm btn-primary mr-1">
<i class="feather icon-arrow-left"></i><span class="d-none d-sm-inline"> {$back}</span>
</a>
HTML;
}
```

View File

@ -5,6 +5,8 @@ return [
'GoodsBrand' => '品牌管理',
'goods' => '商品管理',
'brand' => '品牌',
'create' => '创建',
'edit' => '修改',
],
'fields' => [
'name' => '名称',

View File

@ -6,6 +6,8 @@ return [
'goods' => '商品信息',
'create' => '创建',
'edit' => '修改',
'attr' => '属性',
'spec' => '规格',
],
'fields' => [
'category_id' => '分类',

View File

@ -0,0 +1,86 @@
<div class="row" style="margin-top: 10px;">
<div class="{{$viewClass['label']}}"><h4 class="pull-right">{!! $label !!}</h4></div>
<div class="{{$viewClass['field']}}"></div>
</div>
<hr class="mt-0">
<div class="has-many-{{$columnClass}}">
<div class="has-many-{{$columnClass}}-forms row">
@foreach($forms as $pk => $form)
<div class="has-many-{{$columnClass}}-form fields-group col-md-4">
{!! $form->render() !!}
@if($options['allowDelete'])
<div class="form-group row">
<label class="{{$viewClass['label']}} control-label"></label>
<div class="{{$viewClass['field']}}">
<div class="{{$columnClass}}-remove btn btn-white btn-sm pull-right"><i class="feather icon-trash">&nbsp;</i>{{ trans('admin.remove') }}</div>
</div>
</div>
@endif
<hr>
</div>
@endforeach
</div>
<template class="{{$columnClass}}-tpl">
<div class="has-many-{{$columnClass}}-form fields-group col-md-4">
{!! $template !!}
<div class="form-group row">
<label class="{{$viewClass['label']}} control-label"></label>
<div class="{{$viewClass['field']}}">
<div class="{{$columnClass}}-remove btn btn-white btn-sm pull-right"><i class="feather icon-trash"></i>&nbsp;{{ trans('admin.remove') }}</div>
</div>
</div>
<hr>
</div>
</template>
@if($options['allowCreate'])
<div class="form-group row">
<label class="{{$viewClass['label']}} control-label"></label>
<div class="{{$viewClass['field']}}">
<div class="{{$columnClass}}-add btn btn-primary btn-outline btn-sm"><i class="feather icon-plus"></i>&nbsp;{{ trans('admin.new') }}</div>
</div>
</div>
@endif
</div>
<script>
var nestedIndex = {!! $count !!},
container = '.has-many-{{ $columnClass }}',
forms = '.has-many-{{ $columnClass }}-forms';
function replaceNestedFormIndex(value) {
return String(value)
.replace(/{{ Dcat\Admin\Form\NestedForm::DEFAULT_KEY_NAME }}/g, nestedIndex)
.replace(/{{ Dcat\Admin\Form\NestedForm::DEFAULT_PARENT_KEY_NAME }}/g, nestedIndex);
}
$(container).on('click', '.{{$columnClass}}-add', function () {
var tpl = $('template.{{ $columnClass }}-tpl');
nestedIndex++;
$(forms).append(replaceNestedFormIndex(tpl.html()));
});
$(container).on('click', '.{{$columnClass}}-remove', function () {
var $form = $(this).closest('.has-many-{{ $columnClass }}-form');
$form.hide();
$form.find('.{{ Dcat\Admin\Form\NestedForm::REMOVE_FLAG_CLASS }}').val(1);
$form.find('[required]').prop('required', false);
});
</script>

View File

@ -0,0 +1,154 @@
<div class="table-responsive p-1" id="spec-{{$name}}">
<table class="table table-bordered table-hover">
<thead>
<tr>
@foreach($headers as $item)
<td>{{ $item }}</td>
@endforeach
<td></td>
</tr>
</thead>
<tbody>
@foreach($value as $item)
<tr data-id="{{ $item['name'] }}">
<td rowspan="{{count($headers) + 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>
@endforeach
<td>
<button type="button" class="btn btn-sm btn-outline-danger delete-item-button">
<i class="fa fa-trash"></i>
</button>
</td>
</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
@endforeach
<td>
<button type="button" class="btn btn-sm btn-outline-primary add-item-button">
<i class="fa fa-plus"></i>
</button>
</td>
</tr>
@endforeach
<tr>
<td colspan="{{ count($headers) }}">
<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}}">
<i class="fa fa-plus"></i>
</button>
</td>
</tr>
</tbody>
</table>
</div>
<style>
.table {
text-align: center;
}
.table td {
vertical-align: middle;
}
.editable {
color: #586cb1;
cursor: pointer;
}
</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('')
})
// 添加子属性
.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)
}
})
})
})
</script>

View File

@ -1,16 +0,0 @@
<?php
namespace Peidikeji\Goods\Actions;
use Dcat\Admin\Grid\RowAction;
use Illuminate\Http\Request;
class RowGoodsSkuList extends RowAction
{
protected $title = '货品信息';
public function handle(Request $request)
{
return $this->response()->redirect(admin_route('goods-sku.index', ['goods' => $this->getKey()]));
}
}

View File

@ -0,0 +1,37 @@
<?php
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
{
use LazyWidget;
public function handle(array $input)
{
dd($input);
$goods = Goods::findOrFail($input['goods_id']);
$goods->update(['attr' => $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(['分组', '名称', '属性值']);
}
protected function renderResetButton()
{
return "<a href=\"javascript:window.history.back()\" class=\"btn btn-white pull-left\"><i class=\"feather icon-arrow-left\"></i> 返回</a>";
}
}

View File

@ -0,0 +1,52 @@
<?php
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
{
use LazyWidget;
public function handle(array $input)
{
$goods = Goods::findOrFail($input['goods_id']);
$goods->update(['spec' => $input['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(['名称', '可选值', '价格']);
}
protected function renderResetButton()
{
return "<a href=\"javascript:window.history.back()\" class=\"btn btn-white pull-left\"><i class=\"feather icon-arrow-left\"></i> 返回</a>";
}
protected function getSubmitButtonLabel()
{
return '保存';
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace Peidikeji\Goods\Form;
use Dcat\Admin\Form\Field;
class Spec extends Field
{
protected $view = 'peidikeji.dcat-admin-extension-goods::form.spec';
protected $variables = [
'headers' => []
];
public function header(array $headers)
{
$this->addVariables(['headers' => $headers]);
return $this;
}
}

View File

@ -4,6 +4,8 @@ namespace Peidikeji\Goods;
use Dcat\Admin\Extend\ServiceProvider;
use Dcat\Admin\Admin;
use Dcat\Admin\Form;
use Peidikeji\Goods\Form\Spec;
class GoodsServiceProvider extends ServiceProvider
{
@ -14,4 +16,10 @@ class GoodsServiceProvider extends ServiceProvider
['title' => '商品类别', 'uri' => 'goods/type', 'icon' => '', 'parent' => '商品管理'],
['title' => '商品信息', 'uri' => 'goods', 'icon' => '', 'parent' => '商品管理'],
];
public function init()
{
parent::init();
Form::extend('spec', Spec::class);
}
}

View File

@ -2,17 +2,16 @@
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;
use Dcat\Admin\Http\Controllers\AdminController;
use Dcat\Admin\Layout\Content;
use Dcat\Admin\Show;
use Peidikeji\Goods\Actions\RowGoodsSkuList;
use Dcat\Admin\Widgets\Card;
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;
@ -22,6 +21,33 @@ class GoodsController extends AdminController
{
protected $translation = 'peidikeji.dcat-admin-extension-goods::goods';
public function attr($goods, Content $content)
{
$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');
return $content
->translation($this->translation())
->title($goods->name)
->description($goods->type?->name)
->body($form);
}
public function spec($goods, Content $content)
{
$goods = Goods::findOrFail($goods);
$form = GoodsSpecForm::make([
'type' => $goods->type,
'spec' => $goods->spec
])->payload(['type_id' => $goods->type_id, 'goods_id' => $goods->id])->appendHtmlAttribute('class', 'bg-white');
return $content
->translation($this->translation())
->title($goods->name)
->description($goods->type?->name)
->body($form);
}
protected function grid()
{
return Grid::make(Goods::with(['category', 'brand', 'type']), function (Grid $grid) {
@ -56,7 +82,7 @@ class GoodsController extends AdminController
$grid->column('name')->display(function () {
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');
$grid->column('price')->editable();
$grid->column('spec')->view('peidikeji.dcat-admin-extension-goods::grid.spec');
$grid->column('on_sale')->switch();
$grid->column('sold_count');
@ -64,7 +90,10 @@ class GoodsController extends AdminController
$grid->disableRowSelector();
$grid->actions(function (Actions $actions) {
$actions->append(new RowGoodsSkuList());
$row = $actions->row;
$actions->append('<a href="'.admin_route('goods_sku.index', ['goods' => $row->id]).'" class="">货品信息</a>');
$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>');
});
});
}
@ -89,6 +118,7 @@ class GoodsController extends AdminController
$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;
}
@ -97,109 +127,38 @@ class GoodsController extends AdminController
return Form::make(new Goods(), function (Form $form) {
$model = $form->model();
$isCreating = $form->isCreating();
$type = null;
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;
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);
}
$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/cover-image')
->required();
$form->multipleImage('images')
->autoUpload()
->saveFullUrl()
->move('goods/images');
$form->multipleImage('content')
->autoUpload()
->saveFullUrl()
->move('goods/content');
$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->number('price')->min(0)->attribute('step', 0.01);
$form->switch('on_sale');
$form->disableResetButton();
$form->disableCreatingCheck();
$form->disableViewCheck();
$form->disableEditingCheck();
$admin_url = request()->url();
Admin::script(
<<<JS
var url = "{$admin_url}"
var isCreating = "${isCreating}"
$('[name="type_id"]').change(function (e) {
if (isCreating) {
Dcat.reload(url + '?type_id=' + e.target.value);
}
})
JS
);
});
}
}

View File

@ -8,6 +8,8 @@ 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/{goods}/sku', GoodsSkuController::class)->names('goods_sku');
Route::get('goods/{goods}/attr', [GoodsController::class, 'attr'])->name('goods.attr');
Route::get('goods/{goods}/spec', [GoodsController::class, 'spec'])->name('goods.spec');
Route::resource('goods', GoodsController::class);

View File

@ -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('属性[{name, value}]');
$table->json('spec')->nullable()->comment('规格[{name, values: [{value, price}]}]');
$table->json('part')->nullable()->comment('配件[{name, values: [{value, price}]}]');
$table->json('attr')->nullable()->comment('属性[{name, values: [{name, value}]}]');
$table->json('spec')->nullable()->comment('规格[{name, values: [{name, value}]}]');
$table->json('part')->nullable()->comment('配件[{name, values: [{name, value}]}]');
$table->timestamps();
$table->softDeletes();

View File

@ -36,9 +36,11 @@ class GoodsTableSeeder extends Seeder
[
'name' => '手机',
'attr' => [
['group' => '主体', 'name' => '入网型号', 'values' => ['5G', '4G']],
['group' => '主体', 'name' => '上市年份', 'values' => null],
['group' => '主体', 'name' => '品牌', 'values' => null]
['name' => '主体', 'values' => [
['name' => '入网型号', 'values' => ['5G', '4G']],
['name' => '上市年份', 'values' => null],
['name' => '品牌', 'values' => null]
]]
],
'spec' => [
['name' => '颜色', 'values' => ['白色', '红色', '黑色']],
@ -92,9 +94,11 @@ class GoodsTableSeeder extends Seeder
'stock' => 100,
'price' => 6499.00,
'attr' => [
['group' => '主体', 'name' => '入网型号', 'value' => '5G'],
['group' => '主体', 'name' => '品牌', 'value' => '三星Galaxy'],
['group' => '主体', 'name' => '上市年份', 'value' => '2020'],
['name' => '主体', 'values' => [
['name' => '入网型号', 'value' => '5G'],
['name' => '品牌', 'value' => '三星Galaxy'],
['name' => '上市年份', 'value' => '2020'],
]],
],
'spec' => [
['name' => '颜色', 'values' => [
@ -133,8 +137,10 @@ class GoodsTableSeeder extends Seeder
'stock' => 150,
'price' => 17999.00,
'attr' => [
['group' => '显示器','name' => '屏幕类型', 'value' => 'LED 背光显示屏'],
['group' => '显示器','name' => '物理分辨率', 'value' => '3072 x 1920 (226 ppi)'],
['name' => '显示器', 'values' => [
['name' => '屏幕类型', 'value' => 'LED 背光显示屏'],
['name' => '物理分辨率', 'value' => '3072 x 1920 (226 ppi)']
]],
],
'spec' => [
['name' => '颜色', 'values' => [

View File

@ -20,5 +20,11 @@
<button type="reset" class="btn btn-white"><i class="feather icon-rotate-ccw"></i> {{ trans('admin.reset') }}</button>
</div>
@endif
@if(! empty($buttons['back']))
<div class="btn-group pull-left">
<a href="javascript:window.history.back()" class="btn btn-white"><i class="feather icon-arrow-left"></i> {{ trans('admin.back') }}</a>
</div>
@endif
</div>
</div>
</div>

View File

@ -33,7 +33,7 @@ class Footer implements Renderable
*
* @var array
*/
protected $buttons = ['reset' => true, 'submit' => true];
protected $buttons = ['reset' => false, 'submit' => true, 'back' => true];
/**
* Available checkboxes.
@ -59,6 +59,11 @@ class Footer implements Renderable
$this->builder = $builder;
}
public function disableBack(bool $disable = true)
{
$this->buttons['back'] = !$disable;
}
/**
* Disable reset button.
*

View File

@ -28,7 +28,7 @@ class Tools implements Renderable
*
* @var array
*/
protected $tools = ['delete', 'edit', 'list'];
protected $tools = ['back', 'list', 'edit', 'delete'];
/**
* Tools should be appends to default tools.
@ -47,7 +47,7 @@ class Tools implements Renderable
/**
* @var bool
*/
protected $showList = true;
protected $showList = false;
/**
* @var bool
@ -59,6 +59,8 @@ class Tools implements Renderable
*/
protected $showEdit = true;
protected $showBack = true;
/**
* @var bool
*/
@ -173,6 +175,12 @@ class Tools implements Renderable
return $this;
}
public function disableBack(bool $disable = true)
{
$this->showBack = !$disable;
return $this;
}
/**
* @param bool $disable
* @return $this
@ -250,11 +258,24 @@ class Tools implements Renderable
$list = trans('admin.list');
return <<<HTML
<div class="btn-group pull-right btn-mini" style="margin-right: 5px">
<a href="javascript:window.history.back()" class="btn btn-sm btn-primary ">
<a href="{$this->getListPath()}" class="btn btn-sm btn-primary mr-1">
<i class="feather icon-list"></i><span class="d-none d-sm-inline"> {$list}</span>
</a>
</div>
HTML;
}
protected function renderBack()
{
if (! $this->showBack) {
return;
}
$back = trans('admin.back');
return <<<HTML
<a href="javascript:window.history.back()" class="btn btn-sm btn-primary mr-1">
<i class="feather icon-arrow-left"></i><span class="d-none d-sm-inline"> {$back}</span>
</a>
HTML;
}
@ -276,7 +297,7 @@ HTML;
if ($this->showEdit) {
$btn = <<<EOF
<a href="{$url}" class="btn btn-sm btn-primary">
<a href="{$url}" class="btn btn-sm btn-primary mr-1">
<i class="feather icon-edit-1"></i><span class="d-none d-sm-inline"> {$edit}</span>
</a>
EOF;
@ -293,11 +314,11 @@ EOF;
$text = $this->showEdit ? '' : "<span class='d-none d-sm-inline'> &nbsp; $edit</span>";
$quickBtn = "<button data-url='$url' class='btn btn-sm btn-primary {$id}'><i class=' fa fa-clone'></i>$text</button>";
$quickBtn = "<button data-url='$url' class='btn btn-sm btn-primary mr-1 {$id}'><i class=' fa fa-clone'></i>$text</button>";
}
return <<<HTML
<div class="btn-group pull-right btn-mini" style="margin-right: 5px">{$btn}{$quickBtn}</div>
{$btn}{$quickBtn}
HTML;
}
@ -315,11 +336,9 @@ HTML;
$delete = trans('admin.delete');
return <<<HTML
<div class="btn-group pull-right btn-mini" style="margin-right: 5px">
<button class="btn btn-sm btn-white " data-action="delete" data-url="{$this->getDeletePath()}" data-redirect="{$this->getListPath()}">
<button class="btn btn-sm btn-white mr-1" data-action="delete" data-url="{$this->getDeletePath()}" data-redirect="{$this->getListPath()}">
<i class="feather icon-trash"></i><span class="d-none d-sm-inline"> {$delete}</span>
</button>
</div>
HTML;
}