feat: 更新心情记录功能及相关组件

- 在心情日历中新增心情圆环展示,显示心情强度
- 修改心情记录编辑页面,支持使用图标替代表情
- 优化心情类型配置,使用图片资源替代原有表情
- 新增多种心情图标,丰富用户选择
- 更新相关样式,提升用户体验和界面美观性
- 更新文档,详细描述新功能和使用方法
This commit is contained in:
richarjiang
2025-08-25 09:33:54 +08:00
parent 23aa15f76e
commit 4f2d47c23f
17 changed files with 298 additions and 144 deletions

View File

@@ -8,6 +8,7 @@ import { useGlobalDialog } from '@/components/ui/DialogProvider';
import { Colors } from '@/constants/Colors';
import { TAB_BAR_BOTTOM_OFFSET, TAB_BAR_HEIGHT } from '@/constants/TabBar';
import { useAppDispatch, useAppSelector } from '@/hooks/redux';
import { useAuthGuard } from '@/hooks/useAuthGuard';
import { useColorScheme } from '@/hooks/useColorScheme';
import { clearErrors, createGoal } from '@/store/goalsSlice';
import { clearErrors as clearTaskErrors, fetchTasks, loadMoreTasks } from '@/store/tasksSlice';
@@ -18,7 +19,6 @@ import MaterialIcons from '@expo/vector-icons/MaterialIcons';
import { useFocusEffect } from '@react-navigation/native';
import dayjs from 'dayjs';
import { LinearGradient } from 'expo-linear-gradient';
import { useRouter } from 'expo-router';
import React, { useCallback, useEffect, useState } from 'react';
import { Alert, FlatList, Image, RefreshControl, SafeAreaView, StatusBar, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
@@ -26,7 +26,9 @@ export default function GoalsScreen() {
const theme = (useColorScheme() ?? 'light') as 'light' | 'dark';
const colorTokens = Colors[theme];
const dispatch = useAppDispatch();
const router = useRouter();
const { pushIfAuthedElseLogin, isLoggedIn } = useAuthGuard();
const { showConfirm } = useGlobalDialog();
// Redux状态
@@ -58,8 +60,11 @@ export default function GoalsScreen() {
useFocusEffect(
useCallback(() => {
console.log('useFocusEffect - loading tasks');
loadTasks();
checkAndShowGuide();
if (isLoggedIn) {
loadTasks();
checkAndShowGuide();
}
}, [dispatch])
);
@@ -147,10 +152,10 @@ export default function GoalsScreen() {
try {
await dispatch(createGoal(goalData)).unwrap();
setShowCreateModal(false);
// 获取用户名
const userName = userProfile?.name || '小海豹';
// 创建目标成功后,设置定时推送
try {
const notificationIds = await GoalNotificationHelpers.scheduleGoalNotifications(
@@ -165,13 +170,13 @@ export default function GoalsScreen() {
},
userName
);
console.log(`目标"${goalData.title}"的定时推送已创建通知ID`, notificationIds);
} catch (notificationError) {
console.error('创建目标定时推送失败:', notificationError);
// 通知创建失败不影响目标创建的成功
}
// 使用确认弹窗显示成功消息
showConfirm(
{
@@ -187,7 +192,7 @@ export default function GoalsScreen() {
console.log('用户确认了目标创建成功');
}
);
// 创建目标后重新加载任务列表
loadTasks();
} catch (error) {
@@ -199,7 +204,7 @@ export default function GoalsScreen() {
// 导航到任务列表页面
const handleNavigateToTasks = () => {
router.push('/task-list');
pushIfAuthedElseLogin('/task-list');
};
// 计算各状态的任务数量
@@ -213,7 +218,7 @@ export default function GoalsScreen() {
// 根据筛选条件过滤任务,并将已完成的任务放到最后
const filteredTasks = React.useMemo(() => {
let filtered: TaskListItem[] = [];
switch (selectedFilter) {
case 'pending':
filtered = tasks.filter(task => task.status === 'pending');
@@ -228,7 +233,7 @@ export default function GoalsScreen() {
filtered = tasks;
break;
}
// 对所有筛选结果进行排序:已完成的任务放到最后
return [...filtered].sort((a, b) => {
// 如果a已完成而b未完成a排在后面
@@ -271,7 +276,7 @@ export default function GoalsScreen() {
const renderEmptyState = () => {
let title = '暂无任务';
let subtitle = '创建目标后,系统会自动生成相应的任务';
if (selectedFilter === 'pending') {
title = '暂无待完成的任务';
subtitle = '当前没有待完成的任务';
@@ -282,7 +287,7 @@ export default function GoalsScreen() {
title = '暂无已跳过的任务';
subtitle = '跳过一些任务后,它们会显示在这里';
}
return (
<View style={styles.emptyState}>
<Image
@@ -349,19 +354,19 @@ export default function GoalsScreen() {
{/* 标题区域 */}
<View style={styles.header}>
<View>
<Text style={[styles.pageTitle, { color: '#FFFFFF' }]}>
</Text>
<Text style={[styles.pageTitle2, { color: '#FFFFFF' }]}>
</Text>
<Text style={[styles.pageTitle, { color: '#FFFFFF' }]}>
</Text>
<Text style={[styles.pageTitle2, { color: '#FFFFFF' }]}>
</Text>
</View>
</View>
{/* 任务进度卡片 */}
<View >
<TaskProgressCard
tasks={tasks}
<TaskProgressCard
tasks={tasks}
headerButtons={
<View style={styles.cardHeaderButtons}>
<TouchableOpacity
@@ -436,7 +441,7 @@ export default function GoalsScreen() {
{/* 开发测试按钮 */}
<GuideTestButton visible={__DEV__} />
{/* 目标通知测试按钮 */}
{__DEV__ && (
<TouchableOpacity