import { useState, useEffect } from 'react'; import { useParams, Link, useLocation } from 'react-router-dom'; import { ArrowLeft, Play, Loader2, FileCode, GitCommit, History, AlertTriangle } from 'lucide-react'; import { getBugDetail, triggerRepair, getRepairReportsByBug, type ErrorLog, type RepairReport } from '../api'; const SOURCE_LABELS: Record = { runtime: '运行时', cicd: 'CI/CD', deployment: '部署', }; const STATUS_LABELS: Record = { NEW: '新发现', VERIFYING: '验证中', CANNOT_REPRODUCE: '无法复现', PENDING_FIX: '待修复', FIXING: '修复中', FIXED: '已修复', VERIFIED: '已验证', DEPLOYED: '已部署', FIX_FAILED: '修复失败', }; export default function BugDetail() { const { id } = useParams<{ id: string }>(); const location = useLocation(); const [bug, setBug] = useState(null); const [loading, setLoading] = useState(true); const [repairing, setRepairing] = useState(false); const [repairMessage, setRepairMessage] = useState(''); const [repairHistory, setRepairHistory] = useState([]); const backSearch = location.state?.fromSearch || ''; useEffect(() => { const fetchBug = async () => { if (!id) return; try { const response = await getBugDetail(parseInt(id)); setBug(response.data); } catch (error) { console.error('Failed to fetch bug:', error); } finally { setLoading(false); } }; fetchBug(); }, [id]); useEffect(() => { if (id) { getRepairReportsByBug(parseInt(id)).then(res => { setRepairHistory(res.data.items); }).catch(console.error); } }, [id]); const handleTriggerRepair = async () => { if (!bug) return; setRepairing(true); setRepairMessage(''); try { await triggerRepair(bug.id); setBug({ ...bug, status: 'PENDING_FIX' }); setRepairMessage('已成功触发修复'); } catch (error) { console.error('Failed to trigger repair:', error); setRepairMessage('触发修复失败'); } finally { setRepairing(false); } }; if (loading) { return (
); } if (!bug) { return
未找到该缺陷
; } const isRuntime = !bug.source || bug.source === 'runtime'; const canTriggerRepair = ['NEW', 'FIX_FAILED'].includes(bug.status) && isRuntime; return (
返回缺陷列表

{bug.error_type}: {bug.error_message}

项目:{bug.project_id} 来源:{SOURCE_LABELS[bug.source] || '运行时'} 环境:{bug.environment} 级别:{bug.level}
{STATUS_LABELS[bug.status] || bug.status}
{bug.file_path && (
文件位置
{bug.file_path} : 第 {bug.line_number} 行
)} {bug.source === 'cicd' && bug.context?.workflow_name && (
CI/CD 信息
工作流:{bug.context.workflow_name} / {bug.context.job_name} / {bug.context.step_name} {bug.context.branch && <>
分支:{bug.context.branch}} {bug.context.run_url && ( <>
查看 CI 日志 )}
)} {bug.source === 'deployment' && bug.context?.pod_name && (
部署信息
命名空间:{bug.context.namespace} | Pod:{bug.context.pod_name}
容器:{bug.context.container_name} | 重启次数:{bug.context.restart_count} {bug.context.node_name && <>
节点:{bug.context.node_name}}
)} {bug.commit_hash && (
Git 信息
{bug.commit_hash} {bug.version && ` | v${bug.version}`}
)}
堆栈跟踪
                        {typeof bug.stack_trace === 'string'
                            ? bug.stack_trace
                            : JSON.stringify(bug.stack_trace, null, 2)}
                    
{bug.context && Object.keys(bug.context).length > 0 && (
上下文信息
                            {JSON.stringify(bug.context, null, 2)}
                        
)}
{repairMessage && ( {repairMessage} )} {!canTriggerRepair && !repairing && ( {!isRuntime ? 'CI/CD 和部署错误暂不支持自动修复' : '仅"新发现"或"修复失败"状态的缺陷可触发修复'} )}
{bug.failure_reason && (
修复失败原因
{bug.failure_reason}
)}
元数据
缺陷编号 {bug.id}
指纹 {bug.fingerprint}
重试次数 {bug.retry_count}
上报时间 {new Date(bug.timestamp).toLocaleString()}
{repairHistory.length > 0 && (
修复历史 ({repairHistory.length} 次尝试)
{repairHistory.map(report => ( ))}
轮次 状态 测试结果 失败原因 时间 操作
第 {report.repair_round} 轮 {STATUS_LABELS[report.status] || report.status} {report.test_passed ? '通过' : '失败'} {report.failure_reason || '-'} {new Date(report.created_at).toLocaleString()} 查看
)}
); }