feat: 优化统计和步数详情页面,添加活动等级计算和展示,更新压力计组件以支持HRV值直接显示
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import dayjs from 'dayjs';
|
||||
import { LinearGradient } from 'expo-linear-gradient';
|
||||
import React, { useState } from 'react';
|
||||
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
|
||||
@@ -11,42 +12,47 @@ interface StressMeterProps {
|
||||
}
|
||||
|
||||
export function StressMeter({ value, updateTime, style, hrvValue }: StressMeterProps) {
|
||||
// 格式化更新时间显示
|
||||
const formatUpdateTime = (date: Date): string => {
|
||||
const now = dayjs();
|
||||
const updateTime = dayjs(date);
|
||||
const diffMinutes = now.diff(updateTime, 'minute');
|
||||
const diffHours = now.diff(updateTime, 'hour');
|
||||
const diffDays = now.diff(updateTime, 'day');
|
||||
|
||||
if (diffMinutes < 1) {
|
||||
return '刚刚更新';
|
||||
} else if (diffMinutes < 60) {
|
||||
return `${diffMinutes}分钟前更新`;
|
||||
} else if (diffHours < 24) {
|
||||
return `${diffHours}小时前更新`;
|
||||
} else if (diffDays < 7) {
|
||||
return `${diffDays}天前更新`;
|
||||
} else {
|
||||
return updateTime.format('MM-DD HH:mm');
|
||||
}
|
||||
};
|
||||
|
||||
// 将HRV值转换为压力指数(0-100)
|
||||
// HRV值范围:30-110ms,映射到压力指数100-0
|
||||
// HRV值越高,压力越小;HRV值越低,压力越大
|
||||
// 根据压力指数计算状态
|
||||
const getStressStatus = () => {
|
||||
if (value === null) {
|
||||
return '未知';
|
||||
} else if (value >= 70) {
|
||||
return '放松';
|
||||
} else if (value >= 30) {
|
||||
return '正常';
|
||||
} else {
|
||||
return '紧张';
|
||||
}
|
||||
const convertHrvToStressIndex = (hrv: number | null): number | null => {
|
||||
if (hrv === null || hrv === 0) return null;
|
||||
|
||||
// HRV 范围: 30-110ms,对应压力指数: 100-0
|
||||
// 线性映射: stressIndex = 100 - ((hrv - 30) / (110 - 30)) * 100
|
||||
const normalizedHrv = Math.max(30, Math.min(110, hrv));
|
||||
const stressIndex = 100 - ((normalizedHrv - 30) / (110 - 30)) * 100;
|
||||
|
||||
return Math.round(stressIndex);
|
||||
};
|
||||
|
||||
// 根据状态获取表情
|
||||
const getStatusEmoji = () => {
|
||||
// 当HRV值为null或0时,不展示表情
|
||||
if (value === null || value === 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const status = getStressStatus();
|
||||
switch (status) {
|
||||
case '未知': return '';
|
||||
case '放松': return '😌';
|
||||
case '正常': return '😊';
|
||||
case '紧张': return '😰';
|
||||
default: return '😊';
|
||||
}
|
||||
};
|
||||
// 使用传入的 hrvValue 进行转换
|
||||
const stressIndex = convertHrvToStressIndex(hrvValue);
|
||||
|
||||
// 计算进度条位置(0-100%)
|
||||
// 压力指数越高,进度条越满(红色区域越多)
|
||||
const progressPercentage = value !== null ? Math.max(0, Math.min(100, value)) : 0;
|
||||
const progressPercentage = stressIndex !== null ? Math.max(0, Math.min(100, stressIndex)) : 0;
|
||||
|
||||
// 在组件内部添加状态
|
||||
const [showStressModal, setShowStressModal] = useState(false);
|
||||
@@ -68,12 +74,15 @@ export function StressMeter({ value, updateTime, style, hrvValue }: StressMeterP
|
||||
<View style={styles.leftSection}>
|
||||
<Text style={styles.title}>压力</Text>
|
||||
</View>
|
||||
{updateTime && (
|
||||
<Text style={styles.headerUpdateTime}>{formatUpdateTime(updateTime)}</Text>
|
||||
)}
|
||||
</View>
|
||||
|
||||
{/* 数值显示区域 */}
|
||||
<View style={styles.valueSection}>
|
||||
<Text style={styles.value}>{value === null ? '--' : value}</Text>
|
||||
<Text style={styles.unit}>指数</Text>
|
||||
<Text style={styles.value}>{stressIndex === null ? '--' : stressIndex}</Text>
|
||||
<Text style={styles.unit}>ms</Text>
|
||||
</View>
|
||||
|
||||
{/* 进度条区域 */}
|
||||
@@ -89,14 +98,10 @@ export function StressMeter({ value, updateTime, style, hrvValue }: StressMeterP
|
||||
/>
|
||||
</View>
|
||||
{/* 白色圆形指示器 */}
|
||||
<View style={[styles.indicator, { left: `${Math.max(0, Math.min(100, progressPercentage - 2))}%` }]} />
|
||||
<View style={[styles.indicator, { left: `${Math.max(0, Math.min(100, progressPercentage))}%` }]} />
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* 更新时间
|
||||
{updateTime && (
|
||||
<Text style={styles.updateTime}>{formatUpdateTime(updateTime)}</Text>
|
||||
)} */}
|
||||
</TouchableOpacity>
|
||||
|
||||
{/* 压力分析浮窗 */}
|
||||
@@ -207,4 +212,9 @@ const styles = StyleSheet.create({
|
||||
textAlign: 'right',
|
||||
marginTop: 2,
|
||||
},
|
||||
headerUpdateTime: {
|
||||
fontSize: 11,
|
||||
color: '#9AA3AE',
|
||||
fontWeight: '500',
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user