// 终端审计 — 历史会话子面板 // Logan.Li import { useState } from 'react'; import { Card, CardContent } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table'; import { Search, RefreshCw, Play, Download, Monitor } from 'lucide-react'; import { terminalSessionApi } from '@/api'; import { ReplayDialog } from '@/components/system/ReplayDialog'; import { useTerminalSessions } from '@/hooks/api'; import { formatDuration, getStatusBadge } from './helpers'; export function HistorySessionsPanel() { const { data: sessions = [], isLoading, refetch } = useTerminalSessions({ page: 1, page_size: 100, status: 'closed', }); const [keyword, setKeyword] = useState(''); const [replayId, setReplayId] = useState(null); const [replayOpen, setReplayOpen] = useState(false); const filtered = sessions.filter((s) => { const kw = keyword.toLowerCase(); return ( !kw || (s.username || '').toLowerCase().includes(kw) || (s.server_name || '').toLowerCase().includes(kw) || (s.server_ip || '').toLowerCase().includes(kw) ); }); const openReplay = (id: number) => { setReplayId(id); setReplayOpen(true); }; const handleDownload = async (id: number) => { try { await terminalSessionApi.download(id); } catch { // download error is handled in http.download } }; return ( <>
setKeyword(e.target.value)} className="pl-9 h-9 bg-slate-800/50 border-slate-700 text-slate-200 placeholder:text-slate-500" />
{isLoading ? (
) : filtered.length === 0 ? (

暂无历史会话

) : ( ID 用户 目标服务器 端口 开始时间 结束时间 时长 状态 操作 {filtered.map((s) => ( {s.id} {s.username || '--'}
{s.server_name || '--'} {s.server_ip}
{s.server_port} {s.start_time ? new Date(s.start_time).toLocaleString() : '--'} {s.end_time ? new Date(s.end_time).toLocaleString() : '--'} {formatDuration(s.duration)} {getStatusBadge(s.status)}
))}
)}
); }