feat(ui): 统一应用主题色为天空蓝并优化渐变背景

将应用主色调从 '#BBF246' 更改为 '#87CEEB'(天空蓝),并更新所有相关组件和页面中的颜色引用。同时为多个页面添加统一的渐变背景,提升视觉效果和用户体验。新增压力分析模态框组件,并优化压力计组件的交互与显示逻辑。更新应用图标和启动图资源。
This commit is contained in:
richarjiang
2025-08-20 09:38:25 +08:00
parent 37f8c3c78d
commit d76ba48424
35 changed files with 519 additions and 184 deletions

View File

@@ -1,25 +1,27 @@
import { Ionicons } from '@expo/vector-icons';
import { LinearGradient } from 'expo-linear-gradient';
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
interface StressMeterProps {
value: number;
value: number | null;
updateTime?: Date;
style?: any;
onPress?: () => void;
}
export function StressMeter({ value, updateTime, style }: StressMeterProps) {
// 计算进度条位置0-100%
// HRV值范围30-110ms对应进度条0-100%
const progressPercentage = Math.min(100, Math.max(0, ((value - 30) / 80) * 100));
// 根据HRV值计算状态
const getHrvStatus = () => {
if (value >= 70) {
export function StressMeter({ value, updateTime, style, onPress }: StressMeterProps) {
// 将HRV值转换为压力指数0-100
// HRV值范围30-110ms映射到压力指数100-0
// HRV值越高压力越小HRV值越低压力越大
const stressIndex = value ? Math.round(Math.min(100, Math.max(0, 100 - ((value - 30) / 80) * 100))) : null;
// 根据压力指数计算状态
const getStressStatus = () => {
if (stressIndex === null) {
return '未知';
} else if (stressIndex <= 30) {
return '放松';
} else if (value >= 50) {
} else if (stressIndex <= 70) {
return '正常';
} else {
return '紧张';
@@ -28,13 +30,14 @@ export function StressMeter({ value, updateTime, style }: StressMeterProps) {
// 根据状态获取表情
const getStatusEmoji = () => {
// 当HRV值为0时不展示表情
if (value === 0) {
// 当HRV值为null或0时不展示表情
if (value === null || value === 0) {
return '';
}
const status = getHrvStatus();
const status = getStressStatus();
switch (status) {
case '未知': return '';
case '放松': return '😌';
case '正常': return '😊';
case '紧张': return '😰';
@@ -42,24 +45,18 @@ export function StressMeter({ value, updateTime, style }: StressMeterProps) {
}
};
// 格式化更新时间
const formatUpdateTime = (date?: Date) => {
if (!date) return '';
const hours = date.getHours().toString().padStart(2, '0');
const minutes = date.getMinutes().toString().padStart(2, '0');
return `${hours}:${minutes}`;
};
// 计算进度条位置0-100%
// 压力指数越高,进度条越满
const progressPercentage = stressIndex === null ? 0 : stressIndex;
return (
<View style={[styles.container, style]}>
{/* 渐变背景 */}
<LinearGradient
colors={['#F8F9FF', '#F0F4FF']}
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 1 }}
style={styles.gradientBackground}
/>
<TouchableOpacity
style={[styles.container, style]}
onPress={onPress}
activeOpacity={0.8}
>
{/* 头部区域 */}
<View style={styles.header}>
<View style={styles.leftSection}>
@@ -73,30 +70,32 @@ export function StressMeter({ value, updateTime, style }: StressMeterProps) {
{/* 数值显示区域 */}
<View style={styles.valueSection}>
<Text style={styles.value}>{value}</Text>
<Text style={styles.unit}></Text>
<Text style={styles.value}>{stressIndex === null ? '--' : stressIndex}</Text>
<Text style={styles.unit}></Text>
</View>
{/* 进度条区域 */}
<View style={styles.progressContainer}>
<View style={styles.progressTrack}>
{/* 渐变背景进度条 */}
<LinearGradient
colors={['#FFD700', '#87CEEB', '#98FB98']}
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 0 }}
style={styles.gradientTrack}
/>
<View style={[styles.progressBar, { width: `${progressPercentage}%` }]}>
<LinearGradient
colors={['#10B981', '#FCD34D', '#F97316']}
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 0 }}
style={styles.gradientBar}
/>
</View>
{/* 白色圆形指示器 */}
<View style={[styles.indicator, { left: `${Math.max(0, Math.min(100, progressPercentage - 2))}%` }]} />
</View>
</View>
{/* 更新时间 */}
{/* 更新时间
{updateTime && (
<Text style={styles.updateTime}>{formatUpdateTime(updateTime)}</Text>
)}
</View>
)} */}
</TouchableOpacity>
);
}
@@ -181,7 +180,12 @@ const styles = StyleSheet.create({
position: 'relative',
overflow: 'visible',
},
gradientTrack: {
progressBar: {
height: '100%',
borderRadius: 4,
overflow: 'hidden',
},
gradientBar: {
height: '100%',
borderRadius: 4,
},