新增纯会话页面,独立路由 /pure-chat
- 新增 ChatPagePure 组件:仅保留聊天主区域(section.chat-main),去掉全局 Sidebar 和 AgentSidebar - 复用原有的 ChatHeader、ChatBody、ChatInput、ChatOutline、ChatDrawers 组件,会话功能完全一致 - 独立路由 /pure-chat 和 /pure-chat/:id,绕过 layout-shell 全局布局,不显示侧边栏 - 新增样式文件 chat-page-pure.css,适配纯会话页面全屏布局main
parent
b9cf3bc78a
commit
1b4812acae
|
|
@ -15,7 +15,8 @@ import PromptLibraryPage from './pages/PromptLibraryPage';
|
|||
import StatsPage from './pages/StatsPage';
|
||||
import ProfilePage from './pages/ProfilePage';
|
||||
import PricingPage from './pages/PricingPage';
|
||||
import SharedSessionPage from './pages/SharedSessionPage';
|
||||
import SharedSessionPage from './pages/SharedSessionPage';
|
||||
import ChatPagePure from './pages/chat/ChatPagePure';
|
||||
import WorkflowsPage from './pages/WorkflowsPage';
|
||||
import KnowledgeBasePage from './pages/KnowledgeBase';
|
||||
import { useAuth } from './store/auth';
|
||||
|
|
@ -83,6 +84,12 @@ export default function App() {
|
|||
<Route path="/login" element={<LoginPage />} />
|
||||
<Route path="*" element={<LoginPage />} />
|
||||
</Routes>
|
||||
) : location.pathname.startsWith('/pure-chat') ? (
|
||||
<Routes>
|
||||
{/* 纯会话页:无全局 Sidebar,无 AgentSidebar,仅保留聊天主区域 */}
|
||||
<Route path="/pure-chat" element={<ChatPagePure />} />
|
||||
<Route path="/pure-chat/:id" element={<ChatPagePure />} />
|
||||
</Routes>
|
||||
) : (
|
||||
<div className="layout-shell">
|
||||
{/* 只有编辑器全屏显示,其他页面均保留侧边栏 */}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,179 @@
|
|||
import { useEffect, useState, useCallback, useRef } from 'react';
|
||||
import { App as AntApp, Empty } from 'antd';
|
||||
import type { ChatPageLogicOutput } from './ChatPageLogic';
|
||||
import { markdownToPlainText } from './utils/copy';
|
||||
import { useChatPageLogic } from './ChatPageLogic';
|
||||
import ChatBody from './components/ChatBody';
|
||||
import ChatDrawers from './components/ChatDrawers';
|
||||
import ChatHeader from './components/ChatHeader';
|
||||
import ChatInput from './components/ChatInput';
|
||||
import ChatOutline from './components/ChatOutline';
|
||||
import type { ModelOverrides } from '../../api';
|
||||
import './styles/chat-page-pure.css';
|
||||
|
||||
/**
|
||||
* 纯会话页面组件
|
||||
* 仅保留聊天主区域(section.chat-main),去掉全局 Sidebar 和 AgentSidebar(chat-side)
|
||||
* 会话功能与原聊天页面完全一致
|
||||
*/
|
||||
export default function ChatPagePure() {
|
||||
const logic = useChatPageLogic();
|
||||
const { message } = AntApp.useApp();
|
||||
const [outlineCollapsed, setOutlineCollapsed] = useState(true);
|
||||
const isAutoScrolling = useRef(false);
|
||||
|
||||
const {
|
||||
id,
|
||||
roomId,
|
||||
highlightId,
|
||||
historyDrawerOpen,
|
||||
mcpDrawerOpen,
|
||||
paramsDrawerOpen,
|
||||
tplDrawerOpen,
|
||||
agent,
|
||||
agentList,
|
||||
messages,
|
||||
branches,
|
||||
bodyRef,
|
||||
sender,
|
||||
navigate,
|
||||
overrides,
|
||||
setOverrides,
|
||||
setRoomId,
|
||||
setHighlightId,
|
||||
setHistoryDrawerOpen,
|
||||
setMcpDrawerOpen,
|
||||
setParamsDrawerOpen,
|
||||
setTplDrawerOpen,
|
||||
handleNewSession,
|
||||
} = logic;
|
||||
|
||||
// 初始化时,如果有历史消息,激活最后一条 Agent 消息
|
||||
useEffect(() => {
|
||||
if (messages.length > 0 && !highlightId) {
|
||||
const agentMsgs = messages.filter(m => m.role === 'assistant' || m.role === 'agent' || m.speaker?.type === 'agent');
|
||||
if (agentMsgs.length > 0) {
|
||||
setHighlightId(agentMsgs[agentMsgs.length - 1].id);
|
||||
}
|
||||
}
|
||||
}, [messages.length]);
|
||||
|
||||
const handleJump = useCallback((msgId: string) => {
|
||||
isAutoScrolling.current = true;
|
||||
setHighlightId(msgId);
|
||||
const el = document.getElementById('msg-' + msgId);
|
||||
if (el) {
|
||||
el.scrollIntoView({ block: 'start', behavior: 'smooth' });
|
||||
setTimeout(() => {
|
||||
isAutoScrolling.current = false;
|
||||
}, 800);
|
||||
}
|
||||
}, [setHighlightId]);
|
||||
|
||||
return (
|
||||
<div className="chat-pure-shell">
|
||||
<section className="chat-main">
|
||||
{!agent ? (
|
||||
<div className="chat-empty-state">
|
||||
<Empty description="请选择一个智能体开始对话" />
|
||||
</div>
|
||||
) : (
|
||||
<div className="chat-content-layout">
|
||||
<div className="chat-conversation-panel">
|
||||
<ChatHeader
|
||||
agent={agent}
|
||||
useStream={sender.useStream}
|
||||
setUseStream={sender.setUseStream}
|
||||
onOpenHistory={() => setHistoryDrawerOpen(true)}
|
||||
onOpenParams={() => setParamsDrawerOpen(true)}
|
||||
onOpenMcp={() => setMcpDrawerOpen(true)}
|
||||
onManageAgent={() => navigate(`/agents/${id}`)}
|
||||
onClear={sender.handleClear}
|
||||
/>
|
||||
|
||||
<ChatBody
|
||||
bodyRef={bodyRef}
|
||||
agent={agent}
|
||||
agentList={agentList}
|
||||
currentAgentId={id!}
|
||||
messages={messages}
|
||||
branches={branches}
|
||||
highlightId={highlightId}
|
||||
sending={sender.sending}
|
||||
streaming={sender.streaming}
|
||||
onRegenerate={sender.handleRegenerate}
|
||||
onSwitchBranch={sender.handleSwitchBranch}
|
||||
scrollBottom={logic.scrollBottom}
|
||||
initialScrollDoneRef={logic.initialScrollDoneRef}
|
||||
onCopy={(text, mode) => {
|
||||
const content = mode === 'markdown' ? text : markdownToPlainText(text);
|
||||
navigator.clipboard?.writeText(content).then(() => {
|
||||
message.success(mode === 'markdown' ? '已复制(Markdown)' : '已复制(纯文本)');
|
||||
});
|
||||
}}
|
||||
/>
|
||||
|
||||
<ChatInput
|
||||
input={sender.input}
|
||||
setInput={sender.setInput}
|
||||
sending={sender.sending}
|
||||
attachments={sender.attachments}
|
||||
setAttachments={sender.setAttachments}
|
||||
imageUrls={sender.imageUrls}
|
||||
setImageUrls={sender.setImageUrls}
|
||||
onSend={sender.handleSend}
|
||||
onStop={sender.handleStop}
|
||||
onAttach={sender.handleAttach}
|
||||
onOpenTpl={() => setTplDrawerOpen(true)}
|
||||
modelOptions={sender.modelOptions}
|
||||
activeModelValue={sender.activeModelValue}
|
||||
onChangeModel={(modelId) => {
|
||||
const picked = sender.modelOptions.find((o) => o.value === modelId);
|
||||
setOverrides((o: ModelOverrides) => ({
|
||||
...o,
|
||||
model_id: modelId,
|
||||
model: picked?.label ?? o.model
|
||||
}));
|
||||
}}
|
||||
agentList={agentList}
|
||||
onInsertMention={() => {}}
|
||||
onOpenHistory={() => setHistoryDrawerOpen(true)}
|
||||
onNewSession={handleNewSession}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<ChatOutline
|
||||
messages={messages}
|
||||
activeId={highlightId}
|
||||
collapsed={outlineCollapsed}
|
||||
onToggleCollapse={() => setOutlineCollapsed(!outlineCollapsed)}
|
||||
onJump={handleJump}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
|
||||
<ChatDrawers
|
||||
agentId={id}
|
||||
agent={agent}
|
||||
input={sender.input}
|
||||
setInput={(updater) => sender.setInput(updater)}
|
||||
overrides={overrides}
|
||||
setOverrides={setOverrides}
|
||||
roomId={roomId}
|
||||
setRoomId={setRoomId}
|
||||
setHighlightId={setHighlightId}
|
||||
sessionRefresh={sender.sessionRefresh}
|
||||
mcpDrawerOpen={mcpDrawerOpen}
|
||||
setMcpDrawerOpen={setMcpDrawerOpen}
|
||||
tplDrawerOpen={tplDrawerOpen}
|
||||
setTplDrawerOpen={setTplDrawerOpen}
|
||||
paramsDrawerOpen={paramsDrawerOpen}
|
||||
setParamsDrawerOpen={setParamsDrawerOpen}
|
||||
historyDrawerOpen={historyDrawerOpen}
|
||||
setHistoryDrawerOpen={setHistoryDrawerOpen}
|
||||
notify={{ success: (t) => message.success(t) }}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
/* 纯会话页面样式 - 无侧边栏,仅保留聊天主区域 */
|
||||
|
||||
.chat-pure-shell {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.chat-pure-shell .chat-main {
|
||||
flex: 1;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
min-width: 0;
|
||||
}
|
||||
Loading…
Reference in New Issue