'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, status } = 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 () => { if (status !== 'authenticated') return 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, status]) useEffect(() => { if (status === 'unauthenticated') { router.push('/login') return } if (status === 'authenticated') { fetchMaterials() } }, [fetchMaterials, router, status]) return (
{/* 返回按钮 */} {/* 作者信息卡片 */}
{authorStats.avatar ? (
{authorStats.name}
) : (
)}

{authorStats.name}

{authorStats.totalMaterials} 作品
{authorStats.totalDownloads} 下载
{authorStats.totalLikes} 点赞
{/* 作品列表 */} {loading ? (
) : materials.length === 0 ? (

该作者暂无作品

) : ( <>
{materials.map((material) => (
{material.productModel}

{material.productModel}

{material.materialType || material.categoryName}
{material.downloadCount} {material.likeCount}
))}
{/* 分页 */} {totalPages > 1 && (
{page} / {totalPages}
)} )}
) }