feat: 实现目标通知功能及相关组件
- 新增目标通知功能,支持根据用户创建目标时选择的频率和开始时间自动创建本地定时推送通知 - 实现每日、每周和每月的重复类型,用户可自定义选择提醒时间和重复规则 - 集成目标通知测试组件,方便开发者测试不同类型的通知 - 更新相关文档,详细描述目标通知功能的实现和使用方法 - 优化目标页面,确保用户体验和界面一致性
This commit is contained in:
@@ -13,6 +13,7 @@ import { clearErrors, createGoal } from '@/store/goalsSlice';
|
||||
import { clearErrors as clearTaskErrors, fetchTasks, loadMoreTasks } from '@/store/tasksSlice';
|
||||
import { CreateGoalRequest, TaskListItem } from '@/types/goals';
|
||||
import { checkGuideCompleted, markGuideCompleted } from '@/utils/guideHelpers';
|
||||
import { GoalNotificationHelpers } from '@/utils/notificationHelpers';
|
||||
import MaterialIcons from '@expo/vector-icons/MaterialIcons';
|
||||
import { useFocusEffect } from '@react-navigation/native';
|
||||
import dayjs from 'dayjs';
|
||||
@@ -45,6 +46,8 @@ export default function GoalsScreen() {
|
||||
createError
|
||||
} = useAppSelector((state) => state.goals);
|
||||
|
||||
const userProfile = useAppSelector((state) => state.user.profile);
|
||||
|
||||
const [showCreateModal, setShowCreateModal] = useState(false);
|
||||
const [refreshing, setRefreshing] = useState(false);
|
||||
const [selectedFilter, setSelectedFilter] = useState<TaskFilterType>('all');
|
||||
@@ -145,6 +148,30 @@ export default function GoalsScreen() {
|
||||
await dispatch(createGoal(goalData)).unwrap();
|
||||
setShowCreateModal(false);
|
||||
|
||||
// 获取用户名
|
||||
const userName = userProfile?.name || '小海豹';
|
||||
|
||||
// 创建目标成功后,设置定时推送
|
||||
try {
|
||||
const notificationIds = await GoalNotificationHelpers.scheduleGoalNotifications(
|
||||
{
|
||||
title: goalData.title,
|
||||
repeatType: goalData.repeatType,
|
||||
frequency: goalData.frequency,
|
||||
hasReminder: goalData.hasReminder,
|
||||
reminderTime: goalData.reminderTime,
|
||||
customRepeatRule: goalData.customRepeatRule,
|
||||
startTime: goalData.startTime,
|
||||
},
|
||||
userName
|
||||
);
|
||||
|
||||
console.log(`目标"${goalData.title}"的定时推送已创建,通知ID:`, notificationIds);
|
||||
} catch (notificationError) {
|
||||
console.error('创建目标定时推送失败:', notificationError);
|
||||
// 通知创建失败不影响目标创建的成功
|
||||
}
|
||||
|
||||
// 使用确认弹窗显示成功消息
|
||||
showConfirm(
|
||||
{
|
||||
@@ -389,6 +416,82 @@ export default function GoalsScreen() {
|
||||
|
||||
{/* 开发测试按钮 */}
|
||||
<GuideTestButton visible={__DEV__} />
|
||||
|
||||
{/* 目标通知测试按钮 */}
|
||||
{__DEV__ && (
|
||||
<TouchableOpacity
|
||||
style={styles.testButton}
|
||||
onPress={() => {
|
||||
// 这里可以导航到测试页面或显示测试弹窗
|
||||
Alert.alert(
|
||||
'目标通知测试',
|
||||
'选择要测试的通知类型',
|
||||
[
|
||||
{ text: '取消', style: 'cancel' },
|
||||
{
|
||||
text: '每日目标通知',
|
||||
onPress: async () => {
|
||||
try {
|
||||
const userName = userProfile?.name || '小海豹';
|
||||
const notificationIds = await GoalNotificationHelpers.scheduleGoalNotifications(
|
||||
{
|
||||
title: '每日运动目标',
|
||||
repeatType: 'daily',
|
||||
frequency: 1,
|
||||
hasReminder: true,
|
||||
reminderTime: '09:00',
|
||||
},
|
||||
userName
|
||||
);
|
||||
Alert.alert('成功', `每日目标通知已创建,ID: ${notificationIds.join(', ')}`);
|
||||
} catch (error) {
|
||||
Alert.alert('错误', `创建通知失败: ${error}`);
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
text: '每周目标通知',
|
||||
onPress: async () => {
|
||||
try {
|
||||
const userName = userProfile?.name || '小海豹';
|
||||
const notificationIds = await GoalNotificationHelpers.scheduleGoalNotifications(
|
||||
{
|
||||
title: '每周运动目标',
|
||||
repeatType: 'weekly',
|
||||
frequency: 1,
|
||||
hasReminder: true,
|
||||
reminderTime: '10:00',
|
||||
customRepeatRule: {
|
||||
weekdays: [1, 3, 5], // 周一、三、五
|
||||
},
|
||||
},
|
||||
userName
|
||||
);
|
||||
Alert.alert('成功', `每周目标通知已创建,ID: ${notificationIds.join(', ')}`);
|
||||
} catch (error) {
|
||||
Alert.alert('错误', `创建通知失败: ${error}`);
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
text: '目标达成通知',
|
||||
onPress: async () => {
|
||||
try {
|
||||
const userName = userProfile?.name || '小海豹';
|
||||
await GoalNotificationHelpers.sendGoalAchievementNotification(userName, '每日运动目标');
|
||||
Alert.alert('成功', '目标达成通知已发送');
|
||||
} catch (error) {
|
||||
Alert.alert('错误', `发送通知失败: ${error}`);
|
||||
}
|
||||
}
|
||||
},
|
||||
]
|
||||
);
|
||||
}}
|
||||
>
|
||||
<Text style={styles.testButtonText}>测试通知</Text>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
);
|
||||
@@ -567,4 +670,19 @@ const styles = StyleSheet.create({
|
||||
fontWeight: '600',
|
||||
lineHeight: 18,
|
||||
},
|
||||
testButton: {
|
||||
position: 'absolute',
|
||||
top: 100,
|
||||
right: 20,
|
||||
backgroundColor: '#10B981',
|
||||
paddingHorizontal: 12,
|
||||
paddingVertical: 8,
|
||||
borderRadius: 8,
|
||||
zIndex: 1000,
|
||||
},
|
||||
testButtonText: {
|
||||
color: '#FFFFFF',
|
||||
fontSize: 12,
|
||||
fontWeight: '600',
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user