<!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
上一篇:
下一篇: