From 9c9afbd108c93b0bfa94b37d8274ec4a7e6a9912 Mon Sep 17 00:00:00 2001 From: lanyuanxiaoyao Date: Tue, 2 Jun 2026 08:43:26 +0800 Subject: [PATCH] =?UTF-8?q?feat(chat):=20=E4=BC=98=E5=8C=96=E8=81=8A?= =?UTF-8?q?=E5=A4=A9=E9=9D=A2=E6=9D=BF=E4=BA=A4=E4=BA=92=E4=BD=93=E9=AA=8C?= =?UTF-8?q?=20=E2=80=94=20=E6=8E=A8=E7=90=86=E6=8A=98=E5=8F=A0/=E6=99=BA?= =?UTF-8?q?=E8=83=BD=E6=BB=9A=E5=8A=A8/=E5=B7=A5=E5=85=B7=E4=B8=AD?= =?UTF-8?q?=E6=96=87=E5=90=8D/=E4=BB=A3=E7=A0=81=E5=9D=97=E6=8C=89?= =?UTF-8?q?=E9=92=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/server/ai/tools/get-current-time.ts | 1 + .../workbench/components/chat/ChatPanel.tsx | 18 ++- .../components/chat/parts/ReasoningPart.tsx | 23 ++- .../components/chat/parts/TextPart.tsx | 21 ++- .../components/chat/parts/ToolPart.tsx | 5 +- .../components/chat/use-chat-scroll.ts | 55 +++++++ src/web/styles.css | 42 ++++++ .../components/chat/ReasoningPart.test.tsx | 49 +++++++ tests/web/components/chat/ToolPart.test.tsx | 65 +++++++++ tests/web/hooks/use-chat-scroll.test.ts | 137 ++++++++++++++++++ 10 files changed, 408 insertions(+), 8 deletions(-) create mode 100644 src/web/consoles/workbench/components/chat/use-chat-scroll.ts create mode 100644 tests/web/components/chat/ReasoningPart.test.tsx create mode 100644 tests/web/components/chat/ToolPart.test.tsx create mode 100644 tests/web/hooks/use-chat-scroll.test.ts diff --git a/src/server/ai/tools/get-current-time.ts b/src/server/ai/tools/get-current-time.ts index 4077a8f..34a20e8 100644 --- a/src/server/ai/tools/get-current-time.ts +++ b/src/server/ai/tools/get-current-time.ts @@ -10,6 +10,7 @@ export function createGetCurrentTime(logger?: Logger) { inputSchema: z.object({ timezone: z.string().optional().describe("IANA 时区名称,如 'Asia/Shanghai'、'America/New_York'"), }), + metadata: { displayName: "获取当前时间" }, }); } diff --git a/src/web/consoles/workbench/components/chat/ChatPanel.tsx b/src/web/consoles/workbench/components/chat/ChatPanel.tsx index 9f47098..3b815fa 100644 --- a/src/web/consoles/workbench/components/chat/ChatPanel.tsx +++ b/src/web/consoles/workbench/components/chat/ChatPanel.tsx @@ -1,5 +1,5 @@ import { useChat } from "@ai-sdk/react"; -import { CopyOutlined, EditOutlined, RedoOutlined, RobotOutlined } from "@ant-design/icons"; +import { ArrowDownOutlined, CopyOutlined, EditOutlined, RedoOutlined, RobotOutlined } from "@ant-design/icons"; import { useQueryClient } from "@tanstack/react-query"; import { DefaultChatTransport, type UIMessage } from "ai"; import { App, Button, Card, Flex, Input, Spin, Typography } from "antd"; @@ -17,6 +17,7 @@ import { ChatInputArea } from "./ChatInputArea"; import { ReasoningPart } from "./parts/ReasoningPart"; import { TextPart } from "./parts/TextPart"; import { ToolPart } from "./parts/ToolPart"; +import { useChatScroll } from "./use-chat-scroll"; interface ChatPanelProps { conversationId: null | string; @@ -55,6 +56,8 @@ export function ChatPanel({ conversationId, onConversationCreated, projectId }: const isLoading = status === "submitted" || status === "streaming"; + const { isAtBottom, scrollToBottom } = useChatScroll({ messages, scrollRef, status }); + useEffect(() => { if (!conversationId) { setMessages([]); @@ -125,10 +128,6 @@ export function ChatPanel({ conversationId, onConversationCreated, projectId }: }); }, [conversationId, textModels, projectId, logger]); - useEffect(() => { - scrollRef.current?.scrollTo({ behavior: "smooth", top: scrollRef.current.scrollHeight }); - }, [messages]); - useEffect(() => { if (status === "ready" && conversationId) { void queryClient.invalidateQueries({ queryKey: ["conversations", projectId] }); @@ -380,6 +379,15 @@ export function ChatPanel({ conversationId, onConversationCreated, projectId }: )} + {!isAtBottom && ( +