This commit is contained in:
2025-12-13 14:46:09 +08:00
parent 1882159d09
commit 83473b457f

View File

@@ -0,0 +1,112 @@
import React, { useEffect, useState } from 'react';
import { X } from 'lucide-react';
interface TransparentMediaOverlayProps {
mediaFilename: string;
mediaType: 'photo' | 'video';
avatarText?: string;
duration?: number; // 展示时长(秒)
onClose: () => void;
}
/**
* 透明窗口媒体展示组件
* 在数字人主页中部弹出,展示媒体文件
*/
export const TransparentMediaOverlay: React.FC<TransparentMediaOverlayProps> = ({
mediaFilename,
mediaType,
avatarText,
duration = 30, // 默认30秒
onClose,
}) => {
const [autoCloseTimer, setAutoCloseTimer] = useState<number>(duration);
const [isClosing, setIsClosing] = useState<boolean>(false);
// 构建媒体文件URL
const mediaUrl = `http://localhost:8000/uploads/${mediaFilename}`;
// 处理关闭(带淡出动画)
const handleClose = () => {
setIsClosing(true);
setTimeout(() => {
onClose();
}, 300); // 等待淡出动画完成
};
// 自动关闭倒计时
useEffect(() => {
const interval = setInterval(() => {
setAutoCloseTimer((prev) => {
if (prev <= 1) {
clearInterval(interval);
handleClose();
return 0;
}
return prev - 1;
});
}, 1000);
return () => clearInterval(interval);
}, []);
return (
<div className={`fixed inset-0 z-50 flex items-center justify-center transition-opacity duration-300 ${
isClosing ? 'opacity-0' : 'opacity-100'
}`}>
{/* 媒体内容容器 - 下调10% */}
<div className="relative w-full h-full flex flex-col items-center justify-center p-4 pt-[calc(1rem+10vh)]">
{/* 媒体内容 - 尽量大 */}
<div className="relative max-w-full max-h-full flex items-center justify-center">
{mediaType === 'photo' ? (
<img
src={mediaUrl}
alt="展示的照片"
className="max-w-full max-h-[90vh] object-contain rounded-2xl shadow-2xl"
onError={(e) => {
console.error('图片加载失败:', mediaUrl);
(e.target as HTMLImageElement).src = '/placeholder-photo.jpg';
}}
/>
) : (
<video
src={mediaUrl}
controls
autoPlay
className="max-w-full max-h-[90vh] object-contain rounded-2xl shadow-2xl"
onError={(e) => {
console.error('视频加载失败:', mediaUrl);
}}
/>
)}
{/* 右上角: 倒计时 + 关闭按钮 */}
<div className="absolute top-3 right-3 flex items-center gap-2">
{/* 倒计时 */}
<div className="bg-black/40 backdrop-blur-md text-white px-3 py-1.5 rounded-full text-sm">
{autoCloseTimer}s
</div>
{/* 关闭按钮 */}
<button
onClick={handleClose}
className="w-10 h-10 flex items-center justify-center bg-black/40 backdrop-blur-md hover:bg-black/60 text-white rounded-full transition-all hover:scale-110 active:scale-95"
aria-label="关闭"
>
<X size={20} />
</button>
</div>
{/* 底部: 标题文字(小半透明) */}
{avatarText && (
<div className="absolute bottom-3 left-3 right-3">
<div className="bg-black/40 backdrop-blur-md text-white px-4 py-2 rounded-lg text-base text-center">
{avatarText}
</div>
</div>
)}
</div>
</div>
</div>
);
};