import React, { useState, useRef, useEffect } from 'react'; import { ResizeBox, Tabs } from '@arco-design/web-react'; import styles from './style/logBar.module.less'; import { updateLogBarStatus } from '@/store/ideContainer'; import { useSelector, useDispatch } from 'react-redux'; import { getNodeData } from '@/api/appIns'; import RunTimeData from './components/runTimeData'; import { getCurrentAppKey } from '@/utils/flow/runtime'; const TabPane = Tabs.TabPane; interface LogMessage { id: number; type: string; message: string; timestamp: string; } // 添加运行数据接口 interface RuntimeData { [appId: string]: any; } interface LogBarProps { a?: string; } const data = [ { key: '1', title: '运行日志', content: '运行时日志...', }, { key: '2', title: '校验日志', content: '校验日志...', }, { key: '3', title: '运行数据', content: '运行数据日志...', }, // { // key: '4', // title: '组件日志', // content: '组件日志...' // } ]; const LogBar: React.FC = () => { const [tabs] = useState(data); const [activeTab, setActiveTab] = useState('1'); const resizeBoxRef = useRef(null); // 引用 ResizeBox 容器 const [validationLogs, setValidationLogs] = useState([]); const [runtimeLogs, setruntimeLogs] = useState([]); // 添加运行时日志状态 const [logContainerHeight, setLogContainerHeight] = useState('250px'); // 添加日志容器高度状态 const [runtimeData, setRuntimeData] = useState({}); // 添加运行数据状态 const [loading, setLoading] = useState(false); const { logBarStatus, appRuntimeData, currentAppData } = useSelector( (state: any) => state.ideContainer ); const dispatch = useDispatch(); // 处理 Tab 点击事件 const handleTabClick = (key: string) => { // 如果点击当前激活的 tab,则切换收起状态 if (key === activeTab) { dispatch(updateLogBarStatus(!logBarStatus)); } else { // 如果点击的是其他 tab,则切换到该 tab 并展开 setActiveTab(key); dispatch(updateLogBarStatus(true)); } }; // 当 collapsed 状态改变时,直接更新元素的样式 useEffect(() => { if (resizeBoxRef.current) { resizeBoxRef.current.style.height = logBarStatus ? logContainerHeight : '0px'; } }, [logBarStatus, logContainerHeight]); // 处理 ResizeBox 手动调整大小事件 const handleResize = ( e: MouseEvent, size: { width: number; height: number; } ) => { // 当高度接近收起状态的高度时,同步更新 logBarStatus 状态 if (size.height <= 40) { dispatch(updateLogBarStatus(false)); } else { dispatch(updateLogBarStatus(true)); // 更新日志容器高度状态 setLogContainerHeight(`${size.height}px`); } }; // 监听日志消息事件 useEffect(() => { const handleLogMessage = (event: CustomEvent) => { const { type, message, timestamp, appId } = event.detail; // 如果是校验类型的消息且当前校验日志tab可见,则添加到校验日志中 if (type === 'validation') { const newLog: LogMessage = { id: Date.now(), type, message, timestamp, }; setValidationLogs((prev) => [...prev, newLog]); // 自动切换到校验日志tab并展开logBar // setActiveTab('2'); dispatch(updateLogBarStatus(true)); } // 如果是运行时日志 else if (type === 'runtime') { const newLog: LogMessage = { id: Date.now(), type, message, timestamp, }; setruntimeLogs((prev) => [...prev, newLog]); // 自动切换到运行日志tab并展开logBar dispatch(updateLogBarStatus(true)); // 同时将日志添加到对应应用的运行日志中 // 如果提供了 appId,优先使用提供的 appId;否则使用当前激活的应用 const targetAppKey = appId || getCurrentAppKey(currentAppData); if (targetAppKey) { dispatch({ type: 'ideContainer/addRuntimeLog', payload: { log: newLog, appId: targetAppKey, }, }); } } }; // 添加事件监听器 document.addEventListener('logMessage', handleLogMessage as EventListener); // 清理事件监听器 return () => { document.removeEventListener( 'logMessage', handleLogMessage as EventListener ); }; }, [dispatch, currentAppData]); // 获取当前应用的运行状态 const currentAppKey = getCurrentAppKey(currentAppData); const isRunning = currentAppKey && appRuntimeData[currentAppKey]?.isRunning; // 实现轮询获取运行数据 - 只在应用运行时轮询 useEffect(() => { let intervalId: NodeJS.Timeout | null = null; const appKey = getCurrentAppKey(currentAppData); // 只有在应用正在运行且有 runId 时才开始轮询 if ( appKey && appRuntimeData[appKey]?.isRunning && appRuntimeData[appKey]?.runId ) { const fetchRuntimeData = async () => { try { setLoading(true); const response = await getNodeData(appRuntimeData[appKey].runId); setRuntimeData((prev) => ({ ...prev, [appKey]: response.data, })); } catch (error) { console.error('获取运行数据失败:', error); } finally { setLoading(false); } }; // 立即获取一次数据 fetchRuntimeData(); // 设置轮询,每3秒获取一次数据 intervalId = setInterval(fetchRuntimeData, 3000); } // 清理函数,组件卸载或应用停止运行时清除定时器 return () => { if (intervalId) { clearInterval(intervalId); } }; }, [currentAppData, appRuntimeData]); // 当应用停止运行时,清除运行数据 useEffect(() => { const appKey = getCurrentAppKey(currentAppData); if (appKey && !appRuntimeData[appKey]?.isRunning) { // 清除当前应用的运行数据 setRuntimeData((prev) => { const newData = { ...prev }; delete newData[appKey]; return newData; }); } }, [isRunning, currentAppData]); // 渲染校验日志内容 const renderValidationLogs = () => { return (
{validationLogs.length === 0 ? (

暂无校验日志

) : ( validationLogs.map((log) => (
{new Date(log.timestamp).toLocaleString()}
{log.message}
)) )}
); }; // 渲染运行时日志内容 const renderRuntimeLogs = () => { // 获取当前应用的运行日志 const currentAppKey = getCurrentAppKey(currentAppData); const currentAppLogs = currentAppKey && appRuntimeData[currentAppKey] ? appRuntimeData[currentAppKey].logs || [] : []; return (
{currentAppLogs.length === 0 ? (

暂无运行时日志

) : ( currentAppLogs.map((log: LogMessage) => (
{new Date(log.timestamp).toLocaleString()}
{log.message}
)) )}
); }; // 渲染运行数据内容 const renderRuntimeData = () => { const currentAppKey = getCurrentAppKey(currentAppData); const currentAppDataContent = currentAppKey ? runtimeData[currentAppKey] : null; return (
{!currentAppDataContent ? (

暂无运行数据

) : ( )}
); }; return ( <> {tabs.map((x) => ( {x.key === '1' ? renderRuntimeLogs() : x.key === '2' ? renderValidationLogs() : x.key === '3' ? renderRuntimeData() // 添加运行数据渲染 : x.content} ))} ); }; export default LogBar;