'use client' import { useState, useEffect, useCallback } from 'react' import { useSession } from 'next-auth/react' import { useParams, useRouter } from 'next/navigation' import Image from 'next/image' import Link from 'next/link' import Header from '@/components/Header' import { useThemeStyles, cn } from '@/lib/ui-styles' // 内联SVG图标组件 const UserIcon = ({ className }: { className?: string }) => ( ) const ArrowLeftIcon = ({ className }: { className?: string }) => ( ) const DownloadIcon = ({ className }: { className?: string }) => ( ) const HeartIcon = ({ className }: { className?: string }) => ( ) const ChevronLeftIcon = ({ className }: { className?: string }) => ( ) const ChevronRightIcon = ({ className }: { className?: string }) => ( ) interface Material { id: string productModel: string previewUrl: string materialType: string | null categoryName: string sceneName: string downloadCount: number likeCount: number createdAt: string user?: { username: string avatar: string | null } } interface AuthorMaterialsResponse { materials: Material[] pagination: { page: number pageSize: number total: number totalPages: number } author: { name: string totalMaterials: number totalDownloads: number totalLikes: number } } export default function AuthorPage() { const { data: session } = useSession() const params = useParams() const router = useRouter() const styles = useThemeStyles() const authorName = decodeURIComponent(params.authorName as string) const [materials, setMaterials] = useState([]) const [loading, setLoading] = useState(true) const [page, setPage] = useState(1) const [totalPages, setTotalPages] = useState(1) const [authorStats, setAuthorStats] = useState({ name: authorName, totalMaterials: 0, totalDownloads: 0, totalLikes: 0, avatar: null as string | null, }) const pageSize = 20 const fetchMaterials = useCallback(async () => { setLoading(true) try { const res = await fetch( `/api/materials?authorName=${encodeURIComponent(authorName)}&page=${page}&pageSize=${pageSize}` ) if (res.ok) { const data = await res.json() setMaterials(data.materials || []) setTotalPages(data.pagination?.totalPages || 1) // 计算作者统计 if (data.materials?.length > 0) { const totalDownloads = data.materials.reduce( (sum: number, m: Material) => sum + m.downloadCount, 0 ) const totalLikes = data.materials.reduce( (sum: number, m: Material) => sum + m.likeCount, 0 ) // 获取作者头像(从第一个素材的用户信息中获取) const authorAvatar = data.materials[0]?.user?.avatar || null setAuthorStats({ name: authorName, totalMaterials: data.pagination?.total || data.materials.length, totalDownloads, totalLikes, avatar: authorAvatar, }) } } } catch (error) { console.error('Failed to fetch author materials:', error) } finally { setLoading(false) } }, [authorName, page]) useEffect(() => { fetchMaterials() }, [fetchMaterials]) return ( {/* 返回按钮 */} router.back()} className="flex items-center gap-2 text-slate-600 dark:text-slate-400 hover:text-slate-900 dark:hover:text-white mb-6 transition-colors" > 返回 {/* 作者信息卡片 */} {authorStats.avatar ? ( ) : ( )} {authorStats.name} {authorStats.totalMaterials} 作品 {authorStats.totalDownloads} 下载 {authorStats.totalLikes} 点赞 {/* 作品列表 */} {loading ? ( ) : materials.length === 0 ? ( 该作者暂无作品 ) : ( <> {materials.map((material) => ( {material.productModel} {material.materialType || material.categoryName} {material.downloadCount} {material.likeCount} ))} {/* 分页 */} {totalPages > 1 && ( setPage((p) => Math.max(1, p - 1))} disabled={page === 1} className="p-2 rounded-lg hover:bg-slate-100 dark:hover:bg-slate-700 disabled:opacity-50 disabled:cursor-not-allowed" > {page} / {totalPages} setPage((p) => Math.min(totalPages, p + 1))} disabled={page === totalPages} className="p-2 rounded-lg hover:bg-slate-100 dark:hover:bg-slate-700 disabled:opacity-50 disabled:cursor-not-allowed" > )} > )} ) }
该作者暂无作品