<template>
<view class="content-wrap">
<!-- 消息 -->
<view class="cu-chat">
<view v-for="(message, index) in messages" :key="index" :class="['cu-item', { self: message.sender === 'user' }]">
<!-- 头像 -->
<view v-if="message.sender !== 'user'" class="cu-avatar radius" :style="{ backgroundImage: `url(${message.avatar})` }"></view>
<view class="main">
<view class="content shadow">
<text user-select>{{ message.content }}</text>
</view>
</view>
<view v-if="message.sender === 'user'" class="cu-avatar radius" :style="{ backgroundImage: `url(${message.avatar})` }"></view>
<view class="date">{{ message.time }}</view>
</view>
</view>
<!-- 发送条 -->
<view class="cu-bar foot input">
<view class="action">
<text class="cuIcon-sound text-grey"></text>
</view>
<input class="solid-bottom" v-model="userInput" @confirm="sendMessage" confirm-type="send" :cursor-spacing="40" :focus="false" maxlength="300" cursor-spacing="10" />
<view class="action">
<text class="cuIcon-emojifill text-grey"></text>
</view>
<button @click="sendMessage" class="cu-btn bg-blue shadow">发送</button>
<view class="cu-tabbar-height"></view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
messages: [],
userInput: '', // 绑定输入框的值
typingIndex: 0, // 当前打印到的文字索引
aiReply: '', // AI回复的完整内容
isTyping: false // 标记AI是否正在打字
};
},
methods: {
sendMessage() {
if (!this.userInput.trim()) return; // 如果输入为空,则不执行任何操作
// 添加用户消息到messages数组
this.messages.push({
sender: 'user',
avatar: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big107000.jpg', // 用户头像URL
content: this.userInput,
time: new Date().toLocaleTimeString('en-US', { hour12: false }).slice(0, 5)
});
// 清空输入框
this.userInput = '';
// 模拟AI回复
this.aiReply = '这是一个关于3D打印技术的回答。'; // 设置AI的回复内容
this.typingIndex = 0;
this.isTyping = true;
this.typeWriter();
this.scrollToBottom(); // 完成打印后滚动到底部
},
typeWriter() {
const speed = 100; // 打印速度(ms)
const messageTime = new Date().toLocaleTimeString('en-US', { hour12: false }).slice(0, 5);
if (this.typingIndex <= this.aiReply.length) {
if (this.messages.length === 0 || this.messages[this.messages.length - 1].sender !== 'ai') {
// 如果列表为空或最后一条不是AI的消息,则添加新消息
this.messages.push({
sender: 'ai',
avatar: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big143004.jpg', // AI头像URL
content: this.aiReply.substring(0, this.typingIndex), // 逐步增加显示的文字
time: messageTime
});
} else {
// 更新最后一条消息的内容
this.$set(this.messages, this.messages.length - 1, {
...this.messages[this.messages.length - 1],
content: this.aiReply.substring(0, this.typingIndex)
});
}
this.typingIndex++;
setTimeout(() => {
this.typeWriter();
}, speed);
} else {
this.isTyping = false;
this.scrollToBottom(); // 完成打印后滚动到底部
}
},
scrollToBottom() {
this.$nextTick(() => {
const res = uni.getSystemInfoSync();
uni.createSelectorQuery()
.in(this)
.select('.cu-chat')
.boundingClientRect((data) => {
//data 可以打印data输出看详细数据,有很多数据信息
console.log(data);
uni.pageScrollTo({
scrollTop: data.height
});
})
.exec();
});
}
}
};
</script>
<style lang="scss" scoped>
.cu-chat {
padding-bottom: 120rpx;
}
.bg-blue {
background-color: #3399ff;
}
.bg-orange {
background-color: #ff6600;
}
.text-blue,
.line-blue,
.lines-blue {
color: #3399ff;
}
.text-orange,
.line-orange,
.lines-orange {
color: #ff6600;
}
.content-wrap {
display: flex;
flex-direction: column;
min-height: calc(100vh);
box-sizing: border-box;
background-color: #f1f1f1;
}
.self {
.content {
background-color: green;
}
}
</style>
可根据项目需要自行修改