import Link from "next/link"; import { useRouter } from "next/router"; import { useCallback, useEffect, useRef, useState, type FormEvent, } from "react"; import { ArrowRight, ArrowUpRight, Bot, ChevronRight, FileText, Plus, Search, X, } from "lucide-react"; import GuidanceShell, { useGuidanceAccount } from "@/components/GuidanceShell"; import { EmptyState, KindBadge, KindIcon, Notice, PageHeading, kindNames, Tabs, } from "@/components/GuidanceUI"; import { guides, type Guidance } from "@/content/guides/catalog"; import s from "@/styles/guidance.module.css"; type Summary = { id: string; revision: number; title: string; summary: string; kind: Guidance["kind"]; author?: string; tags?: string[]; source: "community" | "example"; }; type Source = "all" | "published" | "examples"; const kinds = ["all", "guide", "context", "evidence"] as const; const examples: Summary[] = guides.map((g) => ({ ...g, source: "example" })); export default function DocumentDirectory({ communityOnly = false, }: { communityOnly?: boolean; }) { const router = useRouter(); const mine = communityOnly && router.query.scope === "mine"; return ( ); } function DirectoryContent({ communityOnly, mine, }: { communityOnly: boolean; mine: boolean; }) { const router = useRouter(), account = useGuidanceAccount(); const [published, setPublished] = useState([]), [loading, setLoading] = useState(true), [error, setError] = useState(""); const [q, setQ] = useState(""), [kind, setKind] = useState("all"), [source, setSource] = useState(communityOnly ? "published" : "all"), [sort, setSort] = useState("default"); const controller = useRef(null); const refresh = useCallback(async () => { controller.current?.abort(); const abort = new AbortController(); controller.current = abort; setLoading(true); setError(""); try { const r = await fetch( "/api/documents" + (mine && account.user ? "?author=" + account.user.id : ""), { signal: abort.signal }, ); const b = await r.json(); if (!r.ok) throw Error(b.error || "目录暂时不可用"); if (!Array.isArray(b.documents)) throw Error("目录返回异常,请稍后重试"); setPublished( b.documents.map((d: Omit) => ({ ...d, source: "community", })), ); } catch (e) { if (!abort.signal.aborted) setError(e instanceof Error ? e.message : "目录暂时不可用"); } finally { if (!abort.signal.aborted) setLoading(false); } }, [mine, account.user?.id]); useEffect(() => { void refresh(); return () => controller.current?.abort(); }, [refresh]); useEffect(() => { if (!router.isReady) return; setQ(typeof router.query.q === "string" ? router.query.q : ""); setKind( typeof router.query.kind === "string" && kinds.some((k) => k === router.query.kind) ? router.query.kind : "all", ); setSource( communityOnly ? "published" : router.query.source === "published" || router.query.source === "examples" ? router.query.source : "all", ); setSort(router.query.sort === "title" ? "title" : "default"); }, [ router.isReady, router.query.q, router.query.kind, router.query.source, router.query.sort, communityOnly, ]); function remember( next: { q?: string; kind?: string; source?: Source; sort?: string } = {}, ) { const values = { q, kind, source, sort, ...next }, query: Record = {}; if (values.q) query.q = values.q; if (values.kind !== "all") query.kind = values.kind; if (!communityOnly && values.source !== "all") query.source = values.source; if (values.sort !== "default") query.sort = values.sort; if (mine) query.scope = "mine"; void router.push( { pathname: communityOnly ? "/documents" : "/", query }, undefined, { shallow: true, scroll: false }, ); } function search(e: FormEvent) { e.preventDefault(); remember(); } function clear() { setQ(""); setKind("all"); setSource(communityOnly ? "published" : "all"); setSort("default"); remember({ q: "", kind: "all", source: communityOnly ? "published" : "all", sort: "default", }); } const all: Summary[] = communityOnly ? published : [...published, ...examples]; const term = q.trim().toLocaleLowerCase(); const found = all.filter( (d) => (!mine || d.author === account.user?.id) && (source === "all" || (source === "published" && d.source === "community") || (source === "examples" && d.source === "example")) && `${d.title} ${d.summary} ${d.id} ${d.tags?.join(" ") || ""}` .toLocaleLowerCase() .includes(term), ); const documents = found.filter((d) => kind === "all" || d.kind === kind); if (sort === "title") documents.sort((a, b) => a.title.localeCompare(b.title, "zh-CN")); const waiting = loading || (mine && account.loading), filtered = !!q || kind !== "all" || (!communityOnly && source !== "all") || sort !== "default"; const heading = mine ? "我的文档" : communityOnly ? "社区文档" : "探索文档"; return ( <> Agent 入口 {!communityOnly && ( <>

好用的知识,从不必整套加载。

每篇文档都有适用条件和固定版本。需要更多时,再沿着有用的链接继续阅读。

了解工作原理
试试这些任务 {["代码审查", "规划", "验证"].map((t) => ( ))}
)} {mine && !account.loading && !account.user ? (
{account.error && (
{account.error}{" "}
)} 登录 / 创建账户
) : ( <>
({ id: k, label: k === "all" ? "全部文档" : kindNames[k], count: found.filter((d) => k === "all" || d.kind === k).length, }))} value={kind} onChange={(value) => { setKind(value); remember({ kind: value }); }} />
setQ(e.target.value)} /> {q && ( )}
{!communityOnly && ( )}

{waiting ? "正在加载文档…" : error ? `当前显示 ${documents.length} 篇,社区目录加载失败` : `找到 ${documents.length} 篇文档`}

{filtered ? ( ) : ( 最多展示最近 100 篇社区文档 )}
{error && (
{error}{" "}
)} {waiting && (!documents.length || communityOnly) ? (
{[0, 1, 2].map((i) => (
))}
) : ( documents.map((d) => (

{d.title}

{d.summary}

{d.id}

v{d.revision} {d.source === "example" ? "协议样例" : "社区发布"}
v{d.revision} {d.source === "example" ? "协议样例" : "社区发布"} )) )} {!waiting && !documents.length && !error && ( {filtered ? ( ) : ( 发布一篇文档 )} )}
{mine ? "只有你可以更新自己的文档,已发布的历史版本保持不变。" : "社区文档与协议样例分别标识,采用前请确认适用条件与版本。"} 了解读取规范
)} ); }