refactor: 更新应用名称与对话提示以增强用户体验
- 将应用名称从“岁月时书”更改为“岁月留书”,并在多个文件中更新相关文本。 - 在对话提示中将“回忆录助手”替换为“岁月知己”,以统一用户体验。 - 添加新的头像资源以匹配更新后的助手名称。 - 更新多个界面和文档中的文本,以反映新的品牌形象和功能。
This commit is contained in:
@@ -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}
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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** - 让每一段人生故事都被温柔记录 📱✨
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
),
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
) {
|
||||
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(if (isAI) Lavender else BlushPink),
|
||||
.background(BlushPink),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
if (isAI) {
|
||||
// 使用书本图标表示AI助手
|
||||
Icon(
|
||||
imageVector = AppIcons.Book,
|
||||
contentDescription = "AI助手",
|
||||
tint = DeepPurple,
|
||||
modifier = Modifier.size(20.dp)
|
||||
)
|
||||
} else {
|
||||
// 使用人物图标表示用户
|
||||
Icon(
|
||||
imageVector = AppIcons.Person,
|
||||
|
||||
@@ -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,13 +197,23 @@ fun ConversationAvatar(
|
||||
isDefaultAssistant: Boolean,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
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(if (isDefaultAssistant) Lavender else BlushPink),
|
||||
.background(BlushPink),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
if (avatarUrl != null && !isDefaultAssistant) {
|
||||
if (avatarUrl != null) {
|
||||
// TODO: 使用 Coil 或 Glide 加载网络图片
|
||||
Icon(
|
||||
imageVector = AppIcons.Conversation,
|
||||
@@ -209,14 +221,6 @@ fun ConversationAvatar(
|
||||
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,
|
||||
@@ -227,3 +231,4 @@ fun ConversationAvatar(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 估算页数(基于内容长度)
|
||||
*/
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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() }
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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<ChapterDto>): List<ChapterDto> {
|
||||
val apiCategoryMap = apiChapters.associateBy { it.category }
|
||||
val result = mutableListOf<ChapterDto>()
|
||||
|
||||
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 ->
|
||||
// 只有有内容的章节才能点击进入阅读
|
||||
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<ChapterDto>,
|
||||
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,31 +336,34 @@ 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)
|
||||
)
|
||||
}
|
||||
|
||||
// 如果没有章节,显示空状态
|
||||
if (chapterDtos.isEmpty()) {
|
||||
// 章节进度提示
|
||||
item {
|
||||
EmptyStateView(
|
||||
title = "还没有章节",
|
||||
message = "开始对话,让AI帮您整理回忆录章节",
|
||||
icon = "📖",
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 48.dp)
|
||||
ChapterProgressHint(
|
||||
totalChapters = chapterDtos.size,
|
||||
filledChapters = contentChapterCount,
|
||||
modifier = Modifier.padding(bottom = AppDimensions.itemSpacing)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
// 章节列表
|
||||
items(chapterDtos.sortedBy { it.order_index }, key = { it.id }) { chapterDto ->
|
||||
|
||||
// 章节列表(始终显示所有章节)
|
||||
items(chapterDtos, key = { it.id }) { chapterDto ->
|
||||
val isEmpty = chapterDto.content.isBlank()
|
||||
ChapterCard(
|
||||
chapter = chapterDto,
|
||||
onClick = { onChapterClick(chapterDto) }
|
||||
isEmpty = isEmpty,
|
||||
onClick = { onChapterClick(chapterDto) },
|
||||
onGoChat = if (isEmpty) onNavigateToChat else null
|
||||
)
|
||||
Spacer(modifier = Modifier.height(AppDimensions.itemSpacing))
|
||||
}
|
||||
@@ -296,20 +375,70 @@ private fun MemoirTableOfContents(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 浮动阅读全文按钮
|
||||
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,9 +449,8 @@ private fun BookHeaderCard(
|
||||
updatedAt: String,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
SimpleCard(modifier = modifier) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = AppDimensions.sectionSpacing),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
@@ -345,18 +473,16 @@ private fun BookHeaderCard(
|
||||
)
|
||||
|
||||
if (updatedAt.isNotEmpty()) {
|
||||
Spacer(modifier = Modifier.height(6.dp))
|
||||
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
Text(
|
||||
text = updatedAt,
|
||||
fontSize = AppTypography.captionMedium,
|
||||
color = MediumPurple,
|
||||
color = MediumPurple.copy(alpha = 0.7f),
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 浮动阅读全文按钮
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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()
|
||||
},
|
||||
|
||||
BIN
app-android/app/src/main/res/drawable/avatar_assistant.png
Normal file
BIN
app-android/app/src/main/res/drawable/avatar_assistant.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 61 KiB |
@@ -1,5 +1,5 @@
|
||||
<resources>
|
||||
<string name="app_name">岁月时书</string>
|
||||
<string name="app_name">Life Echo</string>
|
||||
|
||||
<!-- Navigation -->
|
||||
<string name="nav_chat">Chat</string>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<resources>
|
||||
<string name="app_name">岁月时书</string>
|
||||
<string name="app_name">岁月留书</string>
|
||||
|
||||
<!-- Navigation -->
|
||||
<string name="nav_chat">聊天</string>
|
||||
|
||||
@@ -13,7 +13,7 @@ export function ChapterContent({ chapter }: ChapterContentProps) {
|
||||
if (!chapter.content) {
|
||||
return (
|
||||
<Text style={styles.emptyText}>
|
||||
这一章还没有内容,快去和回忆录助手聊聊吧!
|
||||
这一章还没有内容,快去和岁月知己聊聊吧!
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ function renderChapterContent(content: string | undefined) {
|
||||
if (!content) {
|
||||
return (
|
||||
<Text style={styles.emptyText}>
|
||||
这一章还没有内容,快去和回忆录助手聊聊吧!
|
||||
这一章还没有内容,快去和岁月知己聊聊吧!
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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',
|
||||
},
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user