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