Files
digital-pilates/docs/mood-calendar-refresh-fix.md
richarjiang 7d28b79d86 feat: 集成推送通知功能及相关组件
- 在项目中引入expo-notifications库,支持本地推送通知功能
- 实现通知权限管理,用户可选择开启或关闭通知
- 新增通知发送、定时通知和重复通知功能
- 更新个人页面,集成通知开关和权限请求逻辑
- 编写推送通知功能实现文档,详细描述功能和使用方法
- 优化心情日历页面,确保数据实时刷新
2025-08-22 22:00:05 +08:00

156 lines
5.0 KiB
Markdown
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.

# 心情日历数据实时刷新修复方案
## 问题描述
用户编辑或新建心情后,当天的心情数据没有实时更新,必须退出页面或切换日期再切换回来才会生效。
## 问题原因
1. **本地状态与 Redux 状态不同步**:心情日历页面使用本地状态 `moodRecords``selectedDateMood` 来管理数据,而不是直接使用 Redux store 中的数据。
2. **缺少页面焦点监听**:当用户从编辑页面返回时,没有监听页面焦点变化来刷新数据。
3. **数据流不一致**:编辑页面通过 Redux 更新数据,但日历页面没有监听这些变化。
## 修复方案
### 1. 迁移到 Redux 状态管理
**修改文件**: `app/mood/calendar.tsx`
#### 移除本地状态
```typescript
// 移除这些本地状态
const [selectedDateMood, setSelectedDateMood] = useState<any>(null);
const [moodRecords, setMoodRecords] = useState<Record<string, any[]>>({});
```
#### 使用 Redux 状态
```typescript
// 使用 Redux store 中的数据
const moodRecords = useAppSelector(state => state.mood.moodRecords);
// 获取选中日期的数据
const selectedDateString = selectedDay ? dayjs(currentMonth).date(selectedDay).format('YYYY-MM-DD') : null;
const selectedDateMood = selectedDateString ? useAppSelector(selectLatestMoodRecordByDate(selectedDateString)) : null;
```
### 2. 添加页面焦点监听
#### 导入 useFocusEffect
```typescript
import { router, useLocalSearchParams, useFocusEffect } from 'expo-router';
import React, { useEffect, useState, useCallback } from 'react';
```
#### 添加焦点监听器
```typescript
// 监听页面焦点变化,当从编辑页面返回时刷新数据
useFocusEffect(
useCallback(() => {
// 当页面获得焦点时,刷新当前月份的数据和选中日期的数据
const refreshData = async () => {
if (selectedDay) {
const selectedDateString = dayjs(currentMonth).date(selectedDay).format('YYYY-MM-DD');
await loadDailyMoodCheckins(selectedDateString);
}
await loadMonthMoodData(currentMonth);
};
refreshData();
}, [currentMonth, selectedDay, loadDailyMoodCheckins, loadMonthMoodData])
);
```
### 3. 简化数据加载逻辑
#### 移除手动状态更新
```typescript
// 加载选中日期的心情记录
const loadDailyMoodCheckins = async (dateString: string) => {
try {
await fetchMoodRecords(dateString);
// 不需要手动设置 selectedDateMood因为它现在从 Redux store 中获取
} catch (error) {
console.error('加载心情记录失败:', error);
}
};
```
#### 简化月份数据加载
```typescript
// 加载整个月份的心情数据
const loadMonthMoodData = async (targetMonth: Date) => {
try {
const startDate = dayjs(targetMonth).startOf('month').format('YYYY-MM-DD');
const endDate = dayjs(targetMonth).endOf('month').format('YYYY-MM-DD');
const historyData = await fetchMoodHistoryRecords({ startDate, endDate });
// 历史记录已经通过 fetchMoodHistoryRecords 自动存储到 Redux store 中
// 不需要额外的处理
} catch (error) {
console.error('加载月份心情数据失败:', error);
}
};
```
### 4. 更新心情图标渲染
#### 使用 Redux 数据渲染图标
```typescript
const renderMoodIcon = (day: number | null, isSelected: boolean) => {
if (!day) return null;
// 检查该日期是否有心情记录 - 现在从 Redux store 中获取
const dayDateString = dayjs(currentMonth).date(day).format('YYYY-MM-DD');
const dayRecords = moodRecords[dayDateString] || [];
const moodRecord = dayRecords.length > 0 ? dayRecords[0] : null;
if (moodRecord) {
const mood = moodOptions.find(m => m.type === moodRecord.moodType);
return (
<View style={[styles.moodIconContainer, { backgroundColor: mood?.color }]}>
<View style={styles.moodIcon}>
<Text style={styles.moodEmoji}>{mood?.emoji || '😊'}</Text>
</View>
</View>
);
}
return (
<View style={styles.defaultMoodIcon}>
<Text style={styles.defaultMoodEmoji}>😊</Text>
</View>
);
};
```
## 修复效果
### 修复前
- 用户编辑心情后,日历页面数据不更新
- 需要退出页面或切换日期才能看到变化
- 用户体验不佳
### 修复后
- 用户编辑心情后,日历页面数据立即更新
- 页面焦点变化时自动刷新数据
- 数据状态统一管理,避免不一致
## 技术要点
1. **统一状态管理**:所有心情数据都通过 Redux 管理,确保数据一致性。
2. **响应式更新**:使用 `useAppSelector` 监听 Redux 状态变化,自动更新 UI。
3. **页面焦点监听**:使用 `useFocusEffect` 监听页面焦点变化,确保从其他页面返回时数据是最新的。
4. **异步数据加载**:保持异步数据加载的性能优势,同时确保数据同步。
## 相关文件
- `app/mood/calendar.tsx` - 心情日历页面
- `app/mood/edit.tsx` - 心情编辑页面
- `store/moodSlice.ts` - 心情 Redux slice
- `hooks/useMoodData.ts` - 心情数据管理 hook