diff --git a/src/pages/code-graph/components/BotHelperModal.tsx b/src/pages/code-graph/components/BotHelperModal.tsx index d8dff06..0a8beb6 100644 --- a/src/pages/code-graph/components/BotHelperModal.tsx +++ b/src/pages/code-graph/components/BotHelperModal.tsx @@ -1,5 +1,6 @@ import { BotIcon, XIcon, FileIcon, FolderIcon, DatabaseIcon, MoreHorizontalIcon } from 'lucide-react'; import { useNavigate, useLocation } from '@tanstack/react-router'; +import { toast } from 'sonner'; import { useBotHelperStore, BOT_KEYS, BotKey } from '../store/bot-helper'; import { useShallow } from 'zustand/react/shallow'; import { useCodeGraphStore, NodeInfoData } from '../store'; @@ -46,13 +47,22 @@ export function BotHelperModal() { const res = await createQuestion({ question: botHelperStore.input, projectPath: nodeInfoData.projectPath, + filePath: nodeInfoData.kind === 'file' ? nodeInfoData.fullPath : undefined, engine: botHelperStore.activeKey, }); console.log(res); } + toast.success('消息发送成功'); botHelperStore.closeModal(); }; + const handleKeyDown = (e: React.KeyboardEvent) => { + if (e.ctrlKey && e.key === 'Enter') { + e.preventDefault(); + handleConfirm(); + } + }; + if (!botHelperStore.open) return null; return ( @@ -124,6 +134,7 @@ export function BotHelperModal() { placeholder='请输入内容...' value={botHelperStore.input} onChange={(e) => botHelperStore.setInput(e.target.value)} + onKeyDown={handleKeyDown} autoFocus /> + ); + })} + + + + ); +} + +export default ProjectPanel; diff --git a/src/pages/code-graph/page.tsx b/src/pages/code-graph/page.tsx index e43f246..2747d67 100644 --- a/src/pages/code-graph/page.tsx +++ b/src/pages/code-graph/page.tsx @@ -8,15 +8,18 @@ import { Code3DGraph } from './components/Code3DGraph'; import { NodeInfoContainer } from './components/NodeInfo'; import { ProjectDialog } from './components/ProjectDialog'; import { BotHelperModal } from './components/BotHelperModal'; +import { ProjectPanel } from './components/ProjectPanel'; import { useLayoutStore } from '../auth/store'; +import type { FileProjectData } from './modules/tree'; type ViewMode = '2d' | '3d'; export default function CodeGraphPage() { const [viewMode, setViewMode] = useState('3d'); + const [projectFocus, setProjectFocus] = useState(null); const layoutStore = useLayoutStore(useShallow((s) => ({ me: s.me, }))); - const { codePodOpen, setCodePodOpen, codePodAttrs, setProjectDialogOpen, init, files, fetchProjects } = useCodeGraphStore( + const { codePodOpen, setCodePodOpen, codePodAttrs, setProjectDialogOpen, init, files, fetchProjects, setFiles } = useCodeGraphStore( useShallow((s) => ({ files: s.files, setFiles: s.setFiles, @@ -34,6 +37,16 @@ export default function CodeGraphPage() { init(layoutStore.me); }, [layoutStore.me]); + const handleProjectClick = (projectPath: string, projectFiles: FileProjectData[]) => { + if (viewMode === '3d') { + setFiles(projectFiles); + setTimeout(() => { + setProjectFocus(projectPath); + setTimeout(() => setProjectFocus(null), 100); + }, 150); + } + }; + return (
{/* 顶部工具栏 */} @@ -77,7 +90,10 @@ export default function CodeGraphPage() { {/* 图视图 */}
{viewMode === '3d' ? ( - + <> + + + ) : ( )} diff --git a/src/pages/code-graph/store/index.ts b/src/pages/code-graph/store/index.ts index e5be0c3..a3c7bc4 100644 --- a/src/pages/code-graph/store/index.ts +++ b/src/pages/code-graph/store/index.ts @@ -64,7 +64,7 @@ type State = { projectPath?: string; // 项目路径,必填 getContent?: boolean; // 是否获取文件内容,默认为 false }) => Promise>; - createQuestion: (opts: { question: string, projectPath: string, engine?: 'openclaw' | 'opencode' }) => any; + createQuestion: (opts: { question: string, projectPath: string, filePath?: string, engine?: 'openclaw' | 'opencode', }) => any; saveFile: (filepath: string, content: string) => Promise; isMobile: boolean; setIsMobile: (isMobile: boolean) => void; @@ -274,11 +274,15 @@ export const useCodeGraphStore = create()((set, get) => ({ isMobile: false, setIsMobile: (isMobile) => set({ isMobile }), createQuestion: async (opts) => { - const { question, projectPath, engine = 'opencode' } = opts; + const { question, projectPath, filePath, engine = 'opencode' } = opts; const url = get().url - const q = ` + let q = ` ${question} 项目路径: ${projectPath}` + if (filePath && filePath !== projectPath) { + q += ` + 文件路径: ${filePath}`; + } const res = await opencodeApi["opencode-cnb"].question({ question: q, directory: projectPath,