feat: 知识库标签/实体关联跳转 + 会话重连容错

前端:
- Wiki 标签与实体改为可点击,弹出 RelatedNotesDialog 查看关联知识
- 知识库首次进入自动打开最近笔记,避免空白阅读区
- 流式重连识别 "Run not found",清理 sessionStorage 残留 key 并静默回退历史

后端:
- 线程鉴权区分 not found / not accessible,并支持 DB 切换产生的孤儿线程认领
- run 查询/join 在内存未命中时回退持久化存储,重启后返回干净的终止 SSE 而非 404
This commit is contained in:
Administrator committed 2026-06-11 23:19:09 +08:00
1 parent 76e2e67af8
commit 1b86373a54
8 files changed
+357 -23

No files matched your search

@@ -468,6 +468,8 @@ export default function KnowledgeBasePage() {
const [status, setStatus] = useState("all");
const [expandedIds, setExpandedIds] = useState<Set<string>>(new Set());
const treeInitializedRef = useRef(false);
// Auto-open a default note once on entry so the reading pane is never blank.
const defaultNoteShownRef = useRef(false);
const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false);
const [sidebarCollapsed, setSidebarCollapsed] = useState(readSidebarCollapsed);
@@ -495,6 +497,15 @@ export default function KnowledgeBasePage() {
const { data: note, isLoading: noteLoading } = useKnowledgeNote(noteId);
const { data: wikiLinks } = useNoteWikilinks(noteId);
// On first entry without an explicit note, open the most recent one so the
// reading pane shows real content instead of the empty placeholder.
useEffect(() => {
if (defaultNoteShownRef.current || noteId || isLoading) return;
if (notes.length === 0) return;
defaultNoteShownRef.current = true;
navigate(`/page/workspace/knowledge/${notes[0].id}`, { replace: true });
}, [noteId, isLoading, notes, navigate]);
// First load: expand the root-level folders so the tree reads as a directory.
useEffect(() => {
if (treeInitializedRef.current || tree.length === 0) return;