基于vue3实现的聊天机器人前端(附代码)
<template>
<div class="container">
<!-- 页面头部 -->
<header>
<h1>跟它说说话吧!</h1>
<p>一个活泼的伙伴,为你提供情感支持!</p>
</header>
<!-- 聊天容器 -->
<div class="chat-container">
<!-- 聊天记录显示区 -->
<div id="chatbox" ref="chatbox" class="chatbox"></div>
<!-- 输入框和发送按钮 -->
<div class="input-container">
<input v-model="message" @keydown.enter="sendMessage" placeholder="输入消息...">
<button @click="sendMessage">🐶 发送消息!</button>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import { v4 as uuidv4 } from 'uuid'; // 引入 UUID 生成库
// 响应式数据
const message = ref(''); // 用户输入的消息
const chatbox = ref(null); // 聊天记录显示区的引用
const chatId = ref(uuidv4()); // 当前会话的唯一标识符
const receiving = ref(false); // 标记是否正在接收消息
const systemPrompt = ref("你是一只活泼可爱的宠物狗,模拟微信聊天应用中的对话。你的任务是为用户提供情感支持和陪伴。记住用户的对话内容,并在短时间内做出相关回应。消息气泡的大小应根据内容长度自动调整。"); // 系统提示信息
// 方法
const generateUUID = () => {
return uuidv4(); // 生成全局唯一标识符
};
const createMessageElement = (text, alignment) => {
const messageElement = document.createElement('div');
messageElement.className = `message ${alignment}`; // 设置消息的对齐方式
const textElement = document.createElement('span');
// 如果消息内容超过20个字符,则截取前20个字符并加上省略号
textElement.textContent = text.length > 20 ? text.slice(0, 20) + '...' : text;
messageElement.appendChild(textElement);
return messageElement;
};
const connectWebSocket = (message) => {
receiving.value = true; // 标记正在接收消息
const url = "your-chat-url";
const websocket = new WebSocket(url);
websocket.addEventListener("open", () => {
// 发送消息到服务器
websocket.send(
JSON.stringify({
chatId: chatId.value,
appId: "nothing-include",
systemPrompt: systemPrompt.value,
message: message
})
);
});
// 创建一个空的消息元素,用于显示从服务器接收到的消息
const messageElement = createMessageElement("", "message-left");
chatbox.value.appendChild(messageElement);
websocket.onmessage = (event) => {
// 将接收到的消息添加到消息元素中
messageElement.innerText += event.data;
// 滚动到底部,确保最新消息可见
chatbox.value.scrollTop = chatbox.value.scrollHeight;
};
websocket.onclose = (event) => {
if (event.code === 1000) {
receiving.value = false; // 正常关闭连接
} else {
// 处理非正常关闭连接的情况
messageElement.textContent += "无法从服务器获取回复。请刷新页面并重试。";
chatbox.value.scrollTop = chatbox.value.scrollHeight;
receiving.value = false;
}
};
};
const sendMessage = () => {
if (!receiving.value && message.value.trim() !== "") {
const messageText = message.value.trim(); // 获取用户输入的消息
message.value = ""; // 清空输入框
// 创建用户消息元素
const messageElement = createMessageElement(messageText, "message-right");
chatbox.value.appendChild(messageElement); // 添加到聊天记录显示区
// 滚动到底部,确保最新消息可见
chatbox.value.scrollTop = chatbox.value.scrollHeight;
// 发送消息到服务器
connectWebSocket(messageText);
}
};
// 生命周期钩子
onMounted(() => {
// 初始化操作
chatbox.value.scrollTop = chatbox.value.scrollHeight;
});
</script>
<style>
body {
/* 页面背景渐变色 */
background: linear-gradient(to right, rgb(249, 244, 200), rgb(249, 244, 240));
}
.container {
/* 容器内边距 */
padding: 16px;
}
header {
/* 页面头部居中对齐 */
text-align: center;
margin-bottom: 16px;
}
h1 {
/* 标题样式 */
font-size: 24px;
font-weight: bold;
color: #1a53ff;
}
p {
/* 描述文字颜色 */
color: #6b7280;
}
.chat-container {
/* 聊天容器最大宽度 */
width: 100%;
max-width: 600px;
/* 阴影效果和圆角 */
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
border-radius: 8px;
overflow: hidden;
margin: 0 auto;
/* 居中 */
}
.chatbox {
/* 聊天记录显示区布局 */
display: flex;
flex-direction: column;
align-items: flex-start;
padding: 16px;
height: 384px;
overflow-y: auto; /* 自动滚动条 */
}
.message {
/* 消息样式 */
display: inline-block;
margin: 10px 0;
padding: 10px;
border-radius: 12px;
color: white;
}
.message-left {
/* 来自机器人的消息样式 */
background-color: #1a53ff;
align-self: flex-start;
}
.message-right {
/* 来自用户的消息样式 */
background-color: #10b981;
align-self: flex-end;
}
.input-container {
/* 输入框和按钮容器布局 */
display: flex;
flex-direction: row;
margin: 16px 0;
padding: 8px;
border-top: 1px solid #d1d5db;
}
input {
/* 输入框样式 */
flex-grow: 1;
padding: 8px;
border: 1px solid #d1d5db;
border-radius: 8px;
margin-right: 8px;
}
button {
/* 发送按钮样式 */
background-color: #1a53ff;
border-radius: 8px;
padding: 8px 16px;
color: white;
font-weight: bold;
}
</style>
效果图 有帮助点个赞吧~
<input>
元素的绑定
<input v-model="message" @keydown.enter="sendMessage" placeholder="输入消息...">
-
v-model="message"
:v-model
是 Vue.js 中的一个指令,用于双向数据绑定。- 在这个例子中,
v-model="message"
将输入框的值与message
变量绑定在一起。每当用户在输入框中输入内容时,message
的值会自动更新;反之,如果message
的值发生变化,输入框的内容也会相应地更新。
-
@keydown.enter="sendMessage"
:@keydown.enter
是 Vue.js 中的一种事件修饰符,用于监听键盘事件。- 在这个例子中,当用户按下回车键(
enter
)时,会触发sendMessage
方法。 - 这样设计的好处是用户可以直接通过回车键发送消息,而不需要点击发送按钮。
引入 UUID 生成库
import { v4 as uuidv4 } from 'uuid'; // 引入 UUID 生成库
import { v4 as uuidv4 } from 'uuid'
:- 这行代码从
uuid
库中导入了v4
方法,并将其重命名为uuidv4
。 uuid
库是一个用于生成唯一标识符(UUID)的库,广泛用于生成唯一的字符串标识。v4
是一种特定的 UUID 版本,生成的是随机的 UUID。
- 这行代码从
generateUUID
方法
const generateUUID = () => {
return uuidv4(); // 生成全局唯一标识符
};
const generateUUID = () => { ... }
:- 这是一个箭头函数,定义了一个名为
generateUUID
的方法。 - 该方法内部调用了
uuidv4()
函数,生成一个全局唯一的标识符(UUID)。 - 返回生成的 UUID 字符串。
- 这是一个箭头函数,定义了一个名为
其他方法
createMessageElement
const createMessageElement = (text, alignment) => {
const messageElement = document.createElement('div');
messageElement.className = `message ${alignment}`; // 设置消息的对齐方式
const textElement = document.createElement('span');
// 如果消息内容超过20个字符,则截取前20个字符并加上省略号
textElement.textContent = text.length > 20 ? text.slice(0, 20) + '...' : text;
messageElement.appendChild(textElement);
return messageElement;
};
-
const createMessageElement = (text, alignment) => { ... }
:- 这是一个箭头函数,定义了一个名为
createMessageElement
的方法。 - 接受两个参数:
text
(消息内容)和alignment
(消息的对齐方式,如message-left
或message-right
)。
- 这是一个箭头函数,定义了一个名为
-
const messageElement = document.createElement('div')
:- 创建一个新的
div
元素,用于表示一条消息。
- 创建一个新的
-
messageElement.className =
message ${alignment}``:- 设置
div
元素的类名,包括固定的message
类和动态的alignment
类(如message-left
或message-right
)。
- 设置
-
const textElement = document.createElement('span')
:- 创建一个新的
span
元素,用于显示消息内容。
- 创建一个新的
-
textElement.textContent = text.length > 20 ? text.slice(0, 20) + '...' : text
:- 设置
span
元素的文本内容。 - 如果消息内容超过20个字符,则截取前20个字符并在末尾加上省略号
...
;否则直接使用原消息内容。
- 设置
-
messageElement.appendChild(textElement)
:- 将
span
元素添加到div
元素中。
- 将
-
return messageElement
:- 返回创建的消息元素。
connectWebSocket
const connectWebSocket = (message) => {
receiving.value = true; // 标记正在接收消息
const url = "wss://backend.buildpicoapps.com/api/chatbot/chat";
const websocket = new WebSocket(url);
websocket.addEventListener("open", () => {
// 发送消息到服务器
websocket.send(
JSON.stringify({
chatId: chatId.value,
appId: "nothing-include",
systemPrompt: systemPrompt.value,
message: message
})
);
});
// 创建一个空的消息元素,用于显示从服务器接收到的消息
const messageElement = createMessageElement("", "message-left");
chatbox.value.appendChild(messageElement);
websocket.onmessage = (event) => {
// 将接收到的消息添加到消息元素中
messageElement.innerText += event.data;
// 滚动到底部,确保最新消息可见
chatbox.value.scrollTop = chatbox.value.scrollHeight;
};
websocket.onclose = (event) => {
if (event.code === 1000) {
receiving.value = false; // 正常关闭连接
} else {
// 处理非正常关闭连接的情况
messageElement.textContent += "无法从服务器获取回复。请刷新页面并重试。";
chatbox.value.scrollTop = chatbox.value.scrollHeight;
receiving.value = false;
}
};
};
-
receiving.value = true
:- 设置
receiving
标记为true
,表示正在接收消息。
- 设置
-
const url = "wss://backend.buildpicoapps.com/api/chatbot/chat"
:- 定义 WebSocket 连接的 URL。
-
const websocket = new WebSocket(url)
:- 创建一个新的 WebSocket 实例,连接到指定的 URL。
-
websocket.addEventListener("open", () => { ... })
:- 监听 WebSocket 连接打开事件。
- 当连接成功打开时,发送消息到服务器。
-
websocket.send(JSON.stringify({ ... }))
:- 将消息对象序列化为 JSON 字符串,并通过 WebSocket 发送到服务器。
- 消息对象包含
chatId
、appId
、systemPrompt
和message
等属性。
-
const messageElement = createMessageElement("", "message-left")
:- 创建一个空的消息元素,用于显示从服务器接收到的消息。
- 设置对齐方式为
message-left
,表示这是来自机器人的消息。
-
chatbox.value.appendChild(messageElement)
:- 将创建的消息元素添加到聊天记录显示区。
-
websocket.onmessage = (event) => { ... }
:- 监听 WebSocket 消息接收事件。
- 当从服务器接收到消息时,将消息内容添加到消息元素中,并滚动到底部以确保最新消息可见。
-
websocket.onclose = (event) => { ... }
:- 监听 WebSocket 连接关闭事件。
- 根据关闭代码判断连接是否正常关闭。
- 如果是非正常关闭,显示错误信息并滚动到底部。
sendMessage
const sendMessage = () => {
if (!receiving.value && message.value.trim() !== "") {
const messageText = message.value.trim(); // 获取用户输入的消息
message.value = ""; // 清空输入框
// 创建用户消息元素
const messageElement = createMessageElement(messageText, "message-right");
chatbox.value.appendChild(messageElement); // 添加到聊天记录显示区
// 滚动到底部,确保最新消息可见
chatbox.value.scrollTop = chatbox.value.scrollHeight;
// 发送消息到服务器
connectWebSocket(messageText);
}
};
-
if (!receiving.value && message.value.trim() !== "")
:- 检查是否正在接收消息且输入框中的内容不为空。
- 如果条件满足,继续执行发送消息的操作。
-
const messageText = message.value.trim()
:- 获取用户输入的消息,并去除首尾的空白字符。
-
message.value = ""
:- 清空输入框的内容。
-
const messageElement = createMessageElement(messageText, "message-right")
:- 创建一个用户消息元素,设置对齐方式为
message-right
,表示这是来自用户的消息。
- 创建一个用户消息元素,设置对齐方式为
-
chatbox.value.appendChild(messageElement)
:- 将创建的消息元素添加到聊天记录显示区。
-
chatbox.value.scrollTop = chatbox.value.scrollHeight
:- 滚动到底部,确保最新消息可见。
-
connectWebSocket(messageText)
:- 调用
connectWebSocket
方法,建立 WebSocket 连接并发送消息到服务器。
- 调用