Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 18 additions & 15 deletions src/app/(app)/posts/PostDetailPageClient.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { useParams, useRouter, useSearchParams } from "next/navigation";
import { Trash2, ArrowLeft, Pencil, Heart, Bookmark, UserPlus, UserMinus } from "lucide-react";
import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
import rehypeSanitize from "rehype-sanitize";
import { api, type Post } from "@/lib/api";
import { useAuth } from "@/contexts/AuthContext";
import { Badge } from "@/components/ui/badge";
Expand All @@ -16,7 +15,7 @@ import { Card, CardContent } from "@/components/ui/card";
import { CommentSection } from "@/components/post/CommentSection";
import { ReportButton } from "@/components/moderation/ReportButton";
import { useToast } from "@/components/ui/toast-context";
import { TAG_LABEL, parsePostTags } from "@/lib/post-tags";
import { POST_SECTION_LABEL } from "@/lib/enums";
import { relativeTime } from "@/lib/utils";
import { getQueryRoute, toQueryRoute } from "@/lib/query-routing";

Expand Down Expand Up @@ -61,7 +60,6 @@ function PostDetailInner() {
const rejected = post.status === "REJECTED";
const hidden = post.status === "HIDDEN";
const draft = post.status === "DRAFT";
const tags = parsePostTags(post.tags);

async function remove() {
if (!id) return;
Expand Down Expand Up @@ -182,17 +180,11 @@ function PostDetailInner() {
) : null}

<article className="space-y-4">
<div className="flex flex-wrap items-center gap-2 text-xs">
{tags.length > 0 ? (
tags.map((t) => (
<Badge key={t} variant="pink">
{TAG_LABEL[t] ?? t}
</Badge>
))
) : (
<Badge variant="outline">动态</Badge>
)}
{post.section === "MEDICAL" && post.hospital ? (
<div className="flex items-center gap-2 flex-wrap">
<Badge variant="pink" className="shrink-0">
{POST_SECTION_LABEL[post.section as keyof typeof POST_SECTION_LABEL] ?? "动态"}
</Badge>
{post.section === "MEDICAL" && post.hospital ? (
<Badge variant="outline">{post.hospital}</Badge>
) : null}
</div>
Expand Down Expand Up @@ -221,7 +213,18 @@ function PostDetailInner() {
) : null}
</div>
<div className="prose-trans text-base leading-relaxed">
<ReactMarkdown remarkPlugins={[remarkGfm]} rehypePlugins={[rehypeSanitize]}>
<ReactMarkdown remarkPlugins={[remarkGfm]} components={{
img: ({ src, alt }) => {
if (!src) return null;
const resolved = src.startsWith("/api/files/") ? api.files.url(src) : src;
return <img src={resolved} alt={alt || ''} style={{maxWidth:'100%',height:'auto',borderRadius:'8px',margin:'12px 0'}} />;
},
a: ({ href, children, ...props }) => {
if (!href) return <a {...props}>{children}</a>;
const resolved = href.startsWith("/api/files/") ? api.files.url(href) : href;
return <a href={resolved} target="_blank" rel="noopener noreferrer" {...props}>{children}</a>;
}
}}>
{post.body}
</ReactMarkdown>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/app/(app)/posts/new/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ function NewPostInner() {
<PageHeader
eyebrow="发帖"
title="发布到广场"
description="选择板块,正文支持 Markdown。提交后内容会经过 AI 审核;违规会被退回,边界内容会进入人工复核。"
description="用户自选板块,正文支持 Markdown。提交后内容会经过 AI 审核;违规会被退回,边界内容会进入人工复核。"
/>
<PostForm mode="create" />
</div>
Expand Down
15 changes: 4 additions & 11 deletions src/components/post/PostCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { MessageCircle, Heart } from "lucide-react";
import type { Post } from "@/lib/api";
import { relativeTime } from "@/lib/utils";
import { toQueryRoute } from "@/lib/query-routing";
import { TAG_LABEL, parsePostTags } from "@/lib/post-tags";
import { POST_SECTION_LABEL } from "@/lib/enums";

type CardPost = Post & { like_count?: number };

Expand All @@ -14,7 +14,6 @@ export function PostCard({ post }: { post: CardPost }) {
const isHidden = post.status === "HIDDEN";
const isRejected = post.status === "REJECTED";
const isDraft = post.status === "DRAFT";
const tags = parsePostTags(post.tags);
// The list endpoint exposes `like_count` (snake_case); the detail endpoint
// exposes `likeCount` (camelCase). Read both so the card works in either
// context (list views, bookmarks, drafts).
Expand All @@ -25,15 +24,9 @@ export function PostCard({ post }: { post: CardPost }) {
<Card className="h-full transition-all group-hover:shadow-lift group-hover:-translate-y-0.5">
<CardContent className="pt-6 space-y-3">
<div className="flex items-center gap-2 flex-wrap text-xs">
{tags.length > 0 ? (
tags.slice(0, 3).map((t) => (
<Badge key={t} variant="pink">
{TAG_LABEL[t] ?? t}
</Badge>
))
) : (
<Badge variant="outline">动态</Badge>
)}
<Badge variant="pink" className="shrink-0">
{POST_SECTION_LABEL[post.section as keyof typeof POST_SECTION_LABEL] ?? "动态"}
</Badge>
{post.section === "MEDICAL" && post.hospital ? (
<Badge variant="outline">{post.hospital}</Badge>
) : null}
Expand Down
Loading
Loading