当前位置: 首页 > news >正文

Electron-Wechat电脑端聊天|vite+electron仿微信桌面端聊天系统

Electron-Wechat电脑端聊天 | Vite+Electron仿微信桌面端聊天系统

引言在当今社交网络时代,微信已成为人们日常沟通的重要工具。然而,微信官方桌面端在某些场景下存在功能受限或体验不佳的问题。作为全栈工程师,我们可以利用 Electron 和 Vite 构建一个功能完善的仿微信桌面端聊天系统。本文将带你从零开始,使用 Vite 作为构建工具,Electron 作为桌面应用框架,实现一个具备消息收发、联系人管理、界面仿微信的聊天系统。## 技术栈概览-Electron:跨平台桌面应用框架,基于 Chromium 和 Node.js-Vite:下一代前端构建工具,提供极速开发体验-Vue 3:响应式前端框架-Socket.IO:实时通信库,用于 WebSocket 消息传递-Node.js:后端服务与 Electron 主进程## 项目初始化与配置首先,我们创建一个基于 Vite 的 Vue 3 项目,并集成 Electron。bash# 创建 Vite 项目npm create vite@latest electron-wechat -- --template vuecd electron-wechat# 安装 Electron 相关依赖npm install electron electron-builder --save-dev# 安装 Socket.IO 客户端npm install socket.io-client# 安装其他依赖npm install vue-router@4 pinia## 主进程与渲染进程通信Electron 应用分为主进程(main process)和渲染进程(renderer process)。主进程负责窗口管理、系统交互,渲染进程负责 UI 展示。我们需要建立两者之间的通信桥梁。### 主进程代码:electron/main.jsjavascript// electron/main.jsconst { app, BrowserWindow, ipcMain } = require('electron');const path = require('path');// 创建主窗口function createWindow() { const win = new BrowserWindow({ width: 1200, height: 800, webPreferences: { preload: path.join(__dirname, 'preload.js'), // 预加载脚本 contextIsolation: true, // 隔离渲染进程 nodeIntegration: false, // 禁用 Node.js 集成 }, }); // 开发环境加载 Vite 开发服务器 if (process.env.VITE_DEV_SERVER_URL) { win.loadURL(process.env.VITE_DEV_SERVER_URL); } else { // 生产环境加载打包后的文件 win.loadFile(path.join(__dirname, '../dist/index.html')); }}// 监听主进程与渲染进程通信ipcMain.on('send-message', (event, message) => { console.log('收到渲染进程消息:', message); // 向渲染进程发送回复 event.sender.send('message-response', `服务器回复: ${message}`);});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/preload.jsjavascript// electron/preload.jsconst { contextBridge, ipcRenderer } = require('electron');// 暴露安全的 API 给渲染进程contextBridge.exposeInMainWorld('electronAPI', { // 发送消息到主进程 sendMessage: (message) => ipcRenderer.send('send-message', message), // 接收主进程消息 onMessageResponse: (callback) => { ipcRenderer.on('message-response', (event, data) => { callback(data); }); }, // 移除监听器 removeMessageListener: () => { ipcRenderer.removeAllListeners('message-response'); },});## 仿微信聊天界面实现接下来,我们构建一个仿微信的聊天界面,包含联系人列表和聊天窗口。### 聊天界面组件:ChatWindow.vuevue<!-- src/components/ChatWindow.vue --><template> <div class="chat-window"> <!-- 联系人列表 --> <div class="contact-list"> <div v-for="contact in contacts" :key="contact.id" class="contact-item" :class="{ active: activeContact?.id === contact.id }" @click="selectContact(contact)" > <img :src="contact.avatar" alt="头像" class="avatar" /> <div class="contact-info"> <div class="name">{{ contact.name }}</div> <div class="last-message">{{ contact.lastMessage }}</div> </div> </div> </div> <!-- 聊天区域 --> <div class="chat-area"> <div class="chat-header"> <h2>{{ activeContact?.name || '请选择联系人' }}</h2> </div> <div class="message-list" ref="messageList"> <div v-for="msg in messages" :key="msg.id" class="message" :class="{ self: msg.isSelf }" > <div class="message-content">{{ msg.content }}</div> <div class="message-time">{{ formatTime(msg.timestamp) }}</div> </div> </div> <div class="input-area"> <input v-model="newMessage" @keyup.enter="sendMessage" placeholder="输入消息..." class="message-input" /> <button @click="sendMessage" class="send-btn">发送</button> </div> </div> </div></template><script setup>import { ref, onMounted, nextTick } from 'vue';import { io } from 'socket.io-client';// 联系人数据const contacts = ref([ { id: 1, name: '张三', avatar: 'https://via.placeholder.com/50', lastMessage: '你好' }, { id: 2, name: '李四', avatar: 'https://via.placeholder.com/50', lastMessage: '在吗?' }, { id: 3, name: '王五', avatar: 'https://via.placeholder.com/50', lastMessage: '今天天气不错' },]);const activeContact = ref(null);const messages = ref([]);const newMessage = ref('');const messageList = ref(null);let socket = null;// 选择联系人function selectContact(contact) { activeContact.value = contact; messages.value = [ { id: 1, content: '你好,我是' + contact.name, isSelf: false, timestamp: Date.now() - 60000 }, { id: 2, content: '很高兴认识你', isSelf: true, timestamp: Date.now() - 30000 }, ];}// 发送消息function sendMessage() { if (!newMessage.value.trim() || !activeContact.value) return; const message = { id: Date.now(), content: newMessage.value, isSelf: true, timestamp: Date.now(), }; messages.value.push(message); // 通过 Socket.IO 发送消息 if (socket) { socket.emit('chat-message', { to: activeContact.value.id, content: newMessage.value, }); } // 通过 Electron IPC 发送到主进程 if (window.electronAPI) { window.electronAPI.sendMessage(newMessage.value); } newMessage.value = ''; scrollToBottom();}// 格式化时间function formatTime(timestamp) { const date = new Date(timestamp); return `${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`;}// 滚动到底部function scrollToBottom() { nextTick(() => { if (messageList.value) { messageList.value.scrollTop = messageList.value.scrollHeight; } });}onMounted(() => { // 连接 Socket.IO 服务器(假设后端运行在 localhost:3000) socket = io('http://localhost:3000'); socket.on('connect', () => { console.log('Socket.IO 连接成功'); }); socket.on('new-message', (data) => { if (data.from === activeContact.value?.id) { messages.value.push({ id: Date.now(), content: data.content, isSelf: false, timestamp: Date.now(), }); scrollToBottom(); } }); // 监听 Electron 主进程回复 if (window.electronAPI) { window.electronAPI.onMessageResponse((response) => { console.log('收到主进程回复:', response); }); }});</script><style scoped>.chat-window { display: flex; height: 100vh; background: #f5f5f5;}.contact-list { width: 300px; background: #fff; border-right: 1px solid #ddd; overflow-y: auto;}.contact-item { display: flex; align-items: center; padding: 15px; cursor: pointer; transition: background 0.2s;}.contact-item:hover { background: #e8f0fe;}.contact-item.active { background: #c8e6c9;}.avatar { width: 50px; height: 50px; border-radius: 50%; margin-right: 10px;}.contact-info { flex: 1;}.name { font-weight: bold; font-size: 16px;}.last-message { color: #999; font-size: 12px; margin-top: 5px;}.chat-area { flex: 1; display: flex; flex-direction: column;}.chat-header { padding: 15px; background: #fff; border-bottom: 1px solid #ddd;}.message-list { flex: 1; overflow-y: auto; padding: 15px;}.message { margin-bottom: 15px; display: flex; flex-direction: column;}.message.self { align-items: flex-end;}.message-content { background: #fff; padding: 10px 15px; border-radius: 10px; max-width: 60%; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);}.message.self .message-content { background: #95ec69;}.message-time { font-size: 10px; color: #999; margin-top: 5px;}.input-area { display: flex; padding: 15px; background: #fff; border-top: 1px solid #ddd;}.message-input { flex: 1; padding: 10px; border: 1px solid #ddd; border-radius: 5px; font-size: 14px;}.send-btn { margin-left: 10px; padding: 10px 20px; background: #07c160; color: #fff; border: none; border-radius: 5px; cursor: pointer; font-size: 14px;}.send-btn:hover { background: #06ad56;}</style>## 后端 Socket.IO 服务器为了实现实时消息通信,我们需要一个简单的后端服务器。### 服务器代码:server/index.jsjavascript// server/index.jsconst express = require('express');const http = require('http');const { Server } = require('socket.io');const app = express();const server = http.createServer(app);const io = new Server(server, { cors: { origin: '*', // 允许所有来源(生产环境需限制) },});// 存储在线用户const onlineUsers = new Map();io.on('connection', (socket) => { console.log('用户连接:', socket.id); // 用户登录 socket.on('user-login', (userId) => { onlineUsers.set(userId, socket.id); console.log(`用户 ${userId} 上线`); }); // 聊天消息 socket.on('chat-message', (data) => { const { to, content } = data; const targetSocketId = onlineUsers.get(to); if (targetSocketId) { io.to(targetSocketId).emit('new-message', { from: socket.id, content, }); } console.log(`消息从 ${socket.id} 发送到 ${to}: ${content}`); }); // 用户断开连接 socket.on('disconnect', () => { for (const [userId, socketId] of onlineUsers) { if (socketId === socket.id) { onlineUsers.delete(userId); console.log(`用户 ${userId} 下线`); break; } } });});server.listen(3000, () => { console.log('Socket.IO 服务器运行在 http://localhost:3000');});## 运行与构建### 开发模式bash# 启动后端服务器node server/index.js# 启动 Vite 开发服务器npm run dev# 启动 Electron(需在另一个终端)npx electron .### 生产构建bash# 构建 Vue 项目npm run build# 打包 Electron 应用npx electron-builder --win --mac --linux## 总结通过本文的实践,我们成功使用 Vite、Electron、Vue 3 和 Socket.IO 构建了一个仿微信桌面端聊天系统。核心要点包括:1.Vite 集成 Electron:利用 Vite 的快速构建能力,结合 Electron 的跨平台特性,实现高效开发。2.主进程与渲染进程通信:通过预加载脚本和 IPC 机制,安全地在主进程和渲染进程之间传递数据。3.实时消息系统:使用 Socket.IO 实现 WebSocket 双向通信,支持多用户在线聊天。4.仿微信 UI:界面设计借鉴微信的布局风格,包含联系人列表、聊天窗口和消息输入区域。这个系统可以作为企业内部通讯工具或学习项目的起点。未来可以扩展更多功能,如文件传输、表情包、群聊等。希望本文能为你的桌面应用开发提供实用的参考。

http://www.cnnetsun.cn/news/3669663.html

相关文章:

  • 3步搞定图片去重难题:AntiDupl智能解决方案完全指南
  • XUnity.AutoTranslator游戏实时翻译插件:从原理到实战优化指南
  • 大模型增强技术:原理、应用与优化策略
  • 为什么选择Laravel-Throttle?5大优势让你的应用更安全
  • 单光子探测技术在三维成像与反射率重建中的应用
  • 深入解析EDMA3:PaRAM配置与DMA/QDMA触发机制实战指南
  • 深入解析C++ STL三大基石:容器、迭代器与适配器设计原理与实践
  • 千笔AI工具:本科论文写作全流程智能解决方案
  • Cursor Composer 模式:多文件重构的工作流与边界
  • 云原生安全:从“城墙“到“零信任“
  • 终极开源媒体播放器:VLC for Android 完整使用指南
  • 深入解析TI DSP EMIF异步接口与NAND Flash驱动设计
  • 2025年主流AI Agent框架技术解析与应用指南
  • 如何优雅的使用RabbitMQ
  • YOLO11地铁客流监测系统:安全线识别与实时预警
  • AI助手豆包:提升工作效率的5个核心功能
  • 幻兽帕鲁存档修复终极指南:告别角色丢失,实现跨服务器无缝转移
  • SSA优化CNN-BiLSTM模型的时间序列预测方法
  • AM261x ADC外部通道选择与SOC配置:硬件自动化扩展采样通道
  • 3步完成QQ空间历史说说完整备份:你的数字记忆守护神器
  • 3个技巧彻底优化魔兽争霸体验:免费开源工具完全指南
  • Azure Linux:微软官方优化的AKS容器主机操作系统详解
  • 为什么92%的虚拟试衣项目在6个月内失败?资深架构师亲述12个被忽略的实时动捕+姿态迁移致命缺陷
  • torch.distributed的初始化方法选择:TCP、共享文件与环境变量的适用场景
  • 嵌入式网络处理器PDMA配置实战:UTOPIA接口数据传输优化与避坑指南
  • 基于嵌入向量的聊天记录主题聚类:原理、实践与优化
  • REFramework松散文件加载器性能优化:如何解决游戏帧率下降问题
  • Bielik.ai开源大语言模型:波兰语NLP实战部署与优化指南
  • 基于深度学习的IMDB电影评论情感分析完整实现
  • 英雄联盟自动化工具:League Akari 终极配置与实战指南