This commit is contained in:
pushuo 2022-07-21 18:42:02 +08:00
parent faf3d09084
commit db2ebdb8da
16 changed files with 639 additions and 109 deletions

View File

@ -6,6 +6,7 @@ use Beike\Admin\Http\Resources\ProductResource;
use Beike\Admin\Repositories\CategoryRepo;
use Beike\Models\Product;
use Beike\Admin\Services\ProductService;
use Beike\Repositories\LanguageRepo;
use Beike\Repositories\ProductRepo;
use Illuminate\Http\Request;
@ -73,6 +74,7 @@ class ProductController extends Controller
'product' => $product,
'descriptions' => $descriptions ?? [],
'category_ids' => $categoryIds ?? [],
'languages' => LanguageRepo::all(),
'source' => [
'categories' => CategoryRepo::flatten(locale()),
],

View File

@ -16,7 +16,7 @@ class ProductController extends Controller
$data = [
'product' => (new ProductDetail($product))->jsonSerialize(),
];
dd($data);
return view('product', $data);
}
}

View File

@ -34,6 +34,17 @@ body {
font-size: 12px;
}
.file-manager-box .layui-layer-title {
background-color: #293042;
color: #fff;
border-color: #404e72;
}
.file-manager-box .layui-layer-ico {
background: url("/image/close.png") no-repeat;
background-size: cover;
background-position: center center;
}
.main-content {
display: flex;
transition: margin-left 0.25s ease-in-out, left 0.25s ease-in-out, margin-right 0.25s ease-in-out, right 0.25s ease-in-out;
@ -537,3 +548,129 @@ body.page-login .btn:not(.btn-link):hover {
transform: scale(1.02);
color: #fff;
}
body.page-product-form .variants-producr-img {
width: 50px;
height: 50px;
border-radius: 2px;
border: 1px solid #eee;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
}
body.page-product-form .variant-value-img {
width: 30px;
height: 30px;
border-radius: 2px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
}
body.page-product-form .selectable-variants div[id^=selectable-variant-] {
border: 1px solid #eee;
border-radius: 4px;
margin-bottom: 10px;
}
body.page-product-form .selectable-variants .title {
margin-bottom: 12px;
display: flex;
align-items: center;
padding: 4px 10px;
background: #f5f5f5;
justify-content: space-between;
}
body.page-product-form .selectable-variants .title:hover .btn-link {
display: block;
}
body.page-product-form .selectable-variants .title > div {
display: flex;
align-items: center;
}
body.page-product-form .selectable-variants .title b {
border-right: 1px solid #f4f4f4;
padding-right: 10px;
}
body.page-product-form .selectable-variants .title .btn-link {
padding: 3px 12px;
display: none;
}
body.page-product-form .selectable-variants .variants-wrap {
padding: 0 10px;
display: flex;
flex-wrap: wrap;
}
body.page-product-form .selectable-variants .variants-wrap > div {
border: 1px solid #eee;
margin-right: 10px;
display: flex;
position: relative;
margin-bottom: 10px;
padding: 4px 6px;
cursor: pointer;
border-radius: 2px;
align-items: center;
}
body.page-product-form .selectable-variants .variants-wrap > div:active {
background-color: #f5f5f5;
}
body.page-product-form .selectable-variants .variants-wrap > div .value-img {
line-height: 1;
margin-right: 3px;
}
body.page-product-form .selectable-variants .variants-wrap > div .value-img a {
width: 26px;
display: flex;
height: 26px;
margin-right: 5px;
}
body.page-product-form .selectable-variants .variants-wrap > div:hover {
border-color: #fd560f;
}
body.page-product-form .selectable-variants .variants-wrap > div:hover .btn-remove {
display: block;
}
body.page-product-form .selectable-variants .variants-wrap > div .btn-remove {
position: absolute;
top: -9px;
right: -7px;
cursor: pointer;
font-size: 17px;
display: none;
background: #fff;
line-height: 1;
}
body.page-product-form .selectable-variants .variants-wrap > div .btn-remove:hover {
color: #d80000;
}
body.page-product-form .selectable-variants .variants-wrap > div .tools {
background: #fd560f;
top: -24px;
right: -31px;
display: none;
overflow: hidden;
}
body.page-product-form .selectable-variants .variants-wrap > div .tools .btn-link {
min-width: 27px;
text-align: center;
float: left;
padding: 0;
border: none;
display: inline-block;
color: #fff;
height: 30px;
}
body.page-product-form .selectable-variants .variants-wrap > div .tools .btn-link:hover {
background: #be3a02;
}
body.page-product-form .selectable-variants .variants-wrap > div .tools .btn-link.rank {
cursor: move;
}
body.page-product-form .selectable-variants .variants-wrap > div .name {
text-align: center;
min-width: 40px;
}
body.page-product-form .selectable-variants .variants-wrap > div .name + .btn-link {
padding-left: 5px;
}

View File

@ -12301,7 +12301,7 @@ textarea.form-control-lg {
align-items: center;
justify-content: space-between;
padding: 1rem 1rem;
border-bottom: 1px solid #dee2e6;
border-bottom: 1px solid #f3f3f3;
border-top-left-radius: calc(0.3rem - 1px);
border-top-right-radius: calc(0.3rem - 1px);
}
@ -12328,7 +12328,7 @@ textarea.form-control-lg {
align-items: center;
justify-content: flex-end;
padding: 0.75rem;
border-top: 1px solid #dee2e6;
border-top: 1px solid #f3f3f3;
border-bottom-right-radius: calc(0.3rem - 1px);
border-bottom-left-radius: calc(0.3rem - 1px);
}
@ -13586,7 +13586,7 @@ textarea.form-control-lg {
}
.border {
border: 1px solid #dee2e6 !important;
border: 1px solid #f3f3f3 !important;
}
.border-0 {
@ -13594,7 +13594,7 @@ textarea.form-control-lg {
}
.border-top {
border-top: 1px solid #dee2e6 !important;
border-top: 1px solid #f3f3f3 !important;
}
.border-top-0 {
@ -13602,7 +13602,7 @@ textarea.form-control-lg {
}
.border-end {
border-right: 1px solid #dee2e6 !important;
border-right: 1px solid #f3f3f3 !important;
}
.border-end-0 {
@ -13610,7 +13610,7 @@ textarea.form-control-lg {
}
.border-bottom {
border-bottom: 1px solid #dee2e6 !important;
border-bottom: 1px solid #f3f3f3 !important;
}
.border-bottom-0 {
@ -13618,7 +13618,7 @@ textarea.form-control-lg {
}
.border-start {
border-left: 1px solid #dee2e6 !important;
border-left: 1px solid #f3f3f3 !important;
}
.border-start-0 {

View File

@ -2065,6 +2065,29 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _js_http__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../js/http */ "./resources/js/http.js");
window.$http = _js_http__WEBPACK_IMPORTED_MODULE_0__["default"];
var base = document.querySelector('base').href;
$(document).on('click', '.open-file-manager', function (event) {
var $this = $(this);
layer.open({
type: 2,
title: '图片管理器',
shadeClose: false,
skin: 'file-manager-box',
scrollbar: false,
shade: 0.4,
area: ['1060px', '680px'],
content: "".concat(base, "/file_manager"),
success: function success(layerInstance, index) {
var iframeWindow = window[layerInstance.find("iframe")[0]["name"]];
iframeWindow.callback = function (images) {
$this.find('img').prop('src', images[0].url);
$this.next('input').val(images[0].path);
$this.next('input')[0].dispatchEvent(new Event('input'));
};
}
});
});
$(document).ready(function ($) {
$.ajaxSetup({
headers: {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

View File

@ -27,6 +27,20 @@ body {
font-size: 12px;
}
.file-manager-box {
.layui-layer-title {
background-color: #293042;
color: #fff;
border-color: #404e72;
}
.layui-layer-ico {
background: url('/image/close.png') no-repeat;
background-size: cover;
background-position: center center;
}
}
.main-content {
display: flex;
// flex-direction: column;

View File

@ -0,0 +1,167 @@
@charset "UTF-8";
body.page-product-form {
.variants-producr-img {
width: 50px;
height: 50px;
border-radius: 2px;
border: 1px solid #eee;
cursor: pointer;
display: flex;
align-items: center; // flex-start | center
justify-content: center; // flex-end | center | space-between
}
.variant-value-img {
width: 30px;
height: 30px;
border-radius: 2px;
cursor: pointer;
display: flex;
align-items: center; // flex-start | center
justify-content: center; // flex-end | center | space-between
}
.selectable-variants {
div[id^="selectable-variant-"] {
border: 1px solid #eee;
// padding: 10px;
border-radius: 4px;
margin-bottom: 10px;
}
.title {
margin-bottom: 12px;
display: flex;
align-items: center;
padding: 4px 10px;
background: #f5f5f5;
justify-content: space-between;
&:hover {
.btn-link {
display: block;
}
}
> div {
display: flex;
align-items: center;
}
b {
border-right: 1px solid #f4f4f4;
padding-right: 10px;
}
.btn-link {
padding: 3px 12px;
display: none;
}
}
.variants-wrap {
// overflow: hidden;
padding: 0 10px;
// display: flex;
display: flex;
flex-wrap: wrap;
> div {
border: 1px solid #eee;
// padding: 3px 8px;
margin-right: 10px;
// float: left;
display: flex;
position: relative;
margin-bottom: 10px;
padding: 4px 6px;
cursor: pointer;
border-radius: 2px;
align-items: center;
&:active {
background-color: #f5f5f5;
}
.value-img {
line-height: 1;
// padding: 2px;
margin-right: 3px;
a {
width: 26px;
display: flex;
height: 26px;
margin-right: 5px;
}
}
&:hover {
border-color: $primary;
.tools {
// display: block;
}
.btn-remove {
display: block;
}
}
.btn-remove {
position: absolute;
top: -9px;
right: -7px;
cursor: pointer;
font-size: 17px;
display: none;
background: #fff;
line-height: 1;
&:hover {
color: #d80000;
}
}
.tools {
// position: absolute;
background: $primary;
top: -24px;
right: -31px;
display: none;
overflow: hidden;
// z-index: -1;
// opacity: 0;
.btn-link {
min-width: 27px;
text-align: center;
float: left;
padding: 0;
border: none;
display: inline-block;
// display: none;
color: #fff;
height: 30px;
&:hover {
background: darken($primary, 15%);
}
&.rank {
cursor: move;
}
}
}
.name {
// border-right: 1px solid #eee;
text-align: center;
// padding: 0 5px 0 0;
min-width: 40px;
& +.btn-link {
padding-left: 5px;
// margin-right: 10px;
}
}
}
}
}
}

View File

@ -21,3 +21,4 @@ $primary: #fd560f;
@import 'form';
@import 'element-ui';
@import 'login';
@import 'page-product';

View File

@ -21,6 +21,7 @@ $form-floating-padding-y: .8rem;
$form-floating-height: 50px;
$btn-focus-width: 0;
$table-border-color: #e9ecef;
$border-color: #f3f3f3;
@import './bootstrap-icons';
@import 'node_modules/bootstrap-5.1.3/scss/bootstrap';

View File

@ -1,5 +1,30 @@
import http from "../../../js/http";
window.$http = http;
const base = document.querySelector('base').href;
$(document).on('click', '.open-file-manager', function(event) {
const $this = $(this);
layer.open({
type: 2,
title: '图片管理器',
shadeClose: false,
skin: 'file-manager-box',
scrollbar: false,
shade: 0.4,
area: ['1060px', '680px'],
content: `${base}/file_manager`,
success: function(layerInstance, index) {
var iframeWindow = window[layerInstance.find("iframe")[0]["name"]];
iframeWindow.callback = function(images) {
$this.find('img').prop('src', images[0].url);
$this.next('input').val(images[0].path)
$this.next('input')[0].dispatchEvent(new Event('input'));
}
}
});
});
$(document).ready(function ($) {
$.ajaxSetup({

View File

@ -13,7 +13,7 @@
<script src="{{ asset('vendor/axios/0.21.1/axios.min.js') }}"></script>
<script src="{{ mix('build/js/app.js') }}"></script> --}}
{{-- <script src="https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.8/index.min.js"></script> --}}
<script src="{{ asset('vendor/bootstrap/5.1.3/js/bootstrap.bundle.min.js') }}"></script>
<link href="{{ mix('/build/beike/admin/css/bootstrap.css') }}" rel="stylesheet">
<link rel="stylesheet" href="{{ asset('vendor/element-ui/2.6.2/css.css') }}">
<link href="{{ mix('build/beike/admin/css/app.css') }}" rel="stylesheet">

View File

@ -2,10 +2,6 @@
@section('title', '分类管理')
@push('header')
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.27.2/axios.min.js"></script>
@endpush
@section('content')
<div id="app">
<el-card class="box-card">

View File

@ -1,13 +1,17 @@
@extends('admin::layouts.master')
@section('body-class', 'page-product-form')
@push('header')
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.js"></script>
<script src="{{ asset('vendor/vue/Sortable.min.js') }}"></script>
<script src="{{ asset('vendor/vue/vuedraggable.js') }}"></script>
@endpush
@section('content')
<div class="card">
{{-- <div class="card-header"><h6 class="card-title">基础信息</h6></div> --}}
<div class="card-body">
<h2>product</h2>
<h5 class="border-bottom pb-3 mb-4">基础信息</h5>
<form action="{{ $product->id ? admin_route('products.update', $product) : admin_route('products.store') }}"
method="POST" id="app">
@csrf
@ -37,118 +41,218 @@
</x-admin::form.row>
<div>
<h2>skus</h2>
<input type="radio" v-model="editing.isVariable" :value="false"> 单规格
<input type="radio" v-model="editing.isVariable" :value="true"> 多规格
<div v-if="editing.isVariable">
<div>
<div v-for="(variant, variantIndex) in source.variables">
<div>
<input type="text" v-model="variant.name" placeholder="variant name">
<h5 class="border-bottom pb-3 mb-4">商品库存</h5>
<div v-for="(value, valueIndex) in variant.values">
<input v-model="variant.values[valueIndex].name" type="text" placeholder="variant value name">
</div>
<button type="button" @click="addVariantValue(variantIndex)">Add value</button>
</div>
<div class="form-group">
<div class="row align-items-center">
<label for="" class="col-sm-2 col-form-label">启用多规格</label>
<div class="col-sm-10">
<el-switch v-model="editing.isVariable"></el-switch>
</div>
<button type="button" @click="addVariant">Add variant</button>
</div>
<div v-if="form.skus.length">
<input v-if="form.skus.length" type="hidden" name="variables" :value="JSON.stringify(form.variables)">
<table>
<thead>
<th v-for="(variant, index) in form.variables" :key="'pv-header-' + index">
@{{ variant.name || 'No name' }}
</th>
<th>image</th>
<th>model</th>
<th>sku</th>
<th>price</th>
<th>orgin price</th>
<th>cost price</th>
<th>quantity</th>
</thead>
<tbody>
<tr v-for="(sku, skuIndex) in form.skus">
<template v-for="(variantValueIndex, j) in sku.variants">
<td v-if="skuIndex % variantValueRepetitions[j] == 0" :key="'pvv' + skuIndex + '-' + j"
:rowspan="variantValueRepetitions[j]">
<span>@{{ form.variables[j].values[variantValueIndex].name || 'No name' }}</span>
</td>
</template>
<td>
<input type="text" v-model="sku.image" :name="'skus[' + skuIndex + '][image]'"
placeholder="image">
<input type="hidden" :name="'skus[' + skuIndex + '][is_default]'" :value="skuIndex == 0 ? 1 : 0">
<input v-for="(variantValueIndex, j) in sku.variants" type="hidden"
:name="'skus[' + skuIndex + '][variants][' + j + ']'" :value="variantValueIndex">
</td>
<td><input type="text" v-model="sku.model" :name="'skus[' + skuIndex + '][model]'"
placeholder="model"></td>
<td><input type="text" v-model="sku.sku" :name="'skus[' + skuIndex + '][sku]'" placeholder="sku">
</td>
<td><input type="text" v-model="sku.price" :name="'skus[' + skuIndex + '][price]'"
placeholder="price"></td>
<td><input type="text" v-model="sku.origin_price" :name="'skus[' + skuIndex + '][origin_price]'"
placeholder="origin_price"></td>
<td><input type="text" v-model="sku.cost_price" :name="'skus[' + skuIndex + '][cost_price]'"
placeholder="cost_price">
</td>
<td><input type="text" v-model="sku.quantity" :name="'skus[' + skuIndex + '][quantity]'"
placeholder="quantity"></td>
</tr>
</tbody>
</table>
</div>
</div>
<div v-if="!editing.isVariable">
<div>
<input type="text" name="skus[0][image]" placeholder="image"
value="{{ old('skus.0.image', $product->skus[0]->image ?? '') }}">
<input type="text" name="skus[0][model]" placeholder="model"
value="{{ old('skus.0.model', $product->skus[0]->model ?? '') }}">
<input type="text" name="skus[0][sku]" placeholder="sku"
value="{{ old('skus.0.sku', $product->skus[0]->sku ?? '') }}">
<input type="text" name="skus[0][price]" placeholder="price"
value="{{ old('skus.0.price', $product->skus[0]->price ?? '') }}">
<input type="text" name="skus[0][origin_price]" placeholder="origin_price"
value="{{ old('skus.0.origin_price', $product->skus[0]->origin_price ?? '') }}">
<input type="text" name="skus[0][cost_price]" placeholder="cost_price"
value="{{ old('skus.0.cost_price', $product->skus[0]->cost_price ?? '') }}">
<input type="text" name="skus[0][quantity]" placeholder="quantity"
value="{{ old('skus.0.quantity', $product->skus[0]->quantity ?? '') }}">
<input type="hidden" name="skus[0][variants]" placeholder="variants" value="">
<input type="hidden" name="skus[0][position]" placeholder="position" value="0">
<input type="hidden" name="skus[0][is_default]" placeholder="is_default" value="1">
<div class="form-group">
<div class="row align-items-center">
<label for="" class="col-sm-2 col-form-label"></label>
<div class="col-sm-10">
<div v-if="editing.isVariable" class="selectable-variants">
<div>
<div v-for="(variant, variantIndex) in source.variables" :id="'selectable-variant-' + variantIndex">
<div class="title">
<div>
<b>@{{ variant.name[current_language_code] }}</b>
<el-link type="primary" @click="modalVariantOpenButtonClicked(variantIndex, null)">编辑</el-link>
<el-link type="danger" class="ms-2" @click="removeSourceVariant(variantIndex)">移除</el-link>
</div>
<div>
<el-checkbox v-model="variant.isImage" border size="mini" class="me-2 bg-white">添加规格图片</el-checkbox>
<el-button type="primary" plain size="mini" @click="modalVariantOpenButtonClicked(variantIndex, -1)">Add value</el-button>
</div>
</div>
<draggable
element="div"
v-if="variant.values.length"
class="variants-wrap"
@end="(e) => {swapSourceVariantValue(e, variantIndex)}"
ghost-class="dragabble-ghost"
:list="variant.values"
:options="{animation: 100}"
>
<div v-for="(value, value_index) in variant.values" :key="value_index" class="variants-item" @dblclick="modalVariantOpenButtonClicked(variantIndex, value_index)">
{{-- <div class="value-img" v-if="variant.isImage"> --}}
{{-- <a href="" :id="'value-img-' + i + '-' + value_index" data-toggle="image" data-no-preview> --}}
{{-- <img :src="thumbnail(value.image)" class="img-responsive" /> --}}
{{-- </a> --}}
{{-- </div> --}}
<div class="open-file-manager variant-value-img" v-if="variant.isImage">
<div>
<img :src="thumbnail(value.image)" class="img-fluid">
</div>
</div>
<input type="hidden" v-model="value.image">
<div class="btn-remove" @click="removeSourceVariantValue(variantIndex, value_index)"><i class="el-icon-error"></i></div>
<div class="name">
@{{ value.name[current_language_code] }}
</div>
</div>
</draggable>
<div v-else>
<div class="p-2" @click="addVariantValue(variantIndex)">请添加 Value</div>
</div>
</div>
<el-button type="primary" size="small" @click="modalVariantOpenButtonClicked(-1, null)" class="btn btn-xs mr-1 mb-1">Add variant</el-button>
</div>
<div v-if="form.skus.length" class="mt-3">
<input v-if="form.skus.length" type="hidden" name="variables" :value="JSON.stringify(form.variables)">
<table class="table table-bordered table-hover">
<thead>
<th v-for="(variant, index) in form.variables" :key="'pv-header-' + index">
@{{ variant.name[current_language_code] || 'No name' }}
</th>
<th>image</th>
<th>model</th>
<th>sku</th>
<th>price</th>
<th>orgin price</th>
<th>cost price</th>
<th>quantity</th>
</thead>
<tbody>
<tr v-for="(sku, skuIndex) in form.skus" :key="skuIndex">
<template v-for="(variantValueIndex, j) in sku.variants">
<td v-if="skuIndex % variantValueRepetitions[j] == 0" :key="'pvv' + skuIndex + '-' + j"
:rowspan="variantValueRepetitions[j]">
<span>@{{ form.variables[j].values[variantValueIndex].name[current_language_code] || 'No name' }}</span>
</td>
</template>
<td>
<div class="open-file-manager variants-producr-img">
<div>
<img :src="thumbnail(sku.image)" class="img-fluid">
</div>
</div>
<input type="hidden" class="form-control" v-model="sku.image" :name="'skus[' + skuIndex + '][image]'"
placeholder="image">
<input type="hidden" class="form-control" :name="'skus[' + skuIndex + '][is_default]'" :value="skuIndex == 0 ? 1 : 0">
<input v-for="(variantValueIndex, j) in sku.variants" type="hidden"
:name="'skus[' + skuIndex + '][variants][' + j + ']'" :value="variantValueIndex">
</td>
<td><input type="text" class="form-control" v-model="sku.model" :name="'skus[' + skuIndex + '][model]'"
placeholder="model"></td>
<td><input type="text" class="form-control" v-model="sku.sku" :name="'skus[' + skuIndex + '][sku]'" placeholder="sku">
</td>
<td><input type="text" class="form-control" v-model="sku.price" :name="'skus[' + skuIndex + '][price]'"
placeholder="price"></td>
<td><input type="text" class="form-control" v-model="sku.origin_price" :name="'skus[' + skuIndex + '][origin_price]'"
placeholder="origin_price"></td>
<td><input type="text" class="form-control" v-model="sku.cost_price" :name="'skus[' + skuIndex + '][cost_price]'"
placeholder="cost_price">
</td>
<td><input type="text" class="form-control" v-model="sku.quantity" :name="'skus[' + skuIndex + '][quantity]'"
placeholder="quantity"></td>
</tr>
</tbody>
</table>
</div>
</div>
<div v-if="!editing.isVariable">
<div>
<input type="text" name="skus[0][image]" placeholder="image"
value="{{ old('skus.0.image', $product->skus[0]->image ?? '') }}">
<input type="text" name="skus[0][model]" placeholder="model"
value="{{ old('skus.0.model', $product->skus[0]->model ?? '') }}">
<input type="text" name="skus[0][sku]" placeholder="sku"
value="{{ old('skus.0.sku', $product->skus[0]->sku ?? '') }}">
<input type="text" name="skus[0][price]" placeholder="price"
value="{{ old('skus.0.price', $product->skus[0]->price ?? '') }}">
<input type="text" name="skus[0][origin_price]" placeholder="origin_price"
value="{{ old('skus.0.origin_price', $product->skus[0]->origin_price ?? '') }}">
<input type="text" name="skus[0][cost_price]" placeholder="cost_price"
value="{{ old('skus.0.cost_price', $product->skus[0]->cost_price ?? '') }}">
<input type="text" name="skus[0][quantity]" placeholder="quantity"
value="{{ old('skus.0.quantity', $product->skus[0]->quantity ?? '') }}">
<input type="hidden" name="skus[0][variants]" placeholder="variants" value="">
<input type="hidden" name="skus[0][position]" placeholder="position" value="0">
<input type="hidden" name="skus[0][is_default]" placeholder="is_default" value="1">
</div>
</div>
</div>
</div>
</div>
</div>
<button type="submit" class="btn btn-primary">Save</button>
<el-dialog
title="编辑"
:visible.sync="dialogVariables.show"
width="400"
@close="closedialogVariablesFormDialog('form')"
:close-on-click-modal="false"
>
<el-form ref="form" :rules="rules" :model="dialogVariables.form" label-width="100px">
<el-form-item label="名称" required class="language-inputs">
<el-form-item :prop="'name.' + lang.code" :inline-message="true" v-for="lang, lang_i in source.languages" :key="lang_i"
:rules="[
{ required: true, message: '输入框不能为空', trigger: 'blur' },
]"
>
<el-input size="mini" v-model="dialogVariables.form.name[lang.code]" placeholder="请填写名称"><template slot="prepend">@{{lang.name}}</template></el-input>
</el-form-item>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="dialogVariablesFormSubmit('form')">保存</el-button>
<el-button @click="closedialogVariablesFormDialog('form')">取消</el-button>
</el-form-item>
</el-form>
</el-dialog>
</form>
</div>
</div>
@endsection
@push('footer')
<script>
Vue.prototype.thumbnail = function thumbnail(image, width, height) {
return '{{ asset('catalog') }}' + image;
};
var app = new Vue({
el: '#app',
data: {
current_language_code: '{{ current_language_code() }}',
form: {
variables: @json($product->variables ?? []),
skus: @json($product->skus ?? []),
},
source: {
variables: @json($product->variables ?? []),
languages: @json($languages ?? []),
},
editing: {
isVariable: @json(($product->variables ?? null) != null),
}
},
dialogVariables: {
show: false,
variantIndex: null,
variantValueIndex: null,
form: {
name: {}
},
},
rules: {}
},
computed: {
// variant value 重复次数
@ -184,18 +288,80 @@
}
},
methods: {
addVariant() {
this.source.variables.push({
name: '',
values: []
// addVariant() {
// this.source.variables.push({
// name: '',
// values: []
// });
// },
dialogVariablesFormSubmit(form) {
const name = JSON.parse(JSON.stringify(this.dialogVariables.form.name));
const variantIndex = this.dialogVariables.variantIndex;
const variantValueIndex = this.dialogVariables.variantValueIndex;
this.$refs[form].validate((valid) => {
if (!valid) {
this.$message.error('请检查表单是否填写正确');
return;
}
if (variantValueIndex !== null) {
if (variantValueIndex == -1) { // 创建
this.source.variables[variantIndex].values.push({name, image: ''});
} else {
this.source.variables[variantIndex].values[variantValueIndex].name = name;
}
} else {
if (variantIndex == -1) { // 创建
this.source.variables.push({name, values: [], isImage: false});
} else {
this.source.variables[variantIndex].name = name;
}
}
this.dialogVariables.show = false;
});
},
closedialogVariablesFormDialog(form) {
this.dialogVariables.show = false;
this.dialogVariables.variantIndex = null;
this.dialogVariables.variantValueIndex = null;
this.dialogVariables.form.name = {};
this.$refs[form].clearValidate();
},
modalVariantOpenButtonClicked(variantIndex, variantValueIndex) {
this.dialogVariables.variantIndex = variantIndex;
this.dialogVariables.variantValueIndex = variantValueIndex;
let name = null;
if (variantIndex === -1 || variantValueIndex === -1) {
name = {};
} else {
if (variantValueIndex !== null) {
// 编辑 variant value
name = this.source.variables[variantIndex].values[variantValueIndex].name;
} else {
// 编辑 variant
name = this.source.variables[variantIndex].name;
}
}
console.log(name)
this.dialogVariables.form.name = JSON.parse(JSON.stringify(name));
this.dialogVariables.show = true;
},
removeSourceVariant() {
},
addVariantValue(variantIndex) {
this.source.variables[variantIndex].values.push({
name: '',
image: ''
});
this.dialogVariables.show = true;
this.dialogVariables.type = 'variant-value';
this.dialogVariables.variantIndex = variantIndex;
},
remakeSkus() {

View File

@ -3,7 +3,6 @@
@section('title', '商品管理')
@push('header')
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.27.2/axios.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/underscore.js/1.13.3/underscore.min.js"></script>
@endpush
@ -11,8 +10,6 @@
<div id="product-app">
<div class="card">
<div class="card-body">
<div class="bg-light p-4">
<div class="row">
<div class="col-xxl-20 col-xl-3 col-lg-4 col-md-4 d-flex align-items-center mb-3">

View File

@ -232,6 +232,7 @@
this.source.variables.forEach((variable, index) => {
variable.values.forEach((value, value_index) => {
const selectedVariantsIndex = this.selectedVariantsIndex.slice(0);
selectedVariantsIndex[index] = value_index;
const selectedSku = skus.find(sku => sku.toString() == selectedVariantsIndex.toString());
if (selectedSku) {