import { View, StyleSheet, Animated, TouchableOpacity, type ColorValue } from 'react-native'; import { ThemedView } from '@/components/themed-view'; import { ThemedText } from '@/components/themed-text'; import { LinearGradient } from 'expo-linear-gradient'; import { RunProgress } from '@/lib/types/template-run'; import { useEffect, useRef } from 'react'; interface RunProgressViewProps { progress: RunProgress; onCancel?: () => void; } export function RunProgressView({ progress, onCancel }: RunProgressViewProps) { const animatedWidth = useRef(new Animated.Value(0)).current; const pulseAnimation = useRef(new Animated.Value(1)).current; // 进度条动画 useEffect(() => { Animated.timing(animatedWidth, { toValue: progress.progress, duration: 500, useNativeDriver: false, }).start(); }, [progress.progress, animatedWidth]); // 脉冲动画 useEffect(() => { if (progress.status === 'running') { const pulseLoop = Animated.loop( Animated.sequence([ Animated.timing(pulseAnimation, { toValue: 1.1, duration: 1000, useNativeDriver: true, }), Animated.timing(pulseAnimation, { toValue: 1, duration: 1000, useNativeDriver: true, }), ]) ); pulseLoop.start(); return () => pulseLoop.stop(); } else { pulseAnimation.setValue(1); } }, [progress.status, pulseAnimation]); const getStatusColor = (): readonly [ColorValue, ColorValue] => { switch (progress.status) { case 'pending': return ['#FFA500', '#FF8C00'] as const; // 橙色 case 'running': return ['#4ECDC4', '#44A3A0'] as const; // 青色 case 'completed': return ['#52B788', '#40916C'] as const; // 绿色 case 'failed': return ['#FF6B6B', '#FF5252'] as const; // 红色 default: return ['#999999', '#666666'] as const; } }; const getStatusText = () => { switch (progress.status) { case 'pending': return '准备中...'; case 'running': return '执行中...'; case 'completed': return '已完成'; case 'failed': return '执行失败'; default: return '未知状态'; } }; const getStatusIcon = () => { switch (progress.status) { case 'pending': return '⏳'; case 'running': return '🔄'; case 'completed': return '✅'; case 'failed': return '❌'; default: return '❓'; } }; const colors = getStatusColor(); return ( {/* 状态头部 */} {getStatusIcon()} {getStatusText()} {progress.message} {/* 进度条 */} {Math.round(progress.progress)}% {/* 详细信息 */} 状态: {getStatusText()} {progress.result?.creditsCost && ( 消耗积分: {progress.result.creditsCost} )} {progress.result?.type && ( 输出类型: {progress.result.type === 'IMAGE' ? '图片' : progress.result.type === 'VIDEO' ? '视频' : progress.result.type === 'TEXT' ? '文本' : '未知'} )} {/* 操作按钮 */} {onCancel && (progress.status === 'pending' || progress.status === 'running') && ( 取消任务 )} ); } const styles = StyleSheet.create({ container: { flex: 1, padding: 20, }, header: { flexDirection: 'row', alignItems: 'center', marginBottom: 24, }, statusIcon: { width: 48, height: 48, borderRadius: 24, backgroundColor: 'rgba(78, 205, 196, 0.1)', justifyContent: 'center', alignItems: 'center', marginRight: 16, }, iconText: { fontSize: 24, }, statusInfo: { flex: 1, }, statusText: { fontSize: 18, fontWeight: '600', marginBottom: 4, }, messageText: { fontSize: 14, opacity: 0.7, }, progressContainer: { marginBottom: 24, }, progressBackground: { height: 8, backgroundColor: 'rgba(0, 0, 0, 0.1)', borderRadius: 4, overflow: 'hidden', marginBottom: 8, }, progressFill: { height: '100%', borderRadius: 4, overflow: 'hidden', }, progressGradient: { flex: 1, }, progressText: { fontSize: 14, fontWeight: '600', textAlign: 'center', }, details: { backgroundColor: 'rgba(0, 0, 0, 0.05)', borderRadius: 12, padding: 16, marginBottom: 20, }, detailText: { fontSize: 14, marginBottom: 8, }, detailValue: { fontWeight: '600', }, actions: { alignItems: 'center', }, cancelButton: { backgroundColor: 'rgba(255, 59, 48, 0.1)', borderRadius: 8, paddingVertical: 12, paddingHorizontal: 24, borderWidth: 1, borderColor: 'rgba(255, 59, 48, 0.3)', }, cancelButtonText: { fontSize: 16, fontWeight: '600', color: '#FF3B30', }, });