<template>
<div id="chat-window">
<ul id="chat-log">
<li
v-for="(message, index) in messages"
:key="index"
:class="{ received: !message.fromMe }"
>
<div class="message-header">{{ message.from }}</div>
<div class="message-body">{{ message.text }}</div>
</li>
</ul>
<div id="chat-input">
<textarea v-model="messageText"></textarea>
<button @click="sendMessage">发送</button>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, ref, nextTick } from "vue";
export default defineComponent({
name: "ChatWindow",
setup() {
const messages = ref<
Array<{ from: string; text: string; fromMe?: boolean }>
>([]);
const messageText = ref<string>("");
const bol = ref(false);
function sendMessage() {
if (messageText.value) {
if (bol.value) {
return;
}
bol.value = true;
const newMessage = {
from: "Me",
text: "",
fromMe: true,
};
const newMessage1 = {
from: "You",
text: "狗",
fromMe: false,
};
messages.value.push(newMessage1);
messages.value.push(newMessage);
const originalText = messageText.value;
// messageText.value = "";
scrollToBottom(); // 先滚动到底部
// 等待滚动到底部后再依次显示消息
nextTick(() => {
// 定时器每200ms将消息一个一个字符地显示出来
let currentIndex = 0;
const timer = setInterval(() => {
if (currentIndex >= originalText.length) {
clearInterval(timer);
nextTick(() => {
newMessage.text = originalText;
scrollToBottom(); // 再次滚动到底部
bol.value = false;
});
return;
}
const currentText = originalText.substring(0, currentIndex + 1);
messages.value[messages.value.length - 1].text = currentText;
scrollToBottom(); // 再次滚动到底部
currentIndex++;
}, 200);
});
}
}
function scrollToBottom() {
const chatLog = document.getElementById("chat-log");
if (chatLog) {
chatLog.scrollTop = chatLog.scrollHeight;
}
}
scrollToBottom(); // 初始化滚动到底部
return {
messages,
messageText,
sendMessage,
scrollToBottom,
};
},
mounted() {
this.scrollToBottom(); // 每次更新聊天记录后滚动到底部
},
});
</script>
<style>
#chat-window {
width: 100%;
height: 100vh;
border: 1px solid #ccc;
overflow: hidden;
display: flex;
flex-direction: column;
}
#chat-log {
list-style: none;
margin: 0;
padding: 0;
height: 100%;
overflow-y: scroll;
}
#chat-log li {
margin-bottom: 10px;
padding: 5px;
border-radius: 5px;
display: flex;
flex-direction: column;
max-width: 100%;
/* max-width: 80%; */
align-items: flex-end;
}
.received {
/* align-self: flex-end; */
align-items: flex-start !important;
background-color: #f5f5f5;
}
.message-header {
font-size: 14px;
font-weight: bold;
margin-bottom: 5px;
}
.message-body {
font-size: 16px;
line-height: 1.5;
}
#chat-input {
display: flex;
align-items: center;
padding: 10px;
background-color: #f5f5f5;
}
#chat-input textarea {
flex: 1;
margin-right: 10px;
border-radius: 5px;
padding: 5px;
font-size: 16px;
border: 1px solid #ccc;
}
#chat-input button {
background-color: #007bff;
color: #fff;
padding: 5px 10px;
border-radius: 5px;
border: none;
cursor: pointer;
font-size: 16px;
}
</style>
vue3简易对话窗口
最新推荐文章于 2025-04-01 22:23:34 发布