!104 Product Added Quick Preview

* Added quick preview
This commit is contained in:
pushuo 2023-05-20 10:20:53 +00:00 committed by Edward Yang
parent 1574805a5a
commit b5cc1ba786
15 changed files with 218 additions and 117 deletions

View File

@ -3,7 +3,7 @@
* @link https://beikeshop.com
* @Author pu shuo <pushuo@guangda.work>
* @Date 2022-08-26 18:18:22
* @LastEditTime 2023-02-08 15:35:25
* @LastEditTime 2023-05-18 15:33:10
*/
import http from "../../../js/http";
@ -92,7 +92,8 @@ const tinymceInit = () => {
toolbar_mode: 'wrap',
font_formats:
"微软雅黑='Microsoft YaHei';黑体=黑体;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Georgia=georgia,palatino;Helvetica=helvetica;Times New Roman=times new roman,times;Verdana=verdana,geneva",
fontsize_formats: "10px 12px 14px 18px 24px 36px",
fontsize_formats: "10px 12px 14px 18px 24px 36px 48px 56px 72px 96px",
lineheight_formats: "1 1.1 1.2 1.3 1.4 1.5 1.7 2.4 3 4",
setup: function(ed) {
const height = ed.getElement().dataset.tinymceHeight;
// console.log(ed);

View File

@ -104,7 +104,8 @@ Vue.component('rich-text-i18n', {
toolbar_mode: 'wrap',
font_formats:
"微软雅黑='Microsoft YaHei';黑体=黑体;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Georgia=georgia,palatino;Helvetica=helvetica;Times New Roman=times new roman,times;Verdana=verdana,geneva",
fontsize_formats: "10px 12px 14px 18px 24px 36px",
fontsize_formats: "10px 12px 14px 18px 24px 36px 48px 56px 72px 96px",
lineheight_formats: "1 1.1 1.2 1.3 1.4 1.5 1.7 2.4 3 4",
relative_urls : true,
// init_instance_callback: function (ed) {
// let code = ed.getElement().dataset.code

View File

@ -3,7 +3,7 @@
* @link https://beikeshop.com
* @Author pu shuo <pushuo@guangda.work>
* @Date 2022-08-29 17:32:51
* @LastEditTime 2023-02-02 11:06:01
* @LastEditTime 2023-05-18 10:18:09
*/
import http from "../../../../js/http";
@ -19,22 +19,6 @@ import './header'
import './bootstrap-validation'
$(document).ready(function ($) {
$(document).on('click', '.offcanvas-products-delete', function () {
const id = $(this).data('id');
$http.delete(`carts/${id}`).then((res) => {
$(this).parents('.product-list').remove();
if (!res.data.quantity) {
$('.cart-badge-quantity').hide();
} else {
$('.cart-badge-quantity').show().html(res.data.quantity > 99 ? '99+' : res.data.quantity);
}
$('.offcanvas-right-cart-count').text(res.data.quantity);
$('.offcanvas-right-cart-amount').text(res.data.amount_format);
})
})
if ($(window).width() > 992 && $('.x-fixed-top').length) {
$('.x-fixed-top').scrollToFixed({
zIndex: 999,

View File

@ -3,7 +3,7 @@
* @link https://beikeshop.com
* @Author pu shuo <pushuo@guangda.work>
* @Date 2022-09-09 19:16:39
* @LastEditTime 2023-05-17 13:49:44
* @LastEditTime 2023-05-18 09:02:44
*/
export default {
@ -31,7 +31,7 @@ export default {
* @param {*} isBuyNow 是否立即购买
* @return {*} 返回Promise
*/
addCart({sku_id, quantity = 1, isBuyNow = false}, event) {
addCart({sku_id, quantity = 1, isBuyNow = false}, event, callback) {
if (!config.isLogin && !config.guestCheckout) {
this.openLogin()
return;
@ -46,8 +46,9 @@ export default {
$http.post('/carts', {sku_id, quantity, buy_now: isBuyNow}, {hload: !!event}).then((res) => {
this.getCarts();
layer.msg(res.message)
if (isBuyNow) {
location.href = 'checkout'
if (callback) {
callback(res)
}
}).finally(() => {$btn.html(btnHtml).prop('disabled', false)})
},
@ -96,6 +97,18 @@ export default {
});
},
productQuickView(id, callback) {
layer.open({
type: 2,
title: '',
shadeClose: true,
scrollbar: false,
area: ['1000px', '600px'],
skin: 'login-pop-box',
content: `products/${id}?iframe=true`
});
},
getQueryString(name, defaultValue) {
const reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)');
const r = window.location.search.substr(1).match(reg);

View File

@ -3,7 +3,7 @@
* @link https://beikeshop.com
* @Author pu shuo <pushuo@guangda.work>
* @Date 2022-08-16 18:47:18
* @LastEditTime 2023-03-16 17:30:20
* @LastEditTime 2023-05-18 10:27:58
*/
$(function () {
@ -22,6 +22,35 @@ $(function () {
});
}
// 购物车侧边栏弹出
$(document).on("click", ".btn-right-cart", function () {
const currentUrl = window.location.pathname;
if (currentUrl == '/checkout' || currentUrl == '/carts') {
return;
}
const offcanvasRightCart = new bootstrap.Offcanvas('#offcanvas-right-cart')
offcanvasRightCart.show()
});
// 侧边栏购物车删除商品
$(document).on('click', '.offcanvas-products-delete', function () {
const id = $(this).data('id');
$http.delete(`carts/${id}`).then((res) => {
$(this).parents('.product-list').remove();
if (!res.data.quantity) {
$('.cart-badge-quantity').hide();
$('.empty-cart').removeClass('d-none');
} else {
$('.cart-badge-quantity').show().html(res.data.quantity > 99 ? '99+' : res.data.quantity);
}
$('.offcanvas-right-cart-count').text(res.data.quantity);
$('.offcanvas-right-cart-amount').text(res.data.amount_format);
})
})
// 响应式下弹窗菜单交互
$(document).on("click", ".mobile-open-menu", function () {
const offcanvasMobileMenu = new bootstrap.Offcanvas('#offcanvas-mobile-menu')

View File

@ -81,6 +81,7 @@ return [
'get_more' => 'Get More',
'view_more' => 'View more',
'view_details' => 'Check Details',
'quick_view' => 'Quick View',
'id' => 'ID',
'created_at' => 'Created At',

View File

@ -80,6 +80,7 @@ return [
'get_more' => '获取更多',
'view_more' => '查看更多',
'view_details' => '查看详情',
'quick_view' => '快速预览',
'id' => 'ID',
'created_at' => '创建时间',

View File

@ -80,6 +80,7 @@ return [
'get_more' => '獲取更多',
'view_more' => '查看更多',
'view_details' => '查看詳情',
'quick_view' => '快速預覽',
'id' => 'ID',
'created_at' => '創建時間',

View File

@ -35,8 +35,9 @@
<td>{{ $item['price'] }}</td>
<td class="text-end">
<div class="">
<a class="btn btn-outline-secondary btn-sm add-cart"
<a class="btn btn-outline-secondary btn-sm"
href="{{ shop_route('products.show', $item['product_id']) }}">{{ __('shop/account.wishlist.check_details') }}</a>
<button class="btn btn-outline-secondary add-cart btn-sm">{{ __('shop/products.add_to_cart') }}</button>
<button class="btn btn-outline-danger btn-sm remove-wishlist"><i class="bi bi-x-lg"></i></button>
</div>
</td>
@ -60,21 +61,23 @@
@push('add-scripts')
<script>
$(document).ready(function() {
$('.remove-wishlist').click(function() {
const product_id = $(this).closest('tr').data('id');
$('.remove-wishlist').click(function() {
const product_id = $(this).closest('tr').data('id');
$http.delete('account/wishlist/' + product_id).then((res) => {
if (res.status == 'success') {
$(this).closest('tr').fadeOut(function() {
$(this).remove();
if ($('.remove-wishlist').length == 0) {
location.reload();
}
});
}
})
});
$http.delete('account/wishlist/' + product_id).then((res) => {
if (res.status == 'success') {
$(this).closest('tr').fadeOut(function() {
$(this).remove();
if ($('.remove-wishlist').length == 0) {
location.reload();
}
});
}
})
});
$('.add-cart').click(function() {
bk.productQuickView($(this).closest('tr').data('id'))
});
</script>
@endpush

View File

@ -6,48 +6,48 @@
@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="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_url'] ?: 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>
<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 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="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_url'] ?: 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>
<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>
</div>
</div>
@endforeach
</div>
@else
<div class="d-flex justify-content-center align-items-center flex-column">
<div class="empty-cart-wrap text-center mt-5">
<div class="empty-cart-icon mb-3">
<i class="bi bi-cart fs-1"></i>
</div>
<div class="empty-cart-text mb-3">
<h5>{{ __('shop/carts.cart_empty') }}</h5>
<p class="text-muted">{{ __('shop/carts.go_buy') }}</p>
</div>
<div class="empty-cart-action">
<a href="{{ shop_route('home.index') }}" class="btn btn-primary">{{ __('shop/carts.go_shopping') }}</a>
</div>
</div>
@endforeach
</div>
@endif
<div class="d-flex justify-content-center align-items-center flex-column empty-cart {{ $carts ? 'd-none' : '' }}">
<div class="empty-cart-wrap text-center mt-5">
<div class="empty-cart-icon mb-3">
<i class="bi bi-cart fs-1"></i>
</div>
<div class="empty-cart-text mb-3">
<h5>{{ __('shop/carts.cart_empty') }}</h5>
<p class="text-muted">{{ __('shop/carts.go_buy') }}</p>
</div>
<div class="empty-cart-action">
<a href="{{ shop_route('home.index') }}" class="btn btn-primary">{{ __('shop/carts.go_shopping') }}</a>
</div>
</div>
@endif
</div>
</div>
@if ($carts)

View File

@ -1,3 +1,8 @@
@push('header')
<script src="{{ asset('vendor/swiper/swiper-bundle.min.js') }}"></script>
<link rel="stylesheet" href="{{ asset('vendor/swiper/swiper-bundle.min.css') }}">
@endpush
<section class="module-item {{ $design ? 'module-item-design' : ''}}" id="module-{{ $module_id }}">
@include('design._partial._module_tool')
@ -37,32 +42,44 @@
</div>
<script>
new Swiper ('.module-product-{{ $module_id }}', {
watchSlidesProgress: true,
breakpoints:{
320: {
slidesPerView: 2,
slidesPerGroup: 2,
spaceBetween: 10,
function productSwiper() {
new Swiper ('.module-product-{{ $module_id }}', {
watchSlidesProgress: true,
breakpoints:{
320: {
slidesPerView: 2,
slidesPerGroup: 2,
spaceBetween: 10,
},
768: {
slidesPerView: 4,
slidesPerGroup: 4,
spaceBetween: 30,
},
},
768: {
slidesPerView: 4,
slidesPerGroup: 4,
spaceBetween: 30,
spaceBetween: 30,
// 如果需要分页器
pagination: {
el: '.module-product-{{ $module_id }}-pagination',
clickable: true,
},
},
spaceBetween: 30,
// 如果需要分页器
pagination: {
el: '.module-product-{{ $module_id }}-pagination',
clickable: true,
},
// 如果需要前进后退按钮
navigation: {
nextEl: '.product-next',
prevEl: '.product-prev',
},
})
// 如果需要前进后退按钮
navigation: {
nextEl: '.product-next',
prevEl: '.product-prev',
},
})
}
@if ($design)
bk.loadStyle('{{ asset('vendor/swiper/swiper-bundle.min.css') }}');
bk.loadScript('{{ asset('vendor/swiper/swiper-bundle.min.js') }}', () => {
productSwiper();
})
@else
productSwiper();
@endif
</script>
</section>

View File

@ -1,3 +1,8 @@
@push('header')
<script src="{{ asset('vendor/swiper/swiper-bundle.min.js') }}"></script>
<link rel="stylesheet" href="{{ asset('vendor/swiper/swiper-bundle.min.css') }}">
@endpush
<section class="module-item {{ $design ? 'module-item-design' : ''}}" id="module-{{ $module_id }}">
@include('design._partial._module_tool')
@ -18,8 +23,7 @@
</div>
<script>
bk.loadStyle('{{ asset('vendor/swiper/swiper-bundle.min.css') }}');
bk.loadScript('{{ asset('vendor/swiper/swiper-bundle.min.js') }}', () => {
function slideshowSwiper() {
new Swiper ('.module-swiper-{{ $module_id }}', {
loop: '{{ count($content['images']) > 1 ? true : false }}', // 循环模式选项
autoplay: true,
@ -38,6 +42,15 @@
prevEl: '.slideshow-btnprev-{{ $module_id }}',
},
})
}
@if ($design)
bk.loadStyle('{{ asset('vendor/swiper/swiper-bundle.min.css') }}');
bk.loadScript('{{ asset('vendor/swiper/swiper-bundle.min.js') }}', () => {
slideshowSwiper();
})
@else
slideshowSwiper();
@endif
</script>
</section>

View File

@ -116,11 +116,15 @@
</li>
@endhookwrapper
<li class="nav-item">
<a class="nav-link position-relative" {{ !equal_route('shop.carts.index') ? 'data-bs-toggle=offcanvas' : '' }}
{{-- <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>
<span class="cart-badge-quantity"></span>
</a> --}}
<a class="nav-link position-relative btn-right-cart {{ equal_route('shop.carts.index') ? 'page-cart' : '' }}" href="javascript:void(0);" role="button">
<i class="iconfont">&#xe634;</i>
<span class="cart-badge-quantity"></span>
</a>
</li>
</ul>
@ -155,9 +159,7 @@
</div>
</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-end" tabindex="-1" id="offcanvas-right-cart" aria-labelledby="offcanvasRightLabel"></div>
<div class="offcanvas offcanvas-top" tabindex="-1" id="offcanvas-search-top" aria-labelledby="offcanvasTopLabel">
<div class="offcanvas-header">

View File

@ -11,15 +11,21 @@
<link rel="stylesheet" href="{{ asset('vendor/swiper/swiper-bundle.min.css') }}">
@endpush
@section('content')
<x-shop-breadcrumb type="product" :value="$product['id']" />
@php
$iframeClass = request('iframe') ? 'd-none' : '';
@endphp
<div class="container" id="product-app" v-cloak>
@section('content')
@if (!request('iframe'))
<x-shop-breadcrumb type="product" :value="$product['id']" />
@endif
<div class="container {{ request('iframe') ? 'pt-4' : '' }}" 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">
@if(!is_mobile())
<div class="left" v-if="images.length">
<div class="left {{ $iframeClass }}" v-if="images.length">
<div class="swiper" id="swiper">
<div class="swiper-wrapper">
<div class="swiper-slide" :class="!index ? 'active' : ''" v-for="image, index in images">
@ -143,11 +149,14 @@
</button>
@hook('product.detail.buy.after')
</div>
@if (current_customer() || !request('iframe'))
<div class="add-wishlist">
<button class="btn btn-link ps-0 text-secondary" data-in-wishlist="{{ $product['in_wishlist'] }}" onclick="bk.addWishlist('{{ $product['id'] }}', this)">
<i class="bi bi-heart{{ $product['in_wishlist'] ? '-fill' : '' }} me-1"></i> {{ __('shop/products.add_to_favorites') }}
</button>
</div>
@endif
@else
<div class="text-danger"><i class="bi bi-exclamation-circle-fill"></i> {{ __('product.has_been_inactive') }}</div>
@endif
@ -157,7 +166,7 @@
</div>
</div>
<div class="product-description">
<div class="product-description {{ $iframeClass }}">
<div class="nav nav-tabs nav-overflow justify-content-start justify-content-md-center border-bottom mb-3">
<a class="nav-link fw-bold active fs-5" data-bs-toggle="tab" href="#product-description">
{{ __('shop/products.product_details') }}
@ -193,7 +202,7 @@
</div>
</div>
@if ($relations)
@if ($relations && !request('iframe'))
<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>
@ -219,6 +228,7 @@
@push('add-scripts')
<script>
let swiperMobile = null;
const isIframe = bk.getQueryString('iframe', false);
let app = new Vue({
el: '#product-app',
@ -273,9 +283,9 @@
},
methods: {
checkedVariableValue(variable_idnex, value_index, value) {
checkedVariableValue(variable_index, value_index, value) {
$('.product-image .swiper .swiper-slide').eq(0).addClass('active').siblings().removeClass('active');
this.source.variables[variable_idnex].values.forEach((v, i) => {
this.source.variables[variable_index].values.forEach((v, i) => {
v.selected = i == value_index
})
@ -309,7 +319,26 @@
},
addCart(isBuyNow = false) {
bk.addCart({sku_id: this.product.id, quantity: this.quantity, isBuyNow});
bk.addCart({sku_id: this.product.id, quantity: this.quantity, isBuyNow}, null, () => {
if (isIframe) {
let index = parent.layer.getFrameIndex(window.name); //当前iframe层的索引
parent.bk.getCarts();
setTimeout(() => {
parent.layer.close(index);
if (isBuyNow) {
parent.location.href = 'checkout'
} else {
parent.$('.btn-right-cart')[0].click()
}
}, 400);
} else {
if (isBuyNow) {
location.href = 'checkout'
}
}
});
},
updateSelectedVariantsIndex() {
@ -424,7 +453,5 @@
const selectedVariants = variables.map((variable, index) => {
return variable.values[selectedVariantsIndex[index]]
});
console.log(selectedVariants);
</script>
@endpush

View File

@ -11,6 +11,14 @@
</a>
@if (!request('style_list') || request('style_list') == 'grid')
<div class="button-wrap">
<button
class="btn btn-dark text-light mx-1 rounded-3"
data-bs-toggle="tooltip"
data-bs-placement="top"
title="{{ __('common.quick_view') }}"
onclick="bk.productQuickView({{ $product['id'] }})">
<i class="bi bi-eye"></i>
</button>
<button
class="btn btn-dark text-light mx-1 rounded-3"
data-bs-toggle="tooltip"