feat(agent-sidebar): 「智能体」区支持收起/展开

标题栏改为可折叠头(chevron 切换),收起后仅留标题栏并隐藏来源下拉/搜索/列表,
下方「最近的对话」占满剩余空间;收起状态持久化到 localStorage。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
吉鑫升andClaude Opus 4.8 committed 2026-06-19 15:04:30 +08:00
1 parent c1c23d9136
commit 1f2a1aaa76
1 file changed
+50 -8
@@ -2,6 +2,7 @@
import { import {
Bot, Bot,
ChevronDown,
Download, Download,
FileJson, FileJson,
FileText, FileText,
@@ -127,6 +128,18 @@ export function AgentChatSidebar({ activeAgentId }: { activeAgentId?: string })
return () => clearTimeout(timer); return () => clearTimeout(timer);
}, [searchInput]); }, [searchInput]);
// 「智能体」区可收起(持久化);收起后只留标题栏,下方「最近的对话」占满剩余空间。
const [agentsCollapsed, setAgentsCollapsed] = useState(
() =>
typeof window !== "undefined" &&
localStorage.getItem("agent-chat-sidebar:agents-collapsed") === "true",
);
const toggleAgents = () =>
setAgentsCollapsed((v) => {
localStorage.setItem("agent-chat-sidebar:agents-collapsed", String(!v));
return !v;
});
// 若所选广场被管理员删除,回退到「我的」,避免指向不存在的广场。 // 若所选广场被管理员删除,回退到「我的」,避免指向不存在的广场。
useEffect(() => { useEffect(() => {
if ( if (
@@ -151,7 +164,32 @@ export function AgentChatSidebar({ activeAgentId }: { activeAgentId?: string })
return ( return (
// 配色与 AgentModuleSidebar 一致:浅色白底,深蓝主题半透明深蓝玻璃面板。 // 配色与 AgentModuleSidebar 一致:浅色白底,深蓝主题半透明深蓝玻璃面板。
<aside className="flex h-full w-(--sidebar-width) shrink-0 flex-col overflow-hidden border-r border-border/70 bg-white text-foreground backdrop-blur-md dark:border-[#2b8ffe]/45 dark:bg-[#032650]/80"> <aside className="flex h-full w-(--sidebar-width) shrink-0 flex-col overflow-hidden border-r border-border/70 bg-white text-foreground backdrop-blur-md dark:border-[#2b8ffe]/45 dark:bg-[#032650]/80">
{/* 顶部:作用域下拉(我的 / 各广场)+ 智能体名称模糊搜索 */} {/* 智能体(上半,可收起)。展开时:标题栏 + 来源下拉/名称搜索 + 列表;
收起时只留标题栏,下方「最近的对话」占满剩余空间。 */}
<div
className={cn(
"flex flex-col",
agentsCollapsed ? "shrink-0" : "min-h-0 flex-[3]",
)}
>
<button
type="button"
onClick={toggleAgents}
className="text-foreground/80 hover:bg-accent/40 flex shrink-0 items-center justify-between border-b border-border/60 px-3 py-2.5 text-[12px] font-semibold transition-colors select-none"
title={agentsCollapsed ? "展开智能体" : "收起智能体"}
>
<span>智能体</span>
<ChevronDown
className={cn(
"text-muted-foreground size-4 shrink-0 transition-transform duration-200",
agentsCollapsed && "-rotate-90",
)}
/>
</button>
{!agentsCollapsed && (
<>
{/* 来源下拉(我的 / 各广场)+ 智能体名称模糊搜索 */}
<div className="shrink-0 space-y-2 border-b border-border/60 px-3 py-2.5"> <div className="shrink-0 space-y-2 border-b border-border/60 px-3 py-2.5">
<Select value={scope} onValueChange={setScope}> <Select value={scope} onValueChange={setScope}>
<SelectTrigger className="h-9 w-full text-sm" title="切换智能体来源"> <SelectTrigger className="h-9 w-full text-sm" title="切换智能体来源">
@@ -189,11 +227,8 @@ export function AgentChatSidebar({ activeAgentId }: { activeAgentId?: string })
</div> </div>
</div> </div>
{/* 智能体列表(上半,独立滚动) */} {/* 智能体列表(独立滚动) */}
<div className="flex min-h-0 flex-[3] flex-col overflow-y-auto px-2 py-3"> <div className="flex min-h-0 flex-1 flex-col overflow-y-auto px-2 py-3">
<h2 className="mb-1 px-3 py-1 text-[11px] font-semibold tracking-[0.04em] text-muted-foreground/80 select-none">
智能体
</h2>
{isLoading && agents.length === 0 ? ( {isLoading && agents.length === 0 ? (
<div className="text-muted-foreground flex h-24 items-center justify-center gap-2 text-xs"> <div className="text-muted-foreground flex h-24 items-center justify-center gap-2 text-xs">
<Loader2 className="size-3.5 animate-spin" /> <Loader2 className="size-3.5 animate-spin" />
@@ -201,7 +236,11 @@ export function AgentChatSidebar({ activeAgentId }: { activeAgentId?: string })
</div> </div>
) : agents.length === 0 ? ( ) : agents.length === 0 ? (
<p className="px-3 py-1.5 text-xs text-muted-foreground/70"> <p className="px-3 py-1.5 text-xs text-muted-foreground/70">
{search ? "未找到匹配的智能体" : isMine ? "暂无智能体" : "该广场暂无智能体"} {search
? "未找到匹配的智能体"
: isMine
? "暂无智能体"
: "该广场暂无智能体"}
</p> </p>
) : ( ) : (
<div <div
@@ -258,7 +297,7 @@ export function AgentChatSidebar({ activeAgentId }: { activeAgentId?: string })
{total > agents.length && ( {total > agents.length && (
<Link <Link
href={`${routeBase}/agents`} href={`${routeBase}/agents`}
className="text-muted-foreground hover:text-foreground mt-0.5 rounded-lg px-3 py-1.5 text-center text-xs transition-colors hover:bg-accent/50" className="text-muted-foreground hover:text-foreground hover:bg-accent/50 mt-0.5 rounded-lg px-3 py-1.5 text-center text-xs transition-colors"
> >
共 {total} 个,查看全部 → 共 {total} 个,查看全部 →
</Link> </Link>
@@ -266,6 +305,9 @@ export function AgentChatSidebar({ activeAgentId }: { activeAgentId?: string })
</div> </div>
)} )}
</div> </div>
</>
)}
</div>
{/* 最近的对话(下半,独立滚动)—— 参考首页通用问答左栏 */} {/* 最近的对话(下半,独立滚动)—— 参考首页通用问答左栏 */}
<RecentChatsPane activeAgentId={activeAgentId} /> <RecentChatsPane activeAgentId={activeAgentId} />