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

用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>

相关文章:

用vue3写一个AI聊天室

效果图如下&#xff1a; 1、页面布局&#xff1a; <template><div class"body" style"background-color: rgb(244, 245, 248); height: 730px"><div class"container"><div class"right"><div class"…...

photomaker:customizing realistic human photos via stacked id embedding

PhotoMaker: 高效个性化定制人像照片文生图 - 知乎今天分享我们团队最新的工作PhotoMaker的技术细节。该工作开源5天Githubstar数已过6千次&#xff0c;已列入Github官方Trending榜第一位&#xff0c;PaperswithCode热度榜第一位&#xff0c;HuggingFace Spaces趋势榜第一位。项…...

FFmpeg - 如何在Linux上安装支持CUDA的FFmpeg

FFmpeg - 如何在Linux(Ubuntu)上安装支持CUDA的FFmpeg 笔者认为现在的很多“xx教程”只讲干什么不讲为什么&#xff0c;这样即使报错了看官也不知道如何解决。 在安装过程的探索部分会记录我的整个安装过程以及报错和报错的解决办法。 在省流之一步到位的方法部分会省去安装过…...

新火种AI|商汤发布下棋机器人元萝卜,率先深入家庭场景。

作者&#xff1a;小岩 编辑&#xff1a;彩云 如今提及生成式AI&#xff08;AIGC&#xff09;&#xff0c;已经不算什么新鲜产物了。自2014年GAN神经网络出现&#xff0c;2017年Transformer架构演进&#xff0c;再加上2023年ChatGPT的大火&#xff0c;无不说明生成式AI正在有条…...

CSS实现三栏自适应布局(两边固定,中间自适应)

绝对定位的元素会脱离文档流&#xff0c;它们是相对于包含块&#xff08;通常是最近的具有相对定位、绝对定位或固定定位属性的父元素&#xff09;进行定位的。当你把一个绝对定位的元素的高度设置为100%时&#xff0c;它会相对于其包含块的高度来确定自己的高度。如果包含块是…...

MoCo 算法阅读记录

论文地址&#xff1a;&#x1f430; 何凯明大神之作&#xff0c;通过无监督对比学习预训练Image Encoder的表征能力。后也被许多VLP算法作为ITC的底层算法来使用。 一方面由于源代码本身并不复杂&#xff0c;但是要求多GPU分布式训练&#xff0c;以及需要下载ImageNet这个大规模…...

华为OD机试 - 数组连续和 - 滑动窗口(Java 2024 C卷 100分)

华为OD机试 2024C卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷C卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;每一题都有详细的答题思路、详细的代码注释、样例测试…...

微店micro获得微店micro商品详情,API接口封装系列

微店商品详情API接口封装系列主要涉及注册账号、获取API密钥、选择API接口、发送请求以及处理响应等步骤。以下是详细的流程&#xff1a; 请求示例&#xff0c;API接口接入Anzexi58 一、注册账号并获取API密钥 首先&#xff0c;你需要在微店开放平台注册一个账号。注册成功后…...

C语言中的数据结构--链表的应用1(2)

前言 上一节我们学习了链表的概念以及链表的实现&#xff0c;那么本节我们就来了解一下链表具体有什么用&#xff0c;可以解决哪些实质性的问题&#xff0c;我们借用习题来加强对链表的理解&#xff0c;那么废话不多说&#xff0c;我们正式进入今天的学习 单链表相关经典算法O…...

.Net6 使用Autofac进行依赖注入

一、背景 刚接触.net 6&#xff0c;记录一下在.net6上是怎么使用Autofac进行动态的依赖注入的 二、注入方式 1、新建一个webapi项目&#xff0c;框架选择net 6 2、引用Nuget包---Autofac.Extensions.Dependency   3、在Program.cs上添加如下代码 //依赖注入 builder.Host.Us…...

第十二届蓝桥杯省赛真题(C/C++大学B组)

目录 #A 空间 #B 卡片 #C 直线 #D 货物摆放 #E 路径 #F 时间显示 #G 砝码称重 #H 杨辉三角形 #I 双向排序 #J 括号序列 #A 空间 #include <bits/stdc.h> using namespace std;int main() {cout<<256 * 1024 * 1024 / 4<<endl;return 0; } #B 卡片…...

DC40V降压恒压芯片H4120 40V转5V 3A 40V降压12V 车充降压恒压控制器

同步整流恒压芯片在现代电子设备中发挥着重要作用&#xff0c;为各种设备提供了稳定、高效的电源管理解决方案。 同步整流恒压芯片是一种电源管理芯片&#xff0c;它能够在不同电压输入条件下保持输出电压恒定。这种芯片广泛应用于各种电子设备中&#xff0c;如通讯设备、液晶…...

2、Qt UI控件 -- qucsdk项目使用

前言&#xff1a;上一篇文章讲了qucsdk的环境部署&#xff0c;可以在QDesigner和Qt Creator中看到qucsdk控件&#xff0c;这一篇来讲下在项目中使用qucsdk库中的控件。 一、准备材料 要想使用第三方库&#xff0c;需要三个先决条件&#xff0c; 1、控件的头文件 2、动/静态链…...

MATLAB算法实战应用案例精讲-【人工智能】AIGC概念三部曲(三)

目录 前言 算法原理 大模型 什么是AIGC? AIGC和Chat GPT的关系 常见的AIGC应用...

外汇110:外汇交易不同货币类别及交易注意事项!

外汇市场是一个庞大而复杂的市场&#xff0c;其中有各种各样的货币品种。对于外汇投资者来说&#xff0c;了解外汇品种的特性和走势是比较重要的。1. 货币种类 外汇市场中的货币品种可以分为主要货币、次要货币和外围货币。 主要货币&#xff1a;主要指美元、欧元、英镑、日元、…...

gerrit 拉取失败

在浏览器gerrit的设置界面设置的邮箱地址和在命令行使用git config --gloable user.email设置的邮箱地址必须保持一致吗 在浏览器gerrit的设置界面设置的邮箱地址和在命令行使用git config --global user.email设置的邮箱地址并不一定需要保持一致。这两个邮箱地址是独立的&am…...

大数据行业英语单词巩固20240410

20240410 Communication - 沟通 Example: Effective communication is essential for project success. 有效的沟通对于项目的成功至关重要。 Collaboration - 协作 Example: Team collaboration is crucial in achieving our goals. 团队协作对于实现我们的目标至关重要。 …...

天软特色因子看板 (2024.4 第3期)

该因子看板跟踪天软特色因子A05005(近一月单笔流出金额占比(%)&#xff0c;该因子为近一月单笔流出金额占比(% 均值因子&#xff0c;用以刻画下跌时的 单成交中可能存在的抄底现象 今日为该因子跟踪第3期&#xff0c;跟踪其在SH000852 (中证1000) 中的表现&#xff0c;要点如下…...

使用QT 开发不规则窗体

使用QT 开发不规则窗体 不规则窗体贴图法的不规则窗体创建UI模板创建一个父类创建业务窗体main函数直接调用user_dialog创建QSS文件 完整的QT工程 不规则窗体 QT中开发不规则窗体有两种方法&#xff1a;&#xff08;1&#xff09;第一种方法&#xff0c;使用QWidget::setMask函…...

如何构建企业经营所需的商业智能(BI)能力

构建企业经营所需的商业智能&#xff08;BI&#xff09;能力是一项涉及诸多关键环节与细致考量的系统工程&#xff0c;通过科学的数据处理、分析与应用&#xff0c;赋能企业实现精准决策&#xff0c;提升运营效率&#xff0c;优化业务流程&#xff0c;并在竞争激烈的市场环境中…...

墨语灵犀对比传统方法:自动化作业批改效果实测

墨语灵犀对比传统方法&#xff1a;自动化作业批改效果实测 作为一名在教育技术领域摸爬滚打了多年的从业者&#xff0c;我见过太多关于“AI批改作业”的讨论。从最初的简单关键词匹配&#xff0c;到后来的规则引擎&#xff0c;每次技术迭代都让人充满期待&#xff0c;但实际落…...

为什么LivePortrait能吊打Diffusion模型?揭秘快手69M训练数据背后的技术取舍

LivePortrait为何能突破扩散模型瓶颈&#xff1f;解析69M训练数据驱动的工业级优化策略 当开源社区还在为扩散模型的生成质量惊叹时&#xff0c;快手LivePortrait团队已经用12.8ms/帧的推理速度和6.5K GitHub星标证明&#xff1a;在工业级人像动画领域&#xff0c;隐式关键点框…...

Qwen3-ASR-1.7B惊艳效果:自动识别中英文技术文档朗读中的公式/代码块

Qwen3-ASR-1.7B惊艳效果&#xff1a;自动识别中英文技术文档朗读中的公式/代码块 你有没有遇到过这样的场景&#xff1f;听一场技术分享的录音&#xff0c;讲师在讲解代码逻辑时&#xff0c;你一边听一边手忙脚乱地记录&#xff0c;生怕漏掉一个括号或一个变量名。或者&#x…...

Apache Flink Agents 0.2.1 发布公告

Apache Flink 社区很高兴地宣布发布 Apache Flink Agents 0.2 系列的首个缺陷修复版本。 此版本包含 3 项缺陷和漏洞修复以及一些对Flink-Agents 0.2的小幅改进。下面列出了所有缺陷修复和改进内容&#xff08;不包括构建基础设施和构建稳定性方面的改进&#xff09;。如需查看…...

Pixel Dream Workshop 企业级部署架构:基于 Docker 的高可用方案

Pixel Dream Workshop 企业级部署架构&#xff1a;基于 Docker 的高可用方案 1. 为什么企业需要高可用部署方案 当Pixel Dream Workshop从开发测试环境走向生产环境时&#xff0c;稳定性、扩展性和可维护性就成为了关键考量。想象一下&#xff0c;当营销团队急需批量生成节日…...

昆明理工大学材料科学与工程考研复试资料|F001现代材料测试技术专项复习包|电子版

温馨提示&#xff1a;文末有联系方式一、昆明理工大学材料科学与工程专业复试资料全面升级 专为报考昆明理工大学材料科学与工程学院硕士研究生设计&#xff0c;深度对标最新复试大纲&#xff0c;系统梳理核心考核模块&#xff0c;助力考生精准把握复试命方向与评分标准。二、F…...

别再手动敲命令了!用PyCharm自带功能一键创建Linux桌面快捷方式(附手动配置备份方案)

告别终端&#xff1a;PyCharm内置工具3秒生成Linux桌面快捷方式&#xff08;附应急手动方案&#xff09; 每次打开PyCharm都要在终端输入一长串路径&#xff1f;作为开发者&#xff0c;我们的时间应该花在创造价值上&#xff0c;而不是重复输入命令。JetBrains早就为Linux用户准…...

终极Windows驱动管家:DriverStore Explorer释放系统空间完全指南

终极Windows驱动管家&#xff1a;DriverStore Explorer释放系统空间完全指南 【免费下载链接】DriverStoreExplorer Driver Store Explorer [RAPR] 项目地址: https://gitcode.com/gh_mirrors/dr/DriverStoreExplorer 引言&#xff1a;被遗忘的驱动仓库 你是否曾疑惑为…...

终极Windows风扇控制解决方案:FanControl如何让你的电脑既安静又高效

终极Windows风扇控制解决方案&#xff1a;FanControl如何让你的电脑既安静又高效 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com/GitH…...

2025年SQL2API平台深度评测:QuickAPI、dbapi与Magic API的实战应用指南

1. 2025年SQL2API平台的核心价值与应用场景 在数据爆炸的时代&#xff0c;企业每天产生的数据量呈指数级增长。我曾参与过一个零售企业的数据中台项目&#xff0c;他们的商品数据分散在5个不同系统的数据库中&#xff0c;光是整理基础数据接口就耗费了团队两周时间。直到我们引…...