React19+Electron聊天室|electron41跨平台仿QQ/微信客户端聊天软件

原创实战electron41+react19+arco电脑端聊天系统ElectronReactChat

electron41-react-wechat基于vite8+react19+electron41.1+zustand+arco-design纯手搓仿微信/QQ界面桌面聊天客户端Exe。封装electron/react多窗口,包含聊天、通讯录、收藏、朋友圈、视频、我的等模块。

未标题-3

技术栈

  • 编辑器:Vscode
  • 跨平台框架:Electron41.1.0
  • 前端框架:react^19.2.8+react-router-dom^7.18.2
  • 组件库:@arco-design/web-react^2.66.16
  • 状态管理:zustand^5.0.14
  • 打包管理:electron-builder^26.15.3
  • 前端构建工具:vite^8.2.0
  • 样式处理:sass^1.102.0
  • electron结合react插件:vite-plugin-electron^1.1.1

p2

p3

项目结构目录

react-electron-chat电脑版聊天项目,使用最新跨平台框架 Electron41 整合 React19 搭建项目模板。

360截图20260814230626520

Electron41-ReactChat聊天系统已经发布到我的原创作品集,欢迎下载使用。

原创electron41+react19+arcoDesign客户端聊天Exe

p4

electron结合react搭建跨平台项目

image

image

p1

electron-react-wechat实现类似QQ/微信登录/主窗口切换,支持窗体换肤、自定义最大化/最小化/关闭按钮,新窗口打开朋友圈/短视频。聊天模块支持新开窗口预览视频、拖拽图片到聊天区域。

360截图20260814231223045

项目通用布局

360截图20260814230626523

项目整体布局结构如上图所示。

image

<div className='ra__container flex-c'>
  <div className='ra__layout flexbox flex-col'>
    <div className='ra__layout-body flex1 flexbox'>
      {/* 菜单栏 */}
      <Menubar />

      {/* 侧边栏 */}
      <Sidebar />
      
      {/* 主内容区 */}
      <div className='ra__layout-main flex1 flexbox flex-col'>
        <Toolbar />
        { Lazyload(<Outlet />) }
      </div>
    </div>
  </div>
</div>

p6

001360截图20260815002223109

360截图20260814231324782

360截图20260814231711398

360截图20260814232312430

360截图20260814232903568

360截图20260814233912243

002360截图20260815002613273

003360截图20260815003139958

003360截图20260815003235706

003360截图20260815003336410

004360截图20260815003458278

004360截图20260815003645188

005360截图20260815003743635

005360截图20260815004006135

005360截图20260815004148906

image

image

006360截图20260815004348692

007360截图20260815004537970

007360截图20260815004735861

360截图20260815000041498

008360截图20260815094608269

008360截图20260815094850662

008360截图20260815094913551

008360截图20260815095123519

008360截图20260815095910693

008360截图20260815100349569

008360截图20260815100501589

008360截图20260815100649220

008360截图20260815100939035

009360截图20260815101030806

009360截图20260815101654767

electron主进程/预加载配置

image

/**
 * 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()
})
/**
 * electron预加载文件
 * @author andy
 */

const { contextBridge, ipcRenderer } = require('electron')
// MaxListenersExceededWarning: Possible EventEmitter memory leak detected.
ipcRenderer.setMaxListeners(0)

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))
    },

    // 浏览器打开链接
    openExternal: (url) => ipcRenderer.send('open-external', url)
  }
)

electron+react自定义无边框拖拽窗体/导航条

image

image

image

image

image

image

自定义无边框iframe:false窗口拖拽导航条。

image

function Winbtns(props) {
  const {
    color,
    // 窗口是否可以最小化
    minimizable = true,
    // 窗口是否可以最大化
    maximizable = true,
    // 窗口是否可关闭
    closable = true,
    // 设置层叠
    zIndex = 2026,
    style,
    ...rest
  } = props

  const appState = appStore()

  const [hasMaximized, setHasMaximized] = useState(false)
  const [isResizable, setIsResizable] = useState(true)
  const [isMaximizable, setIsMaximizable] = useState(true)

  useEffect(() => {
    // 用户是否可以手动调整窗口大小
    window.electron.invoke('win-isResizable').then(res => {
      setIsResizable(res)
    })

    // 窗口是否可以最大化
    window.electron.invoke('win-isMaximizable').then(res => {
      setIsMaximizable(res)
    })

    // 初始窗口是否最大化
    window.electron.invoke('win-isMaximized').then(res => {
      setHasMaximized(res)
    })

    // 实时监听窗口是否最大化
    window.electron.on('win-maximized', (e, data) => {
      setHasMaximized(data)
    })
  }, [])

  // 最小化
  const handleWinMin = () => {
    window.electron.invoke('win-min')
  }
  // 最大化/还原
  const handleWinMax2Min = () => {
    window.electron.invoke('win-toggle').then(res => {
      setHasMaximized(res)
    })
  }
  // 关闭
  const handleWinClose = () => {
    if(window.config.isMajor) {
      const modal = Modal.confirm({
        icon: null,
        content: <div style={{fontSize: 15}}>是否最小化到托盘,不退出程序?</div>,
        focusLock: false,
        style: {width: 275, borderRadius: 12, padding: '10px 25px 20px'},
        footer: <div style={{textAlign: 'right'}}>
          <Button type='text' shape='round' size='small' onClick={() => {
            modal.close()
            setTimeout(() => {
              winSet('hide', window.config.id)
            }, 150)
          }}>最小化至托盘</Button>
          <Button type='text' status='danger' shape='round' size='small' onClick={() => {
            appState.logout()
            winSet('close')
          }}>退出</Button>
        </div>
      })
    } else {
      winSet('close', window.config.id)
    }
  }

  return (
    <>
      <div {...rest} className="ra__winbtns flexbox flex-alignc" style={{ zIndex: zIndex, ...style }}>
        <div className="ra__winbtns-actions flexbox flex-alignc" style={{ color: color }}>
          {isTrue(minimizable) && <a className="min" title="最小化" onClick={handleWinMin}><i className="elec-icon elec-icon-min"></i></a>}
          {(isTrue(maximizable) && isResizable && isMaximizable) &&
            <a className="max" title={hasMaximized ? '向下还原' : '最大化'} onClick={handleWinMax2Min}>
              {hasMaximized ? <i className="wicon elec-icon elec-icon-restore"></i> : <i className="elec-icon elec-icon-max"></i>}
            </a>
          }
          {isTrue(closable) && <a className="close" title="关闭" onClick={handleWinClose}><i className="elec-icon elec-icon-quit"></i></a>}
        </div>
      </div>
    </>
  )
}

electron+react封装多开窗口

未标题-1

支持同时打开多个窗口,调用封装函数即可快速创建一个新窗口。

/**
 * 创建新窗口
 * @param {object} args 窗口配置参数 {url: '/about', width: 500, height: 300, ...}
 */
export function winCreate(args) {
  window.electron.send('win-create', args)
}
// 登录窗口
export function loginWindow() {
  winCreate({
    url: '/login',
    title: '登录',
    width: 320,
    height: 380,
    isMajor: true,
    resizable: false,
    maximizable: false,
    alwaysOnTop: true
  })
}

// 关于窗口
export function aboutWindow() {
  winCreate({
    url: '/win/about',
    title: '关于',
    width: 375,
    height: 300,
    minWidth: 375,
    minHeight: 300,
    maximizable: false,
    alwaysOnTop: true,
  })
}

// 设置窗口
export function settingWindow() {
  winCreate({
    url: '/win/setting',
    title: '设置',
    width: 550,
    height: 470,
    resizable: false,
    maximizable: false,
  })
}

窗口支持如下参数配置

// 自定义窗口参数
const windowOptions = {
  // 窗口唯一标识id
  id: null,
  // 窗口标题
  title: 'Electron-ViteChat',
  // 窗口路由地址
  url: '',
  // 窗口数据传参
  data: null,
  // 是否是主窗口(为true则会关闭所有窗口并创建一个新窗口)
  isMajor: false,
  // 是否支持多开窗口(为true则支持创建多个窗口)
  isMultiple: false,
  // 窗口是否最大化
  maximize: false,
}

// 系统窗口参数(与electron的new BrowserWindow()参数一致)
const windowBaseOptions = {
  // 窗口图标
  icon: join(__root, 'resources/shortcut.ico'),
  // 是否自动隐藏菜单栏(按下Alt键显示)
  autoHideMenuBar: true,
  // 窗口标题栏样式
  titleBarStyle: 'hidden',
  // 窗口背景色
  backgroundColor: '#fff',
  // 宽度
  width: 840,
  // 高度
  height: 610,
  // 最小宽度
  minWidth: '',
  // 最小高度
  minHeight: '',
  // 窗口x坐标
  x: '',
  // 窗口y坐标
  y: '',
  // 是否可缩放
  resizable: true,
  // 是否可最小化
  minimizable: true,
  // 是否可最大化
  maximizable: true,
  // 是否可关闭
  closable: true,
  // 父窗口
  parent: null,
  // 是否模态窗口
  modal: false,
  // 窗口是否置顶
  alwaysOnTop: false,
  // 是否显示窗口边框(要创建无边框窗口,将frame参数设置为false)
  frame: false,
  // 是否透明窗口(仅frame: false有效)
  transparent: false,
  // 创建时是否显示窗口
  show: false,
}

electron自定义托盘消息/闪烁

p7

/** 
 * 系统托盘图标
 */
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('鼠标离开')
  })
}

开启/关闭托盘闪烁

// 开启/关闭托盘闪烁
trayFlash(bool) {
  let flag = false
  if(bool) {
    if(this.trayTimer) return
    this.trayTimer = setInterval(() => {
      this.tray.setImage(flag ? this.trayIcon : this.trayEmpty)
      flag = !flag
    }, 500)
  }else {
    if(this.trayTimer) {
      clearInterval(this.trayTimer)
      this.trayTimer = null
    }
    this.tray.setImage(this.trayIcon)
  }
}

011360截图20260815102032020

011360截图20260815102417293

Okay,以上就是Electron41+React19实战桌面端聊天系统的一些项目分享,希望对大家有点帮助!

附上一些最新实战进阶项目

react19-webai网页版AI模板|DeepSeek-V4+React19+Arco智能ai系统

React19-Admin后台管理系统|vite8+react19+arco+zustand通用后台模板

Vite8-Vue3-Admin网页版后台模板|vue3.5+pinia3+echarts后台管理系统

vite8-webos网页版os管理|Vue3+Vite8.0+ArcoDesign搭建pc端os桌面系统

Electron38-Vue3OS客户端OS系统|vite7+electron38+arco桌面os后台管理

Electron38-Wechat电脑端聊天|vite7+electron38仿微信桌面端聊天系统

electron38-admin桌面端后台|Electron38+Vue3+ElementPlus管理系统

最新版Flutter3.41+Dart3.11仿写抖音APP直播+短视频+聊天应用程序

Tauri2.8+Vue3聊天系统|vite7+tauri2+element-plus客户端仿微信聊天程序

Tauri2.9+Vue3桌面版OS系统|vite7+tauri2+arcoDesign电脑端os后台模板

Tauri2-Vite7Admin客户端管理后台|tauri2.9+vue3+element-plus后台系统

Vite8+DeepSeek-V4网页版AI助手|vue3+arco本地web版ai流式问答系统

s13.sinaimg

 

posted @ 2026-08-16 01:06  xiaoyan2017  阅读(7)  评论(0)    收藏  举报
友情链接: UP主小店B站