gongxiangp2/components/upload/PreviewImageUpload.tsx

120 lines
4.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use client'
import Image from 'next/image'
import { PREVIEW_OPTIONAL_TYPES } from './upload-constants'
interface PreviewImageUploadProps {
materialType: string
previewImages: File[]
previewUrls: string[]
isPreviewDragging: boolean
previewInputRef: React.RefObject<HTMLInputElement>
previewDropZoneRef: React.RefObject<HTMLDivElement>
onPreviewChange: (e: React.ChangeEvent<HTMLInputElement>) => void
onPreviewDragEnter: (e: React.DragEvent) => void
onPreviewDragLeave: (e: React.DragEvent) => void
onPreviewDragOver: (e: React.DragEvent) => void
onPreviewDrop: (e: React.DragEvent) => void
onRemovePreviewImage: (index: number) => void
}
export default function PreviewImageUpload({
materialType,
previewImages,
previewUrls,
isPreviewDragging,
previewInputRef,
previewDropZoneRef,
onPreviewChange,
onPreviewDragEnter,
onPreviewDragLeave,
onPreviewDragOver,
onPreviewDrop,
onRemovePreviewImage,
}: PreviewImageUploadProps) {
return (
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
预览图片
{PREVIEW_OPTIONAL_TYPES.includes(materialType) ? '(可选)' : ' *'}
</label>
<div
ref={previewDropZoneRef}
className={`border-2 border-dashed rounded-apple p-4 transition-colors ${
isPreviewDragging
? 'border-blue-500 bg-blue-50 dark:bg-blue-900/20'
: 'border-gray-300 dark:border-gray-600'
}`}
onDragEnter={onPreviewDragEnter}
onDragLeave={onPreviewDragLeave}
onDragOver={onPreviewDragOver}
onDrop={onPreviewDrop}
>
{/* 已上传的图片预览 */}
{previewUrls.length > 0 && (
<div className="grid grid-cols-4 gap-4 mb-4">
{previewUrls.map((url, index) => (
<div key={index} className="relative group">
<div className="relative w-full h-32 rounded-apple overflow-hidden border-2 border-gray-200 dark:border-gray-600">
<Image
src={url}
alt={`预览图 ${index + 1}`}
fill
unoptimized
className="object-cover"
/>
{index === 0 && (
<div className="absolute top-1 left-1 bg-blue-500 text-white text-xs px-2 py-1 rounded">
主预览图
</div>
)}
</div>
<button
type="button"
onClick={() => onRemovePreviewImage(index)}
className="absolute -top-2 -right-2 bg-red-500 text-white rounded-full w-6 h-6 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity"
>
×
</button>
</div>
))}
</div>
)}
{/* 上传按钮 */}
<div className="flex items-center space-x-4">
<div className="w-32 h-32 rounded-apple bg-gray-100 dark:bg-gray-700 flex items-center justify-center">
<svg className="w-12 h-12 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 4v16m8-8H4" />
</svg>
</div>
<div className="flex-1">
<input
ref={previewInputRef}
type="file"
onChange={onPreviewChange}
accept="image/*"
multiple
className="hidden"
/>
<button
type="button"
onClick={() => previewInputRef.current?.click()}
className="btn-secondary"
>
{previewImages.length > 0 ? '继续添加图片' : '选择图片'}
</button>
<p className="text-xs text-gray-500 dark:text-gray-400 mt-2">
支持 JPG、PNG、WebP 等格式,可一次选择多张或拖拽上传
</p>
<p className="text-xs text-blue-600 dark:text-blue-400 mt-1">
💡 第一张图会自动作为主预览图
</p>
</div>
</div>
</div>
</div>
)
}