diff --git a/desktop/src/components/ChatArea.tsx b/desktop/src/components/ChatArea.tsx index a182b84..df9d6ae 100644 --- a/desktop/src/components/ChatArea.tsx +++ b/desktop/src/components/ChatArea.tsx @@ -7,6 +7,7 @@ import { useArtifactStore } from '../store/chat/artifactStore'; import { useConnectionStore } from '../store/connectionStore'; import { useAgentStore } from '../store/agentStore'; 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'; @@ -63,7 +64,21 @@ export function ChatArea() { const connectionState = useConnectionStore((s) => s.connectionState); const { activeClassroom, classroomOpen, closeClassroom, generating, progressPercent, progressActivity, error: classroomError, clearError: clearClassroomError } = useClassroomStore(); const clones = useAgentStore((s) => s.clones); - const models = useConfigStore((s) => s.models); + const configModels = useConfigStore((s) => s.models); + const saasModels = useSaaSStore((s) => s.availableModels); + const isLoggedIn = useSaaSStore((s) => s.isLoggedIn); + + // Merge models: SaaS available models take priority when logged in + const models = useMemo(() => { + if (isLoggedIn && saasModels.length > 0) { + return saasModels.map(m => ({ + id: m.alias || m.id, + name: m.alias || m.id, + provider: m.provider_id, + })); + } + return configModels; + }, [isLoggedIn, saasModels, configModels]); const [input, setInput] = useState(''); const [pendingFiles, setPendingFiles] = useState([]); @@ -418,8 +433,8 @@ export function ChatArea() { ) : ( } - title="Welcome to ZCLAW" - description={connected ? 'Send a message to start the conversation.' : 'Please connect to Gateway first in Settings.'} + title="欢迎使用 ZCLAW" + description={connected ? '发送消息开始对话。' : '请先在设置中连接 Gateway。'} /> )} @@ -457,7 +472,7 @@ export function ChatArea() {
{/* Suggestion chips */} - {!isStreaming && suggestions.length > 0 && ( + {!isStreaming && suggestions.length > 0 && !messages.some(m => m.error) && ( { setInput(text); textareaRef.current?.focus(); }} diff --git a/desktop/src/components/LoginPage.tsx b/desktop/src/components/LoginPage.tsx index 413ffb3..40c65a4 100644 --- a/desktop/src/components/LoginPage.tsx +++ b/desktop/src/components/LoginPage.tsx @@ -440,6 +440,7 @@ export function LoginPage() { onClick={() => setShowPassword(!showPassword)} className="absolute right-3 top-1/2 -translate-y-1/2 text-white/30 hover:text-white/60 cursor-pointer" tabIndex={-1} + aria-label={showPassword ? '隐藏密码' : '显示密码'} > {showPassword ? : } diff --git a/desktop/src/components/Settings/General.tsx b/desktop/src/components/Settings/General.tsx index 053e71c..2958e62 100644 --- a/desktop/src/components/Settings/General.tsx +++ b/desktop/src/components/Settings/General.tsx @@ -2,6 +2,7 @@ import { useState, useEffect } from 'react'; import { useConnectionStore } from '../../store/connectionStore'; import { useConfigStore } from '../../store/configStore'; import { useConversationStore } from '../../store/chat/conversationStore'; +import { useSaaSStore } from '../../store/saasStore'; import { getStoredGatewayToken, setStoredGatewayToken } from '../../lib/gateway-client'; import { silentErrorHandler } from '../../lib/error-utils'; @@ -22,6 +23,7 @@ export function General() { const connected = connectionState === 'connected'; const connecting = connectionState === 'connecting' || connectionState === 'reconnecting'; + const saasUrl = useSaaSStore((s) => s.saasUrl); // 同步主题设置 useEffect(() => { @@ -97,7 +99,9 @@ export function General() {
地址 - ws://127.0.0.1:50051 + + {gatewayVersion === 'saas-relay' && saasUrl ? saasUrl : 'ws://127.0.0.1:50051'} +
Token diff --git a/desktop/src/components/ui/EmptyState.tsx b/desktop/src/components/ui/EmptyState.tsx index 24d689d..fb9e40f 100644 --- a/desktop/src/components/ui/EmptyState.tsx +++ b/desktop/src/components/ui/EmptyState.tsx @@ -100,8 +100,8 @@ export function EmptyConversations({ action, className, size }: PrebuiltEmptySta return ( } - title="No conversations" - description="Your conversation history will appear here." + title="暂无对话" + description="你的对话历史将显示在这里。" action={action} className={className} size={size} @@ -177,8 +177,8 @@ export function EmptyAgents({ action, className, size }: PrebuiltEmptyStateProps * Empty state for welcome screen. */ export function WelcomeEmptyState({ - title = "Welcome to ZCLAW", - description = "Send a message to start the conversation.", + title = "欢迎使用 ZCLAW", + description = "发送消息开始对话。", connected = true, action, className, diff --git a/desktop/src/store/chat/streamStore.ts b/desktop/src/store/chat/streamStore.ts index 7e79a96..5794c52 100644 --- a/desktop/src/store/chat/streamStore.ts +++ b/desktop/src/store/chat/streamStore.ts @@ -410,7 +410,7 @@ export const useStreamStore = create()( _chat?.updateMessages(msgs => msgs.map(m => m.id === assistantId - ? { ...m, content: `⚠️ ${error}`, streaming: false, error } + ? { ...m, content: '', streaming: false, error } : m.role === 'user' && m.optimistic && m.timestamp.getTime() >= streamStartTime ? { ...m, optimistic: false } : m