v3.8.1发布,上传前端代码

This commit is contained in:
JEECG
2025-06-25 16:04:02 +08:00
parent 3d414aaec8
commit 0148f45979
120 changed files with 4783 additions and 486 deletions

View File

@ -0,0 +1,31 @@
import fs from 'fs';
import path from 'path'
import {shell, dialog} from 'electron'
import {_PATHS} from "../paths";
import {isDev} from "../env";
// 通过浏览器打开链接
export function openInBrowser(url: string) {
return shell.openExternal(url);
}
export function getAppInfo(): any {
try {
const yamlPath = isDev ? path.join(_PATHS.publicRoot, '../electron-builder.yaml') : path.join(_PATHS.electronRoot, 'env.yaml');
const yamlContent = fs.readFileSync(yamlPath, 'utf-8');
// 通过正则表达式匹配 appId 和 productName
const appIdMatch = yamlContent.match(/appId:\s*['"]([^'"]+)['"]/);
const productNameMatch = yamlContent.match(/productName:\s*['"]([^'"]+)['"]/);
const appId = appIdMatch ? appIdMatch[1] : '';
const productName = productNameMatch ? productNameMatch[1] : '';
return {appId, productName}
} catch (e) {
dialog.showMessageBoxSync(null, {
type: 'error',
title: '错误',
message: '应用启动失败,请从官网下载最新版本安装包后重新安装!',
});
process.exit(-1);
}
}

View File

@ -0,0 +1,181 @@
// tray = 系统托盘
import path from 'path';
import {Tray, Menu, app, dialog, nativeImage, BrowserWindow, Notification} from 'electron';
import {_PATHS} from '../paths';
import {$env, isDev} from '../env';
const TrayIcons = {
normal: nativeImage.createFromPath(path.join(_PATHS.publicRoot, 'logo.png')),
empty: nativeImage.createEmpty(),
};
// 创建托盘图标
export function createTray(win: BrowserWindow) {
const tray = new Tray(TrayIcons.normal);
const TrayUtils = useTray(tray, win);
tray.setToolTip($env.VITE_GLOB_APP_TITLE! + (isDev ? ' (开发环境)' : ''));
// 左键托盘图标显示主窗口
tray.on('click', () => TrayUtils.showMainWindow());
// 右键托盘图标显示托盘菜单
tray.on('right-click', () => showTrayContextMenu());
function showTrayContextMenu() {
const trayContextMenu = getTrayMenus(win, TrayUtils);
// 弹出托盘菜单,不使用 setContextMenu 方法是因为要实时更新菜单内容
tray.popUpContextMenu(trayContextMenu);
}
}
export function useTray(tray: Tray, win: BrowserWindow) {
let isBlinking = false;
let blinkTimer: NodeJS.Timeout | null = null;
function showMainWindow() {
win.show();
}
// 开始闪动
function startBlink() {
isBlinking = true;
tray.setImage(TrayIcons.empty);
blinkTimer = setTimeout(() => {
tray.setImage(TrayIcons.normal);
setTimeout(() => {
if (isBlinking) {
startBlink();
}
}, 500);
}, 500);
}
// 结束闪动
function stopBlink() {
isBlinking = false;
if (blinkTimer) {
clearTimeout(blinkTimer);
blinkTimer = null;
}
tray.setImage(TrayIcons.normal);
}
// 发送桌面通知
function sendDesktopNotice() {
// 判断是否支持桌面通知
if (!Notification.isSupported()) {
// todo 实际开发中不需要提示,直接返回或者换一种提示方式
dialog.showMessageBoxSync(win, {
type: 'error',
title: '错误',
message: '当前系统不支持桌面通知',
});
return;
}
const ins = new Notification({
title: '通知标题',
subtitle: '通知副标题',
body: '通知内容第一行\n通知内容第二行',
icon: TrayIcons.normal.resize({width: 32, height: 32}),
});
ins.on('click', () => {
dialog.showMessageBoxSync(win, {
type: 'info',
title: '提示',
message: '通知被点击',
});
});
ins.show();
}
return {
showMainWindow,
startBlink,
stopBlink,
isBlinking: () => isBlinking,
sendDesktopNotice,
};
}
const MenuIcon = {
exit: nativeImage
.createFromDataURL(
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACJ0lEQVR4nH1TzWvUQBRP7fpxsWqVXsSLiAevRWhhN28msRJo981kay4WRBCF/QdEFJpbaUHw4kFBQTwUKX4gKh48KPiBBcGLJ1F0uzPZ7ibWXf0DIjObielS+mDIm/fxm9/85sWyBixN06E0CIaV3wB2XhC8puOWNZSG4Y7B+k2mi7Kl9l2n9rHnzvbWJoLRYn7r5jTViQjwzM8ynlC+AFyVgN2NU8G+Rnn6QETx3FfP223A/jeHfWqCsAUJ7Hlryh9Te0nYqiDsz9rE6VHVIABvNwEf/ADYk4OsZPeVFbwiCHtcZBVR9k4CJhJmDuUxwEVJ8H4fINOkC9Vjbeq/UTR1IgPturX3f93Z35+B7ddxgJL6dih/skF9zE9KCJ//5bDLpii1+npIuzolKTubC5gBxzarJo6vWWjrUP+etFlF+ds9lRFOXalN+NPEmxvRDS3KH34v8+PFIgNmTh0EahH+InGCwzoQEbYcuTMnlR8aYbaxGHFvRNiznssP6sA65UsxrdU1+hYnFhlpAGAkdvzlPLFu88mY8pcrVjCsxcqGapC2eYW249/tUH4xS4QaVQLeigi/YWJqPl4DlNRSrAwzSaoXIspeWUYrI9qXINglgT1qAt5JPG+kkNN5BSAJuyoJfhAVdmST4PlPBFASNs6rIgnspqC8HlF+SQAuRQTfKpYiEy6fwuIdP42P71T+t0l/TBKcE8AXm4DXBfB6w50+apgUhf4HZ5j+Z5+zNTAAAAAASUVORK5CYII='
)
.resize({
width: 16,
height: 16,
}),
};
// 设置托盘菜单
function getTrayMenus(win: BrowserWindow, TrayUtils: ReturnType<typeof useTray>) {
const {startBlink, stopBlink, sendDesktopNotice} = TrayUtils;
const isBlinking = TrayUtils.isBlinking();
return Menu.buildFromTemplate([
...(isDev
? [
{
label: '开发工具',
submenu: [
{
label: '以下菜单仅显示在开发环境',
sublabel: '当前为开发环境',
enabled: false,
},
{type: 'separator'},
{
label: '切换 DevTools',
click: () => win.webContents.toggleDevTools(),
},
{
label: `托盘图标${isBlinking ? '停止' : '开始'}闪烁`,
sublabel: '模拟新消息提醒',
click: () => (isBlinking ? stopBlink() : startBlink()),
},
{
label: '发送桌面通知示例',
click: () => sendDesktopNotice(),
},
],
},
{type: 'separator'},
]
: ([] as any)),
{
label: '显示主窗口',
// 文件图标
icon: TrayIcons.normal.resize({width: 16, height: 16}),
click: () => win.show(),
},
{type: 'separator'},
{
label: '退出',
// base64图标
icon: MenuIcon.exit,
click: () => {
// 弹出是否确认退出提示框
const choice = dialog.showMessageBoxSync(win, {
type: 'question',
title: '提示',
message: '确定要退出应用吗?',
buttons: ['退出', '取消'],
defaultId: 1,
cancelId: 1,
noLink: true,
});
// 用户选择了退出,直接 exit
if (choice === 0) {
// global.isQuitting = true;
app.exit(0);
}
},
},
]);
}

View File

@ -0,0 +1,85 @@
import type {BrowserWindowConstructorOptions} from 'electron';
import {BrowserWindow, dialog} from 'electron';
import path from 'path';
import {_PATHS} from '../paths';
import {$env, isDev} from '../env';
import {createTray} from './tray';
// 创建窗口
export function createBrowserWindow(options?: BrowserWindowConstructorOptions) {
const win = new BrowserWindow({
width: 1200,
height: 800,
webPreferences: {
preload: path.join(_PATHS.preloadRoot, 'index.js'),
nodeIntegration: false,
contextIsolation: true,
},
// 应用图标
icon: isDev ? _PATHS.appIcon : void 0,
...options,
});
// 设置窗口打开处理器
win.webContents.setWindowOpenHandler(({url}) => {
const win = createBrowserWindow();
win.loadURL(url);
// 阻止创建新窗口,因为已经被接管
return {action: 'deny'};
});
// 当 beforeunload 阻止窗口关闭时触发
win.webContents.on('will-prevent-unload', () => {
const choice = dialog.showMessageBoxSync(win, {
type: 'question',
title: '确认关闭吗?',
message: '系统可能不会保存您所做的更改。',
buttons: ['关闭', '取消'],
defaultId: 1,
cancelId: 1,
noLink: true,
});
// 用户选择了关闭,直接销毁窗口
if (choice === 0) {
win.destroy();
}
});
return win;
}
// 创建主窗口、系统托盘
export function createMainWindow() {
const win = createIndexWindow()
// 设置系统托盘图标
createTray(win);
// 主窗口尝试关闭时,默认不直接退出应用,而是隐藏到托盘
win.on('close', (event) => {
event.preventDefault();
win.hide();
});
return win;
}
// 创建索引窗口
export function createIndexWindow() {
const win = createBrowserWindow({
width: 1600,
height: 1000,
title: $env.VITE_GLOB_APP_TITLE!,
});
// 开发环境加载Vite服务生产加载打包文件
if (isDev) {
win.loadURL($env.VITE_DEV_SERVER_URL!)
// 开发环境下,自动打开调试工具
// win.webContents.openDevTools()
} else {
win.loadFile(path.join(_PATHS.publicRoot, 'index.html'));
}
return win;
}