1
This commit is contained in:
@@ -203,7 +203,12 @@
|
|||||||
"WebFetch(domain:www.electronjs.org)",
|
"WebFetch(domain:www.electronjs.org)",
|
||||||
"Bash(test:*)",
|
"Bash(test:*)",
|
||||||
"Bash(sqlite3:*)",
|
"Bash(sqlite3:*)",
|
||||||
"Bash(npx electron:*)"
|
"Bash(npx electron:*)",
|
||||||
|
"Bash(.erpClient.exe)",
|
||||||
|
"Bash(start erpClient.exe)",
|
||||||
|
"Bash(grep:*)",
|
||||||
|
"Bash(npx asar list:*)",
|
||||||
|
"Bash(npx @electron/asar extract:*)"
|
||||||
],
|
],
|
||||||
"deny": [],
|
"deny": [],
|
||||||
"ask": [],
|
"ask": [],
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
{
|
{
|
||||||
"appId": "com.erp.client",
|
"appId": "com.erp.client",
|
||||||
"productName": "erpClient",
|
"productName": "erpClient",
|
||||||
"asar": true,
|
"asar": {
|
||||||
|
"smartUnpack": false
|
||||||
|
},
|
||||||
|
"compression": "maximum",
|
||||||
|
"asarUnpack": [
|
||||||
|
"public/**/*"
|
||||||
|
],
|
||||||
"directories": {
|
"directories": {
|
||||||
"output": "dist"
|
"output": "dist"
|
||||||
},
|
},
|
||||||
@@ -38,10 +44,57 @@
|
|||||||
"to": "static",
|
"to": "static",
|
||||||
"filter": ["**/*"]
|
"filter": ["**/*"]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"from": "public",
|
||||||
|
"to": "public",
|
||||||
|
"filter": [
|
||||||
|
"**/*",
|
||||||
|
"!jre/bin/jabswitch.exe",
|
||||||
|
"!jre/bin/jaccessinspector.exe",
|
||||||
|
"!jre/bin/jaccesswalker.exe",
|
||||||
|
"!jre/bin/jar.exe",
|
||||||
|
"!jre/bin/jarsigner.exe",
|
||||||
|
"!jre/bin/javac.exe",
|
||||||
|
"!jre/bin/javadoc.exe",
|
||||||
|
"!jre/bin/javap.exe",
|
||||||
|
"!jre/bin/jcmd.exe",
|
||||||
|
"!jre/bin/jconsole.exe",
|
||||||
|
"!jre/bin/jdb.exe",
|
||||||
|
"!jre/bin/jdeprscan.exe",
|
||||||
|
"!jre/bin/jdeps.exe",
|
||||||
|
"!jre/bin/jfr.exe",
|
||||||
|
"!jre/bin/jhsdb.exe",
|
||||||
|
"!jre/bin/jimage.exe",
|
||||||
|
"!jre/bin/jinfo.exe",
|
||||||
|
"!jre/bin/jlink.exe",
|
||||||
|
"!jre/bin/jmap.exe",
|
||||||
|
"!jre/bin/jmod.exe",
|
||||||
|
"!jre/bin/jpackage.exe",
|
||||||
|
"!jre/bin/jps.exe",
|
||||||
|
"!jre/bin/jrunscript.exe",
|
||||||
|
"!jre/bin/jshell.exe",
|
||||||
|
"!jre/bin/jstack.exe",
|
||||||
|
"!jre/bin/jstat.exe",
|
||||||
|
"!jre/bin/jstatd.exe",
|
||||||
|
"!jre/bin/keytool.exe",
|
||||||
|
"!jre/bin/kinit.exe",
|
||||||
|
"!jre/bin/klist.exe",
|
||||||
|
"!jre/bin/ktab.exe",
|
||||||
|
"!jre/bin/rmiregistry.exe",
|
||||||
|
"!jre/bin/serialver.exe",
|
||||||
|
"!jre/include/**",
|
||||||
|
"!jre/lib/src.zip",
|
||||||
|
"!jre/lib/ct.sym",
|
||||||
|
"!jre/lib/jvm.lib",
|
||||||
|
"!icon/image.png",
|
||||||
|
"!icon/img.png"
|
||||||
|
]
|
||||||
|
},
|
||||||
"!build",
|
"!build",
|
||||||
"!dist",
|
"!dist",
|
||||||
"!scripts"
|
"!scripts"
|
||||||
],
|
],
|
||||||
|
"electronLanguages": ["en", "zh-CN"],
|
||||||
"extraResources": [
|
"extraResources": [
|
||||||
{
|
{
|
||||||
"from": "update-helper.bat",
|
"from": "update-helper.bat",
|
||||||
|
|||||||
1288
electron-vue-template/package-lock.json
generated
1288
electron-vue-template/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -17,10 +17,12 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vitejs/plugin-vue": "^4.4.1",
|
"@vitejs/plugin-vue": "^4.4.1",
|
||||||
"chalk": "^4.1.2",
|
"chalk": "^4.1.2",
|
||||||
"chokidar": "^3.5.3",
|
"chokidar": "^3.5.3",
|
||||||
"electron": "^38.1.2",
|
"electron": "^38.1.2",
|
||||||
"electron-builder": "^25.1.6",
|
"electron-builder": "^25.1.6",
|
||||||
|
"express": "^5.1.0",
|
||||||
|
"fs-extra": "^11.3.2",
|
||||||
"typescript": "^5.2.2",
|
"typescript": "^5.2.2",
|
||||||
"vite": "^4.5.0"
|
"vite": "^4.5.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
html, body { height: 100%; margin: 0; }
|
html, body { height: 100%; margin: 0; }
|
||||||
body {
|
body {
|
||||||
background: #fff; font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;
|
background: #fff; font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;
|
||||||
background-image: url('image/splash_screen.png');
|
background-image: url('./image/splash_screen.png');
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ const Chalk = require('chalk');
|
|||||||
const FileSystem = require('fs');
|
const FileSystem = require('fs');
|
||||||
const Vite = require('vite');
|
const Vite = require('vite');
|
||||||
const compileTs = require('./private/tsc');
|
const compileTs = require('./private/tsc');
|
||||||
|
const copyAssets = require('./copy-assets');
|
||||||
|
|
||||||
function buildRenderer() {
|
function buildRenderer() {
|
||||||
return Vite.build({
|
return Vite.build({
|
||||||
@@ -27,6 +28,8 @@ console.log(Chalk.blueBright('Transpiling renderer & main...'));
|
|||||||
Promise.allSettled([
|
Promise.allSettled([
|
||||||
buildRenderer(),
|
buildRenderer(),
|
||||||
buildMain(),
|
buildMain(),
|
||||||
]).then(() => {
|
]).then(async () => {
|
||||||
|
console.log(Chalk.blueBright('Copying necessary assets...'));
|
||||||
|
await copyAssets();
|
||||||
console.log(Chalk.greenBright('Renderer & main successfully transpiled! (ready to be built with electron-builder)'));
|
console.log(Chalk.greenBright('Renderer & main successfully transpiled! (ready to be built with electron-builder)'));
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import {app, BrowserWindow, ipcMain, Menu, screen, dialog} from 'electron';
|
import {app, BrowserWindow, ipcMain, Menu, screen, dialog} from 'electron';
|
||||||
import {existsSync, createWriteStream, promises as fs} from 'fs';
|
import {existsSync, createWriteStream, promises as fs} from 'fs';
|
||||||
import {join, dirname} from 'path';
|
import {join, dirname} from 'path';
|
||||||
import {spawn, ChildProcessWithoutNullStreams} from 'child_process';
|
import {spawn, ChildProcess} from 'child_process';
|
||||||
import * as https from 'https';
|
import * as https from 'https';
|
||||||
import * as http from 'http';
|
import * as http from 'http';
|
||||||
|
|
||||||
let springProcess: ChildProcessWithoutNullStreams | null = null;
|
let springProcess: ChildProcess | null = null;
|
||||||
let mainWindow: BrowserWindow | null = null;
|
let mainWindow: BrowserWindow | null = null;
|
||||||
let splashWindow: BrowserWindow | null = null;
|
let splashWindow: BrowserWindow | null = null;
|
||||||
let appOpened = false;
|
let appOpened = false;
|
||||||
@@ -17,40 +17,133 @@ let downloadedFilePath: string | null = null;
|
|||||||
function openAppIfNotOpened() {
|
function openAppIfNotOpened() {
|
||||||
if (appOpened) return;
|
if (appOpened) return;
|
||||||
appOpened = true;
|
appOpened = true;
|
||||||
|
|
||||||
// SpringBoot 启动完成,现在加载前端页面
|
|
||||||
if (mainWindow) {
|
if (mainWindow) {
|
||||||
|
mainWindow.webContents.once('did-finish-load', () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
mainWindow?.show();
|
||||||
|
mainWindow?.focus();
|
||||||
|
if (splashWindow) {
|
||||||
|
splashWindow.close();
|
||||||
|
splashWindow = null;
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
});
|
||||||
|
|
||||||
if (process.env.NODE_ENV === 'development') {
|
if (process.env.NODE_ENV === 'development') {
|
||||||
const rendererPort = process.argv[2] || 8083;
|
const rendererPort = process.argv[2] || 8083;
|
||||||
mainWindow.loadURL(`http://localhost:${rendererPort}`);
|
mainWindow.loadURL(`http://localhost:${rendererPort}`);
|
||||||
} else {
|
} else {
|
||||||
mainWindow.loadFile(join(__dirname, '../renderer/index.html'));
|
mainWindow.loadFile(join(__dirname, '../renderer/index.html'));
|
||||||
}
|
}
|
||||||
mainWindow.show();
|
|
||||||
mainWindow.focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (splashWindow) {
|
|
||||||
splashWindow.close();
|
|
||||||
splashWindow = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function startSpringBoot() {
|
function getJavaExecutablePath(): string {
|
||||||
const jarPath = join(__dirname, '../../public/erp_client_sb-2.4.7.jar');
|
if (process.env.NODE_ENV === 'development') {
|
||||||
springProcess = spawn('java', ['-jar', jarPath], {
|
return 'java';
|
||||||
cwd: dirname(jarPath),
|
}
|
||||||
detached: false
|
|
||||||
});
|
|
||||||
springProcess.stdout.on('data', (data) => {
|
|
||||||
if (data.toString().includes('Started Success')) {
|
|
||||||
openAppIfNotOpened();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
springProcess.on('close', (code) => {
|
const bundledJavaPath = join(process.resourcesPath, 'app.asar.unpacked/public/jre/bin/java.exe');
|
||||||
mainWindow ? mainWindow.close() : app.quit();
|
if (existsSync(bundledJavaPath)) {
|
||||||
});
|
return bundledJavaPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
const devJavaPath = join(__dirname, '../../public/jre/bin/java.exe');
|
||||||
|
if (existsSync(devJavaPath)) {
|
||||||
|
return devJavaPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'java';
|
||||||
|
}
|
||||||
|
|
||||||
|
function getJarFilePath(): string {
|
||||||
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
return join(__dirname, '../../public/erp_client_sb-2.4.7.jar');
|
||||||
|
}
|
||||||
|
|
||||||
|
const bundledJarPath = join(process.resourcesPath, 'app.asar.unpacked/public/erp_client_sb-2.4.7.jar');
|
||||||
|
if (existsSync(bundledJarPath)) {
|
||||||
|
return bundledJarPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
return join(__dirname, '../../public/erp_client_sb-2.4.7.jar');
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSplashPath(): string {
|
||||||
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
return join(__dirname, '../../public/splash.html');
|
||||||
|
}
|
||||||
|
|
||||||
|
const bundledSplashPath = join(process.resourcesPath, 'app.asar.unpacked/public/splash.html');
|
||||||
|
if (existsSync(bundledSplashPath)) {
|
||||||
|
return bundledSplashPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
return join(__dirname, '../../public/splash.html');
|
||||||
|
}
|
||||||
|
|
||||||
|
function getIconPath(): string {
|
||||||
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
return join(__dirname, '../../public/icon/icon.png');
|
||||||
|
}
|
||||||
|
|
||||||
|
const bundledIconPath = join(process.resourcesPath, 'app.asar.unpacked/public/icon/icon.png');
|
||||||
|
if (existsSync(bundledIconPath)) {
|
||||||
|
return bundledIconPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
return join(__dirname, '../renderer/icon/icon.png');
|
||||||
|
}
|
||||||
|
|
||||||
|
function startSpringBoot() {
|
||||||
|
const jarPath = getJarFilePath();
|
||||||
|
const javaPath = getJavaExecutablePath();
|
||||||
|
|
||||||
|
if (!existsSync(jarPath)) {
|
||||||
|
dialog.showErrorBox('启动失败', `JAR 文件不存在:\n${jarPath}`);
|
||||||
|
app.quit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
springProcess = spawn(javaPath, ['-jar', jarPath], {
|
||||||
|
cwd: dirname(jarPath),
|
||||||
|
detached: false
|
||||||
|
});
|
||||||
|
|
||||||
|
let startupCompleted = false;
|
||||||
|
|
||||||
|
springProcess.stdout?.on('data', (data) => {
|
||||||
|
const output = data.toString();
|
||||||
|
if (!startupCompleted && (output.includes('Started Success') || output.includes('Started ErpClientSbApplication'))) {
|
||||||
|
startupCompleted = true;
|
||||||
|
openAppIfNotOpened();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
springProcess.on('close', (code) => {
|
||||||
|
mainWindow ? mainWindow.close() : app.quit();
|
||||||
|
});
|
||||||
|
|
||||||
|
springProcess.on('error', (error) => {
|
||||||
|
let errorMessage = '启动 Java 应用失败';
|
||||||
|
if (error.message.includes('ENOENT')) {
|
||||||
|
errorMessage = '找不到 Java 运行环境\n请确保应用包含 JRE 或系统已安装 Java';
|
||||||
|
}
|
||||||
|
dialog.showErrorBox('启动失败', errorMessage);
|
||||||
|
app.quit();
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
if (!startupCompleted) {
|
||||||
|
openAppIfNotOpened();
|
||||||
|
}
|
||||||
|
}, 15000);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
dialog.showErrorBox('启动异常', `无法启动应用: ${error}`);
|
||||||
|
app.quit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
startSpringBoot();
|
startSpringBoot();
|
||||||
@@ -81,7 +174,7 @@ function createWindow() {
|
|||||||
height: 800,
|
height: 800,
|
||||||
show: false,
|
show: false,
|
||||||
autoHideMenuBar: true,
|
autoHideMenuBar: true,
|
||||||
icon: join(__dirname, '../renderer/icon/icon.png'),
|
icon: getIconPath(),
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
preload: join(__dirname, 'preload.js'),
|
preload: join(__dirname, 'preload.js'),
|
||||||
nodeIntegration: false,
|
nodeIntegration: false,
|
||||||
@@ -89,7 +182,6 @@ function createWindow() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
mainWindow.webContents.openDevTools();
|
|
||||||
Menu.setApplicationMenu(null);
|
Menu.setApplicationMenu(null);
|
||||||
mainWindow.setMenuBarVisibility(false);
|
mainWindow.setMenuBarVisibility(false);
|
||||||
|
|
||||||
@@ -97,12 +189,7 @@ function createWindow() {
|
|||||||
setTimeout(() => checkPendingUpdate(), 500);
|
setTimeout(() => checkPendingUpdate(), 500);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (process.env.NODE_ENV === 'development') {
|
// 不立即加载页面,等 SpringBoot 启动完成后再加载
|
||||||
const rendererPort = process.argv[2] || 8083;
|
|
||||||
mainWindow.loadURL(`http://localhost:${rendererPort}`);
|
|
||||||
} else {
|
|
||||||
mainWindow.loadFile(join(__dirname, '../renderer/index.html'));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
app.whenReady().then(() => {
|
app.whenReady().then(() => {
|
||||||
@@ -115,12 +202,17 @@ app.whenReady().then(() => {
|
|||||||
frame: false,
|
frame: false,
|
||||||
transparent: false,
|
transparent: false,
|
||||||
resizable: false,
|
resizable: false,
|
||||||
alwaysOnTop: true,
|
alwaysOnTop: false,
|
||||||
show: true,
|
show: true,
|
||||||
center: true,
|
center: true,
|
||||||
|
icon: getIconPath(),
|
||||||
|
webPreferences: {
|
||||||
|
nodeIntegration: false,
|
||||||
|
contextIsolation: true,
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const splashPath = join(__dirname, '../../public', 'splash.html');
|
const splashPath = getSplashPath();
|
||||||
if (existsSync(splashPath)) {
|
if (existsSync(splashPath)) {
|
||||||
splashWindow.loadFile(splashPath);
|
splashWindow.loadFile(splashPath);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ const { defineConfig } = require('vite');
|
|||||||
*/
|
*/
|
||||||
const config = defineConfig({
|
const config = defineConfig({
|
||||||
root: Path.join(__dirname, 'src', 'renderer'),
|
root: Path.join(__dirname, 'src', 'renderer'),
|
||||||
publicDir: Path.join(__dirname, 'public'),
|
publicDir: Path.join(__dirname, 'src', 'renderer', 'public'), // 使用renderer下的public目录
|
||||||
server: {
|
server: {
|
||||||
port: 8083,
|
port: 8083,
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user