feat: 更新心情相关页面和组件
- 在心情统计、日历和编辑页面中引入 HeaderBar 组件,提升界面一致性和用户体验 - 移除冗余的头部视图代码,简化组件结构 - 更新心情日历和编辑页面的样式,使用新的颜色常量,增强视觉效果 - 优化心情统计页面的加载状态显示,提升用户交互体验
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -798,10 +798,6 @@ const styles = StyleSheet.create({
|
||||
justifyContent: 'space-between',
|
||||
marginBottom: 16,
|
||||
},
|
||||
compactBMICard: {
|
||||
width: 140,
|
||||
minHeight: 110,
|
||||
},
|
||||
healthMetricsContainer: {
|
||||
marginBottom: 16,
|
||||
},
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user