!68 商品重量和多个bug修复

* Optimizing Blog ui
* Optimize breadcrumb position, optimize webpack.mix.js
* Modify request vip status update logic
* 后台商品列表默认按修改时间倒序,商品编辑保存无修改时更新商品修改时间
* wip
* wip
* 高级筛选属性多选问题处理
* 修复游客结账问题
* Add payment success page
* After repairing the data loss problem after dragging the order of specifications
* wip
* Fix the problem that the image of the deleted product in the backgroun…
* wip
* wip
* 占位图
* 更改地址重新加载运费,和重新计算order total运费功能
* wip
* wip
* wip
This commit is contained in:
mengwb 2023-03-31 02:56:57 +00:00 committed by Edward Yang
parent 634a4a2bd2
commit d074c123d9
54 changed files with 275 additions and 250 deletions

View File

@ -55,9 +55,3 @@ PUSHER_APP_CLUSTER=mt1
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
# 前端热更新, PROXY: vhost or path, HOST: 多设备实时
MIX_PROXY=beikeshop.test
MIX_HOST=192.168.0.122

View File

@ -21,6 +21,9 @@ class ProductController extends Controller
public function index(Request $request)
{
$requestData = $request->all();
if (!isset($requestData['sort'])) {
$requestData['sort'] = 'products.updated_at';
}
$productList = ProductRepo::list($requestData);
$products = ProductResource::collection($productList);
$productsFormat = $products->jsonSerialize();

View File

@ -29,6 +29,7 @@ class ProductService
$data['brand_id'] = (int) $data['brand_id'];
$data['variables'] = json_decode($data['variables']);
$product->fill($data);
$product->updated_at = now();
$product->save();
if ($isUpdating) {

View File

@ -98,6 +98,6 @@ class LanguageRepo
*/
public static function enabled()
{
return Language::query()->where('status', true)->get();
return Language::query()->where('status', true)->orderBy('sort_order', 'asc')->get();
}
}

View File

@ -199,17 +199,16 @@ class OrderRepo
$shippingAddress = Address::query()->findOrFail($shippingAddressId);
$paymentAddress = Address::query()->findOrFail($paymentAddressId);
$shippingAddress->country = $shippingAddress->country->name ?? '';
$shippingAddress->country_id = $shippingAddress->country->id ?? 0;
$paymentAddress->country = $paymentAddress->country->name ?? '';
$paymentAddress->country_id = $paymentAddress->country->id ?? 0;
$email = $customer->email;
$email = $customer->email;
} else {
$shippingAddress = new Address($current['guest_shipping_address'] ?? []);
$paymentAddress = new Address($current['guest_payment_address'] ?? []);
$email = $current['guest_shipping_address']['email'];
}
$shippingAddress->country = $shippingAddress->country->name ?? '';
$shippingAddress->country_id = $shippingAddress->country->id ?? 0;
$paymentAddress->country = $paymentAddress->country->name ?? '';
$paymentAddress->country_id = $paymentAddress->country->id ?? 0;
$shippingMethodCode = $current['shipping_method_code'] ?? '';
$paymentMethodCode = $current['payment_method_code'] ?? '';

View File

@ -115,7 +115,7 @@ class ProductRepo
$builder->orderByRaw("FIELD(products.id, {$productIds})");
}
// attr 格式:attr=10:10/13|11:34/23|3:4
// attr 格式:attr=10:10,13|11:34,23|3:4
if (isset($data['attr']) && $data['attr']) {
$attributes = self::parseFilterParamsAttr($data['attr']);
foreach ($attributes as $attribute) {
@ -190,7 +190,7 @@ class ProductRepo
return [
'attr' => $itemArr[0],
'value' => explode('/', $itemArr[1]),
'value' => explode(',', $itemArr[1]),
];
}, $attributes);
@ -199,7 +199,7 @@ class ProductRepo
public static function getFilterAttribute($data): array
{
$builder = self::getBuilder($data)
$builder = self::getBuilder(array_diff_key($data, ['attr'=>'', 'price'=>'']))
->select(['pa.attribute_id', 'pa.attribute_value_id'])
->with(['attributes.attribute.description', 'attributes.attribute_value.description'])
->leftJoin('product_attributes as pa', 'pa.product_id', 'products.id')

View File

@ -28,9 +28,9 @@ class ImageService
*/
public function __construct($image)
{
$this->placeholderImage = system_setting('base.placeholder');
$this->image = $image ?: $this->placeholderImage;
$this->imagePath = public_path($this->image);
$this->placeholderImage = system_setting('base.placeholder');
}
/**

View File

@ -13,6 +13,7 @@ namespace Beike\Shop\Http\Controllers;
use Beike\Shop\Services\CheckoutService;
use Illuminate\Http\Request;
use Beike\Repositories\OrderRepo;
class CheckoutController extends Controller
{
@ -59,4 +60,15 @@ class CheckoutController extends Controller
return hook_filter('checkout.confirm.data', $data);
}
public function success()
{
$order_number = request('order_number');
$customer = current_customer();
$order = OrderRepo::getOrderByNumber($order_number, $customer);
$data = hook_filter('account.order.show.data', ['order' => $order, 'html_items' => []]);
return view('checkout/success', $data);
}
}

View File

@ -43,7 +43,7 @@ class PageCategoryController extends Controller
'category' => new PageCategoryDetail($pageCategory),
'active_page_categories' => PageCategoryRepo::getActiveList(),
'breadcrumb' => $breadCrumb,
'category_pages' => $pageCategory->pages()->paginate(perPage()),
'category_pages' => $pageCategory->pages()->paginate(12),
];
return view('page_categories/show', $data);

View File

@ -78,6 +78,7 @@ Route::prefix('/')
Route::get('checkout', [CheckoutController::class, 'index'])->name('checkout.index');
Route::put('checkout', [CheckoutController::class, 'update'])->name('checkout.update');
Route::get('checkout/success', [CheckoutController::class, 'success'])->name('checkout.success');
Route::post('checkout/confirm', [CheckoutController::class, 'confirm'])->name('checkout.confirm');
Route::get('orders/{number}/success', [OrderController::class, 'success'])->name('orders.success');
Route::get('orders/{number}/pay', [OrderController::class, 'pay'])->name('orders.pay');

View File

@ -141,7 +141,7 @@ class CheckoutService
$weight = 0;
$selectedProducts = $this->selectedProducts;
foreach ($selectedProducts as $product) {
$weight += Weight::convert($product->product['weight'], $product->product['weight_class']);
$weight += Weight::convert($product->product['weight'] * $product['quantity'], $product->product['weight_class']);
}
return $weight;
@ -244,7 +244,8 @@ class CheckoutService
$shipmentCodes = array_merge($shipmentCodes, array_column($shipment['quotes'], 'code'));
}
if (!in_array($currentCart->shipping_method_code, $shipmentCodes)) {
$this->updateShippingMethod($shipmentCodes[0]);
$this->updateShippingMethod($shipmentCodes[0] ?? '');
$this->totalService->setShippingMethod($shipmentCodes[0] ?? '');
}
$data = [

View File

@ -61,7 +61,11 @@
console.log('Capture result', orderData, JSON.stringify(orderData, null, 2));
let captureStatus = orderData.status
if (captureStatus === 'COMPLETED') {
window.location.href = "{{ shop_route('account.order.show', $order->number) }}"
@if (current_customer())
window.location.href = "{{ shop_route('account.order.show', $order->number) }}"
@else
location = "{{ shop_route('checkout.success', ['order_number' => $order->number]) }}"
@endif
}
});
}

View File

@ -12,6 +12,13 @@ body.page-marketing {
.marketing-item {
box-shadow: none;
border: 1px solid #eee;
transition: .3s ease-in-out;
&:hover {
// border-color: $primary;
margin-top: -5px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
}
.plugin-img {
margin: -1rem -1rem 0 -1rem;

View File

@ -3,7 +3,7 @@
* @link https://beikeshop.com
* @Author pu shuo <pushuo@guangda.work>
* @Date 2022-08-22 18:32:26
* @LastEditTime 2023-02-17 17:57:40
* @LastEditTime 2023-03-30 17:30:08
*/
export default {
@ -129,22 +129,29 @@ export default {
// 设置vip更新提示
vipUpdateTips() {
const data = JSON.parse(Cookies.get('beike_vip') || null);
let data = JSON.parse(Cookies.get('beike_vip') || null);
const isHome = document.body.classList.contains('admin-home');
if (data) {
if (!data || isHome) {
$http.get(`${config.api_url}/api/vip?domain=${config.app_url}`, null, {hload: true}).then((res) => {
setVipUi(res)
Cookies.set('beike_vip', res, { expires: 1 });
})
}
setVipUi(data)
function setVipUi(data) {
if (data.vip) {
$('.vip-serve').addClass('active');
if (data.expiring) {
$('.vip-serve .expired-text').show().find('span').text(data.expired_at);
}
} else {
$('.vip-serve').removeClass('active');
$('.vip-serve .expired-text').hide();
}
} else {
$http.get(`${config.api_url}/api/vip?domain=${config.app_url}`, null, {hload: true}).then((res) => {
Cookies.set('beike_vip', res, { expires: 1 });
bk.vipUpdateTips();
})
}
},
}

View File

@ -2,6 +2,8 @@
@section('title', __('admin/common.admin_panel'))
@section('body-class', 'admin-home')
@push('header')
<script src="{{ asset('vendor/chart/chart.min.js') }}"></script>
@endpush

View File

@ -68,7 +68,7 @@
<div class="card mb-4">
<div class="card-header"><h6 class="card-title">{{ __('order.address_info') }}</h6></div>
<div class="card-body">
<table class="table ">
<table class="table">
<thead class="">
<tr>
<th>{{ __('order.shipping_address') }}</th>

View File

@ -5,8 +5,6 @@
@section('body-class', 'page-pages-form')
@push('header')
<script src="{{ asset('vendor/vue/Sortable.min.js') }}"></script>
<script src="{{ asset('vendor/vue/vuedraggable.js') }}"></script>
<script src="{{ asset('vendor/tinymce/5.9.1/tinymce.min.js') }}"></script>
@endpush
@ -17,7 +15,6 @@
@endsection
@section('content')
<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-content" type="button" >{{ __('admin/product.basic_information') }}</button>

View File

@ -71,6 +71,7 @@
<img :src="thumbnail(image)" class="img-fluid">
<input type="hidden" name="images[]" :value="image">
</div>
<div v-if="!form.images.length" class="d-none"><input type="hidden" name="images[]" value=""></div>
<div class="set-product-img wh-80" @click="addProductImages"><i class="bi bi-plus fs-1 text-muted"></i></div>
</draggable>
<div class="help-text mb-1 mt-1">{{ __('admin/product.image_help') }}</div>
@ -156,12 +157,6 @@
: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">
@ -751,17 +746,6 @@
});
},
swapSourceVariantValue(e, variantIndex) {
// 将 sku.variants[variantIndex] == e.oldIndex 的 sku[0] 与 sku.variants[variantIndex] == e.newIndex 的 sku[1] 交换顺序
this.form.skus.forEach(function(sku) {
const oldIndex = sku.variants[variantIndex];
const newIndex = sku.variants[variantIndex] == e.oldIndex ? e.newIndex.toString() : e.oldIndex.toString()
sku.variants[variantIndex] = newIndex;
});
this.remakeSkus()
},
closedialogVariablesFormDialog(form) {
this.dialogVariables.show = false;
this.dialogVariables.variantIndex = null;
@ -772,9 +756,6 @@
removeSourceVariantValue(variantIndex, variantValueIndex) {
this.source.variables[variantIndex].values.splice(variantValueIndex, 1);
// this.form.variants = this.validSourceVariants;
},
modalVariantOpenButtonClicked(variantIndex, variantValueIndex) {
@ -915,6 +896,24 @@
this.form.skus = skus;
},
// 规格值拖拽
swapSourceVariantValue(e, variantIndex) {
this.form.skus.forEach(function(sku) {
const oldIndex = parseInt(sku.variants[variantIndex]);
if (oldIndex == e.oldIndex) {
sku.variants[variantIndex] = e.newIndex.toString();
} else if (oldIndex > e.oldIndex && oldIndex <= e.newIndex) {
sku.variants[variantIndex] = (oldIndex - 1).toString();
} else if (oldIndex < e.oldIndex && oldIndex >= e.newIndex) {
sku.variants[variantIndex] = (oldIndex + 1).toString();
} else {
sku.variants[variantIndex] = oldIndex.toString();
}
});
this.remakeSkus()
},
}
});

View File

@ -31,6 +31,7 @@ footer {
.icon {
width: 34px;
flex: 0 0 34px;
margin-right: 14px;
}
@ -89,9 +90,5 @@ footer {
@media (max-width:768px) {
padding: 10px 0;
}
.right-img {
max-height: 42px;
}
}
}

View File

@ -14,21 +14,6 @@
padding-left: 0;
}
a {
overflow: hidden;
display: block;
img {
transition: .3s ease-in-out;
}
&:hover {
img {
transform: rotate(6deg) scale(1.3);
}
}
}
.module-image-plus-top {
display: flex;
@ -47,4 +32,21 @@
padding-right: 0;
padding-left: 0;
}
}
.banner-magnify-hover {
.image-wrap {
overflow: hidden;
display: block;
img {
transition: .3s ease-in-out;
}
&:hover {
img {
transform: rotate(6deg) scale(1.3);
}
}
}
}

View File

@ -19,7 +19,7 @@ return [
'pending_payment' => 'Pending Payment',
'pending_send' => 'To be delivered',
'pending_receipt' => 'Pending Receipt',
'after_sales' => 'After Sales',
'after_sales' => 'RMA',
'no_order' => "You don't have an order yet!",
'to_buy' => 'To place an order',
'order_number' => 'Order Number',
@ -35,7 +35,7 @@ return [
'edit' => [
'index' => 'Edit',
'modify_avatar' => 'Modify Avatar',
'modify_avatar' => 'Profile Picture',
'suggest' => 'Upload a JPG or PNG image. 300 x 300 is recommended.',
'name' => 'Name',
'email' => 'Email',
@ -72,7 +72,7 @@ return [
'state' => 'State',
'order_amount' => 'Order Amount',
'order_items' => 'Order Items',
'apply_after_sales' => 'Apply for after-sales',
'apply_after_sales' => 'Apply for RMA',
'order_total' => 'Order Total',
'logistics_status' => 'Logistics Status',
'order_status' => 'Order Status',
@ -114,7 +114,7 @@ return [
],
'rma' => [
'index' => 'Rma',
'index' => 'RMA',
'commodity' => 'Commodity',
'quantity' => 'Quantity',
'service_type' => 'Service Type',
@ -127,7 +127,7 @@ return [
],
'rma_form' => [
'index' => 'Submit after-sales information',
'index' => 'Submit RMA information',
'service_type' => 'Service Type',
'return_quantity' => 'Return Quantity',
'unpacked' => 'Unpacked',

View File

@ -29,6 +29,7 @@ return [
'enter_city' => 'Please fill in the city ',
'check_form' => 'Please check that the form is filled out correctly',
'error_payment_address' => 'Please select a billing address',
'checkout_success_title' => 'Thank you for your order!',
'payment' => [
'index' => 'Please Pay',

View File

@ -29,6 +29,7 @@ return [
'enter_city' => '请填写城市',
'check_form' => '请检查表单是否填写正确',
'error_payment_address' => '请选择账单地址',
'checkout_success_title' => '订单已付款成功!',
'payment' => [
'index' => '请付款',

View File

@ -29,6 +29,7 @@ return [
'enter_city' => '請填寫城市',
'check_form' => '請檢查表單是否填寫正確',
'error_payment_address' => '請選擇賬單地址',
'checkout_success_title' => '訂單已付款成功!',
'payment' => [
'index' => '請付款',

View File

@ -3,14 +3,11 @@
@section('body-class', 'page-account')
@section('content')
<x-shop-breadcrumb type="static" value="account.index" />
<div class="container">
<x-shop-breadcrumb type="static" value="account.index" />
<div class="row">
<x-shop-sidebar />
<div class="col-12 col-md-9">
@if (\Session::has('success'))
<div class="alert alert-success">

View File

@ -9,10 +9,9 @@
@endpush
@section('content')
<x-shop-breadcrumb type="static" value="account.addresses.index" />
<div class="container" id="address-app">
<x-shop-breadcrumb type="static" value="account.addresses.index" />
<div class="row">
<x-shop-sidebar />

View File

@ -8,10 +8,9 @@
@endpush
@section('content')
<x-shop-breadcrumb type="static" value="account.edit.index" />
<div class="container" id="address-app">
<x-shop-breadcrumb type="static" value="account.edit.index" />
<div class="row">
<x-shop-sidebar />

View File

@ -10,10 +10,9 @@
@section('content')
<x-shop-breadcrumb type="static" value="forgotten.index" />
<div class="container" id="page-forgotten" v-cloak>
<x-shop-breadcrumb type="static" value="forgotten.index" />
<div class="row my-5 justify-content-md-center">
<div class="col-lg-5 col-xxl-4">
<div class="card">

View File

@ -10,9 +10,10 @@
@section('content')
<x-shop-breadcrumb type="static" value="login.index" />
<div class="{{ request('iframe') ? 'container-fluid form-iframe mt-5' : 'container' }}" id="page-login" v-cloak>
@if (!request('iframe'))
<x-shop-breadcrumb type="static" value="login.index" />
<div class="hero-content pb-5 text-center"><h1 class="hero-heading">{{ __('shop/login.index') }}</h1></div>
@endif

View File

@ -3,15 +3,14 @@
@section('body-class', 'page-account-order-list')
@section('content')
<x-shop-breadcrumb type="static" value="account.order.index" />
<div class="container">
<x-shop-breadcrumb type="static" value="account.order.index" />
<div class="row">
<x-shop-sidebar />
<div class="col-12 col-md-9">
<div class="card mb-4 account-card order-wrap">
<div class="card mb-4 account-card order-wrap h-min-600">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="card-title">{{ __('shop/account.order.index') }}</h5>
</div>

View File

@ -3,10 +3,9 @@
@section('body-class', 'page-account-order-info')
@section('content')
<x-shop-breadcrumb type="order" value="{{ $order->number }}" />
<div class="container">
<x-shop-breadcrumb type="order" value="{{ $order->number }}" />
<div class="row">
<x-shop-sidebar />

View File

@ -2,26 +2,13 @@
@section('body-class', 'page-account-rmas')
@push('header')
{{-- <script src="{{ asset('vendor/vue/2.7/vue' . (!config('app.debug') ? '.min' : '') . '.js') }}"></script> --}}
@endpush
@section('content')
<x-shop-breadcrumb type="static" value="account.rma.index" />
<div class="container" id="address-app">
<x-shop-breadcrumb type="static" value="account.rma.index" />
{{-- <nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="#">Home</a></li>
<li class="breadcrumb-item active" aria-current="page">Library</li>
</ol>
</nav> --}}
<div class="row">
<x-shop-sidebar/>
<div class="col-12 col-md-9">
<div class="card h-min-600">
<div class="card-header d-flex justify-content-between align-items-center">
@ -42,8 +29,6 @@
<form action="{{ shop_route('account.rma.store') }}" method="POST">
@csrf
{{-- {{ method_field('put') }} --}}
@if (session('success'))
<x-shop-alert type="success" msg="{{ session('success') }}" class="mt-4"/>
@endif

View File

@ -3,10 +3,9 @@
@section('body-class', 'page-account-rmas')
@section('content')
<x-shop-breadcrumb type="static" value="account.rma.index" />
<div class="container">
<x-shop-breadcrumb type="static" value="account.rma.index" />
<div class="row">
<x-shop-sidebar />
<div class="col-12 col-md-9">

View File

@ -7,10 +7,9 @@
@endpush
@section('content')
<x-shop-breadcrumb type="rma" value="{{ $rma->id }}" />
<div class="container" id="address-app">
<x-shop-breadcrumb type="rma" value="{{ $rma->id }}" />
<div class="row">
<x-shop-sidebar />

View File

@ -3,9 +3,9 @@
@section('body-class', 'page-account-wishlist')
@section('content')
<div class="container">
<x-shop-breadcrumb type="static" value="account.wishlist.index" />
<x-shop-breadcrumb type="static" value="account.wishlist.index" />
<div class="container">
<div class="row">
<x-shop-sidebar />

View File

@ -3,18 +3,14 @@
@section('title', $brand->name)
@section('content')
<x-shop-breadcrumb type="brand" :value="$brand" />
<div class="container">
<div class="row">
@foreach ($products_format as $product)
<div class="col-6 col-md-3">@include('shared.product')</div>
@endforeach
</div>
<x-shop-breadcrumb type="brand" :value="$brand" />
<div class="row">
@foreach ($products_format as $product)
<div class="col-6 col-md-3">@include('shared.product')</div>
@endforeach
</div>
{{ $products->links('shared/pagination/bootstrap-4') }}
{{ $products->links('shared/pagination/bootstrap-4') }}
</div>
@endsection
@endsection

View File

@ -2,9 +2,9 @@
@section('body-class', 'page-brands')
@section('content')
<div class="container">
<x-shop-breadcrumb type="static" value="brands.index" />
<x-shop-breadcrumb type="static" value="brands.index" />
<div class="container">
<p class="fw-bold fs-3 d-flex justify-content-center mb-4">{{ __('shop/brands.index') }}</p>
<ul class="list-group list-group-horizontal mb-5 curser-list">

View File

@ -10,10 +10,9 @@
@endpush
@section('content')
<x-shop-breadcrumb type="static" value="carts.index" />
<div class="container" id="app-cart" v-cloak>
<x-shop-breadcrumb type="static" value="carts.index" />
<div class="row mt-1 justify-content-center mb-2">
<div class="col-12 col-md-9">@include('shared.steps', ['steps' => 1])</div>
</div>

View File

@ -14,7 +14,7 @@
<i class="bi {{ $cart['selected'] ? 'bi-check-circle-fill' : 'bi-circle' }}" data-id="{{ $cart['cart_id'] }}"></i>
</div>
<div class="product-info d-flex align-items-center">
<div class="left"><a href="{{ shop_route('products.show', $cart['product_id']) }}" class="d-flex justify-content-between align-items-center h-100"><img src="{{ $cart['image'] }}" class="img-fluid"></a></div>
<div class="left"><a href="{{ shop_route('products.show', $cart['product_id']) }}" class="d-flex justify-content-between align-items-center h-100"><img src="{{ $cart['image'] ?: image_resize('', 160, 160) }}" class="img-fluid"></a></div>
<div class="right flex-grow-1">
<a href="{{ shop_route('products.show', $cart['product_id']) }}" class="name fs-sm fw-bold mb-2 text-dark text-truncate-2" title="{{ $cart['name'] }}">{{ $cart['name'] }}</a>
<div class="text-muted mb-1 text-size-min">{{ $cart['variant_labels'] }}</div>

View File

@ -9,10 +9,9 @@
@endpush
@section('content')
<x-shop-breadcrumb type="category" :value="$category" />
<div class="container">
<x-shop-breadcrumb type="category" :value="$category" />
<div class="row">
<div class="col-12 col-lg-3 pe-lg-4 left-column d-none d-lg-block">
<div class="x-fixed-top">@include('shared.filter_sidebar_block')</div>
@ -137,7 +136,7 @@
let checkedAtValues = [];
item.values.forEach((val) => val.selected ? checkedAtValues.push(val.id) : '')
if (checkedAtValues.length) {
filterAtKey.push(`${item.id}:${checkedAtValues.join('/')}`)
filterAtKey.push(`${item.id}:${checkedAtValues.join(',')}`)
}
})

View File

@ -10,10 +10,9 @@
@endpush
@section('content')
<x-shop-breadcrumb type="static" value="checkout.index" />
<div class="container">
<x-shop-breadcrumb type="static" value="checkout.index" />
<div class="row mt-1 justify-content-center">
<div class="col-12 col-md-9">@include('shared.steps', ['steps' => 2])</div>
</div>
@ -44,7 +43,7 @@
<div class="checkout-black">
<h5 class="checkout-title">{{ __('shop/checkout.delivery_method') }}</h5>
<div class="radio-line-wrap">
<div class="radio-line-wrap" id="shipping-methods-wrap">
@foreach ($shipping_methods as $methods)
@foreach ($methods['quotes'] as $shipping)
<div class="radio-line-item {{ $shipping['code'] == $current['shipping_method_code'] ? 'active':'' }}" data-key="shipping_method_code" data-value="{{ $shipping['code'] }}">
@ -123,18 +122,17 @@
@push('add-scripts')
<script>
$(document).ready(function() {
$('.radio-line-item').click(function(event) {
$(document).on('click', '.radio-line-item', function(event) {
const key = $(this).data('key');
const value = $(this).data('value');
let html = '';
$http.put('/checkout', {[key]: value}).then((res) => {
$(this).addClass('active').siblings().removeClass('active')
res.totals.forEach((item) => {
html += `<li><span>${item.title}</span><span>${item.amount_format}</span></li>`
})
updateTotal(res.totals)
$('ul.totals').html(html);
if (typeof checkoutPutCallback === 'function') {
checkoutPutCallback(res)
}
})
});
@ -158,5 +156,37 @@
bk.openLogin();
});
});
function updateTotal(totals) {
let html = '';
totals.forEach((item) => {
html += `<li><span>${item.title}</span><span>${item.amount_format}</span></li>`
})
$('ul.totals').html(html);
}
function updateShippingMethods(data, shipping_method_code) {
let html = '';
data.forEach((methods) => {
methods.quotes.forEach((quote) => {
html += `<div class="radio-line-item d-flex align-items-center ${shipping_method_code == quote.code ? 'active' : ''}" data-key="shipping_method_code" data-value="${quote.code}">
<div class="left">
<span class="radio"></span>
<img src="${quote.icon}" class="img-fluid">
</div>
<div class="right ms-3">
<div class="title">${quote.name}</div>
<div class="sub-title">${quote.description}</div>
<div class="mt-2">${quote.html || ''}</div>
</div>
</div>`;
})
})
$('#shipping-methods-wrap').html(html);
}
</script>
@endpush

View File

@ -229,7 +229,7 @@
if (!this.source.isLogin) {
let data = {[this.dialogAddress.type]: form}
if (this.source.guest_payment_address === null && this.source.guest_shipping_address === null) {
if (this.same_as_shipping_address) {
data = {
guest_shipping_address: form,
guest_payment_address: form
@ -246,6 +246,8 @@
}
this.source[this.dialogAddress.type] = res.current[this.dialogAddress.type];
}
updateTotal(res.totals)
updateShippingMethods(res.shipping_methods, res.current.shipping_method_code)
this.$message.success('{{ __('common.edit_success') }}');
this.$refs['address-dialog'].closeAddressDialog()
})
@ -256,10 +258,10 @@
this.source.addresses[this.dialogAddress.index] = res.data
} else {
this.source.addresses.push(res.data)
this.updateCheckout(res.data.id, this.dialogAddress.type)
this.form[this.dialogAddress.type] = res.data.id
}
this.updateCheckout(res.data.id, this.dialogAddress.type)
this.dialogAddress.index = null;
this.$forceUpdate()
this.$refs['address-dialog'].closeAddressDialog()
@ -268,9 +270,9 @@
},
updateCheckout(id, key) {
if (this.form[key] === id && key != 'same_as_shipping_address') {
return
}
// if (this.form[key] === id && key != 'same_as_shipping_address') {
// return
// }
if (key == 'shipping_address_id' && this.same_as_shipping_address) {
this.form.payment_address_id = id
@ -282,6 +284,9 @@
this.form = res.current
this.source.totals = res.totals
updateTotal(res.totals)
updateShippingMethods(res.shipping_methods, res.current.shipping_method_code)
this.isAllAddress = false
this.isAllAddressPayment = false
})

View File

@ -1,15 +1,17 @@
@unless ($breadcrumbs->isEmpty())
<div class="breadcrumb-wrap">
<div class="container">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
@foreach ($breadcrumbs as $breadcrumb)
@if (isset($breadcrumb['url']) && $breadcrumb['url'])
<li class="breadcrumb-item"><a href="{{ $breadcrumb['url'] }}">{{ $breadcrumb['title'] }}</a></li>
@else
<li class="breadcrumb-item active" aria-current="page">{{ $breadcrumb['title'] }}</li>
@endif
@endforeach
</ol>
<ol class="breadcrumb">
@foreach ($breadcrumbs as $breadcrumb)
@if (isset($breadcrumb['url']) && $breadcrumb['url'])
<li class="breadcrumb-item"><a href="{{ $breadcrumb['url'] }}">{{ $breadcrumb['title'] }}</a></li>
@else
<li class="breadcrumb-item active" aria-current="page">{{ $breadcrumb['title'] }}</li>
@endif
@endforeach
</ol>
</nav>
@endunless
</div>
</div>
@endunless

View File

@ -1,11 +1,11 @@
<section class="module-item {{ $design ? 'module-item-design' : ''}}" id="module-{{ $module_id }}">
@include('design._partial._module_tool')
<div class="module-image-banner module-info mb-3 mb-md-5">
<div class="module-image-banner banner-magnify-hover module-info mb-3 mb-md-5">
<div class="container">
<div class="row">
@foreach ($content['images'] as $item)
<div class="col-12 col-md-6 mb-2 mb-xl-0"><a href="{{ $item['link']['link'] ?: 'javascript:void(0)' }}"><img src="{{ $item['image'] }}" class="img-fluid"></a></div>
<div class="col-12 col-md-6 mb-2 mb-xl-0"><a class="image-wrap" href="{{ $item['link']['link'] ?: 'javascript:void(0)' }}"><img src="{{ $item['image'] }}" class="img-fluid"></a></div>
@endforeach
</div>
</div>

View File

@ -1,11 +1,11 @@
<section class="module-item {{ $design ? 'module-item-design' : ''}}" id="module-{{ $module_id }}">
@include('design._partial._module_tool')
<div class="module-image-banner module-info mb-3 mb-md-5">
<div class="module-image-banner banner-magnify-hover module-info mb-3 mb-md-5">
<div class="container">
<div class="row">
@foreach ($content['images'] as $item)
<div class="col-12 col-md-4"><a href="{{ $item['link']['link'] ?: 'javascript:void(0)' }}"><img src="{{ $item['image'] }}" class="img-fluid"></a></div>
<div class="col-12 col-md-4"><a class="image-wrap" href="{{ $item['link']['link'] ?: 'javascript:void(0)' }}"><img src="{{ $item['image'] }}" class="img-fluid"></a></div>
@endforeach
</div>
</div>

View File

@ -1,18 +1,18 @@
<section class="module-item {{ $design ? 'module-item-design' : ''}}" id="module-{{ $module_id }}">
@include('design._partial._module_tool')
<div class="module-image-plus module-info mb-3 mb-md-5">
<div class="module-image-plus banner-magnify-hover module-info mb-3 mb-md-5">
<div class="container">
<div class="row">
<div class="col-md-6 col-12 mb-3 mb-md-0">
<a href="{{ $content['images'][0]['link']['link'] ?? '' }}"><img src="{{ $content['images'][0]['image'] }}" class="img-fluid"></a>
<a class="image-wrap" href="{{ $content['images'][0]['link']['link'] ?? '' }}"><img src="{{ $content['images'][0]['image'] }}" class="img-fluid"></a>
</div>
<div class="col-md-6 col-12">
<div class="module-image-plus-top">
<a href="{{ $content['images'][1]['link']['link'] ?? '' }}"><img src="{{ $content['images'][1]['image'] }}" class="img-fluid"></a>
<a href="{{ $content['images'][2]['link']['link'] ?? '' }}" class="right"><img src="{{ $content['images'][2]['image'] }}" class="img-fluid"></a>
<a class="image-wrap" href="{{ $content['images'][1]['link']['link'] ?? '' }}"><img src="{{ $content['images'][1]['image'] }}" class="img-fluid"></a>
<a href="{{ $content['images'][2]['link']['link'] ?? '' }}" class="right image-wrap"><img src="{{ $content['images'][2]['image'] }}" class="img-fluid"></a>
</div>
<div class="module-image-plus-bottom"><a href="{{ $content['images'][3]['link']['link'] ?? '' }}"><img src="{{ $content['images'][3]['image'] }}" class="img-fluid"></a></div>
<div class="module-image-plus-bottom"><a class="image-wrap" href="{{ $content['images'][3]['link']['link'] ?? '' }}"><img src="{{ $content['images'][3]['image'] }}" class="img-fluid"></a></div>
</div>
</div>
</div>

View File

@ -90,7 +90,7 @@
</div>
</div>
@if (isset($footer_content['bottom']['image']) && $footer_content['bottom']['image'])
<div class="col-auto right-img">
<div class="col-auto right-img py-2">
<img src="{{ image_origin($footer_content['bottom']['image']) }}" class="img-fluid">
</div>
@endif

View File

@ -1,9 +1,14 @@
@extends('layout.master')
@section('body-class', 'page-categories-home')
@push('header')
<script src="{{ asset('vendor/scrolltofixed/jquery-scrolltofixed-min.js') }}"></script>
@endpush
@section('content')
{{ $breadcrumb->render() }}
<div class="container">
{{ $breadcrumb->render() }}
<div class="row">
<div class="col-lg-9 col-12">
<div class="card mb-4 shadow-sm p-3 h-min-600">
@ -28,7 +33,7 @@
@if ($active_page_categories)
<div class="col-lg-3 col-12">
<div class="card mb-3 shadow-sm">
<div class="card mb-3 shadow-sm h-min-300 x-fixed-top">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="card-title">{{ __('product.category') }}</h5>
</div>

View File

@ -5,20 +5,22 @@
@section('keywords', $category->description->meta_keywords ?: system_setting('base.meta_keyword'))
@section('description', $category->description->meta_description ?: system_setting('base.meta_description'))
@push('header')
<script src="{{ asset('vendor/scrolltofixed/jquery-scrolltofixed-min.js') }}"></script>
@endpush
@section('content')
<x-shop-breadcrumb type="page_category" :value="$category['id']" />
<div class="container">
<x-shop-breadcrumb type="page_category" :value="$category['id']" />
<div class="row">
<div class="col-lg-9 col-12">
<div class="card mb-4 shadow-sm">
<div class="card-body">
<h3>{{ $category->description->title }}</h3>
<div>{{ $category->description->summary }}</div>
</div>
</div>
<div class="card mb-4 shadow-sm">
<div class="card mb-4 shadow-sm h-min-600">
<div class="card-body">
<div class="mb-4">
<h3>{{ $category->description->title }}</h3>
<div>{{ $category->description->summary }}</div>
</div>
@if ($category_pages->count() > 0)
@foreach ($category_pages as $page)
<div>
@ -48,7 +50,7 @@
@if ($active_page_categories)
<div class="col-lg-3 col-12">
<div class="card mb-3 shadow-sm">
<div class="card mb-3 shadow-sm h-min-300 x-fixed-top">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="card-title">{{ __('product.category') }}</h5>
</div>

View File

@ -6,12 +6,14 @@
@push('header')
<script src="{{ asset('vendor/swiper/swiper-bundle.min.js') }}"></script>
<script src="{{ asset('vendor/scrolltofixed/jquery-scrolltofixed-min.js') }}"></script>
<link rel="stylesheet" href="{{ asset('vendor/swiper/swiper-bundle.min.css') }}">
@endpush
@section('content')
<x-shop-breadcrumb type="page" :value="$page['id']" />
<div class="container">
<x-shop-breadcrumb type="page" :value="$page['id']" />
<div class="row">
<div class="{{ $page->category ? "col-lg-9 col-12" : 'col-12' }}">
<div class="card shadow-sm">
@ -52,7 +54,7 @@
@if ($page->category)
<div class="col-lg-3 col-12">
<div class="card mb-3 shadow-sm">
<div class="card mb-3 shadow-sm h-min-300 x-fixed-top">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="card-title">{{ __('product.category') }}</h5>
</div>
@ -80,10 +82,12 @@
breakpoints:{
320: {
slidesPerView: 2,
slidesPerGroup: 2,
spaceBetween: 10,
},
768: {
slidesPerView: 4,
slidesPerGroup: 4,
spaceBetween: 30,
},
},

View File

@ -5,8 +5,9 @@
@section('description', $page['meta_description'])
@section('content')
<x-shop-breadcrumb type="page" :value="$page['id']" />
<div class="container">
<x-shop-breadcrumb type="page" :value="$page['id']" />
<div class="card">
<div class="card-body">
{!! $page_format['content'] !!}

View File

@ -12,9 +12,9 @@
@endpush
@section('content')
<div class="container" id="product-app" v-cloak>
<x-shop-breadcrumb type="product" :value="$product['id']" />
<x-shop-breadcrumb type="product" :value="$product['id']" />
<div class="container" id="product-app" v-cloak>
<div class="row mb-5 mt-3 mt-md-0" id="product-top">
<div class="col-12 col-lg-6 mb-3">
<div class="product-image d-flex align-items-start">

View File

@ -2,10 +2,9 @@
@section('body-class', 'page-categories')
@section('content')
<x-shop-breadcrumb type="static" value="products.search" />
<div class="container">
<x-shop-breadcrumb type="static" value="products.search" />
<div class="row">
@if (count($items))
@foreach ($items as $product)

70
webpack.mix.js vendored
View File

@ -1,28 +1,16 @@
const mix = require('laravel-mix');
/*
|--------------------------------------------------------------------------
| Mix Asset Management
|--------------------------------------------------------------------------
|
| Mix provides a clean, fluent API for defining some Webpack build steps
| for your Laravel applications. By default, we are compiling the CSS
| file for the application as well as bundling up all the JS files.
|
*/
// mix.js('resources/js/app.js', 'public/build/js')
// .postCss('resources/css/app.css', 'public/build/css', [
// //
// ]);
// mix.sass('resources/css/app.scss', 'public/build/css');
// 后台
// 后台 scss/js
mix.sass('resources/beike/admin/css/bootstrap/bootstrap.scss', 'public/build/beike/admin/css/bootstrap.css');
mix.sass('resources/beike/admin/css/app.scss', 'public/build/beike/admin/css/app.css');
mix.js('resources/beike/admin/js/app.js', 'public/build/beike/admin/js/app.js');
// 安装引导
mix.sass('beike/Installer/assets/scss/app.scss', 'public/install/css/app.css');
// design
mix.sass('resources/beike/admin/css/design/app.scss', 'public/build/beike/admin/css/design.css');
// filemanager
mix.sass('resources/beike/admin/css/filemanager/app.scss', 'public/build/beike/admin/css/filemanager.css');
@ -31,34 +19,24 @@ mix.sass('resources/beike/shop/default/css/bootstrap/bootstrap.scss', 'public/bu
mix.sass('resources/beike/shop/default/css/app.scss', 'public/build/beike/shop/default/css/app.css');
mix.js('resources/beike/shop/default/js/app.js', 'public/build/beike/shop/default/js/app.js');
// 如果安装有某一个模板 ,需要修改其 scss/js ,那么你需要添加如下 fashion 模板的编译代码
// mix.sass('resources/beike/shop/fashion/css/bootstrap/bootstrap.scss', 'public/build/beike/shop/fashion/css/bootstrap.css');
// mix.sass('resources/beike/shop/fashion/css/app.scss', 'public/build/beike/shop/fashion/css/app.css');
// mix.js('resources/beike/shop/fashion/js/app.js', 'public/build/beike/shop/fashion/js/app.js');
/* scss/js fashion code
mix.sass('resources/beike/shop/fashion/css/bootstrap/bootstrap.scss', 'public/build/beike/shop/fashion/css/bootstrap.css');
mix.sass('resources/beike/shop/fashion/css/app.scss', 'public/build/beike/shop/fashion/css/app.css');
mix.js('resources/beike/shop/fashion/js/app.js', 'public/build/beike/shop/fashion/js/app.js');
*/
// 安装引导
mix.sass('beike/Installer/assets/scss/app.scss', 'public/install/css/app.css');
/* , themeFileName
const themeFileName = 'Fashion2';
const themeCode = themeCode.toLowerCase();
// design
mix.sass('resources/beike/admin/css/design/app.scss', 'public/build/beike/admin/css/design.css');
// 拷贝模版 blade 文件 到 themes 目录下
mix.copy(`plugins/${themeFileName}/Themes`, 'themes');
// 编译模版 scss/js 到 public/build 下
mix.sass(`plugins/${themeFileName}/Resources/beike/shop/${themeCode}/css/bootstrap/bootstrap.scss`, `public/build/beike/shop/${themeCode}/css/bootstrap.css`);
mix.sass(`plugins/${themeFileName}/Resources/beike/shop/${themeCode}/css/app.scss`, `public/build/beike/shop/${themeCode}/css/app.css`);
mix.js(`plugins/${themeFileName}/Resources/beike/shop/${themeCode}/js/app.js`, `public/build/beike/shop/${themeCode}/js/app.js`);
*/
if (mix.inProduction()) {
mix.version();
}
mix.browserSync({
proxy: 'laravel.test'
});
// 前端热更新
if ( typeof process.env.MIX_PROXY != "undefined" || process.env.MIX_PROXY != '' ) {
mix.browserSync({
proxy: process.env.MIX_PROXY, // apache或iis等代理地址
port: 1001,
notify: false, // 刷新是否提示
watchTask: true,
open: false,
host: process.env.MIX_HOST, // 本机ip, 这样其他设备才可实时看到更新
});
}
mix.version();
}