feat: 优化统计和步数详情页面,添加活动等级计算和展示,更新压力计组件以支持HRV值直接显示
This commit is contained in:
@@ -176,6 +176,39 @@ export default function StepsDetailScreen() {
|
||||
return maxStepsData.steps > 0 ? maxStepsData : null;
|
||||
}, [hourlySteps]);
|
||||
|
||||
// 活动等级配置
|
||||
const activityLevels = useMemo(() => [
|
||||
{ key: 'inactive', label: '不怎么动', minSteps: 0, maxSteps: 3000, color: '#B8C8D6' },
|
||||
{ key: 'light', label: '轻度活跃', minSteps: 3000, maxSteps: 7500, color: '#93C5FD' },
|
||||
{ key: 'moderate', label: '中等活跃', minSteps: 7500, maxSteps: 10000, color: '#FCD34D' },
|
||||
{ key: 'very_active', label: '非常活跃', minSteps: 10000, maxSteps: Infinity, color: '#FB923C' }
|
||||
], []);
|
||||
|
||||
// 计算当前活动等级
|
||||
const currentActivityLevel = useMemo(() => {
|
||||
return activityLevels.find(level =>
|
||||
totalSteps >= level.minSteps && totalSteps < level.maxSteps
|
||||
) || activityLevels[0];
|
||||
}, [totalSteps, activityLevels]);
|
||||
|
||||
// 计算下一等级
|
||||
const nextActivityLevel = useMemo(() => {
|
||||
const currentIndex = activityLevels.indexOf(currentActivityLevel);
|
||||
return currentIndex < activityLevels.length - 1 ? activityLevels[currentIndex + 1] : null;
|
||||
}, [currentActivityLevel, activityLevels]);
|
||||
|
||||
// 计算进度百分比
|
||||
const progressPercentage = useMemo(() => {
|
||||
if (!nextActivityLevel) return 100; // 已达到最高级
|
||||
|
||||
const rangeSize = nextActivityLevel.minSteps - currentActivityLevel.minSteps;
|
||||
const currentProgress = totalSteps - currentActivityLevel.minSteps;
|
||||
return Math.min(Math.max((currentProgress / rangeSize) * 100, 0), 100);
|
||||
}, [totalSteps, currentActivityLevel, nextActivityLevel]);
|
||||
|
||||
// 倒序显示的活动等级(用于图例)
|
||||
const reversedActivityLevels = useMemo(() => [...activityLevels].reverse(), [activityLevels]);
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
{/* 背景渐变 */}
|
||||
@@ -343,6 +376,63 @@ export default function StepsDetailScreen() {
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* 活动等级展示卡片 */}
|
||||
<View style={styles.activityLevelCard}>
|
||||
|
||||
|
||||
{/* 活动级别文本 */}
|
||||
<Text style={styles.activityMainText}>你今天的活动量处于</Text>
|
||||
<Text style={styles.activityLevelText}>{currentActivityLevel.label}</Text>
|
||||
|
||||
{/* 进度条 */}
|
||||
<View style={styles.progressBarContainer}>
|
||||
<View style={styles.progressBarBackground}>
|
||||
<View
|
||||
style={[
|
||||
styles.progressBarFill,
|
||||
{
|
||||
width: `${progressPercentage}%`,
|
||||
backgroundColor: currentActivityLevel.color
|
||||
}
|
||||
]}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* 步数信息 */}
|
||||
<View style={styles.stepsInfoContainer}>
|
||||
<View style={styles.currentStepsInfo}>
|
||||
<Text style={styles.stepsValue}>{totalSteps.toLocaleString()} 步</Text>
|
||||
<Text style={styles.stepsLabel}>当前</Text>
|
||||
</View>
|
||||
<View style={styles.nextStepsInfo}>
|
||||
<Text style={styles.stepsValue}>
|
||||
{nextActivityLevel ? `${nextActivityLevel.minSteps.toLocaleString()} 步` : '--'}
|
||||
</Text>
|
||||
<Text style={styles.stepsLabel}>
|
||||
{nextActivityLevel ? `下一级: ${nextActivityLevel.label}` : '已达最高级'}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* 活动等级图例 */}
|
||||
<View style={styles.activityLegendContainer}>
|
||||
{reversedActivityLevels.map((level) => (
|
||||
<View key={level.key} style={styles.legendItem}>
|
||||
<View style={[styles.legendIcon, { backgroundColor: level.color }]}>
|
||||
<Text style={styles.legendIconText}>🏃</Text>
|
||||
</View>
|
||||
<Text style={styles.legendLabel}>{level.label}</Text>
|
||||
<Text style={styles.legendRange}>
|
||||
{level.maxSteps === Infinity
|
||||
? `> ${level.minSteps.toLocaleString()}`
|
||||
: `${level.minSteps.toLocaleString()} - ${level.maxSteps.toLocaleString()}`}
|
||||
</Text>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
</ScrollView>
|
||||
</SafeAreaView>
|
||||
</View>
|
||||
@@ -541,4 +631,127 @@ const styles = StyleSheet.create({
|
||||
borderWidth: 0.5,
|
||||
borderColor: '#FFA726',
|
||||
},
|
||||
activityLevelCard: {
|
||||
backgroundColor: '#FFFFFF',
|
||||
borderRadius: 16,
|
||||
padding: 24,
|
||||
marginVertical: 16,
|
||||
alignItems: 'center',
|
||||
shadowColor: '#000',
|
||||
shadowOffset: {
|
||||
width: 0,
|
||||
height: 4,
|
||||
},
|
||||
shadowOpacity: 0.08,
|
||||
shadowRadius: 12,
|
||||
elevation: 6,
|
||||
},
|
||||
activityIconContainer: {
|
||||
marginBottom: 16,
|
||||
},
|
||||
activityIcon: {
|
||||
width: 80,
|
||||
height: 80,
|
||||
borderRadius: 40,
|
||||
backgroundColor: '#E0F2FE',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
borderWidth: 2,
|
||||
borderColor: '#93C5FD',
|
||||
borderStyle: 'dashed',
|
||||
},
|
||||
meditationIcon: {
|
||||
width: 50,
|
||||
height: 50,
|
||||
borderRadius: 25,
|
||||
backgroundColor: '#93C5FD',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
meditationEmoji: {
|
||||
fontSize: 24,
|
||||
},
|
||||
activityMainText: {
|
||||
fontSize: 16,
|
||||
color: '#64748B',
|
||||
marginBottom: 4,
|
||||
},
|
||||
activityLevelText: {
|
||||
fontSize: 24,
|
||||
fontWeight: '700',
|
||||
color: '#192126',
|
||||
marginBottom: 20,
|
||||
},
|
||||
progressBarContainer: {
|
||||
width: '100%',
|
||||
marginBottom: 24,
|
||||
},
|
||||
progressBarBackground: {
|
||||
width: '100%',
|
||||
height: 8,
|
||||
backgroundColor: '#F0F9FF',
|
||||
borderRadius: 4,
|
||||
overflow: 'hidden',
|
||||
},
|
||||
progressBarFill: {
|
||||
height: '100%',
|
||||
borderRadius: 4,
|
||||
},
|
||||
stepsInfoContainer: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
width: '100%',
|
||||
marginBottom: 32,
|
||||
},
|
||||
currentStepsInfo: {
|
||||
alignItems: 'flex-start',
|
||||
},
|
||||
nextStepsInfo: {
|
||||
alignItems: 'flex-end',
|
||||
},
|
||||
stepsValue: {
|
||||
fontSize: 20,
|
||||
fontWeight: '700',
|
||||
color: '#192126',
|
||||
marginBottom: 4,
|
||||
},
|
||||
stepsLabel: {
|
||||
fontSize: 14,
|
||||
color: '#64748B',
|
||||
},
|
||||
activityLegendContainer: {
|
||||
width: '100%',
|
||||
},
|
||||
legendItem: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
paddingVertical: 12,
|
||||
paddingHorizontal: 16,
|
||||
backgroundColor: '#F8FAFC',
|
||||
marginBottom: 8,
|
||||
borderRadius: 12,
|
||||
},
|
||||
legendIcon: {
|
||||
width: 32,
|
||||
height: 32,
|
||||
borderRadius: 8,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
marginRight: 12,
|
||||
},
|
||||
legendIconText: {
|
||||
fontSize: 16,
|
||||
},
|
||||
legendLabel: {
|
||||
flex: 1,
|
||||
fontSize: 14,
|
||||
fontWeight: '600',
|
||||
color: '#192126',
|
||||
},
|
||||
legendRange: {
|
||||
fontSize: 14,
|
||||
color: '#64748B',
|
||||
fontWeight: '500',
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user