feat: Migrate to React Flow and add Fixed + Dynamic category mode
Frontend: - Migrate MindmapDAG from D3.js to React Flow (@xyflow/react) - Add custom node components (QueryNode, CategoryHeaderNode, AttributeNode) - Add useDAGLayout hook for column-based layout - Add "AI" badge for LLM-suggested categories - Update CategorySelector with Fixed + Dynamic mode option - Improve dark/light theme support Backend: - Add FIXED_PLUS_DYNAMIC category mode - Filter duplicate category names in LLM suggestions - Update prompts to exclude fixed categories when suggesting new ones - Improve LLM service with better error handling and logging - Auto-remove /no_think prefix for non-Qwen models - Add smart JSON format detection for model compatibility - Improve JSON extraction with multiple parsing strategies 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
import { useState, useRef, useCallback } from 'react';
|
||||
import { ConfigProvider, Layout, theme, Typography } from 'antd';
|
||||
import { ConfigProvider, Layout, theme, Typography, Space } from 'antd';
|
||||
import { ApartmentOutlined } from '@ant-design/icons';
|
||||
import { ThemeToggle } from './components/ThemeToggle';
|
||||
import { InputPanel } from './components/InputPanel';
|
||||
import { MindmapPanel } from './components/MindmapPanel';
|
||||
import { useAttribute } from './hooks/useAttribute';
|
||||
import type { MindmapD3Ref } from './components/MindmapD3';
|
||||
import type { MindmapDAGRef } from './components/MindmapDAG';
|
||||
import type { CategoryMode } from './types';
|
||||
|
||||
const { Header, Sider, Content } = Layout;
|
||||
@@ -22,7 +23,7 @@ function App() {
|
||||
nodeSpacing: 32,
|
||||
fontSize: 14,
|
||||
});
|
||||
const mindmapRef = useRef<MindmapD3Ref>(null);
|
||||
const mindmapRef = useRef<MindmapDAGRef>(null);
|
||||
|
||||
const handleAnalyze = async (
|
||||
query: string,
|
||||
@@ -36,12 +37,8 @@ function App() {
|
||||
await analyze(query, model, temperature, chainCount, categoryMode, customCategories, suggestedCategoryCount);
|
||||
};
|
||||
|
||||
const handleExpandAll = useCallback(() => {
|
||||
mindmapRef.current?.expandAll();
|
||||
}, []);
|
||||
|
||||
const handleCollapseAll = useCallback(() => {
|
||||
mindmapRef.current?.collapseAll();
|
||||
const handleResetView = useCallback(() => {
|
||||
mindmapRef.current?.resetView();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
@@ -57,11 +54,37 @@ function App() {
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
padding: '0 24px',
|
||||
background: isDark
|
||||
? 'linear-gradient(90deg, #141414 0%, #1f1f1f 50%, #141414 100%)'
|
||||
: 'linear-gradient(90deg, #fff 0%, #fafafa 50%, #fff 100%)',
|
||||
borderBottom: isDark ? '1px solid #303030' : '1px solid #f0f0f0',
|
||||
boxShadow: isDark
|
||||
? '0 2px 8px rgba(0, 0, 0, 0.3)'
|
||||
: '0 2px 8px rgba(0, 0, 0, 0.06)',
|
||||
}}
|
||||
>
|
||||
<Title level={4} style={{ margin: 0, color: isDark ? '#fff' : '#000' }}>
|
||||
Attribute Agent
|
||||
</Title>
|
||||
<Space align="center" size="middle">
|
||||
<ApartmentOutlined
|
||||
style={{
|
||||
fontSize: 24,
|
||||
color: isDark ? '#177ddc' : '#1890ff',
|
||||
}}
|
||||
/>
|
||||
<Title
|
||||
level={4}
|
||||
style={{
|
||||
margin: 0,
|
||||
background: isDark
|
||||
? 'linear-gradient(90deg, #177ddc 0%, #69c0ff 100%)'
|
||||
: 'linear-gradient(90deg, #1890ff 0%, #40a9ff 100%)',
|
||||
WebkitBackgroundClip: 'text',
|
||||
WebkitTextFillColor: 'transparent',
|
||||
backgroundClip: 'text',
|
||||
}}
|
||||
>
|
||||
Attribute Agent
|
||||
</Title>
|
||||
</Space>
|
||||
<ThemeToggle isDark={isDark} onToggle={setIsDark} />
|
||||
</Header>
|
||||
<Layout>
|
||||
@@ -96,8 +119,7 @@ function App() {
|
||||
currentResult={currentResult}
|
||||
onAnalyze={handleAnalyze}
|
||||
onLoadHistory={loadFromHistory}
|
||||
onExpandAll={handleExpandAll}
|
||||
onCollapseAll={handleCollapseAll}
|
||||
onResetView={handleResetView}
|
||||
visualSettings={visualSettings}
|
||||
onVisualSettingsChange={setVisualSettings}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user