cvsa/packages/next/app/[locale]/video/[id]/info/page.tsx

104 lines
3.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Suspense } from "react";
import Link from "next/link";
import { format } from "date-fns";
import { notFound } from "next/navigation";
import { Metadata } from "next";
import type { VideoInfoData } from "@cvsa/core";
const StatRow = ({ title, description }: { title: string; description?: number }) => {
return (
<div className="flex justify-between w-36">
<span>{title}</span>
<span>{description?.toLocaleString() ?? "N/A"}</span>
</div>
);
};
export async function generateMetadata({ params }: { params: Promise<{ id: string }> }): Promise<Metadata> {
const backendURL = process.env.BACKEND_URL;
const { id } = await params;
const res = await fetch(`${backendURL}/video/${id}/info`);
if (!res.ok) {
return {
title: "页面未找到 - 中 V 档案馆"
};
}
const data = await res.json();
return {
title: `${data.title} - 视频信息 - 中 V 档案馆`
};
}
const VideoInfo = async ({ id }: { id: string }) => {
const backendURL = process.env.BACKEND_URL;
const res = await fetch(`${backendURL}/video/${id}/info`);
if (!res.ok) {
return notFound();
}
const data: VideoInfoData = await res.json();
return (
<div className="w-full lg:max-w-4xl lg:mx-auto lg:p-6 px-4">
<h2 className="text-lg md:text-2xl mb-2">
<Link href={`https://www.bilibili.com/video/${data.bvid}`}>{data.title || data.bvid}</Link>
</h2>
<p className="text-sm md:text-base font-normal text-on-surface-variant dark:text-dark-on-surface-variant mb-4">
<span>
{data.bvid} · av{data.aid}
</span>
<br />
<span> {format(new Date(data.pubdate * 1000), "yyyy-MM-dd HH:mm:ss")}</span>
<br />
<span>{(data.stat?.view ?? 0).toLocaleString()}</span> ·{" "}
<span>{(data.stat?.danmaku ?? 0).toLocaleString()}</span>
<br />
<span>
: {data.tname}, tid{data.tid} · v2: {data.tname_v2}, tid
{data.tid_v2}
</span>
</p>
<img src={data.pic} referrerPolicy="no-referrer" className="rounded-lg" alt="Video cover" />
<h3 className="font-medium text-lg mt-6 mb-1"></h3>
<pre className="max-w-full wrap-anywhere break-all text-on-surface-variant text-sm md:text-base whitespace-pre-wrap dark:text-dark-on-surface-variant font-zh">
{data.desc}
</pre>
<div className="mb-6 mt-4">
<h2 className="mb-2 text-xl font-medium"></h2>
<div className="flex flex-col gap-1">
<StatRow title="播放" description={data.stat?.view} />
<StatRow title="点赞" description={data.stat?.like} />
<StatRow title="收藏" description={data.stat?.favorite} />
<StatRow title="硬币" description={data.stat?.coin} />
<StatRow title="评论" description={data.stat?.reply} />
<StatRow title="弹幕" description={data.stat?.danmaku} />
<StatRow title="分享" description={data.stat?.share} />
</div>
</div>
</div>
);
};
export default async function VideoPage({ params }: { params: Promise<{ id: string }> }) {
const { id } = await params;
return (
<main className="flex flex-col items-center flex-grow gap-8 mt-10 md:mt-6 relative z-0 overflow-x-auto pb-8">
<Suspense
fallback={
<main className="flex flex-col flex-grow items-center justify-center gap-8">
<h1 className="text-4xl font-extralight"></h1>
</main>
}
>
<VideoInfo id={id} />
</Suspense>
</main>
);
}