--- import Layout from "@layouts/Layout.astro"; import TitleBar from "@components/TitleBar.astro"; import pg from "pg"; import { format } from 'date-fns'; import { zhCN } from 'date-fns/locale'; const databaseHost = process.env.DB_HOST const databaseName = process.env.DB_NAME const databaseUser = process.env.DB_USER const databasePassword = process.env.DB_PASSWORD const databasePort = process.env.DB_PORT const postgresConfig = { hostname: databaseHost, port: parseInt(databasePort!), database: databaseName, user: databaseUser, password: databasePassword, }; // 路由参数 const { id } = Astro.params; const { Client } = pg; const client = new Client(postgresConfig); await client.connect(); // 数据库查询函数 async function getVideoMetadata(aid: number) { const res = await client.query("SELECT * FROM bilibili_metadata WHERE aid = $1", [aid]); if (res.rows.length <= 0) { return null; } const row = res.rows[0]; if (row) { return row; } return {}; } async function getVideoSnapshots(aid: number) { const res = await client.query("SELECT * FROM video_snapshot WHERE aid = $1 ORDER BY created_at DESC", [ aid, ]); if (res.rows.length <= 0) { return null; } return res.rows; } async function getAidFromBV(bv: string) { const res = await client.query("SELECT aid FROM bilibili_metadata WHERE bvid = $1", [bv]); if (res.rows.length <= 0) { return null; } const row = res.rows[0]; if (row && row.aid) { return Number(row.aid); } return null; } async function idExists(aid: number) { const res = await client.query("SELECT COUNT(*) FROM bilibili_metadata WHERE aid = $1", [aid]); return res.rows[0].count > 0; } async function getVideoAid(id: string) { if (id.startsWith("av")) { return parseInt(id.slice(2)); } else if (id.startsWith("BV")) { return getAidFromBV(id); } return parseInt(id); } // 获取数据 if (!id) { Astro.response.status = 404; client.end(); return new Response(null, { status: 404 }); } const aid = await getVideoAid(id); if (!aid || isNaN(aid)) { Astro.response.status = 404; client.end(); return new Response(null, { status: 404 }); } const aidExists = await idExists(aid); if (!aidExists) { Astro.response.status = 404; client.end(); return new Response(null, { status: 404 }); } const videoInfo = await getVideoMetadata(aid); const snapshots = await getVideoSnapshots(aid); client.end(); interface Snapshot { created_at: Date; views: number; danmakus: number; replies: number; coins: number; likes: number; favorites: number; shares: number; id: number; } ---

视频信息: av{aid}

基本信息

ID {videoInfo?.id}
AID {videoInfo?.aid}
BVID {videoInfo?.bvid}
标题 {videoInfo?.title}
描述 {videoInfo?.description}
UID {videoInfo?.uid}
标签 {videoInfo?.tags}
发布时间 {videoInfo?.published_at ? format(new Date(videoInfo.published_at), 'yyyy-MM-dd HH:mm:ss', { locale: zhCN }) : '-'}
时长 (秒) {videoInfo?.duration}
创建时间 {videoInfo?.created_at ? format(new Date(videoInfo.created_at), 'yyyy-MM-dd HH:mm:ss', { locale: zhCN }) : '-'}
封面 {videoInfo?.cover_url ? videoInfo.cover_url : '-'}

播放量历史数据

{snapshots && snapshots.length > 0 ? (
{snapshots.map((snapshot: Snapshot) => ( ))}
创建时间 观看 硬币 点赞 收藏 分享 弹幕 评论
{format(new Date(snapshot.created_at), 'yyyy-MM-dd HH:mm:ss', { locale: zhCN })} {snapshot.views} {snapshot.coins} {snapshot.likes} {snapshot.favorites} {snapshot.shares} {snapshot.danmakus} {snapshot.replies}
) : (

暂无历史数据。

)}