diff --git a/src/pages/code-graph/components/CodePod.tsx b/src/pages/code-graph/components/CodePod.tsx index c50037c..4046bfc 100644 --- a/src/pages/code-graph/components/CodePod.tsx +++ b/src/pages/code-graph/components/CodePod.tsx @@ -1,5 +1,5 @@ import { useEffect, useState } from 'react'; -import { Save, RefreshCw } from 'lucide-react'; +import { Save, RefreshCw, Sparkles } from 'lucide-react'; import './CodePod.css'; import CodeMirror from '@uiw/react-codemirror'; import { vscodeDark } from '@uiw/codemirror-theme-vscode'; @@ -13,6 +13,7 @@ import { queryApi as projectApi } from '@/modules/project-api'; import { FileProjectData } from '../modules/tree'; import './CodePod.css'; import { useCodeGraphStore } from '../store'; +import { useBotHelperStore } from '../store/bot-helper'; import { useShallow } from 'zustand/shallow'; // ─── 目录树类型 ──────────────────────────────────────────────────────────────── @@ -162,15 +163,6 @@ function getLangExtension(filename: string) { return []; } } - -/** 获取文件内容(base64 解码) */ -async function fetchFileContent(filepath: string): Promise { - const res = await projectApi['project-file'].get({ filepath }); - if (res.code !== 200) return ''; - const raw = res.data?.content ?? ''; - return raw ? decodeBase64(raw) : ''; -} - // ─── 组件 ───────────────────────────────────────────────────────────────────── interface CodePodProps { @@ -239,6 +231,11 @@ export function CodePod({ open, onClose, nodeAttrs }: CodePodProps) { if (!filepath) return; await codeGraphStore.saveFile(filepath, fileContent); }; + + const handleAIOpen = () => { + useBotHelperStore.getState().openModal(); + }; + useEffect(() => { if (!selectedFile) return; if (selectedFile.content) { @@ -315,9 +312,10 @@ export function CodePod({ open, onClose, nodeAttrs }: CodePodProps) {
{loading && 加载中…} + {/* 大屏幕显示刷新按钮 */} @@ -327,6 +325,12 @@ export function CodePod({ open, onClose, nodeAttrs }: CodePodProps) { title='保存'> +
diff --git a/src/pages/code-graph/components/NodeInfo.tsx b/src/pages/code-graph/components/NodeInfo.tsx index 52b4da9..536dc38 100644 --- a/src/pages/code-graph/components/NodeInfo.tsx +++ b/src/pages/code-graph/components/NodeInfo.tsx @@ -18,6 +18,39 @@ const KIND_LABEL: Record = { }; export function NodeInfo() { + const codeGraphStore = useCodeGraphStore( + useShallow((s) => ({ + nodeInfoData: s.nodeInfoData, + + })), + ); + const projectPath = codeGraphStore.nodeInfoData?.projectPath || ''; + const relativePath = codeGraphStore.nodeInfoData?.fullPath.replace(projectPath + '/', '') || '/'; + return (<> {/* 内容 */} +
+ {/* projectPath */} +
+ 项目路径 + + {projectPath} + +
+ {/* relativePath */} +
+ 相对路径 + + {relativePath} + +
+ + +
) +} +export const NodeInfoContainer = () => { const { nodeInfoOpen, nodeInfoData, nodeInfoPos, closeNodeInfo, setCodePodOpen, setCodePodAttrs } = useCodeGraphStore( useShallow((s) => ({ nodeInfoOpen: s.nodeInfoOpen, @@ -53,6 +86,16 @@ export function NodeInfo() { // 拖拽偏移 const [offset, setOffset] = useState({ x: 0, y: 0 }); const [pinLeft, setPinLeft] = useState(false); // 编辑后固定到右下角 + const [isMobile, setIsMobile] = useState(false); + + // 检测屏幕大小 + useEffect(() => { + const checkMobile = () => setIsMobile(window.innerWidth < 768); + checkMobile(); + window.addEventListener('resize', checkMobile); + return () => window.removeEventListener('resize', checkMobile); + }, []); + const dragging = useRef(false); const dragStart = useRef({ mx: 0, my: 0, ox: 0, oy: 0 }); @@ -93,20 +136,22 @@ export function NodeInfo() { if (!nodeInfoOpen || !nodeInfoData) return null; - const posStyle = pinLeft - ? { right: 10 - offset.x, bottom: 10 - offset.y, top: 'auto' as const, left: 'auto' as const } - : { left: nodeInfoPos.x + offset.x + 40, top: nodeInfoPos.y + offset.y - 40 }; + const posStyle = isMobile + ? { inset: 0, width: '100%', height: '100%' } + : pinLeft + ? { right: 10 - offset.x, bottom: 10 - offset.y, top: 'auto' as const, left: 'auto' as const } + : { left: nodeInfoPos.x + offset.x + 40, top: nodeInfoPos.y + offset.y - 40 }; const name = nodeInfoData.fullPath.split('/').pop() || nodeInfoData.label; const projectPath = nodeInfoData.projectPath || ''; const relativePath = nodeInfoData.fullPath.replace(projectPath + '/', '') || '/'; return (
+ onMouseDown={isMobile ? undefined : onMouseDown}> {/* 标题栏 */} -
+
@@ -124,7 +169,7 @@ export function NodeInfo() { className='ml-1 text-slate-500 hover:text-emerald-400 transition-colors'> - + {KIND_LABEL[nodeInfoData.kind]} @@ -135,32 +180,9 @@ export function NodeInfo() {
- - {/* 内容 */} -
- {/* projectPath */} -
- 项目路径 - - {projectPath} - -
- {/* relativePath */} -
- 相对路径 - - {relativePath} - -
- - -
+
); } -export default NodeInfo; +export default NodeInfoContainer; diff --git a/src/pages/code-graph/page.tsx b/src/pages/code-graph/page.tsx index f511a13..e43f246 100644 --- a/src/pages/code-graph/page.tsx +++ b/src/pages/code-graph/page.tsx @@ -1,12 +1,11 @@ import { useState, useEffect } from 'react'; -import { FileProjectData } from './modules/tree'; import { useShallow } from 'zustand/react/shallow'; import { DatabaseIcon, RefreshCw } from 'lucide-react'; import { CodePod } from './components/CodePod'; import { useCodeGraphStore } from './store'; import CodeGraphView from './components/CodeGraph'; import { Code3DGraph } from './components/Code3DGraph'; -import { NodeInfo } from './components/NodeInfo'; +import { NodeInfoContainer } from './components/NodeInfo'; import { ProjectDialog } from './components/ProjectDialog'; import { BotHelperModal } from './components/BotHelperModal'; import { useLayoutStore } from '../auth/store'; @@ -90,7 +89,7 @@ export default function CodeGraphPage() { nodeAttrs={codePodAttrs} /> {/* NodeInfo 信息窗 */} - + {/* 项目管理弹窗 */} {/* Bot AI 助手弹窗 */}