feat: 更新心情记录功能和界面

- 调整启动画面中的图片宽度,提升视觉效果
- 移除引导页面相关组件,简化应用结构
- 新增心情统计页面,支持用户查看和分析心情数据
- 优化心情卡片组件,增强用户交互体验
- 更新登录页面标题,提升品牌一致性
- 新增心情日历和编辑功能,支持用户记录和管理心情
This commit is contained in:
richarjiang
2025-08-21 17:59:22 +08:00
parent a7607e0f74
commit 72e75b602e
24 changed files with 2964 additions and 1238 deletions

View File

@@ -0,0 +1,199 @@
import { MoodCheckin, getMoodConfig } from '@/services/moodCheckins';
import dayjs from 'dayjs';
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
interface MoodHistoryCardProps {
moodCheckins: MoodCheckin[];
title?: string;
}
export function MoodHistoryCard({ moodCheckins, title = '心情记录' }: MoodHistoryCardProps) {
// 计算心情统计
const moodStats = React.useMemo(() => {
const stats = {
total: moodCheckins.length,
averageIntensity: 0,
moodDistribution: {} as Record<string, number>,
mostFrequentMood: '',
};
if (moodCheckins.length === 0) return stats;
// 计算平均强度
const totalIntensity = moodCheckins.reduce((sum, checkin) => sum + checkin.intensity, 0);
stats.averageIntensity = Math.round(totalIntensity / moodCheckins.length);
// 计算心情分布
moodCheckins.forEach(checkin => {
const moodLabel = getMoodConfig(checkin.moodType)?.label || checkin.moodType;
stats.moodDistribution[moodLabel] = (stats.moodDistribution[moodLabel] || 0) + 1;
});
// 找出最频繁的心情
const sortedMoods = Object.entries(stats.moodDistribution)
.sort(([, a], [, b]) => b - a);
stats.mostFrequentMood = sortedMoods[0]?.[0] || '';
return stats;
}, [moodCheckins]);
// 获取最近的心情记录
const recentMoods = moodCheckins
.sort((a, b) => dayjs(b.createdAt).valueOf() - dayjs(a.createdAt).valueOf())
.slice(0, 5);
return (
<View style={styles.container}>
<Text style={styles.title}>{title}</Text>
{moodCheckins.length === 0 ? (
<View style={styles.emptyState}>
<Text style={styles.emptyText}></Text>
</View>
) : (
<>
{/* 统计信息 */}
<View style={styles.statsContainer}>
<View style={styles.statItem}>
<Text style={styles.statValue}>{moodStats.total}</Text>
<Text style={styles.statLabel}></Text>
</View>
<View style={styles.statItem}>
<Text style={styles.statValue}>{moodStats.averageIntensity}</Text>
<Text style={styles.statLabel}></Text>
</View>
<View style={styles.statItem}>
<Text style={styles.statValue}>{moodStats.mostFrequentMood}</Text>
<Text style={styles.statLabel}></Text>
</View>
</View>
{/* 最近记录 */}
<View style={styles.recentContainer}>
<Text style={styles.sectionTitle}></Text>
{recentMoods.map((checkin, index) => {
const moodConfig = getMoodConfig(checkin.moodType);
return (
<View key={checkin.id} style={styles.moodItem}>
<View style={styles.moodInfo}>
<Text style={styles.moodEmoji}>{moodConfig?.emoji}</Text>
<View style={styles.moodDetails}>
<Text style={styles.moodLabel}>{moodConfig?.label}</Text>
<Text style={styles.moodDate}>
{dayjs(checkin.createdAt).format('MM月DD日 HH:mm')}
</Text>
</View>
</View>
<View style={styles.moodIntensity}>
<Text style={styles.intensityText}> {checkin.intensity}</Text>
</View>
</View>
);
})}
</View>
</>
)}
</View>
);
}
const styles = StyleSheet.create({
container: {
backgroundColor: '#FFFFFF',
borderRadius: 16,
padding: 16,
marginBottom: 16,
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.1,
shadowRadius: 3.84,
elevation: 5,
},
title: {
fontSize: 18,
fontWeight: '600',
color: '#192126',
marginBottom: 16,
},
emptyState: {
alignItems: 'center',
paddingVertical: 32,
},
emptyText: {
fontSize: 14,
color: '#9CA3AF',
fontStyle: 'italic',
},
statsContainer: {
flexDirection: 'row',
justifyContent: 'space-around',
marginBottom: 20,
paddingVertical: 16,
backgroundColor: '#F8F9FA',
borderRadius: 12,
},
statItem: {
alignItems: 'center',
},
statValue: {
fontSize: 20,
fontWeight: '700',
color: '#192126',
marginBottom: 4,
},
statLabel: {
fontSize: 12,
color: '#6B7280',
},
recentContainer: {
marginTop: 8,
},
sectionTitle: {
fontSize: 16,
fontWeight: '600',
color: '#192126',
marginBottom: 12,
},
moodItem: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
paddingVertical: 8,
borderBottomWidth: 1,
borderBottomColor: '#F3F4F6',
},
moodInfo: {
flexDirection: 'row',
alignItems: 'center',
flex: 1,
},
moodEmoji: {
fontSize: 20,
marginRight: 12,
},
moodDetails: {
flex: 1,
},
moodLabel: {
fontSize: 14,
fontWeight: '500',
color: '#192126',
marginBottom: 2,
},
moodDate: {
fontSize: 12,
color: '#6B7280',
},
moodIntensity: {
alignItems: 'flex-end',
},
intensityText: {
fontSize: 12,
color: '#6B7280',
fontWeight: '500',
},
});