lrj
昨天 9f8395fab13ca4b230a0f7d62636e209745c91d4
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('轮播图ID:', 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;