From 9f8395fab13ca4b230a0f7d62636e209745c91d4 Mon Sep 17 00:00:00 2001 From: lrj <owen.stl@gmail.com> Date: 星期日, 28 九月 2025 14:16:18 +0800 Subject: [PATCH] feat: 完善注册流程的文件上传功能 --- web/src/views/carousel/CarouselForm.vue | 139 +++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 130 insertions(+), 9 deletions(-) diff --git a/web/src/views/carousel/CarouselForm.vue b/web/src/views/carousel/CarouselForm.vue index c70e63a..1e53814 100644 --- a/web/src/views/carousel/CarouselForm.vue +++ b/web/src/views/carousel/CarouselForm.vue @@ -74,7 +74,23 @@ <!-- 瑙嗛棰勮 --> <div v-else-if="isVideo(media)" class="media-preview"> - <video :src="media.url" class="media-video" controls></video> + <div class="video-thumbnail-container" @click="playVideo(media)"> + <img + v-if="media.thumbUrl || media.fullThumbUrl" + :src="media.thumbUrl || media.fullThumbUrl" + class="video-thumbnail" + /> + <div v-else class="video-placeholder"> + <span>瑙嗛缂╃暐鍥�</span> + </div> + <div class="video-play-overlay"> + <div class="video-play-button"> + <svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> + <path d="M8 5v14l11-7z"/> + </svg> + </div> + </div> + </div> <div class="media-info"> <div class="media-name">{{ media.name }}</div> <div class="media-actions"> @@ -145,7 +161,9 @@ import { ElMessage, ElMessageBox } from 'element-plus' import { Plus } from '@element-plus/icons-vue' import { CarouselApi } from '@/api/carousel' -import { getMediasByTarget, deleteMedia, uploadFile } from '@/api/media' +import { getMediasByTarget, deleteMedia, uploadFile, uploadVideoWithThumbnail } from '@/api/media' +import { isVideoFile } from '@/utils/video.js' +import { MediaTargetType } from '@/constants/mediaTargetType' const props = defineProps({ modelValue: Boolean, @@ -196,7 +214,7 @@ try { console.log('=== 鍔犺浇杞挱鍥惧獟浣� ==='); console.log('杞挱鍥綢D:', data.id); - const medias = await getMediasByTarget(4, parseInt(data.id)) + const medias = await getMediasByTarget(MediaTargetType.CAROUSEL, parseInt(data.id)) console.log('鑾峰彇鍒扮殑濯掍綋鍒楄〃:', medias); // 杞崲濯掍綋鏁版嵁鏍煎紡锛屾爣璁颁负宸插瓨鍦ㄧ殑鏂囦欢 @@ -257,6 +275,17 @@ return false } +// 鎾斁瑙嗛 +const playVideo = (media) => { + const videoUrl = media.url || media.fullUrl + if (videoUrl) { + // 鍦ㄦ柊绐楀彛涓墦寮�瑙嗛 + window.open(videoUrl, '_blank') + } else { + ElMessage.warning('瑙嗛鏂囦欢涓嶅瓨鍦�') + } +} + // 澶勭悊濯掍綋鏂囦欢涓婁紶 const handleMediaFileUpload = async (carouselId) => { console.log('=== 寮�濮嬩笂浼犲獟浣撴枃浠� ==='); @@ -270,25 +299,54 @@ try { console.log('涓婁紶鏂囦欢:', media.name); - // 涓婁紶鏂囦欢 - const uploadResult = await uploadFile(media.file); - console.log('涓婁紶缁撴灉:', uploadResult); + let uploadResult; + let thumbnailPath = null; + + // 妫�鏌ユ槸鍚︿负瑙嗛鏂囦欢 + if (isVideoFile(media.file)) { + console.log('妫�娴嬪埌瑙嗛鏂囦欢锛屽紑濮嬪鐞嗚棰戝拰缂╃暐鍥�...'); + + // 浣跨敤瑙嗛涓撶敤涓婁紶鍑芥暟 + const videoResult = await uploadVideoWithThumbnail(media.file); + uploadResult = videoResult.video; + thumbnailPath = videoResult.thumbnail.path; + + console.log('瑙嗛鍜岀缉鐣ュ浘涓婁紶瀹屾垚:', { + video: uploadResult, + thumbnail: videoResult.thumbnail + }); + } else { + // 鏅�氭枃浠朵笂浼� + uploadResult = await uploadFile(media.file); + console.log('鏂囦欢涓婁紶缁撴灉:', uploadResult); + } if (uploadResult.success) { // 淇濆瓨濯掍綋淇℃伅鍒版暟鎹簱 - await CarouselApi.saveMedia({ + const mediaData = { name: uploadResult.fileName, path: uploadResult.path, fileSize: uploadResult.fileSize, fileExt: uploadResult.fileName.split('.').pop() || 'jpg', mediaType: isVideo(media) ? 2 : 1, // 1琛ㄧず鍥剧墖锛�2琛ㄧず瑙嗛 - targetType: 4, // 4琛ㄧず杞挱鍥� + targetType: MediaTargetType.CAROUSEL, // 杞挱鍥� targetId: parseInt(carouselId) - }); + }; + + // 濡傛灉鏄棰戞枃浠讹紝娣诲姞缂╃暐鍥捐矾寰� + if (thumbnailPath) { + mediaData.thumbPath = thumbnailPath; + console.log('娣诲姞缂╃暐鍥捐矾寰�:', thumbnailPath); + } + + await CarouselApi.saveMedia(mediaData); // 鏍囪涓哄凡涓婁紶 media.uploaded = true; media.url = uploadResult.fullUrl; + if (thumbnailPath) { + media.thumbnailUrl = thumbnailPath; + } console.log('鏂囦欢涓婁紶骞朵繚瀛樻垚鍔�:', media.name); } } catch (error) { @@ -472,6 +530,69 @@ border-radius: 4px; } +.video-thumbnail-container { + position: relative; + width: 200px; + height: 120px; + cursor: pointer; + border-radius: 4px; + overflow: hidden; +} + +.video-thumbnail { + width: 100%; + height: 100%; + object-fit: cover; + border-radius: 4px; +} + +.video-placeholder { + width: 100%; + height: 100%; + background: #f0f0f0; + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; + color: #999; + font-size: 14px; +} + +.video-play-overlay { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + display: flex; + align-items: center; + justify-content: center; + background: rgba(0, 0, 0, 0.3); + opacity: 0; + transition: opacity 0.3s ease; +} + +.video-thumbnail-container:hover .video-play-overlay { + opacity: 1; +} + +.video-play-button { + width: 48px; + height: 48px; + background: rgba(255, 255, 255, 0.9); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + color: #333; + transition: all 0.3s ease; +} + +.video-play-button:hover { + background: rgba(255, 255, 255, 1); + transform: scale(1.1); +} + .file-icon { font-size: 48px; margin-bottom: 8px; -- Gitblit v1.8.0