feat: 画布式 RPA 桌面端 Day1(1016 目录/画布/容器/属性/持久化)
This commit is contained in:
commit
32ca0a1af8
34 files changed
+15141
No files matched your search
@@ -0,0 +1,115 @@
|
||||
import { app, BrowserWindow, dialog, ipcMain, shell } from "electron";
|
||||
import path from "node:path";
|
||||
import type { AppInfo, FlowDefinition } from "../shared/types";
|
||||
import { catalogPath, loadCatalog } from "./catalog";
|
||||
import { createFlow, deleteFlow, getFlow, listFlows, saveFlow } from "./flows";
|
||||
|
||||
let mainWindow: BrowserWindow | null = null;
|
||||
|
||||
function createWindow(): void {
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 1440,
|
||||
height: 900,
|
||||
minWidth: 1200,
|
||||
minHeight: 760,
|
||||
show: false,
|
||||
backgroundColor: "#E7EDF3",
|
||||
title: "RPA Studio",
|
||||
titleBarStyle: "hidden",
|
||||
titleBarOverlay: {
|
||||
color: "#FFFFFF",
|
||||
symbolColor: "#4E5A6B",
|
||||
height: 58
|
||||
},
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, "../preload/index.js"),
|
||||
contextIsolation: true,
|
||||
nodeIntegration: false,
|
||||
sandbox: false
|
||||
}
|
||||
});
|
||||
|
||||
mainWindow.on("ready-to-show", () => mainWindow?.show());
|
||||
mainWindow.on("closed", () => {
|
||||
mainWindow = null;
|
||||
});
|
||||
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
|
||||
if (/^https?:/i.test(url)) void shell.openExternal(url);
|
||||
return { action: "deny" };
|
||||
});
|
||||
|
||||
const devUrl = process.env.ELECTRON_RENDERER_URL;
|
||||
if (devUrl) {
|
||||
void mainWindow.loadURL(devUrl);
|
||||
} else {
|
||||
void mainWindow.loadFile(path.join(__dirname, "../renderer/index.html"));
|
||||
}
|
||||
}
|
||||
|
||||
function registerIpc(): void {
|
||||
ipcMain.handle("app:info", (): AppInfo => ({
|
||||
version: app.getVersion(),
|
||||
electron: process.versions.electron,
|
||||
chrome: process.versions.chrome,
|
||||
node: process.versions.node,
|
||||
userData: app.getPath("userData"),
|
||||
catalogPath: catalogPath(),
|
||||
packaged: app.isPackaged
|
||||
}));
|
||||
|
||||
ipcMain.handle("catalog:get", () => loadCatalog());
|
||||
ipcMain.handle("flows:list", () => listFlows());
|
||||
ipcMain.handle("flows:create", (_event, name?: string) => {
|
||||
const flow = createFlow(name);
|
||||
return saveFlow(flow);
|
||||
});
|
||||
ipcMain.handle("flows:get", (_event, id: string) => getFlow(id));
|
||||
ipcMain.handle("flows:save", (_event, flow: FlowDefinition) => saveFlow(flow));
|
||||
ipcMain.handle("flows:delete", (_event, id: string) => {
|
||||
deleteFlow(id);
|
||||
return true;
|
||||
});
|
||||
|
||||
ipcMain.handle("dialog:open", async (_event, options: { title?: string; filters?: Electron.FileFilter[]; directories?: boolean }) => {
|
||||
if (!mainWindow) return null;
|
||||
const result = await dialog.showOpenDialog(mainWindow, {
|
||||
title: options?.title || "选择文件",
|
||||
properties: options?.directories ? ["openDirectory"] : ["openFile"],
|
||||
filters: options?.filters
|
||||
});
|
||||
return result.canceled ? null : result.filePaths[0] || null;
|
||||
});
|
||||
|
||||
ipcMain.handle("dialog:save", async (_event, options: { title?: string; defaultPath?: string; filters?: Electron.FileFilter[] }) => {
|
||||
if (!mainWindow) return null;
|
||||
const result = await dialog.showSaveDialog(mainWindow, {
|
||||
title: options?.title || "保存文件",
|
||||
defaultPath: options?.defaultPath,
|
||||
filters: options?.filters
|
||||
});
|
||||
return result.canceled ? null : result.filePath || null;
|
||||
});
|
||||
}
|
||||
|
||||
const gotLock = app.requestSingleInstanceLock();
|
||||
if (!gotLock) {
|
||||
app.quit();
|
||||
} else {
|
||||
app.on("second-instance", () => {
|
||||
if (!mainWindow) return;
|
||||
if (mainWindow.isMinimized()) mainWindow.restore();
|
||||
mainWindow.focus();
|
||||
});
|
||||
|
||||
app.whenReady().then(() => {
|
||||
registerIpc();
|
||||
createWindow();
|
||||
app.on("activate", () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow();
|
||||
});
|
||||
});
|
||||
|
||||
app.on("window-all-closed", () => {
|
||||
if (process.platform !== "darwin") app.quit();
|
||||
});
|
||||
}
|
||||
Reference in new issue
Block a user