前言

随着chatgpt智能聊天继续火爆,越来越多的开发者参加其中。明天给大家分享vite4.x搭建繁难网页版仿ChatGpt聊天程序Vue3ChatGPT。

技术框架

  • 编辑工具: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

vue3-chatgpt 反对两种布局模板、dark+light模式、全屏+半屏展现、Markdown语法解析、侧边栏收起等性能。

我的项目构造

基于vite4.x构建我的项目,采纳vue3 setup语法糖编码。

main.js入口文件

import { createApp } from 'vue'import App from './App.vue'// 引入Router和Storeimport Router from './router'import Store from './store'// 引入插件配置import Plugins from './plugins'const app = createApp(App)app.use(Router).use(Store).use(Plugins).mount('#app')

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 和 debugger            drop: env.VITE_DROP_CONSOLE ? ['console', 'debugger'] : []        },        /*开发服务器选项*/        server: {            // 端口            port: env.VITE_PORT,            // 是否浏览器主动关上            open: env.VITE_OPEN,            // 开启https            https: 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'            }        }    }})

公共布局模板

整体分为顶部导航栏、左侧菜单栏、右侧主体栏。

<script setup>    import { computed } from 'vue'    import { appStore } from '@/store/modules/app'    // 引入布局模板    import Classic from './layout/classic/index.vue'    import Columns from './layout/columns/index.vue'    const store = appStore()    const config = computed(() => store.config)    const LayoutConfig = {        classic: Classic,        columns: Columns    }</script><template>    <div class="vegpt__container" :class="{'is-half': store.config.halfScreen}" :style="{'--themeSkin': store.config.skin}">        <component :is="LayoutConfig[config.layout]" />    </div></template><style lang="scss" scoped></style>
<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>
/** * 聊天状态治理 * @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 = ssid            this.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', // 不设置则是默认app        storage: localStorage,        paths: ['aa', 'bb'] // 设置缓存键    } */})

如上图:聊天框采纳Input组件实现性能。

<script setup>    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) 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 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)        }    }    // ...</script>

OK,基于vue3开发仿造chatgpt实例就先分享这么多,心愿大家能喜爱~~

https://segmentfault.com/a/1190000042710924
https://segmentfault.com/a/1190000040711708