增强左侧购物车弹出层功能

This commit is contained in:
pushuo 2022-11-04 14:23:36 +08:00 committed by Edward Yang
parent 4ce6a39d38
commit f1a8d55eec
14 changed files with 114 additions and 34 deletions

View File

@ -106,7 +106,7 @@ class CartController extends Controller
public function miniCart()
{
$carts = CartService::list(current_customer());
$reloadData = CartService::reloadData($carts, true);
$reloadData = CartService::reloadData($carts);
$data['html'] = view('cart/mini', $reloadData)->render();
$data['quantity'] = $reloadData['quantity'];

View File

@ -8,7 +8,7 @@
<meta name="csrf-token" content="{{ csrf_token() }}">
<meta name="asset" content="{{ asset('/') }}">
<meta name="editor_language" content="{{ locale() }}">
<script src="{{ asset('vendor/vue/2.7/vue.js') }}"></script>
<script src="{{ asset('vendor/vue/2.7/vue' . (!config('app.debug') ? '.min' : '') . '.js') }}"></script>
<script src="{{ asset('vendor/element-ui/2.15.6/js.js') }}"></script>
<script src="{{ asset('vendor/jquery/jquery-3.6.0.min.js') }}"></script>
<script src="{{ asset('vendor/layer/3.5.1/layer.js') }}"></script>

View File

@ -255,11 +255,26 @@ header {
}
#offcanvas-right-cart {
.select-wrap {
flex: 1;
margin-right: 10px;
cursor: pointer;
i {
font-size: 20px;
color: #aaa;
&.bi-check-circle-fill {
color: $primary;
}
}
}
.offcanvas-right-products {
.product-list {
padding: 1rem 0;
border-top: 1px solid #eee;
.left {
width: 80px;
flex: 0 0 80px;
@ -281,6 +296,14 @@ header {
-webkit-line-clamp: 2;
}
.price {
input {
margin-left: 10px;
width: 50px;
height: 24px;
}
}
.offcanvas-products-delete {
cursor: pointer;
color: #999;
@ -288,6 +311,10 @@ header {
}
}
}
.offcanvas-footer {
}
}
#offcanvas-mobile-menu {

View File

@ -3,12 +3,12 @@
* @link https://beikeshop.com
* @Author pu shuo <pushuo@guangda.work>
* @Date 2022-08-16 18:47:18
* @LastEditTime 2022-09-16 20:56:58
* @LastEditTime 2022-11-04 14:18:43
*/
// offcanvas-search-top
$(function () {
var myOffcanvas = document.getElementById("offcanvas-search-top");
// 搜索弹出层交互
const myOffcanvas = document.getElementById("offcanvas-search-top");
if (myOffcanvas) {
myOffcanvas.addEventListener("shown.bs.offcanvas", function () {
$("#offcanvas-search-top input").focus();
@ -22,8 +22,50 @@ $(function () {
});
}
// 响应式下弹窗菜单交互
$(document).on("click", ".mobile-open-menu", function () {
const offcanvasMobileMenu = new bootstrap.Offcanvas('#offcanvas-mobile-menu')
offcanvasMobileMenu.show()
});
// 右侧购物车弹出层内交互
$(document).on("click", "#offcanvas-right-cart .select-wrap", function () {
const [unchecked, checked] = ['bi bi-circle', 'bi bi-check-circle-fill'];
const productListAll = $('#offcanvas-right-cart .product-list').length;
const isChecked = $(this).children('i').hasClass(unchecked);
$(this).children('i').prop('class', isChecked ? checked : unchecked);
const checkedProduct = $('#offcanvas-right-cart .offcanvas-right-products i.bi-check-circle-fill').length;
if ($(this).hasClass('all-select')) {
const isAll = $('.all-select i').hasClass(checked);
$('#offcanvas-right-cart .product-list').find('.select-wrap i').prop('class', isAll ? checked : unchecked)
} else {
$('.offcanvas-footer .all-select i').prop('class', productListAll == checkedProduct ? checked : unchecked);
}
const checkedIds = $('#offcanvas-right-cart .product-list').map(function() {
return $(this).find('i.bi-check-circle-fill').data('id');
}).get();
$http.post(`/carts/select`, {cart_ids: checkedIds}, {hload: true}).then((res) => {
updateMiniCartData(res);
})
});
// 右侧购物车弹出层内交互
$(document).on("change", "#offcanvas-right-cart .price input", function () {
const [id, sku_id, quantity] = [$(this).data('id'), $(this).data('sku'), $(this).val() * 1];
if ($(this).val() === '') $(this).val(1);
$http.put(`/carts/${id}`, {quantity: quantity, sku_id}, {hload: true}).then((res) => {
updateMiniCartData(res);
})
})
function updateMiniCartData(res) {
$('.offcanvas-right-cart-count').text(res.data.quantity);
$('.offcanvas-right-cart-amount').text(res.data.amount_format);
}
});

View File

@ -3,7 +3,7 @@
@section('body-class', 'page-account-address')
@push('header')
<script src="{{ asset('vendor/vue/2.6.14/vue.js') }}"></script>
<script src="{{ asset('vendor/vue/2.6.14/vue' . (!config('app.debug') ? '.min' : '') . '.js') }}"></script>
<script src="{{ asset('vendor/element-ui/2.15.6/js.js') }}"></script>
<link rel="stylesheet" href="{{ asset('vendor/element-ui/2.15.6/css.css') }}">
@endpush

View File

@ -3,7 +3,7 @@
@section('body-class', 'page-forgotten')
@push('header')
<script src="{{ asset('vendor/vue/2.6.14/vue.js') }}"></script>
<script src="{{ asset('vendor/vue/2.6.14/vue' . (!config('app.debug') ? '.min' : '') . '.js') }}"></script>
<script src="{{ asset('vendor/element-ui/2.15.6/js.js') }}"></script>
<link rel="stylesheet" href="{{ asset('vendor/element-ui/2.15.6/css.css') }}">
@endpush

View File

@ -3,7 +3,7 @@
@section('body-class', 'page-login')
@push('header')
<script src="{{ asset('vendor/vue/2.6.14/vue.js') }}"></script>
<script src="{{ asset('vendor/vue/2.6.14/vue' . (!config('app.debug') ? '.min' : '') . '.js') }}"></script>
<script src="{{ asset('vendor/element-ui/2.15.6/js.js') }}"></script>
<link rel="stylesheet" href="{{ asset('vendor/element-ui/2.15.6/css.css') }}">
@endpush

View File

@ -3,7 +3,7 @@
@section('body-class', 'page-account-rmas')
@push('header')
{{-- <script src="{{ asset('vendor/vue/2.6.14/vue.js') }}"></script> --}}
{{-- <script src="{{ asset('vendor/vue/2.6.14/vue' . (!config('app.debug') ? '.min' : '') . '.js') }}"></script> --}}
@endpush
@section('content')

View File

@ -3,7 +3,7 @@
@section('body-class', 'page-account-rmas')
@push('header')
{{-- <script src="{{ asset('vendor/vue/2.6.14/vue.js') }}"></script> --}}
{{-- <script src="{{ asset('vendor/vue/2.6.14/vue' . (!config('app.debug') ? '.min' : '') . '.js') }}"></script> --}}
@endpush
@section('content')

View File

@ -3,7 +3,7 @@
@section('body-class', 'page-cart')
@push('header')
<script src="{{ asset('vendor/vue/2.6.14/vue.js') }}"></script>
<script src="{{ asset('vendor/vue/2.6.14/vue' . (!config('app.debug') ? '.min' : '') . '.js') }}"></script>
<script src="{{ asset('vendor/element-ui/2.15.6/js.js') }}"></script>
<link rel="stylesheet" href="{{ asset('vendor/element-ui/2.15.6/css.css') }}">
@endpush

View File

@ -3,18 +3,29 @@
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
@php $check = 0 @endphp
@if ($carts)
<div class="offcanvas-right-products">
@foreach ($carts as $cart)
@if ($cart['selected']) @php $check = $check + 1 @endphp @endif
<div class="product-list 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="right flex-grow-1">
<a href="{{ shop_route('products.show', $cart['product_id']) }}" class="name fs-sm fw-bold mb-3 text-dark" title="{{ $cart['name'] }}">{{ $cart['name'] }}</a>
<div class="product-bottom d-flex justify-content-between align-items-center">
<div class="price">{{ $cart['price_format'] }} <span class="text-muted">x {{ $cart['quantity'] }}<span>
<div class="select-wrap">
<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="right flex-grow-1">
<a href="{{ shop_route('products.show', $cart['product_id']) }}" class="name fs-sm fw-bold mb-3 text-dark" title="{{ $cart['name'] }}">{{ $cart['name'] }}</a>
<div class="product-bottom d-flex justify-content-between align-items-center">
<div class="price d-flex align-items-center">
{{ $cart['price_format'] }} x
<input type="text" onkeyup="this.value=this.value.replace(/\D/g,'')" onafterpaste="this.value=this.value.replace(/\D/g,'')"
data-id="{{ $cart['cart_id'] }}" data-sku="{{ $cart['sku_id'] }}" class="form-control p-1" value="{{ $cart['quantity'] }}">
</div>
<span class="offcanvas-products-delete" data-id="{{ $cart['cart_id'] }}"><i class="bi bi-x-lg"></i>
{{ __('common.delete') }}</span>
</div>
<span class="offcanvas-products-delete" data-id="{{ $cart['cart_id'] }}"><i class="bi bi-x-lg"></i>
{{ __('common.delete') }}</span>
</div>
</div>
</div>
@ -40,9 +51,15 @@
@if ($carts)
<div class="offcanvas-footer">
<div class="d-flex justify-content-between align-items-center mb-2 p-4 bg-light">
<strong>{{ __('shop/carts.subtotal') }}<span class="offcanvas-right-cart-count">{{ $quantity }}</span></strong>
<strong class="ms-auto offcanvas-right-cart-amount">{{ $amount_format }}</strong>
<div class="d-flex justify-content-between align-items-center mb-2 p-3 bg-light top-footer">
<div class="select-wrap all-select d-flex align-items-center">
<i class="bi {{ $check == count($carts) ? 'bi-check-circle-fill' : 'bi-circle' }}"></i>
<span class="ms-1 text-secondary">{{ __('common.select_all') }}</span>
</div>
<div>
<span class="text-secondary">{{ __('shop/carts.product_total') }}</span><strong><span class="offcanvas-right-cart-count">{{ $quantity }}</span></strong>
<strong class="ms-auto offcanvas-right-cart-amount">{{ $amount_format }}</strong>
</div>
</div>
<div class="p-4">
<a href="{{ shop_route('checkout.index') }}" class="btn w-100 btn-dark">{{ __('shop/carts.to_checkout') }}</a>

View File

@ -3,7 +3,7 @@
@section('body-class', 'page-checkout')
@push('header')
<script src="{{ asset('vendor/vue/2.6.14/vue.js') }}"></script>
<script src="{{ asset('vendor/vue/2.6.14/vue' . (!config('app.debug') ? '.min' : '') . '.js') }}"></script>
<script src="{{ asset('vendor/element-ui/2.15.6/js.js') }}"></script>
<link rel="stylesheet" href="{{ asset('vendor/element-ui/2.15.6/css.css') }}">
@endpush

View File

@ -36,18 +36,12 @@
<div class="dropdown">
<a class="btn dropdown-toggle" href="javascript:void(0)" role="button" id="language-dropdown" data-toggle="dropdown"
aria-expanded="false">
{{-- @if (current_language()->image)
<img src="{{ image_resize(current_language()->image, 16, 16) }}" class="img-fluid me-1">
@endif --}}
{{ current_language()->name }}
</a>
<div class="dropdown-menu" aria-labelledby="language-dropdown">
@foreach ($languages as $language)
<a class="dropdown-item" href="{{ shop_route('lang.switch', [$language->code]) }}">
{{-- @if ($language->image)
<img src="{{ image_resize($language->image, 16, 16) }}" class="img-fluid me-1">
@endif --}}
{{ $language->name }}
</a>
@endforeach
@ -107,10 +101,10 @@
</ul>
</li>
<li class="nav-item">
<a class="nav-link position-relative" data-bs-toggle="offcanvas" href="#offcanvas-right-cart" role="button"
<a class="nav-link position-relative" {{ !equal_route('shop.carts.index') ? 'data-bs-toggle=offcanvas' : '' }}
href="{{ !equal_route('shop.carts.index') ? '#offcanvas-right-cart' : 'javascript:void(0);' }}" role="button"
aria-controls="offcanvasExample">
<i class="iconfont">&#xe634;</i>
{{-- <div class="navbar-icon-link-badge"></div> --}}
<span class="cart-badge-quantity"></span>
</a>
</li>
@ -148,9 +142,9 @@
</div>
</div>
<div class="offcanvas offcanvas-end" tabindex="-1" id="offcanvas-right-cart"
aria-labelledby="offcanvasRightLabel"></div>
@if (!equal_route('shop.carts.index'))
<div class="offcanvas offcanvas-end" tabindex="-1" id="offcanvas-right-cart" aria-labelledby="offcanvasRightLabel"></div>
@endif
<div class="offcanvas offcanvas-top" tabindex="-1" id="offcanvas-search-top" aria-labelledby="offcanvasTopLabel">
<div class="offcanvas-header">

View File

@ -3,7 +3,7 @@
@section('body-class', 'page-product')
@push('header')
<script src="{{ asset('vendor/vue/2.6.14/vue.js') }}"></script>
<script src="{{ asset('vendor/vue/2.6.14/vue' . (!config('app.debug') ? '.min' : '') . '.js') }}"></script>
<script src="{{ asset('vendor/swiper/swiper-bundle.min.js') }}"></script>
<script src="{{ asset('vendor/zoom/jquery.zoom.min.js') }}"></script>
<link rel="stylesheet" href="{{ asset('vendor/swiper/swiper-bundle.min.css') }}">