electron-qchat: 基于vue3+electron模拟QQ界面聊天程序
发布于 2 个月前 作者 xiaoyan2015 275 次浏览 来自 分享
粉丝福利 : 关注VUE中文社区公众号,回复视频领取粉丝福利

Electron有着出色的跨平台能力,让人轻松的利用Vue.js也能开发出exe软件应用。随着electron不断迭代更新、vue3.0的逐步完善,二者结合开发出一些有创意的桌面端应用程序也受到了众多程序员的追捧。

基于Electron跨端构建的Vue3模仿QQ界面聊天应用,使用了electron11.2+vue3.0+antdv+v3layer等技术开发。 https://segmentfault.com/a/1190000039296059

360截图20210301085101659.png

ElectronQchat 支持新打开多个窗口/父子窗口及换肤等功能。

img

electron模仿QQ登录界面。

img

运用技术

  • vue3全家桶:vue3.0+vuex4+vue-router@4
  • 跨端框架:electron11.2.3
  • 打包工具:vue-cli-plugin-electron-builder
  • UI组件库:ant-design-vue (蚂蚁金服vue3组件库)
  • 弹窗组件:v3layer (vue3桌面端弹窗组件)
  • 滚动条组件:v3scroll (vue3自定义美化滚动条)
  • 字体图标:阿里iconfont图标

项目目录结构

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

electron构建多窗体|父子窗口

项目支持新开多窗口,通过封装公共方法,传入参数快速创建新窗体。

// 换肤窗口
const handleSkinWin = () => {
    createWin({
        title: '换肤',
        route: '/skin',
        width: 720,
        height: 475,
        resize: false,
    })
}

// 朋友圈窗口
const handleFZoneWin = () => {
    createWin({
        title: '朋友圈',
        route: '/fzone',
        width: 550,
        height: 700,
        resize: false,
    })
}

之前有过一篇相关分享文章,大家如果感兴趣可以去看一看哈~ electron+vue3构建多窗体|父子modal窗口模式

electron构建无边框|自定义导航栏菜单

大家可以看到,项目中顶部导航条是自定义组件实现的。 img 使用css3设置 -webkit-app-region: drag 可自定义控制可拖拽区域。不过会出现如下图的一个问题。 img 经过多次调试发现,在创建窗体的时候可以给屏蔽掉。

win.hookWindowMessage(278, () => {
    win.setEnabled(false)
    setTimeout(() => {
        win.setEnabled(true)
    }, 100)

    return true
})

大家如果对vue3/electron实现自定义导航条菜单|右上角最大、小化、关闭按钮感兴趣,可以去看看下面这篇分享。 基于vue3+electron11实现无边框自定义顶部导航菜单栏

electron创建系统托盘/闪烁

electron实现类似QQ系统托盘图标及闪烁效果。 img

/**
 * @Desc     electron创建系统托盘图标
 * @Time     andy by 2021-02  Q:282310962  wx:xy190310
 */

let tray = null
let flashTimer = null
let trayIco1 = path.join(__dirname, '../static/tray.ico')
let trayIco2 = path.join(__dirname, '../static/tray-empty.ico')

createTray() {
    const trayMenu = Menu.buildFromTemplate([
        {
            label: '我在线上', icon: path.join(__dirname, '../static/icon-online.png'),
            click: () => {...}
        },
        {
            label: '忙碌', icon: path.join(__dirname, '../static/icon-busy.png'),
            click: () => {...}
        },
        {
            label: '隐身', icon: path.join(__dirname, '../static/icon-invisible.png'),
            click: () => {...}
        },
        {
            label: '离开', icon: path.join(__dirname, '../static/icon-offline.png'),
            click: () => {...}
        },
        {type: 'separator'},
        {
            label: '关闭所有声音', click: () => {...},
        },
        {
            label: '关闭头像闪动', click: () => {
                this.flashTray(false)
            }
        },
        {type: 'separator'},
        {
            label: '打开主窗口', click: () => {
                try {
                    for(let i in this.winLs) {
                        let win = this.getWin(i)
                        if(!win) return
                        if(win.isMinimized()) win.restore()
                        win.show()
                    }
                } catch (error) {
                    console.log(error)
                }
            }
        },
        {
            label: '退出', click: () => {
                try {
                    for(let i in this.winLs) {
                        let win = this.getWin(i)
                        if(win) win.webContents.send('win-logout')
                    }
                    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', () => {
        // ...
    })
}
// 托盘图标闪烁
flashTray(flash) {
    let hasIco = false

    if(flash) {
        if(this.flashTimer) return
        this.flashTimer = setInterval(() => {
            this.tray.setImage(hasIco ? this.trayIco1 : this.trayIco2)
            hasIco = !hasIco
        }, 500)
    }else {
        if(this.flashTimer) {
            clearInterval(this.flashTimer)
            this.flashTimer = null
        }
        this.tray.setImage(this.trayIco1)
    }
}
// 销毁托盘图标
destoryTray() {
    this.flashTray(false)
    this.tray.destroy()
    this.tray = null
}

非常简单就能实现托盘闪烁,调用 flashTray(true|false) 可开启/关闭闪烁。

electron+vue3项目配置|打包配置

构建项目的时候,根目录会有一个vue.config.js配置文件。里面可以进行一些项目配置和electron-builder打包配置项。

/**
 *  vue3/electron项目打包配置
 */

const path = require('path')

module.exports = {
    ...
    
    pluginOptions: {
        electronBuilder: {
            // 配置后可以在渲染进程使用ipcRenderer
            nodeIntegration: true,

            // 项目打包参数配置
            builderOptions: {
                "productName": "electron-qchat", //项目名称 打包生成exe的前缀名
                "appId": "com.example.electronqchat", //包名
                "compression": "maximum", //store|normal|maximum 打包压缩情况(store速度较快)
                "artifactName": "${productName}-${version}-${platform}-${arch}.${ext}",
                // "directories": {
                //     "output": "build", //输出文件夹(默认dist_electron)
                // },
                "asar": false, //asar打包
                "extraResources": [
                    {
                        "from": "./static",
                        "to": "static"
                    },
                ],
                "nsis": {
                    "oneClick": false, //一键安装
                    "allowToChangeInstallationDirectory": true, //允许修改安装目录
                    "perMachine": true, //是否开启安装时权限设置(此电脑或当前用户)
                    "deleteAppDataOnUninstall": true, //卸载时删除数据
                    "createDesktopShortcut": true, //创建桌面图标
                    "createStartMenuShortcut": true, //创建开始菜单图标
                    "shortcutName": "ElectronQChat", //桌面快捷键图标名称
                },
                "win": {
                    "icon": "./static/shortcut.ico", //图标路径
                }
            }
        }
    }
}

End,以上就是vue3.0+electron11开发仿制QQ客户端聊天应用的分享,希望大家喜欢! img 链接:https://my.oschina.net/xiaoyan2016/blog/4965600 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

回到顶部