优化:商品编辑页面布局调整,添加贸易术语设置及相关内容

This commit is contained in:
wuhui_zzw 2023-09-22 15:04:12 +08:00
parent 9ad042da88
commit 5663f321dc
9 changed files with 191 additions and 99 deletions

View File

@ -163,21 +163,21 @@ class ProductController extends Controller
$product = hook_filter('admin.product.form.product', $product);
$taxClasses = TaxClassRepo::getList();
array_unshift($taxClasses, ['title' => trans('admin/builder.text_no'), 'id' => 0]);
$data = [
'product' => $product,
'descriptions' => $descriptions ?? [],
'category_ids' => $categoryIds ?? [],
'product_attributes' => ProductAttributeResource::collection($product->attributes),
'relations' => ProductResource::collection($product->relations)->resource,
'languages' => LanguageRepo::all(),
'tax_classes' => $taxClasses,
'weight_classes' => Weight::getWeightUnits(),
'source' => [
'categories' => CategoryRepo::flatten(locale(), false),
'product' => $product,
'descriptions' => $descriptions ?? [],
'category_ids' => $categoryIds ?? [],
'product_attributes' => ProductAttributeResource::collection($product->attributes),
'relations' => ProductResource::collection($product->relations)->resource,
'languages' => LanguageRepo::all(),
'tax_classes' => $taxClasses,
'weight_classes' => Weight::getWeightUnits(),
'source' => [
'categories' => CategoryRepo::flatten(locale(),FALSE),
],
'_redirect' => $this->getRedirect(),
'unit_list' => Product::getUnitList(),
'unit_list' => Product::getUnitList(),
'trade_term' => Product::getTradeTermList(),
];
$data = hook_filter('admin.product.form.data', $data);

View File

@ -137,5 +137,20 @@ class Product extends Base
];
}
public static function getTradeTermList(){
return [
['title'=>'EXW'],
['title'=>'FCA'],
['title'=>'FAS'],
['title'=>'FOB'],
['title'=>'CFR'],
['title'=>'CIF'],
['title'=>'CPT'],
['title'=>'CIP'],
['title'=>'DAT'],
['title'=>'DAP'],
['title'=>'DDP'],
];
}
}

View File

@ -41,6 +41,7 @@ class CartDetail extends JsonResource
'name_format' => sub_string($productName),
'unit' => $unit,
'unit_format' => $unit,
'trade_term' => $this->trade_term,
'image' => $image,
'image_url' => image_resize($image),
'quantity' => $this->quantity,

View File

@ -47,6 +47,7 @@ class ProductDetail extends JsonResource
'id' => $this->id,
'name' => $this->description->name ?? '',
'unit' => $this->unit,//$this->description->unit ?? '',
'trade_term' => $this->trade_term,
'description' => $this->description->content ?? '',
'meta_title' => $this->description->meta_title ?? '',
'meta_keywords' => $this->description->meta_keywords ?? '',

View File

@ -41,6 +41,7 @@ class ProductSimple extends JsonResource
'name_format' => $name,
'unit' => $unit,
'unit_format' => $unit,
'trade_term' => $this->trade_term,
'url' => $this->url,
'price' => $masterSku->price,
'origin_price' => $masterSku->origin_price,

BIN
public/image/trade_term.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 KiB

View File

@ -25,7 +25,42 @@
@endforeach
</div>
@endif
<style>
#unitAndTradeTerm{
width: 100%;
display: inline-flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: flex-start;
align-items: center;
}
#unitAndTradeTerm select {
width: 150px!important;
}
#unitAndTradeTerm .col-auto {
width: 150px!important;
}
#unitAndTradeTerm .row:nth-child(2) .col-form-label{
width: 150px!important;
}
#salesMethodContent{
width: 100%;
display: inline-flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: flex-start;
align-items: center;
}
#salesMethodContent .row:nth-child(2) .col-form-label{
width: 84px!important;
}
.trade-term-img{
width: 500px!important;
}
.popover{
--bs-popover-max-width: 550px!important;
}
</style>
<ul class="nav nav-tabs nav-bordered mb-3" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" data-bs-toggle="tab" data-bs-target="#tab-basic" type="button" >{{ __('admin/product.basic_information') }}</button>
@ -58,19 +93,59 @@
<div>
<h5 class="border-bottom pb-3 mb-4">{{ __('product.transaction_info') }}</h5>
<x-admin::form.row title="{{ __('admin/product.price_setting_by.num') }}">
{{--计量单位 语言切换弃用 改为下拉框选择;贸易术语 --}}
<div id="unitAndTradeTerm" class="wp-800">
{{--计量单位--}}
<x-admin::form.row :title="__('product.unit_of_measurement')">
<select class="form-select me-3" name="unit" v-model="form.unit">
@foreach ($unit_list as $option)
<option value="{{ $option['title'] }}" {{ $option['title'] == $product->unit ? 'selected': '' }}>{{ $option['title'] }}</option>
@endforeach
</select>
</x-admin::form.row>
{{--<x-admin-form-input-locale :width="600" name="descriptions.*.unit" title="{{ __('product.unit_of_measurement') }}" :value="$descriptions" :required="true" />--}}
{{--贸易术语--}}
<x-admin-form-select :title="__('product.trade_term')" name="trade_term" :value="old('trade_term', $product->trade_term ?? '')" :options="$trade_term" key="title" label="title" required />
<div style="width: 45px;height: 35px;text-align: right;float: left;">
<i class="bi bi-question-circle" id="tradeTerm"></i>
</div>
</div>
{{--销售方式--}}
<div id="salesMethodContent" class="wp-800">
<x-admin::form.row title="{{ __('product.sales_method') }}">
<div class="mb-1 mt-2 wp-200">
<div class="form-check form-check-inline">
<input v-model="form.sales_method" class="form-check-input" id="sales_method-piece" type="radio" name="sales_method" value="piece">
<label class="form-check-label" for="sales_method-piece">{{ __('product.sales_method_piece') }}</label>
</div>
<div class="form-check form-check-inline">
<input v-model="form.sales_method" class="form-check-input" id="sales_method-batches" type="radio" name="sales_method" value="batches">
<label class="form-check-label" for="sales_method-batches">{{ __('product.sales_method_batches') }}</label>
</div>
</div>
</x-admin::form.row>
<template v-if="form.sales_method == 'batches'">
<x-admin::form.row :title="__('product.one_batch_is_equal_to')" required>
<div class="d-flex wp-400">
<input type="number" v-model="form.piece_to_batch" name="piece_to_batch" class="form-control" style="flex: 0 0 95px" />
<div style="margin-left:10px;line-height: 34px;text-align:center">@{{ form.unit }}</div>
</div>
</x-admin::form.row>
</template>
</div>
{{--价格设置--}}
<x-admin::form.row title="{{ __('admin/product.price_setting') }}">
<div class="mb-1 mt-2">
<div class="form-check form-check-inline">
<input v-model="form.price_setting" class="form-check-input" id="price_setting-sku" type="radio" name="price_setting" id="price_setting-sku" value="sku" {{ $product->price_setting == 'sku' ? 'checked' : '' }}>
<label class="form-check-label" for="price_setting-sku">{{ __('common.disable') }}</label>
<input v-model="form.price_setting" class="form-check-input" id="price_setting-num" type="radio" name="price_setting" id="price_setting-num" value="num" {{ $product->price_setting == 'num' ? 'checked' : '' }}>
<label class="form-check-label" for="price_setting-num">{{ __('admin/product.price_setting_by.num') }}</label>
</div>
<div class="form-check form-check-inline">
<input v-model="form.price_setting" class="form-check-input" id="price_setting-num" type="radio" name="price_setting" id="price_setting-num" value="num" {{ $product->price_setting == 'num' ? 'checked' : '' }}>
<label class="form-check-label" for="price_setting-num">{{ __('common.enable') }}</label>
<input v-model="form.price_setting" class="form-check-input" id="price_setting-sku" type="radio" name="price_setting" id="price_setting-sku" value="sku" {{ $product->price_setting == 'sku' ? 'checked' : '' }}>
<label class="form-check-label" for="price_setting-sku">{{ __('admin/product.price_setting_by.sku') }}</label>
</div>
</div>
</x-admin::form.row>
<span v-if="form.price_setting === 'num'">
{{-- 阶梯价格设置表格 (最小起订量,产品价格),预览,可以增加删除价格区间--}}
<div class="price_setting_by_num">
@ -145,20 +220,16 @@
{{-- <input type="hidden" name="skus[0][is_default]" placeholder="is_default" value="1">--}}
</template>
</span>
<input type="hidden" name="variables" :value="JSON.stringify(form.variables)">
<input type="hidden" name="numPrices" value="" v-if="form.price_setting === 'sku'">
{{--多规格设置--}}
@hookwrapper('admin.product.edit.switch')
<x-admin::form.row :title="__('admin/product.enable_multi_spec')">
<x-admin::form.row :title="__('product.multi_specification_settings')">
<el-switch v-model="editing.isVariable" @change="isVariableChange" class="mt-2"></el-switch>
<div class="help-text mb-1 mt-1">{{ __('product.multi_specification_settings_help') }}</div>
</x-admin::form.row>
@endhookwrapper
<input type="hidden" name="variables" :value="JSON.stringify(form.variables)">
<div class="row g-3 mb-3" v-if="editing.isVariable">
<label for="" class="wp-200 col-form-label text-end"></label>
<div class="col-auto wp-200-">
@ -308,13 +379,40 @@
<div class="invalid-feedback" style="font-size: 16px"><i class="bi bi-exclamation-circle-fill"></i> {{ __('admin/product.add_variable') }}</div>
</div>
</div>
{{--长宽高 重量--}}
<x-admin::form.row :title="__('admin/product.length_width_height')">
<div class="d-flex wp-500">
<input type="text" name="length" placeholder="{{ __('admin/product.length') }}" value="{{ old('weight', $product->length ?? '') }}" class="form-control" style="flex: 0 0 95px" />
<div style="width: 40px;line-height: 34px;text-align:center">CM X</div>
<input type="text" name="width" placeholder="{{ __('admin/product.width') }}" value="{{ old('weight', $product->width ?? '') }}" class="form-control" style="flex: 0 0 95px" />
<div style="width: 40px;line-height: 34px;text-align:center">CM X</div>
<input type="text" name="height" placeholder="{{ __('admin/product.height') }}" value="{{ old('weight', $product->height ?? '') }}" class="form-control" style="flex: 0 0 95px" />
<div style="width: 30px;line-height: 34px;text-align:center">CM</div>
<div v-if="form.sales_method == 'piece'" style="width: 30px;line-height: 34px;text-align:center">/{{ __('product.piece') }}</div>
<div v-else style="width: 30px;line-height: 34px;text-align:center">/{{ __('product.batches') }}</div>
</div>
</x-admin::form.row>
<x-admin::form.row :title="__('admin/product.weight_text')">
<div class="d-flex wp-500">
<input type="text" name="weight" placeholder="{{ __('admin/product.weight_text') }}" value="{{ old('weight', $product->weight ?? '') }}" class="form-control" style="flex: 0 0 260px" />
<select class="form-select ms-4 bg-white wp-100" name="weight_class">
@foreach ($weight_classes as $item)
<option value="{{ $item }}" {{ $product->weight_class == $item ? 'selected' : '' }}>{{ __('product.' . $item) }}</option>
@endforeach
</select>
<div v-if="form.sales_method == 'piece'" style="width: 30px;line-height: 34px;text-align:center">/{{ __('product.piece') }}</div>
<div v-else style="width: 30px;line-height: 34px;text-align:center">/{{ __('product.batches') }}</div>
</div>
</x-admin::form.row>
{{--最小起订量--}}
{{-- 未开启根据数量设置价格、直接下单产品 --}}
<template v-if="form.price_setting === 'sku' && form.active == 1">
<x-admin::form.row :title="__('admin/product.minimum_order')" required>
<div class="d-flex wp-500">
<input type="number" name="minimum_order" v-model="form.minimum_order" class="form-control"/>
<div v-if="form.sales_method == 'piece'" style="width: 30px;line-height: 34px;text-align:center">/{{ __('product.piece') }}</div>
<input type="number" name="minimum_order" v-model="form.minimum_order" class="form-control wp-100"/>
<div v-if="form.sales_method == 'piece'" style="width: 30px;line-height: 34px;text-align:center">{{ __('product.piece') }}</div>
<div v-else style="width: 30px;line-height: 34px;text-align:center">/{{ __('product.batches') }}</div>
</div>
</x-admin::form.row>
@ -323,9 +421,9 @@
<template v-else-if="form.price_setting === 'sku' && form.active != 1">
<x-admin::form.row :title="__('admin/product.minimum_order')">
<div class="d-flex wp-500">
<input type="number" name="minimum_order" v-model="form.minimum_order" class="form-control"/>
<input type="number" name="minimum_order" v-model="form.minimum_order" class="form-control wp-100"/>
<div v-if="form.sales_method == 'piece'" style="width: 30px;line-height: 34px;text-align:center">/{{ __('product.piece') }}</div>
<div v-else style="width: 30px;line-height: 34px;text-align:center">/{{ __('product.batches') }}</div>
<div v-else style="width: 30px;line-height: 34px;text-align:center">{{ __('product.batches') }}</div>
</div>
</x-admin::form.row>
</template>
@ -333,14 +431,13 @@
<template v-else>
<x-admin::form.row :title="__('admin/product.minimum_order')" required>
<div class="d-flex wp-500">
<input type="number" name="minimum_order" :value="form.numPrices.length !== 0 ? form.numPrices[0].num : 0" class="form-control" readonly/>
<input type="number" name="minimum_order" :value="form.numPrices.length !== 0 ? form.numPrices[0].num : 0" class="form-control wp-100" readonly/>
<div v-if="form.sales_method == 'piece'" style="width: 30px;line-height: 34px;text-align:center">/{{ __('product.piece') }}</div>
<div v-else style="width: 30px;line-height: 34px;text-align:center">/{{ __('product.batches') }}</div>
<div v-else style="width: 30px;line-height: 34px;text-align:center">{{ __('product.batches') }}</div>
</div>
</x-admin::form.row>
</template>
@hookwrapper('admin.product.edit.variable')
<div v-if="!editing.isVariable">
<input type="hidden" value="{{ old('skus.0.image', $product->skus[0]->image ?? '') }}" name="skus[0][image]">
@ -401,35 +498,6 @@
<x-admin-form-input name="position" :title="__('common.sort_order')" :value="old('position', $product->position ?? '0')" />
<x-admin::form.row :title="__('admin/product.length_width_height')">
<div class="d-flex wp-500">
<input type="text" name="length" placeholder="{{ __('admin/product.length') }}" value="{{ old('weight', $product->length ?? '') }}" class="form-control" style="flex: 0 0 95px" />
<div style="width: 40px;line-height: 34px;text-align:center">CM X</div>
<input type="text" name="width" placeholder="{{ __('admin/product.width') }}" value="{{ old('weight', $product->width ?? '') }}" class="form-control" style="flex: 0 0 95px" />
<div style="width: 40px;line-height: 34px;text-align:center">CM X</div>
<input type="text" name="height" placeholder="{{ __('admin/product.height') }}" value="{{ old('weight', $product->height ?? '') }}" class="form-control" style="flex: 0 0 95px" />
<div style="width: 30px;line-height: 34px;text-align:center">CM</div>
<div v-if="form.sales_method == 'piece'" style="width: 30px;line-height: 34px;text-align:center">/{{ __('product.piece') }}</div>
<div v-else style="width: 30px;line-height: 34px;text-align:center">/{{ __('product.batches') }}</div>
</div>
</x-admin::form.row>
<x-admin::form.row :title="__('admin/product.weight_text')">
<div class="d-flex wp-500">
<input type="text" name="weight" placeholder="{{ __('admin/product.weight_text') }}" value="{{ old('weight', $product->weight ?? '') }}" class="form-control" style="flex: 0 0 260px" />
<select class="form-select ms-4 bg-white wp-100" name="weight_class">
@foreach ($weight_classes as $item)
<option value="{{ $item }}" {{ $product->weight_class == $item ? 'selected' : '' }}>{{ __('product.' . $item) }}</option>
@endforeach
</select>
<div v-if="form.sales_method == 'piece'" style="width: 30px;line-height: 34px;text-align:center">/{{ __('product.piece') }}</div>
<div v-else style="width: 30px;line-height: 34px;text-align:center">/{{ __('product.batches') }}</div>
</div>
</x-admin::form.row>
@hookwrapper('admin.product.edit.brand')
<x-admin::form.row :title="__('admin/brand.index')">
<input type="text" value="{{ $product->brand->name ?? '' }}" id="brand-autocomplete" class="form-control wp-400 " />
@ -453,32 +521,8 @@
</div>
</x-admin::form.row>
{{--计量单位 语言切换弃用 改为下拉框选择--}}
<x-admin-form-select :title="__('product.unit_of_measurement')" name="unit" :value="old('unit', $product->unit ?? '')" :options="$unit_list" key="title" label="title" />
{{--<x-admin-form-input-locale :width="600" name="descriptions.*.unit" title="{{ __('product.unit_of_measurement') }}" :value="$descriptions" :required="true" />--}}
{{--贸易术语--}}
<x-admin-form-input name="trade_term" :title="__('product.trade_term')" :value="old('trade_term', $product->trade_term ?? '')" />
{{--销售方式--}}
<x-admin::form.row title="{{ __('product.sales_method') }}">
<div class="mb-1 mt-2">
<div class="form-check form-check-inline">
<input v-model="form.sales_method" class="form-check-input" id="sales_method-piece" type="radio" name="sales_method" value="piece">
<label class="form-check-label" for="sales_method-piece">{{ __('product.sales_method_piece') }}</label>
</div>
<div class="form-check form-check-inline">
<input v-model="form.sales_method" class="form-check-input" id="sales_method-batches" type="radio" name="sales_method" value="batches">
<label class="form-check-label" for="sales_method-batches">{{ __('product.sales_method_batches') }}</label>
</div>
</div>
</x-admin::form.row>
<template v-if="form.sales_method == 'batches'">
<x-admin::form.row :title="__('product.one_batch_is_equal_to')" required>
<div class="d-flex wp-400">
<input type="number" v-model="form.piece_to_batch" name="piece_to_batch" class="form-control" style="flex: 0 0 95px" />
<div style="width: 40px;line-height: 34px;text-align:center">{{ __('product.piece') }}</div>
</div>
</x-admin::form.row>
</template>
{{--状态--}}
<x-admin::form.row title="{{ __('product.product_type') }}">
@ -697,11 +741,16 @@
</div>
</div>
<div id="trade-term-img-content" style="display: none;">
<img class='trade-term-img' src='image/trade_term.png'>
</div>
@hook('admin.product.form.footer')
@endsection
@push('footer')
<script>
$(function () { $("[data-toggle='tooltip']").tooltip(); });
$('.submit-form').on('click', function () {
// 关闭多规格提交 清空 variables
if (!app.editing.isVariable) {
@ -737,7 +786,8 @@
numPrices: @json(old('numPrices', $product->numprices) ?? []),
minimum_order: {{$product->minimum_order ?? 0}},
sales_method: '{{$product->sales_method ?? 'piece'}}',
piece_to_batch: {{$product->piece_to_batch ?? 1}}
piece_to_batch: {{$product->piece_to_batch ?? 1}},
unit: '{{$product->unit ?? ''}}',
},
variablesBatch: {
@ -786,7 +836,6 @@
rules: {}
},
computed: {
// variant value 重复次数
variantValueRepetitions() {
@ -809,13 +858,11 @@
return (this.form.numPrices.length && this.form.price_setting === 'num') || this.form.price_setting === 'sku' || ''
}
},
beforeMount() {
if (this.form.variables.length) {
this.variablesBatch.variables = this.form.variables.map((v, i) => '');
}
},
watch: {
'source.variables': {
deep: true,
@ -838,15 +885,32 @@
if (this.isMove) return;
this.remakeSkus();
}
}
},
},
'form': {
deep: true,
handler: function(val) {
// 判断:多规格是否必须启用(直接下单产品,根据规格设置价格时必须启用多规格)
if(this.form.active == 1 && this.form.price_setting == 'sku'){
this.editing.isVariable = true;
}
}
},
'editing': {
deep: true,
handler: function(val) {
// 判断:多规格是否必须启用(直接下单产品,根据规格设置价格时必须启用多规格)
if(this.form.active == 1 && this.form.price_setting == 'sku'){
this.editing.isVariable = true;
}
}
},
},
created() {
if(this.form.numPrices.length === 0){
this.addNumPrices();
}
},
methods: {
addNumPrices() {
this.form.numPrices.push({num: '', price: ''});
@ -1249,9 +1313,17 @@
$('input[name="brand_id"]').val(item['value']);
}
});
$('#tradeTerm').popover({
trigger : 'hover',//鼠标以上时触发弹出提示框
html: true,//开启html 为true的话data-content里就能放html代码了
placement: 'bottom',
delay: { "show": 0, "hide": 100 },
content:"<img class='trade-term-img' src='image/trade_term.png'>"
});
});
</script lang="scss">
<style>
</script>
<style lang="scss">
.price_setting_by_num{
display: flex;
margin-left: 200px;

View File

@ -46,7 +46,8 @@ return [
'product_type' => 'Product type',
'transaction_info' => 'Transaction information',
'trade_term' => 'Trade Term',
'multi_specification_settings' => 'Multi specification settings',
'multi_specification_settings_help' => 'Directly placing an order for a product, multiple specifications must be enabled when setting prices based on specifications',
];

View File

@ -47,6 +47,7 @@ return [
'product_type' => '产品类型',
'transaction_info' => '交易信息',
'trade_term' => '贸易术语',
'multi_specification_settings' => '多规格设置',
'multi_specification_settings_help' => '直接下单产品,根据规格设置价格时必须启用多规格!',
];