diff --git a/apps/ai-game-creator-shell/src/components/error-report/ErrorReportDialog.tsx b/apps/ai-game-creator-shell/src/components/error-report/ErrorReportDialog.tsx index d22ea9902..216f04b61 100644 --- a/apps/ai-game-creator-shell/src/components/error-report/ErrorReportDialog.tsx +++ b/apps/ai-game-creator-shell/src/components/error-report/ErrorReportDialog.tsx @@ -4,6 +4,7 @@ import { ackClientErrorEventsWithRetry, type ClientErrorEvent, type DiagnosticLogFile, + getPendingClientErrorEvents, getStableErrorReportSubmissionId, readApplicationDiagnosticLogs, submitErrorReportBatch, @@ -12,10 +13,12 @@ import { ThemedModal } from '../modal/ThemedModal'; type ErrorReportDialogProps = { open: boolean; - events: ClientErrorEvent[]; onClose: () => void; + fallbackEvents?: ClientErrorEvent[]; }; +const emptyFallbackEvents: ClientErrorEvent[] = []; + function diagnosticLogLabel( logsReady: boolean, logsError: boolean, @@ -28,9 +31,12 @@ function diagnosticLogLabel( export function ErrorReportDialog({ open, - events, onClose, + fallbackEvents = emptyFallbackEvents, }: ErrorReportDialogProps) { + const [events, setEvents] = useState([]); + const [eventsReady, setEventsReady] = useState(false); + const [eventsError, setEventsError] = useState(false); const [selectedFingerprints, setSelectedFingerprints] = useState>( new Set(), ); @@ -45,29 +51,59 @@ export function ErrorReportDialog({ useEffect(() => { if (!open) return; - setSelectedFingerprints( - new Set(events.slice(0, 1).map((event) => event.fingerprint)), - ); + let disposed = false; + setEvents([]); + setEventsReady(false); + setEventsError(false); + setSelectedFingerprints(new Set()); setStatus(''); setLogsReady(false); setLogsError(false); + void getPendingClientErrorEvents() + .then((nextEvents) => { + if (disposed) return; + setEvents(nextEvents); + setSelectedFingerprints( + new Set(nextEvents.map((event) => event.fingerprint)), + ); + setEventsReady(true); + }) + .catch(() => { + if (disposed) return; + if (fallbackEvents.length) { + setEvents(fallbackEvents); + setSelectedFingerprints( + new Set(fallbackEvents.map((event) => event.fingerprint)), + ); + setEventsReady(true); + setStatus('最新错误读取失败,已使用打开通知时的快照'); + return; + } + setEventsError(true); + setEventsReady(true); + }); void readApplicationDiagnosticLogs() .then((nextLogs) => { + if (disposed) return; setLogs(nextLogs); setLogsReady(true); }) .catch(() => { + if (disposed) return; setLogs([]); setLogsError(true); setLogsReady(true); }); - }, [events, open]); + return () => { + disposed = true; + }; + }, [fallbackEvents, open]); const submit = useCallback(async () => { const selectedEvents = events.filter((event) => selectedFingerprints.has(event.fingerprint), ); - if (!selectedEvents.length || busy || !logsReady) return; + if (!selectedEvents.length || busy || !eventsReady || !logsReady) return; if (includeLogs && logsError) return; setBusy(true); setStatus('正在提交…'); @@ -92,6 +128,7 @@ export function ErrorReportDialog({ }, [ busy, description, + eventsReady, events, includeLogs, logs, @@ -124,7 +161,11 @@ export function ErrorReportDialog({
错误事件({events.length}) - {events.length ? ( + {!eventsReady &&

正在读取当前错误…

} + {eventsReady && eventsError && ( +

错误事件暂不可用,请关闭后重试。

+ )} + {eventsReady && !eventsError && events.length > 0 && (
    {events.map((event) => (
  • ))}
- ) : ( + )} + {eventsReady && !eventsError && !events.length && (

当前没有待报告的错误。

)}
@@ -191,11 +233,12 @@ export function ErrorReportDialog({ 取消