From adda2077e1eec9463777b21f8c1daf21423db401 Mon Sep 17 00:00:00 2001 From: Xin Wang Date: Thu, 3 Jul 2025 06:28:57 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=92=AD=E6=94=BE=E5=A3=B0?= =?UTF-8?q?=E9=9F=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/video-grid-layout.tsx | 34 ++++++++++++++-- components/video-screen-layout.tsx | 62 ++++++++++++++++++++++++++---- 2 files changed, 85 insertions(+), 11 deletions(-) diff --git a/components/video-grid-layout.tsx b/components/video-grid-layout.tsx index 63006b3..5665864 100644 --- a/components/video-grid-layout.tsx +++ b/components/video-grid-layout.tsx @@ -1,7 +1,7 @@ 'use client'; // Add this to ensure it's a client component import React, { useState } from 'react'; -import { Edit2, Trash2, Play } from 'lucide-react'; +import { Edit2, Trash2, Play, Volume2, VolumeX } from 'lucide-react'; import { Button } from '@/components/ui/button'; import dynamic from 'next/dynamic'; @@ -19,6 +19,7 @@ interface VideoGridLayoutProps { function VideoGridLayoutComponent({ videos, onEdit, onDelete }: VideoGridLayoutProps) { const [hoveredId, setHoveredId] = useState(null); const [isPlaying, setIsPlaying] = useState<{ [key: string]: boolean }>({}); + const [isMuted, setIsMuted] = useState<{ [key: string]: boolean }>({}); const handleMouseEnter = (id: string) => { setHoveredId(id); @@ -26,11 +27,13 @@ function VideoGridLayoutComponent({ videos, onEdit, onDelete }: VideoGridLayoutP const handleMouseLeave = (id: string) => { setHoveredId(null); - // 暂停视频 + // 暂停视频并重新静音以便下次预览 const video = document.getElementById(`video-${id}`) as HTMLVideoElement; if (video) { video.pause(); + video.muted = true; setIsPlaying(prev => ({ ...prev, [id]: false })); + setIsMuted(prev => ({ ...prev, [id]: true })); } }; @@ -38,8 +41,11 @@ function VideoGridLayoutComponent({ videos, onEdit, onDelete }: VideoGridLayoutP const video = document.getElementById(`video-${id}`) as HTMLVideoElement; if (video) { if (video.paused) { + // 在用户主动播放时取消静音 + video.muted = false; video.play(); setIsPlaying(prev => ({ ...prev, [id]: true })); + setIsMuted(prev => ({ ...prev, [id]: false })); } else { video.pause(); setIsPlaying(prev => ({ ...prev, [id]: false })); @@ -47,6 +53,15 @@ function VideoGridLayoutComponent({ videos, onEdit, onDelete }: VideoGridLayoutP } }; + const toggleMute = (id: string, event: React.MouseEvent) => { + event.stopPropagation(); // 防止触发父元素的点击事件 + const video = document.getElementById(`video-${id}`) as HTMLVideoElement; + if (video) { + video.muted = !video.muted; + setIsMuted(prev => ({ ...prev, [id]: video.muted })); + } + }; + return (
{videos.map((video) => ( @@ -64,7 +79,7 @@ function VideoGridLayoutComponent({ videos, onEdit, onDelete }: VideoGridLayoutP suppressHydrationWarning className="w-full h-full object-cover" loop - muted + muted={isMuted[video.id] !== false} // 默认静音,除非明确设置为false playsInline /> @@ -86,6 +101,19 @@ function VideoGridLayoutComponent({ videos, onEdit, onDelete }: VideoGridLayoutP ${hoveredId === video.id ? 'translate-y-0 opacity-100' : 'translate-y-[-10px] opacity-0'} `} > + +
+ + {/* 视频标题 */} +
+

{video.title}

+
+ )} {/* 玻璃态遮罩 - 侧面板半透明效果 */}