- 将标签页中的“首页”改为“探索”,并更新相关逻辑 - 新增探索页面,展示推荐文章和训练计划 - 优化教练页面的导航,确保用户体验一致性 - 移除不再使用的代码,简化项目结构 - 更新路由常量,确保路径管理集中化
235 lines
6.0 KiB
TypeScript
235 lines
6.0 KiB
TypeScript
import { ThemedText } from '@/components/ThemedText';
|
||
import { ThemedView } from '@/components/ThemedView';
|
||
import { ROUTES } from '@/constants/Routes';
|
||
import { useColorScheme } from '@/hooks/useColorScheme';
|
||
import { useThemeColor } from '@/hooks/useThemeColor';
|
||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||
import { router } from 'expo-router';
|
||
import React from 'react';
|
||
import {
|
||
Dimensions,
|
||
StatusBar,
|
||
StyleSheet,
|
||
Text,
|
||
TouchableOpacity,
|
||
View
|
||
} from 'react-native';
|
||
|
||
const { width, height } = Dimensions.get('window');
|
||
|
||
export default function WelcomeScreen() {
|
||
const colorScheme = useColorScheme();
|
||
const backgroundColor = useThemeColor({}, 'background');
|
||
const primaryColor = useThemeColor({}, 'primary');
|
||
const textColor = useThemeColor({}, 'text');
|
||
|
||
const handleGetStarted = () => {
|
||
router.push(ROUTES.ONBOARDING_PERSONAL_INFO);
|
||
};
|
||
|
||
const handleSkip = async () => {
|
||
try {
|
||
await AsyncStorage.setItem('@onboarding_completed', 'true');
|
||
router.replace(ROUTES.TAB_COACH);
|
||
} catch (error) {
|
||
console.error('保存引导状态失败:', error);
|
||
router.replace(ROUTES.TAB_COACH);
|
||
}
|
||
};
|
||
|
||
return (
|
||
<ThemedView style={[styles.container, { backgroundColor }]}>
|
||
<StatusBar
|
||
barStyle={'dark-content'}
|
||
backgroundColor={backgroundColor}
|
||
/>
|
||
|
||
{/* 跳过按钮 */}
|
||
<TouchableOpacity style={styles.skipButton} onPress={handleSkip}>
|
||
<ThemedText style={[styles.skipText, { color: textColor }]}>
|
||
跳过
|
||
</ThemedText>
|
||
</TouchableOpacity>
|
||
|
||
{/* 主要内容区域 */}
|
||
<View style={styles.contentContainer}>
|
||
{/* Logo 或插图区域 */}
|
||
<View style={styles.imageContainer}>
|
||
<View style={[styles.logoPlaceholder, { backgroundColor: primaryColor }]}>
|
||
<Text style={styles.logoText}>🧘♀️</Text>
|
||
</View>
|
||
</View>
|
||
|
||
{/* 标题和描述 */}
|
||
<View style={styles.textContainer}>
|
||
<ThemedText type="title" style={styles.title}>
|
||
欢迎来到数字普拉提
|
||
</ThemedText>
|
||
<ThemedText style={[styles.subtitle, { color: textColor + '90' }]}>
|
||
让我们一起开始您的健康之旅{'\n'}
|
||
个性化的普拉提体验正等着您
|
||
</ThemedText>
|
||
</View>
|
||
|
||
{/* 特色功能点 */}
|
||
<View style={styles.featuresContainer}>
|
||
{[
|
||
{ icon: '📊', title: '个性化训练', desc: '根据您的身体状况定制训练计划' },
|
||
{ icon: '🤖', title: 'AI 姿态分析', desc: '实时纠正您的动作姿态' },
|
||
{ icon: '📈', title: '进度追踪', desc: '记录您的每一次进步' },
|
||
].map((feature, index) => (
|
||
<View key={index} style={styles.featureItem}>
|
||
<Text style={styles.featureIcon}>{feature.icon}</Text>
|
||
<View style={styles.featureTextContainer}>
|
||
<ThemedText style={[styles.featureTitle, { color: textColor }]}>
|
||
{feature.title}
|
||
</ThemedText>
|
||
<ThemedText style={[styles.featureDesc, { color: textColor + '70' }]}>
|
||
{feature.desc}
|
||
</ThemedText>
|
||
</View>
|
||
</View>
|
||
))}
|
||
</View>
|
||
</View>
|
||
|
||
{/* 底部按钮 */}
|
||
<View style={styles.buttonContainer}>
|
||
<TouchableOpacity
|
||
style={[styles.getStartedButton, { backgroundColor: primaryColor }]}
|
||
onPress={handleGetStarted}
|
||
activeOpacity={0.8}
|
||
>
|
||
<Text style={styles.getStartedButtonText}>开始体验</Text>
|
||
</TouchableOpacity>
|
||
|
||
<TouchableOpacity style={styles.laterButton} onPress={handleSkip}>
|
||
<ThemedText style={[styles.laterButtonText, { color: textColor + '70' }]}>
|
||
稍后再说
|
||
</ThemedText>
|
||
</TouchableOpacity>
|
||
</View>
|
||
</ThemedView>
|
||
);
|
||
}
|
||
|
||
const styles = StyleSheet.create({
|
||
container: {
|
||
flex: 1,
|
||
paddingTop: StatusBar.currentHeight || 44,
|
||
},
|
||
skipButton: {
|
||
position: 'absolute',
|
||
top: StatusBar.currentHeight ? StatusBar.currentHeight + 16 : 60,
|
||
right: 20,
|
||
zIndex: 10,
|
||
padding: 8,
|
||
},
|
||
skipText: {
|
||
fontSize: 16,
|
||
fontWeight: '500',
|
||
},
|
||
contentContainer: {
|
||
flex: 1,
|
||
paddingHorizontal: 24,
|
||
justifyContent: 'center',
|
||
},
|
||
imageContainer: {
|
||
alignItems: 'center',
|
||
marginBottom: 40,
|
||
},
|
||
logoPlaceholder: {
|
||
width: 120,
|
||
height: 120,
|
||
borderRadius: 60,
|
||
justifyContent: 'center',
|
||
alignItems: 'center',
|
||
shadowColor: '#000',
|
||
shadowOffset: {
|
||
width: 0,
|
||
height: 4,
|
||
},
|
||
shadowOpacity: 0.1,
|
||
shadowRadius: 8,
|
||
elevation: 8,
|
||
},
|
||
logoText: {
|
||
fontSize: 48,
|
||
},
|
||
textContainer: {
|
||
alignItems: 'center',
|
||
marginBottom: 48,
|
||
},
|
||
title: {
|
||
textAlign: 'center',
|
||
marginBottom: 16,
|
||
fontWeight: '700',
|
||
},
|
||
subtitle: {
|
||
fontSize: 16,
|
||
textAlign: 'center',
|
||
lineHeight: 24,
|
||
paddingHorizontal: 12,
|
||
},
|
||
featuresContainer: {
|
||
marginBottom: 40,
|
||
},
|
||
featureItem: {
|
||
flexDirection: 'row',
|
||
alignItems: 'center',
|
||
marginBottom: 24,
|
||
paddingHorizontal: 8,
|
||
},
|
||
featureIcon: {
|
||
fontSize: 32,
|
||
marginRight: 16,
|
||
width: 40,
|
||
textAlign: 'center',
|
||
},
|
||
featureTextContainer: {
|
||
flex: 1,
|
||
},
|
||
featureTitle: {
|
||
fontSize: 18,
|
||
fontWeight: '600',
|
||
marginBottom: 4,
|
||
},
|
||
featureDesc: {
|
||
fontSize: 14,
|
||
lineHeight: 20,
|
||
},
|
||
buttonContainer: {
|
||
paddingHorizontal: 24,
|
||
paddingBottom: 48,
|
||
},
|
||
getStartedButton: {
|
||
height: 56,
|
||
borderRadius: 16,
|
||
justifyContent: 'center',
|
||
alignItems: 'center',
|
||
marginBottom: 16,
|
||
shadowColor: '#000',
|
||
shadowOffset: {
|
||
width: 0,
|
||
height: 2,
|
||
},
|
||
shadowOpacity: 0.1,
|
||
shadowRadius: 4,
|
||
elevation: 4,
|
||
},
|
||
getStartedButtonText: {
|
||
color: '#192126',
|
||
fontSize: 18,
|
||
fontWeight: '600',
|
||
},
|
||
laterButton: {
|
||
height: 48,
|
||
justifyContent: 'center',
|
||
alignItems: 'center',
|
||
},
|
||
laterButtonText: {
|
||
fontSize: 16,
|
||
fontWeight: '500',
|
||
},
|
||
});
|