diff --git a/apps/desktop/src/renderer/src/components/context-room/ported/components/detail-panels/ThoughtsPane.tsx b/apps/desktop/src/renderer/src/components/context-room/ported/components/detail-panels/ThoughtsPane.tsx deleted file mode 100644 index cd413953..00000000 --- a/apps/desktop/src/renderer/src/components/context-room/ported/components/detail-panels/ThoughtsPane.tsx +++ /dev/null @@ -1,266 +0,0 @@ -import { Footprints, ListTree, Lock, LockOpen, Network, RotateCcw, Sparkles, Undo2 } from 'lucide-react'; -import { useMemo, useState } from 'react'; - -import { useLocale } from '../../../../../i18n/LocaleContext'; -import type { EmergenceCardDto, EmergenceMode } from '../../../../../../../shared/knowledge'; -import type { ContextRoomRecord } from '../../types'; -import { useEmergence } from '../../hooks/useEmergence'; -import { VeinGraphCanvas } from '../VeinGraphCanvas'; -import { EmergenceCard } from './EmergenceCard'; - -/** - * 思路面板 · 知识涌现:聚焦=默认态(随焦点增量更新);漫步=底部入口进入的 - * 独立态(两个世界,整屏交叉过渡),再走一次=新 seed、沿此漫步=换起点。 - * 模式是临时态:不进 localStorage,重进面板落在聚焦。 - */ -export function ThoughtsPane({ - room, - variant = 'board', - focusDocumentId, - focusDocumentTitle, - focusSelectionText, - onQuote, - onViewChange, -}: { - room: ContextRoomRecord; - /** board=独立板块;companion=伴随区(引用=光标处插块引用)。 */ - variant?: 'board' | 'companion'; - focusDocumentId?: string | null; - focusDocumentTitle?: string | null; - /** 选区文本(伴随区编辑态);渲染层截断到 300 字。 */ - focusSelectionText?: string | null; - onQuote?: (card: EmergenceCardDto) => void; - /** 视图切换回调(伴随区据此扩展/收缩列宽)。 */ - onViewChange?: (view: 'cards' | 'vein') => void; -}) { - const { t } = useLocale(); - const [mode, setMode] = useState('focus'); - const [view, setView] = useState<'cards' | 'vein'>('cards'); - const [locked, setLocked] = useState(false); - const [pinned, setPinned] = useState([]); - const [hiddenFocus, setHiddenFocus] = useState>(() => new Set()); - const [hiddenWander, setHiddenWander] = useState>(() => new Set()); - const [expandedId, setExpandedId] = useState(null); - const [wanderStart, setWanderStart] = useState<{ nodeRef: string | null; label: string } | null>(null); - - const selectionText = focusSelectionText ? focusSelectionText.slice(0, 300) : null; - const focusInput = useMemo(() => ({ - documentId: focusDocumentId ?? null, - selectionText, - blockId: null, - }), [focusDocumentId, selectionText]); - - const { - focusResult, wanderResult, focusLoading, wanderLoading, error, wanderFrom, - } = useEmergence({ roomId: room.id, focus: focusInput, locked }); - - const focusLabel = selectionText - ? t('contextRoom:emergence.selectionFocus') - : (focusDocumentTitle || room.title); - const nodeLabels = useMemo(() => new Map( - (mode === 'focus' ? focusResult?.nodes : wanderResult?.nodes)?.map((node) => [node.id, node.label]) ?? [], - ), [mode, focusResult, wanderResult]); - - const visibleFocusCards = (focusResult?.cards ?? []).filter((card) => !hiddenFocus.has(card.id)); - const visibleWanderCards = (wanderResult?.cards ?? []).filter((card) => !hiddenWander.has(card.id)); - - const enterWander = (startNodeRef: string | null, label: string) => { - setMode('wander'); - setExpandedId(null); - setWanderStart({ nodeRef: startNodeRef, label }); - wanderFrom(startNodeRef); - }; - - const backToFocus = () => { - setMode('focus'); - setExpandedId(null); - setWanderStart(null); - }; - - const pinCard = (card: EmergenceCardDto) => { - setPinned((current) => current.some((item) => item.id === card.id) ? current : [...current, card]); - }; - - const quoteCard = (card: EmergenceCardDto) => { - if (onQuote) onQuote(card); - else pinCard(card); - }; - - const wanderLabel = wanderStart?.label ?? focusLabel; - const focusCenterRef = focusDocumentId ? `doc:${focusDocumentId}` : `room:${room.id}`; - const expandedCard = expandedId === null - ? null - : (mode === 'focus' ? focusResult?.cards : wanderResult?.cards)?.find((card) => card.id === expandedId) ?? null; - - // 点脉络节点=切回卡片流并展开同一候选卡;卡片展开的 nodeRef 反向高亮脉络节点 - const openCardAtNode = (nodeRef: string) => { - const card = (mode === 'focus' ? focusResult?.cards : wanderResult?.cards) - ?.find((candidate) => candidate.nodeRef === nodeRef); - if (!card) return; - switchView('cards'); - setExpandedId(card.id); - }; - - const switchView = (next: 'cards' | 'vein') => { - setView(next); - onViewChange?.(next); - }; - - const viewToggle = ( -
- - -
- ); - - const veinOf = (result: typeof focusResult, centerRef: string) => ( - result && result.nodes.length > 0 ? ( -
- -
- ) : ( -
{t('contextRoom:emergence.veinEmpty')}
- ) - ); - - return ( -
-
-
-
-
-
- {viewToggle} - -
-
- {view === 'cards' ? ( -
- {visibleFocusCards.map((card) => ( - setExpandedId((current) => current === card.id ? null : card.id)} - onPrimaryAction={() => quoteCard(card)} - onPin={() => pinCard(card)} - onHide={() => setHiddenFocus((current) => new Set(current).add(card.id))} - /> - ))} - {!focusLoading && visibleFocusCards.length === 0 ? ( -
- {error ?? t('contextRoom:emergence.noCardsYet')} -
- ) : null} - {focusLoading && visibleFocusCards.length === 0 ? ( -
{t('contextRoom:emergence.projecting')}
- ) : null} -
- ) : veinOf(focusResult, focusCenterRef)} - {focusResult?.degraded ? ( -

{t('contextRoom:emergence.degraded')}

- ) : null} - {pinned.length > 0 ? ( -
- {pinned.map((card) => ( - - {card.title} - - ))} -
- ) : null} -
- -
-
- -
-
-
-
-
- {viewToggle} -
- - -
-
-
- {view === 'cards' ? ( -
- {visibleWanderCards.map((card) => ( - setExpandedId((current) => current === card.id ? null : card.id)} - onPrimaryAction={() => enterWander(card.nodeRef, card.title)} - onPin={() => pinCard(card)} - onHide={() => setHiddenWander((current) => new Set(current).add(card.id))} - /> - ))} - {!wanderLoading && visibleWanderCards.length === 0 ? ( -
- {error ?? t('contextRoom:emergence.wanderEmpty')} -
- ) : null} - {wanderLoading ? ( -
{t('contextRoom:emergence.wandering')}
- ) : null} -
- ) : veinOf(wanderResult, wanderStart?.nodeRef ?? focusCenterRef)} -
-
- ); -}