"use client" import { useState, useMemo } from "react" import { Card } from "@/components/ui/card" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from "@/components/ui/breadcrumb" import { Search, Tag, TrendingUp, Hash, Filter, ArrowRight, Camera, Sparkles } from "lucide-react" import { Photo } from "@/lib/queries" interface TagCloudProps { photos: Photo[] onTagSelect: (tag: string) => void onPhotosView: () => void } interface TagStats { name: string count: number percentage: number recentPhotos: Photo[] categories: string[] } export function TagCloud({ photos, onTagSelect, onPhotosView }: TagCloudProps) { const [searchQuery, setSearchQuery] = useState("") const [sortBy, setSortBy] = useState<'popularity' | 'alphabetical' | 'recent'>('popularity') const [minCount, setMinCount] = useState(1) // 计算标签统计 const tagStats = useMemo(() => { const stats = new Map() // 为没有标签的照片添加默认标签 const allTags = photos.flatMap(photo => photo.tags.length > 0 ? photo.tags : ['未分类'] ) // 统计每个标签 allTags.forEach(tag => { if (!stats.has(tag)) { stats.set(tag, { name: tag, count: 0, percentage: 0, recentPhotos: [], categories: [] }) } }) // 计算详细统计 photos.forEach(photo => { const photoTags = photo.tags.length > 0 ? photo.tags : ['未分类'] photoTags.forEach(tag => { const tagStat = stats.get(tag)! tagStat.count++ tagStat.recentPhotos.push(photo) // 收集分类 if (!tagStat.categories.includes(photo.category)) { tagStat.categories.push(photo.category) } }) }) // 计算百分比和排序最近照片 const totalPhotos = photos.length stats.forEach(stat => { stat.percentage = (stat.count / totalPhotos) * 100 stat.recentPhotos.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()) stat.recentPhotos = stat.recentPhotos.slice(0, 4) // 只保留最近4张 }) return Array.from(stats.values()) }, [photos]) // 过滤和排序标签 const filteredTags = useMemo(() => { let filtered = tagStats.filter(tag => tag.count >= minCount && (searchQuery.trim() === '' || tag.name.toLowerCase().includes(searchQuery.toLowerCase())) ) // 排序 switch (sortBy) { case 'popularity': filtered.sort((a, b) => b.count - a.count) break case 'alphabetical': filtered.sort((a, b) => a.name.localeCompare(b.name)) break case 'recent': filtered.sort((a, b) => { const aLatest = a.recentPhotos[0]?.date || '' const bLatest = b.recentPhotos[0]?.date || '' return bLatest.localeCompare(aLatest) }) break } return filtered }, [tagStats, searchQuery, sortBy, minCount]) // 获取标签字体大小(基于热度) const getTagSize = (percentage: number) => { if (percentage >= 20) return 'text-3xl' if (percentage >= 15) return 'text-2xl' if (percentage >= 10) return 'text-xl' if (percentage >= 5) return 'text-lg' return 'text-base' } // 获取标签颜色 const getTagColor = (count: number, maxCount: number) => { const intensity = count / maxCount if (intensity >= 0.8) return 'bg-red-500 hover:bg-red-600' if (intensity >= 0.6) return 'bg-orange-500 hover:bg-orange-600' if (intensity >= 0.4) return 'bg-yellow-500 hover:bg-yellow-600' if (intensity >= 0.2) return 'bg-green-500 hover:bg-green-600' return 'bg-blue-500 hover:bg-blue-600' } const maxCount = Math.max(...tagStats.map(t => t.count)) const totalTags = tagStats.length const totalUniqueCategories = new Set(photos.map(p => p.category)).size return (
{/* 面包屑导航 */} 摄影作品 标签云 {/* 页面标题和统计 */}

标签云

通过 {totalTags} 个标签探索 {photos.length} 张照片

{/* 统计卡片 */}

{totalTags}

标签总数

{maxCount}

最热标签

{totalUniqueCategories}

涉及分类

{totalTags > 0 ? Math.round(photos.length / totalTags) : 0}

平均每标签

{/* 搜索和过滤控制 */}
setSearchQuery(e.target.value)} className="pl-10" />
{/* 标签云 - 文字云样式 */}
{filteredTags.map((tag) => ( ))}
{/* 详细标签列表 */}

标签详情

{filteredTags.slice(0, 12).map((tag) => ( onTagSelect(tag.name)} >

{tag.name}

{tag.count} 张
占比 {tag.percentage.toFixed(1)}% {tag.categories.length} 个分类
{/* 最近照片预览 */}
{tag.recentPhotos.slice(0, 3).map((photo, idx) => (
{photo.title}
))} {tag.recentPhotos.length > 3 && (
+{tag.recentPhotos.length - 3}
)}
点击查看
))}
{/* 空状态 */} {filteredTags.length === 0 && (

{searchQuery ? '未找到匹配的标签' : '暂无标签'}

{searchQuery ? '尝试使用不同的关键词搜索' : '开始为照片添加标签'}

{searchQuery && ( )}
)}
) }