版本合并、和客户修改后的版本合并

修改:商品编辑页面取消sku;起订量从规格中移除,统一设置起订量
修改:客服端显示最小起订量
This commit is contained in:
wuhui_zzw 2023-09-20 13:36:57 +08:00
parent 39cd329a47
commit b679d66adb
20 changed files with 90 additions and 41 deletions

Binary file not shown.

View File

@ -40,7 +40,7 @@ class LogisticsController extends Controller
'logistics' => $logistics,
'type' => 'logistics',
'default_countries' => $countries,
'default_countries_name' => is_array($countries) ? array_values($countries)[0]['name'] : ''
'default_countries_name' => is_array($countries) && count($countries) > 0 ? array_values($countries)[0]['name'] : ''
];
$data = hook_filter('admin.logistics.index.data', $data);

View File

@ -32,14 +32,20 @@ class ProductRequest extends FormRequest
*/
public function rules(): array
{
return [
$rules = [
'descriptions.*.name' => 'required|string|min:3|max:128',
'brand_id' => 'int',
'skus.*.sku' => 'required|string',
// 'skus.*.sku' => 'required|string',
'skus.*.price' => 'required|numeric',
'skus.*.origin_price' => 'required|numeric',
'skus.*.cost_price' => 'numeric',
// 'skus.*.cost_price' => 'numeric',
];
// 判断:最小起订量是否必填 直接下单产品 - 必填
if($this->active == 1){
$rules['minimum_order'] = 'required|numeric|gt:0';
}
return $rules;
}
public function attributes()
@ -47,10 +53,11 @@ class ProductRequest extends FormRequest
return [
'descriptions.*.name' => trans('product.name'),
'brand_id' => trans('product.brand'),
'skus.*.sku' => trans('product.sku'),
// 'skus.*.sku' => trans('product.sku'),
'skus.*.price' => trans('product.price'),
'skus.*.origin_price' => trans('product.origin_price'),
'skus.*.cost_price' => trans('product.cost_price'),
// 'skus.*.cost_price' => trans('product.cost_price'),
'minimum_order' => trans('product.minimum_order'),
];
}
}

View File

@ -24,9 +24,9 @@ class ProductResource extends JsonResource
return image_resize($image);
}, $this->images ?? []),
'name' => $this->description->name ?? '',
'model' => $masterSku->model,
'quantity' => $masterSku->quantity,
'price_formatted' => currency_format($masterSku->price),
'model' => $masterSku->model ?? '',
'quantity' => $masterSku->quantity ?? 0,
'price_formatted' => currency_format($masterSku->price ?? 0),
'active' => $this->active,
'position' => $this->position,
'url' => $this->url,

View File

@ -78,7 +78,7 @@ class ProductService
foreach ($data['skus'] as $index => $sku) {
$sku['position'] = $index;
$sku['origin_price'] = (float) $sku['origin_price'];
$sku['cost_price'] = (float) $sku['cost_price'];
$sku['cost_price'] = (float) ($sku['cost_price'] ?? 0);
$sku['quantity'] = (int) $sku['quantity'];
$skus[] = $sku;
}

View File

@ -11,7 +11,7 @@ class Product extends Base
use HasFactory;
use SoftDeletes;
protected $fillable = ['images', 'video', 'position', 'brand_id', 'tax_class_id', 'weight', 'weight_class', 'active', 'variables', 'price_setting', 'length', 'width', 'height'];
protected $fillable = ['images', 'video', 'position', 'brand_id', 'tax_class_id', 'weight', 'weight_class', 'active', 'variables', 'price_setting', 'length', 'width', 'height', 'minimum_order'];
protected $casts = [
'active' => 'boolean',

View File

@ -38,7 +38,7 @@ class InquiryDetail extends JsonResource{
];
}
$product = $productsku->product;
$description = $product->description;
$description = $product->description ?? '';
return [
'id' => $this->id,
'product_sku_id' => $this->product_sku_id,

View File

@ -47,7 +47,7 @@ class ProductSimple extends JsonResource
'in_wishlist' => $this->inCurrentWishlist->id ?? 0,
'price_setting' => $this->price_setting ?? '',
'numprices' => NumPricesDetail::collection($this->numprices)->jsonSerialize() ?? '',
'minimum_order' => $this->minimum_order,
'images' => array_map(function ($item) {
return image_resize($item, 400, 400);
}, $images),

BIN
placeholder-100x100.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -1 +0,0 @@
open_basedir=/www/wwwroot/wyyl.dev.zoomtk.com/:/tmp/

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

View File

@ -136,7 +136,23 @@
</div>
</x-admin::form.row>
<x-admin-form-switch-status name="active" :title="__('common.status')" :value="old('active', $product->active ?? 1)" />
{{--<x-admin-form-switch-status name="active" :title="__('common.status')" :value="old('active', $product->active ?? 1)" v-model="editing.isVariable" />--}}
<x-admin::form.row title="{{ __('common.status') }}">
<div class="mb-1 mt-2">
<div class="form-check form-check-inline">
<input v-model="form.active" class="form-check-input" id="active-1" type="radio" name="active" value="1">
<label class="form-check-label" for="active-1">{{ __('common.enable_status') }}</label>
</div>
<div class="form-check form-check-inline">
<input v-model="form.active" class="form-check-input" id="active-0" type="radio" name="active" value="0">
<label class="form-check-label" for="active-0">{{ __('common.disable_status') }}</label>
</div>
</div>
</x-admin::form.row>
@hook('admin.product.edit.extra')
@ -161,7 +177,7 @@
<div class="price_setting_by_num">
<div class="left">
<div class="head">
<div class="num" >最小起订量</div>
<div class="num" >{{__('admin/product.minimum_order')}}</div>
<div class="price">产品价格</div>
<div class="delete">删除</div>
</div>
@ -301,10 +317,10 @@
<i class="bi bi-plus fs-3 text-muted" v-else></i>
</div>
<input type="text" class="form-control me-2 bg-white" v-model="variablesBatch.model" placeholder="{{ __('admin/product.model') }}">
<input type="text" class="form-control me-2 bg-white" v-model="variablesBatch.sku" placeholder="sku">
{{--<input type="text" class="form-control me-2 bg-white" v-model="variablesBatch.sku" placeholder="sku">--}}
<input type="number" v-if="form.price_setting === 'sku'" class="form-control me-2 bg-white" v-model="variablesBatch.price" placeholder="{{ __('admin/product.price') }}">
<input type="number" v-if="form.price_setting === 'sku'" class="form-control me-2 bg-white" v-model="variablesBatch.origin_price" placeholder="{{ __('admin/product.origin_price') }}">
<input type="number" class="form-control me-2 bg-white" v-model="variablesBatch.cost_price" placeholder="{{ __('admin/product.cost_price') }}">
{{-- <input type="number" class="form-control me-2 bg-white" v-model="variablesBatch.cost_price" placeholder="{{ __('admin/product.cost_price') }}">--}}
<input type="number" class="form-control me-2 bg-white" v-model="variablesBatch.quantity" placeholder="{{ __('admin/product.quantity') }}">
<button type="button" class="btn btn-primary text-nowrap" @click="batchSettingVariant">{{ __('common.batch_setting') }}</button>
</div>
@ -316,10 +332,10 @@
</th>
<th width="106px">{{ __('common.image') }}</th>
<th class="w-min-100">{{ __('admin/product.model') }}</th>
<th class="w-min-100">sku</th>
{{--<th class="w-min-100">sku</th>--}}
<th v-if="form.price_setting === 'sku'" class="w-min-100">{{ __('admin/product.price') }}</th>
<th v-if="form.price_setting === 'sku'" class="w-min-100">{{ __('admin/product.origin_price') }}</th>
<th class="w-min-100">{{ __('admin/product.cost_price') }}</th>
{{--<th class="w-min-100">{{ __('admin/product.cost_price') }}</th>--}}
<th class="w-min-100">{{ __('admin/product.quantity') }}</th>
</thead>
<tbody>
@ -348,11 +364,11 @@
</td>
<td><input type="text" class="form-control" v-model="sku.model" :name="'skus[' + skuIndex + '][model]'"
placeholder="{{ __('admin/product.model') }}"></td>
<td>
{{-- <td>
<input type="text" class="form-control" v-model="sku.sku" :name="'skus[' + skuIndex + '][sku]'" placeholder="sku" :style="sku.is_default ? 'margin-top: 19px;' : ''" required>
<span role="alert" class="invalid-feedback">{{ __('common.error_required', ['name' => 'sku']) }}</span>
<span v-if="sku.is_default" class="text-success">{{ __('admin/product.default_main_product') }}</span>
</td>
</td>--}}
<td v-if="form.price_setting === 'sku'">
<input type="number" class="form-control" v-model="sku.price" :name="'skus[' + skuIndex + '][price]'" step="any"
placeholder="{{ __('admin/product.price') }}" required>
@ -365,10 +381,9 @@
</td>
<input type="hidden" :name="'skus[' + skuIndex + '][price]'" v-if="form.price_setting === 'num'" placeholder="variants" :value="form.numPrices.length !== 0 ? form.numPrices[0].price : ''">
<input type="hidden" :name="'skus[' + skuIndex + '][origin_price]'" v-if="form.price_setting === 'num'" placeholder="position" :value="form.numPrices.length !== 0 ? form.numPrices[form.numPrices.length - 1].price : ''">
<td><input type="number" class="form-control" v-model="sku.cost_price" :name="'skus[' + skuIndex + '][cost_price]'"
placeholder="{{ __('admin/product.cost_price') }}">
</td>
{{--<td>
<input type="number" class="form-control" v-model="sku.cost_price" :name="'skus[' + skuIndex + '][cost_price]'" placeholder="{{ __('admin/product.cost_price') }}">
</td>--}}
<td><input type="number" class="form-control" v-model="sku.quantity" :name="'skus[' + skuIndex + '][quantity]'"
placeholder="{{ __('admin/product.quantity') }}"></td>
</tr>
@ -380,22 +395,42 @@
<div class="invalid-feedback" style="font-size: 16px"><i class="bi bi-exclamation-circle-fill"></i> {{ __('admin/product.add_variable') }}</div>
</div>
</div>
{{--最小起订量--}}
{{-- 未开启根据数量设置价格、直接下单产品 --}}
<template v-if="form.price_setting === 'sku' && form.active == 1">
<x-admin::form.row :title="__('admin/product.minimum_order')" required>
<input type="number" name="minimum_order" v-model="form.minimum_order" class="form-control wp-400"/>
</x-admin::form.row>
</template>
{{-- 未开启根据数量设置价格、非直接下单商品 --}}
<template v-else-if="form.price_setting === 'sku' && form.active != 1">
<x-admin::form.row :title="__('admin/product.minimum_order')">
<input type="number" name="minimum_order" v-model="form.minimum_order" class="form-control wp-400" />
</x-admin::form.row>
</template>
{{--开启根据数量设置价格 - 数量固定为最小起订量--}}
<template v-else>
<x-admin::form.row :title="__('admin/product.minimum_order')" required>
<input type="number" name="minimum_order" :value="form.numPrices.length !== 0 ? form.numPrices[0].num : 0" class="form-control wp-400" readonly/>
</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]">
<x-admin-form-input name="skus[0][model]" :title="__('admin/product.model')" :value="old('skus.0.model', $product->skus[0]->model ?? '')" />
<x-admin-form-input name="skus[0][sku]" title="sku" :value="old('skus.0.sku', $product->skus[0]->sku ?? '')" required />
{{--<x-admin-form-input name="skus[0][sku]" title="sku" :value="old('skus.0.sku', $product->skus[0]->sku ?? '')" required />--}}
<span v-if="form.price_setting === 'sku'">
<x-admin-form-input name="skus[0][price]" type="number" :title="__('admin/product.price')" :value="old('skus.0.price', $product->skus[0]->price ?? '')" step="any" required />
<x-admin-form-input name="skus[0][origin_price]" type="number" :title="__('admin/product.origin_price')" :value="old('skus.0.origin_price', $product->skus[0]->origin_price ?? '')" step="any" required />
</span>
<x-admin-form-input name="skus[0][cost_price]" type="number" :title="__('admin/product.cost_price')" :value="old('skus.0.cost_price', $product->skus[0]->cost_price ?? '')" />
<x-admin-form-input name="skus[0][quantity]" type="number" :title="__('admin/product.quantity')" :value="old('skus.0.quantity', $product->skus[0]->quantity ?? '')" />
<input type="hidden" name="skus[0][price]" v-if="form.price_setting === 'num'" placeholder="variants" :value="form.numPrices.length !== 0 ? form.numPrices[0].price : ''">
<input type="hidden" name="skus[0][origin_price]" v-if="form.price_setting === 'num'" placeholder="position" :value="form.numPrices.length !== 0 ? form.numPrices[form.numPrices.length - 1].price : ''">
<input type="hidden" name="skus[0][variants]" placeholder="variants" value="">
<input type="hidden" name="skus[0][position]" placeholder="position" value="0">
{{--<x-admin-form-input name="skus[0][cost_price]" type="number" :title="__('admin/product.cost_price')" :value="old('skus.0.cost_price', $product->skus[0]->cost_price ?? '')" required />--}}
<input type="hidden" name="skus[0][is_default]" placeholder="is_default" value="1">
</div>
@endhookwrapper
@ -636,8 +671,10 @@
status: @json($product->skus[0]['status'] ?? false),
variables: @json($product->variables ?? []),
skus: @json(old('skus', $product->skus) ?? []),
active: {{(int)$product->active}},
price_setting: @json(old('price_setting', $product->price_setting) ?? 'sku'),
numPrices: @json(old('numPrices', $product->numprices) ?? []),
minimum_order: {{$product->minimum_order ?? 0}},
},
variablesBatch: {

View File

@ -56,4 +56,5 @@ return [
'confirm_batch_restore' => 'Confirm to restore the selected product? ',
'confirm_delete_restore' => 'Are you sure you want to empty the recycle bin? ',
'num_select' => 'Num select ',
'minimum_order' => 'Min Order'
];

View File

@ -28,4 +28,5 @@ return [
'active' => 'Active',
'inactive' => 'Inactive',
'has_been_inactive' => 'The product has been inactive',
'minimum_order' => 'Min Order'
];

View File

@ -28,9 +28,9 @@ return [
'product_relations' => '相关物流',
'stocks' => '物流库存',
'model' => '型号',
'price' => '',
'origin_price' => '价',
'cost_price' => '成本价',
'price' => '区间低价',
'origin_price' => '区间高价',
'cost_price' => '起订量',
'quantity' => '数量',
'enable_multi_spec' => '启用多规格',
'image_help' => '第一张图片将作为物流主图,支持同时上传多张图片,多张图片之间可随意调整位置',

View File

@ -32,9 +32,9 @@ return [
'product_relations' => '相关商品',
'stocks' => '商品库存',
'model' => '型号',
'price' => '',
'origin_price' => '价',
'cost_price' => '成本价',
'price' => '区间低价',
'origin_price' => '区间高价',
'cost_price' => '起订量',
'quantity' => '数量',
'enable_multi_spec' => '启用多规格',
'image_help' => '第一张图片将作为商品主图,支持同时上传多张图片,多张图片之间可随意调整位置',
@ -61,4 +61,5 @@ return [
'num' => '根据数量设置价格',
],
'num_select' => '数量选择',
'minimum_order' => '起订量'
];

View File

@ -12,9 +12,9 @@
return [
'name' => '名称',
'sku' => 'SKU',
'price' => '',
'origin_price' => '价',
'cost_price' => '成本价',
'price' => '区间低价',
'origin_price' => '区间高价',
'cost_price' => '起订量',
'brand' => '品牌',
'category' => '分类',
'model' => '型号',
@ -29,4 +29,5 @@ return [
'active' => '上架',
'inactive' => '下架',
'has_been_inactive' => '该商品已下架',
'minimum_order' => '起订量'
];

View File

@ -60,7 +60,8 @@
@endhookwrapper
<div class="price-wrap d-flex align-items-end" v-if="price_setting === 'sku'">
<div class="new-price fs-1 lh-1 fw-bold me-2">@{{ product.price_format }}</div>
<div class="old-price text-muted text-decoration-line-through" v-if="product.price != product.origin_price && product.origin_price !== 0">
<div class="new-price fs-1 lh-1 fw-bold me-2">-</div>
<div class="old-price fs-1 lh-1 fw-bold me-2" v-if="product.price != product.origin_price && product.origin_price !== 0">
@{{ product.origin_price_format }}
</div>
</div>

View File

@ -169,7 +169,8 @@
@hookwrapper('product.detail.price')
<div class="price-wrap d-flex align-items-end" v-if="price_setting === 'sku'">
<div class="new-price fs-1 lh-1 fw-bold me-2">@{{ product.price_format }}</div>
<div class="old-price text-muted text-decoration-line-through" v-if="product.price != product.origin_price && product.origin_price !== 0">
<div class="new-price fs-1 lh-1 fw-bold me-2">-</div>
<div class="old-price fs-1 lh-1 fw-bold me-2" v-if="product.price != product.origin_price && product.origin_price !== 0">
@{{ product.origin_price_format }}
</div>
</div>

View File

@ -73,9 +73,9 @@
@if ($product['price_setting'] === 'num')
<span class="price-new">{{$product['numprices'] != [] ? $product['numprices'][0]['num'] : 1}} pieces</span>
@else
<span class="price-new">1 pieces</span>
<span class="price-new">{{$product['minimum_order'] ?? 0}} pieces</span>
@endif
<span style="color:#aaa;margin-left:4px">(Min Order)</span>
<span style="color:#aaa;margin-left:4px">({{__('admin/product.minimum_order')}})</span>
</div>
@if (request('style_list') == 'list')