基于上篇内容,添加交互逻辑,实现一个伪聊天功能的对话框效果:
Tailwind css实战,基于Kooboo构建AI对话框页面(一)-CSDN博客
在前期文章中,我们完成了 AI 对话框的静态页面搭建。本文将聚焦交互逻辑开发,通过原生 JavaScript 实现消息发送 / 接收动态渲染、“正在输入” 动画反馈及关键词触发的智能回复,最终实现一个具备对话能力的交互界面。以下是核心功能的代码实现与逻辑解析:
一、技术栈
1. 技术栈说明
- Kooboo:快速构建对话界面的静态结构(如消息容器、输入框、按钮的布局)。通过拖拽组件和样式配置(直接应用 Tailwind 类名),生成基础 HTML 框架,无需手动编写重复代码。
- Tailwind CSS:通过类名快速实现对话气泡样式(如
bg-blue-600
用户消息、bg-white
AI 回复) - 原生 JavaScript:通过监听用户操作,动态渲染消息,与 Kooboo 生成的静态 DOM 无缝协作,确保交互功能的灵活性
二、核心文件结构
1. 初始化与 DOM 元素获取
document.addEventListener('DOMContentLoaded', function() {
const messageContainer = document.getElementById('messageContainer');
const messageInput = document.getElementById('messageInput');
const sendButton = document.getElementById('sendButton');
});
- 事件监听:页面 DOM 加载完成后执行初始化
- 元素引用:获取消息容器、输入框和发送按钮的 DOM 节点
2. 时间格式化函数
// 获取当前时间(格式:HH:MM AM/PM)
function getCurrentTime() {
const now = new Date();
let hours = now.getHours();
let minutes = now.getMinutes();
const ampm = hours >= 12 ? 'PM' : 'AM';
hours = hours % 12;
hours = hours ? hours : 12; // 0点转为12点
minutes = minutes < 10 ? '0'+minutes : minutes;
return `${hours}:${minutes} ${ampm}`;
}
- 时间格式:将 24 小时制转换为 12 小时制(例如:
2:30 PM
) - 补零处理:分钟数小于 10 时添加前导零(例如:
2:05 PM
)
3. 消息发送功能
3.1 获取用户输入并校验
function sendMessage() {
const message = messageInput.value.trim();
if (message === '') return; // 忽略空消息
- 去除空格:获取输入框中的内容并去除前后空格。
- 空消息过滤:如果输入内容为空,直接返回,不执行后续操作,避免发送空消息。
3.2 生成用户消息的 HTML 结构:
// 添加用户消息
const userMessageHtml = `
<div class="flex items-start space-x-2 justify-end">
<div class="max-w-[70%]">
<div class="bg-blue-600 text-white p-4 rounded-lg rounded-tr-none shadow-sm">
<p>${message}</p>
<span class="text-xs text-blue-200 mt-1 block">${getCurrentTime()}</span>
</div>
</div>
<div class="w-8 h-8 rounded-full bg-blue-500 flex items-center justify-center">
<span class="text-white">我</span>
</div>
</div>
- 外层容器:
flex items-start space-x-2 justify-end
:使用弹性布局,子元素从顶部开始排列,水平间距为 2 单位,用户消息右对齐(justify-end
)。 - 消息内容区域:
max-w-[70%]
:消息内容最大宽度为父容器的 70%,避免消息过宽。 - 消息气泡:
bg-blue-600 text-white p-4 rounded-lg rounded-tr-none shadow-sm
:蓝色背景,白色文字,内边距 4 单位,圆角(右上角为直角,rounded-tr-none
),添加阴影。 - 消息内容:
<p>${message}</p>
:显示用户输入的消息内容。 - 时间戳:
<span class="text-xs text-blue-200 mt-1 block">${getCurrentTime()}</span>
:小字体,浅蓝色,距离顶部 1 单位,块级元素,显示当前时间(通过getCurrentTime
函数获取)。 - 用户头像:
w-8 h-8 rounded-full bg-blue-500 flex items-center justify-center
:8x8 单位的圆形,蓝色背景,内部文字 “我” 居中显示。
3.3 插入用户消息到容器:
messageContainer.insertAdjacentHTML('beforeend', userMessageHtml);
- 将生成的用户消息 HTML 插入到
messageContainer
的末尾,更新界面显示用户消息。
3.4 清空输入框并聚焦:
messageInput.value = '';
messageInput.focus();
- 清空输入框内容,准备接收下一条消息,并将焦点保持在输入框,方便用户继续输入。
3.5 滚动到底部:
scrollToBottom();
- 调用
scrollToBottom
函数,确保消息容器滚动到最底部,显示最新的用户消息。
4. "正在输入" 动画效果
// 显示加载指示器
const typingIndicator = `
<div id="typingIndicator" class="flex items-start space-x-2">
<div class="w-8 h-8 rounded-full bg-gray-200 flex items-center justify-center">🤖</div>
<div class="max-w-[70%]">
<div class="bg-white p-4 rounded-lg rounded-tl-none shadow-sm">
<div class="flex space-x-1">
<div class="w-2 h-2 rounded-full bg-gray-400 animate-pulse"></div>
<div class="w-2 h-2 rounded-full bg-gray-400 animate-pulse" style="animation-delay: 0.2s"></div>
<div class="w-2 h-2 rounded-full bg-gray-400 animate-pulse" style="animation-delay: 0.4s"></div>
</div>
</div>
</div>
</div>
`;
messageContainer.insertAdjacentHTML('beforeend', typingIndicator);
scrollToBottom();
- 动画实现:使用三个小圆点的脉冲动画(
animate-pulse
) - 交错延迟:通过 CSS 动画延迟(0.2s 和 0.4s)创造波浪效果
- AI 标识:使用🤖图标区分 AI 回复
5. 模拟 AI 回复逻辑
// 模拟AI回复
setTimeout(() => {
// 移除"正在输入"指示器
const typing = document.getElementById('typingIndicator');
if (typing) typing.remove();
// 根据用户消息生成不同的回复
let aiResponse = "";
if (message.toLowerCase().includes('python')) {
aiResponse =
`这是一个简单的Python函数示例:
def calculate_sum(a, b):
"""计算两个数字的和"""
return a + b
# 调用函数
result = calculate_sum(5, 3)
print(f"结果是: {result}")
\n
这个函数接受两个参数并返回它们的和。`;
} else if (message.toLowerCase().includes('hello') || message.toLowerCase().includes('hi')) {
aiResponse = "您好!很高兴见到您。有什么我可以帮助您的吗?";
} else if (message.includes('你是谁')) {
aiResponse = "我是AI小助手,您的智能聊天伙伴!";
} else {
aiResponse = "感谢您的提问。我正在学习更多知识,以便更好地回答您的问题。";
}
// 添加AI回复
const aiMessageHtml = `
<div class="flex items-start space-x-2">
<div class="w-8 h-8 rounded-full bg-gray-200 flex items-center justify-center">🤖</div>
<div class="max-w-[70%]">
<div class="bg-white p-4 rounded-lg rounded-tl-none shadow-sm">
<pre class="text-sm bg-gray-50 p-3 rounded-md"><code>${aiResponse}</code></pre>
<span class="text-xs text-gray-500 mt-2 block">${getCurrentTime()}</span>
</div>
</div>
</div>
`;
messageContainer.insertAdjacentHTML('beforeend', aiMessageHtml);
scrollToBottom();
}, 1000 + Math.random() * 1000); // 随机延迟1-2秒
}
- 关键词匹配:根据用户输入内容生成不同回复
- 代码格式化:使用
<pre><code>
标签保持 Python 代码格式 - 随机延迟:模拟 AI 思考时间,增强真实感
6. 滚动控制函数
function scrollToBottom() {
messageContainer.scrollTop = messageContainer.scrollHeight;
}
- 自动滚动:确保最新消息始终可见
- 调用时机:发送消息后、显示 / 隐藏加载指示器后
7. 事件绑定
// 按钮点击触发发送
sendButton.addEventListener('click', sendMessage);
// 回车键触发发送
messageInput.addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
sendMessage();
}
});
// 页面加载后自动聚焦输入框
messageInput.focus();
- 双触发机制:支持鼠标点击和键盘回车发送消息
- 自动聚焦:用户无需手动点击输入框
8. 消息 UI 设计
元素 | 用户消息 | AI 回复 |
---|---|---|
气泡颜色 | 蓝色 (bg-blue-600 ) |
白色 (bg-white ) |
对齐方式 | 右对齐 (justify-end ) |
左对齐(默认) |
头像 | 蓝色圆形 + 文字 "我" | 灰色圆形 +🤖图标 |
时间戳 | 浅蓝色小字 (text-blue-200 ) |
浅灰色小字 (text-gray-500 ) |
最大宽度 | 70% (max-w-[70%] ) |
70% (max-w-[70%] ) |
三、总结
整个交互逻辑的流程就是:当页面加载完成后,通过ID绑定获取输入框、发送按钮和消息容器元素,监听按钮点击和回车事件触发消息发送——用户输入经非空验证后,以右侧蓝色气泡形式显示并附带时间戳,随后展示左侧的"正在输入"动画,经过1-2秒模拟延迟后,根据消息关键词(如Python/问候语/身份询问)动态生成对应回复,以代码块或文本形式在左侧灰色气泡中呈现,整个过程通过DOM操作实时更新界面并保持自动滚动,形成完整的伪实时对话交互闭环。