2025-11-23 10:55:04 +08:00
|
|
|
"use client";
|
|
|
|
|
|
|
|
|
|
import Link from "next/link";
|
|
|
|
|
import { useParams, useSelectedLayoutSegments } from "next/navigation";
|
|
|
|
|
import { ChevronRight, MoreHorizontal, Star } from "lucide-react";
|
2026-01-22 18:53:20 +08:00
|
|
|
import { useMutation, useQuery } from "convex/react";
|
2025-11-23 10:55:04 +08:00
|
|
|
import type { DocumentRecord } from "@/lib/documents";
|
|
|
|
|
import { findBreadcrumb } from "@/lib/documents";
|
|
|
|
|
import { usePageLayoutStore } from "@/store/page-layout";
|
2026-01-22 18:53:20 +08:00
|
|
|
import { api } from "@/lib/convex/api";
|
2025-11-23 10:55:04 +08:00
|
|
|
|
|
|
|
|
interface BreadcrumbProps {
|
|
|
|
|
documents: DocumentRecord[];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function Breadcrumb({ documents }: BreadcrumbProps) {
|
|
|
|
|
const segments = useSelectedLayoutSegments();
|
|
|
|
|
const params = useParams<{ id?: string }>();
|
|
|
|
|
const paramId = typeof params?.id === "string" ? params.id : "";
|
|
|
|
|
const activeId = paramId || segments?.[1] || "";
|
|
|
|
|
const path = findBreadcrumb(documents, activeId);
|
|
|
|
|
const showInspector = usePageLayoutStore((state) => state.showInspector);
|
|
|
|
|
const toggleInspector = usePageLayoutStore((state) => state.toggleInspector);
|
2026-01-22 18:53:20 +08:00
|
|
|
const isStarred = useQuery(api.documentStars.isStarred, activeId ? { documentId: activeId } : "skip");
|
|
|
|
|
const toggleStar = useMutation(api.documentStars.toggle);
|
2025-11-23 10:55:04 +08:00
|
|
|
|
2026-01-10 23:08:56 +08:00
|
|
|
// 新建页面后,侧边栏数据可能还没同步到 layout(SSR)注入的 documents,导致 findBreadcrumb 暂时为空。
|
|
|
|
|
// 这里用 activeId 兜底,避免右上角“收藏/更多”按钮消失。
|
|
|
|
|
if (!activeId) {
|
2025-11-23 10:55:04 +08:00
|
|
|
return <div className="text-sm text-gray-400">请选择一个页面</div>;
|
|
|
|
|
}
|
2026-01-10 23:08:56 +08:00
|
|
|
const displayPath: Array<Pick<DocumentRecord, "id" | "title">> = path.length
|
|
|
|
|
? path
|
|
|
|
|
: [{ id: activeId, title: "无标题" }];
|
2025-11-23 10:55:04 +08:00
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className="flex flex-1 items-center justify-between">
|
2026-01-18 19:01:31 +08:00
|
|
|
<nav className="flex items-center text-sm text-wolai-text-secondary">
|
2026-01-10 23:08:56 +08:00
|
|
|
{displayPath.map((node, index) => {
|
|
|
|
|
const isLast = index === displayPath.length - 1;
|
2025-11-23 10:55:04 +08:00
|
|
|
return (
|
|
|
|
|
<span key={node.id} className="flex items-center">
|
|
|
|
|
{index > 0 && <ChevronRight className="mx-1 h-4 w-4 text-gray-400" />}
|
|
|
|
|
{isLast ? (
|
2026-01-18 19:01:31 +08:00
|
|
|
<span className="font-medium text-wolai-text-primary">{node.title || "无标题"}</span>
|
2025-11-23 10:55:04 +08:00
|
|
|
) : (
|
2026-01-18 19:01:31 +08:00
|
|
|
<Link
|
|
|
|
|
href={`/documents/${node.id}`}
|
|
|
|
|
className="hover:bg-wolai-bg-hover hover:text-wolai-text-primary px-1.5 py-0.5 rounded cursor-pointer transition-colors"
|
|
|
|
|
>
|
2025-11-23 10:55:04 +08:00
|
|
|
{node.title || "无标题"}
|
|
|
|
|
</Link>
|
|
|
|
|
)}
|
|
|
|
|
</span>
|
|
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
</nav>
|
2026-01-18 19:01:31 +08:00
|
|
|
<div className="flex items-center gap-2 text-wolai-text-secondary">
|
|
|
|
|
<button
|
|
|
|
|
type="button"
|
|
|
|
|
className="hover:bg-wolai-bg-hover hover:text-wolai-text-primary rounded-full px-3 py-1 text-sm transition-colors"
|
2026-01-22 18:53:20 +08:00
|
|
|
onClick={() => void toggleStar({ documentId: activeId })}
|
|
|
|
|
disabled={!activeId}
|
2026-01-18 19:01:31 +08:00
|
|
|
>
|
2026-01-22 18:53:20 +08:00
|
|
|
<Star
|
|
|
|
|
className={`mr-1 inline h-4 w-4 ${isStarred ? "text-[#f5a623]" : ""}`}
|
|
|
|
|
fill={isStarred ? "currentColor" : "none"}
|
|
|
|
|
/>
|
2025-11-23 10:55:04 +08:00
|
|
|
收藏
|
|
|
|
|
</button>
|
|
|
|
|
<button
|
|
|
|
|
type="button"
|
2026-01-18 19:01:31 +08:00
|
|
|
className="hover:bg-wolai-bg-hover hover:text-wolai-text-primary rounded-full p-2 transition-colors"
|
2025-11-23 10:55:04 +08:00
|
|
|
onClick={toggleInspector}
|
|
|
|
|
aria-label={showInspector ? "隐藏页面选项" : "显示页面选项"}
|
|
|
|
|
title={showInspector ? "隐藏页面选项" : "显示页面选项"}
|
|
|
|
|
>
|
|
|
|
|
<MoreHorizontal className="h-4 w-4" />
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|