使用vue3+pinia2開發(fā)仿制chatgpt界面聊天實例Vue3-Chatgpt
基于Vue3.x+Pinia2+VueRouter+Vue3-Markdown等技術(shù)構(gòu)建仿ChatGPT網(wǎng)頁端聊天程序。支持經(jīng)典+分欄界面布局、light/dark模式、全屏+半屏顯示、Markdown語法解析、側(cè)邊欄隱藏等功能。
技術(shù)框架
- 編輯工具:Cursor
- 框架技術(shù):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
項目目錄結(jié)構(gòu)
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
/*構(gòu)建選項*/
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 和 debugger
drop: env.VITE_DROP_CONSOLE ? ['console', 'debugger'] : []
},
/*開發(fā)服務(wù)器選項*/
server: {
// 端口
port: env.VITE_PORT,
// 是否瀏覽器自動打開
open: env.VITE_OPEN,
// 開啟https
https: env.VITE_HTTPS,
// 代理配置
proxy: {
// ...
}
},
resolve: {
// 設(shè)置別名
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種布局模式,整體分為頂欄+側(cè)邊欄+主體內(nèi)容三大模塊構(gòu)成。
<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">
<!-- 主內(nèi)容區(qū) -->
<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: '發(fā)送語音', 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">網(wǎng)絡(luò)不給力</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: '發(fā)送圖片', theme: 'light', arrow: false}">
<Icon name="ve-icon-photo" size="16" cursor />
<input ref="uploadImgRef" type="file" title="" accept="image/*" @change="handleUploadImage" />
</Button>
<Input
class="flex1"
ref="editorRef"
v-model="editorText"
type="textarea"
:autosize="{maxRows: 4}"
clearable
placeholder="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)
// ...
// 發(fā)送會話
const handleSubmit = () => {
editorRef.value.focus()
if(!editorText.value) return
let data = {
type: 'text',
role: 'User',
key: guid(),
content: editorText.value
}
chatState.addSession(data)
// 清空
editorText.value = ''
}
const handleKeydown = (e) => {
// ctrl+enter
if(e.ctrlKey && e.keyCode == 13) {
handleSubmit()
}
}
const handleClear = () => {
emit('clear')
}
// 選擇圖片
const handleUploadImage = () => {
let file = uploadImgRef.value.files[0]
if(!file) return
let 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.result
let data = {
type: 'image',
role: 'User',
key: guid(),
content: img
}
chatState.addSession(data)
}
}
/**
* 聊天狀態(tài)管理
* @author YXY Q:282310962
*/
import { defineStore } from 'pinia'
import { guid, isEmpty } from '@/utils'
export const chatStore = defineStore('chat', {
state: () => ({
// 聊天會話記錄
sessionId: '',
session: []
}),
getters: {},
actions: {
// 創(chuàng)建新會話
createSession(ssid) {
this.sessionId = ssid
this.session.push({
sessionId: ssid,
title: '',
data: []
})
},
// 新增會話
addSession(message) {
// 判斷當前會話uuid是否存在,不存在創(chuàng)建新會話
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', // 不設(shè)置則是默認app
storage: localStorage,
paths: ['aa', 'bb'] // 設(shè)置緩存鍵
} */
})
好了,基于vue3+vite4+pinia2開發(fā)模仿chatgpt聊天就分享到這里。
Tauri-Vue3聊天實例|Tauri跨端聊天
uniapp-ttlive短視頻聊天|uniapp+uview仿抖音實例文章來源:http://www.zghlxwxcb.cn/news/detail-438630.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-438630.html
到了這里,關(guān)于基于vue3+pinia2仿ChatGPT聊天實例|vite4.x仿chatgpt界面的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!