相关后台商品配置和 前台ui

This commit is contained in:
pushuo 2023-01-06 17:22:24 +08:00
parent 6e8d7f295f
commit c1db80eaaa
14 changed files with 219 additions and 15 deletions

View File

@ -173,4 +173,66 @@ body.page-product-form {
}
}
}
.autocomplete-group-wrapper {
.inline-input {
width: 100%;
}
.item-group-wrapper {
padding: 10px;
min-height: 280px;
overflow: auto;
background-color: #f5f5f5;
// border: 1px solid #e3e3e3;
.item {
overflow: hidden;
position: relative;
padding: 5px 8px;
margin-bottom: 4px;
background: #fff;
border: 1px solid #eee;
cursor: move;
display: flex;
align-items: center; // flex-start | center
justify-content: space-between; // flex-end | center | space-between
&:hover {
border-color: #aaa;
}
div {
display: flex;
line-height: 1;
width: calc(100% - 16px);
align-items: center; // flex-start | center
i {
margin-right: 4px;
}
}
span {
font-size: 12px;
overflow: hidden;
padding: 2px 0;
text-overflow:ellipsis;
white-space: nowrap;
}
i {
// position: absolute;
color: #999;
font-weight: 400;
&.right {
cursor: pointer;
&:hover {
color: #222;
}
}
}
}
}
}
}

View File

@ -37,11 +37,13 @@
<li class="nav-item" role="presentation">
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#tab-seo" type="button" >SEO</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#tab-relations" type="button">{{ __('admin/product.product_relations') }}</button>
</li>
</ul>
<div class="card">
{{-- <div class="card-header"><h6 class="card-title">基础信息</h6></div> --}}
<div class="card-body">
<div class="card-body h-min-600">
<form novalidate class="needs-validation" action="{{ $product->id ? admin_route('products.update', $product) : admin_route('products.store') }}"
method="POST" id="app">
@csrf
@ -317,6 +319,7 @@
</div>
</x-admin::form.row>
</div>
<div class="tab-pane fade" id="tab-seo">
<h6 class="border-bottom pb-3 mb-4">SEO</h6>
<x-admin::form.row title="Meta title">
@ -344,8 +347,45 @@
@endforeach
</x-admin::form.row>
</div>
</div>
<div class="tab-pane fade" id="tab-relations">
<x-admin::form.row title="{{ __('admin/product.product_relations') }}">
<div class="module-edit-group wp-600">
<div class="autocomplete-group-wrapper">
<el-autocomplete
class="inline-input"
v-model="relations.keyword"
value-key="name"
size="small"
:fetch-suggestions="relationsQuerySearch"
placeholder="{{ __('admin/builder.modules_keywords_search') }}"
@select="relationsHandleSelect"
></el-autocomplete>
<div class="item-group-wrapper" v-loading="relations.loading">
<template v-if="relations.products.length">
<draggable
ghost-class="dragabble-ghost"
:list="relations.products"
:options="{animation: 330}"
>
<div v-for="(item, index) in relations.products" :key="index" class="item">
<div>
<i class="el-icon-s-unfold"></i>
<span>@{{ item.name }}</span>
</div>
<i class="el-icon-delete right" @click="relationsRemoveProduct(index)"></i>
<input type="text" :name="'relations['+ index +']'" v-model="item.id" class="form-control d-none">
</div>
</draggable>
</template>
<template v-else>{{ __('admin/builder.modules_please_products') }}</template>
</div>
</div>
</div>
</x-admin::form.row>
</div>
</div>
<x-admin::form.row title="">
<button type="submit" class="btn btn-primary mt-3 btn-lg">{{ __('common.save') }}</button>
@ -422,6 +462,12 @@
skus: @json($product->skus ?? []),
},
relations: {
keyword: '',
products: @json($relations ?? []),
loading: null,
},
source: {
variables: @json($product->variables ?? []),
languages: @json($languages ?? []),
@ -491,6 +537,23 @@
}
},
methods: {
relationsQuerySearch(keyword, cb) {
$http.get('products/autocomplete?name=' + encodeURIComponent(keyword), null, {hload:true}).then((res) => {
cb(res.data);
})
},
relationsHandleSelect(item) {
if (!this.relations.products.find(v => v == item.id)) {
this.relations.products.push(item);
}
this.relations.keyword = ""
},
relationsRemoveProduct(index) {
this.relations.products.splice(index, 1);
},
variantIsImage(e, index) {
if (!e) {
this.source.variables[index].values.forEach(v => {

View File

@ -22,4 +22,36 @@
display: block;
}
}
}
.swiper-style-plus {
position: relative;
.swiper-button-prev,.swiper-button-next {
width: 34px;
height: 37px;
color: #333;
@media (max-width: 768px) {
display: none;
}
&:after {
font-size: 22px;
}
}
.swiper-button-prev {
left: -50px;
}
.swiper-button-next {
right: -50px;
}
.swiper-pagination {
.swiper-pagination-bullet-active {
background: $primary;
}
}
}

View File

@ -13,6 +13,7 @@
text-align: center;
padding-bottom: .7rem;
transition: all 0.3s ease-in-out;
background-color: #fff;
.image {
margin-bottom: 10px;
@ -41,12 +42,14 @@
}
}
&:hover {
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
@media (min-width: 768px) {
&:hover {
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
.button-wrap {
bottom: 10px;
opacity: 1;
.button-wrap {
bottom: 10px;
opacity: 1;
}
}
}

View File

@ -26,6 +26,7 @@ return [
'basic_information' => 'grundlegende Informationen',
'product_details' => 'Produktdetails',
'product_relations' => 'bezogene Waren',
'stocks' => 'Warenbestand',
'model' => 'Modell',
'price' => 'Preis',

View File

@ -25,6 +25,7 @@ return [
'basic_information' => 'basic information',
'product_details' => 'Product details',
'product_relations' => 'Related goods',
'stocks' => 'goods inventory',
'model' => 'model',
'price' => 'price',

View File

@ -26,6 +26,7 @@ return [
'basic_information' => 'información básica',
'product_details' => 'Detalles de producto',
'product_relations' => 'bienes relacionados',
'stocks' => 'Existencias de materias primas',
'model' => 'modelo',
'price' => 'precio',

View File

@ -26,6 +26,7 @@ return [
'basic_information' => 'informations de base',
'product_details' => 'détails du produit',
'product_relations' => 'biens liés',
'stocks' => 'inventaire des marchandises',
'model' => 'maquette',
'price' => 'le prix',

View File

@ -26,6 +26,7 @@ return [
'basic_information' => 'informazioni di base',
'product_details' => 'Dettagli prodotto',
'product_relations' => 'beni correlati',
'stocks' => 'inventario merci',
'model' => 'modello',
'price' => 'prezzo',

View File

@ -26,6 +26,7 @@ return [
'basic_information' => '基本情報',
'product_details' => '商品の詳細',
'product_relations' => '関連商品',
'stocks' => '商品在庫',
'model' => 'モデル',
'price' => '価格',

View File

@ -26,6 +26,7 @@ return [
'basic_information' => 'основная информация',
'product_details' => 'Подробнее о продукте',
'product_relations' => 'сопутствующие товары',
'stocks' => 'инвентаризация товаров',
'model' => 'модель',
'price' => 'цена',

View File

@ -26,6 +26,7 @@ return [
'basic_information' => '基础信息',
'product_details' => '商品详情',
'product_relations' => '相关商品',
'stocks' => '商品库存',
'model' => '型号',
'price' => '价格',

View File

@ -26,6 +26,7 @@ return [
'basic_information' => '基礎信息',
'product_details' => '商品詳情',
'product_relations' => '相關商品',
'stocks' => '商品庫存',
'model' => '型號',
'price' => '價格',

View File

@ -164,6 +164,27 @@
</div>
</div>
</div>
@if ($relations)
<div class="relations-wrap mt-5">
<div class="container position-relative">
<div class="title text-center fs-1 mb-4">{{ __('admin/product.product_relations') }}</div>
<div class="product swiper-style-plus">
<div class="swiper relations-swiper">
<div class="swiper-wrapper">
@foreach ($relations as $item)
<div class="swiper-slide">
@include('shared.product', ['product' => $item])
</div>
@endforeach
</div>
</div>
<div class="swiper-button-prev relations-swiper-prev"></div>
<div class="swiper-button-next relations-swiper-next"></div>
</div>
</div>
</div>
@endif
@endsection
@push('add-scripts')
@ -317,20 +338,34 @@
slidesPerView: 6,
spaceBetween:3,
},
},
pagination: {
el: ".swiper-pagination",
clickable: true,
},
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
nextEl: '.new-feature-slideshow-next',
prevEl: '.new-feature-slideshow-prev',
},
observer: true,
observeParents: true
});
var relationsSwiper = new Swiper ('.relations-swiper', {
breakpoints:{
320: {
slidesPerView: 2,
spaceBetween: 10,
},
768: {
slidesPerView: 4,
spaceBetween: 30,
},
},
spaceBetween: 30,
// 如果需要前进后退按钮
navigation: {
nextEl: '.relations-swiper-next',
prevEl: '.relations-swiper-prev',
},
})
@if (is_mobile())
swiperMobile = new Swiper("#swiper-mobile", {
slidesPerView: 1,