2025-04-09 11:37:16 +08:00

101 lines
3.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Ai模型接口
//const API_KEY = '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';
const API_KEY = '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';
const API_URL = 'https://openrouter.ai/api/v1/chat/completions';
let messages = [];
// 逐字输出 Markdown 并渲染
async function typeMarkdownEffect(fullText, container) {
let currentText = '';
const length = fullText.length;
const delay = Math.max(5, 40 - Math.min(length / 1.5, 35)); // 根据长度自动调整速度
for (let i = 0; i < length; i++) {
currentText += fullText[i];
const sanitizedHtml = DOMPurify.sanitize(marked.parse(currentText));
container.innerHTML = sanitizedHtml;
// 滚动到底部
container.parentElement.scrollTop = container.parentElement.scrollHeight;
await new Promise(resolve => setTimeout(resolve, delay));
}
}
// 修改后的 appendMessage支持逐字输出 + Markdown
function appendMessage(content, sender, isMarkdown = false, withTyping = false) {
const chatContainer = document.getElementById('chatContainer');
const messageDiv = document.createElement('div');
messageDiv.classList.add('message', sender);
chatContainer.appendChild(messageDiv);
chatContainer.scrollTop = chatContainer.scrollHeight;
// 处理 AI 打字效果
if (isMarkdown && sender === 'bot' && withTyping) {
// 先显示“正在输入中...”提示
messageDiv.innerHTML = `<em class="typing">正在输入中...</em>`;
// 稍等一下再逐字渲染(比如 50ms
setTimeout(() => {
typeMarkdownEffect(content, messageDiv);
}, 50);
} else if (isMarkdown) {
const html = DOMPurify.sanitize(marked.parse(content));
messageDiv.innerHTML = html;
} else {
messageDiv.textContent = content;
}
}
// 发送消息(主函数)
async function sendMessage() {
const inputElem = document.getElementById('userInput');
const userMessage = inputElem.value.trim();
if (!userMessage) return;
appendMessage(userMessage, 'user');
messages.push({ role: 'user', content: userMessage });
inputElem.value = '';
// 👉 提前显示“正在输入中...”并保存 messageDiv 元素引用
const chatContainer = document.getElementById('chatContainer');
const botMessageDiv = document.createElement('div');
botMessageDiv.classList.add('message', 'bot');
botMessageDiv.innerHTML = `<em class="typing">正在输入中...</em>`;
chatContainer.appendChild(botMessageDiv);
chatContainer.scrollTop = chatContainer.scrollHeight;
const payload = {
//model: 'deepseek/deepseek-r1:free',
model: 'deepseek/deepseek-chat-v3-0324:free',
messages: messages
};
try {
const response = await fetch(API_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + API_KEY
},
body: JSON.stringify(payload)
});
const data = await response.json();
if (data.choices && data.choices.length > 0) {
const botMessage = data.choices[0].message.content;
// ✅ 拿到内容后替换 messageDiv 的内容,逐字打字渲染
typeMarkdownEffect(botMessage, botMessageDiv);
messages.push({ role: 'assistant', content: botMessage });
} else {
botMessageDiv.textContent = '没有收到有效响应,请检查 API 设置。';
}
} catch (error) {
console.error('请求错误:', error);
botMessageDiv.textContent = '请求出错:' + error.message;
}
}