feat(ui): 统一应用主题色为天空蓝并优化渐变背景

将应用主色调从 '#BBF246' 更改为 '#87CEEB'(天空蓝),并更新所有相关组件和页面中的颜色引用。同时为多个页面添加统一的渐变背景,提升视觉效果和用户体验。新增压力分析模态框组件,并优化压力计组件的交互与显示逻辑。更新应用图标和启动图资源。
This commit is contained in:
richarjiang
2025-08-20 09:38:25 +08:00
parent 37f8c3c78d
commit d76ba48424
35 changed files with 519 additions and 184 deletions

View File

@@ -0,0 +1,267 @@
import { Colors } from '@/constants/Colors';
import { useColorScheme } from '@/hooks/useColorScheme';
import { LinearGradient } from 'expo-linear-gradient';
import React from 'react';
import {
Modal,
ScrollView,
StyleSheet,
Text,
TouchableOpacity,
View
} from 'react-native';
interface StressAnalysisModalProps {
visible: boolean;
onClose: () => void;
hrvValue: number;
updateTime: Date;
}
export function StressAnalysisModal({ visible, onClose, hrvValue, updateTime }: StressAnalysisModalProps) {
const colorScheme = useColorScheme();
const colors = Colors[colorScheme ?? 'light'];
// 模拟30天HRV数据
const hrvData = {
goodEvents: { percentage: 26, count: 53, range: '>80毫秒' },
energetic: { percentage: 47, count: 97, range: '43-80毫秒' },
stressed: { percentage: 27, count: 56, range: '<43毫秒' },
};
return (
<Modal
visible={visible}
animationType="slide"
presentationStyle="pageSheet"
onRequestClose={onClose}
>
<LinearGradient
colors={[colors.backgroundGradientStart, colors.backgroundGradientEnd]}
style={styles.modalContainer}
start={{ x: 0, y: 0 }}
end={{ x: 0, y: 1 }}
>
<ScrollView style={styles.content} showsVerticalScrollIndicator={false}>
{/* 标题 */}
<Text style={styles.title}></Text>
{/* 最近30天HRV情况 */}
<Text style={styles.sectionTitle}>30HRV情况</Text>
{/* 彩色横条图 */}
<View style={styles.chartContainer}>
<View style={styles.colorBar}>
<LinearGradient
colors={['#10B981', '#3B82F6', '#F59E0B']}
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 0 }}
style={styles.gradientBar}
/>
</View>
<View style={styles.legend}>
<View style={styles.legendItem}>
<View style={[styles.legendDot, { backgroundColor: '#10B981' }]} />
<Text style={styles.legendText}></Text>
</View>
<View style={styles.legendItem}>
<View style={[styles.legendDot, { backgroundColor: '#3B82F6' }]} />
<Text style={styles.legendText}></Text>
</View>
<View style={styles.legendItem}>
<View style={[styles.legendDot, { backgroundColor: '#F59E0B' }]} />
<Text style={styles.legendText}></Text>
</View>
</View>
</View>
{/* 数据统计卡片 */}
<View style={styles.statsCard}>
{/* 好事发生 & 活力满满 */}
<View style={styles.statsRow}>
<View style={styles.statItem}>
<Text style={[styles.statTitle, { color: '#10B981' }]}></Text>
<Text style={styles.statPercentage}>{hrvData.goodEvents.percentage}%</Text>
<View style={styles.statDetails}>
<Text style={styles.statRange}> {hrvData.goodEvents.range}</Text>
</View>
<Text style={styles.statCount}>{hrvData.goodEvents.count}</Text>
</View>
<View style={styles.statItem}>
<Text style={[styles.statTitle, { color: '#3B82F6' }]}></Text>
<Text style={styles.statPercentage}>{hrvData.energetic.percentage}%</Text>
<View style={styles.statDetails}>
<Text style={styles.statRange}> {hrvData.energetic.range}</Text>
</View>
<Text style={styles.statCount}>{hrvData.energetic.count}</Text>
</View>
</View>
{/* 鸭梨山大 */}
<View style={styles.statItem}>
<Text style={[styles.statTitle, { color: '#F59E0B' }]}></Text>
<Text style={styles.statPercentage}>{hrvData.stressed.percentage}%</Text>
<View style={styles.statDetails}>
<Text style={styles.statRange}> {hrvData.stressed.range}</Text>
</View>
<Text style={styles.statCount}>{hrvData.stressed.count}</Text>
</View>
</View>
</ScrollView>
{/* 底部继续按钮 */}
<View style={styles.bottomContainer}>
<TouchableOpacity style={styles.continueButton} onPress={onClose}>
<View style={styles.buttonBackground}>
<Text style={styles.buttonText}></Text>
</View>
</TouchableOpacity>
<View style={styles.homeIndicator} />
</View>
</LinearGradient>
</Modal>
);
}
const styles = StyleSheet.create({
modalContainer: {
flex: 1,
},
content: {
flex: 1,
paddingHorizontal: 20,
},
title: {
fontSize: 24,
fontWeight: '800',
color: '#111827',
textAlign: 'center',
marginTop: 20,
marginBottom: 32,
},
sectionTitle: {
fontSize: 22,
fontWeight: '800',
color: '#111827',
marginBottom: 20,
},
chartContainer: {
marginBottom: 32,
},
colorBar: {
height: 16,
borderRadius: 8,
overflow: 'hidden',
marginBottom: 16,
},
gradientBar: {
flex: 1,
},
legend: {
flexDirection: 'row',
justifyContent: 'space-around',
},
legendItem: {
flexDirection: 'row',
alignItems: 'center',
},
legendDot: {
width: 12,
height: 12,
borderRadius: 6,
marginRight: 6,
},
legendText: {
fontSize: 14,
fontWeight: '600',
color: '#374151',
},
statsCard: {
backgroundColor: '#FFFFFF',
borderRadius: 16,
padding: 20,
marginBottom: 32,
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.05,
shadowRadius: 8,
elevation: 2,
},
statsRow: {
flexDirection: 'row',
gap: 20,
marginBottom: 24,
},
statItem: {
flex: 1,
},
statTitle: {
fontSize: 16,
fontWeight: '700',
marginBottom: 8,
},
statPercentage: {
fontSize: 36,
fontWeight: '800',
color: '#111827',
marginBottom: 4,
},
statDetails: {
marginBottom: 4,
},
statRange: {
fontSize: 14,
fontWeight: '600',
color: '#DC2626',
backgroundColor: '#FEE2E2',
paddingHorizontal: 8,
paddingVertical: 3,
borderRadius: 10,
alignSelf: 'flex-start',
},
statCount: {
fontSize: 16,
fontWeight: '600',
color: '#6B7280',
},
bottomContainer: {
paddingHorizontal: 20,
paddingBottom: 34,
},
continueButton: {
borderRadius: 25,
overflow: 'hidden',
marginBottom: 8,
},
buttonGradient: {
paddingVertical: 18,
alignItems: 'center',
justifyContent: 'center',
},
buttonBackground: {
backgroundColor: Colors.light.accentGreen, // 应用主色调
paddingVertical: 18,
alignItems: 'center',
justifyContent: 'center',
},
buttonText: {
fontSize: 18,
fontWeight: '700',
color: '#192126', // 主色调上的文字颜色
},
homeIndicator: {
width: 134,
height: 5,
backgroundColor: '#000',
borderRadius: 3,
alignSelf: 'center',
},
});