基于提供的 Git diff,我将生成以下 conventional commit message: ## 变更分析: 1. **核心功能**: - 新增睡眠监控服务(`services/sleepMonitor.ts`) - 新增睡眠通知服务(`services/sleepNotificationService.ts`) - iOS 原生端增加睡眠观察者方法 2. **应用启动优化**: - 重构 `app/_layout.tsx` 中的初始化流程,按优先级分阶段加载服务 3. **药品功能改进**: - 优化语音识别交互(实时预览、可取消) - Widget 增加 URL scheme 支持 4. **路由配置**: - 新增药品管理路由常量 ## 提交信息类型: - **主类型**:`feat` (新增睡眠监控功能) - **作用域**:`health` (健康相关功能) --- 请确认方案后,我将生成最终的 commit message。 --- **最终 Commit Message:** feat(health): 添加睡眠监控和通知服务,优化应用启动流程 - 新增睡眠监控服务,支持实时监听 HealthKit 睡眠数据更新 - 实现睡眠质量分析算法,计算睡眠评分和各阶段占比 - 新增睡眠通知服务,分析完成后自动推送质量评估和建议 - iOS 原生端实现睡眠数据观察者,支持后台数据传递 - 重构应用启动初始化流程,按优先级分阶段加载服务(关键/次要/后台/空闲) - 优化药品录入页面语音识别交互,支持实时预览和取消操作 - 药品 Widget 增加 deeplink 支持,点击跳转到应用 - 新增药品管理路由常量配置
191 lines
4.8 KiB
TypeScript
191 lines
4.8 KiB
TypeScript
/**
|
||
* 睡眠通知服务
|
||
*
|
||
* 负责在睡眠分析完成后发送通知,提供睡眠质量评估和建议
|
||
*/
|
||
|
||
import { logger } from '@/utils/logger';
|
||
import * as Notifications from 'expo-notifications';
|
||
import { SleepAnalysisData } from './sleepMonitor';
|
||
|
||
/**
|
||
* 分析睡眠数据并发送通知
|
||
*/
|
||
export async function analyzeSleepAndSendNotification(
|
||
analysis: SleepAnalysisData
|
||
): Promise<void> {
|
||
try {
|
||
logger.info('开始分析睡眠并发送通知:', {
|
||
score: analysis.sleepScore,
|
||
quality: analysis.quality,
|
||
duration: analysis.totalSleepHours,
|
||
});
|
||
|
||
// 构建通知内容
|
||
const notification = buildSleepNotification(analysis);
|
||
|
||
// 发送通知
|
||
await Notifications.scheduleNotificationAsync({
|
||
content: notification,
|
||
trigger: null, // 立即发送
|
||
});
|
||
|
||
logger.info('睡眠分析通知已发送');
|
||
} catch (error) {
|
||
logger.error('发送睡眠分析通知失败:', error);
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 构建睡眠通知内容
|
||
*/
|
||
function buildSleepNotification(analysis: SleepAnalysisData): Notifications.NotificationContentInput {
|
||
const { sleepScore, quality, totalSleepHours, sleepEfficiency } = analysis;
|
||
|
||
// 根据质量等级选择emoji和标题
|
||
const qualityConfig = getQualityConfig(quality);
|
||
|
||
// 构建通知标题
|
||
const title = `${qualityConfig.emoji} ${qualityConfig.title}`;
|
||
|
||
// 构建通知正文
|
||
const sleepDuration = formatSleepDuration(totalSleepHours);
|
||
const efficiencyText = `睡眠效率 ${sleepEfficiency.toFixed(0)}%`;
|
||
const body = `您昨晚睡了 ${sleepDuration},${efficiencyText}。评分:${sleepScore}分`;
|
||
|
||
// 获取建议
|
||
const suggestion = getSleepSuggestion(analysis);
|
||
|
||
return {
|
||
title,
|
||
body: `${body}\n${suggestion}`,
|
||
data: {
|
||
type: 'sleep_analysis',
|
||
score: sleepScore,
|
||
quality,
|
||
analysis: JSON.stringify(analysis),
|
||
url: '/sleep-detail', // 点击通知跳转到睡眠详情页
|
||
},
|
||
sound: 'default',
|
||
badge: 1,
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 获取质量配置
|
||
*/
|
||
function getQualityConfig(quality: string): {
|
||
emoji: string;
|
||
title: string;
|
||
} {
|
||
const configs = {
|
||
excellent: {
|
||
emoji: '😴',
|
||
title: '睡眠质量优秀',
|
||
},
|
||
good: {
|
||
emoji: '😊',
|
||
title: '睡眠质量良好',
|
||
},
|
||
fair: {
|
||
emoji: '😐',
|
||
title: '睡眠质量一般',
|
||
},
|
||
poor: {
|
||
emoji: '😟',
|
||
title: '睡眠质量较差',
|
||
},
|
||
very_poor: {
|
||
emoji: '😰',
|
||
title: '睡眠质量很差',
|
||
},
|
||
};
|
||
|
||
return configs[quality as keyof typeof configs] || {
|
||
emoji: '💤',
|
||
title: '睡眠分析完成',
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 格式化睡眠时长
|
||
*/
|
||
function formatSleepDuration(hours: number): string {
|
||
const h = Math.floor(hours);
|
||
const m = Math.round((hours - h) * 60);
|
||
|
||
if (m === 0) {
|
||
return `${h}小时`;
|
||
}
|
||
return `${h}小时${m}分钟`;
|
||
}
|
||
|
||
/**
|
||
* 获取睡眠建议
|
||
*/
|
||
function getSleepSuggestion(analysis: SleepAnalysisData): string {
|
||
const { quality, totalSleepHours, deepSleepPercentage, remSleepPercentage, sleepEfficiency } = analysis;
|
||
|
||
// 优秀或良好的睡眠
|
||
if (quality === 'excellent' || quality === 'good') {
|
||
const tips = [
|
||
'继续保持良好的睡眠习惯!',
|
||
'坚持规律作息,身体会感谢你!',
|
||
'优质睡眠让你精力充沛!',
|
||
];
|
||
return tips[Math.floor(Math.random() * tips.length)];
|
||
}
|
||
|
||
// 根据具体问题给出建议
|
||
const suggestions: string[] = [];
|
||
|
||
if (totalSleepHours < 7) {
|
||
suggestions.push('建议增加睡眠时间至7-9小时');
|
||
} else if (totalSleepHours > 9) {
|
||
suggestions.push('睡眠时间偏长,注意睡眠质量');
|
||
}
|
||
|
||
if (deepSleepPercentage < 13) {
|
||
suggestions.push('深度睡眠不足,睡前避免使用电子设备');
|
||
}
|
||
|
||
if (remSleepPercentage < 20) {
|
||
suggestions.push('REM睡眠不足,保持规律的作息时间');
|
||
}
|
||
|
||
if (sleepEfficiency < 85) {
|
||
suggestions.push('睡眠效率较低,改善睡眠环境');
|
||
}
|
||
|
||
// 如果有具体建议,返回第一条;否则返回通用建议
|
||
if (suggestions.length > 0) {
|
||
return `💡 ${suggestions[0]}`;
|
||
}
|
||
|
||
return '建议关注睡眠质量,保持良好作息';
|
||
}
|
||
|
||
/**
|
||
* 发送简单的睡眠提醒(用于测试)
|
||
*/
|
||
export async function sendSimpleSleepReminder(userName: string = '朋友'): Promise<void> {
|
||
try {
|
||
await Notifications.scheduleNotificationAsync({
|
||
content: {
|
||
title: '😴 睡眠质量分析',
|
||
body: `${userName},您的睡眠数据已更新,点击查看详细分析`,
|
||
data: {
|
||
type: 'sleep_reminder',
|
||
url: '/sleep-detail',
|
||
},
|
||
sound: 'default',
|
||
},
|
||
trigger: null,
|
||
});
|
||
|
||
logger.info('简单睡眠提醒已发送');
|
||
} catch (error) {
|
||
logger.error('发送简单睡眠提醒失败:', error);
|
||
}
|
||
} |