blob: 3f0c6e2236444ed5a63276bad76fa7dd1d14c9f9 [file] [log] [blame]
9563036699de8c092025-06-21 16:41:18 +08001import React, { useState } from 'react'
2import VideoPreview from './VideoPreview'
3import { Play } from 'lucide-react'
4
5// 判断文件是否为视频
6const isVideoFile = (url) => {
7 if (!url) return false
8 const videoExtensions = ['.mp4', '.webm', '.ogg', '.avi', '.mov', '.wmv', '.flv', '.mkv']
9 const lowerUrl = url.toLowerCase()
10 return videoExtensions.some(ext => lowerUrl.includes(ext)) || lowerUrl.includes('video')
11}
12
13// 媒体预览组件(支持图片和视频)
14const MediaPreview = ({
15 url,
16 alt = '',
17 className = '',
18 style = {},
19 onClick = null,
20 showPlayIcon = true,
21 maxWidth = 220,
22 maxHeight = 220
23}) => {
24 const [showVideoPreview, setShowVideoPreview] = useState(false)
25
26 const handleMediaClick = () => {
27 if (isVideoFile(url)) {
28 setShowVideoPreview(true)
29 } else if (onClick) {
30 onClick(url)
31 }
32 }
33
34 const defaultStyle = {
35 maxWidth,
36 maxHeight,
37 borderRadius: 8,
38 objectFit: 'cover',
39 cursor: 'pointer',
40 ...style
41 }
42
43 if (isVideoFile(url)) {
44 return (
45 <>
46 <div style={{ position: 'relative', ...defaultStyle }} onClick={handleMediaClick}>
47 <video
48 src={url}
49 style={defaultStyle}
50 preload="metadata"
51 muted
52 />
53 {showPlayIcon && (
54 <div style={{
55 position: 'absolute',
56 top: '50%',
57 left: '50%',
58 transform: 'translate(-50%, -50%)',
59 background: 'rgba(0,0,0,0.6)',
60 borderRadius: '50%',
61 padding: 12,
62 color: 'white'
63 }}>
64 <Play size={24} fill="white" />
65 </div>
66 )}
67 </div>
68
69 {/* 视频预览弹窗 */}
70 {showVideoPreview && (
71 <div
72 style={{
73 position: 'fixed',
74 zIndex: 9999,
75 top: 0,
76 left: 0,
77 right: 0,
78 bottom: 0,
79 background: 'rgba(0,0,0,0.8)',
80 display: 'flex',
81 alignItems: 'center',
82 justifyContent: 'center',
83 padding: 20
84 }}
85 onClick={() => setShowVideoPreview(false)}
86 >
87 <div
88 style={{
89 maxWidth: '90vw',
90 maxHeight: '90vh',
91 width: 'auto',
92 height: 'auto'
93 }}
94 onClick={(e) => e.stopPropagation()}
95 >
96 <VideoPreview
97 src={url}
98 onClose={() => setShowVideoPreview(false)}
99 style={{ borderRadius: 12, overflow: 'hidden' }}
100 />
101 </div>
102 </div>
103 )}
104 </>
105 )
106 }
107
108 return (
109 <img
110 src={url}
111 alt={alt}
112 className={className}
113 style={defaultStyle}
114 onClick={handleMediaClick}
115 />
116 )
117}
118
119export default MediaPreview