From 2f25316e83b6abbcec7f65e47bc8f5536938cef7 Mon Sep 17 00:00:00 2001 From: iven Date: Thu, 9 Apr 2026 17:48:18 +0800 Subject: [PATCH] =?UTF-8?q?feat(desktop):=20simple=20mode=20UI=20=E2=80=94?= =?UTF-8?q?=20ChatArea=20compact=20+=20SimpleSidebar=20+=20RightPanel=20du?= =?UTF-8?q?al-mode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adapt ChatArea for compact/butler mode: - Add onOpenDetail prop for expanding to full view - Remove inline export dialog (moved to detail view) - Replace SquarePen with ClipboardList icon Add SimpleSidebar component for butler simple mode: - Two tabs: 对话 / 行业资讯 - Quick suggestion buttons - Minimal navigation RightPanel refactoring for dual-mode support: - Detect simple vs professional mode - Conditional rendering based on butler mode state --- desktop/src/components/ChatArea.tsx | 47 ++------ desktop/src/components/RightPanel.tsx | 139 ++++++++++++++--------- desktop/src/components/SimpleSidebar.tsx | 120 +++++++++++++++++++ 3 files changed, 213 insertions(+), 93 deletions(-) create mode 100644 desktop/src/components/SimpleSidebar.tsx diff --git a/desktop/src/components/ChatArea.tsx b/desktop/src/components/ChatArea.tsx index 4852ae7..63a4736 100644 --- a/desktop/src/components/ChatArea.tsx +++ b/desktop/src/components/ChatArea.tsx @@ -10,7 +10,7 @@ import { useConfigStore } from '../store/configStore'; import { useSaaSStore } from '../store/saasStore'; import { type UnlistenFn } from '@tauri-apps/api/event'; import { safeListenEvent } from '../lib/safe-tauri'; -import { Paperclip, SquarePen, ArrowUp, MessageSquare, Download, X, FileText, Image as ImageIcon, Search } from 'lucide-react'; +import { Paperclip, ArrowUp, MessageSquare, Download, X, FileText, Image as ImageIcon, Search, ClipboardList } from 'lucide-react'; import { Button, EmptyState, MessageListSkeleton, LoadingDots } from './ui'; import { ResizableChatLayout } from './ai/ResizableChatLayout'; import { ArtifactPanel } from './ai/ArtifactPanel'; @@ -49,11 +49,11 @@ const DEFAULT_MESSAGE_HEIGHTS: Record = { // Threshold for enabling virtualization (messages count) const VIRTUALIZATION_THRESHOLD = 100; -export function ChatArea({ compact }: { compact?: boolean }) { +export function ChatArea({ compact, onOpenDetail }: { compact?: boolean; onOpenDetail?: () => void }) { const { messages, isStreaming, isLoading, sendMessage: sendToGateway, initStreamListener, - newConversation, chatMode, setChatMode, suggestions, + chatMode, setChatMode, suggestions, totalInputTokens, totalOutputTokens, } = useChatStore(); const currentAgent = useConversationStore((s) => s.currentAgent); @@ -239,23 +239,6 @@ export function ChatArea({ compact }: { compact?: boolean }) { const connected = connectionState === 'connected'; - // Export current conversation as Markdown - const exportCurrentConversation = () => { - const title = currentAgent?.name || 'ZCLAW 对话'; - const lines = [`# ${title}`, '', `导出时间: ${new Date().toLocaleString('zh-CN')}`, '']; - for (const msg of messages) { - const label = msg.role === 'user' ? '用户' : msg.role === 'assistant' ? '助手' : msg.role; - lines.push(`## ${label}`, '', msg.content, ''); - } - const blob = new Blob([lines.join('\n')], { type: 'text/markdown;charset=utf-8' }); - const url = URL.createObjectURL(blob); - const a = document.createElement('a'); - a.href = url; - a.download = `${title.replace(/[/\\?%*:|"<>]/g, '_')}.md`; - a.click(); - URL.revokeObjectURL(url); - }; - // Build artifact panel content const artifactRightPanel = ( )} - {messages.length > 0 && ( + {/* 详情按钮 (简洁模式) */} + {compact && onOpenDetail && ( - )} - {messages.length > 0 && ( - )} diff --git a/desktop/src/components/RightPanel.tsx b/desktop/src/components/RightPanel.tsx index 3d7c1eb..467620d 100644 --- a/desktop/src/components/RightPanel.tsx +++ b/desktop/src/components/RightPanel.tsx @@ -85,7 +85,11 @@ import { Button, Badge } from './ui'; import { getPersonalityById } from '../lib/personality-presets'; import { silentErrorHandler } from '../lib/error-utils'; -export function RightPanel() { +interface RightPanelProps { + simpleMode?: boolean; +} + +export function RightPanel({ simpleMode = false }: RightPanelProps) { // Connection store const connectionState = useConnectionStore((s) => s.connectionState); const gatewayVersion = useConnectionStore((s) => s.gatewayVersion); @@ -271,60 +275,85 @@ export function RightPanel() {