当前位置: 首页 > article >正文

一、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:


http://www.kler.cn/a/513585.html

相关文章:

  • Github 2025-01-20 开源项目周报 Top15
  • 如何使用 Pytest 断言测试 Python 异常处理
  • Qt基础项目篇——Qt版Word字处理软件
  • Ubuntu cuda-cudnn中断安装如何卸载
  • 【玩转全栈】----Django模板的继承
  • 风吹字符起,诗意Linux:一场指令与自由的浪漫邂逅(上)
  • 数电票:引领会计行业数字化革命的关键力量
  • 定时器setTimeout和setInterval
  • 【RabbitMQ 消息丢失常见情况分析】
  • 依赖倒置原则
  • node和nest生态及区别和优势
  • Swift语言的函数实现
  • 解决MySQL查询不区分大小写的两种方式
  • 【GORM】Hook钩子函数,Session会话函数讲解及使用案例
  • 【2025小年源码免费送】
  • OFD实现在线预览的几种方式
  • 计算机的错误计算(二百一十八)
  • 【Golang/gRPC/Nacos】在golang中将gRPC和Nacos结合使用
  • 刷题日记3
  • 天机学堂7--Redisson自定义注解AOP以及SPEL表达式实现分布式锁
  • 顽固性失眠怎么调理
  • InVideo AI技术浅析(五):生成对抗网络
  • centos下设置服务器开机自启动 redis
  • MongoDB实训:电子商务日志存储任务
  • leetcode 面试经典 150 题:插入区间
  • 音频入门(一):音频基础知识与分类的基本流程