Files
digital-pilates/utils/notificationHelpers.ts

1064 lines
34 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import * as Notifications from 'expo-notifications';
import { NotificationData, NotificationTypes, notificationService } from '../services/notifications';
import { getNotificationEnabled } from './userPreferences';
/**
* 构建 coach 页面的深度链接
*/
export function buildCoachDeepLink(params: {
action?: 'diet' | 'weight' | 'mood' | 'workout';
subAction?: 'record' | 'photo' | 'text' | 'card';
meal?: 'breakfast' | 'lunch' | 'dinner' | 'snack';
message?: string;
}): string {
const baseUrl = '/coach';
const searchParams = new URLSearchParams();
if (params.action) searchParams.set('action', params.action);
if (params.subAction) searchParams.set('subAction', params.subAction);
if (params.meal) searchParams.set('meal', params.meal);
if (params.message) searchParams.set('message', encodeURIComponent(params.message));
const queryString = searchParams.toString();
return queryString ? `${baseUrl}?${queryString}` : baseUrl;
}
/**
* 运动相关的通知辅助函数
*/
export class WorkoutNotificationHelpers {
/**
* 发送运动开始提醒
*/
static async sendWorkoutStartReminder(userName: string) {
return notificationService.sendImmediateNotification({
title: '运动时间到',
body: `${userName},该开始今天的普拉提训练了!`,
data: { type: 'workout_start' },
sound: true,
priority: 'high',
});
}
/**
* 发送运动完成通知
*/
static async sendWorkoutCompleteNotification(userName: string, duration: number) {
return notificationService.sendImmediateNotification({
title: '运动完成',
body: `${userName},恭喜您完成了${duration}分钟的训练!`,
data: { type: 'workout_complete' },
sound: true,
priority: 'normal',
});
}
/**
* 安排每日运动提醒
*/
static async scheduleDailyWorkoutReminder(userName: string, hour: number = 9, minute: number = 0) {
const reminderTime = new Date();
reminderTime.setHours(hour, minute, 0, 0);
// 如果今天的时间已经过了,设置为明天
if (reminderTime.getTime() <= Date.now()) {
reminderTime.setDate(reminderTime.getDate() + 1);
}
return notificationService.scheduleRepeatingNotification(
{
title: '每日运动提醒',
body: `${userName},该开始今天的普拉提训练了!`,
data: { type: 'daily_workout_reminder' },
sound: true,
priority: 'high',
},
{ days: 1 }
);
}
}
// GoalNotificationHelpers 类已删除,因为目标功能已移除
export class ChallengeNotificationHelpers {
static buildChallengesTabUrl(): string {
return '/(tabs)/challenges';
}
static async sendEncouragementNotification(params: {
userName: string;
challengeTitle: string;
challengeId: string;
}): Promise<string> {
const { userName, challengeTitle, challengeId } = params;
const notification: NotificationData = {
title: '挑战提醒',
body: `${userName},今天还没有完成「${challengeTitle}」挑战,快来打卡吧!`,
data: {
type: NotificationTypes.CHALLENGE_ENCOURAGEMENT,
challengeId,
url: ChallengeNotificationHelpers.buildChallengesTabUrl(),
},
sound: true,
priority: 'high',
};
return notificationService.sendImmediateNotification(notification);
}
}
/**
* 营养相关的通知辅助函数
*/
export class NutritionNotificationHelpers {
/**
* 发送营养记录提醒
*/
static async sendNutritionRecordReminder(userName: string) {
return notificationService.sendImmediateNotification({
title: '营养记录',
body: `${userName},记得记录今天的饮食情况`,
data: { type: 'nutrition_record_reminder' },
sound: true,
priority: 'normal',
});
}
/**
* 安排每日午餐提醒
* @param userName 用户名
* @param hour 小时 (默认12点)
* @param minute 分钟 (默认0分)
* @returns 通知ID
*/
static async scheduleDailyLunchReminder(
userName: string,
hour: number = 12,
minute: number = 0
): Promise<string | null> {
try {
// 检查是否已经存在午餐提醒
const existingNotifications = await notificationService.getAllScheduledNotifications();
const existingLunchReminder = existingNotifications.find(
notification =>
notification.content.data?.type === 'lunch_reminder' &&
notification.content.data?.isDailyReminder === true
);
if (existingLunchReminder) {
console.log('午餐提醒已存在,跳过重复注册:', existingLunchReminder.identifier);
return existingLunchReminder.identifier;
}
// 构建跳转到 coach 页面的深度链接
const coachUrl = buildCoachDeepLink({
action: 'diet',
subAction: 'card',
meal: 'lunch'
});
// 创建午餐提醒通知
const notificationId = await notificationService.scheduleCalendarRepeatingNotification(
{
title: '午餐记录提醒',
body: `${userName},记得记录今天的午餐情况哦!`,
data: {
type: 'lunch_reminder',
isDailyReminder: true,
meal: '午餐',
url: coachUrl // 添加深度链接
},
sound: true,
priority: 'normal',
},
{
type: Notifications.SchedulableTriggerInputTypes.DAILY,
hour: hour,
minute: minute,
}
);
console.log('每日午餐提醒已安排ID:', notificationId);
return notificationId;
} catch (error) {
console.error('安排每日午餐提醒失败:', error);
throw error;
}
}
/**
* 安排每日晚餐提醒
* @param userName 用户名
* @param hour 小时 (默认18点)
* @param minute 分钟 (默认0分)
* @returns 通知ID
*/
static async scheduleDailyDinnerReminder(
userName: string,
hour: number = 18,
minute: number = 0
): Promise<string | null> {
try {
// 检查是否已经存在晚餐提醒
const existingNotifications = await notificationService.getAllScheduledNotifications();
const existingDinnerReminder = existingNotifications.find(
notification =>
notification.content.data?.type === 'dinner_reminder' &&
notification.content.data?.isDailyReminder === true
);
if (existingDinnerReminder) {
console.log('晚餐提醒已存在,跳过重复注册:', existingDinnerReminder.identifier);
return existingDinnerReminder.identifier;
}
// 创建晚餐提醒通知
const notificationId = await notificationService.scheduleCalendarRepeatingNotification(
{
title: '🍽️ 晚餐时光到啦!',
body: `${userName},美好的晚餐时光开始了~记得记录今天的晚餐哦!营养均衡很重要呢 💪`,
data: {
type: 'dinner_reminder',
isDailyReminder: true,
meal: '晚餐',
url: '/nutrition/records' // 直接跳转到营养记录页面
},
sound: true,
priority: 'normal',
},
{
type: Notifications.SchedulableTriggerInputTypes.DAILY,
hour: hour,
minute: minute,
}
);
console.log('每日晚餐提醒已安排ID:', notificationId);
return notificationId;
} catch (error) {
console.error('安排每日晚餐提醒失败:', error);
throw error;
}
}
/**
* 取消晚餐提醒
*/
static async cancelDinnerReminder(): Promise<void> {
try {
const notifications = await notificationService.getAllScheduledNotifications();
for (const notification of notifications) {
if (notification.content.data?.type === 'dinner_reminder' &&
notification.content.data?.isDailyReminder === true) {
await notificationService.cancelNotification(notification.identifier);
console.log('已取消晚餐提醒:', notification.identifier);
}
}
} catch (error) {
console.error('取消晚餐提醒失败:', error);
throw error;
}
}
/**
* 安排营养记录提醒
*/
static async scheduleNutritionReminders(userName: string) {
// 安排三餐提醒
const mealTimes = [
{ hour: 8, minute: 0, meal: '早餐' },
{ hour: 12, minute: 0, meal: '午餐' },
{ hour: 18, minute: 0, meal: '晚餐' },
];
const notifications = [];
for (const mealTime of mealTimes) {
const reminderTime = new Date();
reminderTime.setHours(mealTime.hour, mealTime.minute, 0, 0);
// 如果今天的时间已经过了,设置为明天
if (reminderTime.getTime() <= Date.now()) {
reminderTime.setDate(reminderTime.getDate() + 1);
}
// 构建深度链接
const mealTypeMap: Record<string, string> = {
'早餐': 'breakfast',
'午餐': 'lunch',
'晚餐': 'dinner'
};
const coachUrl = buildCoachDeepLink({
action: 'diet',
subAction: 'card',
meal: mealTypeMap[mealTime.meal] as 'breakfast' | 'lunch' | 'dinner'
});
const notificationId = await notificationService.scheduleRepeatingNotification(
{
title: `${mealTime.meal}提醒`,
body: `${userName},记得记录您的${mealTime.meal}情况`,
data: {
type: 'meal_reminder',
meal: mealTime.meal,
url: coachUrl
},
sound: true,
priority: 'normal',
},
{ days: 1 }
);
notifications.push(notificationId);
}
return notifications;
}
}
/**
* 心情相关的通知辅助函数
*/
export class MoodNotificationHelpers {
/**
* 安排每日心情提醒
* @param userName 用户名
* @param hour 小时 (默认21点)
* @param minute 分钟 (默认0分)
* @returns 通知ID
*/
static async scheduleDailyMoodReminder(
userName: string,
hour: number = 21,
minute: number = 0
): Promise<string | null> {
try {
// 检查是否已经存在心情提醒
const existingNotifications = await notificationService.getAllScheduledNotifications();
const existingMoodReminder = existingNotifications.find(
notification =>
notification.content.data?.type === 'mood_reminder' &&
notification.content.data?.isDailyReminder === true
);
if (existingMoodReminder) {
console.log('心情提醒已存在,跳过重复注册:', existingMoodReminder.identifier);
return existingMoodReminder.identifier;
}
// 创建心情提醒通知
const notificationId = await notificationService.scheduleCalendarRepeatingNotification(
{
title: '🌙 今天过得怎么样呀?',
body: `${userName},夜深了~来记录一下今天的心情吧!每一份情感都值得被珍藏 ✨💕`,
data: {
type: 'mood_reminder',
isDailyReminder: true,
url: '/mood-statistics' // 跳转到心情统计页面
},
sound: true,
priority: 'normal',
},
{
type: Notifications.SchedulableTriggerInputTypes.DAILY,
hour: hour,
minute: minute,
}
);
console.log('每日心情提醒已安排ID:', notificationId);
return notificationId;
} catch (error) {
console.error('安排每日心情提醒失败:', error);
throw error;
}
}
/**
* 发送心情记录提醒
*/
static async sendMoodReminder(userName: string) {
return notificationService.sendImmediateNotification({
title: '🌙 今天过得怎么样呀?',
body: `${userName},夜深了~来记录一下今天的心情吧!每一份情感都值得被珍藏 ✨💕`,
data: {
type: 'mood_reminder',
url: '/mood-statistics'
},
sound: true,
priority: 'normal',
});
}
/**
* 取消心情提醒
*/
static async cancelMoodReminder(): Promise<void> {
try {
const notifications = await notificationService.getAllScheduledNotifications();
for (const notification of notifications) {
if (notification.content.data?.type === 'mood_reminder' &&
notification.content.data?.isDailyReminder === true) {
await notificationService.cancelNotification(notification.identifier);
console.log('已取消心情提醒:', notification.identifier);
}
}
} catch (error) {
console.error('取消心情提醒失败:', error);
throw error;
}
}
}
/**
* 喝水相关的通知辅助函数
*/
export class WaterNotificationHelpers {
/**
* 检查喝水目标完成情况并发送提醒
* @param userName 用户名
* @param todayStats 今日喝水统计数据
* @param currentHour 当前小时(用于时间限制检查)
* @returns 是否发送了通知
*/
static async checkWaterGoalAndNotify(
userName: string,
todayStats: { totalAmount: number; dailyGoal: number; completionRate: number },
currentHour: number = new Date().getHours()
): Promise<boolean> {
try {
// 检查时间限制早上9点以前和晚上9点以后不通知
if (currentHour < 9 || currentHour >= 23) {
console.log(`当前时间${currentHour}不在通知时间范围内9:00-21:00跳过喝水提醒`);
return false;
}
// 检查喝水目标是否已达成
if (todayStats.completionRate >= 100) {
console.log('喝水目标已达成,无需发送提醒');
return false;
}
// 检查是否在过去2小时内已经发送过喝水提醒避免重复打扰
const lastNotificationKey = '@last_water_notification';
const AsyncStorage = (await import('@/utils/kvStore')).default;
const lastNotificationTime = await AsyncStorage.getItem(lastNotificationKey);
const now = new Date().getTime();
const twoHoursAgo = now - (2 * 60 * 60 * 1000); // 2小时前
if (lastNotificationTime && parseInt(lastNotificationTime) > twoHoursAgo) {
console.log('2小时内已发送过喝水提醒跳过本次通知');
return false;
}
// 计算还需要喝多少水
const remainingAmount = todayStats.dailyGoal - todayStats.totalAmount;
const completionPercentage = Math.round(todayStats.completionRate);
// 根据完成度生成不同的提醒消息
let title = '💧 该喝水啦!';
let body = '';
if (completionPercentage < 30) {
// 完成度低于30%
const encouragingMessages = [
`${userName},今天才喝了${completionPercentage}%的水哦!还需要${Math.round(remainingAmount)}ml记得多补水身体会感谢您的💙`,
`${userName},水分补充进度${completionPercentage}%,再喝${Math.round(remainingAmount)}ml就更健康啦来一大杯清水吧🚰`,
`${userName},喝水进度才${completionPercentage}%呢~身体需要更多水分,还差${Math.round(remainingAmount)}ml一起加油`,
];
body = encouragingMessages[Math.floor(Math.random() * encouragingMessages.length)];
} else if (completionPercentage < 60) {
// 完成度30-60%
const moderateMessages = [
`${userName},喝水进度${completionPercentage}%,还需要${Math.round(remainingAmount)}ml哦保持这个节奏您做得很棒👍`,
`${userName},水分补充已完成${completionPercentage}%,再来${Math.round(remainingAmount)}ml就达标了继续保持💪`,
`${userName},今日饮水${completionPercentage}%完成!距离目标还有${Math.round(remainingAmount)}ml加把劲🌊`,
];
body = moderateMessages[Math.floor(Math.random() * moderateMessages.length)];
} else {
// 完成度60-99%
const almostDoneMessages = [
`${userName},喝水进度${completionPercentage}%,太棒了!最后${Math.round(remainingAmount)}ml就达成目标啦🎉`,
`${userName},已经完成${completionPercentage}%了!还有${Math.round(remainingAmount)}ml就成功了您很快就能达成今天的目标🏆`,
`${userName},水分补充进度${completionPercentage}%,就差最后一点点!再喝${Math.round(remainingAmount)}ml就胜利了🥳`,
];
body = almostDoneMessages[Math.floor(Math.random() * almostDoneMessages.length)];
}
// 发送通知
const notificationId = await notificationService.sendImmediateNotification({
title,
body,
data: {
type: 'water_reminder',
completionRate: completionPercentage,
remainingAmount: Math.round(remainingAmount),
dailyGoal: todayStats.dailyGoal,
currentAmount: todayStats.totalAmount,
url: '/statistics' // 跳转到统计页面查看详情
},
sound: true,
priority: 'normal',
});
// 记录通知发送时间
await AsyncStorage.setItem(lastNotificationKey, now.toString());
console.log(`喝水提醒通知已发送ID: ${notificationId},完成度: ${completionPercentage}%`);
return true;
} catch (error) {
console.error('检查喝水目标并发送通知失败:', error);
return false;
}
}
/**
* 发送立即喝水提醒
* @param userName 用户名
* @param message 自定义消息(可选)
*/
static async sendWaterReminder(userName: string, message?: string) {
const defaultMessage = `${userName},记得要多喝水哦!保持身体水分充足很重要~💧`;
return notificationService.sendImmediateNotification({
title: '💧 喝水提醒',
body: message || defaultMessage,
data: {
type: 'water_reminder',
url: '/statistics'
},
sound: true,
priority: 'normal',
});
}
/**
* 安排定期喝水提醒每2小时一次在9:00-21:00之间
* @param userName 用户名
* @returns 通知ID数组
*/
static async scheduleRegularWaterReminders(userName: string): Promise<string[]> {
try {
const notificationIds: string[] = [];
// 检查是否已经存在定期喝水提醒
const existingNotifications = await notificationService.getAllScheduledNotifications();
const existingWaterReminders = existingNotifications.filter(
notification =>
notification.content.data?.type === 'regular_water_reminder' &&
notification.content.data?.isRegularReminder === true
);
if (existingWaterReminders.length > 0) {
console.log('定期喝水提醒已存在,跳过重复注册');
return existingWaterReminders.map(n => n.identifier);
}
// 创建多个时间点的喝水提醒9:00-21:00每2小时一次
const reminderHours = [9, 11, 13, 15, 17, 19, 21];
for (const hour of reminderHours) {
const notificationId = await notificationService.scheduleCalendarRepeatingNotification(
{
title: '💧 定时喝水提醒',
body: `${userName},该喝水啦!记得补充水分,保持身体健康~`,
data: {
type: 'regular_water_reminder',
isRegularReminder: true,
reminderHour: hour,
url: '/statistics'
},
sound: true,
priority: 'normal',
},
{
type: Notifications.SchedulableTriggerInputTypes.DAILY,
hour: hour,
minute: 0,
}
);
notificationIds.push(notificationId);
console.log(`已安排${hour}:00的定期喝水提醒通知ID: ${notificationId}`);
}
console.log(`定期喝水提醒设置完成,共${notificationIds.length}个通知`);
return notificationIds;
} catch (error) {
console.error('设置定期喝水提醒失败:', error);
throw error;
}
}
/**
* 根据用户设置安排喝水提醒通知
* @param userName 用户名
* @param settings 喝水提醒设置
* @returns 通知ID数组
*/
static async scheduleCustomWaterReminders(
userName: string,
settings: {
enabled: boolean;
startTime: string; // 格式: "HH:mm"
endTime: string; // 格式: "HH:mm"
interval: number; // 分钟
}
): Promise<string[]> {
try {
const notificationIds: string[] = [];
// 如果不启用提醒,先取消所有提醒
if (!settings.enabled) {
await this.cancelAllWaterReminders();
return notificationIds;
}
// 先取消现有的喝水提醒
await this.cancelAllWaterReminders();
// 解析开始和结束时间
const [startHour, startMinute] = settings.startTime.split(':').map(Number);
const [endHour, endMinute] = settings.endTime.split(':').map(Number);
// 计算一天内所有的提醒时间点
const reminderTimes: { hour: number; minute: number }[] = [];
// 创建开始时间的 Date 对象
let currentTime = new Date();
currentTime.setHours(startHour, startMinute, 0, 0);
// 创建结束时间的 Date 对象
let endTime = new Date();
endTime.setHours(endHour, endMinute, 0, 0);
// 如果结束时间小于开始时间,说明跨天了,结束时间设为第二天
if (endTime <= currentTime) {
endTime.setDate(endTime.getDate() + 1);
}
// 生成所有的提醒时间点
while (currentTime < endTime) {
reminderTimes.push({
hour: currentTime.getHours(),
minute: currentTime.getMinutes(),
});
// 增加间隔时间
currentTime.setTime(currentTime.getTime() + settings.interval * 60 * 1000);
}
console.log(`计算出${reminderTimes.length}个喝水提醒时间点:`, reminderTimes);
// 为每个时间点创建重复通知
for (const time of reminderTimes) {
const notificationId = await notificationService.scheduleCalendarRepeatingNotification(
{
title: '💧 喝水时间到啦!',
body: `${userName},记得补充水分哦~保持身体健康!`,
data: {
type: 'custom_water_reminder',
isCustomReminder: true,
reminderHour: time.hour,
reminderMinute: time.minute,
url: '/statistics'
},
sound: true,
priority: 'normal',
},
{
type: Notifications.SchedulableTriggerInputTypes.DAILY,
hour: time.hour,
minute: time.minute,
}
);
notificationIds.push(notificationId);
console.log(`已安排${time.hour}:${String(time.minute).padStart(2, '0')}的喝水提醒通知ID: ${notificationId}`);
}
console.log(`自定义喝水提醒设置完成,共${notificationIds.length}个通知`);
return notificationIds;
} catch (error) {
console.error('设置自定义喝水提醒失败:', error);
throw error;
}
}
/**
* 取消所有喝水提醒
*/
static async cancelAllWaterReminders(): Promise<void> {
try {
const notifications = await notificationService.getAllScheduledNotifications();
for (const notification of notifications) {
if (notification.content.data?.type === 'water_reminder' ||
notification.content.data?.type === 'regular_water_reminder' ||
notification.content.data?.type === 'custom_water_reminder') {
await notificationService.cancelNotification(notification.identifier);
console.log('已取消喝水提醒:', notification.identifier);
}
}
} catch (error) {
console.error('取消喝水提醒失败:', error);
throw error;
}
}
}
/**
* 通用通知辅助函数
*/
export class GeneralNotificationHelpers {
/**
* 发送欢迎通知
*/
static async sendWelcomeNotification(userName: string) {
return notificationService.sendImmediateNotification({
title: '欢迎使用',
body: `${userName},欢迎来到普拉提世界!开始您的健康之旅吧`,
data: { type: 'welcome' },
sound: true,
priority: 'normal',
});
}
/**
* 发送成就通知
*/
static async sendAchievementNotification(userName: string, achievement: string) {
return notificationService.sendImmediateNotification({
title: '新成就',
body: `${userName},恭喜您获得了新成就:${achievement}`,
data: { type: 'achievement', achievement },
sound: true,
priority: 'high',
});
}
/**
* 发送系统维护通知
*/
static async sendMaintenanceNotification(message: string) {
return notificationService.sendImmediateNotification({
title: '系统通知',
body: message,
data: { type: 'maintenance' },
sound: true,
priority: 'high',
});
}
/**
* 取消特定类型的通知
*/
static async cancelNotificationsByType(type: string) {
const notifications = await notificationService.getAllScheduledNotifications();
for (const notification of notifications) {
if (notification.content.data?.type === type) {
await notificationService.cancelNotification(notification.identifier);
}
}
}
/**
* 批量发送通知
*/
static async sendBatchNotifications(notifications: NotificationData[]) {
const results = [];
for (const notification of notifications) {
try {
const id = await notificationService.sendImmediateNotification(notification);
results.push({ success: true, id, notification });
} catch (error) {
results.push({ success: false, error, notification });
}
}
return results;
}
}
/**
* 站立提醒通知助手
*/
export class StandReminderHelpers {
/**
* 检查站立状态并发送提醒通知
*/
static async checkStandStatusAndNotify(userName: string): Promise<boolean> {
try {
console.log('检查站立状态并发送提醒通知...');
// 动态导入健康工具,避免循环依赖
const { getCurrentHourStandStatus } = await import('@/utils/health');
// 获取当前小时站立状态
const standStatus = await getCurrentHourStandStatus();
console.log('当前站立状态:', standStatus);
// 如果已经站立过,不需要提醒
if (standStatus.hasStood) {
console.log('用户当前小时已经站立,无需提醒');
return false;
}
// 检查时间范围(工作时间内提醒,避免深夜或清晨打扰)
const currentHour = new Date().getHours();
if (currentHour < 9 || currentHour >= 22) {
console.log(`当前时间${currentHour}点,不在站立提醒时间范围内`);
return false;
}
// 检查是否启用了通知
if (!(await getNotificationEnabled())) {
console.log('用户未启用通知功能,跳过站立提醒');
return false;
}
// 生成提醒消息
const reminderMessage = this.generateStandReminderMessage(userName, standStatus.standHours, standStatus.standHoursGoal);
// 发送站立提醒通知
await notificationService.sendImmediateNotification({
title: '站立提醒',
body: reminderMessage,
data: {
type: 'stand_reminder',
currentStandHours: standStatus.standHours,
standHoursGoal: standStatus.standHoursGoal,
timestamp: Date.now()
},
sound: true,
priority: 'normal',
});
console.log('站立提醒通知发送成功');
return true;
} catch (error) {
console.error('检查站立状态并发送提醒失败:', error);
return false;
}
}
/**
* 生成站立提醒消息
*/
private static generateStandReminderMessage(userName: string, currentStandHours: number, goalHours: number): string {
const currentHour = new Date().getHours();
const progress = Math.round((currentStandHours / goalHours) * 100);
const messages = [
`${userName},该站起来活动一下了!当前已完成${progress}%的站立目标`,
`${userName},久坐伤身,起来走走吧~已站立${currentStandHours}/${goalHours}小时`,
`${userName},站立一会儿对健康有益,目前进度${currentStandHours}/${goalHours}小时`,
`${userName},记得起身活动哦!今日站立进度${progress}%`
];
// 根据时间选择不同的消息
const messageIndex = currentHour % messages.length;
return messages[messageIndex];
}
/**
* 取消所有站立提醒通知
*/
static async cancelStandReminders(): Promise<void> {
try {
await GeneralNotificationHelpers.cancelNotificationsByType('stand_reminder');
console.log('已取消所有站立提醒通知');
} catch (error) {
console.error('取消站立提醒通知失败:', error);
}
}
}
/**
* 通知模板
*/
export const NotificationTemplates = {
workout: {
start: (userName: string) => ({
title: '运动时间到',
body: `${userName},该开始今天的普拉提训练了!`,
data: { type: 'workout_start' },
sound: true,
priority: 'high' as const,
}),
complete: (userName: string, duration: number) => ({
title: '运动完成',
body: `${userName},恭喜您完成了${duration}分钟的训练!`,
data: { type: 'workout_complete' },
sound: true,
priority: 'normal' as const,
}),
},
goal: {
achievement: (userName: string, goalName: string) => ({
title: '目标达成',
body: `${userName},恭喜您达成了目标:${goalName}`,
data: { type: 'goal_achievement', goalName },
sound: true,
priority: 'high' as const,
}),
progress: (userName: string, goalName: string, progress: number) => ({
title: '目标进度',
body: `${userName},您的目标"${goalName}"已完成${progress}%`,
data: { type: 'goal_progress', goalName, progress },
sound: true,
priority: 'normal' as const,
}),
},
mood: {
reminder: (userName: string) => ({
title: '心情打卡',
body: `${userName},记得记录今天的心情状态哦`,
data: { type: 'mood_checkin_reminder' },
sound: true,
priority: 'normal' as const,
}),
},
nutrition: {
reminder: (userName: string, meal: string) => {
const mealTypeMap: Record<string, string> = {
'早餐': 'breakfast',
'午餐': 'lunch',
'晚餐': 'dinner',
'加餐': 'snack'
};
const coachUrl = buildCoachDeepLink({
action: 'diet',
subAction: 'card',
meal: mealTypeMap[meal] as 'breakfast' | 'lunch' | 'dinner' | 'snack'
});
return {
title: `${meal}提醒`,
body: `${userName},记得记录您的${meal}情况`,
data: {
type: 'meal_reminder',
meal,
url: coachUrl
},
sound: true,
priority: 'normal' as const,
};
},
lunch: (userName: string) => {
const coachUrl = buildCoachDeepLink({
action: 'diet',
subAction: 'card',
meal: 'lunch'
});
return {
title: '午餐记录提醒',
body: `${userName},记得记录今天的午餐情况哦!`,
data: {
type: 'lunch_reminder',
meal: '午餐',
url: coachUrl
},
sound: true,
priority: 'normal' as const,
};
},
},
water: {
reminder: (userName: string, completionRate: number, remainingAmount: number) => ({
title: '💧 该喝水啦!',
body: `${userName},今日喝水进度${completionRate}%,还需要${Math.round(remainingAmount)}ml记得补充水分`,
data: {
type: 'water_reminder',
completionRate,
remainingAmount: Math.round(remainingAmount),
url: '/statistics'
},
sound: true,
priority: 'normal' as const,
}),
regular: (userName: string) => ({
title: '💧 定时喝水提醒',
body: `${userName},该喝水啦!记得补充水分,保持身体健康~`,
data: {
type: 'regular_water_reminder',
url: '/statistics'
},
sound: true,
priority: 'normal' as const,
}),
achievement: (userName: string) => ({
title: '🎉 喝水目标达成!',
body: `${userName},恭喜您完成了今天的喝水目标!继续保持健康的饮水习惯~`,
data: {
type: 'water_achievement',
url: '/statistics'
},
sound: true,
priority: 'high' as const,
}),
},
dailySummary: {
reminder: (userName: string) => ({
title: '今日健康总结',
body: `${userName},来看看今天的健康生活总结吧~每一份记录都是成长的足迹!✨`,
data: {
type: 'daily_summary_reminder',
url: '/statistics'
},
sound: true,
priority: 'normal' as const,
}),
highCompletion: (userName: string, completedItems: string[]) => ({
title: '今天表现棒极了!',
body: `${userName},今天您${completedItems.join('、')},真的很棒!继续保持这样的好习惯!🌟`,
data: {
type: 'daily_summary',
completedItems,
url: '/statistics'
},
sound: true,
priority: 'normal' as const,
}),
mediumCompletion: (userName: string, completedItems: string[], encouragementItems: string[]) => ({
title: '今日健康小结',
body: `${userName},今天您${completedItems.join('、')},已经很不错了!明天记得关注一下${encouragementItems.join('、')},让健康生活更完整~`,
data: {
type: 'daily_summary',
completedItems,
encouragementItems,
url: '/statistics'
},
sound: true,
priority: 'normal' as const,
}),
lowCompletion: (userName: string, encouragementItems: string[]) => ({
title: '明天是新的开始',
body: `${userName},今天可能比较忙碌。明天记得关注${encouragementItems.slice(0, 2).join('和')},每一个小改变都是向健康生活迈进的一步~💪`,
data: {
type: 'daily_summary',
encouragementItems,
url: '/statistics'
},
sound: true,
priority: 'normal' as const,
}),
},
};