42 lines
1.2 KiB
TypeScript
42 lines
1.2 KiB
TypeScript
|
|
import { cn } from '@/lib/utils';
|
||
|
|
|
||
|
|
interface Props {
|
||
|
|
phase: string;
|
||
|
|
progress: number;
|
||
|
|
currentItem?: number;
|
||
|
|
totalItems?: number;
|
||
|
|
status?: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
export function PipelineProgress({ phase, progress, currentItem, totalItems, status }: Props) {
|
||
|
|
const phaseLabel: Record<string, string> = {
|
||
|
|
images: '生成图片',
|
||
|
|
upload: '上传素材',
|
||
|
|
videos: '生成视频',
|
||
|
|
tts: '配音',
|
||
|
|
assemble: '成片组装',
|
||
|
|
};
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div className="bg-zinc-900 border border-zinc-800 rounded-lg p-3 my-2">
|
||
|
|
<div className="flex items-center justify-between mb-1.5">
|
||
|
|
<span className="text-xs text-zinc-400">
|
||
|
|
{phaseLabel[phase] || phase}
|
||
|
|
{currentItem && totalItems ? ` (${currentItem}/${totalItems})` : ''}
|
||
|
|
</span>
|
||
|
|
<span className="text-xs text-zinc-500">{progress}%</span>
|
||
|
|
</div>
|
||
|
|
<div className="w-full h-1.5 bg-zinc-800 rounded-full overflow-hidden">
|
||
|
|
<div
|
||
|
|
className={cn(
|
||
|
|
'h-full rounded-full transition-all duration-500',
|
||
|
|
progress < 100 ? 'bg-blue-500' : 'bg-green-500'
|
||
|
|
)}
|
||
|
|
style={{ width: `${progress}%` }}
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
{status && <p className="text-xs text-zinc-500 mt-1">{status}</p>}
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|