如需源码:请私信。
普通版视频地址:普通版视频
流式进阶版视频地址:流式进阶版视频
流式进阶版:流式进阶版源码
html结构和js方法:
<!DOCTYPE html>
<html lang="zh"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>研发工具</title><script src="https://unpkg.com/vue@3/dist/vue.global.js"></script><link rel="stylesheet" href="https://unpkg.com/element-plus/dist/index.css"><script src="https://unpkg.com/element-plus"></script><script src="https://unpkg.com/@element-plus/icons-vue"></script><link rel="stylesheet" href="common.css">
</head><body><div id="app"><div class="chat-container"><el-container style="height: 100%"><el-aside width="80px" class="nav-sidebar"><el-icon style="font-size: 30px"><chat-dot-square /></el-icon><div style="font-size: 12px">对话</div></el-aside><el-main class="main-wrapper"><el-card style="height: 100%"><el-container class="chat-wrapper"><el-aside class="chat-sidebar" width="250px"><div class="sidebar-header"><el-button style="width: 80%" :disabled="isDisabled" type="primary" round @click="createNewChat"><el-icon><plus /></el-icon><span>新建对话</span></el-button></div><div class="chat-list"><el-button :disabled="isDisabled" class="chat-item":class="{ 'chat-item-active': item.chatId == this.currentChatId }" v-for="item in chatHistory":key="item.value" @click="switchChat(item.chatId)"><span class="chat-title-text">{{ item.value }}</span></el-button></div></el-aside><el-container><el-main class="message-container"><el-scrollbar ref="messageScrollbar"><div v-for="item in messageList" :key="item.value"><div v-if="item.show" class="message-user"><pre class="message-content">{{ item.value }}</pre><el-icon class="user-avatar"><avatar /></el-icon></div><div v-if="!item.show" class="message-bot"><img src="./img/home.png" /><pre class="message-content">{{ item.value }}</pre></div></div></el-scrollbar></el-main><el-footer class="chat-footer"><el-input style="width: 50%" v-model="userInput" placeholder="请输入聊天内容" @keyup.enter="sendMessage"><template #suffix><el-icon @click="sendMessage" style="cursor: pointer"><promotion /></el-icon></template></el-input></el-footer></el-container></el-container></el-card></el-main></el-container></div></div><script>const App = {// 定义响应式数据data () {return {// 控制按钮禁用状态isDisabled: false,// 消息计数器messageCount: 1,// 当前聊天会话IDcurrentChatId: 1,// 用户输入内容userInput: '',// 聊天历史记录chatHistory: [],// 所有消息记录allMessages: [],// 当前会话消息列表messageList: [],};},// 监听消息列表变化watch: {messageList: {immediate: true,deep: true,// 消息列表变化时滚动到底部handler () {this.$nextTick(() => {this.scrollToBottom();});},},},// 组件挂载完成时加载历史记录mounted () {this.loadChatHistory();},methods: {// 切换聊天会话switchChat (chatId) {// 设置当前聊天会话IDthis.currentChatId = chatId;// 过滤出当前聊天会话的消息this.messageList = this.allMessages.filter(item => item.chatId == chatId);},// 创建新的聊天会话createNewChat () {// 重置消息计数器this.messageCount = 1;// 增加当前聊天会话IDthis.currentChatId = this.currentChatId + 1;// 清空当前会话消息列表this.messageList = [];},// 加载聊天历史记录loadChatHistory () {// 将当前会话消息列表添加到所有消息记录this.allMessages.push(...this.messageList);// 恢复按钮禁用状态this.isDisabled = false;},// 发送消息async sendMessage () {this.isDisabled = true;if (this.userInput.trim()) {// 创建用户消息对象let message = {type: 'user',value: this.userInput,show: true,chatId: this.currentChatId,messageId: this.messageCount,};// 添加用户消息到列表this.messageList.push(message);// 创建机器人响应消息const botResponse = {type: 'bot',value: '正在思考....',show: false,chatId: this.currentChatId};// 添加机器人响应到列表this.messageList.push(botResponse);// 如果是新会话的第一条消息,添加到历史记录if (message.messageId == 1) {this.chatHistory.push(message);// 倒序this.chatHistory.reverse();}// 更新消息计数器this.messageCount = this.messageCount + 1;// 清空输入框this.userInput = '';// 获取机器人响应消息的索引const responseIndex = this.messageList.length - 1;// 模拟响应延迟setTimeout(() => {// 如果机器人响应消息是“正在思考....”,则替换为“抱歉,我没有获取到正确的回复”if (this.messageList[responseIndex].value === '正在思考....') {this.messageList[responseIndex].value = '抱歉,我没有获取到正确的回复';}// 恢复按钮禁用状态this.isDisabled = false;}, 2000)} else {this.$message.warning('输入不能为空');}},// 滚动到消息列表底部scrollToBottom () {this.$nextTick(() => {// 获取消息列表的滚动条 const scrollbar = this.$refs.messageScrollbar;if (scrollbar) {// 获取滚动条的容器const wrapEl = scrollbar.wrapRef;// 滚动到容器底部wrapEl.scrollTop = wrapEl.scrollHeight;}});},},};// 创建Vue应用实例const app = Vue.createApp(App);// 使用Element Plusapp.use(ElementPlus);// 注册图标组件app.component('chat-dot-square', ElementPlusIconsVue.ChatDotSquare);app.component('plus', ElementPlusIconsVue.Plus);app.component('promotion', ElementPlusIconsVue.Promotion);app.component('avatar', ElementPlusIconsVue.Avatar);// 挂载应用app.mount("#app");</script>
</body></html>
css文件:
* {margin: 0;padding: 0;box-sizing: border-box;
}body {background: #f5f5f5;font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
}.chat-container {box-sizing: border-box;width: 100%;height: 100vh;background-image: url(./img/bag.jpg), linear-gradient(105deg, rgb(97, 92, 237) 7%, rgb(213, 220, 255) 66%);background-position: left center;background-size: cover;background-repeat: no-repeat;
}.chat-container .chat-footer .el-input__wrapper {box-sizing: border-box;height: 80px;border-radius: 20px;
}.chat-container .main-wrapper .el-card__body {height: 100%;padding: 0 !important;
}.chat-container .el-card {border-radius: 12px;position: relative;
}.chat-container .el-footer {min-height: 100px !important;
}.chat-container .el-button+.el-button {margin: 10px 0 0 0 !important;
}.nav-sidebar {box-sizing: border-box;padding: 20px;color: #fff;font-size: 18px;text-align: center;height: 100%;
}.chat-footer {box-sizing: border-box;display: flex;align-items: flex-start;justify-content: center;background-color: rgba(97, 92, 237, 0.1);
}.main-wrapper {box-sizing: border-box;height: 100%;padding: 15px !important;
}.chat-wrapper {height: 100%;
}.chat-sidebar {height: 100%;
}.message-container {background-color: rgba(97, 92, 237, 0.1);height: 100%;display: flex;justify-content: center;
}.message-container .el-scrollbar {width: 70%;
}.message-content {margin: 0 !important;box-sizing: border-box;display: inline-block;background: #fff;padding: 15px;border-radius: 10px;
}.user-avatar {width: 40px !important;height: 40px !important;margin-left: 10px;display: block;font-size: 30px;border-radius: 30px;background: rgba(97, 92, 237, 0.5);padding: 5px;color: #fff;
}.message-user {padding: 15px;display: flex;justify-content: end;
}.message-bot {display: flex;padding: 15px;justify-content: start;
}.message-bot img {width: 40px;height: 40px;margin-right: 10px;
}.sidebar-header {box-sizing: border-box;background: #fff;position: absolute;top: 0;left: 0;width: 250px;padding: 15px;text-align: center;z-index: 100;
}.chat-list {padding: 0 15px 15px 15px;margin-top: 70px;
}.chat-item {box-sizing: border-box;position: relative;width: 100%;height: 36px;justify-content: flex-start;border-radius: 12px;border: 1px solid #fff;font-weight: 400;
}.chat-item:hover {background-color: #f3f2ff;color: #615ced;
}.chat-item-active {border-radius: 30px;background-color: #f3f2ff;color: #615ced;
}.chat-title-text {display: inline-block;max-width: 180px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;
}
图片1:
图片2: