经过半个多月潜心研发,新版跨平台聊天新作Electron38-Chat客户端聊天软件正式完结啦~

未标题-8.png

electron38-vitechat基于最新跨平台框架Electron38整合Vite7.0搭建项目模板。

p1.gif

使用技术

  • 开发工具:VScode
  • 前端框架:vite7.1.2+vue3.5.18+vue-router4.5.1
  • 跨平台技术:electron38.0.0
  • 组件库:element-plus^2.11.2
  • 状态插件:pinia^3.0.3
  • 存储插件:pinia-plugin-persistedstate^4.5.0
  • 打包构建:electron-builder^24.13.3
  • electron整合vite插件:vite-plugin-electron^0.29.0

p2.gif

p4.gif

项目框架结构

electron-wechat使用最新electron38.0高性能框架,结合vite7.x构建工具,整个项目均是采用vue3 setup语法编码开发。

360截图20250911234347782.png

001360截图20250911221130445.png

360截图20250911235225581.png

360截图20250911235310309.png

360截图20250911235524326.png

360截图20250911235637658.png

360截图20250911235839919.png

项目入口文件main.js

import { createApp } from 'vue'
import './style.scss'
import App from './App.vue'

// 引入组件库
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import VEPlus from 've-plus'
import 've-plus/dist/ve-plus.css'

// 引入路由/状态管理
import Router from './router'
import Pinia from './pinia'

import { launchApp } from '@/windows/actions'

launchApp().then(config => {
  if(config) {
    // 全局存储窗口配置
    window.config = config
  }

  // 创建app应用实例
  createApp(App)
  .use(ElementPlus)
  .use(VEPlus)
  .use(Router)
  .use(Pinia)
  .mount('#app')
})

页面布局结构

360截图20250911233614102.png

如上图:项目整体分为左侧菜单栏+侧边栏+右侧主体区域三个大模块。

7a38d1a01768cfa947aa85f425926a64_1289798-20250913073839199-108741287.png

<template>
  <template v-if="!route?.meta?.isNewWin">
    <div
      class="vu__container flexbox flex-alignc flex-justifyc"
      :style="{'--themeSkin': appstate.config.skin}"
    >
      <div class="vu__layout flexbox flex-col">
        <div class="vu__layout-body flex1 flexbox" @contextmenu.prevent>
          <!-- 菜单栏 -->
          <slot v-if="!route?.meta?.hideMenuBar" name="menubar">
            <MenuBar />
          </slot>

          <!-- 侧边栏 -->
          <div v-if="route?.meta?.showSideBar" class="vu__layout-sidebar flexbox">
            <aside class="vu__layout-sidebar__body flexbox flex-col">
              <slot name="sidebar">
                <SideBar />
              </slot>
            </aside>
          </div>

          <!-- 主内容区 -->
          <div class="vu__layout-main flex1 flexbox flex-col">
            <ToolBar v-if="!route?.meta?.hideToolBar" />
            <router-view v-slot="{ Component, route }">
              <keep-alive>
                <component :is="Component" :key="route.path" />
              </keep-alive>
            </router-view>
          </div>
        </div>
      </div>
    </div>
  </template>
  <template v-else>
    <WinLayout />
  </template>
</template>

360截图20250912000314089.png

360截图20250912000735188.png

003360截图20250911222132307.png

004360截图20250911222724876.png

004360截图20250911223155962.png

005360截图20250911223351208.png

005360截图20250911223428779.png

007360截图20250911223912025.png

008360截图20250911224537972.png

electron主线程|预加载配置

9e53ed11bf315826920c3c1a37274824_1289798-20250913074947075-1129199514.png

创建主窗口配置

/**
 * electron主进程配置
 * @author andy
 */

import { app, BrowserWindow } from 'electron'

import { WindowManager } from '../src/windows/index.js'

// 忽略安全警告提示 Electron Security Warning (Insecure Content-Security-Policy)
process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = true

const createWindow = () => {
  let win = new WindowManager()
  win.create({isMajor: true})
  // 系统托盘管理
  win.trayManager()
  // 监听ipcMain事件
  win.ipcManager()
}

app.whenReady().then(() => {
  createWindow()

  app.on('activate', () => {
    if(BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

app.on('window-all-closed', () => {
  if(process.platform !== 'darwin') app.quit()
})

preload.js预加载配置

import { contextBridge, ipcRenderer } from 'electron'

contextBridge.exposeInMainWorld(
  'electron',
  {
    // 通过 channel 向主进程发送异步消息。主进程使用 ipcMain.on() 监听 channel
    send: (channel, args) => {
      ipcRenderer.send(channel, args)
    },

    // 通过 channel 向主进程发送消息,并异步等待结果。主进程应该使用 ipcMain.handle() 监听 channel
    invoke: (channel, args) => {
      return new Promise(resolve => ipcRenderer.invoke(channel, args).then(data => resolve(data)).catch(e => console.log(e)))
    },

    // 监听 channel 事件
    on: (channel, func) => {
      console.log('receive event')
      ipcRenderer.on(channel, (event, ...args) => func(event, ...args))
    },

    // 一次性监听事件
    once: (channel, func) => {
      ipcRenderer.once(channel, (event, ...args) => func(event, ...args))
    },

    setTitle: (title) => ipcRenderer.send('win-setTitle', title)
  }
)

electron38+vue3自定义无边框拖拽窗口导航

image.png

整个项目采用无边框iframe:false模式,全新自定义导航栏。

b8d120de5aaa892caed299d7768734ba_1289798-20250913080042252-589917298.png

<script setup>
  import { ref } from 'vue'
  import { isTrue } from '@/utils'

  import { winSet } from '@/windows/actions'

  import Winbtns from './btns.vue'

  const props = defineProps({
    // 标题
    title: {type: String, default: ''},
    // 标题颜色
    color: String,
    // 背景色
    background: String,
    // 标题是否居中
    center: {type: [Boolean, String], default: false},
    // 是否固定
    fixed: {type: [Boolean, String], default: false},
    // 背景是否镂空
    transparent: {type: [Boolean, String], default: false},
    // 层级
    zIndex: {type: [Number, String], default: 2024},

    /* 控制Winbtn参数 */
    // 窗口是否可最小化
    minimizable: {type: [Boolean, String], default: true},
    // 窗口是否可最大化
    maximizable: {type: [Boolean, String], default: true},
    // 窗口是否可关闭
    closable: {type: [Boolean, String], default: true},
  })
</script>

<template>
  <div class="ev__winbar" :class="{'fixed': fixed || transparent, 'transparent': transparent}">
    <div class="ev__winbar-wrap flexbox flex-alignc vu__drag">
      <div class="ev__winbar-body flex1 flexbox flex-alignc">
        <!-- 左侧区域 -->
        <div class="ev__winbar-left"><slot name="left" /></div>
        <!-- 标题 -->
        <div class="ev__winbar-title" :class="{'center': center}">
          <slot name="title">{{title}}</slot>
        </div>
        <!-- 右侧附加区域 -->
        <div class="ev__winbar-extra vu__undrag"><slot name="extra" /></div>
      </div>
      <Winbtns :color="color" :minimizable="minimizable" :maximizable="maximizable" :closable="closable" :zIndex="zIndex" />
    </div>
  </div>
</template>

009360截图20250911224908419.png

009360截图20250911225000821.png

009360截图20250911225137532.png

009360截图20250911225347917.png

009360截图20250911225523570.png

009360截图20250911225616898.png

011360截图20250911231535128.png

012360截图20250911231643010.png

013360截图20250911231727280.png

016360截图20250911231959561.png

018360截图20250911232633429.png

020360截图20250911232955112.png

electron38自定义系统托盘闪烁|仿QQ消息提醒

项目托盘管理采用自定义electron窗口实现托盘消息提醒。

p6.gif

020360截图20250911233105068.png

/** 
 * 系统托盘图标管理
 */
trayManager() {
  if(this.tray) return
  const trayMenu = Menu.buildFromTemplate([
    {
      label: '打开主界面',
      icon: join(__root, 'resources/tray-win.png'),
      click: () => {
        this.winMain.restore()
        this.winMain.show()
      }
    },
    {
      label: '设置',
      icon: join(__root, 'resources/tray-setting.png'),
      click: () => this.sendByMainWin('win-ipcdata', {type: 'WINIPC_SETTINGWIN', value: null})
    },
    {
      label: '锁定系统',
      click: () => null,
    },
    {
      label: '关闭托盘闪烁',
      click: () => this.trayFlash(false)
    },
    {
      label: '关于',
      click: () => this.sendByMainWin('win-ipcdata', {type: 'WINIPC_ABOUTWIN', value: null})
    },
    {
      label: '退出聊天室',
      icon: join(__root, 'resources/tray-exit.png'),
      click: () => {
        dialog.showMessageBox(this.winMain, {
          title: '提示',
          message: '确定要退出聊天程序吗?',
          buttons: ['取消', '最小化托盘', '确认退出'],
          type: 'error',
          noLink: false,
          cancelId: 0,
        }).then(res => {
          // console.log(res)
          const index = res.response
          if(index == 0) {
            console.log('用户取消操作')
          }else if(index == 1) {
            console.log('最小化到托盘')
            this.winMain.hide()
          }else if(index == 2) {
            console.log('退出程序')
            this.sendByMainWin('win-ipcdata', {type: 'WINIPC_LOGOUT', value: null})
            app.quit()
          }
        })
      }
    }
  ])
  this.tray = new Tray(this.trayIcon)
  this.tray.setContextMenu(trayMenu)
  this.tray.setToolTip(app.name)
  this.tray.on('double-click', () => {
    console.log('tray double clicked!')
    this.winMain.restore()
    this.winMain.show()
  })
  this.tray.on('mouse-enter', (event, position) => {
    // console.log('鼠标划入', position)
    if(!this.hasFlash) return
    this.sendByMainWin('win-ipcdata', {type: 'WINIPC_MESSAGEWIN', value: position})
    // 简略消息通知
    /* this.tray.displayBalloon({
      iconType: 'none',
      title: 'Electron38研发组',
      content: 'Electron38+Vite7仿微信客户端聊天。'
    }) */
  })
  this.tray.on('mouse-leave', (event, position) => {
    // console.log('鼠标离开')
  })
}

020360截图20250911232955117.png

this.tray.on('mouse-enter', (event, position) => {
  // console.log('鼠标划入', position)
  if(!this.hasFlash) return
  this.sendByMainWin('win-ipcdata', {type: 'WINIPC_MESSAGEWIN', value: position})
  // 简略消息通知
  /* this.tray.displayBalloon({
    iconType: 'none',
    title: 'Electron38研发组',
    content: 'Electron38+Vite7仿微信客户端聊天。'
  }) */
})

创建托盘消息窗口

export function messageWindow(position) {
  winCreate({
    url: '/win/msgbox',
    title: '设置',
    width: 250,
    height: 120,
    resizable: false,
    movable: false,
    fullscreenable: false,
    alwaysOnTop: true,
    skipTaskbar: true,
    x: position?.x - 125,
    y: position?.y - 120 - 10,
    show: true,
  })
}

综上就是electron38+vue3 setup实战客户端聊天系统的一些分享,希望对大家有所帮助!

基于uniapp+vue3+uvue短视频+聊天+直播app系统

基于uniapp+vue3+deepseek+markdown搭建app版流式输出AI模板

vue3.5+deepseek+arco+markdown搭建web版流式输出AI模板

Vue3-Electron32-OS桌面os实例|electron32+vite5+arco实战os桌面

原创electron31+vite5.x+elementPlus桌面端后台管理系统

自研tauri2.0+vite5+vue3+element-plus电脑版exe聊天系统Vue3-Tauri2Chat

unios-admin手机版后台|uniapp+vue3全端admin管理系统

基于flutter3.32+window_manager仿macOS/Wins风格桌面os系统

flutter3.27+bitsdojo_window电脑端仿微信Exe应用

自研tauri2.0+vite6.x+vue3+rust+arco-design桌面版os管理系统Tauri2-ViteOS

基于uni-app+vue3+uvui跨三端仿微信app聊天模板

Flutter3.x深度融合短视频+直播+聊天app实例

a8a5dc63jw1falkc05snfg206q046gli.gif

本站提供的所有下载资源均来自互联网,仅提供学习交流使用,版权归原作者所有。如需商业使用,请联系原作者获得授权。 如您发现有涉嫌侵权的内容,请联系我们 邮箱:[email protected]