一、vue智能Ai对话(高仿通义千问)普通版。
如需源码:请私信。
普通版视频地址:普通版视频
流式进阶版视频地址:流式进阶版视频
流式进阶版:流式进阶版源码
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,
// 当前聊天会话ID
currentChatId: 1,
// 用户输入内容
userInput: '',
// 聊天历史记录
chatHistory: [],
// 所有消息记录
allMessages: [],
// 当前会话消息列表
messageList: [],
};
},
// 监听消息列表变化
watch: {
messageList: {
immediate: true,
deep: true,
// 消息列表变化时滚动到底部
handler () {
this.$nextTick(() => {
this.scrollToBottom();
});
},
},
},
// 组件挂载完成时加载历史记录
mounted () {
this.loadChatHistory();
},
methods: {
// 切换聊天会话
switchChat (chatId) {
// 设置当前聊天会话ID
this.currentChatId = chatId;
// 过滤出当前聊天会话的消息
this.messageList = this.allMessages.filter(item => item.chatId == chatId);
},
// 创建新的聊天会话
createNewChat () {
// 重置消息计数器
this.messageCount = 1;
// 增加当前聊天会话ID
this.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 Plus
app.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: