feat(agents): 智能体问答页落地态展示常用问题入口并默认展开简介栏

- 落地页 Hero 以"Hi,我是{名称}"问候,将管理员配置的常用问题渲染为可点击的引导气泡,点击即发起对话
- 右侧智能体简介栏改为默认展开,作为主要"专家信息"卡片,仍可手动收起

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
吉鑫升andClaude Opus 4.8 committed 2026-06-11 09:52:27 +08:00
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; onAskQuestion: (text: string) => void;
disabled?: boolean; 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 [detailSkillName, setDetailSkillName] = useState<string | null>(null);
const { skills } = useSkills(); const { skills } = useSkills();
const updateAgent = useUpdateAgent(); const updateAgent = useUpdateAgent();
@@ -1,39 +1,76 @@
"use client"; "use client";
import { BotIcon } from "lucide-react"; import { BotIcon } from "lucide-react";
import { type Agent } from "@/core/agents"; import { type Agent } from "@/core/agents";
import { desensitize } from "@/lib/desensitize"; import { desensitize } from "@/lib/desensitize";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
export function AgentWelcome({ /**
className, * Landing (home) hero shown above the input box before the first message of an
agent, * agent conversation. Mirrors the qclaw landing screen: centered avatar, a
agentName, * "Hi,我是{name}" greeting, the agent's one-line description as a slogan, and
}: { * the agent's admin-configured common questions surfaced as clickable starter
className?: string; * pills. Clicking a pill sends it as the opening message via `onAskQuestion`.
agent: Agent | null | undefined; */
agentName: string; export function AgentWelcome({
}) { className,
const displayName = desensitize(agent?.name ?? agentName); agent,
const description = agent?.description agentName,
? desensitize(agent.description) onAskQuestion,
: undefined; disabled,
}: {
return ( className?: string;
<div agent: Agent | null | undefined;
className={cn( agentName: string;
"mx-auto flex w-full flex-col items-center justify-center gap-2 px-8 py-4 text-center", onAskQuestion?: (text: string) => void;
className, disabled?: boolean;
)} }) {
> const displayName = desensitize(agent?.name ?? agentName);
<div className="bg-primary/10 flex h-12 w-12 items-center justify-center rounded-full"> const description = agent?.description
<BotIcon className="text-primary h-6 w-6" /> ? desensitize(agent.description)
</div> : undefined;
<div className="text-2xl font-bold">{displayName}</div> const questions = (agent?.common_questions ?? []).filter(
{description && ( (q) => q.trim().length > 0,
<p className="text-muted-foreground max-w-sm text-sm">{description}</p> );
)}
</div> 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>
);
}
+10 -1
View File
@@ -268,7 +268,16 @@ export default function AgentChatPage() {
context={settings.context} context={settings.context}
extraHeader={ extraHeader={
isLandingState && ( 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"} disabled={env.NEXT_PUBLIC_STATIC_WEBSITE_ONLY === "true"}