feat(chat): 修复 Strategy/Workspace 统一聊天布局与历史路由归属
This commit is contained in:
1 parent
dbf62e5889
commit
519e4c0c01
7 files changed
+107
-70
No files matched your search
@@ -3,6 +3,7 @@
|
||||
import {
|
||||
BotIcon,
|
||||
Compass,
|
||||
PanelLeftCloseIcon,
|
||||
PanelLeftOpenIcon,
|
||||
PanelRightOpenIcon,
|
||||
PlusSquare,
|
||||
@@ -14,7 +15,6 @@ import { useCallback, useEffect, useMemo, useRef, useState, type ReactNode } fro
|
||||
|
||||
import type { PromptInputMessage } from "@/components/ai-elements/prompt-input";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useSidebarSafe } from "@/components/ui/sidebar";
|
||||
import { AgentChatSidebar } from "@/components/workspace/agents/agent-chat-sidebar";
|
||||
import { AgentDetailPanel } from "@/components/workspace/agents/agent-detail-panel";
|
||||
import { AgentQuestionChips } from "@/components/workspace/agents/agent-question-chips";
|
||||
@@ -87,6 +87,7 @@ import {
|
||||
AGENTFX_REPORT_JSON_OUTPUT_PATH,
|
||||
notifyTaskReportSaved,
|
||||
} from "@/strategy-components/lib/agentfx-report-schema";
|
||||
import { cn } from "@/lib/utils";
|
||||
import type { Message } from "@langchain/langgraph-sdk";
|
||||
|
||||
/** 内置「模板数据转换器」agent 的稳定 id。仅此 agent 的对话页显示「页面模板 + 渲染预览」调试入口。 */
|
||||
@@ -227,7 +228,9 @@ export default function AgentChatPage({
|
||||
const { t } = useI18n();
|
||||
const [showFollowups, setShowFollowups] = useState(false);
|
||||
const router = useRouter();
|
||||
const workspaceSidebar = useSidebarSafe();
|
||||
// 独立智能体页的左列是 AgentChatSidebar,而不是外层 WorkspaceSidebar;
|
||||
// 由本页维护其收展状态,避免顶部按钮切到了不可见的另一层侧栏。
|
||||
const [agentSidebarOpen, setAgentSidebarOpen] = useState(true);
|
||||
|
||||
const { agent_id: agentIdFromPath } = useParams<{
|
||||
agent_id: string;
|
||||
@@ -797,7 +800,11 @@ export default function AgentChatPage({
|
||||
{showAgentList && (
|
||||
<div
|
||||
data-agent-guide="chat-sidebar"
|
||||
className="flex h-full shrink-0"
|
||||
aria-hidden={!agentSidebarOpen}
|
||||
className={cn(
|
||||
"flex h-full shrink-0 overflow-hidden transition-[width] duration-200 ease-out",
|
||||
agentSidebarOpen ? "w-(--sidebar-width)" : "pointer-events-none w-0",
|
||||
)}
|
||||
>
|
||||
<AgentChatSidebar activeAgentId={agent_id} />
|
||||
</div>
|
||||
@@ -809,23 +816,25 @@ export default function AgentChatPage({
|
||||
<main className="relative flex size-full min-h-0 min-w-0 flex-col">
|
||||
{/* Header in normal flow, fixed height. */}
|
||||
<header className="bg-card/90 border-border/70 flex h-12 shrink-0 items-center gap-2 border-b px-4 backdrop-blur-md">
|
||||
{/* 工作区左栏收起后,在智能体聊天区左上角提供展开入口。 */}
|
||||
{showAgentList &&
|
||||
!isEmbedded &&
|
||||
workspaceSidebar &&
|
||||
!workspaceSidebar.open && (
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="icon-sm"
|
||||
onClick={workspaceSidebar.toggleSidebar}
|
||||
title="展开左侧栏"
|
||||
aria-label="展开左侧栏"
|
||||
className="shrink-0 text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
{/* 智能体列表栏的本地收展入口。 */}
|
||||
{showAgentList && !isEmbedded && (
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="icon-sm"
|
||||
onClick={() => setAgentSidebarOpen((open) => !open)}
|
||||
title={agentSidebarOpen ? "收起左侧栏" : "展开左侧栏"}
|
||||
aria-label={agentSidebarOpen ? "收起左侧栏" : "展开左侧栏"}
|
||||
aria-expanded={agentSidebarOpen}
|
||||
className="shrink-0 text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
{agentSidebarOpen ? (
|
||||
<PanelLeftCloseIcon className="size-4" />
|
||||
) : (
|
||||
<PanelLeftOpenIcon className="size-4" />
|
||||
</Button>
|
||||
)}
|
||||
)}
|
||||
</Button>
|
||||
)}
|
||||
<div className="flex shrink-0 items-center gap-1.5 rounded-md border px-2 py-1">
|
||||
<BotIcon className="text-primary h-3.5 w-3.5" />
|
||||
<span
|
||||
@@ -1121,6 +1130,7 @@ export default function AgentChatPage({
|
||||
onAskQuestion={(text) => handleSubmit({ text, files: [] })}
|
||||
collapsed={detailCollapsed}
|
||||
onCollapsedChange={setDetailCollapsed}
|
||||
showRecentChats={!taskCtxOn}
|
||||
compactAppearanceActions={compactAppearanceActions}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -46,7 +46,7 @@ import { isEmbedActive, isHideChromeActive } from "@/core/embed/embed-session";
|
||||
import { isWujieEnv } from "@/core/embed/wujie";
|
||||
import { useSidebar } from "@/components/ui/sidebar";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { MessageSquarePlus, PanelLeftOpen } from "lucide-react";
|
||||
import { MessageSquarePlus, PanelLeftClose, PanelLeftOpen } from "lucide-react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useAgentSelector, useAgentsPaginated } from "@/core/agents";
|
||||
import { useI18n } from "@/core/i18n/hooks";
|
||||
@@ -728,18 +728,22 @@ export default function ChatPage() {
|
||||
)}
|
||||
>
|
||||
<div className="flex min-w-0 flex-1 items-center overflow-hidden text-sm font-medium">
|
||||
{/* 左栏收起后,展开入口固定在聊天区左上角。 */}
|
||||
{compactChrome && !historySidebarOpen && !compactActionsHidden && (
|
||||
{/* 左上角始终提供左栏切换;展开态显示“收起”,收起态显示“展开”。 */}
|
||||
{compactChrome && !compactActionsHidden && (
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="icon-sm"
|
||||
onClick={toggleHistorySidebar}
|
||||
title="展开左侧栏"
|
||||
aria-label="展开左侧栏"
|
||||
title={historySidebarOpen ? "收起左侧栏" : "展开左侧栏"}
|
||||
aria-label={historySidebarOpen ? "收起左侧栏" : "展开左侧栏"}
|
||||
className="mr-1 shrink-0 text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
<PanelLeftOpen className="size-4" />
|
||||
{historySidebarOpen ? (
|
||||
<PanelLeftClose className="size-4" />
|
||||
) : (
|
||||
<PanelLeftOpen className="size-4" />
|
||||
)}
|
||||
</Button>
|
||||
)}
|
||||
<ThreadTitle
|
||||
@@ -753,7 +757,7 @@ export default function ChatPage() {
|
||||
enabled={tokenUsageEnabled}
|
||||
messages={displayThread.messages}
|
||||
/>
|
||||
{compactChrome && !historySidebarOpen && !compactActionsHidden && (
|
||||
{compactChrome && !compactActionsHidden && (
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { Navigate, Route, Routes } from "react-router-dom";
|
||||
import { Toaster } from "sonner";
|
||||
|
||||
import { SidebarProvider } from "@/components/ui/sidebar";
|
||||
import { SidebarInset, SidebarProvider } from "@/components/ui/sidebar";
|
||||
import { WorkspaceSidebar } from "@/components/workspace/workspace-sidebar";
|
||||
import { getAccountDisplayName, getStoredAuth } from "@/core/auth";
|
||||
import { isSentimentAgentVisible } from "@/core/sentiment-agent/config";
|
||||
import { RouteBaseProvider } from "@/core/route-base";
|
||||
@@ -79,6 +80,24 @@ import AdminScheduledTasksPage from "./AdminScheduledTasksPage";
|
||||
import AdminUserActivityPage from "./AdminUserActivityPage";
|
||||
import { ChatRuntime } from "./WorkspaceRoutes";
|
||||
|
||||
/**
|
||||
* Strategy's legacy `/chats/:thread_id` route shares ChatPage's header.
|
||||
* Unlike WorkspaceRoutes it did not render a WorkspaceSidebar, leaving the
|
||||
* header's expand/collapse control with no visible panel to operate.
|
||||
*/
|
||||
function StrategyChatThreadLayout() {
|
||||
return (
|
||||
<div className="flex size-full min-h-0 overflow-hidden">
|
||||
<WorkspaceSidebar compactChrome />
|
||||
<SidebarInset className="min-w-0">
|
||||
<ChatRuntime>
|
||||
<ChatPage />
|
||||
</ChatRuntime>
|
||||
</SidebarInset>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function StrategyRoutes() {
|
||||
const storedAuth = getStoredAuth();
|
||||
const canManageBusinessMappings = !storedAuth || storedAuth.system_role === "admin";
|
||||
@@ -342,11 +361,7 @@ export default function StrategyRoutes() {
|
||||
<Route path="chats" element={<ChatsPage />} />
|
||||
<Route
|
||||
path="chats/:thread_id"
|
||||
element={
|
||||
<ChatRuntime>
|
||||
<ChatPage />
|
||||
</ChatRuntime>
|
||||
}
|
||||
element={<StrategyChatThreadLayout />}
|
||||
/>
|
||||
|
||||
<Route path="agents" element={<AgentsPage />} />
|
||||
|
||||
@@ -182,7 +182,11 @@ export function WorkspaceLayout({
|
||||
'--header-height': headerHidden ? '0rem' : '4rem',
|
||||
} as CSSProperties
|
||||
}
|
||||
key={String(compactWorkspaceSidebar)}
|
||||
// Agent and general-chat routes share this layout component. Keep their
|
||||
// sidebar state separate: otherwise React preserves the collapsed agent
|
||||
// state when a history item switches to `/chats/:thread_id`, while the
|
||||
// new page's header button is meant to control GeneralQaSidebar.
|
||||
key={`${String(compactWorkspaceSidebar)}:${isGeneralQa ? 'general' : 'workspace'}`}
|
||||
data-page-sidebar-collapsed={pageSidebarCollapsed}
|
||||
defaultOpen={
|
||||
forceWorkspaceSidebarCollapsed
|
||||
|
||||
Reference in new issue
Block a user