diff --git a/frontend/src/components/LogViewer/LogStreamViewer.tsx b/frontend/src/components/LogViewer/LogStreamViewer.tsx index 9d034097..28e51a81 100644 --- a/frontend/src/components/LogViewer/LogStreamViewer.tsx +++ b/frontend/src/components/LogViewer/LogStreamViewer.tsx @@ -73,7 +73,7 @@ export const LogStreamViewer: React.FC = ({ console.log('[LogStreamViewer] Render - status:', currentStatus, 'error:', error, 'shouldShowError:', shouldShowError, 'isConnecting:', isConnecting); return ( -
+
{/* 自定义控制栏 */} {customToolbar && (
@@ -82,7 +82,7 @@ export const LogStreamViewer: React.FC = ({ )} {/* 日志显示区域 */} -
+
{shouldShowError ? (
diff --git a/frontend/src/components/LogViewer/MonacoLogViewer.tsx b/frontend/src/components/LogViewer/MonacoLogViewer.tsx index f3f3a0fe..f2af88ab 100644 --- a/frontend/src/components/LogViewer/MonacoLogViewer.tsx +++ b/frontend/src/components/LogViewer/MonacoLogViewer.tsx @@ -12,6 +12,7 @@ export const MonacoLogViewer: React.FC = ({ fontSize = 12, theme = 'vs-dark', height = '100%', + wordWrap = false, onReady, className = '', style = {}, @@ -27,6 +28,15 @@ export const MonacoLogViewer: React.FC = ({ autoScrollRef.current = autoScroll; }, [autoScroll]); + // 更新wordWrap设置 + useEffect(() => { + if (editorRef.current) { + editorRef.current.updateOptions({ + wordWrap: wordWrap ? 'on' : 'off', + }); + } + }, [wordWrap]); + // Monaco Editor挂载完成 const handleEditorDidMount = (editor: editor.IStandaloneCodeEditor, monaco: Monaco) => { editorRef.current = editor; @@ -125,7 +135,7 @@ export const MonacoLogViewer: React.FC = ({ }; return ( -
+
= ({ readOnly: true, minimap: { enabled: false }, scrollBeyondLastLine: false, - wordWrap: 'off', + wordWrap: wordWrap ? 'on' : 'off', lineNumbers: 'on', glyphMargin: false, folding: false, diff --git a/frontend/src/components/LogViewer/types.ts b/frontend/src/components/LogViewer/types.ts index c1b2d50e..6effcf00 100644 --- a/frontend/src/components/LogViewer/types.ts +++ b/frontend/src/components/LogViewer/types.ts @@ -159,6 +159,9 @@ export interface MonacoLogViewerProps { /** 高度 */ height?: string | number; + /** 自动换行 */ + wordWrap?: boolean; + /** 就绪回调 */ onReady?: (api: LogViewerAPI) => void; diff --git a/frontend/src/components/Terminal/TerminalWindowManager.tsx b/frontend/src/components/Terminal/TerminalWindowManager.tsx index 3c55eae4..b2495bbc 100644 --- a/frontend/src/components/Terminal/TerminalWindowManager.tsx +++ b/frontend/src/components/Terminal/TerminalWindowManager.tsx @@ -199,9 +199,9 @@ export function TerminalWindowManager({ {windows.map(win => (
= ({
- {/* 窗口内容 */} -
+ {/* 窗口内容 - relative定位确保子元素的absolute定位正确 */} +
{children}
diff --git a/frontend/src/pages/Dashboard/components/LogWindowManager.tsx b/frontend/src/pages/Dashboard/components/LogWindowManager.tsx index 79d71559..f2eb090f 100644 --- a/frontend/src/pages/Dashboard/components/LogWindowManager.tsx +++ b/frontend/src/pages/Dashboard/components/LogWindowManager.tsx @@ -28,6 +28,7 @@ import { Loader2, ChevronUp, ChevronDown, + WrapText, } from 'lucide-react'; import { Badge } from '@/components/ui/badge'; import { @@ -76,6 +77,7 @@ const LogViewerContent: React.FC<{ const [loadingPods, setLoadingPods] = useState(app.runtimeType === 'K8S'); const [isControlBarCollapsed, setIsControlBarCollapsed] = useState(false); const [status, setStatus] = useState(LogStreamStatus.DISCONNECTED); + const [wordWrap, setWordWrap] = useState(true); const controlApiRef = useRef(null); const logApiRef = useRef(null); @@ -392,6 +394,9 @@ const LogViewerContent: React.FC<{ controlApiRef.current.send(JSON.stringify(stopMessage)); + // 立即更新状态为DISCONNECTED,确保UI正确显示开始按钮 + setStatus(LogStreamStatus.DISCONNECTED); + setTimeout(() => { controlApiRef.current?.disconnect(); }, 100); @@ -537,6 +542,20 @@ const LogViewerContent: React.FC<{ 清空 + + + + + + {wordWrap ? '关闭换行' : '自动换行'} +
@@ -587,6 +606,7 @@ const LogViewerContent: React.FC<{ theme: 'vs-dark', fontSize: 13, height: '100%', + wordWrap: wordWrap, }} onReady={(controlApi, logApi) => { controlApiRef.current = controlApi;