feat: 更新睡眠详情页面,集成真实睡眠数据生成逻辑,优化睡眠阶段图表展示,添加睡眠样本数据处理功能,提升用户体验
This commit is contained in:
@@ -57,6 +57,9 @@ export type SleepDetailData = {
|
||||
// 睡眠阶段统计
|
||||
sleepStages: SleepStageStats[];
|
||||
|
||||
// 原始睡眠样本数据(用于图表显示)
|
||||
rawSleepSamples: SleepSample[];
|
||||
|
||||
// 心率数据
|
||||
averageHeartRate: number | null; // 平均心率
|
||||
sleepHeartRateData: HeartRateData[]; // 睡眠期间心率数据
|
||||
@@ -96,7 +99,19 @@ async function fetchSleepSamples(date: Date): Promise<SleepSample[]> {
|
||||
return;
|
||||
}
|
||||
|
||||
// 添加详细日志,了解实际获取到的数据类型
|
||||
console.log('获取到睡眠样本:', results.length);
|
||||
console.log('睡眠样本详情:', results.map(r => ({
|
||||
value: r.value,
|
||||
start: r.startDate?.substring(11, 16),
|
||||
end: r.endDate?.substring(11, 16),
|
||||
duration: `${Math.round((new Date(r.endDate).getTime() - new Date(r.startDate).getTime()) / 60000)}min`
|
||||
})));
|
||||
|
||||
// 检查可用的睡眠阶段类型
|
||||
const uniqueValues = [...new Set(results.map(r => r.value))];
|
||||
console.log('可用的睡眠阶段类型:', uniqueValues);
|
||||
|
||||
resolve(results as unknown as SleepSample[]);
|
||||
});
|
||||
});
|
||||
@@ -274,7 +289,6 @@ export function getSleepStageColor(stage: SleepStage): string {
|
||||
case SleepStage.Core:
|
||||
return '#3B82F6'; // 蓝色
|
||||
case SleepStage.REM:
|
||||
return '#8B5CF6'; // 紫色
|
||||
case SleepStage.Asleep:
|
||||
return '#06B6D4'; // 青色
|
||||
case SleepStage.Awake:
|
||||
@@ -340,6 +354,7 @@ export async function fetchSleepDetailForDate(date: Date): Promise<SleepDetailDa
|
||||
wakeupTime,
|
||||
timeInBed,
|
||||
sleepStages,
|
||||
rawSleepSamples: sleepSamples, // 保存原始睡眠样本数据
|
||||
averageHeartRate,
|
||||
sleepHeartRateData,
|
||||
sleepEfficiency,
|
||||
@@ -373,4 +388,64 @@ export function formatSleepTime(minutes: number): string {
|
||||
// 格式化时间显示 (HH:MM)
|
||||
export function formatTime(dateString: string): string {
|
||||
return dayjs(dateString).format('HH:mm');
|
||||
}
|
||||
|
||||
// 将睡眠样本数据转换为15分钟间隔的睡眠阶段数据
|
||||
export function convertSleepSamplesToIntervals(sleepSamples: SleepSample[], bedtime: string, wakeupTime: string): { time: string; stage: SleepStage }[] {
|
||||
const data: { time: string; stage: SleepStage }[] = [];
|
||||
|
||||
if (sleepSamples.length === 0) {
|
||||
console.log('没有睡眠样本数据可用于图表显示');
|
||||
return [];
|
||||
}
|
||||
|
||||
// 过滤掉InBed阶段,只保留实际睡眠阶段
|
||||
const sleepOnlySamples = sleepSamples.filter(sample =>
|
||||
sample.value !== SleepStage.InBed
|
||||
);
|
||||
|
||||
if (sleepOnlySamples.length === 0) {
|
||||
console.log('只有InBed数据,没有详细睡眠阶段数据');
|
||||
return [];
|
||||
}
|
||||
|
||||
console.log('处理睡眠阶段数据 - 样本数量:', sleepOnlySamples.length);
|
||||
console.log('时间范围:', formatTime(bedtime), '-', formatTime(wakeupTime));
|
||||
|
||||
const startTime = dayjs(bedtime);
|
||||
const endTime = dayjs(wakeupTime);
|
||||
let currentTime = startTime.clone();
|
||||
|
||||
// 创建一个映射,用于快速查找每个时间点的睡眠阶段
|
||||
while (currentTime.isBefore(endTime)) {
|
||||
const currentTimestamp = currentTime.toDate().getTime();
|
||||
|
||||
// 找到当前时间点对应的睡眠阶段
|
||||
let currentStage = SleepStage.Awake; // 默认为清醒
|
||||
|
||||
for (const sample of sleepOnlySamples) {
|
||||
const sampleStart = new Date(sample.startDate).getTime();
|
||||
const sampleEnd = new Date(sample.endDate).getTime();
|
||||
|
||||
// 如果当前时间在这个样本的时间范围内
|
||||
if (currentTimestamp >= sampleStart && currentTimestamp < sampleEnd) {
|
||||
currentStage = sample.value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const timeStr = currentTime.format('HH:mm');
|
||||
data.push({ time: timeStr, stage: currentStage });
|
||||
|
||||
// 移动到下一个15分钟间隔
|
||||
currentTime = currentTime.add(15, 'minute');
|
||||
}
|
||||
|
||||
console.log('生成的睡眠阶段间隔数据点数量:', data.length);
|
||||
console.log('阶段分布:', data.reduce((acc, curr) => {
|
||||
acc[curr.stage] = (acc[curr.stage] || 0) + 1;
|
||||
return acc;
|
||||
}, {} as Record<string, number>));
|
||||
|
||||
return data;
|
||||
}
|
||||
Reference in New Issue
Block a user