feat(compose): 正文内嵌隐藏块并升级 Markdown 编辑器
去掉整帖可见性表单,改为 :::hide 按块脱敏;工具栏补齐代码块、链接/图片对话框与粘贴拖拽上传。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -34,7 +34,7 @@ import MobilePostBar from "@/components/MobilePostBar";
|
||||
import Avatar from "@/components/Avatar";
|
||||
import RoleBadge from "@/components/RoleBadge";
|
||||
import MarkdownBody from "@/components/MarkdownBody";
|
||||
import ContentLockGate from "@/components/ContentLockGate";
|
||||
import { publicMarkdownForSeo } from "@/lib/hideBlocks";
|
||||
import PostAttachments from "@/components/PostAttachments";
|
||||
import PostInteractPanels, { QuestionStatusCard } from "@/components/PostInteractPanels";
|
||||
import AcceptedAnswerCard from "@/components/AcceptedAnswerCard";
|
||||
@@ -60,9 +60,10 @@ export async function generateMetadata({ params }: PageProps): Promise<Metadata>
|
||||
robots: { index: false, follow: false },
|
||||
};
|
||||
}
|
||||
const desc = post.content_locked
|
||||
? post.access_hint || "部分内容需满足条件后可见"
|
||||
: (post.content || "").slice(0, 160);
|
||||
const publicBody = publicMarkdownForSeo(post.content || "");
|
||||
const desc = publicBody
|
||||
? publicBody.slice(0, 160)
|
||||
: post.access_hint || "部分内容需满足条件后可见";
|
||||
return {
|
||||
title: post.title,
|
||||
description: desc,
|
||||
@@ -481,10 +482,11 @@ export default async function PostDetailPage({ params, searchParams }: PageProps
|
||||
const related = (relatedData?.posts ?? []).filter((p) => p.id !== post.id).slice(0, 5);
|
||||
const authorPosts = (profile?.posts ?? []).filter((p) => p.id !== post.id).slice(0, 5);
|
||||
|
||||
const toc = post.content_locked ? [] : extractToc(post.content);
|
||||
const publicBody = publicMarkdownForSeo(post.content || "");
|
||||
const toc = extractToc(publicBody);
|
||||
const readingMinutes = Math.max(
|
||||
1,
|
||||
Math.ceil((post.content_locked ? post.title.length : post.content.length) / 400)
|
||||
Math.ceil((publicBody.length > 0 ? publicBody.length : post.title.length) / 400)
|
||||
);
|
||||
const edited =
|
||||
new Date(post.updated_at).getTime() - new Date(post.created_at).getTime() > 60_000;
|
||||
@@ -527,8 +529,8 @@ export default async function PostDetailPage({ params, searchParams }: PageProps
|
||||
"@context": "https://schema.org",
|
||||
"@type": "DiscussionForumPosting",
|
||||
headline: post.title,
|
||||
// 锁定正文不进 JSON-LD,避免 SEO 泄露付费/回复可见内容
|
||||
articleBody: post.content_locked ? undefined : post.content,
|
||||
// 仅公开片段进 JSON-LD,避免 SEO 泄露隐藏块原文
|
||||
articleBody: publicBody || undefined,
|
||||
datePublished: post.created_at,
|
||||
dateModified: post.updated_at,
|
||||
author: { "@type": "Person", name: post.user.nickname },
|
||||
@@ -541,7 +543,7 @@ export default async function PostDetailPage({ params, searchParams }: PageProps
|
||||
...(allowComments &&
|
||||
acceptedAnswer &&
|
||||
!acceptedAnswer.deleted &&
|
||||
!post.content_locked && {
|
||||
!!publicBody && {
|
||||
acceptedAnswer: {
|
||||
"@type": "Comment",
|
||||
text: acceptedAnswer.content,
|
||||
@@ -718,24 +720,14 @@ export default async function PostDetailPage({ params, searchParams }: PageProps
|
||||
</div>
|
||||
)}
|
||||
|
||||
{post.content_locked ? (
|
||||
<ContentLockGate
|
||||
postId={post.id}
|
||||
hint={post.access_hint}
|
||||
access={post.content_access}
|
||||
points={post.access_points}
|
||||
loggedIn={!!me.user}
|
||||
/>
|
||||
) : (
|
||||
<MarkdownBody
|
||||
content={post.content}
|
||||
components={{ h2: headingRenderer("h2"), h3: headingRenderer("h3") }}
|
||||
/>
|
||||
)}
|
||||
<MarkdownBody
|
||||
content={post.content}
|
||||
postId={post.id}
|
||||
loggedIn={!!me.user}
|
||||
components={{ h2: headingRenderer("h2"), h3: headingRenderer("h3") }}
|
||||
/>
|
||||
|
||||
{!post.content_locked && (
|
||||
<PostAttachments postId={post.id} items={post.attachments || []} />
|
||||
)}
|
||||
<PostAttachments postId={post.id} items={post.attachments || []} />
|
||||
|
||||
{/* 类型特殊块(投票/悬赏/抽奖/问答)统一放正文最下方 */}
|
||||
<PostInteractPanels
|
||||
@@ -745,7 +737,7 @@ export default async function PostDetailPage({ params, searchParams }: PageProps
|
||||
lottery={post.lottery}
|
||||
loggedIn={!!me.user}
|
||||
/>
|
||||
{!post.content_locked && allowComments && acceptedAnswer ? (
|
||||
{allowComments && acceptedAnswer ? (
|
||||
<AcceptedAnswerCard
|
||||
answer={acceptedAnswer}
|
||||
variant={acceptedAnswerVariant}
|
||||
|
||||
Reference in New Issue
Block a user