diff --git a/src/renderer/components/MessageCard.tsx b/src/renderer/components/MessageCard.tsx
index f2e062b..60dcacf 100644
--- a/src/renderer/components/MessageCard.tsx
+++ b/src/renderer/components/MessageCard.tsx
@@ -2,6 +2,7 @@ import { useState } from 'react';
import ReactMarkdown from 'react-markdown';
import { useIPC } from '../hooks/useIPC';
import { useAppStore } from '../store';
+import { MESSAGE_CARD, CODE_BLOCK } from '../constants/ui';
import type { Message, ContentBlock, ToolUseContent, ToolResultContent, QuestionItem } from '../types';
import {
ChevronDown,
@@ -477,7 +478,27 @@ function AskUserQuestionBlock({ block }: { block: ToolUseContent }) {
}
function ToolResultBlock({ block }: { block: ToolResultContent }) {
- const [expanded, setExpanded] = useState(true);
+ // 智能判断初始展开状态:如果内容过长,默认收起
+ const contentLength = block.content?.length || 0;
+ const lineCount = block.content?.split('\n').length || 0;
+ const isLongContent =
+ contentLength > MESSAGE_CARD.TOOL_RESULT_COLLAPSE_CHARS ||
+ lineCount > MESSAGE_CARD.TOOL_RESULT_COLLAPSE_LINES;
+
+ const [expanded, setExpanded] = useState(!isLongContent);
+
+ // 生成预览文本
+ const getPreviewText = () => {
+ if (!block.content) return '';
+ const lines = block.content.split('\n');
+ const preview = lines.slice(0, MESSAGE_CARD.TOOL_RESULT_PREVIEW_LINES).join('\n');
+ if (lines.length > MESSAGE_CARD.TOOL_RESULT_PREVIEW_LINES) {
+ return preview + '\n...';
+ }
+ return preview.length > MESSAGE_CARD.TOOL_RESULT_PREVIEW_CHARS
+ ? preview.slice(0, MESSAGE_CARD.TOOL_RESULT_PREVIEW_CHARS) + '...'
+ : preview;
+ };
return (
@@ -492,9 +513,16 @@ function ToolResultBlock({ block }: { block: ToolResultContent }) {
) : (
)}
-
- {block.isError ? 'Error' : 'Result'}
-
+
+
+ {block.isError ? 'Error' : 'Result'}
+
+ {isLongContent && (
+
+ ({contentLength} 字符, {lineCount} 行)
+
+ )}
+
{expanded ? (
) : (
@@ -502,13 +530,29 @@ function ToolResultBlock({ block }: { block: ToolResultContent }) {
)}
- {expanded && (
+ {expanded ? (
- )}
+ ) : isLongContent ? (
+ // 收起状态显示预览
+
+
+ {getPreviewText()}
+
+
+
+ ) : null}
);
}
@@ -519,7 +563,7 @@ function CodeBlock({ language, children }: { language: string; children: string
const handleCopy = async () => {
await navigator.clipboard.writeText(children);
setCopied(true);
- setTimeout(() => setCopied(false), 2000);
+ setTimeout(() => setCopied(false), CODE_BLOCK.COPY_SUCCESS_DURATION);
};
return (
diff --git a/src/renderer/constants/index.ts b/src/renderer/constants/index.ts
new file mode 100644
index 0000000..cb9cb53
--- /dev/null
+++ b/src/renderer/constants/index.ts
@@ -0,0 +1,4 @@
+/**
+ * 统一导出所有常量配置
+ */
+export * from './ui';
diff --git a/src/renderer/constants/ui.ts b/src/renderer/constants/ui.ts
new file mode 100644
index 0000000..cfbb50a
--- /dev/null
+++ b/src/renderer/constants/ui.ts
@@ -0,0 +1,30 @@
+/**
+ * UI 组件常量配置
+ * 用于统一管理界面组件的阈值、限制等魔法数字
+ */
+
+/**
+ * MessageCard 组件相关常量
+ */
+export const MESSAGE_CARD = {
+ /** ToolResultBlock 折叠阈值 - 字符数 */
+ TOOL_RESULT_COLLAPSE_CHARS: 800,
+
+ /** ToolResultBlock 折叠阈值 - 行数 */
+ TOOL_RESULT_COLLAPSE_LINES: 15,
+
+ /** ToolResultBlock 预览显示行数 */
+ TOOL_RESULT_PREVIEW_LINES: 3,
+
+ /** ToolResultBlock 预览显示字符数 */
+ TOOL_RESULT_PREVIEW_CHARS: 200,
+} as const;
+
+/**
+ * CodeBlock 组件相关常量
+ */
+export const CODE_BLOCK = {
+ /** 代码复制成功提示持续时间(毫秒) */
+ COPY_SUCCESS_DURATION: 2000,
+} as const;
+