前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >electron25+vue3+pinia2跨端chatgpt聊天应用

electron25+vue3+pinia2跨端chatgpt聊天应用

原创
作者头像
andy2018
发布2023-06-11 09:13:11
9122
发布2023-06-11 09:13:11
举报
文章被收录于专栏:h5h5

最近一直学习electron25集成vite4.x技术开发跨端应用。就搭建了一个electron-chatgpt聊天EXE程序。

electron-vite4 for chatgpt 基于最新前端技术栈vite4+vue3+pinia2+vue-router+electron25跨端技术开发桌面端仿chatgpt聊天应用程序。支持经典+分栏两种布局、暗黑+明亮主题模式、多窗口封装管理等功能。

使用技术

  • 编码工具:vscode
  • 框架技术:electron25+vite4+vue3+pinia2
  • 组件库:veplus (基于vue3自定义组件库)
  • 打包工具:electron-builder^23.6.0
  • 调试工具:electron-devtools-installer^3.2.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跨端技术配合vite4.x全家桶技术,采用vue3 setup语法编码开发。

electron+vite快速搭建应用

  • 创建vite项目
代码语言:javascript
复制
yarn create vite electron-vite4-vue3
cd electron-vite4-vue3
yarn install
yarn dev
  • 安装electron依赖包
代码语言:javascript
复制
# 安装electron
yarn add -D electron
# 安装electron-builder 用于打包可安装exe程序和绿色版免安装exe程序
yarn add -D electron-builder
# 安装electron-devtools-installer 用于开发调试electron
yarn add -D electron-devtools-installer
# electron的vite插件
yarn add -D vite-plugin-electron
  • 新建background.js主进程文件
代码语言:javascript
复制
const { app, BrowserWindow } = require('electron')
const { join } = require('path')

// 屏蔽安全警告
// ectron Security Warning (Insecure Content-Security-Policy)
process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true'

const createWindow = () => {
    const win = new BrowserWindow({
        // 窗口图标
        icon: join(__dirname, 'resource/shortcut.ico'),
        width: 800,
        height: 600,
        webPreferences: {
            // contextIsolation: false,
            // nodeIntegration: true,
            // preload: path.join(__dirname, 'preload.js')
        }
    })
    // 加载vue url视本地环境而定,如http://localhost:5173
    // win.loadURL('http://localhost:3000')

    // development模式
    if(process.env.VITE_DEV_SERVER_URL) {
        win.loadURL(process.env.VITE_DEV_SERVER_URL)
        // 开启调试台
        win.webContents.openDevTools()
    }else {
        win.loadFile(join(__dirname, 'dist/index.html'))
    }
}

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配置主进程入口
代码语言:javascript
复制
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import electron from 'vite-plugin-electron'

// https://vitejs.dev/config/
export default defineConfig({
    plugins: [
        vue(),
        electron({
            // 主进程入口文件
            entry: 'background.js'
        })
    ],
    /*开发服务器选项*/
    server: {
        // 端口
        port: 3000,
    }
})
  • package.json中配置main入口
代码语言:javascript
复制
{
  "name": "electron-vite4-vue3",
  "private": true,
  "version": "0.0.0",
  "description": "基于Electron24+Vite4.x+Vue3搭建项目框架",
  "author": "andy <282310962@qq.com>",
  "copyright": "MIT License(MIT) ©2023 Andy",
  "main": "background.js",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview",
    "electron:serve": "vite --host",
    "electron:build": "vite build && electron-builder"
  },
  "dependencies": {
    "vue": "^3.2.47"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^4.1.0",
    "electron": "^24.4.0",
    "electron-builder": "^23.6.0",
    "electron-devtools-installer": "^3.2.0",
    "vite": "^4.3.2",
    "vite-plugin-electron": "^0.11.2"
  }
}

electron-chatgpt布局结构

代码语言:javascript
复制
<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无边框窗口

项目中顶部导航栏采用自定义布局,设置frame: false创建无边框窗口。

新建titlebar目录,用于封装多窗口及调用函数。

代码语言:javascript
复制
<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>
    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中引入control.vue文件。

代码语言:javascript
复制
<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-builder打包配置

在根目录新建一个electron-builder.json打包配置文件。

代码语言:javascript
复制
{
    "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": "ElectronVite4Vue3"
    },
    "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实例就先分享到这里,希望对大家有所帮助。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 使用技术
  • 项目结构图
  • electron+vite快速搭建应用
  • electron-chatgpt布局结构
  • electron无边框窗口
  • electron-builder打包配置
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档