diff --git a/works/ai-chat-app/www/app.js b/works/ai-chat-app/www/app.js index a28bda8..2bab46d 100644 --- a/works/ai-chat-app/www/app.js +++ b/works/ai-chat-app/www/app.js @@ -69,6 +69,12 @@ async function sendMessage() { userInput.value = ''; autoResize(userInput); + // 调用流式生成 + await streamGenerate(messages.length - 1); +} + +// 流式生成 AI 回复 +async function streamGenerate(userMsgIndex) { // 显示加载状态 isLoading = true; sendBtn.disabled = true; @@ -98,7 +104,7 @@ async function sendMessage() { content: m.content })), max_tokens: CONFIG.maxTokens, - stream: true // 开启流式输出 + stream: true }) }); @@ -119,7 +125,7 @@ async function sendMessage() { // 解析 SSE 数据 const lines = buffer.split('\n'); - buffer = lines.pop() || ''; // 保留未完成的行 + buffer = lines.pop() || ''; for (const line of lines) { if (line.startsWith('data: ')) { @@ -129,64 +135,124 @@ async function sendMessage() { try { const data = JSON.parse(jsonStr); if (data.choices && data.choices[0]?.delta?.content) { - // 追加内容 messages[aiMessageIndex].content += data.choices[0].delta.content; - - // 更新显示(带光标) - contentEl.innerHTML = formatContent(messages[aiMessageIndex].content) + '▌'; + contentEl.innerHTML = renderMarkdown(messages[aiMessageIndex].content) + '▌'; scrollToBottom(); } - } catch (e) { - // 忽略解析错误 - } + } catch (e) {} } } } // 完成,移除光标 - contentEl.innerHTML = formatContent(messages[aiMessageIndex].content); + contentEl.innerHTML = renderMarkdown(messages[aiMessageIndex].content); } catch (error) { console.error('Error:', error); messages[aiMessageIndex].content = `抱歉,出现了错误:${error.message}\n\n请检查网络连接后重试。`; - contentEl.innerHTML = formatContent(messages[aiMessageIndex].content); + contentEl.innerHTML = renderMarkdown(messages[aiMessageIndex].content); } finally { isLoading = false; sendBtn.disabled = false; saveHistory(); + renderMessages(); // 重新渲染显示操作按钮 + } +} + +// 重新生成 AI 回复 +async function regenerate(index) { + if (isLoading || index < 1) return; + + // 找到对应的用户消息(AI消息前一条) + const userMsgIndex = index - 1; + if (messages[userMsgIndex].role !== 'user') return; + + // 删除当前 AI 回复 + messages.splice(index, 1); + + // 重新生成 + await streamGenerate(userMsgIndex); +} + +// 删除消息 +function deleteMessage(index) { + if (isLoading) return; + + const msg = messages[index]; + + if (msg.role === 'assistant') { + // 删除 AI 消息时,同时删除前一条用户消息 + if (index > 0 && messages[index - 1].role === 'user') { + messages.splice(index - 1, 2); // 删除两条 + } else { + messages.splice(index, 1); + } + } else { + // 删除用户消息时,同时删除后一条 AI 消息 + if (index < messages.length - 1 && messages[index + 1].role === 'assistant') { + messages.splice(index, 2); + } else { + messages.splice(index, 1); + } + } + + renderMessages(); + saveHistory(); + + // 如果没有消息了,显示欢迎界面 + if (messages.length === 0) { + welcome.style.display = 'block'; } } // 渲染消息 function renderMessages() { - messagesDiv.innerHTML = messages.map(msg => { + messagesDiv.innerHTML = messages.map((msg, index) => { const isUser = msg.role === 'user'; const avatar = isUser ? '👤' : '🤖'; - const content = formatContent(msg.content); + const content = renderMarkdown(msg.content); + + // 操作按钮 + const actions = isUser + ? `
` + : ``; return ` - +