feat(fasting): 新增轻断食功能模块

新增完整的轻断食功能,包括:
- 断食计划列表和详情页面,支持12-12、14-10、16-8、18-6四种计划
- 断食状态实时追踪和倒计时显示
- 自定义开始时间选择器
- 断食通知提醒功能
- Redux状态管理和数据持久化
- 新增tab导航入口和路由配置
This commit is contained in:
richarjiang
2025-10-13 19:21:29 +08:00
parent 971aebd560
commit e03b2b3032
17 changed files with 2390 additions and 7 deletions

206
constants/Fasting.ts Normal file
View File

@@ -0,0 +1,206 @@
import dayjs from 'dayjs';
export type FastingDifficulty = '新手' | '进阶' | '强化';
export type FastingPlan = {
id: string;
title: string;
subtitle: string;
badge?: string;
difficulty: FastingDifficulty;
fastingHours: number;
eatingHours: number;
recommendedStartHour: number;
recommendedStartMinute?: number;
description: string;
highlights: string[];
audienceFit: string[];
audienceAvoid: string[];
nutritionTips: string[];
theme: {
backdrop: string;
accent: string;
accentSecondary: string;
ringTrack: string;
ringProgress: string;
};
};
export const FASTING_STORAGE_KEYS = {
preferredPlanId: '@fasting_preferred_plan',
notificationsRegistered: '@fasting_notifications_registered',
startNotificationId: '@fasting_notification_start_id',
endNotificationId: '@fasting_notification_end_id',
} as const;
export const FASTING_PLANS: FastingPlan[] = [
{
id: '12-12',
title: '12-12 新手体验计划',
subtitle: '进食12小时 · 断食12小时',
badge: '新手',
difficulty: '新手',
fastingHours: 12,
eatingHours: 12,
recommendedStartHour: 20,
description: '帮助初次尝试轻断食的用户建立稳定节奏,温和过渡到代谢切换。',
highlights: [
'维持血糖稳定,减少夜间加餐',
'保护基础代谢率,循序渐进更易坚持',
'适合与轻度有氧、舒缓训练搭配',
],
audienceFit: [
'没有断食经验的初学者',
'作息规律、希望改善饮食结构的用户',
'需要缓解水肿或控制晚间进食的群体',
],
audienceAvoid: [
'孕期、哺乳期人群',
'血糖波动较大或正在服用降糖药者',
'近期有胃病或严重胃酸倒流史者',
],
nutritionTips: [
'进食期优先安排高纤维蔬菜 + 优质蛋白 + 复杂碳水搭配',
'保持足量饮水,可搭配无糖茶饮、电解质水',
'睡前2小时避免高糖、高脂肪食物降低夜间胃酸',
],
theme: {
backdrop: '#EEF5E3',
accent: '#99B75F',
accentSecondary: '#F6F7ED',
ringTrack: 'rgba(153, 183, 95, 0.18)',
ringProgress: '#9FBB62',
},
},
{
id: '14-10',
title: '14-10 轻断食计划',
subtitle: '进食10小时 · 断食14小时',
badge: '热门',
difficulty: '新手',
fastingHours: 14,
eatingHours: 10,
recommendedStartHour: 19,
description: '黄金入门比例,兼顾脂肪代谢与日常社交,适合作为长期饮食模式。',
highlights: [
'夜间空腹时长更长,有利于提高睡眠质量',
'降低胰岛素分泌频率,优化血脂指标',
'搭配力量训练,可提升瘦体重占比',
],
audienceFit: [
'需要控制体脂、保持肌力的办公人群',
'晚餐时间较固定的家庭用户',
'希望巩固作息、减少夜宵的用户',
],
audienceAvoid: [
'体重过低 (BMI < 18.5) 或营养不良者',
'高强度训练日需额外摄入能量的运动员',
'正在恢复期的慢性病患者(需医师评估)',
],
nutritionTips: [
'进食窗口内保持 3 餐或 2 餐 1 加餐的均衡结构',
'早餐建议加入优质蛋白与低 GI 碳水,避免血糖波动',
'断食期可饮用黑咖啡、无糖茶饮,补充矿物质避免疲劳',
],
theme: {
backdrop: '#F8F2DD',
accent: '#E4B74B',
accentSecondary: '#FBF5E2',
ringTrack: 'rgba(228, 183, 75, 0.18)',
ringProgress: '#E8B649',
},
},
{
id: '16-8',
title: '16-8 进阶燃脂计划',
subtitle: '进食8小时 · 断食16小时',
badge: '进阶',
difficulty: '进阶',
fastingHours: 16,
eatingHours: 8,
recommendedStartHour: 18,
description: '经典进阶版,帮助维持较长脂肪供能区间,适合已有断食基础的用户。',
highlights: [
'延长生长激素分泌窗口,辅助保持肌肉',
'强化脂肪动员,改善胰岛素敏感性',
'与力量训练、HIIT 等组合,塑形效率更高',
],
audienceFit: [
'有一定断食经验,希望进一步控制体脂',
'每日有规律运动或力量训练基础的用户',
'午晚餐可在 12:00-20:00 完成的职场人士',
],
audienceAvoid: [
'近期有暴饮暴食或进食障碍史者',
'工作强度大且需要夜间补充能量的岗位',
'肝胆问题或血糖控制异常者需遵医嘱执行',
],
nutritionTips: [
'进食期注意蛋白质分配,建议每餐 ≥25g 蛋白',
'提前准备低油低糖食谱,避免进食窗口暴食',
'断食期补充电解质与维生素C缓解疲劳与饥饿感',
],
theme: {
backdrop: '#EFE8FD',
accent: '#8E75E1',
accentSecondary: '#F4EDFF',
ringTrack: 'rgba(142, 117, 225, 0.18)',
ringProgress: '#8F78E0',
},
},
{
id: '18-6',
title: '18-6 脂代强化计划',
subtitle: '进食6小时 · 断食18小时',
badge: '高阶',
difficulty: '强化',
fastingHours: 18,
eatingHours: 6,
recommendedStartHour: 17,
description: '针对塑形巩固与体重停滞期用户,提供高强度代谢刺激方案。',
highlights: [
'强化脂肪氧化,提升线粒体效率',
'帮助突破减脂平台期,维持血脂稳态',
'适合与周期力量训练、冷热交替等手段配合',
],
audienceFit: [
'已有 8 周以上断食经验且生理指标稳定者',
'体重调节遇到平台期的进阶用户',
'可在 10:30-16:30 内完成主要餐食的用户',
],
audienceAvoid: [
'甲状腺功能异常或血糖控制不佳者',
'夜班、倒班等作息紊乱人群',
'有过度节食史或需要高能量摄入的用户',
],
nutritionTips: [
'确保进食窗口内能量充足,搭配足量优质脂肪与蛋白',
'安排训练前后加餐,保障恢复与肌肉合成',
'断食期适量补充电解质、绿叶蔬菜汁,避免头晕疲劳',
],
theme: {
backdrop: '#F7E3E5',
accent: '#E26A7F',
accentSecondary: '#FCE9EC',
ringTrack: 'rgba(226, 106, 127, 0.18)',
ringProgress: '#E06B80',
},
},
];
export const getPlanById = (planId: string) =>
FASTING_PLANS.find((plan) => plan.id === planId);
export const getRecommendedStart = (plan: FastingPlan, baseDate: Date = new Date()) => {
const start = dayjs(baseDate)
.hour(plan.recommendedStartHour)
.minute(plan.recommendedStartMinute ?? 0)
.second(0)
.millisecond(0);
// If the recommended time already passed today, schedule for tomorrow
if (start.isBefore(dayjs())) {
return start.add(1, 'day').toDate();
}
return start.toDate();
};