From 63b1c529099630ab8108d5d99e7aede6d8ffa007 Mon Sep 17 00:00:00 2001 From: richarjiang Date: Tue, 19 Aug 2025 19:22:38 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=20StressMeter=20?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=EF=BC=8C=E7=A7=BB=E9=99=A4=E5=8E=9F=20HRV=20?= =?UTF-8?q?=E5=8E=8B=E5=8A=9B=E7=9B=91=E6=B5=8B=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/(tabs)/statistics.tsx | 144 +------------------------------ components/StressMeter.tsx | 170 +++++++++++++++++++++++++++++++++++++ 2 files changed, 172 insertions(+), 142 deletions(-) create mode 100644 components/StressMeter.tsx diff --git a/app/(tabs)/statistics.tsx b/app/(tabs)/statistics.tsx index d9422f2..4ad167f 100644 --- a/app/(tabs)/statistics.tsx +++ b/app/(tabs)/statistics.tsx @@ -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() { {/* HRV压力监测卡片 */} - - - - - - 压力监测 - - - - - {hrvValue} - 毫秒 - - - - {hrvStatus} - - {hrvStatus === '放松' ? '😌' : - hrvStatus === '正常' ? '😊' : - '😰'} - - - - - - - - - - 放松 - 正常 - 紧张 - - - + {/* 查看更多 */} @@ -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', - }, }); diff --git a/components/StressMeter.tsx b/components/StressMeter.tsx new file mode 100644 index 0000000..818895f --- /dev/null +++ b/components/StressMeter.tsx @@ -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 ( + + {/* 头部区域 */} + + + + + + 压力 + + {getStatusEmoji()} + + + {/* 数值显示区域 */} + + {value} + 毫秒 + + + {/* 进度条区域 */} + + + {/* 渐变背景进度条 */} + + + + {/* 白色圆形指示器 */} + + + + + ); +} + +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', + }, +}); \ No newline at end of file