并发版

This commit is contained in:
Administrator committed 2026-06-29 16:09:51 +08:00
1 parent cd2ca406a5
commit d39b58255d
11 files changed
+530 -73

No files matched your search

@@ -321,14 +321,49 @@ function KnowledgeMarkdownView({
() => anchorResolver.headings.filter((item) => item.level >= 1 && item.level <= 3),
[anchorResolver],
);
const [activeHeadingId, setActiveHeadingId] = useState<string | null>(null);
const excerpt = useMemo(() => getMarkdownExcerpt(content), [content]);
const sectionCount = headings.length;
const wordCount = useMemo(() => countReadableWords(content), [content]);
useEffect(() => {
setActiveHeadingId(headings[0]?.id ?? null);
}, [headings]);
useEffect(() => {
const root = rootRef.current;
if (!root || headings.length === 0) return;
const targets = headings
.map((item) => root.querySelector<HTMLElement>(selectorForId(item.id)))
.filter((item): item is HTMLElement => !!item);
if (targets.length === 0) return;
const observer = new IntersectionObserver(
(entries) => {
const visible = entries
.filter((entry) => entry.isIntersecting)
.sort((a, b) => a.boundingClientRect.top - b.boundingClientRect.top)[0];
if (visible?.target.id) {
setActiveHeadingId(visible.target.id);
}
},
{
root: root.closest("[data-radix-scroll-area-viewport]") ?? null,
rootMargin: "-96px 0px -65% 0px",
threshold: [0, 1],
},
);
targets.forEach((target) => observer.observe(target));
return () => observer.disconnect();
}, [headings, content]);
const scrollToHeading = useCallback((id: string) => {
const root = rootRef.current;
const target =
root?.querySelector<HTMLElement>(selectorForId(id)) ?? document.getElementById(id);
setActiveHeadingId(id);
target?.scrollIntoView({ behavior: "smooth", block: "start" });
}, []);
@@ -336,12 +371,12 @@ function KnowledgeMarkdownView({
<div
ref={rootRef}
className={cn(
"grid min-h-0 gap-4 lg:grid-cols-[minmax(0,1fr)_260px]",
"grid min-h-0 gap-5 lg:grid-cols-[minmax(0,1fr)_300px]",
className,
)}
>
<article className="min-w-0 rounded-md border border-slate-200/70 bg-white shadow-sm dark:border-slate-800 dark:bg-slate-950">
<div className="border-b border-slate-100 bg-slate-50/80 px-5 py-4 dark:border-slate-800 dark:bg-slate-900/60">
<article className="min-w-0 overflow-hidden rounded-lg border border-slate-200/80 bg-white shadow-sm dark:border-slate-800 dark:bg-slate-950">
<div className="border-b border-slate-100 bg-slate-50/90 px-6 py-5 dark:border-slate-800 dark:bg-slate-900/70 md:px-8">
<div className="flex flex-wrap items-center gap-2 text-xs text-slate-500 dark:text-slate-400">
<span className="inline-flex items-center gap-1 rounded-md bg-white px-2 py-1 font-medium text-slate-600 ring-1 ring-slate-200 dark:bg-slate-950 dark:text-slate-300 dark:ring-slate-800">
<BookOpen className="size-3.5" />
@@ -368,7 +403,7 @@ function KnowledgeMarkdownView({
</span>
</div>
</div>
<div className="wiki-markdown px-5 py-5 md:px-7 md:py-6">
<div className="wiki-markdown public-report-markdown mx-auto w-full max-w-[980px] px-6 py-7 md:px-10 md:py-9">
<MarkdownContent
className="max-w-none"
content={content}
@@ -380,19 +415,21 @@ function KnowledgeMarkdownView({
</article>
<aside className="hidden min-w-0 lg:block">
<div className="sticky top-3 rounded-md border border-slate-200/70 bg-white p-3 shadow-sm dark:border-slate-800 dark:bg-slate-950">
<div className="sticky top-4 rounded-lg border border-slate-200/80 bg-white p-4 shadow-sm dark:border-slate-800 dark:bg-slate-950">
<div className="mb-2 flex items-center gap-2 text-sm font-semibold text-slate-800 dark:text-slate-100">
<List className="size-4" />
内容目录
</div>
{headings.length > 0 ? (
<nav className="max-h-[calc(100vh-260px)] space-y-1 overflow-auto pr-1">
<nav className="max-h-[calc(100vh-210px)] space-y-1 overflow-auto pr-1">
{headings.map((item) => (
<button
key={item.id}
type="button"
className={cn(
"block w-full truncate rounded-md px-2 py-1.5 text-left text-xs text-slate-600 transition-colors hover:bg-slate-100 hover:text-slate-950 dark:text-slate-300 dark:hover:bg-slate-900 dark:hover:text-slate-50",
"block w-full truncate rounded-md border-l-2 border-transparent px-2 py-1.5 text-left text-xs leading-5 text-slate-600 transition-colors hover:bg-slate-100 hover:text-slate-950 dark:text-slate-300 dark:hover:bg-slate-900 dark:hover:text-slate-50",
activeHeadingId === item.id &&
"border-primary bg-primary/10 font-medium text-primary dark:text-primary",
item.level === 2 && "pl-4",
item.level === 3 && "pl-7 text-slate-500 dark:text-slate-400",
)}