$thumbnailUrl) { $largeUrl = $largeImages[$index]; if ($hasLink) { $html .= ""; } else { $html .= ""; } } return $html; } return $html; } /* * 返回oss的url */ public static function ossUrl($imageUrl) { if (strpos($imageUrl, 'http:') === 0 || strpos($imageUrl, 'https:') === 0) { return $imageUrl; } if (env('OSS_DOMAIN')) { return "http://".env('OSS_DOMAIN').'/'.$imageUrl; } return "http://".env('OSS_BUCKET').'.'.env('OSS_ENDPOINT').'/'.$imageUrl; } /* * 图库图片URL */ public static function albumUrl($imageUrl) { if (strpos($imageUrl, 'http:') === 0 || strpos($imageUrl, 'https:') === 0) { return $imageUrl; } return env('ALBUM_OSS_URL').'/'.$imageUrl; } /* * 显示视频 */ public static function displayVideo($items,$videoCover,$videoSrc,$boxSize=150,$ossSource=1) { $html = ''; if (is_array($items)) { foreach ($items as $item) { $item = (array) $item; $cover = $item[$videoCover]; $src = $item[$videoSrc]; if ($ossSource == 1) { $videoUrl = CommonHelper::ossUrl($src); } else { $videoUrl = CommonHelper::albumUrl($src); } if ($ossSource == 1) { $thumbnailUrl = CommonHelper::ossUrl($cover) . "?x-oss-process=image/resize,m_pad,h_{$boxSize},w_{$boxSize},color_ffffff"; } else { $thumbnailUrl = CommonHelper::albumUrl($cover) . "?x-oss-process=image/resize,m_pad,h_{$boxSize},w_{$boxSize},color_ffffff"; } $html .= '
Video Thumbnail
'; } $html .= '
×
'; } //视频播放CSS Admin::style(" .video-container { position: relative; display: inline-block; } .video-container img { height: 200px; margin-right: 5px; border: 1px solid #ececf1; } .video-download-button { position: absolute; top: 50%; left: 35%; transform: translate(-50%, -50%); width: 35px; height: 35px; background-color: rgba(0, 0, 0, 0.5); border-radius: 50%; cursor: pointer; } .video-download-button::after { content: '↓'; font-size: 15px; color: white; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } .play-button { position: absolute; top: 50%; left: 58%; transform: translate(-50%, -50%); width: 35px; height: 35px; background-color: rgba(0, 0, 0, 0.5); border-radius: 50%; cursor: pointer; } .play-button::after { content: '▶'; font-size: 15px; color: white; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } .video-popup { display: none; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background-color: white; padding: 25px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.5); z-index: 1000; } .video-popup iframe { width: 800px; height: 450px; } .close-btn { position: absolute; top: 0px; right: 5px; font-size: 24px; color: #000; cursor: pointer; } .close-btn:hover { color: #f00; } "); Admin::script(" $('.playVideo').on('click', function(e) { e.preventDefault(); // 阻止默认跳转行为 var videoUrl = $(this).attr('videoUrl'); // 获取 videoUrl 属性 $('#videoPopup').css('display', 'block'); $('#videoPopup iframe').attr('src', videoUrl); // 设置 iframe 的 src }); $('.downloadVideo').on('click', function(e) { e.preventDefault(); const button = $(this); const videoUrl = button.attr('videoUrl'); // 使用 Dcat Admin 内置 loading 组件 const loading = Dcat.loading({ }); fetch(videoUrl, { headers: new Headers({ 'Origin': location.origin, 'X-CSRF-TOKEN': Dcat.token // 集成 CSRF 保护[7](@ref) }), mode: 'cors' }).then(response => { if (!response.ok) throw new Error(`HTTP \${response.status}`); // 动态创建进度条组件 const progress = new Dcat.Progress({ title: '下载进度', showCancel: true, onCancel: () => controller.abort() }); const reader = response.body.getReader(); const controller = new AbortController(); const contentLength = +response.headers.get('Content-Length'); let receivedLength = 0; const chunks = []; // 流式处理优化 const processChunk = ({ done, value }) => { if (done || progress.canceled) { if (!progress.canceled) { const blob = new Blob(chunks); const filename = videoUrl.split('/').pop() || 'video.mp4'; const link = document.createElement('a'); // 集成 Dcat 文件管理器[6](@ref) Dcat.handleFileDownload(blob, filename); } progress.close(); loading.close(); return; } chunks.push(value); receivedLength += value.length; progress.update({ percent: Math.round((receivedLength / contentLength) * 100), statusText: `\${formatBytes(receivedLength)} / \${formatBytes(contentLength)}` }); return reader.read().then(processChunk); }; return reader.read().then(processChunk); }).catch(error => { loading.close(); Dcat.error(`下载失败: \${error.message}`); console.error('Download Error:', error); }); }); // 字节单位转换工具函数 function formatBytes(bytes) { const units = ['B', 'KB', 'MB', 'GB']; let i = 0; while (bytes >= 1024 && i < units.length - 1) { bytes /= 1024; i++; } return `\${bytes.toFixed(1)} \${units[i]}`; } // 点击关闭按钮关闭视频 $('.close-btn').on('click', function() { $('#videoPopup').css('display', 'none'); $('#videoPopup iframe').attr('src', ''); // 停止播放视频 }); "); return $html; // 当没有数组数据时 } /* * 替换新增与编辑的url,在后边加上指定的参数 (适用于弹出框的新增与编辑) * $addButton = '.tree-quick-create'; * $editButton = '.tree-quick-edit'; * $paramsUrl = 'location=0'; */ public static function replaceAddEditerUrl($addButton,$editButton,$paramsUrl) { Admin::script( <<或已有download-wrapper则跳过 if ($(this).parent().hasClass('download-wrapper') || $(this).parent().is('a')) return; if ($(this).hasClass('fullscreen-image') || $(this).hasClass('video-thumbnail')) { return; } const fileName = this.src.split('/').pop().split('?')[0]; $(this).wrap('
') .after(`
`); const \$btn = $(this).parent().find('.download-btn').first(); \$btn.click(function() { const btn = $(this); btn.addClass('disabled'); downloadImage( btn.closest('.download-wrapper').find('img')[0].src, fileName ).finally(() => btn.removeClass('disabled')); }); // 全屏放大功能 $(this).next().find('.zoom-btn').click(function() { let imgSrc = $(this).closest('.download-wrapper').find('img').attr('src'); imgSrc = imgSrc.replace(/\?.*$/, ''); fullscreenImage.attr('src', imgSrc); fullscreenOverlay.fadeIn(200); }); }); } // 关闭全屏 fullscreenOverlay.click(function(e) { if (e.target === this) $(this).fadeOut(200); }); function downloadImage(url, filename) { url = url.replace(/\?.*$/, ''); return new Promise((resolve, reject) => { fetch(url) .then(response => { if (!response.ok) throw new Error('网络异常'); return response.blob() }) .then(blob => { const blobUrl = URL.createObjectURL(blob); console.log(blobUrl); const link = document.createElement('a'); link.href = blobUrl; link.download = filename || 'image.jpg'; document.body.appendChild(link); link.click(); setTimeout(() => { document.body.removeChild(link); URL.revokeObjectURL(blobUrl); }, 100); resolve(); }) .catch(error => { console.error(error); alert('下载失败'); reject(error); }); }); } initDownloadButtons(); JS); } /* * 用于详情页,图片下载与放大 HTML */ public static function viewDownloadEnlargeHtml() { return '
'; } }