chat.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>大模型聊天界面</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
margin: 0;
padding: 0;
background-color: #f5f5f5;
}
.chat-container {
max-width: 800px;
margin: 0 auto;
height: 100vh;
display: flex;
flex-direction: column;
background-color: white;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
}
.header {
background-color: #007bff;
color: white;
padding: 15px;
text-align: center;
}
.messages-container {
flex: 1;
overflow-y: auto;
padding: 20px;
}
.message {
margin-bottom: 15px;
display: flex;
align-items: flex-start;
}
.message.user {
justify-content: flex-end;
}
.message.assistant {
justify-content: flex-start;
}
.message-content {
max-width: 70%;
padding: 12px 16px;
border-radius: 18px;
word-wrap: break-word;
}
.message.user .message-content {
background-color: #007bff;
color: white;
}
.message.assistant .message-content {
background-color: #e9ecef;
color: #333;
}
.input-container {
display: flex;
padding: 20px;
background-color: #f8f9fa;
border-top: 1px solid #dee2e6;
}
.message-input {
flex: 1;
padding: 12px 16px;
border: 1px solid #ced4da;
border-radius: 25px;
outline: none;
font-size: 14px;
}
.send-button {
margin-left: 10px;
padding: 12px 24px;
background-color: #007bff;
color: white;
border: none;
border-radius: 25px;
cursor: pointer;
font-size: 14px;
}
.send-button:hover {
background-color: #0056b3;
}
.send-button:disabled {
background-color: #6c757d;
cursor: not-allowed;
}
.loading {
display: none;
text-align: center;
padding: 10px;
color: #6c757d;
}
.model-selector {
padding: 15px;
background-color: #f8f9fa;
border-bottom: 1px solid #dee2e6;
}
.model-selector select {
width: 100%;
padding: 8px;
border: 1px solid #ced4da;
border-radius: 4px;
}
.stream-toggle {
margin-top: 10px;
}
</style>
</head>
<body>
<div class="chat-container">
<div class="header">
<h1>大模型聊天助手</h1>
</div>
<div class="model-selector">
<label for="model-select">选择模型:</label>
<select id="model-select">
<option value="doubao-seed-1-6-251015">doubao-seed-1-6-251015</option>
<option value="qwen-max">qwen-max</option>
</select>
<div class="stream-toggle">
<label>
<input type="checkbox" id="stream-toggle" checked> 启用流式输出
</label>
</div>
<div class="msgid-input" style="margin-top: 10px;">
<label for="msgid-input">消息ID:</label>
<input type="text" id="msgid-input" placeholder="输入消息ID(留空则自动生成)" style="width: 100%; padding: 8px; border: 1px solid #ced4da; border-radius: 4px; margin-top: 5px;">
</div>
</div>
<div class="messages-container" id="messages-container">
<!-- 消息将在这里动态添加 -->
</div>
<div class="loading" id="loading">
正在生成回复...
</div>
<div class="input-container">
<input
type="text"
class="message-input"
id="message-input"
placeholder="输入您的问题..."
autocomplete="off"
>
<button class="send-button" id="send-button">发送</button>
</div>
</div>
<script>
class ChatApp {
constructor() {
this.messagesContainer = document.getElementById('messages-container');
this.messageInput = document.getElementById('message-input');
this.sendButton = document.getElementById('send-button');
this.loading = document.getElementById('loading');
this.modelSelect = document.getElementById('model-select');
this.streamToggle = document.getElementById('stream-toggle');
this.msgIdInput = document.getElementById('msgid-input');
this.messages = [];
this.msgId = 1;
this.bindEvents();
}
bindEvents() {
this.sendButton.addEventListener('click', () => this.sendMessage());
this.messageInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
this.sendMessage();
}
});
}
async sendMessage() {
const message = this.messageInput.value.trim();
if (!message) return;
this.addMessage('user', message);
this.messageInput.value = '';
this.setLoading(true);
// 获取msgId,如果用户输入了就使用用户输入的,否则自动生成
const customMsgId = this.msgIdInput.value.trim();
const msgId = customMsgId || String(this.msgId++);
const requestData = {
model: this.modelSelect.value,
message: message,
msgId: msgId,
stream: this.streamToggle.checked
};
try {
if (requestData.stream) {
await this.handleStreamResponse(requestData);
} else {
await this.handleNormalResponse(requestData);
}
} catch (error) {
console.error('Error:', error);
this.addMessage('assistant', '抱歉,发生了错误,请稍后重试。');
} finally {
this.setLoading(false);
}
}
async handleStreamResponse(requestData) {
const response = await fetch('http://localhost:8080/chat/send', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(requestData)
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const reader = response.body.getReader();
const decoder = new TextDecoder();
let assistantMessageElement = this.addMessage('assistant', '');
let content = '';
while (true) {
const { value, done } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
const lines = chunk.split('\n');
for (const line of lines) {
if (line.startsWith('data: ') && line !== 'data: [DONE]') {
try {
const jsonStr = line.slice(6);
const data = JSON.parse(jsonStr);
if (data.choices && data.choices[0] && data.choices[0].delta && data.choices[0].delta.content) {
content += data.choices[0].delta.content;
this.updateMessageContent(assistantMessageElement, content);
}
} catch (e) {
console.error('Error parsing chunk:', e);
}
}
}
}
}
async handleNormalResponse(requestData) {
const response = await fetch('http://localhost:8080/chat/send', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(requestData)
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
if (data.code === 0 && data.data && data.data.messages) {
const lastMessage = data.data.messages[data.data.messages.length - 1];
if (lastMessage && lastMessage.role === 'assistant') {
this.addMessage('assistant', lastMessage.content);
}
} else {
throw new Error(data.msg || 'Unknown error');
}
}
addMessage(role, content) {
const messageDiv = document.createElement('div');
messageDiv.className = `message ${role}`;
const messageContent = document.createElement('div');
messageContent.className = 'message-content';
messageContent.textContent = content;
messageDiv.appendChild(messageContent);
this.messagesContainer.appendChild(messageDiv);
this.messagesContainer.scrollTop = this.messagesContainer.scrollHeight;
return messageContent;
}
updateMessageContent(messageElement, content) {
messageElement.textContent = content;
this.messagesContainer.scrollTop = this.messagesContainer.scrollHeight;
}
setLoading(loading) {
this.sendButton.disabled = loading;
this.loading.style.display = loading ? 'block' : 'none';
this.sendButton.textContent = loading ? '发送中...' : '发送';
}
}
// 初始化应用
document.addEventListener('DOMContentLoaded', () => {
new ChatApp();
});
</script>
</body>
</html>
作者:admin 创建时间:2025-11-16 23:38
最后编辑:admin 更新时间:2025-11-16 23:47
最后编辑:admin 更新时间:2025-11-16 23:47