旗下品牌:
石家庄网站开发 石家庄网站开发公司

资讯动态

察而思、思而行、行而后语、知行合一

聊天功能实现:流式响应与实时渲染

发布时间:2025-10-31 热度:

聊天功能实现:流式响应与实时渲染

我将创建一个具有流式响应的聊天界面,使用Fetch API获取数据并以流式方式渲染到页面。

设计思路

  • 创建直观的聊天界面,包含消息区域和输入框

  • 使用模拟服务器响应实现流式数据返回

  • 通过Fetch 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>

功能说明

  1. 用户界面:

    1. 现代化聊天界面设计,带有渐变背景和圆角元素

    2. 清晰的用户消息和机器人消息区分

    3. 响应式设计,适应不同屏幕尺寸

  2. 核心功能:

    1. 用户输入消息并发送

    2. 模拟流式响应,逐字显示回复内容

    3. 显示"正在输入"指示器

    4. 自动滚动到最新消息

  3. 技术实现:

    1. 使用Fetch API模拟流式数据传输

    2. 通过JavaScript定时器模拟逐字输出效果

    3. 动态创建和更新DOM元素

    4. 添加时间戳和动画效果增强用户体验

 

使用方法

  1. 在输入框中输入您的问题

  2. 点击发送按钮或按Enter键发送

  3. 观察机器人如何以流式方式逐步显示回复

这个实现模拟了真实聊天应用中的流式响应功能,可以根据需要进一步扩展,例如连接真实API或添加更多交互功能。

联系尚武科技
客户服务
石家庄APP开发
400-666-4864
为您提供售前购买咨询、解决方案推荐等1V1服务!
技术支持及售后
石家庄APP开发公司
0311-66682288
为您提供从产品到服务的全面技术支持 !
客户服务
石家庄小程序开发
石家庄小程序开发公司
加我企业微信
为您提供售前购买咨询、
解决方案推荐等1V1服务!
石家庄网站建设公司
咨询相关问题或预约面谈,可以通过以下方式与我们联系。
石家庄网站制作
在线联系:
石家庄Web开发
石家庄软件开发
石家庄软件开发公司
ADD/地址:
河北·石家庄
新华区西三庄大街86号河北互联网大厦B座二层
Copyright © 2008-2025尚武科技 保留所有权利。 冀ICP备12011207号-2 石家庄网站开发冀公网安备 13010502001294号《互联网平台公约协议》
Copyright © 2025 www.sw-tech.cn, Inc. All rights reserved