!123 Add video function

* Optimize shopping cart entries
* File manager selection type judgment
* video function
* Support video for file manager
* Optimize file manager
This commit is contained in:
pushuo 2023-06-09 05:58:33 +00:00 committed by Edward Yang
parent 523b8a3e7c
commit e7019a9722
30 changed files with 363 additions and 117 deletions

View File

@ -33,7 +33,7 @@ class UploadRequest extends FormRequest
public function rules()
{
return [
'file' => 'required|image|mimes:jpg,png,jpeg,gif,svg|max:10240',
'file' => 'required|mimes:jpg,png,jpeg,gif,svg,mp4|max:20480',
];
}
}

View File

@ -236,12 +236,19 @@ class FileManagerService
*/
private function handleImage($filePath, $baseName): array
{
$path = "catalog{$filePath}";
$path = "catalog{$filePath}";
$realPath = $this->fileBasePath . $filePath;
$mime = '';
if(file_exists($realPath)) {
$mime = mime_content_type($realPath);
}
return [
'path' => $path,
'name' => $baseName,
'origin_url' => image_origin($path),
'mime' => $mime,
'selected' => false,
];
}

View File

@ -74,6 +74,7 @@ class Order extends Base
public function getStatusFormatAttribute()
{
$statusMap = array_column(StateMachineService::getAllStatuses(), 'name', 'status');
return $statusMap[$this->status];
}

View File

@ -24,6 +24,7 @@ class OrderHistory extends Base
public function getStatusFormatAttribute()
{
$statusMap = array_column(StateMachineService::getAllStatuses(), 'name', 'status');
return $statusMap[$this->status];
}
}

View File

@ -63,7 +63,7 @@ class CategoryRepo
$sql .= ' LEFT JOIN categories c2 ON (cp.path_id = c2.id)';
$sql .= ' LEFT JOIN category_descriptions cd1 ON (cp.path_id = cd1.category_id)';
$sql .= " WHERE cd1.locale = '" . $locale . "' ";
if (!$includeInactive) {
if (! $includeInactive) {
$sql .= ' AND c1.active = 1 ';
}
$sql .= ' GROUP BY cp.category_id ORDER BY c1.position ASC';

View File

@ -24,8 +24,8 @@ class OrderController extends Controller
}
$order = Order::query()->where('number', $number)->where('email', $email)->firstOrFail();
$data = hook_filter('order.show.data', ['order' => $order, 'html_items' => []]);
$data = hook_filter('order.show.data', ['order' => $order, 'html_items' => []]);
return view('order_info', $data);
}
}
}

View File

@ -28,7 +28,7 @@ class ProductController extends Controller
$data = hook_filter('product.show.data', $data);
return view('product', $data);
return view('product/product', $data);
}
/**

View File

@ -40,6 +40,7 @@ class ProductDetail extends JsonResource
'meta_description' => $this->description->meta_description ?? '',
'brand_id' => $this->brand->id ?? 0,
'brand_name' => $this->brand->name ?? '',
'video' => $this->video ?? '',
'images' => array_map(function ($image) {
return [
'preview' => image_resize($image, 500, 500),

1
public/vendor/video/video-js.min.css vendored Normal file

File diff suppressed because one or more lines are too long

40
public/vendor/video/video.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -171,26 +171,21 @@ body.page-filemanager {
.content-center {
height: calc(100% - 56px);
// display: flex;
// align-items: flex-start;
// flex-wrap: wrap;
// align-items: center; // flex-start | center
background: #f7f9fc;
padding: 16px 6px;
// justify-content: space-between; // flex-end | center | space-between
// flex-wrap: wrap;
// margin-right: -20px;
overflow-y: auto;
align-content: flex-start;
&::-webkit-scrollbar {
width: 4px;
width: 8px;
height: 1px;
}
&::-webkit-scrollbar-thumb {
border-radius: 2px;
background: $primary;
border-radius: 4px;
background: #ccc;
}
&::-webkit-scrollbar-track {
background: transparent;
}
@ -199,27 +194,10 @@ body.page-filemanager {
// display: flex;
// flex-direction: column;
display: inline-block;
// align-items: center;
// margin-bottom: 20px;
background: #fff;
margin: 0 8px 16px;
box-shadow: 0 0 2px 1px rgba(0, 0, 0, .07);
cursor: pointer;
// width: calc(20% - 20px);
// @media (min-width: 600px) {
// width: calc(25% - 20px);
// }
// @media (min-width: 1000px) {
// width: calc(20% - 20px);
// }
// @media (min-width: 1300px) {
// width: calc(16.666% - 20px);
// }
// border: 1px solid transparent;
.img {
width: 137px;
@ -232,6 +210,12 @@ body.page-filemanager {
max-width: 100%;
max-height: 100%;
}
i {
font-size: 86px;
color: #333;
font-weight: 400;
}
}
&.active {
@ -295,22 +279,34 @@ body.page-filemanager {
}
.upload-image {
height: 200px;
min-height: 200px;
max-height: 300px;
overflow-y: auto;
margin-right: -4px;
padding-right: 6px;
// 滚动条 透明背景
&::-webkit-scrollbar {
width: 8px;
height: 1px;
}
&::-webkit-scrollbar-thumb {
border-radius: 4px;
background: #ddd;
}
.list {
background-color: #f2f2f2;
padding: 6px 10px;
border-radius: 4px;
margin-bottom: 8px;
margin-bottom: 12px;
padding-bottom: 14px;
font-size: 12px;
border-bottom: 1px solid #f1f1f1;
.info {
display: flex;
align-items: center; // flex-start | center
justify-content: space-between; // flex-end | center | space-between
margin-bottom: 6px;
}
.name {

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-05-18 15:33:10
* @LastEditTime 2023-06-08 19:18:24
*/
import http from "../../../js/http";
@ -95,21 +95,17 @@ const tinymceInit = () => {
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);
// 修改 tinymce 的高度
// if (height) {
// ed.theme.resizeTo(null, height);
// }
ed.ui.registry.addButton('toolbarImageButton',{
// text: '',
icon: 'image',
onAction:function() {
bk.fileManagerIframe(images => {
if (images.length) {
images.forEach(e => {
ed.insertContent(`<img src='/${e.path}' class="img-fluid" />`);
if (e.mime == 'video/mp4') {
ed.insertContent(`<video src='/${e.path}' controls loop muted class="img-fluid" />`);
} else {
ed.insertContent(`<img src='/${e.path}' class="img-fluid" />`);
}
});
}
})

View File

@ -3,13 +3,14 @@
* @link https://beikeshop.com
* @Author pu shuo <pushuo@guangda.work>
* @Date 2022-08-22 18:32:26
* @LastEditTime 2023-04-19 15:26:41
* @LastEditTime 2023-06-09 08:53:52
*/
export default {
// 打开文件管理器
fileManagerIframe(callback) {
fileManagerIframe(callback, params) {
const base = document.querySelector('base').href;
params = params ? `?${Object.keys(params).map(key => `${key}=${params[key]}`).join('&')}` : '';
layer.open({
type: 2,
@ -19,7 +20,7 @@ export default {
scrollbar: false,
shade: 0.4,
area: ['1060px', '680px'],
content: `${base}/file_manager`,
content: `${base}/file_manager${params}`,
success: function(layerInstance, index) {
var iframeWindow = window[layerInstance.find("iframe")[0]["name"]];
iframeWindow.callback = function(images) {

View File

@ -1,5 +1,5 @@
<div class="row g-3 mb-3">
<label for="" class="wp-200 col-form-label text-end {{ isset($required) && $required ? 'required' : '' }}">{{ $title ?? '' }}</label>
<label class="wp-200 col-form-label text-end {{ isset($required) && $required ? 'required' : '' }}">{{ $title ?? '' }}</label>
<div class="col-auto wp-200-">
{{ $slot }}
</div>

View File

@ -107,19 +107,18 @@ Vue.component('rich-text-i18n', {
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
// ed.setContent(self.value[code])
// },
setup: function(ed) {
ed.ui.registry.addButton('toolbarImageButton', {
// text: '',
icon: 'image',
onAction:function() {
bk.fileManagerIframe(images => {
if (images.length) {
images.forEach(e => {
ed.insertContent(`<img src='/${e.path}' class="img-fluid" />`);
if (e.mime == 'video/mp4') {
ed.insertContent(`<video src='/${e.path}' controls loop muted class="img-fluid" />`);
} else {
ed.insertContent(`<img src='/${e.path}' class="img-fluid" />`);
}
});
}
})

View File

@ -73,8 +73,8 @@
<div class="content-head">
<div class="left d-lg-flex">
<el-button class="me-5 mb-1 mb-lg-0" size="small" icon="el-icon-check" type="primary" @click="fileChecked" :disabled="!!!selectImageIndex.length">{{ __('admin/builder.modules_choose') }}</el-button>
<el-link :underline="false" :disabled="!!!selectImageIndex.length" icon="el-icon-download"
@click="downloadImages">{{ __('admin/file_manager.download') }}</el-link>
<el-link :underline="false" :disabled="!!!selectImageIndex.length" icon="el-icon-view"
@click="viewImages">{{ __('common.view') }}</el-link>
<el-link :underline="false" :disabled="!!!selectImageIndex.length" @click="deleteFile"
icon="el-icon-delete">{{ __('common.delete') }}</el-link>
<el-link :underline="false" :disabled="selectImageIndex.length == 1 ? false : true"
@ -114,7 +114,10 @@
v-batch-select="{ className: '.image-list', selectImageIndex, setSelectStatus: updateSelectStatus }">
<div :class="['image-list', file.selected ? 'active' : '']" v-for="file, index in images"
:key="index" @click="checkedImage(index)">
<div class="img"><img :src="file.url"></div>
<div class="img">
<i class="el-icon-video-play" v-if="file.mime == 'video/mp4'"></i>
<img v-else :src="file.url">
</div>
<div class="text">
<span :title="file.name">@{{ file.name }}</span>
<i v-if="file.selected" class="el-icon-check"></i>
@ -143,7 +146,6 @@
</div>
@else
<div class="text-center mt-5 w-100 fs-4">{{ __('admin/file_manager.show_pc') }}</div>
@endif
<el-dialog title="{{ __('admin/file_manager.upload_files') }}" top="12vh" :visible.sync="uploadFileDialog.show" width="500px"
@ -161,11 +163,13 @@
<div class="info">
<div class="name">@{{ index + 1 }}. @{{ image.name }}</div>
<div class="status">
<span v-if="image.status == 'complete'">{{ __('admin/file_manager.finish') }}</span>
<span v-if="image.status == 'complete'" class="text-success">{{ __('admin/file_manager.finish') }}</span>
<span v-else-if="image.status == 'fail'" class="text-danger">{{ __('admin/file_manager.upload_fail') }}</span>
<span v-else>{{ __('admin/file_manager.uploading') }}</span>
</div>
</div>
<el-progress :percentage="image.progre" :show-text="false" :stroke-width="4"></el-progress>
<el-progress :percentage="image.progre" :status="image.status == 'fail' ? 'exception' : 'success'" :show-text="false" :stroke-width="4"></el-progress>
<div v-if="image.fail_text" class="mt-1 text-danger" v-text="image.fail_text"></div>
</div>
</div>
</el-dialog>
@ -186,13 +190,10 @@
paneLengthPercent: 26,
triggerLength: 10,
isShift: false,
ssss: [],
mime: @json(request('mime')),
loading: false,
isBatchSelect: false,
selectImageIndex: [],
filter: {
sort: 'created',
order: 'desc'
@ -330,12 +331,16 @@
let index = this.uploadFileDialog.images.length - 1;
$http.post('file_manager/upload', formData).then((res) => {
$http.post('file_manager/upload', formData, {hmsg: true}).then((res) => {
this.uploadFileDialog.images[index].status = 'complete';
this.uploadFileDialog.images[index].progre = 100;
}).catch((err) => {
this.uploadFileDialog.images[index].status = 'fail';
this.uploadFileDialog.images[index].progre = 80;
this.uploadFileDialog.images[index].fail_text = err.response.data.message;
}).finally(() => {
index += 1
})
});
},
handleUploadChange(e) {
@ -442,6 +447,20 @@
fileChecked() {
let typedFiles = this.images.filter(e => e.selected)
if (this.mime) {
// 判断 typedFiles 数组内 mime 是否有不是 image 开头的
if (this.mime == 'image' && typedFiles.some(e => !e.mime.startsWith('image'))) {
layer.msg('{{ __('admin/file_manager.verify_select_image') }}', () => {});
return;
}
// 判断 typedFiles 数组内 mime 是否有不是 video 开头的
if (this.mime == 'video' && typedFiles.some(e => !e.mime.startsWith('video'))) {
layer.msg('{{ __('admin/file_manager.verify_select_video') }}', () => {});
return;
}
}
if (callback !== null) {
callback(typedFiles);
}
@ -513,6 +532,13 @@
});
},
viewImages() {
const selectedImages = this.images.filter(e => e.selected);
selectedImages.forEach(e => {
window.open(e.origin_url);
});
},
openInputBox(type, node, data) {
let fileSuffix, fileName = '';

View File

@ -79,7 +79,19 @@
</draggable>
<div class="help-text mb-1 mt-1">{{ __('admin/product.image_help') }}</div>
</x-admin::form.row>
{{-- <x-admin-form-input name="video" title="视频" :value="old('video', $product->video ?? '')" /> --}}
<x-admin::form.row title="{{ __('product.video') }}">
<div class="d-flex align-items-end">
<div class="set-product-img wh-80 rounded-2 me-2" @click="addProductVideo">
<i v-if="form.video.path" class="bi bi-play-circle fs-1"></i>
<i v-else class="bi bi-plus fs-1 text-muted"></i>
</div>
<input type="hidden" name="video" :value="form.video.path">
<a v-if="form.video.path" target="_blank" :href="form.video.url">{{ __('common.view') }}</a>
</div>
<div class="help-text mb-1 mt-1">{{ __('admin/product.video_help') }}</div>
</x-admin::form.row>
<x-admin-form-input name="position" :title="__('common.sort_order')" :value="old('position', $product->position ?? '0')" />
<x-admin::form.row :title="__('admin/product.weight_text')">
@ -516,6 +528,10 @@
form: {
attributes: @json(old('pickups', $product_attributes) ?? []),
images: @json(old('images', $product->images) ?? []),
video: {
path: @json(old('video', $product->video ?? '')),
url: @json(image_origin(old('video', $product->video ?? ''))),
},
model: @json($product->skus[0]['model'] ?? ''),
price: @json($product->skus[0]['price'] ?? ''),
quantity: @json($product->skus[0]['quantity'] ?? ''),
@ -678,7 +694,13 @@
return;
}
this.form.images.push(...images.map(e => e.path))
})
}, {mime: 'image'})
},
addProductVideo() {
bk.fileManagerIframe(images => {
this.form.video = {path: images[0].path, url: images[0].url}
}, {mime: 'video'})
},
removeImages(index) {

View File

@ -322,4 +322,25 @@ img {
padding-top: .8rem;
padding-bottom: .8rem;
}
}
}
// 溢出隐藏 显示省略号
.text-ellipsis {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
// 加一个 line
&.line-2 {
white-space: normal;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
&.line-3 {
white-space: normal;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
}
}

View File

@ -23,6 +23,8 @@ body.page-product {
}
.product-image {
position: relative;
#swiper {
height: 250px;
@media (min-width: 480px) {
@ -117,6 +119,68 @@ body.page-product {
.right {
border: 1px solid #eee;
position: relative;
}
#product-video {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
z-index: 99;
display: none;
}
.open-video {
position: absolute;
bottom: 10px;
z-index: 99;
line-height: 1;
cursor: pointer;
@media (min-width: 768px) {
transform: translateX(-50%);
left: 50%;
}
@media (max-width: 768px) {
right: 10px;
}
&:hover {
i {
color: #fff;
background-color: rgba(0, 0, 0, 0.648);
}
}
i {
font-size: 3.5rem;
line-height: 1;
border-radius: 50%;
font-weight: 400;
display: inline-block;
color: rgba(255, 255, 255, 0.948);
background-color: rgba(0, 0, 0, 0.348);
@media (max-width: 768px) {
font-size: 2.5rem;
}
}
}
.close-video {
position: absolute;
top: 6px;
right: 10px;
z-index: 9999;
color: #aaa;
font-size: 30px;
cursor: pointer;
&:hover {
color: #fff;
}
}
}

View File

@ -33,6 +33,8 @@ return [
'no_file' => 'No File',
'picture_space' => 'Picture Space',
'show_pc' => 'Please go to the PC side to operate',
'verify_select_image' => 'Please select a picture',
'verify_select_video' => 'Please select video',
'confirm_delete_file' => 'Do you want to delete the selected file',
'confirm_delete_folder' => 'The folder deletion operation is in progress, all files in the folder will be deleted, do you want to confirm?',
@ -40,5 +42,6 @@ return [
'can_empty' => 'Can not be empty',
'finish' => 'Finish',
'uploading' => 'loading...',
'upload_fail' => 'Upload failed',
'file_manager' => 'File Manager',
];

View File

@ -36,6 +36,7 @@ return [
'quantity' => 'Quantity',
'enable_multi_spec' => 'Enable multi-spec',
'image_help' => 'The first picture will be used as the main picture of the product, and multiple pictures can be uploaded at the same time, and the position of multiple pictures can be adjusted at will',
'video_help' => 'If the prompt exceeds the system size limit, please modify the php.ini parameter post_max_size',
'add_variable' => 'Add Specs',
'add_variable_value' => 'Add Specification Value',
'add_variable_image' => 'Add Spec Image',

View File

@ -23,6 +23,7 @@ return [
'g' => 'Gram',
'oz' => 'Ounce',
'lb' => 'Pound',
'video' => 'Video',
'active' => 'Active',
'inactive' => 'Inactive',

View File

@ -13,7 +13,7 @@ return [
'index' => 'Cart',
'added_to_cart' => 'Added To Cart',
'select_all' => 'Select All',
'commodity' => 'Commodity',
'commodity' => 'Product',
'quantity' => 'Quantity',
'subtotal' => 'Subtotal',
'product_total' => 'Product Total',

View File

@ -33,12 +33,15 @@ return [
'no_file' => '没有文件',
'picture_space' => '图片空间',
'show_pc' => '请到PC端操作',
'verify_select_image' => '请选择图片',
'verify_select_video' => '请选择视频',
'confirm_delete_file' => '是否要删除选中文件',
'confirm_delete_folder' => '正在进行删除文件夹操作,文件夹内所有文件都将被删除,是否确认?',
'new_folder' => '新建文件夹',
'can_empty' => '不能为空',
'finish' => '完成',
'uploading' => '上传中',
'file_manager' => '图片管理器',
'confirm_delete_file' => '是否要删除选中文件',
'confirm_delete_folder' => '正在进行删除文件夹操作,文件夹内所有文件都将被删除,是否确认?',
'new_folder' => '新建文件夹',
'can_empty' => '不能为空',
'finish' => '完成',
'uploading' => '上传中',
'upload_fail' => '上传失败',
'file_manager' => '图片管理器',
];

View File

@ -36,6 +36,7 @@ return [
'quantity' => '数量',
'enable_multi_spec' => '启用多规格',
'image_help' => '第一张图片将作为商品主图,支持同时上传多张图片,多张图片之间可随意调整位置',
'video_help' => '如果提示超出系统大小限制,请修改 php.ini 参数 post_max_size',
'add_variable' => '添加规格',
'add_variable_value' => '添加规格值',
'add_variable_image' => '添加规格图片',

View File

@ -24,6 +24,7 @@ return [
'g' => '克',
'oz' => '盎司',
'lb' => '磅',
'video' => '视频',
'active' => '上架',
'inactive' => '下架',

View File

@ -14,40 +14,41 @@
<h5 class="card-title">{{ __('shop/account.rma.index') }}</h5>
</div>
<div class="card-body">
<table class="table ">
<thead>
<tr>
<th>{{ __('shop/account.rma.commodity') }}</th>
<th>{{ __('shop/account.rma.quantity') }}</th>
<th>{{ __('shop/account.rma.service_type') }}</th>
<th>{{ __('shop/account.rma.return_reason') }}</th>
<th>{{ __('shop/account.rma.creation_time') }}</th>
{{-- <th>状态</th> --}}
<th class="text-end">{{ __('common.action') }}</th>
</tr>
</thead>
<tbody>
@if (count($rmas))
@foreach ($rmas as $rma)
<tr>
<td>{{ sub_string($rma['product_name'], 80) }}</td>
<td>{{ $rma['quantity'] }}</td>
<td>{{ $rma['type'] }}</td>
<td>{{ $rma['reason'] }}</td>
<td>{{ $rma['created_at'] }}</td>
<td class="text-end"><a href="{{ shop_route('account.rma.show', [$rma['id']]) }}"
class="btn btn-outline-secondary btn-sm">{{ __('shop/account.rma.check') }}</a> </td>
</tr>
@endforeach
@else
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<td colspan="6" class="border-0">
<x-shop-no-data />
</td>
<th>{{ __('shop/account.rma.commodity') }}</th>
<th class="text-nowrap">{{ __('shop/account.rma.quantity') }}</th>
<th class="text-nowrap">{{ __('shop/account.rma.service_type') }}</th>
<th class="text-nowrap">{{ __('shop/account.rma.creation_time') }}</th>
<th class="text-end">{{ __('common.action') }}</th>
</tr>
@endif
</tbody>
</table>
</thead>
<tbody>
@if (count($rmas))
@foreach ($rmas as $rma)
<tr>
<td>
<div class="text-ellipsis line-2 w-min-100 w-max-300">{{ sub_string($rma['product_name'], 80) }}</div>
</td>
<td>{{ $rma['quantity'] }}</td>
<td>{{ $rma['type'] }}</td>
<td class="text-nowrap">{{ $rma['created_at'] }}</td>
<td class="text-end"><a href="{{ shop_route('account.rma.show', [$rma['id']]) }}"
class="btn text-nowrap btn-outline-secondary btn-sm">{{ __('shop/account.rma.check') }}</a> </td>
</tr>
@endforeach
@else
<tr>
<td colspan="6" class="border-0">
<x-shop-no-data />
</td>
</tr>
@endif
</tbody>
</table>
</div>
{{-- {{ $rmas->links('shared/pagination/bootstrap-4') }} --}}
</div>

View File

@ -23,7 +23,7 @@
<div class="row mt-5" v-if="products.length">
<div class="col-12 col-md-9 left-column">
<div class="card shadow-sm">
<div class="card shadow-sm h-min-600">
<div class="card-body p-lg-4">
<div class="p-lg-0"><h4 class="mb-3">{{ __('shop/carts.commodity') }}</h4></div>
<div class="cart-products-wrap table-responsive">
@ -36,8 +36,8 @@
{{ __('shop/carts.select_all') }}
</label>
</th>
<th width="40%">{{ __('shop/carts.index') }}</th>
<th width="170">{{ __('shop/carts.commodity') }}</th>
<th width="40%">{{ __('shop/carts.commodity') }}</th>
<th width="170">{{ __('shop/carts.quantity') }}</th>
<th width="170">{{ __('shop/carts.subtotal') }}</th>
<th width="100" class="text-end">{{ __('common.action') }}</th>
</tr>

View File

@ -0,0 +1,50 @@
@if ($product['video'])
<div class="video-wrap">
<video
id="product-video"
class="video-js vjs-big-play-centered vjs-fluid vjs-16-9"
controls loop muted
>
<source src="{{ image_origin($product['video']) }}" type="video/mp4" />
</video>
<div class="close-video d-none"><i class="bi bi-x-circle"></i></div>
<div class="open-video d-none"><i class="bi bi-play-circle"></i></div>
</div>
@endif
@push('add-scripts')
<script>
let pVideo = null;
$(function () {
if ($('#product-video').length) {
pVideo = videojs("product-video");
pVideo.on('loadedmetadata', function(e) {
$('.open-video').removeClass('d-none');
});
$(document).on('click', '.open-video', function () {
pVideo.play();
pVideo.currentTime(0);
$(this).addClass('d-none');
$('#product-video').fadeIn();
$('.close-video').removeClass('d-none');
});
$(document).on('click', '.close-video', function () {
closeVideo()
});
}
})
function closeVideo() {
if (pVideo) {
pVideo.pause();
$('#product-video').fadeOut();
$('.close-video').addClass('d-none');
$('.open-video').removeClass('d-none');
}
}
</script>
@endpush

View File

@ -9,6 +9,10 @@
<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') }}">
@if ($product['video'])
<script src="{{ asset('vendor/video/video.min.js') }}"></script>
<link rel="stylesheet" href="{{ asset('vendor/video/video-js.min.css') }}">
@endif
@endpush
@php
@ -41,9 +45,11 @@
</div>
</div>
<div class="right" id="zoom">
@include('product.product-video')
<img :src="images.length ? images[0].preview : '{{ asset('image/placeholder.png') }}'" class="img-fluid">
</div>
@else
@include('product.product-video')
<div class="swiper" id="swiper-mobile">
<div class="swiper-wrapper">
<div class="swiper-slide" v-for="image, index in images">
@ -324,6 +330,8 @@
$('#zoom').trigger('zoom.destroy');
$('#zoom').zoom({url: $('#swiper a').attr('data-zoom-image')});
})
closeVideo()
},
addCart(isBuyNow = false) {
@ -385,6 +393,7 @@
$('#zoom').trigger('zoom.destroy');
$('#zoom img').attr('src', $(this).attr('data-image'));
$('#zoom').zoom({url: $(this).attr('data-zoom-image')});
closeVideo()
});
var swiper = new Swiper("#swiper", {