feat(qa-center): 问答中心左侧栏改造(0616 需求 2-5)
- 多智能体会商:Step1 落地左栏「业务链(public 前3) + 分析记录」;点链=勾选(autoChainResult),第一步澄清后点「进入研讨」才按链执行
- zzJC/zzXD:独立模块路由 /page/strategy/qa/{zzjc,zzxd},常驻左栏(按 agent 标签分组 + 仅本模块会话的聊天记录),点智能体模块内切换不跳页,默认落地配置类型下首个智能体
- zzJC/zzXD admin 设置:左栏齿轮→单选类型(TDesign)配置面板+智能体预览;后端 system_settings.agent_modules 持久化(GET 开放/PUT admin)+ test_agent_modules
- 课题研究:左栏「研究模板(文章类型) + 笔记本」;模板点击预填表单,笔记本点击设为素材来源(selectedNotebookId 上提 WritingFormContext)
- 通用问答:全量模式历史侧栏默认展开
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
8794c51f88
commit
f39cffcb9a
18 files changed
+1113
-41
No files matched your search
@@ -208,9 +208,7 @@ export default function AgentChatPage() {
|
||||
size="sm"
|
||||
variant="secondary"
|
||||
onClick={() => {
|
||||
router.push(
|
||||
`/page/workspace/agents/${agent_id}/chats/new`,
|
||||
);
|
||||
router.push(`${routeBase}/agents/${agent_id}/chats/new`);
|
||||
}}
|
||||
>
|
||||
<PlusSquare /> {t.agents.newChat}
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
"use client";
|
||||
|
||||
import { Loader2 } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
import { Navigate, Route, Routes, useParams } from "react-router-dom";
|
||||
|
||||
import {
|
||||
AgentModuleSidebar,
|
||||
type AgentModuleConfig,
|
||||
} from "@/components/workspace/agents/agent-module-sidebar";
|
||||
import { AgentModuleSettingsDialog } from "@/components/workspace/agents/agent-module-settings-dialog";
|
||||
import { useAgents } from "@/core/agents";
|
||||
import { getStoredAuth } from "@/core/auth";
|
||||
import { RouteBaseProvider } from "@/core/route-base";
|
||||
import { useAgentModuleConfig } from "@/core/system-settings/hooks";
|
||||
|
||||
import AgentChatPage from "./AgentChatPage";
|
||||
import { ChatRuntime } from "./WorkspaceRoutes";
|
||||
|
||||
/**
|
||||
* 「按类型聚合」模块页(需求 0616 #3 zzJC / #4 zzXD,重做)。
|
||||
*
|
||||
* 一个**常驻外壳**(左栏:按类型分组智能体 + 聊天记录 + admin 设置)包裹右侧对话;
|
||||
* 点击智能体只在模块内切换对话(左栏不卸载,无整页跳转)。模块自带独立路由
|
||||
* ``/page/strategy/qa/{moduleKey}``,并以该路径作为 RouteBase,使内嵌的 AgentChatPage
|
||||
* 所有跳转(新建对话 / onStart 改写 hash)都留在模块子树内。
|
||||
*/
|
||||
export function AgentModuleRoutes({ module }: { module: AgentModuleConfig }) {
|
||||
const base = `/page/strategy/qa/${module.key}`;
|
||||
return (
|
||||
<RouteBaseProvider value={base}>
|
||||
<Routes>
|
||||
<Route index element={<ModuleDefaultRedirect module={module} />} />
|
||||
<Route
|
||||
path="agents/:agent_id/chats/:thread_id"
|
||||
element={<ModuleChatShell module={module} />}
|
||||
/>
|
||||
</Routes>
|
||||
</RouteBaseProvider>
|
||||
);
|
||||
}
|
||||
|
||||
/** 进入模块默认落地:配置类型下的第一个智能体;无配置回退到模块默认体。 */
|
||||
function ModuleDefaultRedirect({ module }: { module: AgentModuleConfig }) {
|
||||
const { agents, isLoading: agentsLoading } = useAgents();
|
||||
const { data: config, isLoading: configLoading } = useAgentModuleConfig(
|
||||
module.key,
|
||||
);
|
||||
|
||||
if (agentsLoading || configLoading) {
|
||||
return (
|
||||
<div className="flex size-full items-center justify-center">
|
||||
<Loader2 className="text-muted-foreground size-5 animate-spin" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const tagIds = config?.tag_ids ?? [];
|
||||
let targetId = module.fallbackAgentId;
|
||||
if (tagIds.length > 0) {
|
||||
const allowed = new Set(tagIds);
|
||||
const first = agents.find((a) =>
|
||||
(a.tags ?? []).some((t) => allowed.has(t.id)),
|
||||
);
|
||||
if (first) targetId = first.id;
|
||||
}
|
||||
|
||||
return <Navigate to={`agents/${targetId}/chats/new`} replace />;
|
||||
}
|
||||
|
||||
/** 模块外壳:常驻左栏 + 内嵌当前智能体对话(按 agent_id 重建对话区,左栏保持挂载)。 */
|
||||
function ModuleChatShell({ module }: { module: AgentModuleConfig }) {
|
||||
const { agent_id } = useParams<{ agent_id: string }>();
|
||||
const isAdmin = getStoredAuth()?.system_role === "admin";
|
||||
const [settingsOpen, setSettingsOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<div className="flex size-full min-h-0 overflow-hidden">
|
||||
<AgentModuleSidebar
|
||||
moduleKey={module.key}
|
||||
activeAgentId={agent_id}
|
||||
onOpenSettings={isAdmin ? () => setSettingsOpen(true) : undefined}
|
||||
/>
|
||||
<div className="min-h-0 min-w-0 flex-1">
|
||||
<ChatRuntime>
|
||||
<AgentChatPage key={agent_id} />
|
||||
</ChatRuntime>
|
||||
</div>
|
||||
{isAdmin && (
|
||||
<AgentModuleSettingsDialog
|
||||
open={settingsOpen}
|
||||
onOpenChange={setSettingsOpen}
|
||||
moduleKey={module.key}
|
||||
moduleTitle={module.title}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -19,6 +19,8 @@ import BusinessChainListPage from "@/roundtable-planning/pages/BusinessChainList
|
||||
import BusinessChainEditorPage from "@/roundtable-planning/pages/BusinessChainEditorPage";
|
||||
import "@/roundtable-planning/styles/roundtable-planning.css";
|
||||
import AgentChatPage from "./AgentChatPage";
|
||||
import { AgentModuleRoutes } from "./AgentModulePage";
|
||||
import { AGENT_MODULES } from "@/components/workspace/agents/agent-module-sidebar";
|
||||
import AgentsPage from "./AgentsPage";
|
||||
import BusinessChainMappingPage from "./BusinessChainMappingPage";
|
||||
import ChatPage from "./ChatPage";
|
||||
@@ -75,6 +77,10 @@ export default function StrategyRoutes() {
|
||||
}
|
||||
/>
|
||||
|
||||
{/* 需求 0616 #3/#4:zzJC / zzXD 「按类型聚合」模块页(重做,独立路由)。 */}
|
||||
<Route path="qa/zzjc/*" element={<AgentModuleRoutes module={AGENT_MODULES.zzjc} />} />
|
||||
<Route path="qa/zzxd/*" element={<AgentModuleRoutes module={AGENT_MODULES.zzxd} />} />
|
||||
|
||||
<Route path="task-management" element={<TaskManagement />}>
|
||||
<Route index element={<Navigate to="xk-task-jc" replace />} />
|
||||
<Route
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { CSSProperties, ReactNode } from 'react';
|
||||
import { Navigate, Route, Routes, useParams } from 'react-router-dom';
|
||||
import { Navigate, Route, Routes, useLocation, useParams } from 'react-router-dom';
|
||||
|
||||
import { getStoredAuth } from '@/core/auth';
|
||||
|
||||
@@ -87,6 +87,10 @@ export function WorkspaceLayout({
|
||||
insetOverflowHidden?: boolean;
|
||||
pageSidebarDark?: boolean;
|
||||
}) {
|
||||
// 全量模式下通用问答(/page/workspace/chats*)的历史侧栏默认展开;其余紧凑页
|
||||
// (如智能体对话,为聊天区更宽而默认收起)维持原默认。
|
||||
const isGeneralQa = useLocation().pathname.startsWith("/page/workspace/chats");
|
||||
|
||||
const pageSidebarWidth = pageSidebarHidden
|
||||
? '0rem'
|
||||
: pageSidebarDark
|
||||
@@ -113,7 +117,9 @@ export function WorkspaceLayout({
|
||||
}
|
||||
key={String(compactWorkspaceSidebar)}
|
||||
data-page-sidebar-collapsed={pageSidebarCollapsed}
|
||||
defaultOpen={defaultHistorySidebarOpen ?? !compactWorkspaceSidebar}
|
||||
defaultOpen={
|
||||
defaultHistorySidebarOpen ?? (isGeneralQa || !compactWorkspaceSidebar)
|
||||
}
|
||||
>
|
||||
{!workspaceSidebarHidden && (
|
||||
<WorkspaceSidebar compactChrome={compactWorkspaceSidebar} />
|
||||
|
||||
Reference in new issue
Block a user