From d5d8619f223e009b44fa86980aeb8d47d3a40393 Mon Sep 17 00:00:00 2001 From: iammm0 Date: Wed, 28 Jan 2026 12:59:32 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E4=BC=98=E5=8C=96=E5=89=8D?= =?UTF-8?q?=E7=AB=AFUI=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 优化MessageBubble消息气泡组件 - 优化ErrorView错误视图组件 - 优化WebSocketDebugPanel调试面板 - 优化ChapterCard章节卡片组件 - 优化ChapterReadingView章节阅读视图 - 优化FullTextReadingView全文阅读视图 - 优化OrganizeConversationDialog组织对话对话框 - 更新AppIcons图标 --- .../ui/components/chat/MessageBubble.kt | 12 ++-- .../ui/components/common/ErrorView.kt | 66 ++++++++++++++++++- .../components/debug/WebSocketDebugPanel.kt | 6 +- .../ui/components/memoir/ChapterCard.kt | 3 +- .../components/memoir/ChapterReadingView.kt | 16 +++-- .../components/memoir/FullTextReadingView.kt | 16 +++-- .../memoir/OrganizeConversationDialog.kt | 2 +- .../com/huaga/life_echo/ui/icons/AppIcons.kt | 9 ++- 8 files changed, 104 insertions(+), 26 deletions(-) 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 f87b989..06646ff 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 @@ -20,6 +20,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import com.huaga.life_echo.ui.components.common.MarkdownText import com.huaga.life_echo.ui.theme.LightPurple /** @@ -59,6 +60,7 @@ fun UserMessageBubble( /** * AI消息气泡(左侧/白色) + * 支持 Markdown 格式渲染 */ @Composable fun AIMessageBubble( @@ -82,12 +84,12 @@ fun AIMessageBubble( containerColor = MaterialTheme.colorScheme.surface ) ) { - Text( - text = text, + MarkdownText( + content = text, modifier = Modifier.padding(12.dp), - fontSize = 14.sp, - color = MaterialTheme.colorScheme.onSurface, - lineHeight = 20.sp + textColor = MaterialTheme.colorScheme.onSurface, + fontSize = 14, + lineHeight = 20 ) } } diff --git a/app-android/app/src/main/java/com/huaga/life_echo/ui/components/common/ErrorView.kt b/app-android/app/src/main/java/com/huaga/life_echo/ui/components/common/ErrorView.kt index 6bbe297..049eb23 100644 --- a/app-android/app/src/main/java/com/huaga/life_echo/ui/components/common/ErrorView.kt +++ b/app-android/app/src/main/java/com/huaga/life_echo/ui/components/common/ErrorView.kt @@ -11,17 +11,44 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import com.huaga.life_echo.config.AppConfig import com.huaga.life_echo.ui.theme.LightPurple /** * 错误视图组件 + * + * 生产模式下自动转换技术性错误为友好提示 + * 开发模式下显示原始错误信息便于调试 + * + * @param message 错误信息(可以是原始错误或自定义信息) + * @param errorType 可选的错误类型,用于显示更精确的友好提示 + * @param onRetry 重试回调 */ @Composable fun ErrorView( message: String, + errorType: ErrorType? = null, onRetry: (() -> Unit)? = null, modifier: Modifier = Modifier ) { + // 如果指定了错误类型,使用友好错误视图 + if (errorType != null) { + FriendlyErrorView( + errorType = errorType, + originalMessage = message, + onRetry = onRetry, + modifier = modifier + ) + return + } + + // 处理显示消息:生产模式下过滤技术性错误 + val displayMessage = if (AppConfig.isDebugMode) { + message + } else { + sanitizeErrorMessage(message) + } + Column( modifier = modifier .fillMaxWidth() @@ -35,7 +62,7 @@ fun ErrorView( ) Spacer(modifier = Modifier.height(16.dp)) Text( - text = message, + text = displayMessage, fontSize = 16.sp, color = MaterialTheme.colorScheme.onSurfaceVariant, textAlign = TextAlign.Center @@ -53,3 +80,40 @@ fun ErrorView( } } } + +/** + * 清理错误消息,将技术性错误转换为用户友好的提示 + */ +private fun sanitizeErrorMessage(message: String): String { + val lowerMessage = message.lowercase() + return when { + // 网络相关错误 + lowerMessage.contains("timeout") || lowerMessage.contains("timed out") -> + "网络响应超时,请稍后重试" + lowerMessage.contains("connect") || lowerMessage.contains("network") || + lowerMessage.contains("socket") || lowerMessage.contains("unreachable") -> + "网络连接失败,请检查网络后重试" + + // 服务器相关错误 + lowerMessage.contains("500") || lowerMessage.contains("502") || + lowerMessage.contains("503") || lowerMessage.contains("server error") -> + "服务暂时不可用,请稍后重试" + + // 认证相关错误 + lowerMessage.contains("401") || lowerMessage.contains("unauthorized") || + lowerMessage.contains("token") && lowerMessage.contains("expired") -> + "登录已过期,请重新登录" + + // 资源不存在 + lowerMessage.contains("404") || lowerMessage.contains("not found") -> + "内容不存在或已被删除" + + // 异常和技术性错误(包含堆栈信息的) + lowerMessage.contains("exception") || lowerMessage.contains("stacktrace") || + message.contains("\n") || message.length > 100 -> + "操作失败,请稍后重试" + + // 保留业务相关的简短错误信息 + else -> message + } +} diff --git a/app-android/app/src/main/java/com/huaga/life_echo/ui/components/debug/WebSocketDebugPanel.kt b/app-android/app/src/main/java/com/huaga/life_echo/ui/components/debug/WebSocketDebugPanel.kt index 85c0856..e0d24ea 100644 --- a/app-android/app/src/main/java/com/huaga/life_echo/ui/components/debug/WebSocketDebugPanel.kt +++ b/app-android/app/src/main/java/com/huaga/life_echo/ui/components/debug/WebSocketDebugPanel.kt @@ -114,7 +114,7 @@ fun WebSocketDebugPanel( DebugInfoRow("是否已连接", if (isConnected) "是" else "否", if (isConnected) Color(0xFF4CAF50) else Color(0xFFF44336)) DebugInfoRow("对话ID", conversationId ?: "未设置", MaterialTheme.colorScheme.onSurfaceVariant) - Divider(modifier = Modifier.padding(vertical = 4.dp)) + HorizontalDivider(modifier = Modifier.padding(vertical = 4.dp)) // 消息统计 DebugInfoRow("消息总数", "$messageCount", MaterialTheme.colorScheme.primary) @@ -123,7 +123,7 @@ fun WebSocketDebugPanel( // 最后一条消息信息 if (lastMessageType != null) { - Divider(modifier = Modifier.padding(vertical = 4.dp)) + HorizontalDivider(modifier = Modifier.padding(vertical = 4.dp)) DebugInfoRow("最后消息类型", lastMessageType, MaterialTheme.colorScheme.primary) if (lastMessageTime != null) { DebugInfoRow("最后消息时间", lastMessageTime, MaterialTheme.colorScheme.onSurfaceVariant) @@ -132,7 +132,7 @@ fun WebSocketDebugPanel( // 错误信息 if (errorMessages.isNotEmpty()) { - Divider(modifier = Modifier.padding(vertical = 4.dp)) + HorizontalDivider(modifier = Modifier.padding(vertical = 4.dp)) Text( text = "错误日志", fontSize = 12.sp, 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 c7cfce9..1784b32 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 @@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults +import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text @@ -109,7 +110,7 @@ fun ChapterCard( // 展开时显示详细内容 if (isExpanded) { - androidx.compose.material3.Divider( + HorizontalDivider( modifier = Modifier.padding(horizontal = 16.dp) ) Column( 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 4ca621e..0efb4bb 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 @@ -13,10 +13,12 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.huaga.life_echo.network.models.ChapterContentDto +import com.huaga.life_echo.ui.components.common.MarkdownText import com.huaga.life_echo.ui.theme.LightPurple /** * 章节阅读视图组件 + * 支持 Markdown 格式渲染 */ @Composable fun ChapterReadingView( @@ -45,13 +47,13 @@ fun ChapterReadingView( modifier = Modifier.padding(bottom = 24.dp) ) - // 正文内容 - Text( - text = chapter.content, - fontSize = 16.sp, - lineHeight = 28.sp, - color = MaterialTheme.colorScheme.onSurface, - modifier = Modifier.padding(bottom = 16.dp) + // 正文内容(支持 Markdown) + MarkdownText( + content = chapter.content, + modifier = Modifier.padding(bottom = 16.dp), + textColor = MaterialTheme.colorScheme.onSurface, + fontSize = 16, + lineHeight = 28 ) // 引用块 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 dc8c132..6e3ce41 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 @@ -17,11 +17,13 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.huaga.life_echo.network.models.ChapterContentDto +import com.huaga.life_echo.ui.components.common.MarkdownText import com.huaga.life_echo.ui.icons.AppIcons import com.huaga.life_echo.ui.theme.LightPurple /** * 全文阅读视图组件 + * 支持 Markdown 格式渲染 */ @Composable fun FullTextReadingView( @@ -59,13 +61,13 @@ fun FullTextReadingView( modifier = Modifier.padding(bottom = 16.dp) ) - // 章节内容 - Text( - text = chapter.content, - fontSize = 16.sp, - lineHeight = 28.sp, - color = MaterialTheme.colorScheme.onSurface, - modifier = Modifier.padding(bottom = 16.dp) + // 章节内容(支持 Markdown) + MarkdownText( + content = chapter.content, + modifier = Modifier.padding(bottom = 16.dp), + textColor = MaterialTheme.colorScheme.onSurface, + fontSize = 16, + lineHeight = 28 ) // 引用块 diff --git a/app-android/app/src/main/java/com/huaga/life_echo/ui/components/memoir/OrganizeConversationDialog.kt b/app-android/app/src/main/java/com/huaga/life_echo/ui/components/memoir/OrganizeConversationDialog.kt index 4db04a0..32f90aa 100644 --- a/app-android/app/src/main/java/com/huaga/life_echo/ui/components/memoir/OrganizeConversationDialog.kt +++ b/app-android/app/src/main/java/com/huaga/life_echo/ui/components/memoir/OrganizeConversationDialog.kt @@ -62,7 +62,7 @@ fun OrganizeConversationDialog( } } - Divider() + HorizontalDivider() // 对话列表 if (isLoading) { diff --git a/app-android/app/src/main/java/com/huaga/life_echo/ui/icons/AppIcons.kt b/app-android/app/src/main/java/com/huaga/life_echo/ui/icons/AppIcons.kt index 29b9425..c7093c0 100644 --- a/app-android/app/src/main/java/com/huaga/life_echo/ui/icons/AppIcons.kt +++ b/app-android/app/src/main/java/com/huaga/life_echo/ui/icons/AppIcons.kt @@ -3,6 +3,7 @@ package com.huaga.life_echo.ui.icons import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.automirrored.filled.Chat +import androidx.compose.material.icons.automirrored.filled.ExitToApp import androidx.compose.material.icons.automirrored.filled.Help import androidx.compose.material.icons.automirrored.filled.MenuBook import androidx.compose.material.icons.automirrored.filled.Send @@ -85,6 +86,12 @@ object AppIcons { val ManageAccounts = Icons.Default.ManageAccounts val Lock = Icons.Default.Lock val Phone = Icons.Default.Phone - val ExitToApp = Icons.Default.ExitToApp + val ExitToApp = Icons.AutoMirrored.Filled.ExitToApp val DevicesOther = Icons.Default.DevicesOther + + // 错误处理图标 + val WifiOff = Icons.Default.WifiOff + val CloudOff = Icons.Default.CloudOff + val SearchOff = Icons.Default.SearchOff + val SignalWifiOff = Icons.Default.SignalWifiOff }