feat(web): 前端接会话持久化——拉历史热分页 + 侧栏会话列表
- store: 消息真源移到后端(sessions元数据map + activeSessionId,partialize 移除 messages 改存会话元数据,version:2 migrate 清旧数据) - api: fetchSessions/createSubSession/fetchMessages(热分页before游标)/deleteSession + MessageDto→toChatMessage - Nav: 侧栏「会话」区——主会话置顶 + 次级列表 + +新建会话(Miuix) - 新增 HistoryList: 顶部「加载更早」向上分页 + 保守虚拟化(>200只渲染最近200) - useChat: send 用 activeSessionId;App: token 后 fetchSessions→激活主会话→拉近50条 - Docs/api-client: v0.10 补 WS sessionId + history 回放事件契约
This commit is contained in:
1 parent
48421923f6
commit
bcc53d68f3
9 files changed
+371
-32
No files matched your search
@@ -3,7 +3,7 @@ import { useAppStore } from "../store/useAppStore";
|
||||
import { useModeStore } from "../store/useModeStore";
|
||||
import { useSendChat } from "../lib/useChat";
|
||||
import { sendUp } from "../lib/ws";
|
||||
import { SplitChatBubble } from "../components/chat";
|
||||
import { HistoryList } from "../components/messages/HistoryList";
|
||||
import { ChatInput } from "../components/ChatInput";
|
||||
import { EmptyState } from "../components/primitives";
|
||||
import { Icon } from "../components/Icon";
|
||||
@@ -49,9 +49,13 @@ export function ChatShell(): React.ReactNode {
|
||||
return undefined;
|
||||
}, [messages]);
|
||||
|
||||
// Scroll to the newest message only when a *new* message reaches the tail
|
||||
// (append/session-switch), not when the user hot-pages older history into the
|
||||
// list — otherwise "load earlier" would yank the viewport to the bottom.
|
||||
const lastMessageId = messages[messages.length - 1]?.id;
|
||||
useEffect(() => {
|
||||
bottomRef.current?.scrollIntoView({ behavior: "smooth", block: "end" });
|
||||
}, [messages]);
|
||||
}, [lastMessageId]);
|
||||
|
||||
return (
|
||||
<div className="flex h-full flex-col">
|
||||
@@ -77,17 +81,7 @@ export function ChatShell(): React.ReactNode {
|
||||
hint="模式只改变消息框的呈现方式,会话上下文与记忆保持不变"
|
||||
/>
|
||||
) : (
|
||||
messages.map((m) => (
|
||||
<SplitChatBubble
|
||||
key={m.id}
|
||||
message={m}
|
||||
active={
|
||||
m.id === lastAssistantId &&
|
||||
m.role === "assistant" &&
|
||||
(m.streaming ?? false)
|
||||
}
|
||||
/>
|
||||
))
|
||||
<HistoryList lastAssistantId={lastAssistantId} />
|
||||
)}
|
||||
<div ref={bottomRef} />
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user