Files
ViGent2/frontend/src/components/VideoPreviewModal.tsx
Kevin Wong be6a3436bb 更新
2026-02-05 12:03:55 +08:00

82 lines
2.9 KiB
TypeScript

"use client";
import { useEffect } from "react";
import { X, Video } from "lucide-react";
interface VideoPreviewModalProps {
videoUrl: string | null;
onClose: () => void;
title?: string;
subtitle?: string;
}
export default function VideoPreviewModal({
videoUrl,
onClose,
title = "视频预览",
subtitle = "ESC 关闭 · 点击空白关闭",
}: VideoPreviewModalProps) {
useEffect(() => {
if (!videoUrl) return;
// 按 ESC 关闭
const handleEsc = (e: KeyboardEvent) => {
if (e.key === 'Escape') onClose();
};
const prevOverflow = document.body.style.overflow;
document.addEventListener('keydown', handleEsc);
// 禁止背景滚动
document.body.style.overflow = 'hidden';
return () => {
document.removeEventListener('keydown', handleEsc);
document.body.style.overflow = prevOverflow;
};
}, [videoUrl, onClose]);
if (!videoUrl) return null;
return (
<div
className="fixed inset-0 z-[200] flex items-center justify-center bg-black/80 backdrop-blur-sm p-4 animate-in fade-in duration-200"
onClick={onClose}
>
<div
className="relative w-full max-w-4xl bg-gray-900 border border-white/10 rounded-2xl shadow-2xl overflow-hidden flex flex-col"
onClick={(e) => e.stopPropagation()}
>
<div className="flex items-center justify-between px-6 py-3 border-b border-white/10 bg-gradient-to-r from-white/5 via-white/0 to-white/5">
<div className="flex items-center gap-3">
<div className="h-9 w-9 rounded-lg bg-white/10 flex items-center justify-center text-white">
<Video className="h-5 w-5" />
</div>
<div>
<h3 className="text-lg font-semibold text-white">
{title}
</h3>
<p className="text-xs text-gray-400">
{subtitle}
</p>
</div>
</div>
<button
onClick={onClose}
className="p-2 text-gray-400 hover:text-white hover:bg-white/10 rounded-lg transition-colors"
>
<X className="h-5 w-5" />
</button>
</div>
<div className="bg-black flex items-center justify-center min-h-[50vh] max-h-[80vh]">
<video
src={videoUrl}
controls
autoPlay
preload="metadata"
className="w-full h-full max-h-[80vh] object-contain"
/>
</div>
</div>
</div>
);
}