From 4897a4da582e338e9c110c87fb722c35cdfa3d88 Mon Sep 17 00:00:00 2001 From: MT-Fire <798521692@qq.com> Date: Sun, 15 Mar 2026 15:07:19 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=E8=81=8A=E5=A4=A9?= =?UTF-8?q?=E7=95=8C=E9=9D=A2UI=E4=B8=8E=E4=BA=A4=E4=BA=92=E4=BD=93?= =?UTF-8?q?=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增退出确认对话框,点击返回时提示用户保存 - Artifact 面板改用 DropdownMenu 选择文件,优化头部布局 - 添加微软雅黑字体支持,调整主题配色 - Todo 按钮添加 Tooltip 提示 - 调整面板分割比例为 50/50,优化样式细节 --- .../app/workspace/chats/[thread_id]/page.tsx | 50 ++++-- .../src/components/ai-elements/artifact.tsx | 4 +- frontend/src/components/ui/card.tsx | 2 +- frontend/src/components/ui/dev-dialog.tsx | 144 ++++++++++++++++++ frontend/src/components/ui/resizable.tsx | 2 +- .../artifacts/artifact-file-detail.tsx | 65 ++++---- .../workspace/artifacts/artifact-trigger.tsx | 2 +- .../components/workspace/chats/chat-box.tsx | 4 +- .../components/workspace/dev-todo-list.tsx | 3 - .../src/components/workspace/input-box.tsx | 5 +- .../workspace/messages/message-group.tsx | 2 +- .../workspace/messages/message-list.tsx | 1 + frontend/src/core/i18n/locales/zh-CN.ts | 2 +- frontend/src/styles/globals.css | 11 +- 14 files changed, 237 insertions(+), 60 deletions(-) create mode 100644 frontend/src/components/ui/dev-dialog.tsx diff --git a/frontend/src/app/workspace/chats/[thread_id]/page.tsx b/frontend/src/app/workspace/chats/[thread_id]/page.tsx index 4ce7c0b0..8572acb7 100644 --- a/frontend/src/app/workspace/chats/[thread_id]/page.tsx +++ b/frontend/src/app/workspace/chats/[thread_id]/page.tsx @@ -1,9 +1,17 @@ "use client"; -import { useCallback } from "react"; +import { useCallback, useState } from "react"; +import { ListTodoIcon } from "lucide-react"; import { type PromptInputMessage } from "@/components/ai-elements/prompt-input"; import { Button } from "@/components/ui/button"; +import { + DevDialog, + DevDialogContent, + DevDialogFooter, + DevDialogHeader, + DevDialogTitle, +} from "@/components/ui/dev-dialog"; import { ArtifactTrigger } from "@/components/workspace/artifacts"; import { ChatBox, @@ -11,6 +19,7 @@ import { useThreadChat, } from "@/components/workspace/chats"; import { DevTodoList } from "@/components/workspace/dev-todo-list"; +import { Tooltip } from "@/components/workspace/tooltip"; import { InputBox } from "@/components/workspace/input-box"; import { MessageList } from "@/components/workspace/messages"; import { ThreadContext } from "@/components/workspace/messages/context"; @@ -27,6 +36,7 @@ import { cn } from "@/lib/utils"; export default function ChatPage() { const { t } = useI18n(); const [settings, setSettings] = useLocalSettings(); + const [showExitDialog, setShowExitDialog] = useState(false); const { threadId, isNewThread, setIsNewThread, isMock } = useThreadChat(); useSpecificChatMode(); @@ -73,7 +83,7 @@ export default function ChatPage() { return ( -
+
{/* 返回查看结果左箭头 */}
- - - +
-
+ + {/* 退出确认对话框 */} + + + + 提示 + +

+ 退出后,当前会话结束并销毁,请先下载保存当前结果! +

+ + + + +
+
); } diff --git a/frontend/src/components/ai-elements/artifact.tsx b/frontend/src/components/ai-elements/artifact.tsx index 550dfa11..ed076cbf 100644 --- a/frontend/src/components/ai-elements/artifact.tsx +++ b/frontend/src/components/ai-elements/artifact.tsx @@ -16,7 +16,7 @@ export type ArtifactProps = HTMLAttributes; export const Artifact = ({ className, ...props }: ArtifactProps) => (
(
) {
) { + return +} + +function DevDialogTrigger({ + ...props +}: React.ComponentProps) { + return +} + +function DevDialogPortal({ + ...props +}: React.ComponentProps) { + return +} + +function DevDialogClose({ + ...props +}: React.ComponentProps) { + return +} + +function DevDialogOverlay({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function DevDialogContent({ + className, + children, + showCloseButton = true, + ...props +}: React.ComponentProps & { + showCloseButton?: boolean +}) { + return ( + + + + {children} + {showCloseButton && ( + + + Close + + )} + + + ) +} + +function DevDialogHeader({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function DevDialogFooter({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function DevDialogTitle({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function DevDialogDescription({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +export { + DevDialog, + DevDialogClose, + DevDialogContent, + DevDialogDescription, + DevDialogFooter, + DevDialogHeader, + DevDialogOverlay, + DevDialogPortal, + DevDialogTitle, + DevDialogTrigger, +} \ No newline at end of file diff --git a/frontend/src/components/ui/resizable.tsx b/frontend/src/components/ui/resizable.tsx index 2a04e8ef..18577c8e 100644 --- a/frontend/src/components/ui/resizable.tsx +++ b/frontend/src/components/ui/resizable.tsx @@ -39,7 +39,7 @@ function ResizableHandle({ div]:rotate-90", + "focus-visible:ring-ring relative flex w-px items-center justify-center after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:ring-1 focus-visible:ring-offset-1 focus-visible:outline-hidden data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:translate-x-0 data-[panel-group-direction=vertical]:after:-translate-y-1/2 [&[data-panel-group-direction=vertical]>div]:rotate-90", className, )} {...props} diff --git a/frontend/src/components/workspace/artifacts/artifact-file-detail.tsx b/frontend/src/components/workspace/artifacts/artifact-file-detail.tsx index 0539d181..40a654c1 100644 --- a/frontend/src/components/workspace/artifacts/artifact-file-detail.tsx +++ b/frontend/src/components/workspace/artifacts/artifact-file-detail.tsx @@ -20,13 +20,13 @@ import { ArtifactHeader, ArtifactTitle, } from "@/components/ai-elements/artifact"; -import { Select, SelectItem } from "@/components/ui/select"; import { - SelectContent, - SelectGroup, - SelectTrigger, - SelectValue, -} from "@/components/ui/select"; + DropdownMenu, + DropdownMenuContent, + DropdownMenuRadioGroup, + DropdownMenuRadioItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"; import { CodeEditor } from "@/components/workspace/code-editor"; import { useArtifactContent } from "@/core/artifacts/hooks"; @@ -125,33 +125,10 @@ export function ArtifactFileDetail({ }, [threadId, filepath, isInstalling]); return ( - -
- - {isWriteFile ? ( -
{getFileName(filepath)}
- ) : ( - - )} -
-
-
+ +
{isSupportPreview && ( )}
-
+
+ + {isWriteFile ? ( +
{getFileName(filepath)}
+ ) : ( + + + {getFileName(filepath)} + + + + {(artifacts ?? []).map((artifactPath) => ( + + {getFileName(artifactPath)} + + ))} + + + + )} +
+
+
{!isWriteFile && filepath.endsWith(".skill") && ( @@ -234,7 +233,7 @@ export function ArtifactFileDetail({
- + {isSupportPreview && viewMode === "preview" && (language === "markdown" || language === "html") && ( diff --git a/frontend/src/components/workspace/artifacts/artifact-trigger.tsx b/frontend/src/components/workspace/artifacts/artifact-trigger.tsx index df1fe684..7933c661 100644 --- a/frontend/src/components/workspace/artifacts/artifact-trigger.tsx +++ b/frontend/src/components/workspace/artifacts/artifact-trigger.tsx @@ -16,7 +16,7 @@ export const ArtifactTrigger = () => { return (