This repository has been archived on 2026-08-12. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Cyrene/frontend/web/src/components/layout/AppLayout.tsx
T
AskaEth b123a36aae fix: 第四轮调试 — 回复去重/消息时序/UI布局/自主思考深度优化 + 文档重整
后端修复:
- main.go: 恢复 /api/v1/chat 路由中丢失的 handleChat 调用 (空响应回归)
- orchestrator.go: splitChatByLines 改为双换行分割, 避免单换行误拆
- chat_handler.go: multi_message 增加 !hasReview 守卫, 消息延迟 200→800ms
- thinker.go: RecordUserMessage 追踪活跃会话ID, 推送主动消息到正确会话
- thinker.go: 增强思考提示词 — 禁止在用户休息/离开时发送主动消息

前端修复:
- useWebSocket.ts: stream_segments 不再创建消息气泡, 消除重复回复
- MessageBubble.tsx: 动作消息居左对齐无头像, 时间戳移至气泡外侧 hover 显示
- ChatInput.tsx: 昔涟输入提示移至输入框上方, 波点动画效果
- MessageList/TypingIndicator/ChatContainer: 清理冗余 isTyping 传递
- MemoryPanel.tsx: 新增记忆面板组件

文档重整:
- docs/debug/ → docs/debug_log/ 重命名统一
- 新增 debug_log/README.md 索引
- .gitignore: 新增 android/ 排除规则

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 13:09:18 +08:00

59 lines
1.9 KiB
TypeScript

import { useState } from 'react';
import { Sidebar } from './Sidebar';
import { Header } from './Header';
import { SearchModal } from './SearchModal';
import { MemoryPanel } from './MemoryPanel';
import { useAuth } from '@/hooks/useAuth';
interface AppLayoutProps {
children: React.ReactNode;
}
export function AppLayout({ children }: AppLayoutProps) {
const [sidebarOpen, setSidebarOpen] = useState(false);
const [searchOpen, setSearchOpen] = useState(false);
const [memoryOpen, setMemoryOpen] = useState(false);
const { isLoggedIn } = useAuth();
return (
<div className="flex h-screen bg-[#FFFAF5] dark:bg-[#1a1a2e]">
{/* 侧边栏 */}
{isLoggedIn && (
<>
{/* 移动端遮罩 */}
{sidebarOpen && (
<div
className="fixed inset-0 bg-black/30 z-20 lg:hidden"
onClick={() => setSidebarOpen(false)}
/>
)}
<div
className={`
fixed lg:static inset-y-0 left-0 z-30 w-64 transform transition-transform duration-300 ease-in-out
${sidebarOpen ? 'translate-x-0' : '-translate-x-full lg:translate-x-0'}
`}
>
<Sidebar onClose={() => setSidebarOpen(false)} onMemoryClick={() => setMemoryOpen(true)} />
</div>
</>
)}
{/* 主内容区 */}
<div className="flex-1 flex flex-col min-w-0">
{isLoggedIn && (
<Header
onMenuClick={() => setSidebarOpen(!sidebarOpen)}
onSearchClick={() => setSearchOpen(true)}
/>
)}
<main className="flex-1 min-h-0 overflow-hidden">{children}</main>
</div>
{/* 搜索弹窗 */}
<SearchModal isOpen={searchOpen} onClose={() => setSearchOpen(false)} />
{/* 记忆管理弹窗 */}
<MemoryPanel isOpen={memoryOpen} onClose={() => setMemoryOpen(false)} />
</div>
);
}