基于vue3+pinia2仿ChatGPT聊天实例|vite4.x仿chatgpt界面
使用vue3+pinia2开发仿制chatgpt界面聊天实例Vue3-Chatgpt
基于Vue3.x+Pinia2+VueRouter+Vue3-Markdown等技术构建仿ChatGPT网页端聊天程序。支持经典+分栏界面布局、light/dark模式、全屏+半屏显示、Markdown语法解析、侧边栏隐藏等功能。
技术框架
- 编辑工具:Cursor
- 框架技术:Vue3+Vite4.x+Pinia2
- 组件库:VEPlus (基于vue3桌面端组件库)
- 国际化多语言:vue-i18n^9.2.2
- 代码高亮:highlight.js^11.7.0
- 本地存储:pinia-plugin-persistedstate^3.1.0
- markdown解析:vue3-markdown-it
项目目录结构
vite.config.js配置
import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
import { parseEnv } from './src/utils/env'// https://vitejs.dev/config/
export default defineConfig(({ mode }) => {const viteEnv = loadEnv(mode, process.cwd())const env = parseEnv(viteEnv)return {plugins: [vue()],// base: '/',// mode: 'development', // development|production/*构建选项*/build: {// minify: 'esbuild', // 打包方式 esbuild(打包快)|terser// chunkSizeWarningLimit: 2000, // 打包大小警告// rollupOptions: {// output: {// chunkFileNames: 'assets/js/[name]-[hash].js',// entryFileNames: 'assets/js/[name]-[hash].js',// assetFileNames: 'assets/[ext]/[name]-[hash].[ext]',// }// }},esbuild: {// 打包去除 console.log 和 debuggerdrop: env.VITE_DROP_CONSOLE ? ['console', 'debugger'] : []},/*开发服务器选项*/server: {// 端口port: env.VITE_PORT,// 是否浏览器自动打开open: env.VITE_OPEN,// 开启httpshttps: env.VITE_HTTPS,// 代理配置proxy: {// ...}},resolve: {// 设置别名alias: {'@': resolve(__dirname, 'src'),'@assets': resolve(__dirname, 'src/assets'),'@components': resolve(__dirname, 'src/components'),'@views': resolve(__dirname, 'src/views'),// 解决vue-i18n警告提示:You are running the esm-bundler build of vue-i18n.'vue-i18n': 'vue-i18n/dist/vue-i18n.cjs.js'}}}
})
main.js主入口
import { createApp } from 'vue'
import App from './App.vue'// 引入Router和Store
import Router from './router'
import Store from './store'// 引入插件配置
import Plugins from './plugins'const app = createApp(App)app
.use(Router)
.use(Store)
.use(Plugins)
.mount('#app')
vue3.x组件库
项目中使用的组件库是基于vue3自定义UI组件库Ve-plus。一个支持40+组件的轻量级组件库。
安装组件
yarn add ve-plus
npm i ve-plus --save
https://blog.csdn.net/yanxinyun1990/article/details/129312570
整体布局
项目支持2种布局模式,整体分为顶栏+侧边栏+主体内容三大模块构成。
<div class="ve__layout-body flex1 flexbox"><!-- //中间栏 --><div class="ve__layout-menus flexbox" :class="{'hidden': store.config.collapse}"><aside class="ve__layout-aside flexbox flex-col"><ChatNew /><Scrollbar class="flex1" autohide size="4" gap="1"><ChatList /></Scrollbar><ExtraLink /><Collapse /></aside></div><!-- //右边栏 --><div class="ve__layout-main flex1 flexbox flex-col"><!-- 主内容区 --><Main /></div>
</div>
<template><div class="vegpt__editor"><div class="vegpt__editor-inner"><Flex :gap="0"><Popover placement="top" trigger="click" width="150"><Button class="btn" type="link" icon="ve-icon-yuyin1" v-tooltip="{content: '发送语音', theme: 'light', arrow: false}"></Button><template #content><div class="flexbox flex-alignc flex-col" style="padding: 15px 0;"><Icon name="ve-icon-yuyin" size="40" color="#0fa27e" /><p class="fs-12 mb-15 c-999">网络不给力</p><Button size="small"><i style="background:#f00;border-radius:50%;box-shadow:0 1px 2px #999;margin-right:5px;height:8px;width:8px;"></i>开始讲话</Button></div></template></Popover><Button class="btn" type="link" v-tooltip="{content: '发送图片', theme: 'light', arrow: false}"><Icon name="ve-icon-photo" size="16" cursor /><input ref="uploadImgRef" type="file" title="" accept="image/*" @change="handleUploadImage" /></Button><Inputclass="flex1"ref="editorRef"v-model="editorText"type="textarea":autosize="{maxRows: 4}"clearableplaceholder="Prompt..."@keydown="handleKeydown"@clear="handleClear"style="margin: 0 5px;"/><Button class="btn" type="link" icon="ve-icon-submit" @click="handleSubmit"></Button></Flex></div></div>
</template>
import { ref, watch } from 'vue'
import { guid } from '@/utils'
import { chatStore } from '@/store/modules/chat'const props = defineProps({value: { type: [String, Number] }
})
const emit = defineEmits(['clear'])const chatState = chatStore()const uploadImgRef = ref()
const editorRef = ref()
const editorText = ref(props.value)// ...// 发送会话
const handleSubmit = () => {editorRef.value.focus()if(!editorText.value) returnlet data = {type: 'text',role: 'User',key: guid(),content: editorText.value}chatState.addSession(data)// 清空editorText.value = ''
}
const handleKeydown = (e) => {// ctrl+enterif(e.ctrlKey && e.keyCode == 13) {handleSubmit()}
}
const handleClear = () => {emit('clear')
}
// 选择图片
const handleUploadImage = () => {let file = uploadImgRef.value.files[0]if(!file) returnlet size = Math.floor(file.size / 1024)console.log(size)if(size > 2*1024) {Message.danger('图片大小不能超过2M')uploadImgRef.value.value = ''return false}let reader = new FileReader()reader.readAsDataURL(file)reader.onload = function() {let img = this.resultlet data = {type: 'image',role: 'User',key: guid(),content: img}chatState.addSession(data)}
}
/*** 聊天状态管理* @author YXY Q:282310962*/import { defineStore } from 'pinia'
import { guid, isEmpty } from '@/utils'export const chatStore = defineStore('chat', {state: () => ({// 聊天会话记录sessionId: '',session: []}),getters: {},actions: {// 创建新会话createSession(ssid) {this.sessionId = ssidthis.session.push({sessionId: ssid,title: '',data: []})},// 新增会话addSession(message) {// 判断当前会话uuid是否存在,不存在创建新会话if(!this.sessionId) {const ssid = guid()this.createSession(ssid)}this.session.map(item => {if(item.sessionId == this.sessionId) {if(!item.title) {item.title = message.content}item.data.push(message)}})// ...},// 获取会话getSession() {return this.session.find(item => item.sessionId == this.sessionId)},// 移除会话removeSession(ssid) {const index = this.session.findIndex(item => item?.sessionId === ssid)if(index > -1) {this.session.splice(index, 1)}this.sessionId = ''},// 删除某一条会话deleteSession(ssid) {// ...},// 清空会话clearSession() {this.session = []this.sessionId = ''}},// 本地持久化存储(默认存储localStorage)persist: true/* persist: {// key: 'chatStore', // 不设置则是默认appstorage: localStorage,paths: ['aa', 'bb'] // 设置缓存键} */
})
好了,基于vue3+vite4+pinia2开发模仿chatgpt聊天就分享到这里。
Tauri-Vue3聊天实例|Tauri跨端聊天
uniapp-ttlive短视频聊天|uniapp+uview仿抖音实例
相关文章:

基于vue3+pinia2仿ChatGPT聊天实例|vite4.x仿chatgpt界面
使用vue3pinia2开发仿制chatgpt界面聊天实例Vue3-Chatgpt 基于Vue3.xPinia2VueRouterVue3-Markdown等技术构建仿ChatGPT网页端聊天程序。支持经典分栏界面布局、light/dark模式、全屏半屏显示、Markdown语法解析、侧边栏隐藏等功能。 技术框架 编辑工具:Cursor框架…...
JDK动态代理和CGLIB动态代理
JDK动态代理和CGLIB动态代理 JDK动态代理和CGLIB动态代理 JDK动态代理和CGLIB动态代理 ① JDK动态代理只提供接口的代理,不支持类的代理,要求被代理类实现接口。JDK动态代理的核心是InvocationHandler接口和Proxy类,在获取代理对象时&#x…...

Jetpack Hilt 框架的基本使用
什么是 Hilt? Hilt 是一个功能强大、用法简单的依赖注入框架,于 2020 年加入到 Jetpack 家族中。它是 Android 团队联系了 Dagger2 团队,一起开发出来的一个专门面向 Android 的依赖注入框架。相比于 Dagger2,Hilt 最明显的特征就…...
exec()在不同namespace执行结果的区别
记录一个很tricky的问题,下面这段code在执行func1时会出现NameError: name List is not defined,但执行func2时一切正常。 import typescontent """ from typing import Listclass GeneratedData:qna: List"""def func1…...
人工智能革命中的22个隐藏职业:推动科技行业的变革
作者 | Manas Sadangi 随着人工智能技术的不断发展,它正在创造一系列前所未有的就业机会。虽然数据科学家、机器学习工程师和人工智能研究人员等传统的人工智能角色得到了广泛认可,但在推动科技行业变革方面,还有一些鲜为人知的职业同样重要。…...
算法题3 — 求字符串中的最长子串
文章目录 题目示例示例1示例2示例3 解题解法1解法2 leetcode 题目 给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。 示例 示例1 输入: s “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。 示例…...

【FreeRTOS】——中断优先级设置中断相关寄存器临界段代码保护调度器挂起与恢复
目录 前言: 一、中断优先级设置 二、中断相关寄存器(STM32-Cortex M3) 三、临界段代码保护 四、任务调度器的挂起和恢复 总结: 前言: 博客笔记根据正点原子视频教程编辑,仅供学习交流使用࿰…...
1.2 什么是eBPF?(下)
四,eBPF的优势 4.1 eBPF程序的动态加载 eBPF程序可以动态地加载到内核中,或从内核中删除。这个要与内核模块的加载与卸载区分开来。这里顺便讨论下eBPF程序与内核模块的区别,如下: 而Linux内核模块是面向内核API编程的,可以直接运行在内核当中。eBPF程序是面向BPF体系结构…...

掌握哪些测试技术才能说自己已经学成了?
一、过硬的基础能力 其实所有的测试大佬都是从底层基础开始的,随着时间,经验的积累慢慢变成大佬。要想稳扎稳打在测试行业深耕,成为测试大牛,首当其冲的肯定就是拥有过硬的基础,所有的基础都是根基,后期所…...
什么是C语言?
C语言是一种高级编程语言,于1972年由Dennis Ritchie在贝尔实验室开发出来。它是一种通用的、结构化的编程语言,被广泛用于系统软件、嵌入式系统、游戏开发以及科学计算等领域。 C语言的设计目标是提供一种简洁、高效、可移植的编程语言,以便…...

SAP-物料主数据-质量管理视图字段解析
过账到质检库存:要勾选,否则收货后库存不进入质检库存HU检验:收货到启用HU管理的库位时产生检验批,例如某个成品物料是收货到C002库位,该库位启用了HU管理,那么此处要勾选。但是如果勾选了,却收…...

TOP RPA·脱普×实在丨日用品企业脱普签约实在智能,构建全域数据智能运营系统
近日,实在智能与脱普日用化学品(中国)有限公司(简称“脱普企业”)在脱普企业上海总部举行“全域数据智能运营”项目启动会,双方领导及项目组关键成员共同参会,就项目目标、实施进程、沟通机制等…...
【Android】Handler(四)Looper的相关知识点
Handler 机制是 Android 多线程间通信的一种常见方式。每个 Handler 对象由一个 Looper 和一个 MessageQueue 组成,用于将 Message 对象处理到指定的线程中。通过创建 Handler 实例,在子线程中创建 Message 对象并通过sendMessage()方法发送给 Handler&a…...

Redis缓存雪崩及解决办法
缓存雪崩 1.缓存雪崩是指在同- -时段大量的缓存key同时失效或者Redis服务宕机,导致大量请求到 达数据库,带来巨大压力。 2.解决方案: ◆给不同的Key的TTL添加随机值 ◆利用Redis集群提高服务的可用性 ◆给缓存业务添加降级限流策略 降级可做为系统的保底…...

Maven私服仓库配置-Nexus详解
目录 一、什么是Maven私服?二、Maven 私服优势三、Maven 私服搭建四、Sonatype Nexus介绍五、Nexus仓库属性和分类六、Nexus仓库配置以及创建仓库七、Nexus配置用户角色八、Maven SNAPSHOT(快照)九、项目当中配置Nexus上传依赖十、项目当中配置Nexus下载依赖十一、测…...
Systrace系列10 —— Binder 和锁竞争解读
本文主要是对 Systrace 中的 Binder 和锁信息进行简单介绍,简单介绍了 Binder 的情况,介绍了 Systrace 中 Binder 通信的表现形式,以及 Binder 信息查看,SystemServer 锁竞争分析等。 Binder 概述 Android 的大部分进程间通信都使用 Binder,这里对 Binder 不做过多的解释…...
React Hooks中使用useState异步回调获取不到最新值的问题
ReactHook中useState异步回调获取不到最新值及解决⽅案 预先了解 setState 的两种传参⽅式 1、直接传⼊新值 setState(options); 列如: const [state, setState] useState(0); setState(state 1); 2、传⼊回调函数 setState(callBack); 例如: …...
JavaScript 高级 (完结)
目录 深浅拷贝 浅拷贝 深拷贝 递归实现深拷贝 js库lodash里面cloneDeep内部实现了深拷贝 JSON序列化 异常处理 throw 抛异常 try /catch 捕获异常 debugg 处理this this指向 普通函数 箭头函数 改变this call() apply() bind() call apply bind 总结 性能优化…...

【P30】JMeter 事务控制器(Transaction Controller)
文章目录 一、事务控制器(Transaction Controller)参数说明二、测试计划设计2.2.1、勾选 Generate parent sample2.2.1、勾选 Include duration of timer and pre-post processors in generated sample 一、事务控制器(Transaction Controlle…...

【MySQL】MySQL的事务原理和实现?
文章目录 MySQL事务的底层实现原理一、事务的目的可靠性和并发处理 二、实现事务功能的三个技术2.1 redo log 与 undo log介绍2.1.1 redo log2.1.2undo log 2.2 mysql锁技术2.2.1 mysql锁技术 2.3 MVCC基础 三、事务的实现3.1 原子性的实现3.1.1 undo log 的生成3.1.2 根据undo…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...

css实现圆环展示百分比,根据值动态展示所占比例
代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...

【项目实战】通过多模态+LangGraph实现PPT生成助手
PPT自动生成系统 基于LangGraph的PPT自动生成系统,可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析:自动解析Markdown文档结构PPT模板分析:分析PPT模板的布局和风格智能布局决策:匹配内容与合适的PPT布局自动…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...

自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...