74 lines
2.4 KiB
TypeScript
74 lines
2.4 KiB
TypeScript
import { prisma } from "@/lib/prisma";
|
|
import FeedMasonry from "./components/FeedMasonry";
|
|
import SearchBox from "./components/SearchBox";
|
|
import type { FeedItem } from "./types/feed";
|
|
import type { Metadata } from "next";
|
|
import { getFileUrl } from "@/lib/minio";
|
|
|
|
export const dynamic = "force-dynamic";
|
|
|
|
export const metadata: Metadata = {
|
|
title: "作品集 - 抖歪",
|
|
description: "抖歪作品集,记录当下时代的精彩瞬间",
|
|
};
|
|
|
|
export default async function Home() {
|
|
const [videos, posts] = await Promise.all([
|
|
prisma.video.findMany({
|
|
orderBy: { created_at: "desc" },
|
|
take: 60,
|
|
include: { author: true },
|
|
}),
|
|
prisma.imagePost.findMany({
|
|
orderBy: { created_at: "desc" },
|
|
take: 60,
|
|
include: { author: true, images: { orderBy: { order: "asc" }, take: 1 } },
|
|
}),
|
|
]);
|
|
|
|
const feed: FeedItem[] = [
|
|
...videos.map((v) => ({
|
|
type: "video" as const,
|
|
aweme_id: v.aweme_id,
|
|
created_at: v.created_at,
|
|
desc: v.desc,
|
|
video_url: getFileUrl(v.video_url),
|
|
cover_url: getFileUrl(v.cover_url ?? ''),
|
|
width: v.width ?? null,
|
|
height: v.height ?? null,
|
|
author: { nickname: v.author.nickname, avatar_url: getFileUrl(v.author.avatar_url ?? '') },
|
|
likes: Number(v.digg_count)
|
|
})),
|
|
...posts.map((p) => ({
|
|
type: "image" as const,
|
|
aweme_id: p.aweme_id,
|
|
created_at: p.created_at,
|
|
desc: p.desc,
|
|
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 ?? '') },
|
|
likes: Number(p.digg_count)
|
|
})),
|
|
]
|
|
//.sort(() => Math.random() - 0.5)
|
|
.sort((a, b) => +new Date(b.created_at) - +new Date(a.created_at));
|
|
|
|
return (
|
|
<main className="min-h-screen w-full px-4 py-8 md:py-12">
|
|
<div className="flex flex-col items-center mb-8">
|
|
<h1 className="text-2xl md:text-3xl font-semibold tracking-tight mb-6">
|
|
作品集
|
|
</h1>
|
|
<SearchBox />
|
|
</div>
|
|
|
|
{(() => {
|
|
const initial = feed.slice(0, 24);
|
|
const cursor = initial.length > 0 ? new Date(initial[initial.length - 1].created_at as any).toISOString() : null;
|
|
return <FeedMasonry initialItems={initial} initialCursor={cursor} />;
|
|
})()}
|
|
</main>
|
|
);
|
|
}
|