From 8337c34fcc761d07acaad796d10f3e12e9bbe2d1 Mon Sep 17 00:00:00 2001
From: lrj <owen.stl@gmail.com>
Date: 星期日, 05 十月 2025 08:56:04 +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