import React from 'react'; import { CheckCircle2, ChevronLeft, ChevronRight, Circle, Database, FileCheck2, Loader2, Megaphone, Sparkles, Target, Users, Workflow, Zap, } from 'lucide-react'; import { useTheme } from '../../contexts/ThemeContext'; import type { MainStepKey, StepStatus, SubStepKey } from './types'; interface SixStepProgressProps { mainStatus: Record; subStatus: Record; collapsed?: boolean; onToggleCollapse?: () => void; } interface StepItem { key: T; title: string; desc: string; icon: React.ComponentType<{ className?: string }>; color: { dark: string; light: string }; } const MAIN_STEPS: StepItem[] = [ { key: 'info', title: '信息准备', desc: '梳理输入素材与上下文', icon: Database, color: { dark: 'text-sky-300 bg-sky-500/15 border-sky-400/40', light: 'text-sky-600 bg-sky-50 border-sky-200' } }, { key: 'sixstep', title: '6 步法推演', desc: '依次完成四个阶段推演', icon: Workflow, color: { dark: 'text-violet-300 bg-violet-500/15 border-violet-400/40', light: 'text-violet-600 bg-violet-50 border-violet-200' } }, { key: 'final', title: '最终结果生成', desc: '汇总各阶段产出,输出结论', icon: FileCheck2, color: { dark: 'text-emerald-300 bg-emerald-500/15 border-emerald-400/40', light: 'text-emerald-600 bg-emerald-50 border-emerald-200' } }, ]; const SUB_STEPS: StepItem[] = [ { key: 'purpose', title: '目的生成', desc: '识别核心目的方向', icon: Target, color: { dark: 'text-violet-300 bg-violet-500/15 border-violet-400/40', light: 'text-violet-600 bg-orange-50 border-orange-200' } }, { key: 'actor', title: '行为体生成', desc: '匹配行为体角色', icon: Users, color: { dark: 'text-cyan-300 bg-cyan-500/15 border-cyan-400/40', light: 'text-red-600 bg-red-50 border-red-200' } }, { key: 'behavior', title: '预期行为与驱动因素', desc: '推演行为与动因', icon: Zap, color: { dark: 'text-emerald-300 bg-emerald-500/15 border-emerald-400/40', light: 'text-emerald-600 bg-emerald-50 border-emerald-200' } }, { key: 'narrative', title: '叙事生成', desc: '构建叙事框架', icon: Megaphone,color: { dark: 'text-amber-300 bg-amber-500/15 border-amber-400/40', light: 'text-amber-600 bg-amber-50 border-amber-200' } }, ]; function dotColor(status: StepStatus, isDark: boolean) { if (status === 'done') return isDark ? 'bg-emerald-400' : 'bg-emerald-500'; if (status === 'running') return isDark ? 'bg-cyan-400 sixstep-pulse' : 'bg-red-500 sixstep-pulse'; return isDark ? 'bg-slate-600' : 'bg-gray-300'; } function StatusIcon({ status, isDark }: { status: StepStatus; isDark: boolean }) { if (status === 'done') return ; if (status === 'running') return ; return ; } function cardBorder(status: StepStatus, isDark: boolean) { if (status === 'running') return isDark ? 'border-cyan-400/40 bg-cyan-500/5 shadow-[0_0_0_1px_rgba(34,211,238,0.15)]' : 'border-red-300 bg-red-50/60 shadow-sm'; return isDark ? 'border-slate-700/60 bg-slate-800/40' : 'border-gray-200 bg-white'; } function connectorColor(status: StepStatus, isDark: boolean) { return status === 'done' ? isDark ? 'bg-emerald-400/40' : 'bg-emerald-300' : isDark ? 'bg-slate-700/60' : 'bg-gray-200'; } // ── Collapsed view ──────────────────────────────────────────────────────────── const CollapsedView: React.FC<{ mainStatus: Record; subStatus: Record; isDark: boolean; onExpand: () => void; }> = ({ mainStatus, subStatus, isDark, onExpand }) => { const sixstepUnlocked = mainStatus.sixstep !== 'pending'; return (
{MAIN_STEPS.map((step) => { const status = mainStatus[step.key]; const Icon = step.icon; const clr = step.color[isDark ? 'dark' : 'light']; return (
{status === 'running' ? : }
{step.key === 'sixstep' && sixstepUnlocked && (
{SUB_STEPS.map((sub) => { const ss = subStatus[sub.key]; const SubIcon = sub.icon; const sc = sub.color[isDark ? 'dark' : 'light']; return (
{ss === 'running' ? : }
); })}
)}
); })}
); }; // ── Expanded view ───────────────────────────────────────────────────────────── const SixStepProgress: React.FC = ({ mainStatus, subStatus, collapsed = false, onToggleCollapse, }) => { const { theme } = useTheme(); const isDark = theme === 'dark'; const sixstepUnlocked = mainStatus.sixstep !== 'pending'; const sixstepRunning = mainStatus.sixstep === 'running'; if (collapsed) { return ( onToggleCollapse?.()} /> ); } return (
{/* Header */}
生成进度
实时跟踪推演阶段
{/* Steps */}
{MAIN_STEPS.map((step, idx) => { const status = mainStatus[step.key]; const Icon = step.icon; const clr = step.color[isDark ? 'dark' : 'light']; const showSubBlock = step.key === 'sixstep' && sixstepUnlocked; return (
{idx < MAIN_STEPS.length - 1 && (
)}
{status === 'running' ? : }
{step.title}
{status === 'done' ? '已完成' : status === 'running' ? '生成中' : '待开始'}
{step.desc}
{/* 6步法子阶段 */} {showSubBlock && (
6 步法 · 子阶段
{SUB_STEPS.map((sub, subIdx) => { const ss = subStatus[sub.key]; const SubIcon = sub.icon; const sc = sub.color[isDark ? 'dark' : 'light']; return (
{subIdx < SUB_STEPS.length - 1 && (
)}
{ss === 'running' ? : }
{sub.title}
{sub.desc}
); })}
{sixstepRunning && (
推演正在进行...
)}
)}
); })}
); }; export default SixStepProgress;