import type { Metadata } from "next"; import BackButton from "@/app/components/BackButton"; import { getFileUrl } from "@/lib/minio"; import { parsePlaybackContext } from "@/lib/playback-context"; import { resolvePlayback } from "@/lib/playback-context.server"; import { prisma } from "@/lib/prisma"; import AwemeDetailClient from "./Client"; import type { AwemeData, VideoTranscript } from "./types"; export async function generateMetadata({ params, }: { params: Promise<{ awemeId: string }>; }): Promise { const id = (await params).awemeId; const [video, post] = await Promise.all([ prisma.video.findUnique({ where: { aweme_id: id }, select: { desc: true, author: { select: { nickname: true } } }, }), prisma.imagePost.findUnique({ where: { aweme_id: id }, select: { desc: true, author: { select: { nickname: true } } }, }), ]); const data = video || post; if (!data) { return { title: "作品不存在", }; } const desc = data.desc || "查看作品详情"; const author = data.author.nickname; const title = desc.length > 50 ? `${desc.slice(0, 50)}... - ${author}` : `${desc} - ${author}`; return { title, description: desc, }; } export default async function AwemeDetail({ params, searchParams, }: { params: Promise<{ awemeId: string }>; searchParams: Promise>; }) { const id = (await params).awemeId; const [video, post] = await Promise.all([ prisma.video.findUnique({ where: { aweme_id: id }, include: { author: true, transcript: true }, }), prisma.imagePost.findUnique({ where: { aweme_id: id }, include: { author: true, images: { orderBy: { order: "asc" } } }, }), ]); if (!video && !post) return
找不到该作品
; const isVideo = Boolean(video); // 获取评论总数 const commentsCount = await prisma.comment.count({ where: isVideo ? { videoId: id } : { imagePostId: id }, }); let data: AwemeData; let transcript: VideoTranscript | null = null; if (video) { transcript = video.transcript ?? null; data = { type: "video", aweme_id: video.aweme_id, desc: video.desc, created_at: video.created_at, likesCount: Number(video.digg_count), commentsCount, author: { nickname: video.author.nickname, avatar_url: getFileUrl(video.author.avatar_url || "default-avatar.png"), sec_uid: video.author.sec_uid, }, cover_url: getFileUrl(video.cover_url ?? "default-cover.png"), cover_size: { h: video.height ?? 0, w: video.width ?? 0 }, duration_ms: video.duration_ms, video_url: getFileUrl(video.video_url), width: video.width ?? null, height: video.height ?? null, content_tags: video.manual_content_tags, manual_content_tags: video.manual_content_tags, }; } else if (post) { const coverImage = post.images[0]; data = { type: "image", aweme_id: post.aweme_id, desc: post.desc, created_at: post.created_at, likesCount: Number(post.digg_count), commentsCount, author: { nickname: post.author.nickname, avatar_url: getFileUrl(post.author.avatar_url || "default-avatar.png"), sec_uid: post.author.sec_uid, }, cover_url: getFileUrl(coverImage?.url ?? "default-cover.png"), cover_size: { h: coverImage?.height ?? 0, w: coverImage?.width ?? 0, }, images: post.images.map((img) => ({ ...img, url: getFileUrl(img.url), animated: img.animated ? getFileUrl(img.animated) : null, })), music_url: getFileUrl(post.music_url || "default-music.mp3"), }; } else { return
找不到该作品
; } const authorId = video?.authorId ?? post?.authorId ?? null; const [playback, authorWorksCount] = await Promise.all([ resolvePlayback(id, parsePlaybackContext(await searchParams)), authorId ? Promise.all([ prisma.video.count({ where: { authorId } }), prisma.imagePost.count({ where: { authorId } }), ]).then(([videos, posts]) => videos + posts) : 0, ]); return (
{/* 顶部条改为悬浮在媒体区域之上,避免 sticky 造成 Y 方向滚动条 */}
); } export const dynamic = "force-dynamic";