feat: 新增 StressMeter 组件,移除原 HRV 压力监测代码

This commit is contained in:
richarjiang
2025-08-19 19:22:38 +08:00
parent 35cd320ea7
commit 63b1c52909
2 changed files with 172 additions and 142 deletions

View File

@@ -3,6 +3,7 @@ import { BMICard } from '@/components/BMICard';
import { CircularRing } from '@/components/CircularRing';
import { NutritionRadarCard } from '@/components/NutritionRadarCard';
import { ProgressBar } from '@/components/ProgressBar';
import { StressMeter } from '@/components/StressMeter';
import { WeightHistoryCard } from '@/components/WeightHistoryCard';
import { Colors } from '@/constants/Colors';
import { getTabBarBottomPadding } from '@/constants/TabBar';
@@ -210,53 +211,7 @@ export default function ExploreScreen() {
<WeightHistoryCard />
{/* HRV压力监测卡片 */}
<View style={[styles.hrvCard, { backgroundColor: '#F0F7FF' }]}>
<View style={styles.hrvHeader}>
<View style={styles.hrvIconContainer}>
<Ionicons name="heart" size={24} color="#3B82F6" />
</View>
<Text style={styles.hrvTitle}></Text>
</View>
<View style={styles.hrvContent}>
<View style={styles.hrvValueContainer}>
<Text style={styles.hrvValue}>{hrvValue}</Text>
<Text style={styles.hrvUnit}></Text>
</View>
<View style={[styles.hrvStatus,
hrvStatus === '放松' ? { backgroundColor: '#DCFCE7' } :
hrvStatus === '正常' ? { backgroundColor: '#FEF3C7' } :
{ backgroundColor: '#FEE2E2' }
]}>
<Text style={[styles.hrvStatusText,
hrvStatus === '放松' ? { color: '#166534' } :
hrvStatus === '正常' ? { color: '#92400E' } :
{ color: '#991B1B' }
]}>{hrvStatus}</Text>
<Text style={styles.hrvEmoji}>
{hrvStatus === '放松' ? '😌' :
hrvStatus === '正常' ? '😊' :
'😰'}
</Text>
</View>
</View>
<View style={styles.hrvSliderContainer}>
<View style={styles.hrvSliderTrack}>
<View style={[styles.hrvSliderProgress, {
width: `${Math.min(100, Math.max(0, (hrvValue / 150) * 100))}%`,
backgroundColor: hrvStatus === '放松' ? '#10B981' :
hrvStatus === '正常' ? '#F59E0B' : '#EF4444'
}]} />
</View>
<View style={styles.hrvLabels}>
<Text style={styles.hrvLabel}></Text>
<Text style={styles.hrvLabel}></Text>
<Text style={styles.hrvLabel}></Text>
</View>
</View>
</View>
<StressMeter value={hrvValue} status={hrvStatus} />
{/* 查看更多 */}
<View style={styles.viewMoreContainer}>
@@ -641,99 +596,4 @@ const styles = StyleSheet.create({
color: '#192126',
marginLeft: 4,
},
hrvCard: {
backgroundColor: '#F0F7FF',
borderRadius: 22,
padding: 20,
marginBottom: 16,
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.1,
shadowRadius: 8,
elevation: 5,
},
hrvHeader: {
flexDirection: 'row',
alignItems: 'center',
marginBottom: 16,
},
hrvIconContainer: {
width: 40,
height: 40,
borderRadius: 12,
backgroundColor: '#DBEAFE',
alignItems: 'center',
justifyContent: 'center',
marginRight: 12,
},
hrvTitle: {
fontSize: 18,
fontWeight: '800',
color: '#1E293B',
},
hrvContent: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
marginBottom: 20,
},
hrvValueContainer: {
flexDirection: 'row',
alignItems: 'baseline',
},
hrvValue: {
fontSize: 36,
fontWeight: '800',
color: '#1E293B',
marginRight: 4,
},
hrvUnit: {
fontSize: 16,
fontWeight: '600',
color: '#64748B',
},
hrvStatus: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#DCFCE7',
paddingHorizontal: 12,
paddingVertical: 6,
borderRadius: 20,
},
hrvStatusText: {
fontSize: 14,
fontWeight: '600',
color: '#166534',
marginRight: 4,
},
hrvEmoji: {
fontSize: 16,
},
hrvSliderContainer: {
marginTop: 8,
},
hrvSliderTrack: {
height: 8,
backgroundColor: '#E2E8F0',
borderRadius: 4,
marginBottom: 8,
overflow: 'hidden',
},
hrvSliderProgress: {
height: '100%',
backgroundColor: '#3B82F6',
borderRadius: 4,
},
hrvLabels: {
flexDirection: 'row',
justifyContent: 'space-between',
},
hrvLabel: {
fontSize: 12,
fontWeight: '500',
color: '#64748B',
},
});

170
components/StressMeter.tsx Normal file
View File

@@ -0,0 +1,170 @@
import { Ionicons } from '@expo/vector-icons';
import { LinearGradient } from 'expo-linear-gradient';
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
interface StressMeterProps {
value: number;
status: '放松' | '正常' | '紧张';
}
export function StressMeter({ value, status }: StressMeterProps) {
// 计算进度条位置0-100%
const progressPercentage = Math.min(100, Math.max(0, (value / 150) * 100));
// 根据状态获取颜色
const getStatusColor = () => {
switch (status) {
case '放松': return '#10B981';
case '正常': return '#F59E0B';
case '紧张': return '#EF4444';
default: return '#F59E0B';
}
};
// 根据状态获取表情
const getStatusEmoji = () => {
switch (status) {
case '放松': return '😌';
case '正常': return '😊';
case '紧张': return '😰';
default: return '😊';
}
};
return (
<View style={styles.container}>
{/* 头部区域 */}
<View style={styles.header}>
<View style={styles.leftSection}>
<View style={styles.iconContainer}>
<Ionicons name="heart" size={20} color="#3B82F6" />
</View>
<Text style={styles.title}></Text>
</View>
<Text style={styles.emoji}>{getStatusEmoji()}</Text>
</View>
{/* 数值显示区域 */}
<View style={styles.valueSection}>
<Text style={styles.value}>{value}</Text>
<Text style={styles.unit}></Text>
</View>
{/* 进度条区域 */}
<View style={styles.progressContainer}>
<View style={styles.progressTrack}>
{/* 渐变背景进度条 */}
<View style={[styles.progressBar, { width: `${progressPercentage}%` }]}>
<LinearGradient
colors={['#F97316', '#FCD34D', '#84CC16', '#10B981']}
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 0 }}
style={styles.gradientBar}
/>
</View>
{/* 白色圆形指示器 */}
<View style={[styles.indicator, { left: `${Math.max(0, progressPercentage - 2)}%` }]} />
</View>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
backgroundColor: '#FFFFFF',
borderRadius: 20,
padding: 16,
marginBottom: 12,
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.08,
shadowRadius: 12,
elevation: 3,
},
header: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
marginBottom: 12,
},
leftSection: {
flexDirection: 'row',
alignItems: 'center',
},
iconContainer: {
width: 28,
height: 28,
borderRadius: 8,
backgroundColor: '#EBF4FF',
alignItems: 'center',
justifyContent: 'center',
marginRight: 8,
},
title: {
fontSize: 16,
fontWeight: '700',
color: '#1F2937',
},
emoji: {
fontSize: 24,
},
valueSection: {
flexDirection: 'row',
alignItems: 'baseline',
marginBottom: 16,
},
value: {
fontSize: 42,
fontWeight: '800',
color: '#1F2937',
lineHeight: 46,
},
unit: {
fontSize: 14,
fontWeight: '500',
color: '#6B7280',
marginLeft: 4,
},
progressContainer: {
height: 20,
},
progressTrack: {
height: 12,
backgroundColor: '#F3F4F6',
borderRadius: 6,
position: 'relative',
overflow: 'visible',
},
progressBar: {
height: '100%',
borderRadius: 6,
overflow: 'hidden',
},
gradientBar: {
height: '100%',
borderRadius: 6,
},
indicator: {
position: 'absolute',
top: -4,
width: 20,
height: 20,
borderRadius: 10,
backgroundColor: '#FFFFFF',
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.15,
shadowRadius: 4,
elevation: 4,
borderWidth: 2,
borderColor: '#E5E7EB',
},
});