mirror of
https://gitee.com/wanwujie/deer-flow
synced 2026-04-03 14:22:13 +08:00
fix: translate into English
This commit is contained in:
@@ -3,7 +3,13 @@
|
||||
|
||||
import { LoadingOutlined } from "@ant-design/icons";
|
||||
import { motion } from "framer-motion";
|
||||
import { Download, Headphones, ChevronDown, ChevronRight, Brain } from "lucide-react";
|
||||
import {
|
||||
Download,
|
||||
Headphones,
|
||||
ChevronDown,
|
||||
ChevronRight,
|
||||
Brain,
|
||||
} from "lucide-react";
|
||||
import React, { useCallback, useMemo, useRef, useState } from "react";
|
||||
|
||||
import { LoadingAnimation } from "~/components/deer-flow/loading-animation";
|
||||
@@ -23,7 +29,11 @@ import {
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "~/components/ui/card";
|
||||
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "~/components/ui/collapsible";
|
||||
import {
|
||||
Collapsible,
|
||||
CollapsibleContent,
|
||||
CollapsibleTrigger,
|
||||
} from "~/components/ui/collapsible";
|
||||
import type { Message, Option } from "~/core/messages";
|
||||
import {
|
||||
closeResearch,
|
||||
@@ -323,59 +333,63 @@ function ThoughtBlock({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={cn("w-full mb-6", className)}>
|
||||
<div className={cn("mb-6 w-full", className)}>
|
||||
<Collapsible open={isOpen} onOpenChange={setIsOpen}>
|
||||
<CollapsibleTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
className={cn(
|
||||
"w-full justify-start px-6 py-4 h-auto text-left rounded-xl border transition-all duration-200",
|
||||
"h-auto w-full justify-start rounded-xl border px-6 py-4 text-left transition-all duration-200",
|
||||
"hover:bg-accent hover:text-accent-foreground",
|
||||
isStreaming
|
||||
? "border-primary/20 bg-primary/5 shadow-sm"
|
||||
: "border-border bg-card"
|
||||
: "border-border bg-card",
|
||||
)}
|
||||
>
|
||||
<div className="flex items-center gap-3 w-full">
|
||||
<div className="flex w-full items-center gap-3">
|
||||
<Brain
|
||||
size={18}
|
||||
className={cn(
|
||||
"shrink-0 transition-colors duration-200",
|
||||
isStreaming ? "text-primary" : "text-muted-foreground"
|
||||
isStreaming ? "text-primary" : "text-muted-foreground",
|
||||
)}
|
||||
/>
|
||||
<span className={cn(
|
||||
"font-semibold leading-none transition-colors duration-200",
|
||||
isStreaming ? "text-primary" : "text-foreground"
|
||||
)}>
|
||||
深度思考过程
|
||||
<span
|
||||
className={cn(
|
||||
"leading-none font-semibold transition-colors duration-200",
|
||||
isStreaming ? "text-primary" : "text-foreground",
|
||||
)}
|
||||
>
|
||||
Deep Thinking
|
||||
</span>
|
||||
{isStreaming && (
|
||||
<LoadingAnimation className="ml-2 scale-75" />
|
||||
)}
|
||||
{isStreaming && <LoadingAnimation className="ml-2 scale-75" />}
|
||||
<div className="flex-grow" />
|
||||
{isOpen ? (
|
||||
<ChevronDown size={16} className="text-muted-foreground transition-transform duration-200" />
|
||||
<ChevronDown
|
||||
size={16}
|
||||
className="text-muted-foreground transition-transform duration-200"
|
||||
/>
|
||||
) : (
|
||||
<ChevronRight size={16} className="text-muted-foreground transition-transform duration-200" />
|
||||
<ChevronRight
|
||||
size={16}
|
||||
className="text-muted-foreground transition-transform duration-200"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</Button>
|
||||
</CollapsibleTrigger>
|
||||
<CollapsibleContent className="mt-3 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:slide-up-2 data-[state=open]:slide-down-2">
|
||||
<Card className={cn(
|
||||
"transition-all duration-200",
|
||||
isStreaming
|
||||
? "border-primary/20 bg-primary/5"
|
||||
: "border-border"
|
||||
)}>
|
||||
<CollapsibleContent className="data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:slide-up-2 data-[state=open]:slide-down-2 mt-3">
|
||||
<Card
|
||||
className={cn(
|
||||
"transition-all duration-200",
|
||||
isStreaming ? "border-primary/20 bg-primary/5" : "border-border",
|
||||
)}
|
||||
>
|
||||
<CardContent className="py-6">
|
||||
<Markdown
|
||||
className={cn(
|
||||
"prose dark:prose-invert max-w-none transition-colors duration-200",
|
||||
isStreaming
|
||||
? "prose-primary"
|
||||
: "opacity-80"
|
||||
isStreaming ? "prose-primary" : "opacity-80",
|
||||
)}
|
||||
animated={isStreaming}
|
||||
>
|
||||
@@ -417,7 +431,9 @@ function PlanCard({
|
||||
}, [message.content]);
|
||||
|
||||
const reasoningContent = message.reasoningContent;
|
||||
const hasMainContent = Boolean(message.content && message.content.trim() !== "");
|
||||
const hasMainContent = Boolean(
|
||||
message.content && message.content.trim() !== "",
|
||||
);
|
||||
|
||||
// 判断是否正在思考:有推理内容但还没有主要内容
|
||||
const isThinking = Boolean(reasoningContent && !hasMainContent);
|
||||
@@ -461,55 +477,61 @@ function PlanCard({
|
||||
</Markdown>
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Markdown className="opacity-80" animated={message.isStreaming}>
|
||||
{plan.thought}
|
||||
</Markdown>
|
||||
{plan.steps && (
|
||||
<ul className="my-2 flex list-decimal flex-col gap-4 border-l-[2px] pl-8">
|
||||
{plan.steps.map((step, i) => (
|
||||
<li key={`step-${i}`}>
|
||||
<h3 className="mb text-lg font-medium">
|
||||
<Markdown animated={message.isStreaming}>{step.title}</Markdown>
|
||||
</h3>
|
||||
<div className="text-muted-foreground text-sm">
|
||||
<Markdown animated={message.isStreaming}>{step.description}</Markdown>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</CardContent>
|
||||
<CardFooter className="flex justify-end">
|
||||
{!message.isStreaming && interruptMessage?.options?.length && (
|
||||
<motion.div
|
||||
className="flex gap-2"
|
||||
initial={{ opacity: 0, y: 12 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.3, delay: 0.3 }}
|
||||
>
|
||||
{interruptMessage?.options.map((option) => (
|
||||
<Button
|
||||
key={option.value}
|
||||
variant={option.value === "accepted" ? "default" : "outline"}
|
||||
disabled={!waitForFeedback}
|
||||
onClick={() => {
|
||||
if (option.value === "accepted") {
|
||||
void handleAccept();
|
||||
} else {
|
||||
onFeedback?.({
|
||||
option,
|
||||
});
|
||||
}
|
||||
}}
|
||||
>
|
||||
{option.text}
|
||||
</Button>
|
||||
))}
|
||||
</motion.div>
|
||||
)}
|
||||
</CardFooter>
|
||||
</Card>
|
||||
<CardContent>
|
||||
<Markdown className="opacity-80" animated={message.isStreaming}>
|
||||
{plan.thought}
|
||||
</Markdown>
|
||||
{plan.steps && (
|
||||
<ul className="my-2 flex list-decimal flex-col gap-4 border-l-[2px] pl-8">
|
||||
{plan.steps.map((step, i) => (
|
||||
<li key={`step-${i}`}>
|
||||
<h3 className="mb text-lg font-medium">
|
||||
<Markdown animated={message.isStreaming}>
|
||||
{step.title}
|
||||
</Markdown>
|
||||
</h3>
|
||||
<div className="text-muted-foreground text-sm">
|
||||
<Markdown animated={message.isStreaming}>
|
||||
{step.description}
|
||||
</Markdown>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</CardContent>
|
||||
<CardFooter className="flex justify-end">
|
||||
{!message.isStreaming && interruptMessage?.options?.length && (
|
||||
<motion.div
|
||||
className="flex gap-2"
|
||||
initial={{ opacity: 0, y: 12 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.3, delay: 0.3 }}
|
||||
>
|
||||
{interruptMessage?.options.map((option) => (
|
||||
<Button
|
||||
key={option.value}
|
||||
variant={
|
||||
option.value === "accepted" ? "default" : "outline"
|
||||
}
|
||||
disabled={!waitForFeedback}
|
||||
onClick={() => {
|
||||
if (option.value === "accepted") {
|
||||
void handleAccept();
|
||||
} else {
|
||||
onFeedback?.({
|
||||
option,
|
||||
});
|
||||
}
|
||||
}}
|
||||
>
|
||||
{option.text}
|
||||
</Button>
|
||||
))}
|
||||
</motion.div>
|
||||
)}
|
||||
</CardFooter>
|
||||
</Card>
|
||||
</motion.div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user