Files
mnote/wolai-frontend/src/components/editor/page-backlinks-panel.tsx
T

78 lines
2.8 KiB
TypeScript
Raw Normal View History

2025-11-23 10:55:04 +08:00
"use client";
import { useMemo } from "react";
import { Button } from "@/components/ui/button";
import { useBacklinks } from "@/hooks/use-backlinks";
import type { BacklinkRecord } from "@/types/references";
import { cn } from "@/lib/utils";
interface PageBacklinksPanelProps {
workspaceId: string;
documentId: string;
className?: string;
}
const formatRelative = (value: string) => {
if (!value) return "";
const date = new Date(value);
return date.toLocaleString();
};
const EmptyState = () => (
<div className="rounded-xl border border-dashed border-[#e2e8f0] bg-white/60 px-4 py-6 text-center text-sm text-gray-500">
暂无反向引用。试试输入 <code className="rounded bg-gray-100 px-1">[[</code> <code className="rounded bg-gray-100 px-1">#</code>{" "}
来引用其他页面。
</div>
);
const BacklinkItem = ({ record }: { record: BacklinkRecord }) => (
<div className="rounded-xl border border-[#f1f5f9] bg-white p-4 shadow-sm">
<div className="flex items-center justify-between text-sm font-medium text-gray-900">
<span>{record.alias || record.sourceTitle || "无标题"}</span>
<span className="text-xs text-gray-400">{record.displayMode === "embed" ? "嵌入块" : "行内引用"}</span>
</div>
<div className="mt-1 text-xs text-gray-500">
来自页面:{record.sourceTitle || "无标题"} · 更新:{formatRelative(record.updatedAt)}
</div>
</div>
);
export function PageBacklinksPanel({ workspaceId, documentId, className }: PageBacklinksPanelProps) {
const { data, isLoading, error, refetch, isFetching } = useBacklinks({
workspaceId,
documentId,
});
const records = useMemo(() => data ?? [], [data]);
if (!isLoading && !error && records.length === 0) {
return null;
}
return (
<section className={cn("rounded-2xl border border-[#eef2ff] bg-[#fdfdff] p-5 shadow-sm", className)}>
<div className="mb-4 flex items-center justify-between">
<div>
<p className="text-base font-semibold text-[#1f2933]">反向引用</p>
<p className="text-xs text-gray-500">展示指向当前页面的所有页面或块引用</p>
</div>
<Button size="sm" variant="ghost" onClick={() => refetch()} disabled={isFetching}>
{isFetching ? "刷新中..." : "刷新"}
</Button>
</div>
{isLoading ? (
<div className="py-6 text-center text-sm text-gray-500">加载引用中...</div>
) : error ? (
<div className="py-6 text-center text-sm text-red-500">{(error as Error).message}</div>
) : records.length === 0 ? (
<EmptyState />
) : (
<div className="space-y-3">
{records.map((record) => (
<BacklinkItem key={record.id} record={record} />
))}
</div>
)}
</section>
);
}