feat: 本次提交更新内容如下
改造下视频上传组件
This commit is contained in:
94
nkebao/src/components/UploadVideo.tsx
Normal file
94
nkebao/src/components/UploadVideo.tsx
Normal file
@@ -0,0 +1,94 @@
|
||||
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;
|
||||
@@ -14,6 +14,7 @@ import { Upload } from 'tdesign-mobile-react';
|
||||
import type { UploadFile as TDesignUploadFile } from 'tdesign-mobile-react/es/upload/type';
|
||||
import { uploadImage } from '@/api/upload';
|
||||
import UploadImage from '@/components/UploadImage';
|
||||
import UploadVideo from '@/components/UploadVideo';
|
||||
|
||||
export default function NewMaterial() {
|
||||
const navigate = useNavigate();
|
||||
@@ -161,7 +162,7 @@ export default function NewMaterial() {
|
||||
<select
|
||||
value={contentType}
|
||||
onChange={e => setContentType(Number(e.target.value))}
|
||||
className="w-full h-12 rounded-2xl border border-gray-300 focus:border-blue-500 focus:ring-2 focus:ring-blue-100 px-4 text-base bg-white appearance-none"
|
||||
className="w-full h-12 border border-gray-300 focus:border-blue-500 focus:ring-2 focus:ring-blue-100 px-4 text-base bg-white appearance-none"
|
||||
>
|
||||
<option value="" disabled>请选择类型</option>
|
||||
<option value={1}>图片</option>
|
||||
@@ -217,20 +218,12 @@ export default function NewMaterial() {
|
||||
{contentType === 3 && (
|
||||
<>
|
||||
<Label className="font-bold mb-2">上传视频</Label>
|
||||
<div className="flex items-center gap-4">
|
||||
{!videoUrl ? (
|
||||
<Button type="button" variant="outline" className="rounded-2xl border-dashed border-2 border-blue-300 bg-white hover:bg-blue-50 h-28 w-44 flex flex-col items-center justify-center p-0" onClick={() => setVideoUrl('https://www.w3schools.com/html/mov_bbb.mp4')}>
|
||||
<UploadCloud className="h-8 w-8 mb-2 text-gray-400 mx-auto" />
|
||||
<span className="text-sm text-gray-500">上传视频</span>
|
||||
</Button>
|
||||
) : (
|
||||
<div className="relative">
|
||||
<video src={videoUrl} controls className="object-contain rounded-xl h-24 w-40 mx-auto my-auto" />
|
||||
<Button type="button" variant="base" size="small" className="absolute top-1 right-1 h-8 px-2 rounded-lg" onClick={() => setVideoUrl('')}>删除</Button>
|
||||
</div>
|
||||
)}
|
||||
<div className="pt-4">
|
||||
<UploadVideo
|
||||
value={videoUrl}
|
||||
onChange={setVideoUrl}
|
||||
/>
|
||||
</div>
|
||||
<div className="text-xs text-gray-400 mt-1">支持MP4,建议不超过20MB</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user