用vue3写一个AI聊天室

效果图如下:

1、页面布局:

<template><div class="body" style="background-color: rgb(244, 245, 248); height: 730px"><div class="container"><div class="right"><div class="top">AI问答</div><div class="chat" ref="chatContainer"><divv-for="(item, i) in msgList":key="i":class="item.type == '1' ? 'rightMsg' : 'leftMsg'"><imgv-if="item.type == '0'"src="../assets/images/AI.png"alt=""/><div class="msg">{{ item.content }}</div><imgv-if="item.type == '1'"src="../assets/images/me.png"alt=""/></div><!-- <div v-if="msgList.length >= 10" class="separator">-------------- 本AI问答仅显示最近10条对话 --------------</div> --></div><div class="bottom"><input v-model="value" placeholder="请输入您想提问的内容" /><button @click="onSend"><img src="../assets/images/send.png" alt="发送" /></button></div></div></div></div>
</template>

2、封转函数(用户输入问题和AI回答问题):

const msgList = reactive([]);
//提问
const userQuestion = (question) => {var userMsg = {content: question,type: "1",id: Date.now(),};msgList.push(userMsg);
};
//回答
const AIReplay = (replay) => {var autoReplyMsg = {content: replay,type: "0",id: Date.now(),};msgList.push(autoReplyMsg);
};

3、从后端获取最近的10个对话:

const getMes = () => {getQandA({}).then((res) => {console.log(res);if (res.data.status == 200) {// 获取最近五条问答信息for (var i = 0; i < 5; i++) {userQuestion(res.data.data[i].inputMessage);AIReplay(res.data.data[i].aiResult);}scrollToNew();}});
};

4、为了使用户发送问题后内容滚动在最底处,写一个函数让其自动滚动,在发送信息和获取信息时调用该函数即可

// 等待DOM更新完成。自动滚动到最新发送的消息处
const scrollToNew = async () => {await nextTick();const chatContainer = document.querySelector(".chat");if (chatContainer) {chatContainer.scrollTop = chatContainer.scrollHeight;}
};

5、点击发送按钮,发送到后端进行处理:

const onSend = () => {// 发送用户输入的消息AIQandA({inputMessage: value.value,}).then((res) => {console.log(res);if (res.data.status == 200) {console.log(6666);AIReplay(res.data.data);scrollToNew();}});userQuestion(value.value);scrollToNew();value.value = "";
};

完整代码如下:

<template><Header></Header><div class="body" style="background-color: rgb(244, 245, 248); height: 730px"><header><div class="cover"><imgsrc="1.png"alt=""style="width: 100%; height: 100%"/></div></header><main><div class="container"><div class="right"><div class="top">AI问答</div><div class="chat" ref="chatContainer"><divv-for="(item, i) in msgList":key="i":class="item.type == '1' ? 'rightMsg' : 'leftMsg'"><imgv-if="item.type == '0'"src="../assets/images/AI.png"alt=""/><div class="msg">{{ item.content }}</div><imgv-if="item.type == '1'"src="../assets/images/me.png"alt=""/></div><!-- <div v-if="msgList.length >= 10" class="separator">-------------- 本AI问答仅显示最近10条对话 --------------</div> --></div><div class="bottom"><input v-model="value" placeholder="请输入您想提问的内容" /><button @click="onSend"><img src="../assets/images/send.png" alt="发送" /></button></div></div></div></main></div><foot></foot>
</template><script setup>
import { ref, reactive, nextTick, onMounted } from "vue";
import Header from "../components/header.vue";
import foot from "../components/foot.vue";
import { AIQandA, getQandA } from "../api/AIApi";
const value = ref("");
const msgList = reactive([]);
onMounted(() => {getMes();
});
// 等待DOM更新完成。自动滚动到最新发送的消息处
const scrollToNew = async () => {await nextTick();const chatContainer = document.querySelector(".chat");if (chatContainer) {chatContainer.scrollTop = chatContainer.scrollHeight;}
};
const userQuestion = (question) => {var userMsg = {content: question,type: "1",id: Date.now(),};msgList.push(userMsg);
};
const AIReplay = (replay) => {var autoReplyMsg = {content: replay,type: "0",id: Date.now(),};msgList.push(autoReplyMsg);
};
const getMes = () => {getQandA({}).then((res) => {console.log(res);if (res.data.status == 200) {// 获取最近五条问答信息for (var i = 0; i < 5; i++) {userQuestion(res.data.data[i].inputMessage);AIReplay(res.data.data[i].aiResult);}scrollToNew();}});
};const onSend = () => {// 发送用户输入的消息AIQandA({inputMessage: value.value,}).then((res) => {console.log(res);if (res.data.status == 200) {console.log(6666);AIReplay(res.data.data);scrollToNew();}});userQuestion(value.value);scrollToNew();value.value = "";
};
</script><style scoped lang="scss">
.body {color: #fff;font-weight: 900;letter-spacing: 2px;width: 100%;height: 100%;background-size: 50%;display: flex;align-items: center;position: relative;
}
main {/* border: 1px solid red; */width: 1400px;height: 600px;margin: 100px auto;display: flex;
}
.cover {position: absolute;top: 0px;z-index: 0;height: 180px;width: 1483px;left: 50%;margin-left: -754px;overflow: hidden;
}
.body {:deep(.slick-slide) {text-align: center;height: 100%;line-height: 100%;background: #364d79;overflow: hidden;}:deep(.slick-arrow.custom-slick-arrow) {width: 25px;height: 25px;font-size: 25px;color: #fff;background-color: rgba(31, 45, 61, 0.11);transition: ease all 0.3s;opacity: 0.3;z-index: 1;}:deep(.slick-arrow.custom-slick-arrow:before) {display: none;}:deep(.slick-arrow.custom-slick-arrow:hover) {color: #fff;opacity: 0.5;}:deep(.slick-slide h3) {color: #fff;}
}.container {z-index: 1;// border: solid 1px #bebebe;width: 85%;height: 100%;margin: -6px auto;display: flex;justify-content: center;.right {flex: 1;// border-radius: 10px;background-color: white;display: flex;flex-direction: column;height: 600px;.top {height: 70px;background-color: rgba(147, 213, 255, 0.764);width: 100%;font-size: 22px;text-align: center;line-height: 70px;}.chat {flex: 1;max-height: 580px;overflow-y: auto;padding: 10px;.leftMsg,.rightMsg {display: flex;flex-direction: row;justify-content: start;align-items: center;margin: 10px;img {width: 40px;height: 40px;border-radius: 20px;overflow: hidden;object-fit: cover;margin: 0 10px;}.msg {display: inline-block;padding: 10px;word-wrap: anywhere;max-width: 600px;background-color: #364d79;border-radius: 10px;}}.rightMsg {justify-content: end;.msg {color: black;background-color: #dfdfdf;}}}.bottom {height: 45px;display: flex;align-items: center;width: 80%;margin: 10px auto;input {width: 90%;border: 1px solid rgb(171, 171, 171);border-right: none;height: 40px;color: black;text-indent: 2px;line-height: 40px;border-radius: 10px 0 0 10px;}button {cursor: pointer;width: 10%;border: none;outline: none;height: 45px;border-radius: 0 10px 10px 0;background: linear-gradient(to right,rgb(146, 197, 255),rgb(200, 134, 200));}img {width: 20px;height: 20px;}}}
}
.separator {color: rgb(133, 132, 132);text-align: center;font-size: 15px;font-weight: normal;
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/806146.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何用electron(vue)搜索电脑本地wifi

对于搜索本地 WiFi 网络&#xff0c;可以使用 Electron 结合 Node.js 来编写一个简单的应用程序。 以下是一个基本的示例&#xff0c;它使用 Node.js 的 wifi 模块来搜索并列出附近的 WiFi 网络&#xff1a; 首先&#xff0c;确保你已经安装了 Node.js 和 Electron。 然后&am…

数据结构——线性表(链式存储结构)

语言&#xff1a;C语言软件&#xff1a;Visual Studio 2022笔记书籍&#xff1a;数据结构——用C语言描述如有错误&#xff0c;感谢指正。若有侵权请联系博主 一、线性表的逻辑结构 线性表是n个类型相同的数据元素的有限序列&#xff0c;对n>0&#xff0c;除第一元素无直接…

蓝桥杯刷题 二分-[2145]求阶乘(C++)

问题描述 满足 N! 的末尾恰好有 K 个 0 的最小的 N 是多少? 如果这样的 N 不存在输出 −1。 输入格式 一个整数 K。 输出格式 一个整数代表答案。 样例输入 2 样例输出 10 评测用例规模与约定 对于 30% 的数据&#xff0c;1 ≤ K ≤ 10的6次方 对于 100% 的数据&…

结合 tensorflow.js 、opencv.js 与 Ant Design 创建美观且高性能的人脸动捕组件并发布到InsCode

系列文章目录 如何在前端项目中使用opencv.js | opencv.js入门如何使用tensorflow.js实现面部特征点检测tensorflow.js 如何从 public 路径加载人脸特征点检测模型tensorflow.js 如何使用opencv.js通过面部特征点估算脸部姿态并绘制示意图tensorflow.js 使用 opencv.js 将人脸…

uniapp:聊天消息列表(好友列表+私人单聊)支持App、H5、小程序

&#x1f3ac; 江城开朗的豌豆&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 &#x1f4dd; 个人网站 :《 江城开朗的豌豆&#x1fadb; 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 ⭐ 文章简介&#xff08;效果图展示&#xff…

2024-04-10 Linux gzip 和 gunzip 命令,gzip 压缩的文件通常比原始文件小得多。

一、gzip 是 Linux 系统中用于压缩文件的命令&#xff0c;它通常用于将单个文件压缩成 .gz 格式的文件。gzip 压缩的文件通常比原始文件小得多&#xff0c;因此它在节省磁盘空间和减少文件传输时间方面非常有用。 gzip 命令的基本语法如下&#xff1a; gzip [选项] [文件]复制…

Vue3学习01 Vue3核心语法

Vue3学习 1. Vue3新的特性 2. 创建Vue3工程2.1 基于 vue-cli 创建项目文件说明 2.2 基于 vite 创建具体操作项目文件说明 2.3 简单案例(vite) 3. Vue3核心语法3.1 OptionsAPI 与 CompositionAPIOptions API 弊端Composition API 优势 ⭐3.2 setup小案例setup返回值setup 与 Opt…

ssm038汽车养护管理系统+jsp

汽车养护管理系统设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本汽车养护管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短…

保姆级教程带你实现HarmonyOS手语猜一猜元服务(二)

由于文章篇幅较长&#xff0c;共分为了三篇发布&#xff1a; 保姆级教程带你实现HarmonyOS手语猜一猜元服务&#xff08;一&#xff09; 保姆级教程带你实现HarmonyOS手语猜一猜元服务&#xff08;二&#xff09; 保姆级教程带你实现HarmonyOS手语猜一猜元服务&#xff08;三&…

微信小程序页面交互综合练习 (重点:解决“setData of undefined”报错问题)

一、写一个注册表单&#xff0c;点击“注册”按钮将用户输入的数据带到服务器&#xff0c;并且能在控制台显示参数。 &#xff08;1&#xff09;首先&#xff0c;我需要在vscode里面创建一个简易的node.js服务器 //第一步:引入http模块 var http require(http); //第二步:创建…

自动驾驶定位算法-粒子滤波(Particle Filter)

自动驾驶定位算法-粒子滤波(Particle Filter) 自动驾驶对定位的精度的要求在厘米级的&#xff0c;如何实现厘米级的高精度定位呢&#xff1f;一种众所周知的定位方法是利用全球定位系统(GPS)&#xff0c;利用多颗卫星的测量结果&#xff0c;通过三角测量(Triangulation)机制确…

spring-cloud微服务openfeign

Spring Cloud openfeign对Feign进行了增强&#xff0c;使其支持Spring MVC注解&#xff0c;另外还整合了Ribbon和Nacos&#xff0c;从而使得Feign的使用更加方便 优势&#xff0c;openfeign可以做到使用HTTP请求远程服务时就像洞用本地方法一样的体验&#xff0c;开发者完全感…

自己动手封装axios通用方法并上传至私有npm仓库:详细步骤与实现指南

文章目录 一、构建方法1、api/request.js2、api/requestHandler.js3、api/index.js 二、测试方法1、api/axios.js2、main.js3、app.vue4、vue.config.js5、index.html 三、打包1、配置package.json2、生成库包3、配置发布信息4、发布 四、使用1、安装2、使用 五、维护1、维护和…

M1 Flutter SDK的安装和环境配置

前言 作为iOS 开发&#xff0c;观望了许久的Flutter &#xff0c;还是对它下手了&#xff0c;不是故意要卷&#xff0c;没办法工作需要&#xff01;既然要学Flutter&#xff0c;首先就得配置Flutter的相关环境&#xff0c;由于我的是M1 芯片的电脑&#xff0c;记录下来配置过程…

spring boot 集成 flyway依赖 做数据库迁移,让部署没烦恼

flyway 是一个敏捷工具&#xff0c;用于数据库的移植。采用 Java 开发&#xff0c;支持所有兼容 JDBC 的数据库。 主要用于在你的应用版本不断升级的同时&#xff0c;升级你的数据库结构和里面的数据。 还是直接上代码 第一步&#xff1a; <!-- Flyway 数据库迁移 依赖 他…

python爬虫-------JsonPath(第十九天)

&#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; &#x1f388;&#x1f388;所属专栏&#xff1a;python爬虫学习&#x1f388;&#x1f388; ✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天…

【一学就会】(一)C++编译工具链——基于VSCode的CMake、make与g++简单理解与应用示例

目录 一、CMake、make与g 1、名词辨析 2、孰优孰劣 二、应用示例 1、工具类安装与配置 1&#xff09;VSCode安装与配置 2&#xff09;CMake下载与安装 3&#xff09;MinGW-W64下载与安装 A、科学上网法 B、无需科学上网法 4&#xff09;VSCode推荐插件 A、c/c编译环…

Linux/Ubuntu/Debian中与进程和系统资源有关的命令top/ps

top命令是Linux系统中非常实用的一个工具&#xff0c;其主要功能是展示当前系统中资源使用情况最高的进程列表。通过这个命令&#xff0c;我们可以一目了然地看到哪些进程正在消耗大量的CPU、内存等资源。top命令默认每3秒更新一次数据&#xff0c;提供了实时的系统资源状态&am…

【Qt 学习笔记】QWidget的geometry属性及window frame的影响

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ QWidget的geometry属性 文章编号&#xff1a;Qt 学习笔记 / 16 文章目…

BK-SDM读图片逻辑-评估结果FID逻辑

以inherit为例 这是借助bksdm的代码用于我的A-sdm的生成 bksdm中2个关键路径是 src/genetate.py script/eval_scores.sh 一 以generate.py文件进行生成 借助ms-coco的csv文件里面的30K个提示词和图片名字&#xff0c;来生成图片&#xff0c;并保存 share/huanggao/zjc/code_i2…