94 lines
2.9 KiB
TypeScript
94 lines
2.9 KiB
TypeScript
import React, { useRef } from 'react';
|
|
import { Button } from 'tdesign-mobile-react';
|
|
import { X } from 'lucide-react';
|
|
import { uploadImage } from '@/api/upload';
|
|
|
|
interface UploadVideoProps {
|
|
value?: string;
|
|
onChange?: (url: string) => void;
|
|
accept?: string;
|
|
disabled?: boolean;
|
|
}
|
|
|
|
const VIDEO_BOX_CLASS =
|
|
'relative flex items-center justify-center w-full aspect-[16/9] rounded-2xl border-2 border-dashed border-blue-300 bg-gray-50 overflow-hidden';
|
|
|
|
const UploadVideo: React.FC<UploadVideoProps> = ({
|
|
value,
|
|
onChange,
|
|
accept = 'video/mp4,video/webm,video/ogg,video/quicktime,video/x-msvideo,video/x-ms-wmv,video/x-flv,video/x-matroska',
|
|
disabled,
|
|
}) => {
|
|
const inputRef = useRef<HTMLInputElement>(null);
|
|
|
|
// 选择文件并上传
|
|
const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
const file = e.target.files?.[0];
|
|
if (!file) return;
|
|
try {
|
|
const url = await uploadImage(file);
|
|
onChange?.(url);
|
|
} catch (err: any) {
|
|
alert(err?.message || '上传失败');
|
|
} finally {
|
|
if (inputRef.current) inputRef.current.value = '';
|
|
}
|
|
};
|
|
|
|
// 触发文件选择
|
|
const handleClick = () => {
|
|
if (!disabled) inputRef.current?.click();
|
|
};
|
|
|
|
// 删除视频
|
|
const handleDelete = () => {
|
|
onChange?.('');
|
|
};
|
|
|
|
return (
|
|
<div className="flex flex-col items-center w-full">
|
|
{!value ? (
|
|
<div className={VIDEO_BOX_CLASS}>
|
|
<input
|
|
ref={inputRef}
|
|
type="file"
|
|
accept={accept}
|
|
style={{ display: 'none' }}
|
|
onChange={handleFileChange}
|
|
disabled={disabled}
|
|
/>
|
|
<button
|
|
type="button"
|
|
className="flex flex-col items-center justify-center w-full h-full bg-transparent border-none outline-none cursor-pointer"
|
|
onClick={handleClick}
|
|
disabled={disabled}
|
|
>
|
|
<span className="text-3xl mb-2">🎬</span>
|
|
<span className="text-base text-gray-500 font-medium">点击上传视频</span>
|
|
<span className="text-xs text-gray-400 mt-1">支持MP4、WebM、MOV等格式</span>
|
|
</button>
|
|
</div>
|
|
) : (
|
|
<div className={VIDEO_BOX_CLASS}>
|
|
<video
|
|
src={value}
|
|
controls
|
|
className="w-full h-full object-cover rounded-2xl bg-black"
|
|
style={{ background: '#000' }}
|
|
/>
|
|
<button
|
|
type="button"
|
|
className="absolute top-2 right-2 z-10 bg-white/80 hover:bg-white rounded-full p-1 shadow"
|
|
onClick={handleDelete}
|
|
disabled={disabled}
|
|
aria-label="删除视频"
|
|
>
|
|
<X className="w-5 h-5 text-gray-600" />
|
|
</button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default UploadVideo;
|