feat(background-task): 完善iOS后台任务系统并优化断食通知和UI体验

- 修复iOS后台任务注册时机问题,确保任务能正常触发
- 添加后台任务调试辅助工具和完整测试指南
- 优化断食通知系统,增加防抖机制避免频繁重调度
- 改进断食自动续订逻辑,使用固定时间而非相对时间计算
- 优化统计页面布局,添加身体指标section标题
- 增强饮水详情页面视觉效果,改进卡片样式和配色
- 添加用户反馈入口到个人设置页面
- 完善锻炼摘要卡片条件渲染逻辑
- 增强日志记录和错误处理机制

这些改进显著提升了应用的稳定性、性能和用户体验,特别是在iOS后台任务执行和断食功能方面。
This commit is contained in:
richarjiang
2025-11-05 11:23:33 +08:00
parent d74046498d
commit ea22901553
12 changed files with 1060 additions and 171 deletions

View File

@@ -243,6 +243,7 @@ const WaterDetail: React.FC<WaterDetailProps> = () => {
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f3f4fb',
},
gradientBackground: {
position: 'absolute',
@@ -253,23 +254,23 @@ const styles = StyleSheet.create({
},
decorativeCircle1: {
position: 'absolute',
top: 40,
right: 20,
width: 60,
height: 60,
borderRadius: 30,
backgroundColor: '#0EA5E9',
opacity: 0.1,
top: 80,
right: 30,
width: 80,
height: 80,
borderRadius: 40,
backgroundColor: '#4F5BD5',
opacity: 0.08,
},
decorativeCircle2: {
position: 'absolute',
bottom: -15,
left: -15,
width: 40,
height: 40,
borderRadius: 20,
backgroundColor: '#0EA5E9',
opacity: 0.05,
bottom: 100,
left: -20,
width: 60,
height: 60,
borderRadius: 30,
backgroundColor: '#4F5BD5',
opacity: 0.06,
},
keyboardAvoidingView: {
flex: 1,
@@ -278,44 +279,49 @@ const styles = StyleSheet.create({
flex: 1,
},
scrollContent: {
padding: 20,
paddingHorizontal: 24,
paddingTop: 20,
},
section: {
marginBottom: 32,
marginBottom: 36,
},
sectionTitle: {
fontSize: 16,
fontWeight: '500',
marginBottom: 20,
fontSize: 20,
fontWeight: '700',
marginBottom: 24,
letterSpacing: -0.5,
color: '#1c1f3a',
},
subsectionTitle: {
fontSize: 14,
fontWeight: '500',
marginBottom: 12,
fontSize: 16,
fontWeight: '600',
marginBottom: 16,
letterSpacing: -0.3,
color: '#1c1f3a',
},
sectionSubtitle: {
fontSize: 12,
fontWeight: '400',
lineHeight: 18,
fontSize: 14,
fontWeight: '500',
lineHeight: 20,
color: '#6f7ba7',
},
// 饮水记录相关样式
recordsList: {
gap: 12,
gap: 16,
},
recordCardContainer: {
// iOS 阴影效果
shadowColor: '#000000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.08,
shadowRadius: 4,
// iOS 阴影效果 - 增强阴影效果
shadowColor: 'rgba(30, 41, 59, 0.18)',
shadowOffset: { width: 0, height: 8 },
shadowOpacity: 0.16,
shadowRadius: 16,
// Android 阴影效果
elevation: 2,
elevation: 6,
},
recordCard: {
borderRadius: 12,
padding: 10,
borderRadius: 20,
padding: 18,
backgroundColor: '#ffffff',
},
recordMainContent: {
flexDirection: 'row',
@@ -323,44 +329,47 @@ const styles = StyleSheet.create({
justifyContent: 'space-between',
},
recordIconContainer: {
width: 40,
height: 40,
borderRadius: 10,
width: 48,
height: 48,
borderRadius: 16,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'rgba(79, 91, 213, 0.08)',
},
recordIcon: {
width: 20,
height: 20,
width: 24,
height: 24,
},
recordInfo: {
flex: 1,
marginLeft: 12,
marginLeft: 16,
},
recordLabel: {
fontSize: 16,
fontWeight: '600',
marginBottom: 8,
fontSize: 17,
fontWeight: '700',
color: '#1c1f3a',
marginBottom: 6,
},
recordTimeContainer: {
flexDirection: 'row',
alignItems: 'center',
gap: 4,
gap: 6,
},
recordAmountContainer: {
alignItems: 'flex-end',
},
recordAmount: {
fontSize: 14,
fontWeight: '500',
fontSize: 18,
fontWeight: '700',
color: '#4F5BD5',
},
deleteSwipeButton: {
backgroundColor: '#EF4444',
justifyContent: 'center',
alignItems: 'center',
width: 80,
borderRadius: 12,
marginLeft: 8,
borderRadius: 16,
marginLeft: 12,
},
deleteSwipeButtonText: {
color: '#FFFFFF',
@@ -369,47 +378,61 @@ const styles = StyleSheet.create({
marginTop: 4,
},
recordTimeText: {
fontSize: 12,
fontWeight: '400',
fontSize: 13,
fontWeight: '500',
color: '#6f7ba7',
},
recordNote: {
marginTop: 8,
marginTop: 12,
padding: 12,
backgroundColor: 'rgba(79, 91, 213, 0.04)',
borderRadius: 12,
fontSize: 14,
fontStyle: 'italic',
fontStyle: 'normal',
lineHeight: 20,
color: '#5f6a97',
},
recordsSummary: {
marginTop: 20,
padding: 16,
borderRadius: 12,
marginTop: 24,
padding: 20,
borderRadius: 20,
backgroundColor: '#ffffff',
shadowColor: 'rgba(30, 41, 59, 0.12)',
shadowOpacity: 0.16,
shadowRadius: 18,
shadowOffset: { width: 0, height: 10 },
elevation: 6,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
},
summaryText: {
fontSize: 12,
fontWeight: '500',
fontSize: 16,
fontWeight: '700',
color: '#1c1f3a',
},
summaryGoal: {
fontSize: 12,
fontWeight: '500',
fontSize: 14,
fontWeight: '600',
color: '#6f7ba7',
},
noRecordsContainer: {
alignItems: 'center',
justifyContent: 'center',
paddingVertical: 40,
gap: 16,
paddingVertical: 60,
gap: 20,
},
noRecordsText: {
fontSize: 15,
fontWeight: '500',
lineHeight: 20,
fontSize: 17,
fontWeight: '600',
lineHeight: 24,
color: '#6f7ba7',
},
noRecordsSubText: {
fontSize: 13,
fontSize: 14,
textAlign: 'center',
lineHeight: 18,
opacity: 0.7,
lineHeight: 20,
color: '#9ba3c7',
},
modalBackdrop: {
...StyleSheet.absoluteFillObject,
@@ -476,10 +499,14 @@ const styles = StyleSheet.create({
// color will be set dynamically
},
settingsButton: {
width: 32,
height: 32,
width: 40,
height: 40,
alignItems: 'center',
justifyContent: 'center',
borderRadius: 20,
backgroundColor: 'rgba(255, 255, 255, 0.24)',
borderWidth: 1,
borderColor: 'rgba(255, 255, 255, 0.45)',
},
settingsModalSheet: {
position: 'absolute',