import { Button } from '@heroui/button'; import { Card, CardBody, CardHeader } from '@heroui/card'; import { Select, SelectItem } from '@heroui/select'; import type { Selection } from '@react-types/shared'; import { useEffect, useRef, useState } from 'react'; import { colorizeLogLevel } from '@/utils/terminal'; import PageLoading from '../page_loading'; import XTerm from '../xterm'; import type { XTermRef } from '../xterm'; import LogLevelSelect from './log_level_select'; export interface HistoryLogsProps { list: string[] onSelect: (name: string) => void selectedLog?: string refreshList: () => void refreshLog: () => void listLoading?: boolean logLoading?: boolean listError?: Error logContent?: string } const HistoryLogs: React.FC = (props) => { const { list, onSelect, selectedLog, refreshList, refreshLog, listLoading, logContent, listError, logLoading, } = props; const Xterm = useRef(null); const [logLevel, setLogLevel] = useState( new Set(['info', 'warn', 'error']) ); const logToColored = (log: string) => { const logs = log .split('\n') .map((line) => { const colored = colorizeLogLevel(line); return colored; }) .filter((log) => { if (logLevel === 'all') { return true; } return logLevel.has(log.level); }) .map((log) => log.content) .join('\r\n'); return logs; }; const onDownloadLog = () => { if (!logContent) { return; } const blob = new Blob([logContent], { type: 'text/plain' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `${selectedLog}.log`; a.click(); URL.revokeObjectURL(url); }; useEffect(() => { if (!Xterm.current || !logContent) { return; } Xterm.current.clear(); const _logContent = logToColored(logContent); Xterm.current.write(_logContent + '\r\nnapcat@webui:~$ '); }, [logContent, logLevel]); return ( <> 历史日志 - NapCat WebUI ); }; export default HistoryLogs;