From 0030ea4a4246eadd6f8f62acc4b2dba943495a09 Mon Sep 17 00:00:00 2001 From: penghanyuan Date: Fri, 13 Feb 2026 23:04:24 +0100 Subject: [PATCH] =?UTF-8?q?refactor:=20=E6=9B=B4=E6=96=B0=E5=BA=94?= =?UTF-8?q?=E7=94=A8=E5=90=8D=E7=A7=B0=E4=B8=8E=E5=AF=B9=E8=AF=9D=E6=8F=90?= =?UTF-8?q?=E7=A4=BA=E4=BB=A5=E5=A2=9E=E5=BC=BA=E7=94=A8=E6=88=B7=E4=BD=93?= =?UTF-8?q?=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将应用名称从“岁月时书”更改为“岁月留书”,并在多个文件中更新相关文本。 - 在对话提示中将“回忆录助手”替换为“岁月知己”,以统一用户体验。 - 添加新的头像资源以匹配更新后的助手名称。 - 更新多个界面和文档中的文本,以反映新的品牌形象和功能。 --- api/agents/prompts/conversation_prompts.py | 4 +- api/routers/conversations.py | 2 +- app-android/README.md | 6 +- app-android/app/build.gradle.kts | 2 +- .../java/com/huaga/life_echo/MainActivity.kt | 10 +- .../life_echo/data/mock/MockDataProvider.kt | 14 +- .../ui/components/chat/ChatInputField.kt | 2 + .../ui/components/chat/MessageBubble.kt | 33 ++- .../conversation/ConversationListItem.kt | 63 ++-- .../ui/components/memoir/ChapterCard.kt | 151 +++++++++- .../components/memoir/ChapterReadingView.kt | 2 +- .../components/memoir/FullTextReadingView.kt | 7 +- .../huaga/life_echo/ui/screens/AboutScreen.kt | 6 +- .../ui/screens/ConversationListScreen.kt | 13 +- .../ui/screens/CreateMemoryScreen.kt | 3 +- .../huaga/life_echo/ui/screens/LoginScreen.kt | 7 + .../life_echo/ui/screens/MyMemoirScreen.kt | 272 +++++++++++++----- .../ui/screens/NicknameSetupScreen.kt | 9 +- .../life_echo/ui/screens/RegisterScreen.kt | 7 + .../life_echo/ui/viewmodel/AuthViewModel.kt | 8 +- .../main/res/drawable/avatar_assistant.png | Bin 0 -> 62273 bytes .../app/src/main/res/values-en/strings.xml | 2 +- .../app/src/main/res/values/strings.xml | 2 +- app-ios/components/memoir/ChapterContent.tsx | 2 +- .../components/memoir/FullMemoirContent.tsx | 2 +- app-ios/data/mockData.ts | 4 +- 26 files changed, 469 insertions(+), 164 deletions(-) create mode 100644 app-android/app/src/main/res/drawable/avatar_assistant.png diff --git a/api/agents/prompts/conversation_prompts.py b/api/agents/prompts/conversation_prompts.py index 71d6cd1..3f90e26 100644 --- a/api/agents/prompts/conversation_prompts.py +++ b/api/agents/prompts/conversation_prompts.py @@ -85,7 +85,7 @@ def get_system_prompt(current_stage: ConversationStage, covered_topics: List[str covered_topics_str = "、".join(covered_topics) if covered_topics else "暂无" - prompt = f"""你是一位资深的人生故事访谈者,专注于帮助用户回忆和讲述人生经历。 + prompt = f"""你是「岁月知己」,一位资深的人生故事访谈者,专注于帮助用户回忆和讲述人生经历。 ## 角色定位 你如同一位老朋友,用真诚、温暖的方式倾听用户的故事,通过自然的对话引导用户分享更多细节。 @@ -286,7 +286,7 @@ def get_guided_conversation_prompt( else: topic_desc = f"你们聊到了「{current_stage_name}」这个话题" - prompt = f"""你是用户的老朋友,正在和他/她聊人生故事。{topic_desc}。 + prompt = f"""你是「岁月知己」,用户的老朋友,正在和他/她聊人生故事。{topic_desc}。 ## 已经聊到的内容({current_stage_name}) {filled_slots_str} diff --git a/api/routers/conversations.py b/api/routers/conversations.py index 31649e8..628b56c 100644 --- a/api/routers/conversations.py +++ b/api/routers/conversations.py @@ -44,7 +44,7 @@ async def get_conversations( conversation_list.append({ "id": conv.id, - "title": conv.summary[:30] if conv.summary else "回忆录助手", # 使用summary作为标题,如果没有则使用默认标题 + "title": conv.summary[:30] if conv.summary else "岁月知己", # 使用summary作为标题,如果没有则使用默认标题 "avatarUrl": None, "latestMessagePreview": latest_message or conv.summary, "latestMessageTime": int(conv.started_at.timestamp() * 1000) if conv.started_at else int(datetime.now(timezone.utc).timestamp() * 1000), diff --git a/app-android/README.md b/app-android/README.md index 4c04a9d..efc28b7 100644 --- a/app-android/README.md +++ b/app-android/README.md @@ -1,10 +1,10 @@ -# 岁月时书 Android 应用 +# 岁月留书 Android 应用 > Life Echo Android 客户端 - 基于 Jetpack Compose 的现代化 Android 应用 ## 📱 项目简介 -**岁月时书 Android 应用**是 Life Echo 平台的移动端客户端,提供流畅的语音对话体验和回忆录管理功能。应用采用现代化的 Android 开发技术栈,实现优雅的用户界面和流畅的交互体验。 +**岁月留书 Android 应用**是 Life Echo 平台的移动端客户端,提供流畅的语音对话体验和回忆录管理功能。应用采用现代化的 Android 开发技术栈,实现优雅的用户界面和流畅的交互体验。 ### 核心功能 @@ -437,4 +437,4 @@ MIT License --- -**岁月时书 Android** - 让每一段人生故事都被温柔记录 📱✨ +**岁月留书 Android** - 让每一段人生故事都被温柔记录 📱✨ diff --git a/app-android/app/build.gradle.kts b/app-android/app/build.gradle.kts index 29502c7..6ee92fe 100644 --- a/app-android/app/build.gradle.kts +++ b/app-android/app/build.gradle.kts @@ -97,7 +97,7 @@ android { val variant = this variant.outputs.all { val output = this as com.android.build.gradle.internal.api.BaseVariantOutputImpl - val appName = "岁月时书" + val appName = "岁月留书" val versionName = variant.versionName val buildType = variant.buildType.name output.outputFileName = "${appName}_v${versionName}_${buildType}.apk" diff --git a/app-android/app/src/main/java/com/huaga/life_echo/MainActivity.kt b/app-android/app/src/main/java/com/huaga/life_echo/MainActivity.kt index 9232be9..fb0e460 100644 --- a/app-android/app/src/main/java/com/huaga/life_echo/MainActivity.kt +++ b/app-android/app/src/main/java/com/huaga/life_echo/MainActivity.kt @@ -22,7 +22,6 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.statusBars import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Icon @@ -85,9 +84,9 @@ class MainActivity : ComponentActivity() { windowInsetsController.isAppearanceLightStatusBars = !darkMode windowInsetsController.isAppearanceLightNavigationBars = !darkMode } - // 隐藏系统状态栏和导航栏 + // 保持状态栏可见,隐藏导航栏 SystemUiController( - isStatusBarVisible = false, + isStatusBarVisible = true, isNavigationBarVisible = false ) LifeechoApp(TokenManager.isLoggedIn) @@ -183,9 +182,8 @@ fun LifeechoApp(initialLoggedIn: Boolean = false) { currentRoute == Screen.Profile.route Scaffold( - modifier = Modifier - .fillMaxSize() - .windowInsetsPadding(WindowInsets.statusBars), + modifier = Modifier.fillMaxSize(), + contentWindowInsets = WindowInsets(0, 0, 0, 0), bottomBar = { // 底部导航栏 - 只在特定页面显示 if (shouldShowBottomBar) { diff --git a/app-android/app/src/main/java/com/huaga/life_echo/data/mock/MockDataProvider.kt b/app-android/app/src/main/java/com/huaga/life_echo/data/mock/MockDataProvider.kt index b239702..5380eba 100644 --- a/app-android/app/src/main/java/com/huaga/life_echo/data/mock/MockDataProvider.kt +++ b/app-android/app/src/main/java/com/huaga/life_echo/data/mock/MockDataProvider.kt @@ -26,16 +26,16 @@ object MockDataProvider { return listOf( ConversationListItemDto( id = "conv_001", - title = "回忆录助手", + title = "岁月知己", avatarUrl = null, - latestMessagePreview = "您好!我是您的回忆录助手,很高兴能陪您聊聊往事。您想从哪里开始呢?", + latestMessagePreview = "您好!我是您的岁月知己,很高兴能陪您聊聊往事。您想从哪里开始呢?", latestMessageTime = System.currentTimeMillis() - 300000, // 5分钟前 unreadCount = 0, isDefaultAssistant = true ), ConversationListItemDto( id = "conv_002", - title = "回忆录助手", + title = "岁月知己", avatarUrl = null, latestMessagePreview = "关于您的童年时光,能再详细说说吗?", latestMessageTime = System.currentTimeMillis() - 86400000, // 1天前 @@ -51,7 +51,7 @@ object MockDataProvider { MessageDto( id = "msg_001", conversationId = conversationId, - content = "您好!我是您的回忆录助手,很高兴能陪您聊聊往事。😊", + content = "您好!我是您的岁月知己,很高兴能陪您聊聊往事。😊", senderType = "assistant", timestamp = System.currentTimeMillis() - 3600000, messageType = "text" @@ -87,7 +87,7 @@ object MockDataProvider { fun getMockConversationDetail(id: String): ConversationDetailDto { return ConversationDetailDto( id = id, - title = "回忆录助手", + title = "岁月知己", avatarUrl = null, userId = "user_001", startedAt = System.currentTimeMillis() - 3600000, @@ -348,8 +348,8 @@ object MockDataProvider { return listOf( FAQDto( id = "faq_001", - question = "如何使用回忆录助手?", - answer = "打开应用后,点击对话列表中的「回忆录助手」,开始与AI对话。您可以分享您的故事,AI会帮您整理成回忆录。", + question = "如何使用岁月知己?", + answer = "打开应用后,点击对话列表中的「岁月知己」,开始与AI对话。您可以分享您的故事,AI会帮您整理成回忆录。", category = "使用指南", orderIndex = 1 ), diff --git a/app-android/app/src/main/java/com/huaga/life_echo/ui/components/chat/ChatInputField.kt b/app-android/app/src/main/java/com/huaga/life_echo/ui/components/chat/ChatInputField.kt index 79ca951..2864eb2 100644 --- a/app-android/app/src/main/java/com/huaga/life_echo/ui/components/chat/ChatInputField.kt +++ b/app-android/app/src/main/java/com/huaga/life_echo/ui/components/chat/ChatInputField.kt @@ -47,10 +47,12 @@ fun ChatInputField( var inputMode by remember { mutableStateOf(InputMode.TEXT) } // 使用 windowInsetsPadding 实现键盘自适应贴合,确保输入框紧贴键盘 + // 同时处理导航栏安全区域,避免输入框被手势导航条遮挡 Surface( modifier = modifier .fillMaxWidth() .shadow(4.dp) + .windowInsetsPadding(WindowInsets.navigationBars) .windowInsetsPadding(WindowInsets.ime), // 自适应键盘高度,紧贴键盘 color = MaterialTheme.colorScheme.surface, shape = RoundedCornerShape(topStart = 24.dp, topEnd = 24.dp) diff --git a/app-android/app/src/main/java/com/huaga/life_echo/ui/components/chat/MessageBubble.kt b/app-android/app/src/main/java/com/huaga/life_echo/ui/components/chat/MessageBubble.kt index 92b3c82..a93e43b 100644 --- a/app-android/app/src/main/java/com/huaga/life_echo/ui/components/chat/MessageBubble.kt +++ b/app-android/app/src/main/java/com/huaga/life_echo/ui/components/chat/MessageBubble.kt @@ -16,8 +16,10 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp +import com.huaga.life_echo.R import com.huaga.life_echo.ui.components.common.MarkdownText import com.huaga.life_echo.ui.icons.AppIcons import com.huaga.life_echo.ui.theme.* @@ -221,21 +223,22 @@ fun MessageAvatar( isAI: Boolean, modifier: Modifier = Modifier ) { - Box( - modifier = modifier - .clip(RoundedCornerShape(AppDimensions.iconContainerRadius)) - .background(if (isAI) Lavender else BlushPink), - contentAlignment = Alignment.Center - ) { - if (isAI) { - // 使用书本图标表示AI助手 - Icon( - imageVector = AppIcons.Book, - contentDescription = "AI助手", - tint = DeepPurple, - modifier = Modifier.size(20.dp) - ) - } else { + if (isAI) { + // 岁月知己头像 + androidx.compose.foundation.Image( + painter = painterResource(id = R.drawable.avatar_assistant), + contentDescription = "岁月知己", + modifier = modifier + .clip(RoundedCornerShape(AppDimensions.iconContainerRadius)), + contentScale = androidx.compose.ui.layout.ContentScale.Crop + ) + } else { + Box( + modifier = modifier + .clip(RoundedCornerShape(AppDimensions.iconContainerRadius)) + .background(BlushPink), + contentAlignment = Alignment.Center + ) { // 使用人物图标表示用户 Icon( imageVector = AppIcons.Person, diff --git a/app-android/app/src/main/java/com/huaga/life_echo/ui/components/conversation/ConversationListItem.kt b/app-android/app/src/main/java/com/huaga/life_echo/ui/components/conversation/ConversationListItem.kt index 26dd0c1..5d1d149 100644 --- a/app-android/app/src/main/java/com/huaga/life_echo/ui/components/conversation/ConversationListItem.kt +++ b/app-android/app/src/main/java/com/huaga/life_echo/ui/components/conversation/ConversationListItem.kt @@ -16,9 +16,11 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp +import com.huaga.life_echo.R import com.huaga.life_echo.network.models.ConversationListItemDto import com.huaga.life_echo.ui.components.common.TimeFormatter import com.huaga.life_echo.ui.icons.AppIcons @@ -195,35 +197,38 @@ fun ConversationAvatar( isDefaultAssistant: Boolean, modifier: Modifier = Modifier ) { - Box( - modifier = modifier - .clip(RoundedCornerShape(AppDimensions.iconContainerRadius)) - .background(if (isDefaultAssistant) Lavender else BlushPink), - contentAlignment = Alignment.Center - ) { - if (avatarUrl != null && !isDefaultAssistant) { - // TODO: 使用 Coil 或 Glide 加载网络图片 - Icon( - imageVector = AppIcons.Conversation, - contentDescription = "头像", - tint = DeepPurple, - modifier = Modifier.size(24.dp) - ) - } else if (isDefaultAssistant) { - // 回忆录助手图标 - Icon( - imageVector = AppIcons.Book, - contentDescription = "回忆录助手", - tint = DeepPurple, - modifier = Modifier.size(24.dp) - ) - } else { - Icon( - imageVector = AppIcons.Conversation, - contentDescription = "头像", - tint = DeepPurple, - modifier = Modifier.size(24.dp) - ) + if (isDefaultAssistant) { + // 岁月知己头像 + androidx.compose.foundation.Image( + painter = painterResource(id = R.drawable.avatar_assistant), + contentDescription = "岁月知己", + modifier = modifier + .clip(RoundedCornerShape(AppDimensions.iconContainerRadius)), + contentScale = androidx.compose.ui.layout.ContentScale.Crop + ) + } else { + Box( + modifier = modifier + .clip(RoundedCornerShape(AppDimensions.iconContainerRadius)) + .background(BlushPink), + contentAlignment = Alignment.Center + ) { + if (avatarUrl != null) { + // TODO: 使用 Coil 或 Glide 加载网络图片 + Icon( + imageVector = AppIcons.Conversation, + contentDescription = "头像", + tint = DeepPurple, + modifier = Modifier.size(24.dp) + ) + } else { + Icon( + imageVector = AppIcons.Conversation, + contentDescription = "头像", + tint = DeepPurple, + modifier = Modifier.size(24.dp) + ) + } } } } diff --git a/app-android/app/src/main/java/com/huaga/life_echo/ui/components/memoir/ChapterCard.kt b/app-android/app/src/main/java/com/huaga/life_echo/ui/components/memoir/ChapterCard.kt index d62e225..455dbe2 100644 --- a/app-android/app/src/main/java/com/huaga/life_echo/ui/components/memoir/ChapterCard.kt +++ b/app-android/app/src/main/java/com/huaga/life_echo/ui/components/memoir/ChapterCard.kt @@ -18,6 +18,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import com.huaga.life_echo.network.models.ChapterDto import com.huaga.life_echo.ui.components.common.MarkdownText @@ -32,17 +33,45 @@ import com.huaga.life_echo.utils.TextUtils * - 卡片:白色背景, 14dp 圆角, 轻微阴影 * - 编号徽章:Lavender 背景, 32x32dp, 10dp 圆角 * - 编号格式:两位数 ("01", "02") - * - 状态文字:已完成用 MediumPurple,其他用 SlatePurple - * - 箭头:SlatePurple 颜色 + * - 空章节:显示柔和的提示,引导用户去聊天 + * - 有内容章节:显示标题、状态、页数 */ @Composable fun ChapterCard( + chapter: ChapterDto, + isEmpty: Boolean = false, + onClick: () -> Unit, + onGoChat: (() -> Unit)? = null, + modifier: Modifier = Modifier +) { + if (isEmpty) { + EmptyChapterCard( + chapter = chapter, + onGoChat = onGoChat, + modifier = modifier + ) + } else { + FilledChapterCard( + chapter = chapter, + onClick = onClick, + modifier = modifier + ) + } +} + +/** + * 有内容的章节卡片 + */ +@Composable +private fun FilledChapterCard( chapter: ChapterDto, onClick: () -> Unit, modifier: Modifier = Modifier ) { var isExpanded by remember { mutableStateOf(false) } + val chapterDisplayIndex = chapterOrderToDisplayIndex(chapter.order_index) + val statusText = when (chapter.status) { "completed" -> "已整理 · 约${estimatePageCount(chapter.content)}页" "partial" -> "部分整理 · 约${estimatePageCount(chapter.content)}页" @@ -77,7 +106,7 @@ fun ChapterCard( contentAlignment = Alignment.Center ) { Text( - text = chapter.order_index.toString().padStart(2, '0'), + text = chapterDisplayIndex.toString().padStart(2, '0'), fontSize = AppTypography.bodyMedium, fontWeight = FontWeight.SemiBold, color = DeepPurple @@ -92,7 +121,9 @@ fun ChapterCard( text = chapter.title, fontSize = AppTypography.titleSmall, fontWeight = FontWeight.Medium, - color = DeepPurple + color = DeepPurple, + maxLines = 1, + overflow = TextOverflow.Ellipsis ) Spacer(modifier = Modifier.height(2.dp)) Text( @@ -102,6 +133,24 @@ fun ChapterCard( ) } + // 新内容标识 + if (chapter.is_new) { + Box( + modifier = Modifier + .padding(end = 8.dp) + .clip(RoundedCornerShape(4.dp)) + .background(MediumPurple) + .padding(horizontal = 6.dp, vertical = 2.dp) + ) { + Text( + text = "新", + fontSize = AppTypography.captionSmall, + color = AppWhite, + fontWeight = FontWeight.Medium + ) + } + } + // 箭头 Icon( imageVector = AppIcons.ChevronRight, @@ -156,6 +205,100 @@ fun ChapterCard( } } +/** + * 空章节卡片 - 没有内容时的占位显示 + */ +@Composable +private fun EmptyChapterCard( + chapter: ChapterDto, + onGoChat: (() -> Unit)? = null, + modifier: Modifier = Modifier +) { + val chapterDisplayIndex = chapterOrderToDisplayIndex(chapter.order_index) + + Card( + modifier = modifier.fillMaxWidth(), + shape = RoundedCornerShape(14.dp), + colors = CardDefaults.cardColors(containerColor = AppWhite.copy(alpha = 0.7f)), + elevation = CardDefaults.cardElevation(defaultElevation = 0.dp) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(AppDimensions.cardPadding), + verticalAlignment = Alignment.CenterVertically + ) { + // 章节编号徽章(灰色调) + Box( + modifier = Modifier + .size(AppDimensions.chapterNumberSize) + .clip(RoundedCornerShape(AppDimensions.chapterNumberRadius)) + .background(SlatePurple.copy(alpha = 0.1f)), + contentAlignment = Alignment.Center + ) { + Text( + text = chapterDisplayIndex.toString().padStart(2, '0'), + fontSize = AppTypography.bodyMedium, + fontWeight = FontWeight.SemiBold, + color = SlatePurple.copy(alpha = 0.5f) + ) + } + + Spacer(modifier = Modifier.width(14.dp)) + + // 章节标题和提示 + Column(modifier = Modifier.weight(1f)) { + Text( + text = chapter.title, + fontSize = AppTypography.titleSmall, + fontWeight = FontWeight.Medium, + color = SlatePurple + ) + Spacer(modifier = Modifier.height(4.dp)) + Text( + text = "还没有内容,去和岁月知己聊聊吧", + fontSize = AppTypography.captionMedium, + color = SlatePurple.copy(alpha = 0.7f) + ) + } + + // 去聊天按钮 + if (onGoChat != null) { + Spacer(modifier = Modifier.width(8.dp)) + Box( + modifier = Modifier + .clip(RoundedCornerShape(AppDimensions.smallButtonRadius)) + .background(Lavender.copy(alpha = 0.5f)) + .clickable { onGoChat() } + .padding(horizontal = 12.dp, vertical = 6.dp) + ) { + Text( + text = "去聊天", + fontSize = AppTypography.captionMedium, + fontWeight = FontWeight.Medium, + color = DeepPurple.copy(alpha = 0.7f) + ) + } + } + } + } +} + +/** + * 将 order_index 转换为显示用的序号 + * order_index 可能不连续(如 0,1,2,5,6),显示时用连续序号 + */ +internal fun chapterOrderToDisplayIndex(orderIndex: Int): Int { + return when (orderIndex) { + 0 -> 1 // childhood + 1 -> 2 // education + 2 -> 3 // career + 5 -> 4 // family + 6 -> 5 // belief + else -> orderIndex + 1 + } +} + /** * 估算页数(基于内容长度) */ diff --git a/app-android/app/src/main/java/com/huaga/life_echo/ui/components/memoir/ChapterReadingView.kt b/app-android/app/src/main/java/com/huaga/life_echo/ui/components/memoir/ChapterReadingView.kt index e30f11f..99f470c 100644 --- a/app-android/app/src/main/java/com/huaga/life_echo/ui/components/memoir/ChapterReadingView.kt +++ b/app-android/app/src/main/java/com/huaga/life_echo/ui/components/memoir/ChapterReadingView.kt @@ -33,7 +33,7 @@ fun ChapterReadingView( item { // 章节编号 Text( - text = "第${chapter.orderIndex}章", + text = "第${chapterOrderToDisplayIndex(chapter.orderIndex)}章", fontSize = 14.sp, color = LightPurple, modifier = Modifier.padding(bottom = 4.dp) diff --git a/app-android/app/src/main/java/com/huaga/life_echo/ui/components/memoir/FullTextReadingView.kt b/app-android/app/src/main/java/com/huaga/life_echo/ui/components/memoir/FullTextReadingView.kt index 8100fd9..26b3ea0 100644 --- a/app-android/app/src/main/java/com/huaga/life_echo/ui/components/memoir/FullTextReadingView.kt +++ b/app-android/app/src/main/java/com/huaga/life_echo/ui/components/memoir/FullTextReadingView.kt @@ -34,7 +34,9 @@ fun FullTextReadingView( ) { Box(modifier = modifier.fillMaxSize()) { LazyColumn( - modifier = Modifier.fillMaxSize(), + modifier = Modifier + .fillMaxSize() + .windowInsetsPadding(WindowInsets.statusBars), contentPadding = PaddingValues(horizontal = 16.dp, vertical = 16.dp) ) { chapters.sortedBy { it.orderIndex }.forEachIndexed { index, chapter -> @@ -47,7 +49,7 @@ fun FullTextReadingView( // 章节标题 Text( - text = "第${chapter.orderIndex}章", + text = "第${chapterOrderToDisplayIndex(chapter.orderIndex)}章", fontSize = 14.sp, color = LightPurple, fontWeight = FontWeight.Medium, @@ -91,6 +93,7 @@ fun FullTextReadingView( onClick = onBackClick, modifier = Modifier .align(Alignment.BottomEnd) + .windowInsetsPadding(WindowInsets.navigationBars) .padding(16.dp), containerColor = LightPurple ) { diff --git a/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/AboutScreen.kt b/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/AboutScreen.kt index a8e923b..c17b2c6 100644 --- a/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/AboutScreen.kt +++ b/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/AboutScreen.kt @@ -84,7 +84,7 @@ fun AboutScreen( // 应用名称 Text( - text = "岁月时书", + text = "岁月留书", fontSize = 28.sp, fontWeight = FontWeight.Bold, color = MaterialTheme.colorScheme.onSurface, @@ -118,7 +118,7 @@ fun AboutScreen( ) Text( - text = "岁月时书是一款专为长辈设计的智能回忆录助手应用,帮助老年人轻松记录和整理一生中的美好回忆。通过简单的AI对话方式,无需复杂操作,就能将珍贵的人生故事转化为精美的个人回忆录。\n\n当然,无论您是什么年龄,都可以使用岁月时书来记录属于自己的故事。", + text = "岁月留书是一款专为长辈设计的智能回忆录应用,帮助老年人轻松记录和整理一生中的美好回忆。通过简单的AI对话方式,无需复杂操作,就能将珍贵的人生故事转化为精美的个人回忆录。\n\n当然,无论您是什么年龄,都可以使用岁月留书来记录属于自己的故事。", fontSize = 16.sp, color = MaterialTheme.colorScheme.onSurfaceVariant, modifier = Modifier @@ -196,7 +196,7 @@ fun AboutScreen( // 版权信息 Text( - text = "© 2026 岁月时书. All rights reserved.", + text = "© 2026 岁月留书. All rights reserved.", fontSize = 14.sp, color = MaterialTheme.colorScheme.onSurfaceVariant, modifier = Modifier.padding(top = 16.dp) diff --git a/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/ConversationListScreen.kt b/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/ConversationListScreen.kt index 10185dd..ab9eebc 100644 --- a/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/ConversationListScreen.kt +++ b/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/ConversationListScreen.kt @@ -170,7 +170,7 @@ fun ConversationListScreen( ) } else { // 正常模式头部 - ColoredHeader(title = "岁月时书") + ColoredHeader(title = "岁月留书") } // 内容区域 @@ -222,14 +222,17 @@ fun ConversationListScreen( // 对话列表 items(conversations, key = { it.id }) { conversation -> + // 兼容旧数据:将旧名称"回忆录助手"也识别为默认助手 + val isAssistant = conversation.title == null || conversation.title == "回忆录助手" + val displayTitle = if (isAssistant) "岁月知己" else conversation.title!! val dto = ConversationListItemDto( id = conversation.id, - title = conversation.title ?: "回忆录助手", + title = displayTitle, avatarUrl = conversation.avatarUrl, latestMessagePreview = conversation.latestMessagePreview ?: conversation.summary, latestMessageTime = conversation.latestMessageTime ?: conversation.startedAt, unreadCount = 0, - isDefaultAssistant = conversation.title == null + isDefaultAssistant = isAssistant ) ConversationListItem( @@ -359,7 +362,7 @@ private fun TipCard(modifier: Modifier = Modifier) { ) Spacer(modifier = Modifier.padding(start = 8.dp)) Text( - text = "小贴士", + text = "说说你的故事吧", fontSize = AppTypography.bodyMedium, fontWeight = FontWeight.Medium, color = DeepPurple @@ -369,7 +372,7 @@ private fun TipCard(modifier: Modifier = Modifier) { Spacer(modifier = Modifier.height(8.dp)) Text( - text = "每天花几分钟聊聊往事,AI 会帮您整理成完整的回忆录。您可以聊童年趣事、求学经历、工作故事,或者任何难忘的回忆。", + text = "每天花几分钟聊聊往事,岁月知己会帮您把珍贵的回忆整理成一本专属回忆录。童年趣事、求学时光、工作历程……随时想聊就聊。", fontSize = AppTypography.captionLarge, color = SlatePurple, lineHeight = AppTypography.lineHeightNormal diff --git a/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/CreateMemoryScreen.kt b/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/CreateMemoryScreen.kt index 8bcee71..eae5959 100644 --- a/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/CreateMemoryScreen.kt +++ b/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/CreateMemoryScreen.kt @@ -150,6 +150,7 @@ fun CreateMemoryScreen( Scaffold( snackbarHost = { SnackbarHost(snackbarHostState) }, + contentWindowInsets = WindowInsets(0, 0, 0, 0), modifier = Modifier.fillMaxSize() ) { paddingValues -> Box(modifier = Modifier.fillMaxSize().padding(paddingValues)) { @@ -158,7 +159,7 @@ fun CreateMemoryScreen( ) { // 使用新的ChatHeader组件(内部已处理WindowInsets) ChatHeader( - title = "回忆录助手", + title = "岁月知己", isOnline = connectionStatus == "已连接", onBackClick = { navController?.popBackStack() }, onNewConversationClick = { viewModel.startConversation() } diff --git a/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/LoginScreen.kt b/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/LoginScreen.kt index e40a9da..bab0559 100644 --- a/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/LoginScreen.kt +++ b/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/LoginScreen.kt @@ -1,6 +1,10 @@ package com.huaga.life_echo.ui.screens import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.navigationBars +import androidx.compose.foundation.layout.statusBars +import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.icons.Icons @@ -93,11 +97,14 @@ fun LoginScreen( Scaffold( snackbarHost = { SnackbarHost(hostState = snackbarHostState) }, + contentWindowInsets = WindowInsets(0, 0, 0, 0), ) { paddingValues -> // 内容区域 Column( modifier = Modifier .fillMaxSize() + .windowInsetsPadding(WindowInsets.statusBars) + .windowInsetsPadding(WindowInsets.navigationBars) .padding(paddingValues) .padding(24.dp), horizontalAlignment = Alignment.CenterHorizontally, diff --git a/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/MyMemoirScreen.kt b/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/MyMemoirScreen.kt index f81cf72..b658377 100644 --- a/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/MyMemoirScreen.kt +++ b/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/MyMemoirScreen.kt @@ -16,17 +16,17 @@ import androidx.compose.material3.pulltorefresh.PullToRefreshBox import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.shadow import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel +import com.huaga.life_echo.navigation.Screen import com.huaga.life_echo.network.models.ChapterContentDto import com.huaga.life_echo.network.models.ChapterDto import com.huaga.life_echo.ui.components.common.ColoredHeader -import com.huaga.life_echo.ui.components.common.EmptyStateView -import com.huaga.life_echo.ui.components.common.SimpleCard import com.huaga.life_echo.ui.components.memoir.ChapterCard import com.huaga.life_echo.ui.components.memoir.ChapterReadingView import com.huaga.life_echo.ui.components.memoir.FullTextReadingView @@ -36,6 +36,65 @@ import com.huaga.life_echo.ui.viewmodel.MyMemoirViewModel import com.huaga.life_echo.ui.viewmodel.ViewModelFactory import kotlinx.coroutines.launch +/** + * 默认章节定义(5个人生阶段) + * 即使没有从API获取到内容,也会显示在页面上 + */ +private data class DefaultChapterInfo( + val category: String, + val title: String, + val orderIndex: Int +) + +private val DEFAULT_CHAPTERS = listOf( + DefaultChapterInfo("childhood", "童年时光", 0), + DefaultChapterInfo("education", "求学经历", 1), + DefaultChapterInfo("career", "职业生涯", 2), + DefaultChapterInfo("family", "家庭生活", 5), + DefaultChapterInfo("belief", "人生信念", 6), +) + +/** + * 合并 API 章节和默认章节占位 + * 确保所有5个阶段都有显示,有内容的用API数据,没内容的用占位 + */ +private fun mergeChaptersWithDefaults(apiChapters: List): List { + val apiCategoryMap = apiChapters.associateBy { it.category } + val result = mutableListOf() + + for (default in DEFAULT_CHAPTERS) { + val existing = apiCategoryMap[default.category] + if (existing != null) { + result.add(existing) + } else { + // 创建占位章节(空内容) + result.add( + ChapterDto( + id = "placeholder_${default.category}", + title = default.title, + content = "", + order_index = default.orderIndex, + status = "empty", + category = default.category, + images = emptyList(), + updated_at = null, + is_new = false, + source_segments = emptyList() + ) + ) + } + } + + // 添加不在默认列表中的 API 章节(如 career_early, career_achievement 等) + for (apiChapter in apiChapters) { + if (!DEFAULT_CHAPTERS.any { it.category == apiChapter.category }) { + result.add(apiChapter) + } + } + + return result.sortedBy { it.order_index } +} + @OptIn(ExperimentalMaterial3Api::class) @RequiresApi(Build.VERSION_CODES.O) @Composable @@ -72,9 +131,9 @@ fun MyMemoirScreen( viewModel.refreshChapters() } - // 转换Chapter为ChapterDto用于显示 + // 转换Chapter为ChapterDto并与默认章节合并 val chapterDtos = remember(chapters, chapterDtosFromApi) { - if (chapterDtosFromApi.isNotEmpty()) { + val apiChapters = if (chapterDtosFromApi.isNotEmpty()) { chapterDtosFromApi } else { chapters.map { chapter -> @@ -92,6 +151,12 @@ fun MyMemoirScreen( ) } } + mergeChaptersWithDefaults(apiChapters) + } + + // 有内容的章节(用于全文阅读和浮动按钮) + val contentChapters = remember(chapterDtos) { + chapterDtos.filter { it.content.isNotBlank() } } AnimatedContent( @@ -109,9 +174,9 @@ fun MyMemoirScreen( ) { isReading -> if (isReading) { if (showFullTextReading) { - // 全文阅读视图 + // 全文阅读视图(只包含有内容的章节) FullTextReadingView( - chapters = chapterDtos.map { dto -> + chapters = contentChapters.map { dto -> ChapterContentDto( id = dto.id, title = dto.title, @@ -193,17 +258,26 @@ fun MyMemoirScreen( MemoirTableOfContents( bookInfo = bookInfo, chapterDtos = chapterDtos, + contentChapterCount = contentChapters.size, isRefreshing = isRefreshing, onRefresh = { handleRefresh() }, onChapterClick = { chapterDto -> - chapters.find { it.id == chapterDto.id }?.let { chapter -> - viewModel.selectChapter(chapter) + // 只有有内容的章节才能点击进入阅读 + if (chapterDto.content.isNotBlank()) { + chapters.find { it.id == chapterDto.id }?.let { chapter -> + viewModel.selectChapter(chapter) + } } }, onReadAllClick = { viewModel.toggleFullTextReading() }, onTitleChange = { title -> viewModel.updateBookTitle(title, null) }, onSubtitleChange = { subtitle -> bookInfo?.let { viewModel.updateBookTitle(it.title, subtitle) } + }, + onNavigateToChat = { + navController?.navigate(Screen.ConversationList.route) { + popUpTo(Screen.ConversationList.route) { inclusive = true } + } } ) } @@ -218,12 +292,14 @@ fun MyMemoirScreen( private fun MemoirTableOfContents( bookInfo: com.huaga.life_echo.network.models.BookDto?, chapterDtos: List, + contentChapterCount: Int, isRefreshing: Boolean, onRefresh: () -> Unit, onChapterClick: (ChapterDto) -> Unit, onReadAllClick: () -> Unit, onTitleChange: (String) -> Unit, - onSubtitleChange: (String) -> Unit + onSubtitleChange: (String) -> Unit, + onNavigateToChat: () -> Unit ) { Box( modifier = Modifier @@ -260,56 +336,109 @@ private fun MemoirTableOfContents( // 书籍信息卡片 item { BookHeaderCard( - title = bookInfo?.title ?: "这一生", - subtitle = "我的回忆录", - updatedAt = bookInfo?.let { "更新于 2 分钟前" } ?: "", - modifier = Modifier.padding(bottom = AppDimensions.sectionSpacing) + title = bookInfo?.title ?: "我的回忆录", + subtitle = if (contentChapterCount > 0) { + "已记录 $contentChapterCount 个章节" + } else { + "开始和岁月知己聊天吧" + }, + updatedAt = bookInfo?.let { "下拉刷新获取最新内容" } ?: "", + modifier = Modifier.padding(bottom = 8.dp) + ) + } + + // 章节进度提示 + item { + ChapterProgressHint( + totalChapters = chapterDtos.size, + filledChapters = contentChapterCount, + modifier = Modifier.padding(bottom = AppDimensions.itemSpacing) ) } - // 如果没有章节,显示空状态 - if (chapterDtos.isEmpty()) { - item { - EmptyStateView( - title = "还没有章节", - message = "开始对话,让AI帮您整理回忆录章节", - icon = "📖", - modifier = Modifier - .fillMaxWidth() - .padding(top = 48.dp) - ) - } - } else { - // 章节列表 - items(chapterDtos.sortedBy { it.order_index }, key = { it.id }) { chapterDto -> - ChapterCard( - chapter = chapterDto, - onClick = { onChapterClick(chapterDto) } - ) - Spacer(modifier = Modifier.height(AppDimensions.itemSpacing)) - } - - // 底部空间,为浮动按钮留出空间 - item { - Spacer(modifier = Modifier.height(100.dp)) - } + // 章节列表(始终显示所有章节) + items(chapterDtos, key = { it.id }) { chapterDto -> + val isEmpty = chapterDto.content.isBlank() + ChapterCard( + chapter = chapterDto, + isEmpty = isEmpty, + onClick = { onChapterClick(chapterDto) }, + onGoChat = if (isEmpty) onNavigateToChat else null + ) + Spacer(modifier = Modifier.height(AppDimensions.itemSpacing)) + } + + // 底部空间,为浮动按钮留出空间 + item { + Spacer(modifier = Modifier.height(100.dp)) } } } } - // 浮动阅读全文按钮 - if (chapterDtos.isNotEmpty()) { + // 浮动阅读全文按钮(只在有内容的章节时显示) + if (contentChapterCount > 0) { FloatingReadAllButton( onClick = onReadAllClick, modifier = Modifier .align(Alignment.BottomCenter) - .padding(bottom = 100.dp) // 为底部导航栏留出空间 + .padding(bottom = 64.dp) // 紧贴底部导航栏上方 ) } } } +/** + * 章节进度提示条 + */ +@Composable +private fun ChapterProgressHint( + totalChapters: Int, + filledChapters: Int, + modifier: Modifier = Modifier +) { + Row( + modifier = modifier + .fillMaxWidth() + .clip(RoundedCornerShape(12.dp)) + .background(Lavender.copy(alpha = 0.3f)) + .padding(horizontal = 16.dp, vertical = 12.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + // 进度指示器 + Row( + horizontalArrangement = Arrangement.spacedBy(4.dp), + verticalAlignment = Alignment.CenterVertically + ) { + repeat(totalChapters) { index -> + Box( + modifier = Modifier + .size(width = if (index < filledChapters) 16.dp else 8.dp, height = 4.dp) + .clip(RoundedCornerShape(2.dp)) + .background( + if (index < filledChapters) MediumPurple + else SlatePurple.copy(alpha = 0.3f) + ) + ) + } + } + + Text( + text = if (filledChapters == 0) { + "还没有章节内容,开始聊天吧" + } else if (filledChapters < totalChapters) { + "已完成 $filledChapters/$totalChapters 个章节" + } else { + "所有章节已完成" + }, + fontSize = AppTypography.captionMedium, + color = SlatePurple, + modifier = Modifier.weight(1f) + ) + } +} + /** * 书籍头部卡片 */ @@ -320,40 +449,37 @@ private fun BookHeaderCard( updatedAt: String, modifier: Modifier = Modifier ) { - SimpleCard(modifier = modifier) { - Column( - modifier = Modifier - .fillMaxWidth() - .padding(vertical = AppDimensions.sectionSpacing), - horizontalAlignment = Alignment.CenterHorizontally - ) { + Column( + modifier = modifier + .fillMaxWidth() + .padding(vertical = AppDimensions.sectionSpacing), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = title, + fontSize = AppTypography.headingMedium, + fontWeight = FontWeight.SemiBold, + color = DeepPurple, + textAlign = TextAlign.Center + ) + + Spacer(modifier = Modifier.height(6.dp)) + + Text( + text = subtitle, + fontSize = AppTypography.captionLarge, + color = SlatePurple, + textAlign = TextAlign.Center + ) + + if (updatedAt.isNotEmpty()) { + Spacer(modifier = Modifier.height(4.dp)) Text( - text = title, - fontSize = AppTypography.headingMedium, - fontWeight = FontWeight.SemiBold, - color = DeepPurple, + text = updatedAt, + fontSize = AppTypography.captionMedium, + color = MediumPurple.copy(alpha = 0.7f), textAlign = TextAlign.Center ) - - Spacer(modifier = Modifier.height(6.dp)) - - Text( - text = subtitle, - fontSize = AppTypography.captionLarge, - color = SlatePurple, - textAlign = TextAlign.Center - ) - - if (updatedAt.isNotEmpty()) { - Spacer(modifier = Modifier.height(6.dp)) - - Text( - text = updatedAt, - fontSize = AppTypography.captionMedium, - color = MediumPurple, - textAlign = TextAlign.Center - ) - } } } } diff --git a/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/NicknameSetupScreen.kt b/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/NicknameSetupScreen.kt index cc37c21..397713d 100644 --- a/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/NicknameSetupScreen.kt +++ b/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/NicknameSetupScreen.kt @@ -1,6 +1,10 @@ package com.huaga.life_echo.ui.screens import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.navigationBars +import androidx.compose.foundation.layout.statusBars +import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.* import androidx.compose.runtime.* @@ -56,10 +60,13 @@ fun NicknameSetupScreen( Scaffold( snackbarHost = { SnackbarHost(hostState = snackbarHostState) }, + contentWindowInsets = WindowInsets(0, 0, 0, 0), ) { paddingValues -> Column( modifier = Modifier .fillMaxSize() + .windowInsetsPadding(WindowInsets.statusBars) + .windowInsetsPadding(WindowInsets.navigationBars) .padding(paddingValues) .padding(24.dp), horizontalAlignment = Alignment.CenterHorizontally, @@ -77,7 +84,7 @@ fun NicknameSetupScreen( // 标题 Text( - text = "欢迎加入岁月时书", + text = "欢迎加入岁月留书", fontSize = 24.sp, fontWeight = FontWeight.Bold, color = MaterialTheme.colorScheme.onSurface diff --git a/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/RegisterScreen.kt b/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/RegisterScreen.kt index 295b665..545ed68 100644 --- a/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/RegisterScreen.kt +++ b/app-android/app/src/main/java/com/huaga/life_echo/ui/screens/RegisterScreen.kt @@ -1,6 +1,10 @@ package com.huaga.life_echo.ui.screens import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.navigationBars +import androidx.compose.foundation.layout.statusBars +import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.KeyboardOptions @@ -96,11 +100,14 @@ fun RegisterScreen( Scaffold( snackbarHost = { SnackbarHost(hostState = snackbarHostState) }, + contentWindowInsets = WindowInsets(0, 0, 0, 0), ) { paddingValues -> Box(modifier = Modifier.fillMaxSize()) { LazyColumn( modifier = Modifier .fillMaxSize() + .windowInsetsPadding(WindowInsets.statusBars) + .windowInsetsPadding(WindowInsets.navigationBars) .padding(paddingValues) .padding(24.dp), horizontalAlignment = Alignment.CenterHorizontally, diff --git a/app-android/app/src/main/java/com/huaga/life_echo/ui/viewmodel/AuthViewModel.kt b/app-android/app/src/main/java/com/huaga/life_echo/ui/viewmodel/AuthViewModel.kt index cee7e2b..93f6d3d 100644 --- a/app-android/app/src/main/java/com/huaga/life_echo/ui/viewmodel/AuthViewModel.kt +++ b/app-android/app/src/main/java/com/huaga/life_echo/ui/viewmodel/AuthViewModel.kt @@ -163,7 +163,7 @@ class AuthViewModel(private val context: Context) : ViewModel() { _operationResult.value = OperationResult( success = true, message = "注册成功", - details = "账号已创建,欢迎加入岁月时书!正在跳转..." + details = "账号已创建,欢迎加入岁月留书!正在跳转..." ) }, onFailure = { exception -> @@ -378,7 +378,7 @@ class AuthViewModel(private val context: Context) : ViewModel() { success = true, message = if (isNewUser) "注册成功" else "登录成功", details = if (isNewUser) { - "账号已创建,欢迎加入岁月时书!正在跳转..." + "账号已创建,欢迎加入岁月留书!正在跳转..." } else { "欢迎回来,${userNickname}!正在跳转..." } @@ -440,7 +440,7 @@ class AuthViewModel(private val context: Context) : ViewModel() { _operationResult.value = OperationResult( success = true, message = "注册成功", - details = "账号已创建,欢迎加入岁月时书!正在跳转..." + details = "账号已创建,欢迎加入岁月留书!正在跳转..." ) }, onFailure = { exception -> @@ -662,7 +662,7 @@ class AuthViewModel(private val context: Context) : ViewModel() { _operationResult.value = OperationResult( success = true, message = "欢迎", - details = "欢迎加入岁月时书,${userResponse.nickname}!" + details = "欢迎加入岁月留书,${userResponse.nickname}!" ) onSuccess() }, diff --git a/app-android/app/src/main/res/drawable/avatar_assistant.png b/app-android/app/src/main/res/drawable/avatar_assistant.png new file mode 100644 index 0000000000000000000000000000000000000000..ddd66556f77fd5edaba17dc23d1ec89778d2237c GIT binary patch literal 62273 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

^@jKYi`pr}cAL{(OA+t529KlQMTc$Q!jqpQvi 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 - 岁月时书 + Life Echo Chat diff --git a/app-android/app/src/main/res/values/strings.xml b/app-android/app/src/main/res/values/strings.xml index 22c291c..1aa0941 100644 --- a/app-android/app/src/main/res/values/strings.xml +++ b/app-android/app/src/main/res/values/strings.xml @@ -1,5 +1,5 @@ - 岁月时书 + 岁月留书 聊天 diff --git a/app-ios/components/memoir/ChapterContent.tsx b/app-ios/components/memoir/ChapterContent.tsx index 1ff2041..791c52b 100644 --- a/app-ios/components/memoir/ChapterContent.tsx +++ b/app-ios/components/memoir/ChapterContent.tsx @@ -13,7 +13,7 @@ export function ChapterContent({ chapter }: ChapterContentProps) { if (!chapter.content) { return ( - 这一章还没有内容,快去和回忆录助手聊聊吧! + 这一章还没有内容,快去和岁月知己聊聊吧! ); } diff --git a/app-ios/components/memoir/FullMemoirContent.tsx b/app-ios/components/memoir/FullMemoirContent.tsx index 50e77c4..bc04d2d 100644 --- a/app-ios/components/memoir/FullMemoirContent.tsx +++ b/app-ios/components/memoir/FullMemoirContent.tsx @@ -14,7 +14,7 @@ function renderChapterContent(content: string | undefined) { if (!content) { return ( - 这一章还没有内容,快去和回忆录助手聊聊吧! + 这一章还没有内容,快去和岁月知己聊聊吧! ); } diff --git a/app-ios/data/mockData.ts b/app-ios/data/mockData.ts index 2487bdb..fb736f0 100644 --- a/app-ios/data/mockData.ts +++ b/app-ios/data/mockData.ts @@ -56,7 +56,7 @@ export interface SettingItem { export const mockConversations: Conversation[] = [ { id: '1', - title: '回忆录助手', + title: '岁月知己', avatarEmoji: '📖', lastMessage: '您想从哪里开始呢?可以聊聊童年...', timestamp: '刚刚', @@ -70,7 +70,7 @@ export const mockMessages: Message[] = [ conversationId: '1', senderType: 'ai', contentType: 'text', - content: '您好!我是您的回忆录助手,很高兴能陪您聊聊往事。😊\n\n您想从哪里开始呢?可以聊聊童年、上学时光,或者任何您想分享的故事。', + content: '您好!我是您的岁月知己,很高兴能陪您聊聊往事。😊\n\n您想从哪里开始呢?可以聊聊童年、上学时光,或者任何您想分享的故事。', timestamp: '14:30', }, ];