import { TaskListItem } from '@/types/goals'; import MaterialIcons from '@expo/vector-icons/MaterialIcons'; import React, { useEffect, useRef, useState } from 'react'; import { Animated, Dimensions, Modal, StatusBar, StyleSheet, Text, TouchableOpacity, View, } from 'react-native'; interface GoalsPageGuideProps { visible: boolean; onComplete: () => void; tasks?: TaskListItem[]; // 添加任务数据,用于智能引导 } const { width: screenWidth, height: screenHeight } = Dimensions.get('window'); // 计算精确的高亮位置 const calculateHighlightPosition = (stepIndex: number, hasTasks: boolean) => { const baseTop = 120; // 状态栏 + 标题区域高度 const cardHeight = 180; // 任务进度卡片高度 const filterHeight = 60; // 筛选标签高度 const listHeight = 300; // 任务列表高度 switch (stepIndex) { case 0: // 欢迎标题 return { top: baseTop - 40, left: 20, right: 20, height: 60, borderRadius: 12, }; case 1: // 任务进度卡片 return { top: baseTop + 20, left: 20, right: 20, height: cardHeight, borderRadius: 16, }; case 2: // 目标管理按钮(有任务时) if (hasTasks) { return { top: baseTop + 40, right: 60, width: 40, height: 28, borderRadius: 14, }; } else { return { top: baseTop + 40, right: 20, width: 28, height: 28, borderRadius: 14, }; } case 3: // 创建新目标按钮(有任务时) if (hasTasks) { return { top: baseTop + 40, right: 20, width: 28, height: 28, borderRadius: 14, }; } else { return null; // 没有这一步 } case 4: // 任务筛选标签 return { top: baseTop + cardHeight + 40, left: 20, right: 20, height: filterHeight, borderRadius: 24, }; case 5: // 任务列表 return { top: baseTop + cardHeight + filterHeight + 60, left: 20, right: 20, height: listHeight, borderRadius: 24, }; default: return null; } }; export const GoalsPageGuide: React.FC = ({ visible, onComplete, tasks = [], }) => { const [currentStep, setCurrentStep] = useState(0); const fadeAnim = useRef(new Animated.Value(0)).current; const scaleAnim = useRef(new Animated.Value(0.8)).current; // 根据任务数据智能生成引导步骤 const generateSteps = () => { const hasTasks = tasks.length > 0; const hasCompletedTasks = tasks.some(task => task.status === 'completed'); const hasPendingTasks = tasks.some(task => task.status === 'pending'); const baseSteps = [ { title: '欢迎来到目标页面', description: '这里是您的目标管理中心,让我们一起来了解各个功能。', icon: 'flag', }, { title: '任务进度统计', description: '这里显示您当天的任务完成情况,包括待完成、已完成和已跳过的任务数量。', icon: 'analytics', }, ]; // 根据任务状态添加不同的引导内容 if (!hasTasks) { baseSteps.push({ title: '创建您的第一个目标', description: '点击加号按钮,创建您的第一个目标,系统会自动生成相应的任务。', icon: 'add', }); } else { baseSteps.push( { title: '目标管理', description: '点击右上角的目标按钮,可以查看和管理您的所有目标。', icon: 'flag', }, { title: '创建新目标', description: '点击加号按钮,可以快速创建新的目标。', icon: 'add', } ); } baseSteps.push({ title: '任务筛选', description: '使用这些标签可以筛选查看不同状态的任务。', icon: 'filter-list', }); // 根据任务状态调整任务列表的引导内容 if (!hasTasks) { baseSteps.push({ title: '任务列表', description: '创建目标后,您的任务将显示在这里。', icon: 'list', }); } else if (!hasPendingTasks && hasCompletedTasks) { baseSteps.push({ title: '任务列表', description: '您已完成所有任务!可以创建新目标或查看历史记录。', icon: 'check-circle', }); } else { baseSteps.push({ title: '任务列表', description: '这里显示您的所有任务,可以标记完成或跳过。', icon: 'list', }); } return baseSteps; }; const steps = generateSteps(); const hasTasks = tasks.length > 0; const currentHighlightPosition = calculateHighlightPosition(currentStep, hasTasks); useEffect(() => { if (visible) { Animated.parallel([ Animated.timing(fadeAnim, { toValue: 1, duration: 300, useNativeDriver: true, }), Animated.timing(scaleAnim, { toValue: 1, duration: 300, useNativeDriver: true, }), ]).start(); } else { Animated.parallel([ Animated.timing(fadeAnim, { toValue: 0, duration: 200, useNativeDriver: true, }), Animated.timing(scaleAnim, { toValue: 0.8, duration: 200, useNativeDriver: true, }), ]).start(); } }, [visible, fadeAnim, scaleAnim]); const handleNext = () => { if (currentStep < steps.length - 1) { setCurrentStep(currentStep + 1); } else { handleComplete(); } }; const handlePrevious = () => { if (currentStep > 0) { setCurrentStep(currentStep - 1); } }; const handleComplete = () => { Animated.parallel([ Animated.timing(fadeAnim, { toValue: 0, duration: 200, useNativeDriver: true, }), Animated.timing(scaleAnim, { toValue: 0.8, duration: 200, useNativeDriver: true, }), ]).start(() => { setCurrentStep(0); onComplete(); }); }; const handleSkip = () => { handleComplete(); }; if (!visible || !currentHighlightPosition) return null; const currentStepData = steps[currentStep]; return ( {/* 背景遮罩 */} {/* 高亮区域 */} {/* 引导内容 */} {/* 步骤指示器 */} {steps.map((_, index) => ( ))} {/* 图标 */} {/* 标题 */} {currentStepData.title} {/* 描述 */} {currentStepData.description} {/* 按钮区域 */} 跳过 {currentStep > 0 && ( 回顾 )} {currentStep === steps.length - 1 ? '完成' : '下一步'} ); }; const styles = StyleSheet.create({ overlay: { flex: 1, backgroundColor: 'rgba(0, 0, 0, 0.8)', justifyContent: 'center', alignItems: 'center', }, highlightArea: { position: 'absolute', justifyContent: 'center', alignItems: 'center', }, highlightBorder: { width: '100%', height: '100%', borderWidth: 2, borderColor: '#7A5AF8', backgroundColor: 'rgba(122, 90, 248, 0.08)', shadowColor: '#7A5AF8', shadowOffset: { width: 0, height: 0 }, shadowOpacity: 0.3, shadowRadius: 8, elevation: 4, }, guideContainer: { position: 'absolute', bottom: 120, left: 20, right: 20, backgroundColor: '#FFFFFF', borderRadius: 20, padding: 24, alignItems: 'center', shadowColor: '#000', shadowOffset: { width: 0, height: 4, }, shadowOpacity: 0.25, shadowRadius: 12, elevation: 8, }, stepIndicator: { flexDirection: 'row', marginBottom: 20, }, stepDot: { width: 8, height: 8, borderRadius: 4, backgroundColor: '#E5E7EB', marginHorizontal: 4, }, stepDotActive: { backgroundColor: '#7A5AF8', }, iconContainer: { width: 80, height: 80, borderRadius: 40, backgroundColor: '#F3F4F6', justifyContent: 'center', alignItems: 'center', marginBottom: 16, }, title: { fontSize: 20, fontWeight: '700', color: '#1F2937', textAlign: 'center', marginBottom: 12, }, description: { fontSize: 16, color: '#6B7280', textAlign: 'center', lineHeight: 24, marginBottom: 24, }, buttonContainer: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', width: '100%', }, navigationButtons: { flexDirection: 'row', gap: 12, }, skipButton: { paddingHorizontal: 20, paddingVertical: 12, borderRadius: 12, borderWidth: 1, borderColor: '#E5E7EB', }, skipButtonText: { fontSize: 16, fontWeight: '600', color: '#6B7280', }, previousButton: { paddingHorizontal: 20, paddingVertical: 12, borderRadius: 12, borderWidth: 1, borderColor: '#7A5AF8', backgroundColor: 'rgba(122, 90, 248, 0.1)', }, previousButtonText: { fontSize: 16, fontWeight: '600', color: '#7A5AF8', }, nextButton: { paddingHorizontal: 24, paddingVertical: 12, borderRadius: 12, backgroundColor: '#7A5AF8', }, nextButtonText: { fontSize: 16, fontWeight: '600', color: '#FFFFFF', }, });