Files
2026-09-23 21:27:55 +08:00

146 lines
4.3 KiB
HTML
Raw Permalink 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.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DeepSeek 流式对话</title>
<style>
body { font-family: system-ui, sans-serif; max-width: 760px; margin: 30px auto; padding: 0 16px; }
h1 { font-size: 1.3rem; }
#output {
border: 1px solid #ddd; border-radius: 10px;
padding: 16px; min-height: 300px; white-space: pre-wrap;
line-height: 1.6; background: #fafafa;
}
.reasoning {
background: #f1f5f9; border-left: 4px solid #94a3b8;
padding: 8px 12px; border-radius: 6px; margin-bottom: 12px;
color: #475569; font-size: 0.9rem; white-space: pre-wrap;
}
.content { color: #0f172a; }
.label { font-size: 0.75rem; font-weight: bold; color: #64748b; margin-bottom: 4px; }
.row { display: flex; gap: 8px; margin-top: 12px; }
input {
flex: 1; padding: 12px 16px; border: 1px solid #ccc;
border-radius: 8px; font-size: 1rem; outline: none;
}
input:focus { border-color: #4f46e5; }
button {
padding: 12px 24px; background: #4f46e5; color: white;
border: none; border-radius: 8px; font-size: 1rem;
cursor: pointer;
}
button:disabled { background: #cbd5e1; cursor: not-allowed; }
</style>
</head>
<body>
<h1>💬 DeepSeek 流式对话</h1>
<div id="output">等待输入…</div>
<div class="row">
<input id="input" placeholder="输入问题,回车发送" autocomplete="off">
<button id="send">发送</button>
</div>
<script>
const inputEl = document.getElementById('input');
const sendBtn = document.getElementById('send');
const outputEl = document.getElementById('output');
let es = null; // EventSource
let reasoningEl = null; // 推理区块
let contentEl = null; // 回答区块
function resetOutput() {
outputEl.innerHTML = '';
reasoningEl = null;
contentEl = null;
}
function getReasoningEl() {
if (!reasoningEl) {
const wrap = document.createElement('div');
wrap.className = 'reasoning';
const label = document.createElement('div');
label.className = 'label';
label.textContent = '🧠 推理过程';
const text = document.createElement('div');
wrap.appendChild(label);
wrap.appendChild(text);
outputEl.appendChild(wrap);
reasoningEl = text;
}
return reasoningEl;
}
function getContentEl() {
if (!contentEl) {
const wrap = document.createElement('div');
wrap.className = 'content';
outputEl.appendChild(wrap);
contentEl = wrap;
}
return contentEl;
}
function send() {
const text = inputEl.value.trim();
if (!text) return;
// 关闭上一个连接
if (es) { es.close(); es = null; }
resetOutput();
inputEl.value = '';
sendBtn.disabled = true;
const url = `http://localhost:8001/chat?user_input=${encodeURIComponent(text)}&model=deepseek-chat`;
es = new EventSource(url);
// 推理过程(命名事件 reasoning)
es.addEventListener('reasoning', (e) => {
const chunk = JSON.parse(e.data);
getReasoningEl().textContent += chunk;
});
// 正式回答(命名事件 content ★ 关键)
es.addEventListener('content', (e) => {
const chunk = JSON.parse(e.data);
getContentEl().textContent += chunk;
});
// 服务端错误(命名事件 server_error)
es.addEventListener('server_error', (e) => {
const msg = JSON.parse(e.data);
outputEl.innerHTML += `<div style="color:red;">⚠️ ${msg}</div>`;
finish();
});
// 结束(命名事件 done)
es.addEventListener('done', () => {
finish();
});
// 网络层错误
es.onerror = () => {
if (es && es.readyState === EventSource.CLOSED) {
finish();
}
};
function finish() {
if (es) { es.close(); es = null; }
sendBtn.disabled = false;
if (!outputEl.textContent.trim()) {
outputEl.textContent = '(无返回内容)';
}
}
}
sendBtn.addEventListener('click', send);
inputEl.addEventListener('keydown', (e) => {
if (e.key === 'Enter') send();
});
</script>
</body>
</html>