Files
digital-pilates/app/onboarding/index.tsx
richarjiang 807e185761 feat: 更新应用版本和主题设置
- 将应用版本更新至 1.0.3,修改相关配置文件
- 强制全局使用浅色主题,确保一致的用户体验
- 在训练计划功能中新增激活计划的 API 接口,支持用户激活训练计划
- 优化打卡功能,支持自动同步打卡记录至服务器
- 更新样式以适应新功能的展示和交互
2025-08-14 22:23:45 +08:00

234 lines
6.0 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { ThemedText } from '@/components/ThemedText';
import { ThemedView } from '@/components/ThemedView';
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('/onboarding/personal-info');
};
const handleSkip = async () => {
try {
await AsyncStorage.setItem('@onboarding_completed', 'true');
router.replace('/(tabs)');
} catch (error) {
console.error('保存引导状态失败:', error);
router.replace('/(tabs)');
}
};
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',
},
});