feat: 优化健康数据相关组件及功能

- 在 CoachScreen 中调整键盘高度计算,移除不必要的 insets.bottom
- 更新 Statistics 组件,移除未使用的健康数据相关函数,简化代码
- 修改多个统计卡片,移除不必要的图标属性,提升组件简洁性
- 优化 HealthDataCard 和其他统计卡片的样式,提升视觉一致性
- 更新健康数据获取逻辑,确保数据处理更为准确
- 移除 MoodCard 中的多余元素,简化心情记录展示
- 调整 StressMeter 和其他组件的样式,提升用户体验
This commit is contained in:
richarjiang
2025-08-25 12:44:40 +08:00
parent ee84a801fb
commit be0a8e7393
10 changed files with 83 additions and 197 deletions

View File

@@ -18,7 +18,7 @@ import { useColorScheme } from '@/hooks/useColorScheme';
import { calculateNutritionSummary, getDietRecords, NutritionSummary } from '@/services/dietRecords';
import { fetchDailyMoodCheckins, selectLatestMoodRecordByDate } from '@/store/moodSlice';
import { getMonthDaysZh, getTodayIndexInMonth } from '@/utils/date';
import { ensureHealthPermissions, fetchHealthDataForDate, testOxygenSaturationData } from '@/utils/health';
import { ensureHealthPermissions, fetchHealthDataForDate } from '@/utils/health';
import { useBottomTabBarHeight } from '@react-navigation/bottom-tabs';
import { useFocusEffect } from '@react-navigation/native';
import dayjs from 'dayjs';
@@ -124,14 +124,12 @@ export default function ExploreScreen() {
const [oxygenSaturation, setOxygenSaturation] = useState<number | null>(null);
const [heartRate, setHeartRate] = useState<number | null>(null);
const [isLoading, setIsLoading] = useState(false);
// 用于触发动画重置的 token当日期或数据变化时更新
const [animToken, setAnimToken] = useState(0);
const [trainingProgress, setTrainingProgress] = useState(0); // 暂定静态80%
// 营养数据状态
const [nutritionSummary, setNutritionSummary] = useState<NutritionSummary | null>(null);
const [isNutritionLoading, setIsNutritionLoading] = useState(false);
const { registerTask } = useBackgroundTasks();
// 心情相关状态
const dispatch = useAppDispatch();
@@ -182,7 +180,6 @@ export default function ExploreScreen() {
const loadHealthData = async (targetDate?: Date) => {
try {
console.log('=== 开始HealthKit初始化流程 ===');
setIsLoading(true);
const ok = await ensureHealthPermissions();
if (!ok) {
@@ -246,15 +243,12 @@ export default function ExploreScreen() {
// 重置血氧饱和度和心率数据
setOxygenSaturation(null);
setHeartRate(null);
} finally {
setIsLoading(false);
}
};
// 加载营养数据
const loadNutritionData = async (targetDate?: Date) => {
try {
setIsNutritionLoading(true);
// 确定要查询的日期:优先使用传入的日期,否则使用当前选中索引对应的日期
let derivedDate: Date;
@@ -281,8 +275,6 @@ export default function ExploreScreen() {
} catch (error) {
console.error('营养数据加载失败:', error);
setNutritionSummary(null);
} finally {
setIsNutritionLoading(false);
}
};
@@ -300,20 +292,20 @@ export default function ExploreScreen() {
}, [selectedIndex])
);
// useEffect(() => {
// // 注册任务
// registerTask({
// id: 'health-data-task',
// name: 'health-data-task',
// handler: async () => {
// try {
// await loadHealthData();
// } catch (error) {
// console.error('健康数据任务执行失败:', error);
// }
// },
// });
// }, []);
useEffect(() => {
// 注册任务
registerTask({
id: 'health-data-task',
name: 'health-data-task',
handler: async () => {
try {
await loadHealthData();
} catch (error) {
console.error('健康数据任务执行失败:', error);
}
},
});
}, []);
// 日期点击时,加载对应日期数据
const onSelectDate = (index: number, date: Date) => {
@@ -325,16 +317,6 @@ export default function ExploreScreen() {
}
};
// 测试血氧饱和度数据
const testOxygenData = async () => {
console.log('开始测试血氧饱和度数据...');
const currentDate = getCurrentSelectedDate();
await testOxygenSaturationData(currentDate);
};
// 使用统一的渐变背景色
const backgroundGradientColors = [colorTokens.backgroundGradientStart, colorTokens.backgroundGradientEnd] as const;
return (
<View style={styles.container}>
{/* 背景渐变 */}
@@ -384,8 +366,8 @@ export default function ExploreScreen() {
/>
</FloatingCard>
<FloatingCard style={[styles.masonryCard, styles.caloriesCard]} delay={500}>
<Text style={styles.cardTitleSecondary}></Text>
<FloatingCard style={styles.masonryCard} delay={500}>
<Text style={styles.cardTitle}></Text>
{activeCalories != null ? (
<AnimatedNumber
value={activeCalories}
@@ -398,7 +380,7 @@ export default function ExploreScreen() {
)}
</FloatingCard>
<FloatingCard style={[styles.masonryCard, styles.stepsCard]} delay={1000}>
<FloatingCard style={styles.masonryCard} delay={1000}>
<View style={styles.cardHeaderRow}>
<Text style={styles.cardTitle}></Text>
</View>
@@ -414,14 +396,14 @@ export default function ExploreScreen() {
)}
<ProgressBar
progress={Math.min(1, Math.max(0, (stepCount ?? 0) / stepGoal))}
height={16}
height={14}
trackColor="#FFEBCB"
fillColor="#FFC365"
showLabel={false}
/>
</FloatingCard>
{/* 心情卡片 */}
<FloatingCard style={[styles.masonryCard, styles.moodCard]} delay={1500}>
<FloatingCard style={styles.masonryCard} delay={1500}>
<MoodCard
moodCheckin={currentMoodCheckin}
onPress={() => pushIfAuthedElseLogin('/mood/calendar')}
@@ -444,7 +426,7 @@ export default function ExploreScreen() {
/>
</FloatingCard>
<FloatingCard style={[styles.masonryCard, styles.sleepCard]} delay={750}>
<FloatingCard style={styles.masonryCard} delay={750}>
<View style={styles.cardHeaderRow}>
<Text style={styles.cardTitle}></Text>
</View>
@@ -473,13 +455,6 @@ export default function ExploreScreen() {
style={styles.basalMetabolismCardOverride}
oxygenSaturation={oxygenSaturation}
/>
{/* 测试按钮 - 开发时使用 */}
<Text
style={styles.testButton}
onPress={testOxygenData}
>
</Text>
</FloatingCard>
{/* 心率卡片 */}
@@ -577,22 +552,11 @@ const styles = StyleSheet.create({
borderRadius: 22,
padding: 16,
},
caloriesCard: {
backgroundColor: '#FFFFFF',
},
trainingCard: {
backgroundColor: '#EEE9FF',
},
cardTitleSecondary: {
color: '#9AA3AE',
fontSize: 10,
fontWeight: '600',
marginBottom: 10,
},
caloriesValue: {
color: '#192126',
fontSize: 18,
fontWeight: '800',
marginTop: 18,
},
trainingContent: {
marginTop: 8,
@@ -706,9 +670,6 @@ const styles = StyleSheet.create({
color: '#5B5B5B',
fontWeight: '600',
},
stepsCard: {
backgroundColor: '#FFE4B8',
},
stepsValue: {
fontSize: 14,
color: '#7A6A42',
@@ -797,9 +758,6 @@ const styles = StyleSheet.create({
justifyContent: 'space-between',
marginTop: 8,
},
sleepCard: {
backgroundColor: '#E8F4FD',
},
sleepValue: {
fontSize: 16,
color: '#1E40AF',
@@ -821,14 +779,5 @@ const styles = StyleSheet.create({
top: 0,
padding: 4,
},
moodCard: {
backgroundColor: '#F0FDF4',
},
testButton: {
fontSize: 12,
color: '#3B82F6',
textAlign: 'center',
marginTop: 8,
padding: 4,
},
});