Electron25+vue3桌面端聊天AI实例|electron仿chatgpt
基于最新前端技术栈 vite4+vue3+pinia2+vue-router 整合 electron25 跨端技术开发桌面端仿chatgpt聊天程序。支持经典+分栏布局、暗黑+明亮主题模式、多开窗口功能。
技术框架
编辑器:VScode
使用技术:Electron25+Vite4+Vue3+Pinia2
组件库:VEPlus (基于vue3组件库)
打包插件:electron-builder^23.6.0
代码高亮:highlight.js^11.7.0
markdown插件:vue3-markdown-it
本地缓存:pinia-plugin-persistedstate^3.1.0
electron整合vite插件:vite-plugin-electron^0.11.2
electron-chatgpt 使用的electron25和vite4.x融合开发,运行构建速度非常快,明显改善了之前electron多开窗口卡顿问题。
electron整合vite4创建桌面端程序
electron+vite4窗口多开管理|electron新建多窗口
项目结构目录
布局结构
<template><div class="vegpt__layout flexbox flex-col"><!-- //操作工具栏 --><Toolbar /><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></div>
</template>
electron运行主入口
在项目根目录新建一个electron-main.js
用来作为主进程入口文件。
/*** 主进程入口* @author YXY*/const { app, BrowserWindow } = require('electron')const MultiWindow = require('./src/multiwindow')// 关闭提示
// ectron Security Warning (Insecure Content-Security-Policy)
process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true'const createWindow = () => {let win = new MultiWindow()win.createWin({isMainWin: true})
}app.whenReady().then(() => {createWindow()app.on('activate', () => {if(BrowserWindow.getAllWindows().length === 0) createWindow()})
})app.on('window-all-closed', () => {if(process.platform !== 'darwin') app.quit()
})
然后在vite.config.js
中引入vite-plugin-electron
插件,并配置入口。
import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import electron from 'vite-plugin-electron'
import { resolve } from 'path'
import { parseEnv } from './src/utils/env'export default defineConfig(({ command, mode }) => {const viteEnv = loadEnv(mode, process.cwd())const env = parseEnv(viteEnv)return {plugins: [vue(),electron({// 主进程入口文件entry: 'electron-main.js'})],/*构建选项*/build: {/* minify: 'esbuild', // 打包方式 esbuild(打包快)|terserchunkSizeWarningLimit: 2000, // 打包大小rollupOptions: {output: {chunkFileNames: 'assets/js/[name]-[hash].js',entryFileNames: 'assets/js/[name]-[hash].js',assetFileNames: 'assets/[ext]/[name]-[hash].[ext]',}} */},esbuild: {// 打包去除 console.logdrop: env.VITE_DROP_CONSOLE && command === 'build' ? ["console"] : []},/*开发服务器选项*/server: {port: env.VITE_PORT,// ...},resolve: {// 设置别名alias: {'@': resolve(__dirname, 'src'),'@assets': resolve(__dirname, 'src/assets'),'@components': resolve(__dirname, 'src/components'),'@views': resolve(__dirname, 'src/views')}}}
})
vite-plugin-electron
插件用于集成electron和vite通讯功能。
目前Electron 尚未支持"type": "module"
,需要在package.json
中去掉,并且配置 “main”: "electron-main.js"
, 入口。
electron自定义无边框操作栏窗口
在创建窗口的时候配置 frame: false
,即可创建无边框窗口。设置css3属性-webkit-app-region: drag
,可对自定义操作区域进行拖拽功能。
新建components/titlebar目录
control.vue
<template><div class="vegpt__control ve__nodrag"><div class="vegpt__control-btns" :style="{'color': color}"><slot /><div v-if="isTrue(minimizable)" class="btn win-btn win-min" @click="handleMin"><i class="iconfont ve-icon-minimize"></i></div><div v-if="isTrue(maximizable) && winCfg.window.resizable" class="btn win-btn win-maxmin" @click="handleRestore"><i class="iconfont" :class="isMaximized ? 've-icon-maxrestore' : 've-icon-maximize'"></i></div><div v-if="isTrue(closable)" class="btn win-btn win-close" @click="handleQuit"><i class="iconfont ve-icon-close"></i></div></div></div>
</template><script setup>/*** 封装操作按钮* @author YXY Q:282310962*/import { onMounted, ref } from 'vue'import { winCfg, setWin } from '@/multiwindow/actions'import { appStore } from '@/pinia/modules/app'import { isTrue } from '@/utils'const appState = appStore()const props = defineProps({// 标题颜色color: String,// 窗口是否可以最小化minimizable: { type: [Boolean, String], default: true },// 窗口是否可以最大化maximizable: { type: [Boolean, String], default: true },// 窗口是否可以关闭closable: { type: [Boolean, String], default: true }})// 是否最大化let isMaximized = ref(false)onMounted(() => {window.electronAPI.invoke('win__isMaximized').then(data => {console.log(data)isMaximized.value = data})window.electronAPI.receive('win__hasMaximized', (e, data) => {console.log(data)isMaximized.value = data})})// 最小化const handleMin = () => {window.electronAPI.send('win__minimize')}// 最大化/还原const handleRestore = () => {window.electronAPI.invoke('win__max2min').then(data => {console.log(data)isMaximized.value = data})}// 关闭窗体const handleQuit = () => {if(winCfg.window.isMainWin) {MessageBox.confirm('应用提示', '是否最小化到托盘, 不退出程序?', {type: 'warning',cancelText: '最小化至托盘',confirmText: '残忍退出',confirmType: 'danger',width: 300,callback: action => {if(action == 'confirm') {appState.$reset()setWin('close')}else if(action == 'cancel') {setWin('hide', winCfg.window.id)}}})}else {setWin('close', winCfg.window.id)}}
</script>
index.vue
<template><div class="vegpt__titlebar" :class="{'fixed': isTrue(fixed), 'transparent fixed': isTrue(transparent)}"><div class="vegpt__titlebar-wrapper flexbox flex-alignc ve__drag" :style="{'background': bgcolor, 'color': color, 'z-index': zIndex}"><slot name="left"><img src="/logo.png" height="20" style="margin-left: 10px;" /></slot><div class="vegpt__titlebar-title" :class="{'center': isTrue(center)}"><slot name="title">{{ title || winCfg.window.title || env.VITE_APPTITLE }}</slot></div><!-- 控制按钮 --><Control :minimizable="minimizable" :maximizable="maximizable" :closable="closable"><slot name="btn" /></Control></div></div>
</template>
electron创建系统托盘菜单
创建系统托盘图标文件tray.ico放在resource目录下。
// 创建托盘图标
createTray() {console.log('——+——+——Start Create Tray!')console.log(__dirname)console.log(join(process.env.ROOT, 'resource/tray.ico'))const trayMenu = Menu.buildFromTemplate([{label: '打开主界面',icon: join(process.env.ROOT, 'resource/home.png'),click: () => {try {for(let i in this.group) {let win = this.getWin(i)if(!win) return// 是否主窗口if(this.group[i].isMainWin) {if(win.isMinimized()) win.restore()win.show()}}} catch (error) {console.log(error)}}},{label: '设置中心',icon: join(process.env.ROOT, 'resource/setting.png'),click: () => {for(let i in this.group) {let win = this.getWin(i)if(win) win.webContents.send('win__ipcData', { type: 'CREATE_WIN_SETTING', value: null })}},},{label: '锁屏',icon: join(process.env.ROOT, 'resource/lock.png'),click: () => null,},{label: '关闭托盘闪烁',click: () => {this.flashTray(false)}},{type: 'separator'},{label: '关于',click: () => {for(let i in this.group) {let win = this.getWin(i)if(win) win.webContents.send('win__ipcData', { type: 'CREATE_WIN_ABOUT', value: null })}}},{label: '关闭应用并退出',icon: join(process.env.ROOT, 'resource/quit.png'),click: () => {dialog.showMessageBox(this.main, {title: '询问',message: '确定要退出应用程序吗?',buttons: ['取消', '最小化托盘', '退出应用'],type: 'error',noLink: false, // true传统按钮样式 false链接样式cancelId: 0}).then(res => {console.log(res)const index = res.responseif(index == 0) {console.log('取消')}if(index == 1) {console.log('最小化托盘')for(let i in this.group) {let win = this.getWin(i)if(win) win.hide()}}else if(index == 2) {console.log('退出应用')try {for(let i in this.group) {let win = this.getWin(i)if(win) win.webContents.send('win__ipcData', { type: 'WIN_LOGOUT', value: null })}app.quit()} catch (error) {console.log(error)}}})}}])this.tray = new Tray(this.trayIco1)this.tray.setContextMenu(trayMenu)this.tray.setToolTip(app.name)this.tray.on('double-click', () => {console.log('double clicked')})
}
需要注意:这里图标路径很容易设置错误,显示不了图标。__dirname
指向你主进程文件目录路径。
比如你主进程文件在 src/multiwindow/index.js,则需要返回../../
找到resource目录。
// 根目录路径
process.env.ROOT = join(__dirname, '../../')
electron打包
一切准备就绪,项目也能正常启动运行。最后就需要配置打包。
新建一个electron-builder.json文件,用来作为electron打包配置文件。
{"productName": "Electron-ChatGPT","appId": "com.yxy.electron-chatgpt-vue3","copyright": "Copyright © 2023-present Andy","compression": "maximum","asar": true,"directories": {"output": "release/${version}"},"nsis": {"oneClick": false,"allowToChangeInstallationDirectory": true,"perMachine": true,"deleteAppDataOnUninstall": true,"createDesktopShortcut": true,"createStartMenuShortcut": true,"shortcutName": "ElectronChatGPT"},"win": {"icon": "./resource/shortcut.ico","artifactName": "${productName}-v${version}-${platform}-${arch}-setup.${ext}","target": [{"target": "nsis","arch": ["ia32"]}]},"mac": {"icon": "./resource/shortcut.icns","artifactName": "${productName}-v${version}-${platform}-${arch}-setup.${ext}"},"linux": {"icon": "./resource","artifactName": "${productName}-v${version}-${platform}-${arch}-setup.${ext}"}
}
以上就是electron25+vue3开发客户端仿chatgpt实例的一些分享,希望能喜欢~~
vue3+pinia2后台管理模板|vue3自定义轻量级后台系统
vue3+tauri跨桌面端聊天程序|tauri仿微信聊天应用