refactor: state 管理优化 - 结构化浅比较 + update/setIn/batch API

- state.js: 新增 shallowEqual、update()、setIn()、batch() 方法
- input-area.js: messages.push() 全部改为 state.update(),确保引用变化触发通知
- model-bar.js: 直接属性赋值改为 state.update(),修复 model 切换不触发变更检测
This commit is contained in:
thzxx
2026-04-05 01:27:24 +08:00
parent e519631bee
commit b802c896cf
3 changed files with 177 additions and 29 deletions
+33 -12
View File
@@ -345,15 +345,24 @@ export async function sendMessage() {
msgsToAdd.push(msg);
}
// 更新会话标题
if (currentSession.messages.length === 0) {
const titleText = text
|| (pendingFiles.length > 0 ? `[文件: ${pendingFiles.map(f => f.name).join(', ')}]` : '[图片消息]');
currentSession.title = truncate(titleText, 30);
currentSession.model = model;
}
// 更新会话标题 + 追加消息(通过 update 确保引用变化,触发浅比较)
const isFirstMsg = currentSession.messages.length === 0;
state.update(KEYS.CURRENT_SESSION, session => ({
...session,
...(isFirstMsg && {
title: truncate(
text || (pendingFiles.length > 0 ? `[文件: ${pendingFiles.map(f => f.name).join(', ')}]` : '[图片消息]'),
30
),
model
}),
messages: [...session.messages, ...msgsToAdd],
updatedAt: Date.now()
}));
// update() 产生新引用,后续必须从 state 读取最新值
const freshSession = state.get(KEYS.CURRENT_SESSION);
msgsToAdd.forEach(m => currentSession.messages.push(m));
enableAutoScroll();
renderMessages();
@@ -391,7 +400,7 @@ export async function sendMessage() {
let modelName = '';
try {
const apiMessages = buildApiMessages(currentSession.messages);
const apiMessages = buildApiMessages(freshSession.messages);
const chatParams = {
model,
@@ -502,7 +511,11 @@ ${ragContext}
...(finalStats && { eval_count: finalStats.eval_count, total_duration: finalStats.total_duration }),
...(ragSources && { ragSources })
};
currentSession.messages.push(assistantMsg);
state.update(KEYS.CURRENT_SESSION, session => ({
...session,
messages: [...session.messages, assistantMsg],
updatedAt: Date.now()
}));
if (finalStats) {
updateLastAssistantMessage(assistantContent, thinkContent || null, finalStats, modelName || null);
@@ -549,7 +562,11 @@ ${ragContext}
...(thinkContent && { think: thinkContent }),
stopped: true
};
currentSession.messages.push(partialMsg);
state.update(KEYS.CURRENT_SESSION, session => ({
...session,
messages: [...session.messages, partialMsg],
updatedAt: Date.now()
}));
if (contentDiv) {
let html = '';
@@ -584,7 +601,11 @@ ${ragContext}
content: assistantContent + '\n\n`[已中断]`',
timestamp: Date.now(),
};
currentSession.messages.push(partialMsg);
state.update(KEYS.CURRENT_SESSION, session => ({
...session,
messages: [...session.messages, partialMsg],
updatedAt: Date.now()
}));
contentDiv.innerHTML = safeMarkdown(assistantContent) + '<p><code>[已中断]</code></p>';
await saveCurrentSession();
} else {