feat: 新增 StressMeter 组件,移除原 HRV 压力监测代码
This commit is contained in:
170
components/StressMeter.tsx
Normal file
170
components/StressMeter.tsx
Normal 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',
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user