优化图文页

This commit is contained in:
2026-04-28 17:11:42 +08:00
parent 674c202264
commit 040273586b
69 changed files with 3939 additions and 2302 deletions
+36 -15
View File
@@ -9,7 +9,7 @@ import { Search, ArrowLeft, X, MessageSquare } from "lucide-react";
type SearchResultItem = {
id: string;
awemeId: string;
type: 'video' | 'image';
type: "video" | "image";
rank: number;
snippet: string; // 后端返回的高亮片段,已包含<mark>标签
video?: {
@@ -35,7 +35,11 @@ type SearchResultItem = {
};
};
};
export default function SearchClient({ initialQuery }: { initialQuery: string }) {
export default function SearchClient({
initialQuery,
}: {
initialQuery: string;
}) {
const searchParams = useSearchParams();
const router = useRouter();
@@ -53,7 +57,9 @@ export default function SearchClient({ initialQuery }: { initialQuery: string })
setLoading(true);
setSearched(true);
try {
const res = await fetch(`/api/search?q=${encodeURIComponent(q.trim())}&limit=60`);
const res = await fetch(
`/api/search?q=${encodeURIComponent(q.trim())}&limit=60`,
);
if (!res.ok) throw new Error("Search failed");
const data = await res.json();
setResults(data.results || []);
@@ -101,7 +107,10 @@ export default function SearchClient({ initialQuery }: { initialQuery: string })
<ArrowLeft size={24} />
</button>
<form onSubmit={handleSearch} className="flex-1 flex items-center gap-3">
<form
onSubmit={handleSearch}
className="flex-1 flex items-center gap-3"
>
<div className="relative flex-1">
<input
type="text"
@@ -160,7 +169,9 @@ export default function SearchClient({ initialQuery }: { initialQuery: string })
<div className="flex flex-col items-center justify-center py-20 text-white/40">
<Search size={64} className="mb-4 opacity-20" />
<p className="text-xl">输入关键词开始搜索</p>
<p className="text-sm mt-2">支持搜索视频描述、图文描述及语音转写内容</p>
<p className="text-sm mt-2">
支持搜索视频描述、图文描述及语音转写内容
</p>
</div>
)}
@@ -168,14 +179,19 @@ export default function SearchClient({ initialQuery }: { initialQuery: string })
<div>
<div className="mb-6 flex items-center justify-between">
<h2 className="text-lg text-white/80">
找到 <span className="text-white font-semibold">{results.length}</span> 个结果
找到{" "}
<span className="text-white font-semibold">
{results.length}
</span>{" "}
个结果
</h2>
</div>
{/* 单列列表布局 */}
<div className="space-y-4">
{results.map((item) => {
const content = item.type === 'video' ? item.video : item.imagePost;
const content =
item.type === "video" ? item.video : item.imagePost;
if (!content) return null;
return (
@@ -202,12 +218,14 @@ export default function SearchClient({ initialQuery }: { initialQuery: string })
<div className="flex-1 min-w-0 flex flex-col">
{/* 类型标签 */}
<div className="flex items-center gap-2 mb-2">
<span className={`px-2 py-0.5 text-xs rounded ${
item.type === 'video'
? 'bg-blue-600/20 text-blue-300'
: 'bg-purple-600/20 text-purple-300'
}`}>
{item.type === 'video' ? '视频' : '图文'}
<span
className={`px-2 py-0.5 text-xs rounded ${
item.type === "video"
? "bg-blue-600/20 text-blue-300"
: "bg-purple-600/20 text-purple-300"
}`}
>
{item.type === "video" ? "视频" : "图文"}
</span>
<span className="flex items-center gap-1 px-2 py-0.5 bg-green-600/20 text-green-300 text-xs rounded">
<MessageSquare size={12} />
@@ -216,7 +234,10 @@ export default function SearchClient({ initialQuery }: { initialQuery: string })
</div>
{/* 描述 */}
<Link href={`/aweme/${content.aweme_id}`} target="_blank">
<Link
href={`/aweme/${content.aweme_id}`}
target="_blank"
>
<p className="text-white/90 text-sm sm:text-base line-clamp-2 mb-3 hover:text-white transition-colors">
{content.desc || "无描述"}
</p>
@@ -245,7 +266,7 @@ export default function SearchClient({ initialQuery }: { initialQuery: string })
className="text-xs text-white/70 bg-white/5 rounded-lg p-2 leading-relaxed"
dangerouslySetInnerHTML={{ __html: item.snippet }}
style={{
wordBreak: 'break-word',
wordBreak: "break-word",
}}
/>
</div>
+5 -1
View File
@@ -2,7 +2,11 @@
import { Suspense } from "react";
import SearchClient from "./SearchClient";
export default function Page({ searchParams }: { searchParams: { q?: string } }) {
export default function Page({
searchParams,
}: {
searchParams: { q?: string };
}) {
const q = typeof searchParams.q === "string" ? searchParams.q : "";
return (
<Suspense fallback={<div className="p-6 text-zinc-400">Loading…</div>}>