"use client" import type React from "react" import { useState, useRef, useEffect, useCallback } from "react" import { Button } from "@/components/ui/button" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Badge } from "@/components/ui/badge" import { Progress } from "@/components/ui/progress" import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" import { Upload, ImageIcon, Trash2, Eye, Info, CheckCircle } from "lucide-react" interface ImageData { id: string name: string url: string size: number type: string } interface DataCollectionStepProps { onNext?: () => void selectedImages: string[] onImagesChange: (images: string[]) => void } const sampleImageCategories = { landscape: { name: "风景画", images: [ { id: "landscape-1", name: "山水湖泊.jpg", url: "/mountain-lake-painting.png", size: 245760, type: "image/jpeg" }, { id: "landscape-2", name: "日出山峰.jpg", url: "/sunrise-mountain-peaks.png", size: 234560, type: "image/jpeg" }, { id: "landscape-3", name: "森林小径.jpg", url: "/forest-path-painting.png", size: 267890, type: "image/jpeg" }, { id: "landscape-4", name: "海边日落.jpg", url: "/sunset-beach-painting.png", size: 298765, type: "image/jpeg" }, { id: "landscape-5", name: "雪山风光.jpg", url: "/snowy-mountain-landscape.png", size: 312450, type: "image/jpeg", }, { id: "landscape-6", name: "田园风光.jpg", url: "/pastoral-landscape.png", size: 287650, type: "image/jpeg" }, { id: "landscape-7", name: "瀑布奇观.jpg", url: "/waterfall-landscape.png", size: 345670, type: "image/jpeg" }, { id: "landscape-8", name: "沙漠绿洲.jpg", url: "/desert-oasis-painting.png", size: 276540, type: "image/jpeg" }, { id: "landscape-9", name: "湖光山色.jpg", url: "/lake-mountain-reflection-painting.png", size: 298760, type: "image/jpeg", }, { id: "landscape-10", name: "秋叶满山.jpg", url: "/autumn-mountain-foliage-painting.png", size: 321450, type: "image/jpeg", }, ], }, portrait: { name: "人物肖像", images: [ { id: "portrait-1", name: "经典肖像.jpg", url: "/artistic-portrait.png", size: 312320, type: "image/jpeg" }, { id: "portrait-2", name: "女性肖像.jpg", url: "/elegant-woman-portrait.png", size: 298450, type: "image/jpeg" }, { id: "portrait-3", name: "老人肖像.jpg", url: "/elderly-man-portrait.png", size: 287650, type: "image/jpeg" }, { id: "portrait-4", name: "儿童肖像.jpg", url: "/child-portrait-painting.png", size: 276540, type: "image/jpeg" }, { id: "portrait-5", name: "艺术家自画像.jpg", url: "/artist-self-portrait.png", size: 345670, type: "image/jpeg", }, { id: "portrait-6", name: "古典美人.jpg", url: "/classical-beauty-portrait.png", size: 321450, type: "image/jpeg", }, { id: "portrait-7", name: "现代肖像.jpg", url: "/modern-portrait-painting.png", size: 298760, type: "image/jpeg", }, { id: "portrait-8", name: "侧面肖像.jpg", url: "/profile-portrait-painting.png", size: 287650, type: "image/jpeg", }, { id: "portrait-9", name: "双人肖像.jpg", url: "/couple-portrait-painting.png", size: 356780, type: "image/jpeg", }, { id: "portrait-10", name: "表情肖像.jpg", url: "/expressive-portrait-painting.png", size: 312450, type: "image/jpeg", }, ], }, abstract: { name: "抽象艺术", images: [ { id: "abstract-1", name: "几何抽象.jpg", url: "/colorful-geometric-abstract.png", size: 189440, type: "image/jpeg", }, { id: "abstract-2", name: "色彩流动.jpg", url: "/flowing-colors-abstract.png", size: 234560, type: "image/jpeg", }, { id: "abstract-3", name: "线条构成.jpg", url: "/linear-composition-abstract.png", size: 267890, type: "image/jpeg", }, { id: "abstract-4", name: "色块拼接.jpg", url: "/color-blocks-abstract.png", size: 298765, type: "image/jpeg", }, { id: "abstract-5", name: "动感抽象.jpg", url: "/dynamic-abstract-painting.png", size: 312450, type: "image/jpeg", }, { id: "abstract-6", name: "纹理抽象.jpg", url: "/textured-abstract-art.png", size: 287650, type: "image/jpeg", }, { id: "abstract-7", name: "光影抽象.jpg", url: "/light-shadow-abstract.png", size: 345670, type: "image/jpeg", }, { id: "abstract-8", name: "螺旋构图.jpg", url: "/spiral-composition-abstract.png", size: 276540, type: "image/jpeg", }, { id: "abstract-9", name: "对比抽象.jpg", url: "/contrast-abstract-painting.png", size: 298760, type: "image/jpeg", }, { id: "abstract-10", name: "渐变抽象.jpg", url: "/gradient-abstract-art.png", size: 321450, type: "image/jpeg", }, ], }, stilllife: { name: "静物画", images: [ { id: "stilllife-1", name: "花卉静物.jpg", url: "/floral-still-life.png", size: 278528, type: "image/jpeg" }, { id: "stilllife-2", name: "水果静物.jpg", url: "/fruit-still-life.png", size: 234560, type: "image/jpeg", }, { id: "stilllife-3", name: "花瓶静物.jpg", url: "/vase-still-life.png", size: 267890, type: "image/jpeg", }, { id: "stilllife-4", name: "书籍静物.jpg", url: "/books-still-life.png", size: 298765, type: "image/jpeg", }, { id: "stilllife-5", name: "茶具静物.jpg", url: "/tea-set-still-life.png", size: 312450, type: "image/jpeg", }, { id: "stilllife-6", name: "蜡烛静物.jpg", url: "/candle-still-life.png", size: 287650, type: "image/jpeg", }, { id: "stilllife-7", name: "乐器静物.jpg", url: "/musical-instrument-still-life.png", size: 345670, type: "image/jpeg", }, { id: "stilllife-8", name: "古董静物.jpg", url: "/antique-still-life.png", size: 276540, type: "image/jpeg", }, { id: "stilllife-9", name: "厨具静物.jpg", url: "/kitchen-utensils-still-life.png", size: 298760, type: "image/jpeg", }, { id: "stilllife-10", name: "珠宝静物.jpg", url: "/jewelry-still-life.png", size: 321450, type: "image/jpeg", }, ], }, } export default function DataCollectionStep({ onNext, selectedImages: selectedImageUrls, onImagesChange, }: DataCollectionStepProps) { const [selectedImages, setSelectedImages] = useState([]) const [uploadedImages, setUploadedImages] = useState([]) const [selectedCategory, setSelectedCategory] = useState("landscape") const fileInputRef = useRef(null) useEffect(() => { if (selectedImageUrls.length > 0 && selectedImages.length === 0) { const matchingImages: ImageData[] = [] Object.values(sampleImageCategories).forEach((category) => { category.images.forEach((image) => { if (selectedImageUrls.includes(image.url)) { matchingImages.push(image) } }) }) setSelectedImages(matchingImages) } }, []) // Empty dependency array to run only on mount const handleImagesChange = useCallback(() => { const allImageUrls = [...selectedImages, ...uploadedImages].map((img) => img.url) onImagesChange(allImageUrls) }, [selectedImages, uploadedImages, onImagesChange]) useEffect(() => { handleImagesChange() }, [handleImagesChange]) const handleFileUpload = (event: React.ChangeEvent) => { const files = event.target.files if (!files) return Array.from(files).forEach((file) => { if (file.type.startsWith("image/")) { const reader = new FileReader() reader.onload = (e) => { const newImage: ImageData = { id: `upload-${Date.now()}-${Math.random()}`, name: file.name, url: e.target?.result as string, size: file.size, type: file.type, } setUploadedImages((prev) => [...prev, newImage]) } reader.readAsDataURL(file) } }) } const handleSampleSelect = (image: ImageData) => { if (!selectedImages.find((img) => img.id === image.id)) { setSelectedImages((prev) => [...prev, image]) } } const handleSelectCategory = (categoryKey: string) => { const category = sampleImageCategories[categoryKey as keyof typeof sampleImageCategories] const newImages = category.images.filter((img) => !selectedImages.find((selected) => selected.id === img.id)) setSelectedImages((prev) => [...prev, ...newImages]) } const handleRemoveImage = (imageId: string) => { setSelectedImages((prev) => prev.filter((img) => img.id !== imageId)) setUploadedImages((prev) => prev.filter((img) => img.id !== imageId)) } const formatFileSize = (bytes: number) => { if (bytes === 0) return "0 Bytes" const k = 1024 const sizes = ["Bytes", "KB", "MB", "GB"] const i = Math.floor(Math.log(bytes) / Math.log(k)) return Number.parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i] } const allImages = [...selectedImages, ...uploadedImages] const totalSize = allImages.reduce((sum, img) => sum + img.size, 0) const handleNext = () => { if (onNext && allImages.length > 0) { onNext() } } return (
{/* Introduction */}
什么是数据采集?

数据采集是AI绘画的第一步,也是最关键的步骤。就像人类艺术家需要观察大量的艺术作品来学习绘画技巧一样, AI模型也需要"看到"大量的图像数据来学习如何创作。数据的质量和多样性直接影响AI生成图像的效果。

{/* Data Collection Interface */} 示例数据集 上传图像 选择示例图像 从我们准备的示例数据集中选择图像作为AI的学习材料,每个类别包含10张精选图像 风景画 人物肖像 抽象艺术 静物画 {Object.entries(sampleImageCategories).map(([categoryKey, category]) => (

{category.name} (10张图像)

{category.images.map((image) => { const isSelected = selectedImages.find((img) => img.id === image.id) return (
{image.name}

{image.name}

{formatFileSize(image.size)}

{isSelected ? (
) : ( )}
) })}
))}
上传自定义图像 上传你自己的图像来训练AI模型(支持 JPG, PNG, GIF 格式)
fileInputRef.current?.click()} >

点击上传图像

或将图像文件拖拽到此区域

{uploadedImages.length > 0 && (

已上传的图像

{uploadedImages.map((image) => (
{image.name}

{image.name}

{formatFileSize(image.size)}

))}
)}
{/* Dataset Statistics */} 数据集统计 当前选择的训练数据概览
{allImages.length}
图像总数
{formatFileSize(totalSize)}
总大小
{selectedImages.length}
示例图像
{uploadedImages.length}
上传图像
数据集完整度 {Math.min(100, (allImages.length / 10) * 100).toFixed(0)}%

建议至少选择 10 张图像以获得更好的训练效果

{allImages.length > 0 && (

已选择的图像

{allImages.map((image) => ( {image.name} ))}
)}
{/* Next Step Button */}
) }