diff --git a/scripts/clean.js b/build/scripts/clean.js similarity index 100% rename from scripts/clean.js rename to build/scripts/clean.js diff --git a/build/scripts/generateProdEntry.js b/build/scripts/generateProdEntry.js new file mode 100644 index 0000000..e02a191 --- /dev/null +++ b/build/scripts/generateProdEntry.js @@ -0,0 +1,21 @@ +const fs = require('fs') +const path = require('path') + +if (!fs.existsSync(path.join(process.cwd(), 'dist/main/build.jsc'))) { + throw new Error('字节码文件未找到,请先执行编译') +} + +const content = ` +const {app} = require('electron'); +require('bytenode'); +require('./index.jsc); +` + +const outputPath = path.join(process.cwd(), 'dist/main/build.js') + +// 确保目录存在 +fs.mkdirSync(path.dirname(outputPath), { recursive: true }) + +// 写入文件 +fs.writeFileSync(outputPath, content.trim()) +console.log(`生产环境入口文件已生成: ${outputPath}`) \ No newline at end of file diff --git a/forge.config.ts b/forge.config.ts index c59a670..db7d809 100644 --- a/forge.config.ts +++ b/forge.config.ts @@ -25,12 +25,12 @@ const config: ForgeConfig = { build: [ { // `entry` is just an alias for `build.lib.entry` in the corresponding file of `config`. - entry: 'src/main.ts', + entry: 'src/electron/main/main.ts', config: 'vite.main.config.ts', target: 'main', }, { - entry: 'src/preload.ts', + entry: 'src/electron/preload/preload.ts', config: 'vite.preload.config.ts', target: 'preload', }, diff --git a/index.html b/index.html index 5f37e43..fe2d2f1 100644 --- a/index.html +++ b/index.html @@ -11,6 +11,6 @@
- + diff --git a/package-lock.json b/package-lock.json index 1ffa541..815c007 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,10 @@ "dependencies": { "axios": "^1.12.2", "bytenode": "^1.5.7", + "crypto": "^1.0.1", "electron-squirrel-startup": "^1.0.1", + "lodash-es": "^4.17.21", + "log4js": "^6.9.1", "pinia": "^2.3.1", "vue": "^3.5.22", "vue-router": "^4.5.1" @@ -29,6 +32,7 @@ "@tailwindcss/postcss": "^4.1.14", "@tailwindcss/vite": "^4.0.0", "@types/electron-squirrel-startup": "^1.0.2", + "@types/lodash-es": "^4.17.12", "@typescript-eslint/eslint-plugin": "^5.62.0", "@typescript-eslint/parser": "^5.62.0", "@vitejs/plugin-vue": "^5.2.4", @@ -2804,6 +2808,23 @@ "@types/node": "*" } }, + "node_modules/@types/lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/lodash-es": { + "version": "4.17.12", + "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz", + "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/lodash": "*" + } + }, "node_modules/@types/mute-stream": { "version": "0.0.4", "resolved": "https://registry.npmmirror.com/@types/mute-stream/-/mute-stream-0.0.4.tgz", @@ -4568,6 +4589,13 @@ "node": ">=12.10" } }, + "node_modules/crypto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz", + "integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==", + "deprecated": "This package is no longer supported. It's now a built-in Node module. If you've depended on crypto, you should switch to the one that's built-in.", + "license": "ISC" + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmmirror.com/cssesc/-/cssesc-3.0.0.tgz", @@ -4641,11 +4669,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/date-format": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz", + "integrity": "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==", + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -6438,7 +6474,6 @@ "version": "3.3.3", "resolved": "https://registry.npmmirror.com/flatted/-/flatted-3.3.3.tgz", "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", - "dev": true, "license": "ISC" }, "node_modules/flora-colossus": { @@ -6977,7 +7012,6 @@ "version": "4.2.11", "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, "license": "ISC" }, "node_modules/graphemer": { @@ -8355,6 +8389,12 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "license": "MIT" + }, "node_modules/lodash.get": { "version": "4.4.2", "resolved": "https://registry.npmmirror.com/lodash.get/-/lodash.get-4.4.2.tgz", @@ -8496,6 +8536,22 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/log4js": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.9.1.tgz", + "integrity": "sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==", + "license": "Apache-2.0", + "dependencies": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "flatted": "^3.2.7", + "rfdc": "^1.3.0", + "streamroller": "^3.1.5" + }, + "engines": { + "node": ">=8.0" + } + }, "node_modules/lowercase-keys": { "version": "2.0.0", "resolved": "https://registry.npmmirror.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz", @@ -8813,7 +8869,6 @@ "version": "2.1.3", "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, "license": "MIT" }, "node_modules/mute-stream": { @@ -10297,7 +10352,6 @@ "version": "1.4.1", "resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.4.1.tgz", "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", - "dev": true, "license": "MIT" }, "node_modules/rimraf": { @@ -10934,6 +10988,52 @@ "node": ">= 0.4" } }, + "node_modules/streamroller": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.5.tgz", + "integrity": "sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==", + "license": "MIT", + "dependencies": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "fs-extra": "^8.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/streamroller/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/streamroller/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/streamroller/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.3.0.tgz", diff --git a/package.json b/package.json index 5b5d4e5..98f5619 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,9 @@ "package": "electron-forge package", "make": "electron-forge make", "publish": "electron-forge publish", - "lint": "eslint --ext .ts,.tsx ." + "lint": "eslint --ext .ts,.tsx .", + "generate-prod-entry": "node build/scripts/generateProdEntry.js", + "build:encrypt": "npm run clean && npm run lint && npm run package && npm run generate-prod-entry" }, "keywords": [], "author": { @@ -30,6 +32,7 @@ "@tailwindcss/postcss": "^4.1.14", "@tailwindcss/vite": "^4.0.0", "@types/electron-squirrel-startup": "^1.0.2", + "@types/lodash-es": "^4.17.12", "@typescript-eslint/eslint-plugin": "^5.62.0", "@typescript-eslint/parser": "^5.62.0", "@vitejs/plugin-vue": "^5.2.4", @@ -45,7 +48,10 @@ "dependencies": { "axios": "^1.12.2", "bytenode": "^1.5.7", + "crypto": "^1.0.1", "electron-squirrel-startup": "^1.0.1", + "lodash-es": "^4.17.21", + "log4js": "^6.9.1", "pinia": "^2.3.1", "vue": "^3.5.22", "vue-router": "^4.5.1" diff --git a/shims-vue.d.ts b/shims-vue.d.ts new file mode 100644 index 0000000..a622f87 --- /dev/null +++ b/shims-vue.d.ts @@ -0,0 +1,6 @@ +declare module '*.vue' { + import type { DefineComponent } from 'vue' + // 泛型参数:Props类型、Emits类型、Slots类型(默认任意) + const component: DefineComponent<{}, {}, any> + export default component +} diff --git a/src/automation/baidu-automation.js b/src/electron/automation/baidu-automation.js similarity index 100% rename from src/automation/baidu-automation.js rename to src/electron/automation/baidu-automation.js diff --git a/src/automation/recording-automation.js b/src/electron/automation/recording-automation.js similarity index 100% rename from src/automation/recording-automation.js rename to src/electron/automation/recording-automation.js diff --git a/src/main.ts b/src/electron/main/main.ts similarity index 78% rename from src/main.ts rename to src/electron/main/main.ts index 888ec03..cca310c 100644 --- a/src/main.ts +++ b/src/electron/main/main.ts @@ -1,8 +1,9 @@ import { app, BrowserWindow, ipcMain, shell } from "electron"; import path from "node:path"; import started from "electron-squirrel-startup"; -import { TabManager } from './controller/tab-manager' -import "./controller/window-size-controll"; +import { TabManager } from '@modules/tab-manager' +import { logger } from '@modules/logger' +import "@modules/window-size"; if (started) { app.quit(); @@ -17,6 +18,7 @@ class AppMain { this.registerLifecycle() this.registerCommonIPC() this.registerAppIPC() + this.registerLogIPC() } private createWindow(options?: { frameless?: boolean; route?: string }): BrowserWindow { @@ -34,8 +36,8 @@ class AppMain { webPreferences: { devTools: this.isDev, nodeIntegration: false, - contextIsolation: true, - sandbox: true, + contextIsolation: true, // 同时启动上下文隔离 + sandbox: true, // 启动沙箱模式 preload: path.join(__dirname, "preload.js"), }, }) @@ -55,6 +57,12 @@ class AppMain { } else { win.loadFile(path.join(__dirname, `../renderer/${MAIN_WINDOW_VITE_NAME}/index.html`)) } + + // 暴露安全 API 示例:通过 IPC 处理文件读取 + ipcMain.handle('read-file', async (event, filePath) => { + const fs = require('fs'); + return fs.promises.readFile(filePath, 'utf-8'); // 主进程处理敏感操作 + }); } private initTabsIfNeeded(options?: { frameless?: boolean; route?: string }) { @@ -118,7 +126,33 @@ class AppMain { ipcMain.handle('tab:switch', (_e, tabId: string) => tabs.switch(tabId)) ipcMain.handle('tab:close', (_e, tabId: string) => tabs.close(tabId)) } + + private registerLogIPC() { + ipcMain.handle('log-to-main', (_e, logLevel: string, message: string) => { + switch(logLevel) { + case 'trace': + logger.trace(message) + break + case 'debug': + logger.debug(message) + break + case 'info': + logger.info(message) + break + case 'warn': + logger.warn(message) + break + case 'error': + logger.error(message) + break + default: + logger.info(message) + break + } + }) + } } new AppMain().init() + \ No newline at end of file diff --git a/src/electron/main/modules/ipc/index.ts b/src/electron/main/modules/ipc/index.ts new file mode 100644 index 0000000..5772758 --- /dev/null +++ b/src/electron/main/modules/ipc/index.ts @@ -0,0 +1,95 @@ +import { ipcMain, BaseWindow } from 'electron' + +type Handler = (...args:any[]) => any +type AsyncHandler = (...args:any[]) => Promise + +export class IPCManager { + private static instance: IPCManager + private handlers: Map + private asyncHandlers: Map + private constructor() { + this.handlers = new Map() + this.asyncHandlers =new Map() + this.initialize() + } + + public static getInstance(): IPCManager { + if (!IPCManager.instance) { + IPCManager.instance =new IPCManager() + } + + return IPCManager.instance + } + + private initialize(): void { + //注册同步处理器 + ipcMain.on('ipc:invoke',(event, channel,...args) => { + try { + const handler = this.handlers.get(channel) + + if(handler){ + event.returnValue = handler(...args) + } else { + event.returnValue = { success: false, error: `No handler for channel: ${channel}`} + } + } catch (error) { + event.returnValue = { success: false, error:(error as Error).message} + } + }) + + // 注册异步处理器 + ipcMain.handle('ipc:invokeAsync', async (_event, channel, ...args) => { + try { + const handler = this.asyncHandlers.get(channel) + + if(handler){ + return await handler(...args) + } + + throw new Error(`No async handler for channel: ${channel}`) + } catch (error) { + throw error + } + }) + + ipcMain.handle('get-window-id',(event) => { + event.returnValue = event.sender.id + }) + } + + // 注册同步处理器 + public register(channel:string, handler:Handler):void { + this.handlers.set(channel, handler) + } + + // 注册异步处理器 + public registerAsync(channel:string, handler:AsyncHandler):void { + this.asyncHandlers.set(channel, handler) + } + + // 广播消息给所有窗口 + public broadcast(channel:string, ...args:any[]):void { + BaseWindow.getAllWindows().forEach(window => { + if (!window.isDestroyed()) { + window.webContents.send(channel, ...args) + } + }) + } + + // 发送消息给指定窗口 + public sendToWindow(windowId: string, channel:string, ...args:any[]):void { + const window = BaseWindow.fromId(windowId) + + if (window && !window.isDestroyed()) { + window.webContents.send(channel, ...args) + } + } + + // 清理所有处理器 + public clear():void { + this.handlers.clear() + this.asyncHandlers.clear() + } +} + +export const ipcManager = IPCManager.getInstance() diff --git a/src/electron/main/modules/logger/index.ts b/src/electron/main/modules/logger/index.ts new file mode 100644 index 0000000..9eb1c1d --- /dev/null +++ b/src/electron/main/modules/logger/index.ts @@ -0,0 +1,29 @@ +import * as log4js from 'log4js'; + +log4js.configure({ + appenders: { + out: { + type: 'stdout' + }, + app: { + type: 'file', + filename: 'logs/app.log', + backups: 3, + compress: false, + encoding: 'utf-8', + layout: { + type: 'pattern', + pattern: '[%d{yyyy-MM-dd hh:mm:ss.SSS}] [%p] %m' + }, + keepFileExt: true + } + }, + categories: { + default: { + appenders: ['out', 'app'], + level: 'debug' + } + } +}); + +export const logger = log4js.getLogger(); \ No newline at end of file diff --git a/src/controller/tab-manager/index.ts b/src/electron/main/modules/tab-manager/index.ts similarity index 100% rename from src/controller/tab-manager/index.ts rename to src/electron/main/modules/tab-manager/index.ts diff --git a/src/controller/tray-controll/tray.ts b/src/electron/main/modules/tray/index.ts similarity index 100% rename from src/controller/tray-controll/tray.ts rename to src/electron/main/modules/tray/index.ts diff --git a/src/controller/window-size-controll/index.ts b/src/electron/main/modules/window-size/index.ts similarity index 100% rename from src/controller/window-size-controll/index.ts rename to src/electron/main/modules/window-size/index.ts diff --git a/src/preload.ts b/src/electron/preload/preload.ts similarity index 51% rename from src/preload.ts rename to src/electron/preload/preload.ts index 6ed39cf..bcdf4b6 100644 --- a/src/preload.ts +++ b/src/electron/preload/preload.ts @@ -1,22 +1,25 @@ import { contextBridge, ipcRenderer } from 'electron' +import { IPCChannel, IPCAPI } from '@/shared/types/ipc.types' -contextBridge.exposeInMainWorld('electronAPI', { - openBaidu: () => ipcRenderer.invoke('open-baidu') -}) +const api: IPCAPI = { + openBaidu: () => ipcRenderer.invoke('open-baidu'), -contextBridge.exposeInMainWorld('api', { versions: process.versions, + external: { open: (url: string) => ipcRenderer.invoke('external-open', url) }, + window: { minimize: () => ipcRenderer.send('window-min'), maximize: () => ipcRenderer.send('window-max'), close: () => ipcRenderer.send('window-close') }, + app: { setFrameless: (route?: string) => ipcRenderer.invoke('app:set-frameless', route) }, + tabs: { create: (url?: string) => ipcRenderer.invoke('tab:create', url), list: () => ipcRenderer.invoke('tab:list'), @@ -31,5 +34,38 @@ contextBridge.exposeInMainWorld('api', { ipcRenderer.on(event, listener) return () => ipcRenderer.removeListener(event, listener) } - } -}) \ No newline at end of file + }, + + // 通过 IPC 调用主进程 + readFile: (filePath: string) => ipcRenderer.invoke('read-file', filePath), + + // 同步调用 + invoke: (channel: IPCChannel, ...args: any[]) => ipcRenderer.sendSync('ipc:invoke', channel, ...args), + + // 异步调用 + invokeAsync: (channel: IPCChannel, ...args: any[]) => { + try { + ipcRenderer.invoke('ipc:invokeAsync', channel, ...args) + } catch (error) { + throw error + } + }, + + // 监听主进程消息 + on: (event: IPCChannel, callback: (...args: any[]) => void) => { + const subscription = (_event: any, ...args: any[]) => callback(...args) + ipcRenderer.on(event, subscription) + return () => ipcRenderer.removeListener(event, subscription) + }, + + // 发送消息到主进程 + send: (channel: IPCChannel, ...args: any[]) => ipcRenderer.send(channel, ...args), + + // 获取窗口ID + getCurrentWindowId: () => ipcRenderer.sendSync(IPCChannel.GET_WINDOW_ID), + + // 发送日志 + logToMain: (logLevel: string, message: string) => ipcRenderer.send('log-to-main', logLevel, message), +} + +contextBridge.exposeInMainWorld('ipcAPI', api) \ No newline at end of file diff --git a/src/env.d.ts b/src/env.d.ts deleted file mode 100644 index 2f95523..0000000 --- a/src/env.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -declare module "@stores/counter"; -declare module "@utils/request"; \ No newline at end of file diff --git a/src/ipc/index.ts b/src/ipc/index.ts deleted file mode 100644 index b9b9cf0..0000000 --- a/src/ipc/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { ipcMain } from 'electron' -import { TabManager } from '../controller/tab-manager' - -export const registerTabIpc = (tabs: TabManager) => { - ipcMain.handle('tab:create', (_e, url?: string) => tabs.create(url)) - ipcMain.handle('tab:list', () => tabs.list()) - ipcMain.handle('tab:navigate', (_e, payload: { tabId: string; url: string }) => tabs.navigate(payload.tabId, payload.url)) - ipcMain.handle('tab:reload', (_e, tabId: string) => tabs.reload(tabId)) - ipcMain.handle('tab:back', (_e, tabId: string) => tabs.goBack(tabId)) - ipcMain.handle('tab:forward', (_e, tabId: string) => tabs.goForward(tabId)) - ipcMain.handle('tab:switch', (_e, tabId: string) => tabs.switch(tabId)) - ipcMain.handle('tab:close', (_e, tabId: string) => tabs.close(tabId)) -} \ No newline at end of file diff --git a/src/plugins/bytenode/vite-plugin-electron-encrypt.ts b/src/plugins/bytenode/vite-plugin-electron-encrypt.ts new file mode 100644 index 0000000..1213e30 --- /dev/null +++ b/src/plugins/bytenode/vite-plugin-electron-encrypt.ts @@ -0,0 +1,47 @@ +import type { PluginOption } from 'vite' +import * as bytenode from 'bytenode' +import * as path from 'path' +import * as fs from 'fs-extra' + +export interface ElectronBytecodeOptions { + entry?: string + keepSource?: boolean +} + +export default function electronBytecode(options?: ElectronBytecodeOptions): PluginOption { + return { + name: 'vite-plugin-electron-encrypt', + apply: 'build', + async closeBundle() { + if (process.env.NODE_ENV !== 'production') return + const electronVersion = require('electron/package.json').version + const nodeVersion = process.version + const versionData = { + node: nodeVersion, + electron: electronVersion, + platform: process.platform, + arch: process.arch, + buildTime: new Date().toISOString() + } + const versionPath = path.resolve(process.cwd(), 'dist', 'version.json') + + fs.ensureDirSync(path.dirname(versionPath)) + fs.writeJsonSync(versionPath, versionData, { spaces: 2 }) + + const entryPath = path.resolve(process.cwd(), options?.entry || '.vite/build/main.js') + + if (!fs.pathExistsSync(entryPath)) return + + const outputPath = entryPath.replace(/\.js$/, '.jsc') + const backupPath = `${entryPath}.bak` + + fs.copyFileSync(entryPath, backupPath) + + await bytenode.compileFile({ filename: entryPath, output: outputPath }) + + if (!options?.keepSource) { + fs.removeSync(entryPath) + } + } + } +} diff --git a/src/renderer.ts b/src/renderer.ts deleted file mode 100644 index cc00d31..0000000 --- a/src/renderer.ts +++ /dev/null @@ -1,45 +0,0 @@ -/** - * This file will automatically be loaded by vite and run in the "renderer" context. - * To learn more about the differences between the "main" and the "renderer" context in - * Electron, visit: - * - * https://electronjs.org/docs/tutorial/process-model - * - * By default, Node.js integration in this file is disabled. When enabling Node.js integration - * in a renderer process, please be aware of potential security implications. You can read - * more about security risks here: - * - * https://electronjs.org/docs/tutorial/security - * - * To enable Node.js integration in this file, open up `main.ts` and enable the `nodeIntegration` - * flag: - * - * ``` - * // Create the browser window. - * mainWindow = new BrowserWindow({ - * width: 800, - * height: 600, - * webPreferences: { - * nodeIntegration: true - * } - * }); - * ``` - */ - -import "./index.css"; -import { createApp } from "vue"; -import { createPinia } from "pinia"; -import router from "./router"; -import App from "./App.vue"; - -// 创建 Vue 应用实例 -const app = createApp(App); - -// 使用 Pinia 状态管理 -app.use(createPinia()); - -// 使用 Vue Router -app.use(router); - -// 挂载应用到 DOM -app.mount("#app"); diff --git a/src/App.vue b/src/renderer/App.vue similarity index 82% rename from src/App.vue rename to src/renderer/App.vue index 15080d9..19901e1 100644 --- a/src/App.vue +++ b/src/renderer/App.vue @@ -5,7 +5,7 @@ diff --git a/src/views/login/index.vue b/src/renderer/views/login/index.vue similarity index 96% rename from src/views/login/index.vue rename to src/renderer/views/login/index.vue index e27ba01..f41c146 100644 --- a/src/views/login/index.vue +++ b/src/renderer/views/login/index.vue @@ -53,7 +53,7 @@