feat(agents): 智能体问答页落地态展示常用问题入口并默认展开简介栏
- 落地页 Hero 以"Hi,我是{名称}"问候,将管理员配置的常用问题渲染为可点击的引导气泡,点击即发起对话
- 右侧智能体简介栏改为默认展开,作为主要"专家信息"卡片,仍可手动收起
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
6efe1b80c5
commit
17bb3715d1
3 files changed
+90
-41
No files matched your search
@@ -43,7 +43,10 @@ export function AgentInfoSidebar({
|
||||
onAskQuestion: (text: string) => void;
|
||||
disabled?: boolean;
|
||||
}) {
|
||||
const [collapsed, setCollapsed] = useState(true);
|
||||
// Expanded by default: the profile card is meant to be the agent's primary
|
||||
// "expert info" panel, not a hidden drawer. Users can still collapse it on
|
||||
// narrow screens via the header toggle.
|
||||
const [collapsed, setCollapsed] = useState(false);
|
||||
const [detailSkillName, setDetailSkillName] = useState<string | null>(null);
|
||||
const { skills } = useSkills();
|
||||
const updateAgent = useUpdateAgent();
|
||||
|
||||
@@ -1,39 +1,76 @@
|
||||
"use client";
|
||||
|
||||
import { BotIcon } from "lucide-react";
|
||||
|
||||
import { type Agent } from "@/core/agents";
|
||||
import { desensitize } from "@/lib/desensitize";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export function AgentWelcome({
|
||||
className,
|
||||
agent,
|
||||
agentName,
|
||||
}: {
|
||||
className?: string;
|
||||
agent: Agent | null | undefined;
|
||||
agentName: string;
|
||||
}) {
|
||||
const displayName = desensitize(agent?.name ?? agentName);
|
||||
const description = agent?.description
|
||||
? desensitize(agent.description)
|
||||
: undefined;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"mx-auto flex w-full flex-col items-center justify-center gap-2 px-8 py-4 text-center",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<div className="bg-primary/10 flex h-12 w-12 items-center justify-center rounded-full">
|
||||
<BotIcon className="text-primary h-6 w-6" />
|
||||
</div>
|
||||
<div className="text-2xl font-bold">{displayName}</div>
|
||||
{description && (
|
||||
<p className="text-muted-foreground max-w-sm text-sm">{description}</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
"use client";
|
||||
|
||||
import { BotIcon } from "lucide-react";
|
||||
|
||||
import { type Agent } from "@/core/agents";
|
||||
import { desensitize } from "@/lib/desensitize";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
/**
|
||||
* Landing (home) hero shown above the input box before the first message of an
|
||||
* agent conversation. Mirrors the qclaw landing screen: centered avatar, a
|
||||
* "Hi,我是{name}" greeting, the agent's one-line description as a slogan, and
|
||||
* the agent's admin-configured common questions surfaced as clickable starter
|
||||
* pills. Clicking a pill sends it as the opening message via `onAskQuestion`.
|
||||
*/
|
||||
export function AgentWelcome({
|
||||
className,
|
||||
agent,
|
||||
agentName,
|
||||
onAskQuestion,
|
||||
disabled,
|
||||
}: {
|
||||
className?: string;
|
||||
agent: Agent | null | undefined;
|
||||
agentName: string;
|
||||
onAskQuestion?: (text: string) => void;
|
||||
disabled?: boolean;
|
||||
}) {
|
||||
const displayName = desensitize(agent?.name ?? agentName);
|
||||
const description = agent?.description
|
||||
? desensitize(agent.description)
|
||||
: undefined;
|
||||
const questions = (agent?.common_questions ?? []).filter(
|
||||
(q) => q.trim().length > 0,
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"mx-auto flex w-full max-w-2xl flex-col items-center justify-center gap-3 px-6 text-center",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<div className="bg-primary/10 ring-primary/15 flex h-16 w-16 items-center justify-center rounded-2xl ring-1">
|
||||
<BotIcon className="text-primary h-8 w-8" />
|
||||
</div>
|
||||
<div className="text-2xl font-bold tracking-tight">
|
||||
Hi,我是{displayName}
|
||||
</div>
|
||||
{description && (
|
||||
<p className="text-muted-foreground max-w-md text-sm leading-relaxed">
|
||||
{description}
|
||||
</p>
|
||||
)}
|
||||
{onAskQuestion && questions.length > 0 && (
|
||||
<div className="mt-1 flex flex-wrap items-center justify-center gap-2">
|
||||
{questions.slice(0, 6).map((question, index) => (
|
||||
<button
|
||||
key={index}
|
||||
type="button"
|
||||
disabled={disabled}
|
||||
onClick={() => onAskQuestion(question)}
|
||||
title={question}
|
||||
className={cn(
|
||||
"border-border/70 bg-card/60 hover:bg-accent hover:border-border max-w-[280px] truncate rounded-full border px-4 py-2 text-sm transition-colors",
|
||||
"disabled:cursor-not-allowed disabled:opacity-50",
|
||||
)}
|
||||
>
|
||||
{desensitize(question)}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -268,7 +268,16 @@ export default function AgentChatPage() {
|
||||
context={settings.context}
|
||||
extraHeader={
|
||||
isLandingState && (
|
||||
<AgentWelcome agent={agent} agentName={agentDisplayName} />
|
||||
<AgentWelcome
|
||||
agent={agent}
|
||||
agentName={agentDisplayName}
|
||||
onAskQuestion={(text) =>
|
||||
handleSubmit({ text, files: [] })
|
||||
}
|
||||
disabled={
|
||||
env.NEXT_PUBLIC_STATIC_WEBSITE_ONLY === "true"
|
||||
}
|
||||
/>
|
||||
)
|
||||
}
|
||||
disabled={env.NEXT_PUBLIC_STATIC_WEBSITE_ONLY === "true"}
|
||||
|
||||
Reference in new issue
Block a user