feat: 更新心情相关页面和组件

- 在心情统计、日历和编辑页面中引入 HeaderBar 组件,提升界面一致性和用户体验
- 移除冗余的头部视图代码,简化组件结构
- 更新心情日历和编辑页面的样式,使用新的颜色常量,增强视觉效果
- 优化心情统计页面的加载状态显示,提升用户交互体验
This commit is contained in:
richarjiang
2025-08-21 19:09:02 +08:00
parent 72e75b602e
commit 098c65b23e
9 changed files with 78 additions and 107 deletions

View File

@@ -198,49 +198,49 @@ export default function CoachScreen() {
{
condition: () => hour >= 5 && hour < 9,
messages: [
`${timeGreeting}${name}我是${botName}你的专属健康管理助手。新的一天开始了,让我们一起为你的健康目标努力吧!`,
`${timeGreeting}早晨是制定健康计划的最佳时机,我是${botName}可以帮你管理营养摄入、运动计划和生活作息。`,
`${timeGreeting}${name}作为你的Seal我很高兴能陪伴你的健康之旅。无论是饮食营养、健身锻炼还是生活管理我都能为你提供专业建议。`
`${timeGreeting}${name}🐳 我是你的小海豹${botName},新的一天开始啦!让我们一起游向健康目标吧~`,
`${timeGreeting}🌅 早晨的阳光真好呢,我是${botName}你的专属小海豹健康伙伴!要不要先制定今天的健康计划呢?`,
`${timeGreeting}${name}🐋 小海豹${botName}来报到啦!今天想从哪个方面开始我们的健康之旅呢?营养、运动还是生活管理,我都可以帮你哦~`
]
},
{
condition: () => hour >= 9 && hour < 12,
messages: [
`${timeGreeting}${name}我是${botName},你的智能健康顾问。上午是身体代谢最活跃的时候,有什么健康目标需要我帮你规划吗?`,
`${timeGreeting}!工作忙碌的上午,别忘了关注身体健康。我是${botName}可以为你提供营养建议运动指导和压力管理方案。`,
`${timeGreeting}${name}!作为你的健康伙伴${botName},我想说:每一个健康的选择都在塑造更好的你。今天想从哪个方面开始呢?`
`${timeGreeting}${name}🐳 上午是身体最活跃的时候呢,小海豹${botName}在这里为你加油!有什么健康目标需要我帮你规划吗?`,
`${timeGreeting}☀️ 工作忙碌的上午,别忘了给身体一些关爱哦~我是你的小海豹${botName}随时准备为你提供营养建议运动指导`,
`${timeGreeting}${name}🐋 作为你的小海豹伙伴${botName},我想说:每一个健康的选择都在让我们的身体更棒呢!今天想从哪个方面开始呢?`
]
},
{
condition: () => hour >= 12 && hour < 14,
messages: [
`${timeGreeting}${name}!午餐时间很关键呢,合理的营养搭配能为下午提供充足能量。我是${botName},可以为你分析饮食营养和热量管理。`,
`${timeGreeting}!忙碌的上午结束了,该关注一下身体需求啦。我是你的健康助手${botName},无论是饮食调整运动安排还是休息建议,都可以找我`,
`${timeGreeting}${name}午间是调整状态的好时机。作为你的Seal建议关注饮食均衡适度放松~`
`${timeGreeting}${name}🍽️ 午餐时间到啦!小海豹${botName}提醒你,合理的营养搭配能让下午充满能量哦~`,
`${timeGreeting}🌊 忙碌的上午结束了,该给身体补充能量啦!我是你的小海豹${botName},无论是饮食调整还是运动安排,都可以找我商量哦~`,
`${timeGreeting}${name}🐳 午间时光,小海豹${botName}建议关注饮食均衡,也要适度放松一下呢`
]
},
{
condition: () => hour >= 14 && hour < 18,
messages: [
`${timeGreeting}${name}!下午是身体活动的黄金时段,适合安排一些运动。我是${botName}可以为你制定个性化的健身计划和身材管理方案。`,
`${timeGreeting}!午后时光,正是关注整体健康的好时机我是你的健康管家${botName},从营养摄入到运动锻炼,我都能为你提供科学指导。`,
`${timeGreeting}${name}!下午时光,身心健康同样重要作为你的智能健康顾问${botName},我在这里支持你的每一个健康目标`
`${timeGreeting}${name}🌊 下午是动的黄金时段呢!小海豹${botName}可以为你制定个性化的健身计划,让我们一起游向更好的身材吧~`,
`${timeGreeting}🐋 午后时光,正是关注健康的好时机我是你的小海豹${botName},从营养到运动,我都能为你提供贴心指导哦~`,
`${timeGreeting}${name}🐳 下午时光,身心健康同样重要呢!作为你的小海豹${botName},我在这里支持你的每一个健康目标`
]
},
{
condition: () => hour >= 18 && hour < 22,
messages: [
`${timeGreeting}${name}!忙碌了一天,现在是时候关注身心平衡了。我是${botName}可以为你提供放松建议、营养补充和恢复方案`,
`${timeGreeting}!夜幕降临,这是一天中最适合总结和调整的时刻我是你的健康伙伴${botName},让我们一起回顾今天的健康表现,规划明天的目标`,
`${timeGreeting}${name}!晚间时光属于你自己,也是关爱身体的珍贵时间作为你的Seal,我想陪你聊聊如何更好地管理健康生活`
`${timeGreeting}${name}🌙 忙碌了一天,现在是放松身心的好时候呢!小海豹${botName}可以为你提供放松建议和恢复方案哦~`,
`${timeGreeting}🌊 夜幕降临,这是一天中最适合总结的时刻我是你的小海豹${botName},让我们一起回顾今天的健康表现,规划明天的目标吧~`,
`${timeGreeting}${name}🐳 晚间时光属于你自己,也是关爱身体的珍贵时间作为你的小海豹${botName},我想陪你聊聊如何更好地管理健康生活呢~`
]
},
{
condition: () => hour >= 22 || hour < 5,
messages: [
`${timeGreeting}${name}!优质睡眠是健康的基石呢。我是${botName},如果需要睡眠优化建议或放松技巧,随时可以问我`,
`夜深了,${name}。充足的睡眠对身体恢复和新陈代谢都很重要我是你的健康助手${botName},有什么关于睡眠健康的问题都可以咨询我`,
`夜深了,愿你能拥有高质量的睡眠。我是${botName},明天我们继续在健康管理的路上同行。晚安,${name}`
`${timeGreeting}${name}🌙 优质睡眠是健康的基石呢!小海豹${botName}提醒你,如果需要睡眠优化建议,随时可以问我哦~`,
`夜深了,${name}🌊 充足的睡眠对身体恢复很重要呢!我是你的小海豹${botName},有什么关于睡眠健康的问题都可以咨询我`,
`夜深了,愿你能拥有甜甜的睡眠。🐳 我是你的小海豹${botName},明天我们继续在健康管理的海洋里同行。晚安,${name}`
]
}
];
@@ -249,11 +249,11 @@ export default function CoachScreen() {
const specialMessages = [
{
condition: () => !userProfile?.weight && !userProfile?.height,
message: `你好,${name}我是${botName},你的智能健康管理助手。我注意到你还没有完善健康档案,不如先聊聊你的健康目标和身体状况,这样能为你制定更个性化的健康方案`
message: `你好,${name}🐳 我是你的小海豹${botName}我注意到你还没有完善健康档案,不如先聊聊你的健康目标和身体状况,这样小海豹就能为你制定更贴心的健康方案啦~`
},
{
condition: () => userProfile && (!userProfile.pilatesPurposes || userProfile.pilatesPurposes.length === 0),
message: `${timeGreeting}${name}!作为你的Seal,我想更好地了解你的健康需求告诉我你希望在营养摄入、身材管理、健身锻炼或生活管理方面实现什么目标吧~`
message: `${timeGreeting}${name}🐋 作为你的小海豹${botName},我想更好地了解你的健康需求呢!告诉我你希望在营养摄入、身材管理、健身锻炼或生活管理方面实现什么目标吧~`
}
];
@@ -272,7 +272,7 @@ export default function CoachScreen() {
}
// 默认消息
return `你好,我是${botName},你的智能健康管理助手。可以向我咨询营养摄入、身材管理、健身锻炼、生活管理等各方面的健康问题~`;
return `你好,我是你的小海豹${botName}!🐳 可以向我咨询营养摄入、身材管理、健身锻炼、生活管理等各方面的健康问题`;
}, [userProfile, params?.name]);
const chips = useMemo(() => [
@@ -605,6 +605,8 @@ export default function CoachScreen() {
}
async function sendStream(text: string, imageUrls: string[] = []) {
console.log('[SEND_STREAM] 开始发送消息:', { text, imageUrls });
const historyForServer = convertToServerMessages(messages);
const cid = ensureConversationId(); // 可能返回空字符串
const body = {
@@ -614,6 +616,7 @@ export default function CoachScreen() {
stream: true,
};
console.log('[SEND_STREAM] 请求体:', { body });
await sendRequestInternal(body, text, imageUrls);
}
@@ -705,6 +708,13 @@ export default function CoachScreen() {
url,
}));
console.log('[AI_CHAT][ui] 构建用户消息:', {
userMsgId,
text,
imageUrls,
attachments: attachments.length > 0 ? attachments : undefined
});
const userMsg: ChatMessage = {
id: userMsgId,
role: 'user',
@@ -1700,17 +1710,22 @@ export default function CoachScreen() {
if (!currentCardId) return;
try {
console.log('[DIET] 开始上传图片:', { uri: asset.uri, name: asset.fileName });
// 上传图片
const { url } = await upload(
{ uri: asset.uri, name: `diet-${Date.now()}.jpg`, type: 'image/jpeg' },
{ prefix: 'images/diet' }
);
console.log('[DIET] 图片上传成功:', { url });
// 移除饮食选择卡片
setMessages((prev) => prev.filter(msg => msg.id !== currentCardId));
// 发送包含图片的饮食记录消息,图片通过 imageUrls 参数传递
const dietMsg = `#记饮食:请分析这张食物照片的营养成分和热量`;
console.log('[DIET] 发送饮食记录消息:', { dietMsg, imageUrls: [url] });
await sendStream(dietMsg, [url]);
} catch (uploadError) {
console.error('[DIET] 图片上传失败:', uploadError);

View File

@@ -798,10 +798,6 @@ const styles = StyleSheet.create({
justifyContent: 'space-between',
marginBottom: 16,
},
compactBMICard: {
width: 140,
minHeight: 110,
},
healthMetricsContainer: {
marginBottom: 16,
},

View File

@@ -10,8 +10,10 @@ import {
selectMoodRecords,
selectMoodStatistics
} from '@/store/moodSlice';
import { HeaderBar } from '@/components/ui/HeaderBar';
import dayjs from 'dayjs';
import { LinearGradient } from 'expo-linear-gradient';
import { router } from 'expo-router';
import React, { useEffect } from 'react';
import {
ActivityIndicator,
@@ -88,8 +90,14 @@ export default function MoodStatisticsScreen() {
end={{ x: 0, y: 1 }}
/>
<SafeAreaView style={styles.safeArea}>
<HeaderBar
title="心情统计"
onBack={() => router.back()}
withSafeTop={false}
transparent={true}
tone="light"
/>
<ScrollView style={styles.scrollView} showsVerticalScrollIndicator={false}>
<Text style={styles.title}></Text>
{loading.history || loading.statistics ? (
<View style={styles.loadingContainer}>
@@ -184,13 +192,7 @@ const styles = StyleSheet.create({
color: '#666',
textAlign: 'center',
},
title: {
fontSize: 28,
fontWeight: '800',
color: '#192126',
marginTop: 24,
marginBottom: 24,
},
loadingContainer: {
flex: 1,
justifyContent: 'center',

View File

@@ -1,3 +1,4 @@
import { HeaderBar } from '@/components/ui/HeaderBar';
import { Colors } from '@/constants/Colors';
import { useColorScheme } from '@/hooks/useColorScheme';
import { useMoodData } from '@/hooks/useMoodData';
@@ -200,13 +201,13 @@ export default function MoodCalendarScreen() {
end={{ x: 0, y: 1 }}
/>
<SafeAreaView style={styles.safeArea}>
<View style={styles.header}>
<TouchableOpacity onPress={() => router.back()}>
<Text style={styles.backButton}></Text>
</TouchableOpacity>
<Text style={styles.headerTitle}></Text>
<View style={styles.headerSpacer} />
</View>
<HeaderBar
title="心情日历"
onBack={() => router.back()}
withSafeTop={false}
transparent={true}
tone="light"
/>
<ScrollView style={styles.content}>
{/* 日历视图 */}
@@ -347,27 +348,7 @@ const styles = StyleSheet.create({
safeArea: {
flex: 1,
},
header: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
paddingHorizontal: 20,
paddingVertical: 16,
},
backButton: {
fontSize: 24,
color: '#666',
},
headerTitle: {
fontSize: 20,
fontWeight: '600',
color: '#333',
flex: 1,
textAlign: 'center',
},
headerSpacer: {
width: 24,
},
content: {
flex: 1,
},
@@ -430,11 +411,11 @@ const styles = StyleSheet.create({
marginBottom: 8,
},
dayButtonSelected: {
backgroundColor: '#4CAF50',
backgroundColor: Colors.light.accentGreen,
},
dayButtonToday: {
borderWidth: 2,
borderColor: '#4CAF50',
borderColor: Colors.light.accentGreen,
},
dayContent: {
position: 'relative',
@@ -456,7 +437,7 @@ const styles = StyleSheet.create({
fontWeight: '600',
},
dayNumberToday: {
color: '#4CAF50',
color: Colors.light.accentGreen,
fontWeight: '600',
},
dayNumberDisabled: {
@@ -520,7 +501,7 @@ const styles = StyleSheet.create({
paddingHorizontal: 16,
height: 32,
borderRadius: 16,
backgroundColor: '#4CAF50',
backgroundColor: Colors.light.accentGreen,
justifyContent: 'center',
alignItems: 'center',
},
@@ -538,7 +519,7 @@ const styles = StyleSheet.create({
width: 48,
height: 48,
borderRadius: 24,
backgroundColor: '#4CAF50',
backgroundColor: Colors.light.accentGreen,
justifyContent: 'center',
alignItems: 'center',
marginRight: 12,

View File

@@ -1,3 +1,4 @@
import { HeaderBar } from '@/components/ui/HeaderBar';
import { Colors } from '@/constants/Colors';
import { useAppDispatch, useAppSelector } from '@/hooks/redux';
import { useColorScheme } from '@/hooks/useColorScheme';
@@ -168,15 +169,13 @@ export default function MoodEditScreen() {
end={{ x: 0, y: 1 }}
/>
<SafeAreaView style={styles.safeArea}>
<View style={styles.header}>
<TouchableOpacity onPress={() => router.back()}>
<Text style={styles.backButton}></Text>
</TouchableOpacity>
<Text style={styles.headerTitle}>
{existingMood ? '编辑心情' : '记录心情'}
</Text>
<View style={styles.headerSpacer} />
</View>
<HeaderBar
title={existingMood ? '编辑心情' : '记录心情'}
onBack={() => router.back()}
withSafeTop={false}
transparent={true}
tone="light"
/>
<ScrollView style={styles.content}>
{/* 日期显示 */}
@@ -274,27 +273,7 @@ const styles = StyleSheet.create({
safeArea: {
flex: 1,
},
header: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
paddingHorizontal: 20,
paddingVertical: 16,
},
backButton: {
fontSize: 24,
color: '#666',
},
headerTitle: {
fontSize: 20,
fontWeight: '600',
color: '#333',
flex: 1,
textAlign: 'center',
},
headerSpacer: {
width: 24,
},
content: {
flex: 1,
},
@@ -339,7 +318,7 @@ const styles = StyleSheet.create({
selectedMoodOption: {
backgroundColor: '#e8f5e8',
borderWidth: 2,
borderColor: '#4CAF50',
borderColor: Colors.light.accentGreen,
},
moodEmoji: {
fontSize: 24,
@@ -378,7 +357,7 @@ const styles = StyleSheet.create({
backgroundColor: '#ddd',
},
intensityDotActive: {
backgroundColor: '#4CAF50',
backgroundColor: Colors.light.accentGreen,
},
intensityLabels: {
flexDirection: 'row',
@@ -416,7 +395,7 @@ const styles = StyleSheet.create({
backgroundColor: '#fff',
},
saveButton: {
backgroundColor: '#4CAF50',
backgroundColor: Colors.light.accentGreen,
borderRadius: 12,
paddingVertical: 16,
alignItems: 'center',