将前后端分离版的前端vue打包成EXE的完整解决方案

news2026/2/21 2:32:51

将若依前后端分离版的前端打包成EXE的完整解决方案

将若依前后端分离版的Vue前端打包成Windows可执行文件(.exe),同时保持与后端API的通信,需要使用Electron框架来实现。下面是详细的步骤和解决方案。

一、准备工作

1. 环境要求

  • Node.js (推荐v16+)
  • npm 或 yarn
  • 若依前后端分离版的前端代码
  • Git

2. 相关技术栈

  • Vue.js (若依前端使用)
  • Electron (桌面应用打包框架)
  • electron-builder (打包工具)

二、项目改造步骤

1. 安装Electron相关依赖

首先,进入若依前端项目目录,安装Electron相关依赖:

# 进入若依前端项目目录
cd ruoyi-ui

# 安装Electron相关依赖
npm install electron electron-builder --save-dev

# 安装其他必要的依赖
npm install electron-is-dev electron-store --save

2. 创建Electron主进程文件

在项目根目录创建Electron主进程文件:

const { app, BrowserWindow, Menu, shell, dialog } = require('electron');
const path = require('path');
const isDev = require('electron-is-dev');
const Store = require('electron-store');

// 初始化配置存储
Store.initRenderer();
const store = new Store();

// 保存主窗口对象的引用
let mainWindow;

// 创建主窗口
function createWindow() {
  // 创建浏览器窗口
  mainWindow = new BrowserWindow({
    width: 1280,
    height: 800,
    minWidth: 1024,
    minHeight: 768,
    icon: path.join(__dirname, '../public/favicon.ico'),
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: false,
      webSecurity: false, // 允许跨域请求
      preload: path.join(__dirname, 'preload.js')
    }
  });

  // 加载应用
  if (isDev) {
    // 开发环境下加载开发服务器地址
    mainWindow.loadURL('http://localhost:80');
    // 打开开发者工具
    mainWindow.webContents.openDevTools();
  } else {
    // 生产环境下加载打包后的index.html
    mainWindow.loadFile(path.join(__dirname, '../dist/index.html'));
  }

  // 当窗口关闭时触发
  mainWindow.on('closed', () => {
    mainWindow = null;
  });

  // 创建菜单
  createMenu();
}

// 创建应用菜单
function createMenu() {
  const template = [
    {
      label: '文件',
      submenu: [
        {
          label: '设置API地址',
          click: () => {
            configApiUrl();
          }
        },
        { type: 'separator' },
        {
          label: '退出',
          accelerator: 'CmdOrCtrl+Q',
          click: () => {
            app.quit();
          }
        }
      ]
    },
    {
      label: '编辑',
      submenu: [
        { role: 'undo', label: '撤销' },
        { role: 'redo', label: '重做' },
        { type: 'separator' },
        { role: 'cut', label: '剪切' },
        { role: 'copy', label: '复制' },
        { role: 'paste', label: '粘贴' }
      ]
    },
    {
      label: '视图',
      submenu: [
        { role: 'reload', label: '刷新' },
        { role: 'forceReload', label: '强制刷新' },
        { role: 'toggleDevTools', label: '开发者工具' },
        { type: 'separator' },
        { role: 'resetZoom', label: '实际大小' },
        { role: 'zoomIn', label: '放大' },
        { role: 'zoomOut', label: '缩小' },
        { type: 'separator' },
        { role: 'togglefullscreen', label: '全屏' }
      ]
    },
    {
      label: '帮助',
      submenu: [
        {
          label: '关于',
          click: () => {
            dialog.showMessageBox({
              title: '关于',
              message: '若依管理系统桌面版',
              detail: `版本: ${app.getVersion()}\n若依是一款优秀的开源后台管理系统。`
            });
          }
        },
        {
          label: '访问官网',
          click: () => {
            shell.openExternal('http://ruoyi.vip');
          }
        }
      ]
    }
  ];

  const menu = Menu.buildFromTemplate(template);
  Menu.setApplicationMenu(menu);
}

// 配置API地址
function configApiUrl() {
  // 获取当前API地址
  const currentApiUrl = store.get('apiUrl') || 'http://localhost:8080';

  // 显示输入对话框
  dialog.showInputBox({
    title: '设置API地址',
    label: '请输入后端API地址:',
    value: currentApiUrl,
    inputAttrs: {
      type: 'url'
    },
    buttons: ['确定', '取消'],
    defaultId: 0,
    cancelId: 1
  }).then(result => {
    if (!result.canceled && result.text) {
      // 保存新的API地址
      store.set('apiUrl', result.text);
      
      // 提示用户重启应用
      dialog.showMessageBox({
        type: 'info',
        title: '设置成功',
        message: 'API地址已更新,请重启应用以应用更改。',
        buttons: ['重启', '稍后']
      }).then(res => {
        if (res.response === 0) {
          app.relaunch();
          app.exit(0);
        }
      });
    }
  }).catch(err => {
    console.error('设置API地址出错:', err);
  });
}

// 当Electron完成初始化并准备创建浏览器窗口时调用此方法
app.whenReady().then(() => {
  createWindow();

  app.on('activate', () => {
    // 在macOS上,当点击dock图标并且没有其他窗口打开时,
    // 通常在应用程序中重新创建一个窗口。
    if (BrowserWindow.getAllWindows().length === 0) {
      createWindow();
    }
  });
});

// 当所有窗口关闭时退出应用
app.on('wind

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2400951.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

「Java教案」Java程序的构成

课程目标 1.知识目标 能够按照Java标识符的命名规则,规范变量的命名。能够区分Java中的关键字与保留字。能够对注释进行分类,根据注释的用途合理的选择注释方式。 2.能力目标 能编写符合规范的标识符。能识别Java中的关键字和…

区块链可投会议CCF B--EDBT 2026 截止10.8 附录用率

Conference:EDBT: 29th International Conference on Extending Database Technology CCF level:CCF B Categories:数据库/数据挖掘/内容检索 Year:2026 Conference time:24th March - 27th…

经典ReLU回归!重大缺陷「死亡ReLU问题」已被解决

来源 | 机器之心 在深度学习领域中,对激活函数的探讨已成为一个独立的研究方向。例如 GELU、SELU 和 SiLU 等函数凭借其平滑梯度与卓越的收敛特性,已成为热门选择。 尽管这一趋势盛行,经典 ReLU 函数仍因其简洁性、固有稀疏性及…

在VSCode中开发一个uni-app项目

创建项目 使用命令行工具(例如 vue-cli)来创建一个新的 uni-app 项目。 创建以JavaScript开发的工程 npx degit dcloudio/uni-preset-vue#vite my-vue3-project //或者 npx degit dcloudio/uni-preset-vue#vite-alpha my-vue3-project创建以TypeScript…

Python - 爬虫;Scrapy框架之插件Extensions(四)

阅读本文前先参考 https://blog.csdn.net/MinggeQingchun/article/details/145904572 在 Scrapy 中,扩展(Extensions)是一种插件,允许你添加额外的功能到你的爬虫项目中。这些扩展可以在项目的不同阶段执行,比如启动…

Spark实战能力测评模拟题精析【模拟考】

1.println(Array(1,2,3,4,5).filter(_%20).toList() 输出结果是(B) A. 2 4 B. List(2,4) C. List(1,3,5) D. 1 3 5 2.println(Array("tom","team","pom") .filter(_.matches("")).toList) 输出结果为(List(tom,…

【OSG学习笔记】Day 15: 路径动画与相机漫游

本章来学习下漫游相机。 路径动画与相机漫游 本届内容比较简单,其实就是实现物体的运动和相机的运动 当然这两个要一起执行。 贝塞尔曲线 贝塞尔曲线(Bzier curve)是一种在计算机图形学、动画制作、工业设计等领域广泛应用的参数曲线&am…

PostgreSQL(PostGIS)触发器+坐标转换案例

需求,只录入一份坐标参考为4326的数据,但是发布的数据要求坐标必须是3857 对这种需求可以利用数据库触发器实现数据的同步 步骤: 1. 使用ArcGIS Pro创建一个名字为testfc_4326的图层,坐标参考为4326 2. 使用Pro再创建一个名字…

Constraints and Triggers

目录 Kinds of Constraints Single-Attribute Keys Multiattribute Key Foreign Keys Expressing Foreign Keys Enforcing Foreign-Key Constraints Actions Taken Attribute-Based Checks Timing of Checks Tuple-Based Checks Assertions Timing of Assertion Ch…

BERT:让AI真正“读懂”语言的革命

BERT:让AI真正“读懂”语言的革命 ——图解谷歌神作《BERT: Pre-training of Deep Bidirectional Transformers》 2018年,谷歌AI团队扔出一篇核弹级论文,引爆了整个NLP领域。这个叫BERT的模型在11项任务中屠榜,甚至超越人类表现…

冷雨泉教授团队:新型视觉驱动智能假肢手,拟人化抓握技术突破,助力截肢者重获生活自信

研究背景:日常生活中,健康人依靠手完成对物体的操作。对于手部截肢患者,手部的缺失导致他们难以有效地操作物体,进而影响正常的日常生活。拥有一个能够实现拟人地自然抓取多种日常物体的五指动力假手是手部截肢患者的夙愿&#xf…

pikachu靶场通关笔记14 XSS关卡10-XSS之js输出(五种方法渗透)

目录 一、源码分析 1、进入靶场 2、代码审计 二、渗透实战 1、根据提示输入tmac 2、XSS探测 3、注入Payload1 4、注入Payload2 5、注入Payload3 6、注入Payload4 7、注入Payload5 本系列为通过《pikachu靶场通关笔记》的XSS关卡(共10关)渗透集合&#x…

李沐-动手学深度学习:RNN

1.RNN从零开始实现 import math import torch from torch import nn from torch.nn import functional as F from d2l import torch as d2l#8.3.4节 #batch_size:每个小批量中子序列样本的数目,num_steps:每个子序列中预定义的时间步数 #loa…

【教学类-36-10】20250531蝴蝶图案描边,最适合大小(一页1图1图、2图图案不同、2图图案相同对称)

背景说明: 之前做了动物头像扇子(描边20),并制作成一页一套图案对称两张 【教学类-36-09】20250526动物头像扇子的描边(通义万相)对称图40张,根据图片长宽,自动旋转图片,最大化图片-CSDN博客文章浏览阅读1k次,点赞37次,收藏6次。【教学类-36-09】20250526动物头像…

高效DBA的日常运维主题沙龙

2024年11月10日,在宁波组织了高效DBA的日常运维沙龙活动,大概有20人左右现场参加。会议的主题为: 目标: 1、识别高频低效操作并制定自动化方案 2、建立关键运维指标健康度体系 3、输出可立即落地的优化清单 会议议程 一、效能瓶…

AAAI 2025论文分享│STD-PLM:基于预训练语言模型的时空数据预测与补全方法

本文详细介绍了一篇发表于人工智能顶级会议AAAI 2025的论文《STD-PLM: Understanding Both Spatial and Temporal Properties of Spatial-Temporal Data with PLM》。该论文提出了一种基于预训练语言模型(Pre-trained Language Model‌,PLM)的…

Ethernet/IP转DeviceNet网关:驱动大型矿山自动化升级的核心纽带

在大型矿山自动化系统中,如何高效整合新老设备、打通数据孤岛、实现统一控制,是提升效率与安全的关键挑战。JH-EIP-DVN疆鸿智能EtherNet/IP转DeviceNet网关,正是解决这一难题的核心桥梁,为矿山各环节注入强劲连接力: …

[蓝桥杯]模型染色

模型染色 题目描述 在电影《超能陆战队》中,小宏可以使用他的微型机器人组合成各种各样的形状。 现在他用他的微型机器人拼成了一个大玩具给小朋友们玩。为了更加美观,他决定给玩具染色。 小宏的玩具由 nn 个球型的端点和 mm 段连接这些端点之间的边…

卡西欧模拟器:Windows端功能强大的计算器

引言 大家还记得初中高中时期用的计算器吗?今天给大家分享的就是一款windows端的卡西欧计算器。 软件介绍 大家好,我是逍遥小欢。 CASIO fx-9860G是一款功能强大的图形计算器,适用于数学、科学和工程计算。以下是其主要功能和特点的详细介…

机器学习基础(三) 逻辑回归

目录 逻辑回归的概念核心思想 Sigmoid 函数 逻辑回归的原理和底层优化手段伯努利分布最大似然估计 Maximum Likelihood Estimation (MLE)伯努利分布的似然函数交叉熵损失函数(Cross-Entropy Loss),也称为 对数损失&…