feat: 新增基础代谢详情页面并优化HRV数据获取逻辑

- 新增基础代谢详情页面,包含图表展示、数据缓存和防抖机制
- 优化HRV数据获取逻辑,支持实时、近期和历史数据的智能获取
- 移除WaterIntakeCard和WaterSettings中的登录验证逻辑
- 更新饮水数据管理hook,直接使用HealthKit数据
- 添加饮水目标存储和获取功能
- 更新依赖包版本
This commit is contained in:
richarjiang
2025-09-25 14:15:42 +08:00
parent 83e534c4a7
commit 79ab354f31
12 changed files with 1563 additions and 702 deletions

View File

@@ -518,32 +518,70 @@ async function fetchHeartRateVariability(options: HealthDataOptions): Promise<HR
if (result && result.data && Array.isArray(result.data) && result.data.length > 0) {
let selectedSample: any = null;
let bestQuality = -1;
console.log('result~~~', result);
console.log(`获取到 ${result.data.length} 个HRV样本`);
// 优先使用优化后的最佳质量值对应的样本
// 首先尝试使用最佳质量值
if (result.bestQualityValue && typeof result.bestQualityValue === 'number') {
const qualityValue = validateHRVValue(result.bestQualityValue);
if (qualityValue !== null) {
// 找到对应的最佳质量样本
selectedSample = result.data[result.data.length - 1];
// 找到质量分数最高的样本
for (const sample of result.data) {
const sampleQuality = sample.qualityScore || 0;
const sampleValue = validateHRVValue(sample.value);
logSuccess('HRV数据最佳质量', {
value: qualityValue,
totalSamples: result.data.length,
recordedAt: selectedSample.endDate
});
if (sampleValue !== null && sampleQuality > bestQuality) {
bestQuality = sampleQuality;
selectedSample = sample;
}
}
if (selectedSample) {
logSuccess('HRV数据最佳质量', {
value: qualityValue,
qualityScore: bestQuality,
totalSamples: result.data.length,
recordedAt: selectedSample.endDate
});
}
}
}
// 如果没有找到最佳质量样本,使用第一个有效样本
// 如果没有找到最佳质量样本,或者最佳质量值无效,重新评估所有样本
if (!selectedSample) {
for (const sample of result.data) {
console.log('重新评估所有样本以找到最佳数据...');
// 按质量分数、手动测量标志和时间排序
const sortedSamples = result.data.sort((a: any, b: any) => {
const qualityA = a.qualityScore || 0;
const qualityB = b.qualityScore || 0;
const isManualA = a.isManualMeasurement || false;
const isManualB = b.isManualMeasurement || false;
// 手动测量优先
if (isManualA && !isManualB) return -1;
if (!isManualA && isManualB) return 1;
// 质量分数优先
if (qualityA !== qualityB) return qualityB - qualityA;
// 时间优先(最新的优先)
const dateA = new Date(a.endDate || a.startDate).getTime();
const dateB = new Date(b.endDate || b.startDate).getTime();
return dateB - dateA;
});
// 选择第一个有效样本
for (const sample of sortedSamples) {
const sampleValue = validateHRVValue(sample.value);
if (sampleValue !== null) {
selectedSample = sample;
console.log('使用有效HRV样本:', {
bestQuality = sample.qualityScore || 0;
console.log('选择最佳HRV样本:', {
value: sampleValue,
qualityScore: bestQuality,
isManual: sample.isManualMeasurement,
source: sample.source?.name,
recordedAt: sample.endDate
});
@@ -733,8 +771,35 @@ export async function fetchTodayHealthData(): Promise<TodayHealthData> {
export async function fetchHRVForDate(date: Date): Promise<HRVData | null> {
console.log('开始获取指定日期HRV数据...', date);
// 首先尝试获取指定日期的HRV数据
const options = createDateRange(date);
return fetchHeartRateVariability(options);
const hrvData = await fetchHeartRateVariability(options);
// 如果当天没有数据尝试获取最近7天内的最新数据
if (!hrvData) {
console.log('指定日期无HRV数据尝试获取最近7天内的数据...');
const endDate = new Date(date);
const startDate = new Date(date);
startDate.setDate(startDate.getDate() - 7); // 往前推7天
const recentOptions = {
startDate: startDate.toISOString(),
endDate: endDate.toISOString()
};
const recentHrvData = await fetchHeartRateVariability(recentOptions);
if (recentHrvData) {
console.log('获取到最近7天内的HRV数据:', recentHrvData);
return recentHrvData;
} else {
console.log('最近7天内也无HRV数据');
}
}
return hrvData;
}
export async function fetchTodayHRV(): Promise<HRVData | null> {
@@ -1189,3 +1254,117 @@ export async function fetchHRVWithAnalysis(date: Date): Promise<{ hrvData: HRVDa
}
}
// 智能HRV数据获取 - 优先获取实时数据,如果没有则获取历史数据
export async function fetchSmartHRVData(date: Date): Promise<HRVData | null> {
console.log('开始智能HRV数据获取...', date);
try {
// 1. 首先尝试获取最近2小时的实时数据
console.log('1. 尝试获取最近2小时的实时HRV数据...');
const recentHRV = await fetchRecentHRV(2);
if (recentHRV) {
console.log('✅ 成功获取到实时HRV数据:', recentHRV);
// 检查数据是否足够新1小时内
const dataTime = new Date(recentHRV.recordedAt).getTime();
const now = Date.now();
const oneHour = 60 * 60 * 1000;
if (now - dataTime <= oneHour) {
console.log('✅ 实时数据足够新,直接使用');
return recentHRV;
} else {
console.log('⚠️ 实时数据较旧,继续寻找更好的数据');
}
}
// 2. 如果没有实时数据或数据太旧,尝试获取当天的数据
console.log('2. 尝试获取当天的HRV数据...');
const todayHRV = await fetchHRVForDate(date);
if (todayHRV) {
console.log('✅ 成功获取到当天HRV数据:', todayHRV);
return todayHRV;
}
// 3. 如果当天没有数据尝试获取最近3天的数据
console.log('3. 尝试获取最近3天的HRV数据...');
const endDate = new Date(date);
const startDate = new Date(date);
startDate.setDate(startDate.getDate() - 3);
const recentOptions = {
startDate: startDate.toISOString(),
endDate: endDate.toISOString()
};
const recentData = await fetchHeartRateVariability(recentOptions);
if (recentData) {
console.log('✅ 成功获取到最近3天的HRV数据:', recentData);
return recentData;
}
// 4. 如果仍然没有数据返回null
console.log('❌ 未找到任何HRV数据');
return null;
} catch (error) {
console.error('智能HRV数据获取失败:', error);
return null;
}
}
// 获取HRV数据并附带详细的状态信息
export async function fetchHRVWithStatus(date: Date): Promise<{
hrvData: HRVData | null;
status: 'realtime' | 'recent' | 'historical' | 'none';
message: string;
}> {
try {
const hrvData = await fetchSmartHRVData(date);
if (!hrvData) {
return {
hrvData: null,
status: 'none',
message: '未找到HRV数据'
};
}
const dataTime = new Date(hrvData.recordedAt).getTime();
const now = Date.now();
const oneHour = 60 * 60 * 1000;
const oneDay = 24 * 60 * 60 * 1000;
let status: 'realtime' | 'recent' | 'historical';
let message: string;
if (now - dataTime <= oneHour) {
status = 'realtime';
message = '实时HRV数据';
} else if (now - dataTime <= oneDay) {
status = 'recent';
message = '近期HRV数据';
} else {
status = 'historical';
message = '历史HRV数据';
}
return {
hrvData,
status,
message
};
} catch (error) {
console.error('获取HRV状态失败:', error);
return {
hrvData: null,
status: 'none',
message: '获取HRV数据失败'
};
}
}