fix: 书库阅读页/帖子详情页/SiteDocMasthead/TOC 等前端细节修复

This commit is contained in:
2026-10-02 01:47:14 +08:00
parent 7912b67ddc
commit 11f2131e4b
4 changed files with 18 additions and 9 deletions

View File

@@ -16,7 +16,7 @@ import {
groupSections,
type ChapterNav,
} from "@/lib/librarySections";
import { extractToc, estimateReadingMinutes, markdownHeadingToc, buildTocFromSegments } from "@/lib/toc";
import { extractToc, estimateReadingMinutes, formatReadingDuration, markdownHeadingToc, buildTocFromSegments } from "@/lib/toc";
import { splitContentSegments } from "@/lib/directiveBlocks";
import { wrapImplicitEntries } from "@/lib/entryBlocks";
import PostToc, { type TocItem } from "@/components/PostToc";
@@ -223,7 +223,7 @@ export default async function LibraryReadPage({ params, searchParams }: PageProp
{current.title}
</p>
<p className="meta mt-0.5 text-[10.5px] leading-tight">
第 {nav.index + 1} / {nav.total} 章 · 约 {chapterMinutes} 分钟
第 {nav.index + 1} / {nav.total} 章 · 约 {formatReadingDuration(chapterMinutes)} 读完
</p>
</>
}
@@ -265,7 +265,7 @@ export default async function LibraryReadPage({ params, searchParams }: PageProp
<header>
<div className="flex items-center justify-between gap-3">
<p className="meta text-[12px]">
第 {nav.index + 1} / {nav.total} 章 · 约 {chapterMinutes} 分钟
第 {nav.index + 1} / {nav.total} 章 · 约 {formatReadingDuration(chapterMinutes)} 读完
</p>
<BookSearch
slug={d.slug}

View File

@@ -45,7 +45,7 @@ import AcceptedAnswerCard from "@/components/AcceptedAnswerCard";
import { canModerateBoard } from "@/lib/roles";
import { IconComment, IconEye } from "@/components/Icons";
import { normalizePostType, postTypeLabel, contentAccessLabel, typeStatusLabel, typeStatusClass } from "@/lib/postMeta";
import { extractToc, estimateReadingMinutes, markdownHeadingToc } from "@/lib/toc";
import { extractToc, estimateReadingMinutes, formatReadingDuration, markdownHeadingToc } from "@/lib/toc";
import { requestCanonical } from "@/lib/canonicalMeta";
import { absoluteCanonical, canonicalPage } from "@/lib/siteUrl";
import { postPath, userPath, type UrlStyle } from "@/lib/urlStyle";
@@ -450,7 +450,7 @@ export default async function PostDetailPage({ params, searchParams }: PageProps
<p className="truncate text-[13px] font-bold leading-tight" style={{ color: "var(--ink)" }}>
{post.title}
</p>
<p className="meta mt-0.5 text-[10.5px] leading-tight">约 {readingMinutes} 分钟读完</p>
<p className="meta mt-0.5 text-[10.5px] leading-tight">约 {formatReadingDuration(readingMinutes)} 读完</p>
</>
}
left={leftRailNode ? { label: "导航", content: leftRailNode } : undefined}
@@ -599,8 +599,8 @@ export default async function PostDetailPage({ params, searchParams }: PageProps
<IconComment size={14} /> {post.comment_count} 评论
</span>
) : null}
<span className="inline-flex items-center gap-1.5" aria-label={`阅读约需 ${readingMinutes} 分钟`}>
<Clock size={14} /> 约 {readingMinutes} 分钟读完
<span className="inline-flex items-center gap-1.5" aria-label={`阅读约需 ${formatReadingDuration(readingMinutes)}`}>
<Clock size={14} /> 约 {formatReadingDuration(readingMinutes)} 读完
</span>
</div>
<p className="meta w-full text-[12px] sm:w-auto sm:ml-auto">

View File

@@ -1,6 +1,7 @@
import type { ReactNode } from "react";
import { Clock } from "lucide-react";
import { formatDate } from "@/lib/format";
import { formatReadingDuration } from "@/lib/toc";
function formatDateTime(dateStr: string) {
return new Date(dateStr).toLocaleString("zh-CN", {
@@ -83,9 +84,9 @@ export default function SiteDocMasthead({
{readingMinutes != null ? (
<span
className="meta inline-flex items-center gap-1.5 text-[12.5px] sm:ml-auto"
aria-label={`阅读约需 ${readingMinutes} 分钟`}
aria-label={`阅读约需 ${formatReadingDuration(readingMinutes)}`}
>
<Clock size={13} /> 约 {readingMinutes} 分钟读完
<Clock size={13} /> 约 {formatReadingDuration(readingMinutes)} 读完
</span>
) : null}
</div>

View File

@@ -167,3 +167,11 @@ export function estimateReadingMinutes(text: string, fallbackLen = 0): number {
const len = text.trim().length > 0 ? text.trim().length : fallbackLen;
return Math.max(1, Math.ceil(len / 400));
}
/** 阅读时长展示:≥60 分钟换算成「X 小时 Y 分钟」,避免大分钟数需口算 */
export function formatReadingDuration(minutes: number): string {
if (minutes < 60) return `${minutes} 分钟`;
const h = Math.floor(minutes / 60);
const m = minutes % 60;
return m > 0 ? `${h} 小时 ${m} 分钟` : `${h} 小时`;
}