import type { Metadata } from "next";
import type { CSSProperties } from "react";
import Link from "next/link";
import { BookOpen, FileDown } from "lucide-react";
import { fetchLibraryList, type LibraryDocListItem } from "@/lib/api";
import { coverHue } from "@/lib/coverColor";
import { getPublicSettingsCached } from "@/lib/serverData";
import { requestCanonical } from "@/lib/canonicalMeta";
import { libraryPath, libraryDocPath } from "@/lib/urlStyle";
function formatSize(n: number): string {
if (!Number.isFinite(n) || n <= 0) return "0 B";
if (n < 1024) return `${n} B`;
if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;
return `${(n / (1024 * 1024)).toFixed(1)} MB`;
}
/** 文字封面:无图时用完整书名 + 书名派生稳定色相洗底(lib/coverColor.ts) */
function TextCover({ title }: { title: string }) {
const name = title.trim() || "书";
return (
{name}
);
}
function ExtChip({ ext }: { ext: string }) {
return (
{ext}
);
}
function DocCard({
doc,
href,
}: {
doc: LibraryDocListItem;
href: string;
}) {
const exts = Array.from(new Set(doc.files.map((f) => f.ext))).slice(0, 4);
const totalSize = doc.files.reduce((acc, f) => acc + f.size, 0);
return (
{doc.cover_url ? (
// eslint-disable-next-line @next/next/no-img-element

) : (
)}
{doc.title}
{exts.map((ext) => (
))}
{doc.file_count > 0 ? `${doc.file_count} 个文件 · ${formatSize(totalSize)}` : "暂无文件"}
);
}
export async function generateMetadata(): Promise {
const settings = await getPublicSettingsCached();
return {
title: "书库",
description: settings.site_description,
...(await requestCanonical(libraryPath(settings.url_style))),
};
}
export default async function LibraryPage() {
const settings = await getPublicSettingsCached();
const urlStyle = settings.url_style;
// 接口失败降级为空态,不让页面 500
let docs: LibraryDocListItem[] = [];
try {
const res = await fetchLibraryList();
docs = res.docs ?? [];
} catch {
/* 降级空态 */
}
return (
{/* Hero:渐变洗底(与排行榜同语言) */}
{docs.length === 0 ? (
书库还没有内容
管理员可在后台「书库管理」发布条目
) : (
{docs.map((d) => (
))}
)}
);
}