优化图文页

This commit is contained in:
2026-04-28 17:11:42 +08:00
parent 674c202264
commit 040273586b
69 changed files with 3939 additions and 2302 deletions
+42 -20
View File
@@ -6,7 +6,11 @@ import { FeedItem } from "@/app/types/feed";
import { notFound } from "next/navigation";
import Image from "next/image";
export default async function AuthorPage({ params }: { params: Promise<{ secUid: string }> }) {
export default async function AuthorPage({
params,
}: {
params: Promise<{ secUid: string }>;
}) {
const secUid = (await params).secUid;
const author = await prisma.author.findUnique({
@@ -22,15 +26,15 @@ export default async function AuthorPage({ params }: { params: Promise<{ secUid:
const [videos, posts] = await Promise.all([
prisma.video.findMany({
where: { authorId: secUid },
orderBy: { created_at: 'desc' },
orderBy: { created_at: "desc" },
take: limit,
include: { author: true },
}),
prisma.imagePost.findMany({
where: { authorId: secUid },
orderBy: { created_at: 'desc' },
orderBy: { created_at: "desc" },
take: limit,
include: { author: true, images: { orderBy: { order: 'asc' }, take: 1 } },
include: { author: true, images: { orderBy: { order: "asc" }, take: 1 } },
}),
]);
@@ -41,11 +45,15 @@ export default async function AuthorPage({ params }: { params: Promise<{ secUid:
created_at: v.created_at,
desc: v.desc,
video_url: getFileUrl(v.video_url),
cover_url: getFileUrl(v.cover_url ?? 'default_cover.png'),
cover_url: getFileUrl(v.cover_url ?? "default_cover.png"),
width: v.width ?? null,
height: v.height ?? null,
author: { nickname: v.author.nickname, avatar_url: getFileUrl(v.author.avatar_url ?? ''), sec_uid: v.author.sec_uid },
likes: Number(v.digg_count)
author: {
nickname: v.author.nickname,
avatar_url: getFileUrl(v.author.avatar_url ?? ""),
sec_uid: v.author.sec_uid,
},
likes: Number(v.digg_count),
})),
...posts.map((p) => ({
type: "image" as const,
@@ -55,13 +63,23 @@ export default async function AuthorPage({ params }: { params: Promise<{ secUid:
cover_url: getFileUrl(p.images?.[0]?.url ?? null),
width: p.images?.[0]?.width ?? null,
height: p.images?.[0]?.height ?? null,
author: { nickname: p.author.nickname, avatar_url: getFileUrl(p.author.avatar_url ?? ''), sec_uid: p.author.sec_uid },
likes: Number(p.digg_count)
author: {
nickname: p.author.nickname,
avatar_url: getFileUrl(p.author.avatar_url ?? ""),
sec_uid: p.author.sec_uid,
},
likes: Number(p.digg_count),
})),
].sort((a, b) => +new Date(b.created_at) - +new Date(a.created_at))
]
.sort((a, b) => +new Date(b.created_at) - +new Date(a.created_at))
.slice(0, limit);
const initialCursor = initialItems.length > 0 ? new Date(initialItems[initialItems.length - 1].created_at as any).toISOString() : null;
const initialCursor =
initialItems.length > 0
? new Date(
initialItems[initialItems.length - 1].created_at as any,
).toISOString()
: null;
return (
<main className="min-h-screen bg-white dark:bg-black text-black dark:text-white">
@@ -75,21 +93,21 @@ export default async function AuthorPage({ params }: { params: Promise<{ secUid:
<div className="flex flex-col md:flex-row items-center md:items-start gap-6 mb-12">
<div className="relative w-24 h-24 md:w-32 md:h-32 shrink-0">
<Image
src={getFileUrl(author.avatar_url || 'default-avatar.png')}
src={getFileUrl(author.avatar_url || "default-avatar.png")}
alt={author.nickname}
fill
className="rounded-full object-cover border-2 border-gray-200 dark:border-gray-800"
/>
</div>
<div className="flex-1 text-center md:text-left space-y-4">
<div>
<h2 className="text-2xl font-bold">{author.nickname}</h2>
<p className="text-sm text-gray-500 dark:text-gray-400 mt-1">
抖音号:{author.unique_id || author.short_id || '未知'}
抖音号:{author.unique_id || author.short_id || "未知"}
</p>
</div>
{author.signature && (
<p className="text-gray-700 dark:text-gray-300 whitespace-pre-wrap max-w-2xl">
{author.signature}
@@ -98,11 +116,15 @@ export default async function AuthorPage({ params }: { params: Promise<{ secUid:
<div className="flex items-center justify-center md:justify-start gap-6 text-sm">
<div className="flex items-center gap-1">
<span className="font-bold text-lg">{Number(author.total_favorited).toLocaleString()}</span>
<span className="font-bold text-lg">
{Number(author.total_favorited).toLocaleString()}
</span>
<span className="text-gray-500">获赞</span>
</div>
<div className="flex items-center gap-1">
<span className="font-bold text-lg">{Number(author.follower_count).toLocaleString()}</span>
<span className="font-bold text-lg">
{Number(author.follower_count).toLocaleString()}
</span>
<span className="text-gray-500">粉丝</span>
</div>
</div>
@@ -111,9 +133,9 @@ export default async function AuthorPage({ params }: { params: Promise<{ secUid:
<div className="border-t border-gray-200 dark:border-gray-800 pt-8">
<h3 className="text-lg font-semibold mb-6">作品</h3>
<FeedMasonry
initialItems={initialItems}
initialCursor={initialCursor}
<FeedMasonry
initialItems={initialItems}
initialCursor={initialCursor}
fetchUrl={`/api/author/${secUid}/feed`}
/>
</div>