| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465 |
- import type { TechnicalRetryDetail } from "@/lib/flow-ledger/types";
- export function TechnicalRetryDetails({ detail, compact = false }: { detail?: TechnicalRetryDetail | null; compact?: boolean }) {
- if (!detail) return null;
- const rows = [
- ["接口/阶段", detail.stageLabel],
- ["简短原因", detail.briefReason],
- ["错误类型", [detail.failureLabel, detail.failureType].filter(Boolean).join(" / ")],
- ["异常", detail.exceptionType || "无"],
- ["HTTP", detail.httpStatusCode ? String(detail.httpStatusCode) : "无"],
- ["原始错误", detail.errorMessage || "无"],
- ["视频源", detail.videoSource || "未进入视频处理"],
- ["下载", formatSeconds(detail.timings.download_seconds)],
- ["ffmpeg", formatSeconds(detail.timings.ffmpeg_seconds)],
- ["Gemini", formatSeconds(detail.timings.gemini_seconds)],
- ["原视频", formatMb(detail.sizes.downloaded_mb)],
- ["压缩后", formatMb(detail.sizes.compressed_mb)],
- ["OSS", ossText(detail)]
- ].filter(([, value]) => value && value !== "无");
- return (
- <details className={`technical-detail ${compact ? "compact" : ""}`}>
- <summary>技术详情</summary>
- <div className="technical-detail-body">
- {rows.map(([label, value]) => (
- <div className="technical-detail-row" key={label}>
- <span>{label}</span>
- <b>{value}</b>
- </div>
- ))}
- {detail.attempts.length ? (
- <div className="technical-attempts">
- <span>Gemini attempts</span>
- {detail.attempts.map((attempt, index) => (
- <div className="technical-attempt" key={`${attempt.attempt || index}-${index}`}>
- #{attempt.attempt || index + 1} · {attempt.status || "failed"} · {formatSeconds(attempt.durationSeconds)}
- {attempt.failureType ? ` · ${attempt.failureType}` : ""}
- {attempt.exceptionType ? ` · ${attempt.exceptionType}` : ""}
- {attempt.httpStatusCode ? ` · HTTP ${attempt.httpStatusCode}` : ""}
- </div>
- ))}
- </div>
- ) : null}
- </div>
- </details>
- );
- }
- function formatSeconds(value?: number | null): string {
- if (value === null || value === undefined || Number.isNaN(value)) return "无";
- return `${value}s`;
- }
- function formatMb(value?: number | null): string {
- if (value === null || value === undefined || Number.isNaN(value)) return "无";
- return `${value}MB`;
- }
- function ossText(detail: TechnicalRetryDetail): string {
- const oss = detail.oss || {};
- const status = typeof oss.status === "string" ? oss.status : "";
- const error = typeof oss.last_error === "string" ? oss.last_error : "";
- const duration = typeof oss.duration_seconds === "number" ? ` · ${oss.duration_seconds}s` : "";
- return [status, error].filter(Boolean).join(" / ") + duration;
- }
|