RuoYi-Vue3跨平台开发探索:Electron桌面应用改造实践

RuoYi-Vue3跨平台开发探索:Electron桌面应用改造实践

【免费下载链接】RuoYi-Vue3 :tada: (RuoYi)官方仓库 基于SpringBoot,Spring Security,JWT,Vue3 & Vite、Element Plus 的前后端分离权限管理系统 【免费下载链接】RuoYi-Vue3 项目地址: https://gitcode.com/GitHub_Trending/ruo/RuoYi-Vue3

引言:从Web到桌面的无缝迁移

你是否还在为企业级后台系统的跨平台部署而烦恼?是否希望将现有的Web应用快速转化为功能完备的桌面应用,同时保留原有的所有功能和用户体验?本文将带你深入探索如何将基于Vue3 & Vite、Element Plus构建的RuoYi-Vue3权限管理系统,通过Electron框架改造为跨平台桌面应用,解决Web版在特定场景下的局限性,提升企业内部系统的安全性和用户体验。

读完本文,你将获得:

  • 一套完整的RuoYi-Vue3桌面化改造方案
  • Electron与Vue3项目的整合技巧
  • 桌面应用的打包与分发策略
  • 常见问题的解决方案与性能优化建议

一、Electron改造前的技术栈分析

1.1 原项目技术栈概览

RuoYi-Vue3作为一款成熟的权限管理系统,其前端技术栈如下:

技术版本作用
Vue3.5.16核心前端框架
Vite6.3.5构建工具
Element Plus2.10.7UI组件库
Vue Router4.5.1路由管理
Pinia3.0.2状态管理
Axios1.9.0HTTP客户端

1.2 为什么选择Electron

Electron作为一个跨平台桌面应用开发框架,具有以下优势:

mermaid

二、Electron整合实战

2.1 环境准备与依赖安装

首先,我们需要为RuoYi-Vue3项目添加Electron相关依赖:

# 安装Electron核心依赖
npm install electron electron-builder --save-dev

2.2 项目结构调整

为了支持Electron,我们需要在原有项目结构基础上添加以下文件:

RuoYi-Vue3/
├── electron/
│   ├── main.js        # Electron主进程
│   └── preload.js     # 预加载脚本
├── package.json       # 添加Electron脚本和配置
└── vite.config.js     # 调整Vite配置以支持Electron

2.3 主进程实现

创建electron/main.js文件,作为Electron应用的入口点:

const { app, BrowserWindow, ipcMain, Menu } = require('electron');
const path = require('path');
const url = require('url');

// 关闭默认菜单
Menu.setApplicationMenu(null);

let mainWindow;

function createWindow() {
  // 创建浏览器窗口
  mainWindow = new BrowserWindow({
    width: 1200,
    height: 800,
    minWidth: 800,
    minHeight: 600,
    title: 'RuoYi-Vue3管理系统',
    icon: path.join(__dirname, '../src/assets/logo/logo.png'),
    webPreferences: {
      nodeIntegration: false,
      contextIsolation: true,
      enableRemoteModule: false,
      preload: path.join(__dirname, 'preload.js')
    }
  });

  // 加载应用
  const startUrl = process.env.NODE_ENV === 'development'
    ? 'http://localhost:8080'
    : url.format({
        pathname: path.join(__dirname, '../dist/index.html'),
        protocol: 'file:',
        slashes: true
      });

  mainWindow.loadURL(startUrl);

  // 开发环境下打开开发者工具
  if (process.env.NODE_ENV === 'development') {
    mainWindow.webContents.openDevTools();
  }

  // 窗口关闭事件
  mainWindow.on('closed', () => {
    mainWindow = null;
  });
}

// 应用就绪后创建窗口
app.whenReady().then(createWindow);

// 所有窗口关闭时退出应用
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit();
  }
});

// 激活应用时创建窗口(macOS)
app.on('activate', () => {
  if (mainWindow === null) {
    createWindow();
  }
});

// 主进程与渲染进程通信示例
ipcMain.on('window-minimize', () => {
  mainWindow.minimize();
});

ipcMain.on('window-maximize', () => {
  if (mainWindow.isMaximized()) {
    mainWindow.unmaximize();
  } else {
    mainWindow.maximize();
  }
});

ipcMain.on('window-close', () => {
  mainWindow.close();
});

2.4 预加载脚本实现

创建electron/preload.js文件,用于在渲染进程中安全地暴露Electron API:

const { contextBridge, ipcRenderer } = require('electron');

// 暴露安全的API给渲染进程
contextBridge.exposeInMainWorld('electronAPI', {
  minimizeWindow: () => ipcRenderer.send('window-minimize'),
  maximizeWindow: () => ipcRenderer.send('window-maximize'),
  closeWindow: () => ipcRenderer.send('window-close'),
  isElectron: true
});

2.5 调整package.json配置

修改package.json文件,添加Electron相关配置和脚本:

{
  "name": "ruoyi",
  "version": "3.9.0",
  "main": "electron/main.js",
  "scripts": {
    "dev": "vite",
    "build:prod": "vite build",
    "build:stage": "vite build --mode staging",
    "preview": "vite preview",
    "electron:dev": "NODE_ENV=development electron .",
    "electron:build": "npm run build:prod && electron-builder",
    "prepare": "husky"
  },
  "build": {
    "appId": "com.ruoyi.desktop",
    "productName": "RuoYi-Vue3管理系统",
    "copyright": "Copyright © 2025 若依",
    "directories": {
      "output": "electron_dist"
    },
    "files": [
      "dist/**/*",
      "electron/**/*"
    ],
    "win": {
      "icon": "src/assets/logo/logo.png",
      "target": [
        {
          "target": "nsis",
          "arch": [
            "x64"
          ]
        }
      ]
    },
    "mac": {
      "icon": "src/assets/logo/logo.png",
      "target": "dmg"
    },
    "linux": {
      "icon": "src/assets/logo/logo.png",
      "target": "deb"
    },
    "nsis": {
      "oneClick": false,
      "allowToChangeInstallationDirectory": true,
      "installerIcon": "src/assets/logo/logo.png",
      "uninstallerIcon": "src/assets/logo/logo.png",
      "installerHeaderIcon": "src/assets/logo/logo.png",
      "createDesktopShortcut": true,
      "createStartMenuShortcut": true
    }
  }
}

2.6 调整Vite配置

修改vite.config.js文件,确保在开发环境下Electron能正确加载应用:

import { defineConfig, loadEnv } from 'vite'
import path from 'path'
import createVitePlugins from './vite/plugins'

// https://vitejs.dev/config/
export default defineConfig(({ mode, command }) => {
  const env = loadEnv(mode, process.cwd())
  const { VITE_APP_ENV } = env
  
  // 判断是否为Electron开发环境
  const isElectronDev = process.env.NODE_ENV === 'development' && process.env.IS_ELECTRON === 'true';
  
  return {
    base: VITE_APP_ENV === 'production' ? './' : '/',
    plugins: createVitePlugins(env, command === 'build'),
    resolve: {
      alias: {
        '~': path.resolve(__dirname, './'),
        '@': path.resolve(__dirname, './src')
      },
      extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']
    },
    build: {
      sourcemap: command === 'build' ? false : 'inline',
      outDir: 'dist',
      assetsDir: 'assets',
      chunkSizeWarningLimit: 2000,
      rollupOptions: {
        output: {
          chunkFileNames: 'static/js/[name]-[hash].js',
          entryFileNames: 'static/js/[name]-[hash].js',
          assetFileNames: 'static/[ext]/[name]-[hash].[ext]'
        }
      }
    },
    server: {
      port: 8080,
      host: true,
      open: !isElectronDev, // Electron开发环境下不自动打开浏览器
      proxy: {
        '/dev-api': {
          target: 'http://localhost:8080',
          changeOrigin: true,
          rewrite: (p) => p.replace(/^\/dev-api/, '')
        }
      }
    }
  }
})

三、桌面端特有功能实现

3.1 自定义窗口控制

在Vue组件中使用Electron API实现自定义窗口控制:

<template>
  <div class="window-controls">
    <button @click="minimizeWindow" class="control-btn">—</button>
    <button @click="maximizeWindow" class="control-btn">□</button>
    <button @click="closeWindow" class="control-btn">×</button>
  </div>
</template>

<script setup>
import { onMounted, ref } from 'vue';

const isElectron = ref(false);

onMounted(() => {
  // 检查是否在Electron环境中
  isElectron.value = window.electronAPI?.isElectron || false;
});

const minimizeWindow = () => {
  if (isElectron.value) {
    window.electronAPI.minimizeWindow();
  }
};

const maximizeWindow = () => {
  if (isElectron.value) {
    window.electronAPI.maximizeWindow();
  }
};

const closeWindow = () => {
  if (isElectron.value) {
    window.electronAPI.closeWindow();
  }
};
</script>

<style scoped>
.window-controls {
  display: flex;
  gap: 8px;
  padding: 8px;
}

.control-btn {
  width: 30px;
  height: 30px;
  border: none;
  border-radius: 4px;
  background-color: #f0f0f0;
  cursor: pointer;
  font-size: 16px;
  transition: background-color 0.2s;
}

.control-btn:hover {
  background-color: #e0e0e0;
}
</style>

3.2 系统托盘功能

扩展Electron主进程,添加系统托盘功能:

// 在electron/main.js中添加
const { Tray, Menu } = require('electron');

let tray = null;

function createTray() {
  tray = new Tray(path.join(__dirname, '../src/assets/logo/logo.png'));
  
  const contextMenu = Menu.buildFromTemplate([
    { 
      label: '显示窗口', 
      click: () => {
        mainWindow.show();
      }
    },
    { 
      label: '隐藏窗口', 
      click: () => {
        mainWindow.hide();
      }
    },
    { type: 'separator' },
    { 
      label: '退出', 
      click: () => {
        app.quit();
      }
    }
  ]);
  
  tray.setToolTip('RuoYi-Vue3管理系统');
  tray.setContextMenu(contextMenu);
  
  // 点击托盘图标显示/隐藏窗口
  tray.on('click', () => {
    if (mainWindow.isVisible()) {
      mainWindow.hide();
    } else {
      mainWindow.show();
    }
  });
}

// 在createWindow函数中调用
function createWindow() {
  // ... 现有代码 ...
  
  // 创建系统托盘
  createTray();
}

四、应用打包与分发

4.1 打包命令

添加完成所有功能后,使用以下命令打包桌面应用:

# 构建生产版本并打包Electron应用
npm run electron:build

4.2 打包配置详解

Electron-builder的打包配置主要包括以下几个部分:

配置项说明
appId应用唯一标识
productName应用名称
copyright版权信息
directories.output输出目录
files需要打包的文件
win/mac/linux各平台特有配置
nsisWindows安装程序配置

4.3 分发策略

根据目标平台的不同,打包后会生成不同类型的安装文件:

  • Windows: .exe 安装程序
  • macOS: .dmg 磁盘镜像
  • Linux: .deb 安装包

五、常见问题解决方案

5.1 开发环境热重载

在开发过程中,为了实现Vite和Electron的同时热重载,可以使用concurrentlywait-on工具:

npm install concurrently wait-on --save-dev

修改package.json脚本:

{
  "scripts": {
    "electron:dev": "concurrently \"vite\" \"wait-on http://localhost:8080 && NODE_ENV=development electron .\""
  }
}

5.2 跨域问题处理

在Electron环境中,可以通过主进程代理解决API跨域问题:

// 在electron/main.js中添加
const { session } = require('electron');

// 设置API请求代理
session.defaultSession.webRequest.onBeforeSendHeaders((details, callback) => {
  details.requestHeaders['Origin'] = 'http://localhost:8080';
  callback({ requestHeaders: details.requestHeaders });
});

session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
  callback({
    responseHeaders: {
      ...details.responseHeaders,
      'Access-Control-Allow-Origin': ['http://localhost:8080'],
      'Access-Control-Allow-Credentials': ['true']
    }
  });
});

5.3 性能优化建议

  1. 禁用不必要的Web功能:在Electron环境中,可以禁用一些Web特有功能,如PWA等。

  2. 优化资源加载:使用Electron的webPreferences配置优化资源加载:

webPreferences: {
  preload: path.join(__dirname, 'preload.js'),
  webSecurity: true,
  allowRunningInsecureContent: false,
  imageAnimationPolicy: 'no-animation',
  backgroundThrottling: true
}
  1. 内存泄漏监控:使用Electron的性能监控工具:
// 在开发环境中启用性能监控
if (process.env.NODE_ENV === 'development') {
  mainWindow.webContents.openDevTools({ mode: 'detach' });
  setInterval(() => {
    const memoryUsage = process.getHeapUsage();
    console.log(`Memory usage: ${Math.round(memoryUsage.usedHeapSize / 1024 / 1024)}MB`);
  }, 5000);
}

六、总结与展望

6.1 项目改造回顾

通过本文介绍的方法,我们成功将RuoYi-Vue3 Web应用改造为Electron桌面应用,主要完成了以下工作:

  1. 添加Electron相关依赖和配置
  2. 实现主进程和渲染进程通信
  3. 添加桌面端特有功能(窗口控制、系统托盘)
  4. 优化打包配置和分发策略
  5. 解决常见问题(热重载、跨域、性能)

6.2 未来扩展方向

  1. 离线数据同步:利用Electron的文件系统访问能力,实现本地数据存储和云端同步。

  2. 系统集成:与操作系统深度集成,如添加右键菜单、文件类型关联等。

  3. 多窗口管理:实现多文档界面(MDI),提升复杂操作的用户体验。

  4. 自动更新:集成Electron-updater,实现应用自动更新功能。

结语

通过Electron框架,我们可以快速将现有的RuoYi-Vue3 Web应用改造为功能完备的桌面应用,同时保留原有的开发流程和用户体验。这种方式不仅降低了跨平台开发的成本,还为企业级应用提供了更多可能性。希望本文介绍的方案能够帮助你顺利完成自己的跨平台项目改造!

如果觉得本文对你有帮助,请点赞、收藏并关注我们,获取更多关于RuoYi-Vue3和Electron开发的实战技巧。下期我们将带来《RuoYi-Vue3插件系统设计与实现》,敬请期待!

【免费下载链接】RuoYi-Vue3 :tada: (RuoYi)官方仓库 基于SpringBoot,Spring Security,JWT,Vue3 & Vite、Element Plus 的前后端分离权限管理系统 【免费下载链接】RuoYi-Vue3 项目地址: https://gitcode.com/GitHub_Trending/ruo/RuoYi-Vue3

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值