最新文章
聊天功能实现:流式响应与实时渲染
现代化聊天界面设计,带有渐变背景和圆角元素 清晰的用户消息和机器人消息区分 响应式设计,适应不同屏幕尺寸 用户输入消息并发送 模拟流式响应,逐字显示回复内容 显示"正在输入"指示器 自动滚动到最新消息 使用Fetch API模拟流式数据传输 通过JavaScript定时器模拟逐字输出效果 动态创建和更新DOM元素 添加时间戳和动画效果增强用户体验 <!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>












冀公网安备