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
+56
-7
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();
|
||||||
|
|||||||
@@ -6,33 +6,70 @@ 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";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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({
|
export function AgentWelcome({
|
||||||
className,
|
className,
|
||||||
agent,
|
agent,
|
||||||
agentName,
|
agentName,
|
||||||
|
onAskQuestion,
|
||||||
|
disabled,
|
||||||
}: {
|
}: {
|
||||||
className?: string;
|
className?: string;
|
||||||
agent: Agent | null | undefined;
|
agent: Agent | null | undefined;
|
||||||
agentName: string;
|
agentName: string;
|
||||||
|
onAskQuestion?: (text: string) => void;
|
||||||
|
disabled?: boolean;
|
||||||
}) {
|
}) {
|
||||||
const displayName = desensitize(agent?.name ?? agentName);
|
const displayName = desensitize(agent?.name ?? agentName);
|
||||||
const description = agent?.description
|
const description = agent?.description
|
||||||
? desensitize(agent.description)
|
? desensitize(agent.description)
|
||||||
: undefined;
|
: undefined;
|
||||||
|
const questions = (agent?.common_questions ?? []).filter(
|
||||||
|
(q) => q.trim().length > 0,
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"mx-auto flex w-full flex-col items-center justify-center gap-2 px-8 py-4 text-center",
|
"mx-auto flex w-full max-w-2xl flex-col items-center justify-center gap-3 px-6 text-center",
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="bg-primary/10 flex h-12 w-12 items-center justify-center rounded-full">
|
<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-6 w-6" />
|
<BotIcon className="text-primary h-8 w-8" />
|
||||||
|
</div>
|
||||||
|
<div className="text-2xl font-bold tracking-tight">
|
||||||
|
Hi,我是{displayName}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-2xl font-bold">{displayName}</div>
|
|
||||||
{description && (
|
{description && (
|
||||||
<p className="text-muted-foreground max-w-sm text-sm">{description}</p>
|
<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>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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"}
|
||||||
|
|||||||
Reference in new issue
Block a user