代码修改
This commit is contained in:
1 parent
88b1a330a6
commit
6b49741e69
7 files changed
+332
-394
No files matched your search
@@ -0,0 +1,127 @@
|
||||
"use client";
|
||||
|
||||
import { Bot, ChevronRight } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { useMemo } from "react";
|
||||
|
||||
import {
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
} from "@/components/ui/sidebar";
|
||||
import { useAgentsPaginated } from "@/core/agents";
|
||||
import type { Agent } from "@/core/agents";
|
||||
import { desensitize } from "@/lib/desensitize";
|
||||
|
||||
/** 常用智能体最多展示个数(需求 1.2 ②)。 */
|
||||
const MAX_FREQUENT = 3;
|
||||
|
||||
/** 「更多」跳转目标:智能体管理页(需求 1.3)。 */
|
||||
const MORE_HREF = "/page/strategy/agents";
|
||||
|
||||
/** 打开某个智能体主页(其对话落地页,thread_id=new = 新会话)。 */
|
||||
function agentHomeHref(agentId: string): string {
|
||||
return `/page/strategy/agents/${agentId}/chats/new`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 「常用智能体」侧栏区块(通用问答左栏,全量模式)。
|
||||
*
|
||||
* 级联兜底取数(需求 1.2 ② / 1.3)——按优先级补足到最多 3 个、去重:
|
||||
* 1. 置顶智能体(``is_pinned``,可来自「我的」或「广场」);
|
||||
* 2. 不足 3 个 → 用「我的」智能体(``scope="mine"``)补足;
|
||||
* 3. 仍不足 → 用「广场」默认推荐(``scope="square"``)补足。
|
||||
*
|
||||
* 取不到任何智能体时整块隐藏(与 ``RecentChatList`` 的空态约定一致)。
|
||||
*/
|
||||
export function FrequentAgentsList() {
|
||||
const pathname = usePathname();
|
||||
const { agents: mine } = useAgentsPaginated({
|
||||
scope: "mine",
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
});
|
||||
const { agents: square } = useAgentsPaginated({
|
||||
scope: "square",
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
});
|
||||
|
||||
const frequent = useMemo<Agent[]>(() => {
|
||||
const out: Agent[] = [];
|
||||
const seen = new Set<string>();
|
||||
const add = (agent: Agent | undefined) => {
|
||||
if (!agent || out.length >= MAX_FREQUENT || seen.has(agent.id)) return;
|
||||
seen.add(agent.id);
|
||||
out.push(agent);
|
||||
};
|
||||
// 1. 置顶组优先(够 3 个则下面我的/广场都不再补)。
|
||||
[...mine, ...square].filter((a) => a.is_pinned).forEach(add);
|
||||
// 2. 我的智能体补足。
|
||||
mine.forEach(add);
|
||||
// 3. 广场默认推荐补足。
|
||||
square.forEach(add);
|
||||
return out;
|
||||
}, [mine, square]);
|
||||
|
||||
if (frequent.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<SidebarGroup className="px-2 pt-3 mt-2 border-t border-sidebar-border/60">
|
||||
<SidebarGroupLabel className="text-muted-foreground/70 px-3 mb-1 text-[10px] font-semibold tracking-[0.12em] uppercase select-none">
|
||||
常用智能体
|
||||
</SidebarGroupLabel>
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu>
|
||||
<div className="flex w-full flex-col gap-0.5">
|
||||
{frequent.map((agent) => {
|
||||
const href = agentHomeHref(agent.id);
|
||||
const isActive = pathname === href;
|
||||
return (
|
||||
<SidebarMenuItem key={agent.id}>
|
||||
<SidebarMenuButton
|
||||
isActive={isActive}
|
||||
asChild
|
||||
className={
|
||||
"rounded-lg h-7 px-3 text-[13px] text-muted-foreground hover:text-foreground hover:bg-sidebar-accent/60 " +
|
||||
"data-[active=true]:bg-white data-[active=true]:text-foreground data-[active=true]:shadow-[0_1px_2px_rgba(15,23,42,0.05)] " +
|
||||
"dark:data-[active=true]:bg-slate-700/80 dark:data-[active=true]:text-slate-100 dark:data-[active=true]:shadow-none"
|
||||
}
|
||||
>
|
||||
<Link
|
||||
className="flex w-full items-center gap-2 whitespace-nowrap"
|
||||
href={href}
|
||||
>
|
||||
<Bot className="size-3.5 shrink-0 text-muted-foreground/70" />
|
||||
<span className="truncate">{desensitize(agent.name)}</span>
|
||||
</Link>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
);
|
||||
})}
|
||||
<SidebarMenuItem>
|
||||
<SidebarMenuButton
|
||||
asChild
|
||||
className="rounded-lg h-7 px-3 text-[12px] text-muted-foreground/70 hover:text-foreground hover:bg-sidebar-accent/60"
|
||||
>
|
||||
<Link
|
||||
className="flex w-full items-center justify-between gap-1"
|
||||
href={MORE_HREF}
|
||||
>
|
||||
<span>更多</span>
|
||||
<ChevronRight className="size-3.5 shrink-0" />
|
||||
</Link>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
</div>
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
);
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import {
|
||||
ChevronDown,
|
||||
ChevronRight,
|
||||
Download,
|
||||
FileJson,
|
||||
FileText,
|
||||
@@ -74,7 +75,17 @@ import { desensitize } from "@/lib/desensitize";
|
||||
import { isIMEComposing } from "@/lib/ime";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export function RecentChatList({ compact = false }: { compact?: boolean }) {
|
||||
export function RecentChatList({
|
||||
compact = false,
|
||||
limit,
|
||||
moreHref,
|
||||
}: {
|
||||
compact?: boolean;
|
||||
/** 最多展示的会话条数;省略则不限制(需求 1.3:通用问答最多 10 条)。 */
|
||||
limit?: number;
|
||||
/** 「更多」入口跳转目标;省略则不展示「更多」行。 */
|
||||
moreHref?: string;
|
||||
}) {
|
||||
const { t } = useI18n();
|
||||
const router = useRouter();
|
||||
const pathname = usePathname();
|
||||
@@ -190,6 +201,8 @@ export function RecentChatList({ compact = false }: { compact?: boolean }) {
|
||||
if (visibleThreads.length === 0) {
|
||||
return null;
|
||||
}
|
||||
const shownThreads =
|
||||
limit != null ? visibleThreads.slice(0, limit) : visibleThreads;
|
||||
return (
|
||||
<>
|
||||
<SidebarGroup className="px-2 pt-3 mt-2 border-t border-sidebar-border/60">
|
||||
@@ -225,7 +238,7 @@ export function RecentChatList({ compact = false }: { compact?: boolean }) {
|
||||
>
|
||||
<SidebarMenu>
|
||||
<div className="flex w-full flex-col gap-0.5">
|
||||
{visibleThreads.map((thread) => {
|
||||
{shownThreads.map((thread) => {
|
||||
const isActive = pathOfThread(thread) === pathname;
|
||||
const pinned = isThreadPinned(thread);
|
||||
const favorited = isThreadFavorite(thread);
|
||||
@@ -368,6 +381,22 @@ export function RecentChatList({ compact = false }: { compact?: boolean }) {
|
||||
</SidebarMenuItem>
|
||||
);
|
||||
})}
|
||||
{moreHref && (
|
||||
<SidebarMenuItem>
|
||||
<SidebarMenuButton
|
||||
asChild
|
||||
className="rounded-lg h-7 px-3 text-[12px] text-muted-foreground/70 hover:text-foreground hover:bg-sidebar-accent/60"
|
||||
>
|
||||
<Link
|
||||
className="flex w-full items-center justify-between gap-1"
|
||||
href={moreHref}
|
||||
>
|
||||
<span>{t.common.more}</span>
|
||||
<ChevronRight className="size-3.5 shrink-0" />
|
||||
</Link>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
)}
|
||||
</div>
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
|
||||
@@ -10,7 +10,9 @@ import {
|
||||
} from "@/components/ui/sidebar";
|
||||
import { useTheme } from "@/contexts/ThemeContext";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { usePathname } from "next/navigation";
|
||||
|
||||
import { FrequentAgentsList } from "./frequent-agents-list";
|
||||
import { RecentChatList } from "./recent-chat-list";
|
||||
import { RecentRoundtableList } from "./recent-roundtable-list";
|
||||
import { RecentWritingList } from "./recent-writing-list";
|
||||
@@ -25,7 +27,11 @@ export function WorkspaceSidebar({
|
||||
}: React.ComponentProps<typeof Sidebar> & { compactChrome?: boolean }) {
|
||||
const { open: isSidebarOpen } = useSidebar();
|
||||
const { theme } = useTheme();
|
||||
const pathname = usePathname();
|
||||
const useWhiteSidebar = compactChrome && theme === "light";
|
||||
// 通用问答(全量模式)左栏:新建回答 → 常用智能体 → 聊天记录(需求 0616 #1)。
|
||||
// 仅在通用问答(/page/workspace/chats*)下启用三块式布局;其余 workspace 页保持原样。
|
||||
const isGeneralQa = pathname.startsWith("/page/workspace/chats");
|
||||
|
||||
// 紧凑模式:用「外层定宽容器 + transition-[width]」做展开/收起过渡动画。
|
||||
// collapsible="none" 的 Sidebar 是普通 in-flow 定宽块(非 absolute,故不受本布局对
|
||||
@@ -53,7 +59,12 @@ export function WorkspaceSidebar({
|
||||
>
|
||||
<SidebarContent>
|
||||
<WorkspaceNavChatList showCollapseTrigger compact />
|
||||
<RecentChatList compact />
|
||||
{isGeneralQa && <FrequentAgentsList />}
|
||||
<RecentChatList
|
||||
compact
|
||||
limit={isGeneralQa ? 10 : undefined}
|
||||
moreHref={isGeneralQa ? "/page/workspace/chats" : undefined}
|
||||
/>
|
||||
</SidebarContent>
|
||||
<SidebarRail />
|
||||
</Sidebar>
|
||||
|
||||
Reference in new issue
Block a user