import { memo } from 'react' import type { Job } from '@/types/job' import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from '@/components/ui/dialog' import { Badge } from '@/components/ui/badge' import { Separator } from '@/components/ui/separator' import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from '@/components/ui/collapsible' import { ScrollArea } from '@/components/ui/scroll-area' import { AudioPlayer } from '@/components/AudioPlayer' import { ChevronDown, AlertCircle } from 'lucide-react' import { jobApi } from '@/lib/api' interface JobDetailDialogProps { job: Job | null open: boolean onOpenChange: (open: boolean) => void } const jobTypeBadgeVariant = { custom_voice: 'default' as const, voice_design: 'secondary' as const, voice_clone: 'outline' as const, } const jobTypeLabel = { custom_voice: '自定义音色', voice_design: '音色设计', voice_clone: '声音克隆', } const formatTimestamp = (timestamp: string) => { return new Date(timestamp).toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', }) } const getLanguageDisplay = (lang: string | undefined) => { if (!lang || lang === 'Auto') return '自动检测' return lang } const formatBooleanDisplay = (value: boolean | undefined) => { return value ? '是' : '否' } const JobDetailDialog = memo(({ job, open, onOpenChange }: JobDetailDialogProps) => { if (!job) return null const canPlay = job.status === 'completed' const audioUrl = canPlay ? jobApi.getAudioUrl(job.id, job.audio_url) : '' return (
{jobTypeLabel[job.type]} #{job.id} {formatTimestamp(job.created_at)}
查看任务的详细参数和生成结果

基本信息

{job.type === 'custom_voice' && job.parameters?.speaker && (
发音人: {job.parameters.speaker}
)}
语言: {getLanguageDisplay(job.parameters?.language)}
{job.type === 'voice_clone' && ( <>
快速模式: {formatBooleanDisplay(job.parameters?.x_vector_only_mode)}
使用缓存: {formatBooleanDisplay(job.parameters?.use_cache)}
)}

合成文本

{job.parameters?.text || 未设置}
{job.type === 'voice_design' && job.parameters?.instruct && ( <>

音色描述

{job.parameters.instruct}
)} {job.type === 'custom_voice' && job.parameters?.instruct && ( <>

情绪指导

{job.parameters.instruct}
)} {job.type === 'voice_clone' && ( <>

参考文本

{job.parameters?.ref_text || 未提供}
)} 高级参数
{job.parameters?.max_new_tokens !== undefined && (
最大生成长度: {job.parameters.max_new_tokens}
)} {job.parameters?.temperature !== undefined && (
温度: {job.parameters.temperature}
)} {job.parameters?.top_k !== undefined && (
Top K: {job.parameters.top_k}
)} {job.parameters?.top_p !== undefined && (
Top P: {job.parameters.top_p}
)} {job.parameters?.repetition_penalty !== undefined && (
重复惩罚: {job.parameters.repetition_penalty}
)}
{job.status === 'failed' && job.error_message && ( <>

错误信息

{job.error_message}

)} {canPlay && ( <>

音频播放

)}
) }) JobDetailDialog.displayName = 'JobDetailDialog' export { JobDetailDialog }