From 098c65b23ed7f8d307591dbf920ad6e5144b8d40 Mon Sep 17 00:00:00 2001 From: richarjiang Date: Thu, 21 Aug 2025 19:09:02 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9B=B4=E6=96=B0=E5=BF=83=E6=83=85?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E9=A1=B5=E9=9D=A2=E5=92=8C=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在心情统计、日历和编辑页面中引入 HeaderBar 组件,提升界面一致性和用户体验 - 移除冗余的头部视图代码,简化组件结构 - 更新心情日历和编辑页面的样式,使用新的颜色常量,增强视觉效果 - 优化心情统计页面的加载状态显示,提升用户交互体验 --- app/(tabs)/coach.tsx | 57 ++++++++++++++-------- app/(tabs)/statistics.tsx | 4 -- app/mood-statistics.tsx | 18 ++++--- app/mood/calendar.tsx | 47 ++++++------------ app/mood/edit.tsx | 45 +++++------------ components/BMICard.tsx | 1 - components/FitnessRingsCard.tsx | 2 - constants/Colors.ts | 7 +-- ios/digitalpilates/SplashScreen.storyboard | 4 +- 9 files changed, 78 insertions(+), 107 deletions(-) diff --git a/app/(tabs)/coach.tsx b/app/(tabs)/coach.tsx index 351d7e6..a245031 100644 --- a/app/(tabs)/coach.tsx +++ b/app/(tabs)/coach.tsx @@ -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); diff --git a/app/(tabs)/statistics.tsx b/app/(tabs)/statistics.tsx index 144aecb..151784e 100644 --- a/app/(tabs)/statistics.tsx +++ b/app/(tabs)/statistics.tsx @@ -798,10 +798,6 @@ const styles = StyleSheet.create({ justifyContent: 'space-between', marginBottom: 16, }, - compactBMICard: { - width: 140, - minHeight: 110, - }, healthMetricsContainer: { marginBottom: 16, }, diff --git a/app/mood-statistics.tsx b/app/mood-statistics.tsx index 81f0d77..9eeb27a 100644 --- a/app/mood-statistics.tsx +++ b/app/mood-statistics.tsx @@ -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 }} /> + router.back()} + withSafeTop={false} + transparent={true} + tone="light" + /> - 心情统计 {loading.history || loading.statistics ? ( @@ -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', diff --git a/app/mood/calendar.tsx b/app/mood/calendar.tsx index ab96df6..b4d7080 100644 --- a/app/mood/calendar.tsx +++ b/app/mood/calendar.tsx @@ -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 }} /> - - router.back()}> - - - 心情日历 - - + router.back()} + withSafeTop={false} + transparent={true} + tone="light" + /> {/* 日历视图 */} @@ -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, diff --git a/app/mood/edit.tsx b/app/mood/edit.tsx index 2548bce..23c28ec 100644 --- a/app/mood/edit.tsx +++ b/app/mood/edit.tsx @@ -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 }} /> - - router.back()}> - - - - {existingMood ? '编辑心情' : '记录心情'} - - - + router.back()} + withSafeTop={false} + transparent={true} + tone="light" + /> {/* 日期显示 */} @@ -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', diff --git a/components/BMICard.tsx b/components/BMICard.tsx index 313f228..ded3d41 100644 --- a/components/BMICard.tsx +++ b/components/BMICard.tsx @@ -293,7 +293,6 @@ const styles = StyleSheet.create({ card: { borderRadius: 22, padding: 18, - marginBottom: 16, overflow: 'hidden', backgroundColor: '#FFFFFF', }, diff --git a/components/FitnessRingsCard.tsx b/components/FitnessRingsCard.tsx index ab8979a..13d4f74 100644 --- a/components/FitnessRingsCard.tsx +++ b/components/FitnessRingsCard.tsx @@ -118,9 +118,7 @@ export function FitnessRingsCard({ const styles = StyleSheet.create({ container: { - backgroundColor: '#FFFFFF', borderRadius: 16, - padding: 12, shadowColor: '#000', shadowOffset: { width: 0, diff --git a/constants/Colors.ts b/constants/Colors.ts index 0b4c489..5b48891 100644 --- a/constants/Colors.ts +++ b/constants/Colors.ts @@ -20,6 +20,7 @@ export const palette = { orange: '#FCC46F', blue: '#87CEEB', // 更贴近logo背景的天空蓝 blueSecondary: '#4682B4', // 钢蓝色,用于选中状态 + green: '#9ceb87', // 温暖的绿色,用于心情日历等 } as const; const primaryColor = palette.blue; // 应用主题色 @@ -54,12 +55,12 @@ export const Colors = { danger: palette.red, info: palette.blue, accentPurple: palette.purple, - accentGreen: palette.blue, + accentGreen: palette.green, // 温暖的绿色 accentGreenDark: palette.blueSecondary, // 深绿色,用于文本和强调 // 日期选择器主题色 datePickerNormal: palette.blue, - datePickerSelected: palette.blueSecondary, + datePickerSelected: palette.green, // 使用温暖的绿色作为选中状态 // 结构色(优化后的蓝色主题) border: 'rgba(135,206,235,0.2)', // 蓝色调边框 @@ -111,7 +112,7 @@ export const Colors = { // 日期选择器主题色 datePickerNormal: palette.blue, - datePickerSelected: palette.blueSecondary, + datePickerSelected: palette.green, // 使用温暖的绿色作为选中状态 // 结构色 border: '#2A2F32', diff --git a/ios/digitalpilates/SplashScreen.storyboard b/ios/digitalpilates/SplashScreen.storyboard index 47a97b2..ac1f350 100644 --- a/ios/digitalpilates/SplashScreen.storyboard +++ b/ios/digitalpilates/SplashScreen.storyboard @@ -1,6 +1,6 @@ - + @@ -14,7 +14,7 @@ - +