最新文章
聊天功能實現:流式響應與實時渲染
我將創建一個具有流式響應的聊天界面,使用Fetch API獲取數據并以流式方式渲染到頁面。 創建直觀的聊天界面,包含消息區域和輸入框 使用模擬服務器響應實現流式數據返回 通過Fetch API處理數據流并實時渲染到頁面 添加消息發送功能和交互反饋 用戶界面: 現代化聊天界面設計,帶有漸變背景和圓角元素 清晰的用戶消息和機器人消息區分 響應式設計,適應不同屏幕尺寸 核心功能: 用戶輸入消息并發送 模擬流式響應,逐字顯示回復內容 顯示"正在輸入"指示器 自動滾動到最新消息 技術實現: 使用Fetch API模擬流式數據傳輸 通過JavaScript定時器模擬逐字輸出效果 動態創建和更新DOM元素 添加時間戳和動畫效果增強用戶體驗   在輸入框中輸入您的問題 點擊發送按鈕或按Enter鍵發送 觀察機器人如何以流式方式逐步顯示回復 這個實現模擬了真實聊天應用中的流式響應功能,可以根據需要進一步擴展,例如連接真實API或添加更多交互功能。聊天功能實現:流式響應與實時渲染
設計思路
實現代碼
<!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>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }
        
        body {
            background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%);
            color: #333;
            min-height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
            padding: 20px;
        }
        
        .chat-container {
            width: 100%;
            max-width: 800px;
            height: 80vh;
            background-color: rgba(255, 255, 255, 0.9);
            border-radius: 20px;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
            display: flex;
            flex-direction: column;
            overflow: hidden;
        }
        
        .chat-header {
            background: linear-gradient(90deg, #2575fc, #6a11cb);
            color: white;
            padding: 20px;
            text-align: center;
            font-size: 1.5rem;
            font-weight: 600;
        }
        
        .chat-messages {
            flex: 1;
            padding: 20px;
            overflow-y: auto;
            display: flex;
            flex-direction: column;
            gap: 15px;
        }
        
        .message {
            max-width: 70%;
            padding: 15px;
            border-radius: 18px;
            line-height: 1.5;
            position: relative;
            animation: fadeIn 0.3s ease;
        }
        
        .user-message {
            align-self: flex-end;
            background: linear-gradient(135deg, #2575fc, #6a11cb);
            color: white;
            border-bottom-right-radius: 5px;
        }
        
        .bot-message {
            align-self: flex-start;
            background-color: #f1f1f1;
            color: #333;
            border-bottom-left-radius: 5px;
        }
        
        .typing-indicator {
            align-self: flex-start;
            background-color: #f1f1f1;
            padding: 15px;
            border-radius: 18px;
            border-bottom-left-radius: 5px;
            display: flex;
            align-items: center;
            gap: 5px;
            width: 60px;
        }
        
        .typing-dot {
            width: 8px;
            height: 8px;
            border-radius: 50%;
            background-color: #999;
            animation: typing 1.4s infinite ease-in-out;
        }
        
        .typing-dot:nth-child(1) { animation-delay: -0.32s; }
        .typing-dot:nth-child(2) { animation-delay: -0.16s; }
        
        .chat-input-container {
            display: flex;
            padding: 20px;
            border-top: 1px solid #e0e0e0;
            background-color: white;
        }
        
        .chat-input {
            flex: 1;
            padding: 15px;
            border: 2px solid #e0e0e0;
            border-radius: 30px;
            outline: none;
            font-size: 1rem;
            transition: border-color 0.3s;
        }
        
        .chat-input:focus {
            border-color: #2575fc;
        }
        
        .send-button {
            background: linear-gradient(135deg, #2575fc, #6a11cb);
            color: white;
            border: none;
            border-radius: 50%;
            width: 50px;
            height: 50px;
            margin-left: 10px;
            cursor: pointer;
            display: flex;
            justify-content: center;
            align-items: center;
            transition: transform 0.2s;
        }
        
        .send-button:hover {
            transform: scale(1.05);
        }
        
        .send-button:active {
            transform: scale(0.95);
        }
        
        .send-button svg {
            width: 24px;
            height: 24px;
        }
        
        @keyframes fadeIn {
            from { opacity: 0; transform: translateY(10px); }
            to { opacity: 1; transform: translateY(0); }
        }
        
        @keyframes typing {
            0%, 60%, 100% { transform: translateY(0); }
            30% { transform: translateY(-10px); }
        }
        
        .timestamp {
            font-size: 0.7rem;
            opacity: 0.7;
            margin-top: 5px;
            text-align: right;
        }
        
        .bot-message .timestamp {
            text-align: left;
        }
        
        /* 滾動條樣式 */
        .chat-messages::-webkit-scrollbar {
            width: 6px;
        }
        
        .chat-messages::-webkit-scrollbar-track {
            background: #f1f1f1;
            border-radius: 10px;
        }
        
        .chat-messages::-webkit-scrollbar-thumb {
            background: #c1c1c1;
            border-radius: 10px;
        }
        
        .chat-messages::-webkit-scrollbar-thumb:hover {
            background: #a8a8a8;
        }
        
        @media (max-width: 600px) {
            .chat-container {
                height: 90vh;
            }
            
            .message {
                max-width: 85%;
            }
        }    </style></head><body>
    <div class="chat-container">
        <div class="chat-header">
            <h1>智能聊天助手</h1>
        </div>
        <div class="chat-messages" id="chatMessages">
            <div class="message bot-message">
                <div>您好!我是您的智能助手,有什么可以幫您的嗎?</div>
                <div class="timestamp" id="initialTimestamp"></div>
            </div>
        </div>
        <div class="chat-input-container">
            <input type="text" class="chat-input" id="chatInput" placeholder="輸入您的問題...">
            <button class="send-button" id="sendButton">
                <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                    <path d="M22 2L11 13" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                    <path d="M22 2L15 22L11 13L2 9L22 2Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                </svg>
            </button>
        </div>
    </div>
    <script>
        // 獲取DOM元素
        const chatMessages = document.getElementById('chatMessages');
        const chatInput = document.getElementById('chatInput');
        const sendButton = document.getElementById('sendButton');
        const initialTimestamp = document.getElementById('initialTimestamp');
        
        // 設置初始消息時間戳
        initialTimestamp.textContent = formatTime(new Date());
        
        // 添加示例消息
        setTimeout(() => {
            addBotMessage("我可以幫您解答問題、提供信息或進行簡單的對話。請隨時向我提問!");
        }, 1000);
        
        // 發送消息函數
        function sendMessage() {
            const message = chatInput.value.trim();
            if (!message) return;
            
            // 添加用戶消息
            addUserMessage(message);
            
            // 清空輸入框
            chatInput.value = '';
            
            // 顯示正在輸入指示器
            const typingIndicator = showTypingIndicator();
            
            // 模擬流式響應
            simulateStreamResponse(message, typingIndicator);
        }
        
        // 添加用戶消息
        function addUserMessage(text) {
            const messageDiv = document.createElement('div');
            messageDiv.className = 'message user-message';
            
            const messageContent = document.createElement('div');
            messageContent.textContent = text;
            
            const timestamp = document.createElement('div');
            timestamp.className = 'timestamp';
            timestamp.textContent = formatTime(new Date());
            
            messageDiv.appendChild(messageContent);
            messageDiv.appendChild(timestamp);
            chatMessages.appendChild(messageDiv);
            
            // 滾動到底部
            scrollToBottom();
        }
        
        // 添加機器人消息
        function addBotMessage(text) {
            const messageDiv = document.createElement('div');
            messageDiv.className = 'message bot-message';
            
            const messageContent = document.createElement('div');
            messageContent.textContent = text;
            
            const timestamp = document.createElement('div');
            timestamp.className = 'timestamp';
            timestamp.textContent = formatTime(new Date());
            
            messageDiv.appendChild(messageContent);
            messageDiv.appendChild(timestamp);
            chatMessages.appendChild(messageDiv);
            
            // 滾動到底部
            scrollToBottom();
        }
        
        // 顯示正在輸入指示器
        function showTypingIndicator() {
            const indicatorDiv = document.createElement('div');
            indicatorDiv.className = 'typing-indicator';
            indicatorDiv.id = 'typingIndicator';
            
            for (let i = 0; i < 3; i++) {
                const dot = document.createElement('div');
                dot.className = 'typing-dot';
                indicatorDiv.appendChild(dot);
            }
            
            chatMessages.appendChild(indicatorDiv);
            scrollToBottom();
            
            return indicatorDiv;
        }
        
        // 隱藏正在輸入指示器
        function hideTypingIndicator(indicator) {
            if (indicator && indicator.parentNode) {
                indicator.parentNode.removeChild(indicator);
            }
        }
        
        // 模擬流式響應
        function simulateStreamResponse(userMessage, typingIndicator) {
            // 模擬網絡延遲
            setTimeout(() => {
                // 獲取響應文本
                const responseText = generateResponse(userMessage);
                
                // 創建消息容器
                const messageDiv = document.createElement('div');
                messageDiv.className = 'message bot-message';
                
                const messageContent = document.createElement('div');
                messageDiv.appendChild(messageContent);
                
                const timestamp = document.createElement('div');
                timestamp.className = 'timestamp';
                timestamp.textContent = formatTime(new Date());
                messageDiv.appendChild(timestamp);
                
                // 先添加到DOM但內容為空
                chatMessages.appendChild(messageDiv);
                
                // 隱藏正在輸入指示器
                hideTypingIndicator(typingIndicator);
                
                // 模擬流式輸出
                let index = 0;
                const streamInterval = setInterval(() => {
                    if (index < responseText.length) {
                        messageContent.textContent += responseText.charAt(index);
                        index++;
                        scrollToBottom();
                    } else {
                        clearInterval(streamInterval);
                    }
                }, 30); // 控制輸出速度
            }, 1000); // 模擬網絡延遲
        }
        
        // 生成響應內容
        function generateResponse(userMessage) {
            const responses = [
                `感謝您的提問!關于"${userMessage}",這是一個很好的問題。讓我為您詳細解釋一下...`,
                `我理解您對"${userMessage}"的疑問。根據我的知識庫,我可以告訴您...`,
                `您提到了"${userMessage}",這是一個有趣的話題。讓我與您分享一些相關信息...`,
                `關于"${userMessage}"的問題,我可以從幾個角度為您分析。首先...`,
                `我注意到您詢問了"${userMessage}"。這是一個復雜的話題,但我會盡力為您提供清晰的解釋...`
            ];
            
            // 隨機選擇一個響應
            return responses[Math.floor(Math.random() * responses.length)];
        }
        
        // 格式化時間
        function formatTime(date) {
            return `${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`;
        }
        
        // 滾動到底部
        function scrollToBottom() {
            chatMessages.scrollTop = chatMessages.scrollHeight;
        }
        
        // 事件監聽
        sendButton.addEventListener('click', sendMessage);
        
        chatInput.addEventListener('keypress', (e) => {
            if (e.key === 'Enter') {
                sendMessage();
            }
        });
        
        // 初始滾動到底部
        scrollToBottom();
        </script>
        </body>
    </html>功能說明
使用方法
 
                 
                 
             
        




 
                                                        

 
  
 
                



 冀公網安備
冀公網安備